Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into ci-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
karim-en committed Oct 23, 2023
2 parents 1c06fa0 + 0f7b70f commit 050a84e
Show file tree
Hide file tree
Showing 36 changed files with 726 additions and 74 deletions.
1 change: 0 additions & 1 deletion CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
# CODEOWNERS: https://help.github.com/articles/about-codeowners/
* @sept-en
* @karim-en
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: 2 additions & 0 deletions contracts/eth/nearbridge/.catalog-info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ spec:
system: bridge-protocol
deployedAt:
- contract:ethereum/mainnet/0x88f975d5a1153ea92af66e7c4292576a329c04b6
- contract:ethereum/goerli/0x6f2C9EbFB1e3Ff065E6725A715B458EF13206097
interactsWith: []
---
apiVersion: backstage.io/v1alpha1
Expand All @@ -43,6 +44,7 @@ spec:
system: bridge-protocol
deployedAt:
- contract:ethereum/mainnet/0x3FEFc5A4B1c02f21cBc8D3613643ba0635b9a873
- contract:ethereum/goerli/0x37c2d89b55bfd95532637554711441017efabfef
interactsWith:
- relayer:ethereum/mainnet/0x015e634c7c1311a9034220c28d3d12b7f710a3b1
deprecated:
Expand Down
1 change: 1 addition & 0 deletions contracts/eth/nearprover/.catalog-info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ spec:
system: bridge-protocol
deployedAt:
- contract:ethereum/mainnet/0x051ad3f020274910065dcb421629cd2e6e5b46c4
- contract:ethereum/goerli/0xf3430be687dc5652e3e96a9a7b291b5d423dfc3b
interactsWith:
- contract:ethereum/mainnet/0x3be7df8db39996a837041bb8ee0dadf60f767038
11 changes: 6 additions & 5 deletions contracts/near/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/near/eth-client/.catalog-info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ spec:
deployedAt:
- contract:near/mainnet/client.bridge.near
- contract:near/mainnet/client-eth2.bridge.near
- contract:near/testnet/client-eth2.goerli.testnet
interactsWith:
- relayer:near/mainnet/relayer.bridge.near
2 changes: 2 additions & 0 deletions contracts/near/eth-prover/.catalog-info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ spec:
system: bridge-protocol
deployedAt:
- contract:near/mainnet/prover.bridge.near
- contract:near/mainnet/prover_v2.bridge.near
- contract:near/testnet/prover.goerli.testnet
interactsWith:
- contract:near/mainnet/client.bridge.near
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;
Loading

0 comments on commit 050a84e

Please sign in to comment.