diff --git a/contracts/near/Cargo.lock b/contracts/near/Cargo.lock index 93f337cb..822ae64e 100644 --- a/contracts/near/Cargo.lock +++ b/contracts/near/Cargo.lock @@ -1101,7 +1101,7 @@ dependencies = [ [[package]] name = "eth-prover" -version = "0.2.0" +version = "2.0.0" dependencies = [ "borsh", "eth-types", diff --git a/contracts/near/eth-prover/Cargo.toml b/contracts/near/eth-prover/Cargo.toml index 37305ce7..6bc071dc 100644 --- a/contracts/near/eth-prover/Cargo.toml +++ b/contracts/near/eth-prover/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "eth-prover" -version = "0.2.0" +version = "2.0.0" authors = ["Near Inc "] edition = "2021" diff --git a/contracts/near/eth-prover/src/lib.rs b/contracts/near/eth-prover/src/lib.rs index ce513aff..463bcb5d 100644 --- a/contracts/near/eth-prover/src/lib.rs +++ b/contracts/near/eth-prover/src/lib.rs @@ -32,7 +32,7 @@ pub enum Role { #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize, PanicOnDefault, Pausable, Upgradable)] #[access_control(role_type(Role))] -#[pausable(manager_roles(Role::PauseManager))] +#[pausable(manager_roles(Role::PauseManager, Role::DAO))] #[upgradable(access_control_roles( code_stagers(Role::UpgradableCodeStager, Role::DAO), code_deployers(Role::UpgradableCodeDeployer, Role::DAO), @@ -132,9 +132,67 @@ impl EthProver { #[serializer(borsh)] proof: Vec>, #[serializer(borsh)] skip_bridge_call: bool, ) -> PromiseOrValue { + let min_header_height = None; + let max_header_height = None; + self.verify_log_entry_internal( + log_index, + log_entry_data, + receipt_index, + receipt_data, + header_data, + proof, + min_header_height, + max_header_height, + skip_bridge_call, + ) + } + + #[pause(except(roles(Role::UnrestrictedVerifyLogEntry, Role::DAO)))] + #[result_serializer(borsh)] + pub fn verify_log_entry_in_bound( + &self, + #[serializer(borsh)] log_index: u64, + #[serializer(borsh)] log_entry_data: Vec, + #[serializer(borsh)] receipt_index: u64, + #[serializer(borsh)] receipt_data: Vec, + #[serializer(borsh)] header_data: Vec, + #[serializer(borsh)] proof: Vec>, + #[serializer(borsh)] min_header_height: Option, + #[serializer(borsh)] max_header_height: Option, + #[serializer(borsh)] skip_bridge_call: bool, + ) -> PromiseOrValue { + self.verify_log_entry_internal( + log_index, + log_entry_data, + receipt_index, + receipt_data, + header_data, + proof, + min_header_height, + max_header_height, + skip_bridge_call, + ) + } + + fn verify_log_entry_internal( + &self, + #[serializer(borsh)] log_index: u64, + #[serializer(borsh)] log_entry_data: Vec, + #[serializer(borsh)] receipt_index: u64, + #[serializer(borsh)] receipt_data: Vec, + #[serializer(borsh)] header_data: Vec, + #[serializer(borsh)] proof: Vec>, + #[serializer(borsh)] min_header_height: Option, + #[serializer(borsh)] max_header_height: Option, + #[serializer(borsh)] skip_bridge_call: bool, + ) -> PromiseOrValue { + let header: BlockHeader = rlp::decode(header_data.as_slice()).unwrap(); + if !Self::is_block_height_in_bound(header.number, min_header_height, max_header_height) { + return PromiseOrValue::Value(false); + } + let log_entry: LogEntry = rlp::decode(log_entry_data.as_slice()).unwrap(); let receipt: Receipt = rlp::decode(receipt_data.as_slice()).unwrap(); - let header: BlockHeader = rlp::decode(header_data.as_slice()).unwrap(); // Verify log_entry included in receipt let log_index_usize = usize::try_from(log_index).expect("Invalid log_index"); @@ -185,31 +243,8 @@ impl EthProver { #[serializer(borsh)] skip_bridge_call: bool, ) -> PromiseOrValue { 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); - } + if !Self::is_block_height_in_bound(header.number, min_header_height, max_header_height) { + return PromiseOrValue::Value(false); } let account_key = near_keccak256(&contract_address).to_vec(); @@ -242,6 +277,40 @@ impl EthProver { .into() } + fn is_block_height_in_bound( + header_height: u64, + min_header_height: Option, + max_header_height: Option, + ) -> bool { + if let Some(min_header_height) = min_header_height { + if header_height < min_header_height { + env::log_str( + format!( + "Block height {} < Minimum header height {}", + header_height, min_header_height + ) + .as_str(), + ); + return false; + } + } + + if let Some(max_header_height) = max_header_height { + if header_height > max_header_height { + env::log_str( + format!( + "Block height {} > Maximum header height {}", + header_height, max_header_height + ) + .as_str(), + ); + return false; + } + } + + true + } + /// Verify the proof recursively traversing through the key. /// Return the value at the end of the key, in case the proof is valid. /// diff --git a/contracts/near/res/eth_prover.wasm b/contracts/near/res/eth_prover.wasm index 285ba6a7..34613509 100755 Binary files a/contracts/near/res/eth_prover.wasm and b/contracts/near/res/eth_prover.wasm differ