Using the Oracle on Solana
This article explains how the Umbrella Network's Chain
Solana program works. It is a guide for developers who want to verify Rollup Data in Solana. We provide scripts as examples in our Reference Application.
Account structure
On Solana, we dynamically create an account for each block where we store the Merkel root hash for L2 data verification.
All the accounts in Solana have an address (public key). In our case, we make use of Partial Derived Addresses (PDA) which are public keys that don't rely on the elliptic curve, and as a consequence, they don't have any associated private key. We use this PDA for its hash-map property.
How to get data from an account
The first step is to compute the PDA for the account we are interested in. This is done with the findProgramAddress
method which takes the ProgramId and a seed as parameters.
For Umbrella Network's Oracle, the seed is the block ID:
const programId = "4SPgs3L7Ey9VyRuZwx4X3y86LSAZXP2Hhpz9Sps4v3iT";
const seed = LeafValueCoder.encode(blockId, '');
const [blockPda, bump] = await PublicKey.findProgramAddress(
[seed], program.programId
);
The
LeafValueCoder
, an object belonging to Umbrella Network;s SDK, serves to encode and decode common data types such as numbers or strings into data buffers which are most useful for being processed on the blockchain.
PublicKey
is an object that belongs to the@solana/web3.js
interface and contains thefindProgramAddress
function, This function converts the seed and the program ID into a PDA.
These two parameters uniquely determine theblockPda
.
After obtaining the blockPDA
, we can proceed fetching the data using the program object:
let block = await program.account.authority.fetch(blockPda);
Verifying Rollup Data
In order to verify the Rollup Data, we will need first to retrieve the PDA for the account storing the information of the specific block the Rollup Data belongs to. This is done by using the block ID as seed for the `FindProgramAddress' function.
Follows an example for retrieving account for block id: 505332
const programId = "4SPgs3L7Ey9VyRuZwx4X3y86LSAZXP2Hhpz9Sps4v3iT";
let block_id = 505332;
const seed = LeafValueCoder.encode(block_id, '');
const [blockPda, bump] = await PublicKey.findProgramAddress(
[seed], program.programId
);
let block = await program.account.authority.fetch(blockPda);
For actually verifiying the proofs for a Rollup Data we need to invoke the verify_proof_for_block
function in the Chain
program. This function returns TRUE if the proofs were verified (meaning the value for the indicated key is teh one validated by the Oracle for provided block id) or FALSE if not,
In code, this can be performed as:
await program.methods
.verifyProofForBlock(seed, proofs, key, value)
.accounts({
verifyResult: verifyResultAccount.publicKey,
block: blockPda,
})
.rpc({ commitment: 'confirmed' });
// we check the result
const account = await program.account.verifyResult.fetch(verifyResultAccount.publicKey);
console.log('Verify result =', account.result);
where:
seed
: is the block id encoded as byteskey
: is the key of the Rollup Data to verify (e.g. "BTC-USD") encoded as bytesvalue
: is the value (associated to the key) encoded as bytesproofs
: is an array of the proofs for that particular key-value pair
The only way Solana programs can return on-chain information to the real world is also through the use of accounts, which means that the result of the verify_proof_for_block
should be written on an account. For this purpose, the VerifyResult
account must be created.
The following code generates a VerifyAccount account which will be use to store the result of the Rollup Data verification:
const verifyResultAccount = anchor.web3.Keypair.generate();
await program.methods
.initializeVerifyResult()
.accounts({
verifyResult: verifyResultAccount.publicKey,
user: provider.wallet.publicKey,
systemProgram: SystemProgram.programId,
})
.signers([verifyResultAccount])
.rpc({ commitment: 'confirmed' });
where:
verifyResult
: is the address (public key) that the account will have (in this case it is a random generated address)user
: is the address (public key) of the account that will provide the funds for creating this accountsystemProgram
: is the PDA of a Solana program used to initialize accounts
The next figure illustrates the process described above:
Block validation through cross-program invocation (CPI)
In a similar way, it is also possible to verify data through another program on Solana. This second program could be for example a DEX or any other dApp that wants to confirm a price retrieved for a Rollup Data is correct. For this purpose, the caller program will perform a cross-program invocation to our chain program. In turn, the latter will write the result also on the VerifyResult
account or return it directly to the caller program for internal use.
Updated 6 months ago