Skip to content

Commit

Permalink
Added method to check state root - ProverV2 (#875)
Browse files Browse the repository at this point in the history
* Implement storage-proof in `verify_storage_proof()` verification and changes in `_verify_trie_proof()` to prove non existent values.
* Add tests
* Update `eth-prover` contract binary file.

---------

Co-authored-by: karim-en <karim@aurora.dev>
Co-authored-by: Kirill <kirill@aurora.dev>
  • Loading branch information
3 people authored Jun 9, 2023
1 parent 418ce55 commit 9cc1964
Show file tree
Hide file tree
Showing 16 changed files with 655 additions and 17 deletions.
14 changes: 13 additions & 1 deletion cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const {
} = require('rainbow-bridge-testing')
const { ETHDump } = require('./commands/eth-dump')
const { NearDump } = require('./commands/near-dump')
const { ethToNearFindProof } = require('rainbow-bridge-eth2near-block-relay')
const { ethToNearFindProof, ethToNearFindStorageProof } = require('rainbow-bridge-eth2near-block-relay')
const { RainbowConfig } = require('rainbow-bridge-utils')
const { UpdateDagMerkleRoots } = require('./commands/update-dag-merkle-roots')
const {
Expand Down Expand Up @@ -649,6 +649,18 @@ RainbowConfig.addOptions(
]
)

RainbowConfig.addOptions(
program
.command('eth-to-near-find-storage-proof <contract-address> <storage_key> <block-number>')
.description('Get eth-to-near storage proof for provided storage key.'),
async (contractAddress, storageKey, blockNumber, args) => {
await ethToNearFindStorageProof({ contractAddress, storageKey, blockNumber, ...args })
},
[
'eth-node-url'
]
)

// Testing commands
const testingCommand = program
.command('TESTING')
Expand Down
2 changes: 1 addition & 1 deletion contracts/near/eth-prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ rlp = "0.5.2"
hex = "0.4.2"

[dev-dependencies]
hex = "0.4.2"
hex = { version = "0.4.3", features = ["serde"] }
indicatif = "0.14"
lazy_static = "*"
near-crypto = "0.16.0"
Expand Down
28 changes: 28 additions & 0 deletions contracts/near/eth-prover/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Eth-Prover

Eth-Prover trustless contract to prove the integrity of data (proofs) provided by users and relayer trustlessly.

## How To Generate Proofs:-

- Pre-requisites before calling `eth_getProof` :
- DATA, 20 Bytes - address of the account.
- ARRAY, 32 Bytes - array of storage-keys which should be proofed and included. See eth_getStorageAt
- QUANTITY|TAG - integer block number, or the string "latest" or "earliest"


- To generate proofs one need to call RPC method `eth_getProof` [check-here](https://eips.ethereum.org/EIPS/eip-1186).



## About Parameters of `verify_storage_proof` method :-

- `header_data: Vec<u8>` : Rlp-Serilized Header data from RPC call to `eth_getBlockByNumber` [check here](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbynumber)
- `account_proof: Vec<Vec<u8>>`: Buffer data of account-proof from `eth_getProof` method call response.
- `contract_address: Vec<u8>`: Buffered data of Eth-contract address for which we are prooving.
- `expected_account_state: Vec<u8>`: encoded account state made-up of `{nonce, balance, storageHash, codeHash}`
- `storage_key_hash: Vec<u8>`: keccak256 of storage-key in `eth_getProof`
- `storage_proof: Vec<Vec<u8>>`: Buffer data of `storage-proof` for above `storage_key` from `eth_getProof` method call response.
- `expected_storage_value: Vec<u8>`: storage_value against which proof is to be verified.
- `min_header_height: Option<u64>`: Valid-till block height for unlock.
- `max_header_height: Option<u64>`: Currently set to None
- `skip_bridge_call: bool`: whether to make eth-client call or not. Always take false.
97 changes: 86 additions & 11 deletions contracts/near/eth-prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,71 @@ impl EthProver {
.into()
}

/// WARNING: When the value is not found, `eth_getProof` will return "0x0" at
/// the StorageProof `value` field. In order to verify the proof of non
/// existence, you must set `value` to empty vec, *not* the RLP encoding of 0 or null
/// (which would be 0x80).
#[result_serializer(borsh)]
pub fn verify_storage_proof(
&self,
#[serializer(borsh)] header_data: Vec<u8>,
#[serializer(borsh)] account_proof: Vec<Vec<u8>>, // account proof
#[serializer(borsh)] contract_address: Vec<u8>, // eth address
#[serializer(borsh)] expected_account_state: Vec<u8>, // encoded account state
#[serializer(borsh)] storage_key_hash: Vec<u8>, // keccak256 of storage key
#[serializer(borsh)] storage_proof: Vec<Vec<u8>>, // storage proof
#[serializer(borsh)] expected_storage_value: Vec<u8>, // storage value
#[serializer(borsh)] min_header_height: Option<u64>,
#[serializer(borsh)] max_header_height: Option<u64>,
#[serializer(borsh)] skip_bridge_call: bool,
) -> PromiseOrValue<bool> {
self.check_not_paused(PAUSE_VERIFY);
let header: BlockHeader = rlp::decode(header_data.as_slice()).unwrap();

if let Some(min_header_height) = min_header_height {
if header.number < min_header_height {
env::log_str(format!("Block height {} < Minimum header height {}", header.number, min_header_height).as_str());
return PromiseOrValue::Value(false);
}
}

if let Some(max_header_height) = max_header_height {
if header.number > max_header_height {
env::log_str(format!("Block height {} > Maximum header height {}", header.number, max_header_height).as_str());
return PromiseOrValue::Value(false);
}
}

let account_key = near_keccak256(&contract_address).to_vec();
let account_state = Self::verify_trie_proof(header.state_root, account_key, account_proof);
if account_state != expected_account_state {
env::log_str("account_state != expected_account_state");
return PromiseOrValue::Value(false);
}

let storage_hash: H256 = Rlp::new(&account_state).val_at(2).unwrap();
let storage_value = Self::verify_trie_proof(storage_hash, storage_key_hash, storage_proof);
if storage_value != expected_storage_value {
env::log_str("storage_value != expected_storage_value");
return PromiseOrValue::Value(false);
}

if skip_bridge_call {
return PromiseOrValue::Value(true);
}

// Verify block header was in the bridge
eth_client::ext(self.bridge_smart_contract.parse().unwrap())
.with_static_gas(BLOCK_HASH_SAFE_GAS)
.block_hash_safe(header.number)
.then(
remote_self::ext(env::current_account_id())
.with_static_gas(ON_BLOCK_HASH_GAS)
.on_block_hash(header.hash.unwrap()),
)
.into()
}

/// Verify the proof recursively traversing through the key.
/// Return the value at the end of the key, in case the proof is valid.
///
Expand Down Expand Up @@ -184,18 +249,23 @@ impl EthProver {

if node.iter().count() == 17 {
// Branch node
if key_index == key.len() {
if key_index >= key.len() {
assert_eq!(proof_index + 1, proof.len());
get_vec(&node, 16)
} else {
let new_expected_root = get_vec(&node, key[key_index] as usize);
Self::_verify_trie_proof(
new_expected_root,
key,
proof,
key_index + 1,
proof_index + 1,
)
if !new_expected_root.is_empty() {
Self::_verify_trie_proof(
new_expected_root,
key,
proof,
key_index + 1,
proof_index + 1,
)
} else {
// not included in proof
vec![]
}
}
} else {
// Leaf or extension node
Expand All @@ -211,19 +281,23 @@ impl EthProver {
if head % 2 == 1 {
path.push(path_u8[0] % 16);
}
for val in path_u8.into_iter().skip(1) {
for val in path_u8.iter().skip(1) {
path.push(val / 16);
path.push(val % 16);
}
assert_eq!(path.as_slice(), &key[key_index..key_index + path.len()]);

if head >= 2 {
// Leaf node
assert_eq!(proof_index + 1, proof.len());
assert_eq!(key_index + path.len(), key.len());
get_vec(&node, 1)
if path.as_slice() == &key[key_index..key_index + path.len()] {
get_vec(&node, 1)
} else {
vec![]
}
} else {
// Extension node
assert_eq!(path.as_slice(), &key[key_index..key_index + path.len()]);
let new_expected_root = get_vec(&node, 1);
Self::_verify_trie_proof(
new_expected_root,
Expand Down Expand Up @@ -253,3 +327,4 @@ admin_controlled::impl_admin_controlled!(EthProver, paused);

#[cfg(test)]
mod tests;
mod tests_storage_proof;
25 changes: 25 additions & 0 deletions contracts/near/eth-prover/src/test_data/storageProof.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"header_data": "f90217a02feb03d38518e6941c0852c64a9cc06be8f0caed9357d0c45136395110ef4540a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794388ea662ef2c223ec0b047d41bf3c0f362142ad5a035630b01ab13a7f864f9c86f2a2d7ac497320594f92c5868e17063260beba833a083c4eeccb9dad0f16ca684785dd347c70e3c35573ebb38b6db5550d5e2eb2039a0f7679d652f72b54fd7c579a4738ae4d47c53213f266b5a2c2446a53386d17000b901005f04c0c31260591c81984881b480200041180c10098408d4d8840434c215211800660401002162160128100000c44bf4c0c20080061022544a185e0081242a000030000c4444811c600840285d0480624449060340cc6092080220a6000002050a0012428300a20010281180141408049801084502684280311012320608114002000a60802220aa29004800229100280001208004201140009140144462000502a0881100002810134340008b06402082004040224030080091406a288609021291480200194c49160440b14017660c4440018812086589620a005c0c0068839838ab040040a40754492158c0112414c892141012082040020a4a2102800040308381979a8401c9c38083972d598463ec1de09b4d616e69666f6c643a20636f696e62617365202d20676f65726c69a0fbd610d479f34d78d3c1ee5d525906e119babfa742966dfaabfba6ffc6499c3b8800000000000000000c",
"account_proof": [
"f90211a08f3ec3607756301ad7628386a694edef062c32c0af69abdd8582733411fa6f4aa0e9ad940b31824dacc65417f2ae3aafe394949948f5805e645f6a5d7e7f0a5f28a078698a03fd4d2d738df437e1d39ac6dbe2b331474483083ecacd9270227adccea0b13728bf8c7541aac2e5f15840030e1a2a1d8546af961d2c5fe3cec61eb52136a041e20da27ab9f63b643aa550bd5494f42eb980e728499362807ca4a3d20bbd71a0544dfa7c44c6f4fc4318e6d42c8baa7db02467e31bdecb39a5b5c35dc9d75627a082e724d82008044c2339c3518899c58fa94397ec9b754a84ee6862ed980c506fa09858c9a0c3770fdcf0a95ee8657db7e5ff2813a5ee2b02bd2d550602ccf92ceca070c39b9018c1099644f6c8302f054b889f0d9c1c43561193af08c60514373a86a05147dd91ed6576bcb99c84b82e21267336fb5e7b6532bbc3bf3f153c44c7dd8ba0996167eb0ec29dcf3dc5564335936c857a16381f6cfc41e898ac427d5096f763a061cc346b3b193043469e1e63078e26bdffdc77fb9b7e03376a5d04a2e6a8bbd7a05ebe3f8899a1c9ae5c6f519c21bab07f380bc24eacd32d4915efa30990373347a0537e35aef2230294fb0150b5100ce1be4929181b2cbe16919ebdaf5455980a6ca0b11e4d342e93978e8ce006c6dafdc11a4626043ad6cd29c3a20fcaf7469e8846a0c2034f69510242f1af24e3cf53bdf8013959107de3863457d1759a0607cb42bd80",
"f90211a0cb604e92bfce9e89c58adb96d031edd6773b5ea79468c361c11bee3834ad38f7a0c3600619870fbddd0d3031662c20d4f07a7e8879715221e1cf2a27bac8252e84a0b42bfa4ca8a0f93155decb6566a0bfe41da0f0805f50bf22e582fbe09dab761da0f01302bc5b806c36dab88cf8fc3e720d2a9ea8b8c615cb2d6a61e516e7d568d5a0eb7a165077f85af7e1529e66bd052e211e3b0e591459a6b917b3a67b96e6c300a099b855be27efd92907fb6671240ad9b5a194aaaba80ec57f780f7f5132679279a076caa859434ddcc7513f2c40bbcdb0d3c92ef7f00f5575e5103683ed3f12d7aaa04b1f24333d5e1ff59bc1f0e68a4bffc09a109b59b281991e1def7d9a4d304683a01d24cc1c910469b1d5daf5c1ed9a0ff4b90467671498592b2b10bedb28594afca0f6c8564af03a1d6fa2203ad17d1c6cbbf608baed014de79c85c560149bac34a2a014a2351fb2913c7eead2607e6e821cb861a0acecce7e8d6b3eee285cd069b0f0a026385df23dbeafd3adff1c5537bc9b47716c3149c4d557cacaa31f67f8eb854fa0d759139f6c612b3ad3a4f1930a20f5bd1bcbd7e5595ccad018f066cde7cef5b7a052a24711316c1bccd8b72b59e1e0da3bd3254258651f42c468dbc06d33a5ece4a047f3cb14ec806f64d4bdeb04a60aef31966f50b2b191c9d5f697e01e5bc47654a0003d585567fb4aea17878d81f6c8e95e38218216e31263d85b01e387dcd12b6f80",
"f90211a07aa1913685063febef9253361de62ae7177722d980431ad433b6b2a2464d3c04a03df3486d470dc33c576fa0442eeac73b28032d892cee651cb5c8a714ba958f66a06482a869a326022a5fc40172cd9bbae5920b85a4138273da18eed05d2d75d97aa02a026697251d16fce297a1ee61d123da79085dc24ec356bff0f48f5708b04975a026cab39115772141ab3560790f604bf798b8d8744574ec842f57acba1bd3529fa0b78a5d4dcc2f37bbc0e8ba50727e7d08b143080aa2f93355f890bb7a615dae92a005b2270294d81e96ee9c7258f82a4541ec7a6a4eccf5de6fe54821d2e297d8f4a0d8d4d961a8e24b1e2886ee56762b1cd7f77e0ac76f9095636e9a008986b2028ba0eb02ba490b14fab24930230234056ed1cfaaf91fa4a57d9b9a7a178abe1cf3d2a0ba993d463bf76b12d4702be9696e0a1236ab7cd38e9fb590496151e4302ac7c1a08cbbd58b931fa2111148bed4e38c68e827b9a155c1eef0e63f43aa263cc10acea02e9bf22e9f981f53ed4856a0020449dc813cf444781b51fa3eabe13e0232f966a0a3622e12dacf5a9d1df00fe7e59326e1e96f1455492d72e39d5b6bf5f00eebb3a0a52a0b202c7059b5621fc10fd2921babe2c27934fae2d0409cbdc5b76d6b41a7a056aaef786ef7c8b3bda6d9ae2780478a1edc82b1f22e606bd3defe34a9cdeab5a0bf81e0ec8e926a748517a28422ff88e4a3f138a6f9175249c207f3178900bd9380",
"f90211a036e911e298a20d166922b7cb0563d3bceb8550b4adfa9fe08d8ca0a3c6d7ae86a0b9b9ac2b7a0a7c4d415787487e231900a10407acd166e92295ada52ea762c472a03a996e1b0ec3e2bddb98e7767e4666bcd40fa2273e0d3f52fa430f9a46938e7da015ea238cec5879fa069d204e93ff3c951f99d63407860df1882a2c59f325052da051fe87082dd2a2ac9e3610f6a85daba6468f7be31bc0301d3bafb579031848a2a01dfdfc623921a2948b00c4e0eab2d054293ca4869e09eaa79cd88ae492728788a036828736fa97fc9f14f0471b2cef6d6de6ed8e85f60581340e32314f55426d83a0e060a030a17644b352fd5d809fbffab09e4854e5cf79e907775571e72efdbe65a0b99a9776ae25aac78712102d448bca2ad2b0855d9485fd3e5aabc755a857ea1ba09774c71fdeb56de7925402760fc787d0f81a7e9373f017cbcdbba81b2c12df33a0af0f67963ad8a449e4ad7b613c58cb40ccf16786659ca716e9083b981138d2efa09bdc7b5850cd1050dddbc864a0d391312343fb542944cf0409f97ff2213b9f5da09792e17ea99e242aec9465df7f1b2b77e4c2ba916465d5b99702f4c6152bd82ea0dd32ae4192e7f1050eecd2573cc2c324fbbf6bf98cc61a6511920e8ab32091e5a00b4230a149ff4dca81cd7682536de8b1be2fa715bcafb967c35156fdc626dc3ba0b722557e1dc96d95b6af1aa5871ff90d300ce8632102e6b23e7e5d94101702ad80",
"f90211a096da0777dbb2f875bd357722a4387a78ae24efe13e04ed75f65b2c991247203fa0c0082d34071d1d65e712999126ac28e277b079d939821eaa755c4ef0fd2e5baaa0d088ecbd4b6bb84c6fa211bc81474c05c12ca2694faf0b1a2ecbde0bfe6fa3a2a00930aa5c1b70190cd2231cc759fec0c863a2e11bc89b1685d17da64f6bdc5e72a010b3d58569454bcfe1e6c9fad76e7034972f2abb6a3081b3c6b057c7d3151e2ca0868e866d17747182e462be130ceb1b0b3b5011db9f10f3fc8a00743c50497eaaa0aff0dd0b6a09d0e5659b96333f74fd56545addb56451693c1daeb2dbd7fe4470a07094c93901a37d76cc1ce99891c7419188b9dcabcd73075525a844084574c697a0cfd98d359eb86b3cf4531a0ddfa5d1ae5e5cdbed5f3a6a39daff489b2c862ed5a00f80e0d59b59c9e9e27aba7ac54d51f35750c45d45fb3d46c2cf31cb32a8e68aa02a5c88410b94694ae8882eda87af1c56616cd475b0b7feb2306da3959b322418a0609c5a3f274c1d31fa9b4d3c4492b4811c374e4d3d08ca5da98da012a489b273a0df38f9ab051dcee8d4f1a00376b01acecb3b7e9dbc40358c3d6d5958193e0329a0a274c42f4ccef6f20a413218137c6ec00ac7e3fa172f61a7c6487497fe427daba0961e5aac1726d9598c446db66425f7360f87fa5feb744adcfaf19e783cbba1a5a0b5c730c7587872bdc05bd0786f6fd897332d7d2642f953fa019ef58d4e5ec25e80",
"f90171a02a6e86561c33eacbb1826e9832a25f9f2841c281c9e6b6c18c95ce713dae6c868080a0807528ab397894421968b62bead3b9dd446bda7dc79a5b6ec5a29bd3f19a10c5a0072bce4e78f01cc370c9d92dd39bfcee6059d2e60a95135867991c59184d219980a0415df007b0977e95ba9b3d86b64bae14c02250b3da81f81bed47973f9e4a55b180a0e45736d96c006965b5cad5ec8008d31eb2c34e00c36f677b288701f76f43d627a055324754b7752c9149df27e03392c0598ec89f408040b15140a679f02e695017a04fc91448749dcab3e66cc8e45eb8d85a416fa3a33f8951128d17ca208bc3bb38a085a91d9af48d4f428da097b31c09b3f6b27d38212678a30ffd100364546a4d1ea0c60b5a89f1f89e97528a8b352ed55e5de2e7b963d73ba7de9e922c0ae964e816a048ff598a81a0114eb4afe71ef547cf6fecbb970310ef84049c9353d01c17103aa02bd17f471f58c435c937e6457a8a8a7ff7163263be197ec547241bc4791536b18080",
"f871808080808080a03f1587ebf71f19f47449b08f0960630ddbd60d045ea68ee7d89fb1c5682d215a8080808080a06e1618ec47442688101bd341cb8627739ecfd6fc1f793b69191dceeed18a19348080a05344081f911ad616b960a8f2841eb55f4936a97ec5dae614e726c8c0d51e0eff80",
"f8669d3e3757038b7fea6585ca2d0a3dacd72d84bf0c7b916f169cea0348681bb846f8440180a082bab1eb1ecd4b6dccd6d65b93603e6596205eb39ba1e32084c63dd883b17057a0932cddc50793da935ccf915651ad67f6b746e9936fcc5614f0ff492563782c75"
],
"contract_address": "00763f30eEB0eEF506907e18f2a6ceC2DAb30Df8",
"expected_account_state": "f8440180a082bab1eb1ecd4b6dccd6d65b93603e6596205eb39ba1e32084c63dd883b17057a0932cddc50793da935ccf915651ad67f6b746e9936fcc5614f0ff492563782c75",
"storage_key_hash": "7bef74619139dab09d59cafa630682f8f30445738dcfb7147514aa27399ae2ee",
"storage_proof": [
"f90211a07c66fa00b691dc5c5a66e43831b9922316c8740c3c5235e7aa705cebefbd478ca0bbf8c0df9d3837792180786e217cbcbfb6cb6c1ee790ec0dba83fc05248f2627a036b93382543cd1737ddc32dbc8cd4326da47551be33e3ca75af3ea98583edd93a0c024e6190b7ce41e20f27b5cd512ebf50d6c60a1467f3cad8acd46da3a4d3861a04134b666e4a8e3e28701e33bed36680ae025cc5f89f8d29457975148338017c4a0ad773b24d54d681b3d712d913c0bf515407818845922616360b9b5a381cd6299a076515bac0f65924da357aba2f6c312472a9ef94d1c459f2cd0380b84a91d46aca0a3501be4fecb38f8b48131e0f8f63d6be379248ffb7d6f27c6fab26314fd8396a0324a3b32bf60329775f3383b6c98e99683df56a0933516032147008d544af343a029f967b2d7ed040cda92ab4905f2976636a7bb16ba850679eca942e02d5b3458a024bdf35e1d8fd46cdee76420d508c722d7f47825356620c266094f6c66c67f7ea0426a496a8633ec2771fb15f58f646bf689eda39af535bcb9b316e9e601d1a342a00d9cd9aa39cdd4a91bcd4feb8c73db017dce78ec82ba6f14287775567615f247a02f3d28876d69fd8945b3fdeff87186bcb97c236ccefa3b6182507bc6e504606fa03b4078e843b8927c29753dfc91a44c246cb22ea3673a3bad8dab7c8f6b8ce226a061983eaffadbdc7d6e7a0f9d9f5c1c64f983a4a6724aaa2126a0b6c03c984f3280",
"f90191a015203b1feedefc3d12d0e185733524b4e2e5e8c2bdaf7abff246a1fed7ac95e3a0493a8147104d998868825ea6deb1322aae76680d265471262e1767a23bdd1a7fa09b406baa1899b648205b0dd527c9bbde6ada6e3b4fc531a35bd2537d8db733f7a0426dd1071bf0b88c5742facc7fea20e28e765ab489cfdbdd5153e15ea3e2b32ca03edd49ea3795ac11d96e7290b12c1040c1e483c90462e720c7f1d16f873dc751a0132bf193ced5ce4fdb9c534386d84cb653c802dc21694d7dd78863921fea2acda09c60c4557046c9882148d3470e3fde97e88e5d35bd25e1a3cc94384e66a7af1080a0dea2418bd69d857116931f580a50c80761622d7488224a24b233bd4eaaa3c3b7a0bacb8d28242096ba6306d1c073fdeacd9bb5df804e3426c3c945f37836db68e680a08da1ba6ee52fb112c7f4707b78e039c8b52647ac5ce1122f7191356387dc169380a0f00a423bf08615d7c08955ea29573cd2a20d6d19d483ce4116333353290eae0ea06dd01d697beb2d96a5a41e803708b1d2cafd5992d80f7bf6d796e6aead4989ed8080",
"e2a020ef74619139dab09d59cafa630682f8f30445738dcfb7147514aa27399ae2ee01"
],
"expected_storage_value": "01",
"min_header_height": "",
"max_header_height": "",
"skip_bridge_call": true
}
Loading

0 comments on commit 9cc1964

Please sign in to comment.