Skip to content

Commit

Permalink
Add min_proof_acceptance_height (#74)
Browse files Browse the repository at this point in the history
* Add `min_proof_acceptance_height`

* Fix tests

* Fix tests

* Update `aurora-workspace` deps

* Add tests for `min_proof_acceptance_height`

* Fix mocked method

* Fix test

* Fix fmt
  • Loading branch information
karim-en authored Jan 8, 2024
1 parent f73bbe6 commit 6dbfd72
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 15 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

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

6 changes: 3 additions & 3 deletions eth-connector-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ publish = false
autobenches = false

[dev-dependencies]
aurora-eth-connector = { path = "../eth-connector" }
aurora-eth-connector = { path = "../eth-connector", features = ["integration-test"] }
aurora-engine-types = { workspace = true, features = ["impl-serde"] }
near-sdk.workspace = true
near-primitives.workspace = true
Expand All @@ -28,8 +28,8 @@ hex = "0.4.3"
ethabi = "18.0"
rlp = { version = "0.5.0", default-features = false }
aurora-engine-migration-tool = { git = "https://github.com/aurora-is-near/aurora-engine-migration-tool.git", tag = "0.2.2" }
aurora-workspace-eth-connector = { git = "https://github.com/aurora-is-near/aurora-workspace.git", tag = "0.4.1" }
aurora-workspace-utils = { git = "https://github.com/aurora-is-near/aurora-workspace.git", tag = "0.4.1" }
aurora-workspace-eth-connector = { git = "https://github.com/aurora-is-near/aurora-workspace.git", rev = "16d6263d6561cbc1f838016ae15416eadc88ec90" }
aurora-workspace-utils = { git = "https://github.com/aurora-is-near/aurora-workspace.git", rev = "16d6263d6561cbc1f838016ae15416eadc88ec90" }

[features]
migration-tests = []
39 changes: 35 additions & 4 deletions eth-connector-tests/src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,37 @@ async fn test_admin_controlled_admin_can_perform_actions_when_paused() {
assert_eq!(data.eth_custodian_address, custodian_addr);
}

#[tokio::test]
async fn test_deposit_with_proof_lower_than_acceptance_height() {
let min_proof_acceptance_height = 1000;
let contract = TestContract::new_with_options(
CUSTODIAN_ADDRESS,
"owner.root",
min_proof_acceptance_height,
)
.await
.unwrap();

// Should fail
let proof_header_height = min_proof_acceptance_height - 1;
let user_account = contract.contract_account("eth_recipient").await.unwrap();
let proof = contract.mock_proof(user_account.id(), 10, 1, proof_header_height);
let res = contract
.user_deposit_with_proof(&user_account, proof)
.await
.unwrap_err();
assert!(contract.check_error_message(&res, "ERR_VERIFY_PROOF"));

// Should succeed
let proof_header_height = min_proof_acceptance_height;
let proof = contract.mock_proof(user_account.id(), 10, 1, proof_header_height);
let res = contract
.user_deposit_with_proof(&user_account, proof)
.await
.unwrap();
assert!(res.is_success());
}

#[tokio::test]
async fn test_deposit_pausability() {
use aurora_eth_connector::admin_controlled::{PAUSE_DEPOSIT, UNPAUSE_ALL};
Expand All @@ -793,7 +824,7 @@ async fn test_deposit_pausability() {
.unwrap();

// 1st deposit call - should succeed
let proof1 = contract.mock_proof(user_acc.id(), 10, 1);
let proof1 = contract.mock_proof(user_acc.id(), 10, 1, 0);
let res = contract
.user_deposit_with_proof(&user_acc, proof1)
.await
Expand All @@ -811,14 +842,14 @@ async fn test_deposit_pausability() {
assert!(res.is_success());

// 2nd deposit call - should fail for `user_acc`
let proof2 = contract.mock_proof(user_acc.id(), 20, 2);
let proof2 = contract.mock_proof(user_acc.id(), 20, 2, 0);
let res = contract
.user_deposit_with_proof(&user_acc, proof2)
.await
.unwrap_err();
assert!(contract.check_error_message(&res, "ERR_PAUSED"));

let proof3 = contract.mock_proof(user_acc.id(), 30, 3);
let proof3 = contract.mock_proof(user_acc.id(), 30, 3, 0);
let res = contract
.user_deposit_with_proof(&owner_acc, proof3)
.await
Expand All @@ -836,7 +867,7 @@ async fn test_deposit_pausability() {
assert!(res.is_success());

// 3rd deposit call - should succeed
let proof4 = contract.mock_proof(user_acc.id(), 40, 4);
let proof4 = contract.mock_proof(user_acc.id(), 40, 4, 0);
let res = contract
.user_deposit_with_proof(&user_acc, proof4)
.await
Expand Down
20 changes: 19 additions & 1 deletion eth-connector-tests/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ impl TestContract {
pub async fn new_with_custodian_and_owner(
eth_custodian_address: &str,
owner_id: &str,
) -> anyhow::Result<Self> {
Self::new_with_options(eth_custodian_address, owner_id, 0).await
}

pub async fn new_with_options(
eth_custodian_address: &str,
owner_id: &str,
min_proof_acceptance_height: u64,
) -> anyhow::Result<Self> {
let (contract, root_account) = Self::deploy_eth_connector().await?;
let owner_id: AccountId = owner_id.parse().unwrap();
Expand All @@ -48,6 +56,7 @@ impl TestContract {
metadata,
&account_with_access_right,
&owner_id,
min_proof_acceptance_height,
)
.transact()
.await?;
Expand Down Expand Up @@ -234,6 +243,7 @@ impl TestContract {
recipient_id: &AccountId,
deposit_amount: u128,
proof_index: u64,
header_height: u64,
) -> Proof {
use aurora_engine_types::{
types::{Fee, NEP141Wei},
Expand Down Expand Up @@ -277,17 +287,25 @@ impl TestContract {
ethabi::Token::Uint(U256::from(fee.as_u128())),
]),
};
// The borsh is used instead of rlp to simplify the mock logic
let header_data =
near_sdk::borsh::BorshSerialize::try_to_vec(&aurora_eth_connector::proof::MockHeader {
height: header_height,
})
.unwrap();

Proof {
log_index: proof_index,
// Only this field matters for the purpose of this test
log_entry_data: rlp::encode(&log_entry).to_vec(),
receipt_index: 1,
header_data,
..Default::default()
}
}

pub async fn call_deposit_contract(&self) -> anyhow::Result<()> {
let proof = self.mock_proof(self.contract.id(), DEPOSITED_CONTRACT, 1);
let proof = self.mock_proof(self.contract.id(), DEPOSITED_CONTRACT, 1, 0);
let res = self.deposit_with_proof(&proof).await?;
assert!(res.is_success(), "call_deposit_contract: {res:#?}");
Ok(())
Expand Down
1 change: 1 addition & 0 deletions eth-connector/src/admin_controlled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ fn test_pause_control() {
paused_mask: UNPAUSE_ALL,
account_with_access_right: "aurora".parse().unwrap(),
owner_id: "aurora".parse().unwrap(),
min_proof_acceptance_height: 0,
};

assert!(connector.assert_not_paused(PAUSE_DEPOSIT).is_ok());
Expand Down
2 changes: 1 addition & 1 deletion eth-connector/src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub trait FundsFinish {
#[ext_contract(ext_proof_verifier)]
pub trait ProofVerifier {
#[result_serializer(borsh)]
fn verify_log_entry(&self, #[serializer(borsh)] args: VerifyProofArgs) -> bool;
fn verify_log_entry_in_bound(&self, #[serializer(borsh)] args: VerifyProofArgs) -> bool;
}

/// Withdraw method for legacy implementation in Engine
Expand Down
10 changes: 8 additions & 2 deletions eth-connector/src/connector_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
connector::{ext_funds_finish, ext_proof_verifier},
deposit_event::{DepositedEvent, TokenMessageData},
errors, log, panic_err,
proof::Proof,
proof::{Proof, VerifyProofArgs},
types::SdkUnwrap,
AdminControlled, PausedMask,
};
Expand Down Expand Up @@ -58,6 +58,9 @@ pub struct EthConnector {
pub account_with_access_right: AccountId,
/// Owner's account id.
pub owner_id: AccountId,
/// Proofs from blocks that are below the acceptance height will be rejected.
// If `minBlockAcceptanceHeight` value is zero - proofs from block with any height are accepted.
pub min_proof_acceptance_height: u64,
}

impl AdminControlled for EthConnector {
Expand Down Expand Up @@ -160,9 +163,12 @@ impl EthConnector {
}
};

let mut verify_log_args: VerifyProofArgs = proof.into();
verify_log_args.min_header_height = Some(self.min_proof_acceptance_height);

ext_proof_verifier::ext(self.prover_account.clone())
.with_static_gas(GAS_FOR_VERIFY_LOG_ENTRY)
.verify_log_entry(proof.into())
.verify_log_entry_in_bound(verify_log_args)
.then(
ext_funds_finish::ext(current_account_id)
.with_static_gas(GAS_FOR_FINISH_DEPOSIT)
Expand Down
16 changes: 14 additions & 2 deletions eth-connector/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ impl EthConnectorContract {
metadata: &FungibleTokenMetadata,
account_with_access_right: AccountId,
owner_id: &AccountId,
min_proof_acceptance_height: u64,
) -> Self {
metadata.assert_valid();

Expand All @@ -177,6 +178,7 @@ impl EthConnectorContract {
eth_custodian_address,
account_with_access_right,
owner_id: owner_id.clone(),
min_proof_acceptance_height,
};
let mut this = Self {
ft: FungibleToken {
Expand Down Expand Up @@ -204,8 +206,16 @@ impl EthConnectorContract {
#[result_serializer(borsh)]
#[must_use]
#[allow(unused_variables)]
pub fn verify_log_entry(#[serializer(borsh)] proof_args: &VerifyProofArgs) -> bool {
log!("Call from verify_log_entry");
pub fn verify_log_entry_in_bound(
&self,
#[serializer(borsh)] proof_args: &VerifyProofArgs,
) -> bool {
log!("Call from verify_log_entry_in_bound");
if let Ok(header) = proof::MockHeader::try_from_slice(&proof_args.header_data) {
if header.height < self.connector.min_proof_acceptance_height {
return false;
}
}
true
}

Expand Down Expand Up @@ -721,12 +731,14 @@ mod tests {
};
let account_with_access_right = "engine.near".parse().unwrap();
let owner_id = "owner.near".parse().unwrap();
let min_proof_acceptance_height = 0;
EthConnectorContract::new(
prover_account,
eth_custodian_address,
&metadata,
account_with_access_right,
&owner_id,
min_proof_acceptance_height,
)
}
}
10 changes: 10 additions & 0 deletions eth-connector/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ pub struct VerifyProofArgs {
pub receipt_data: Vec<u8>,
pub header_data: Vec<u8>,
pub proof: Vec<Vec<u8>>,
pub min_header_height: Option<u64>,
pub max_header_height: Option<u64>,
pub skip_bridge_call: bool,
}

Expand All @@ -54,11 +56,19 @@ impl From<Proof> for VerifyProofArgs {
receipt_data: value.receipt_data,
header_data: value.header_data,
proof: value.proof,
min_header_height: None,
max_header_height: None,
skip_bridge_call: false,
}
}
}

#[cfg(feature = "integration-test")]
#[derive(BorshDeserialize, BorshSerialize, Default, Debug)]
pub struct MockHeader {
pub height: u64,
}

#[cfg(test)]
mod tests {
use super::Proof;
Expand Down

0 comments on commit 6dbfd72

Please sign in to comment.