Skip to content

Commit

Permalink
Prover: add verify_log_entry_in_bound api (#919)
Browse files Browse the repository at this point in the history
* Prover: add `verify_log_entry_in_bound` api

* Improve naming

* Add DAO role to the pausable manager roles

* Update prover build

* Update prover version

* Update build

* Bump prover version
  • Loading branch information
karim-en committed Dec 7, 2023
1 parent aa6e165 commit 92e6ccc
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 29 deletions.
2 changes: 1 addition & 1 deletion contracts/near/Cargo.lock

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

2 changes: 1 addition & 1 deletion contracts/near/eth-prover/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "eth-prover"
version = "0.2.0"
version = "2.0.0"
authors = ["Near Inc <hello@nearprotocol.com>"]
edition = "2021"

Expand Down
123 changes: 96 additions & 27 deletions contracts/near/eth-prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -132,9 +132,67 @@ impl EthProver {
#[serializer(borsh)] proof: Vec<Vec<u8>>,
#[serializer(borsh)] skip_bridge_call: bool,
) -> PromiseOrValue<bool> {
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<u8>,
#[serializer(borsh)] receipt_index: u64,
#[serializer(borsh)] receipt_data: Vec<u8>,
#[serializer(borsh)] header_data: Vec<u8>,
#[serializer(borsh)] proof: Vec<Vec<u8>>,
#[serializer(borsh)] min_header_height: Option<u64>,
#[serializer(borsh)] max_header_height: Option<u64>,
#[serializer(borsh)] skip_bridge_call: bool,
) -> PromiseOrValue<bool> {
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<u8>,
#[serializer(borsh)] receipt_index: u64,
#[serializer(borsh)] receipt_data: Vec<u8>,
#[serializer(borsh)] header_data: Vec<u8>,
#[serializer(borsh)] proof: Vec<Vec<u8>>,
#[serializer(borsh)] min_header_height: Option<u64>,
#[serializer(borsh)] max_header_height: Option<u64>,
#[serializer(borsh)] skip_bridge_call: bool,
) -> PromiseOrValue<bool> {
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");
Expand Down Expand Up @@ -185,31 +243,8 @@ impl EthProver {
#[serializer(borsh)] skip_bridge_call: bool,
) -> PromiseOrValue<bool> {
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();
Expand Down Expand Up @@ -242,6 +277,40 @@ impl EthProver {
.into()
}

fn is_block_height_in_bound(
header_height: u64,
min_header_height: Option<u64>,
max_header_height: Option<u64>,
) -> 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.
///
Expand Down
Binary file modified contracts/near/res/eth_prover.wasm
Binary file not shown.

0 comments on commit 92e6ccc

Please sign in to comment.