From 83fee73690dd39433a4130ae2415e34b675ed23d Mon Sep 17 00:00:00 2001 From: Karim Date: Tue, 23 May 2023 15:23:35 +0100 Subject: [PATCH 01/13] Implement `serde::Deserialize` for `AccountId` (#763) ## Description The AccountId validation is missing on parsing a JSON input, and this leads to the possibility of calling `ft_transfer()` with an invalid `receiver_id`. here is an [example](https://explorer.near.org/transactions/HKLVudra9nYdtuFBncFipSveZ5d6D1TbHGfAnM4S2rWg) that we received. This pull request removes the default implementation of the `serde::Deserialize` and implements a custom one. --- engine-types/src/account_id.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/engine-types/src/account_id.rs b/engine-types/src/account_id.rs index 1a884a34a..af0ea93ff 100644 --- a/engine-types/src/account_id.rs +++ b/engine-types/src/account_id.rs @@ -16,17 +16,7 @@ pub const MAX_ACCOUNT_ID_LEN: usize = 64; /// /// This guarantees all properly constructed `AccountId`'s are valid for the NEAR network. #[derive( - Default, - BorshSerialize, - Serialize, - Deserialize, - Eq, - Ord, - Hash, - Clone, - Debug, - PartialEq, - PartialOrd, + Default, BorshSerialize, Serialize, Eq, Ord, Hash, Clone, Debug, PartialEq, PartialOrd, )] pub struct AccountId(Box); @@ -126,6 +116,17 @@ impl BorshDeserialize for AccountId { } } +impl<'de> Deserialize<'de> for AccountId { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + D::Error: serde::de::Error, + { + let account = ::deserialize(deserializer)?; + Self::new(&account).map_err(serde::de::Error::custom) + } +} + impl TryFrom for AccountId { type Error = ParseAccountError; @@ -499,4 +500,10 @@ mod tests { ); } } + + #[test] + fn test_json_deserialize_account_id() { + assert!(serde_json::from_str::(r#""test.near""#).is_ok()); + assert!(serde_json::from_str::(r#""test@.near""#).is_err()); + } } From 2df90c13a671f1f540122ed725672e8427e9b360 Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Wed, 31 May 2023 13:52:32 -0400 Subject: [PATCH 02/13] Fix: use single crate for borsh version, allow to choose borsh v0.9 for all crates (#767) ## Description [Near Workspaces](https://crates.io/crates/workspaces) still uses `borsh` version 0.9. Therefore we need the `borsh-compat` feature on all our crates that use `borsh` if we want to use them in Workspaces-based tests. This PR makes this change. This is a non-functional change (impacts only a dependency version and only if a feature is specified), therefore has no impact on tests or performance. --- Cargo.lock | 4 ---- engine-precompiles/Cargo.toml | 4 ++-- engine-precompiles/src/prelude.rs | 3 +-- engine-precompiles/src/promise_result.rs | 3 +-- engine-precompiles/src/xcc.rs | 4 ++-- engine-sdk/Cargo.toml | 4 ++-- engine-sdk/src/io.rs | 2 +- engine-sdk/src/prelude.rs | 6 ++++-- engine-standalone-storage/Cargo.toml | 2 +- engine-standalone-storage/src/diff.rs | 2 +- engine-standalone-storage/src/sync/types.rs | 2 +- engine-tests/src/test_utils/erc20.rs | 10 +++++++++- engine-types/src/lib.rs | 5 +++++ engine/Cargo.toml | 4 ++-- engine/src/connector.rs | 1 + engine/src/deposit_event.rs | 1 + engine/src/fungible_token.rs | 1 + engine/src/lib.rs | 2 +- engine/src/parameters.rs | 1 + engine/src/pausables.rs | 2 +- engine/src/prelude.rs | 2 +- engine/src/proof.rs | 1 + engine/src/state.rs | 2 +- engine/src/xcc.rs | 2 +- 24 files changed, 42 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9501a39f..3fe6a1a82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -270,7 +270,6 @@ dependencies = [ "aurora-engine-transactions", "aurora-engine-types", "bitflags", - "borsh 0.10.3", "byte-slice-cast", "digest 0.10.6", "ethabi", @@ -300,7 +299,6 @@ dependencies = [ "aurora-engine-sdk", "aurora-engine-test-doubles", "aurora-engine-types", - "borsh 0.10.3", "ethabi", "evm", "hex", @@ -321,7 +319,6 @@ version = "1.0.0" dependencies = [ "aurora-engine-types", "base64 0.21.0", - "borsh 0.10.3", "sha2 0.10.6", "sha3", ] @@ -1443,7 +1440,6 @@ dependencies = [ "aurora-engine-sdk", "aurora-engine-transactions", "aurora-engine-types", - "borsh 0.10.3", "evm-core", "hex", "postgres", diff --git a/engine-precompiles/Cargo.toml b/engine-precompiles/Cargo.toml index e3bb8e747..921a671a2 100644 --- a/engine-precompiles/Cargo.toml +++ b/engine-precompiles/Cargo.toml @@ -16,7 +16,6 @@ autobenches = false aurora-engine-modexp = { path = "../engine-modexp", default-features = false } aurora-engine-types = { path = "../engine-types", default-features = false } aurora-engine-sdk = { path = "../engine-sdk", default-features = false } -borsh = { version = "0.10", default-features = false } bn = { version = "0.5.11", package = "zeropool-bn", default-features = false } evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } libsecp256k1 = { version = "0.7.0", default-features = false, features = ["static-context", "hmac"] } @@ -35,7 +34,8 @@ rand = "0.8.5" [features] default = ["std"] -std = ["aurora-engine-types/std", "aurora-engine-sdk/std", "borsh/std", "bn/std", "evm/std", "libsecp256k1/std", "ripemd/std", "sha2/std", "sha3/std", "ethabi/std"] +std = ["aurora-engine-types/std", "aurora-engine-sdk/std", "bn/std", "evm/std", "libsecp256k1/std", "ripemd/std", "sha2/std", "sha3/std", "ethabi/std"] +borsh-compat = ["aurora-engine-types/borsh-compat", "aurora-engine-sdk/borsh-compat"] contract = [] log = [] error_refund = [] diff --git a/engine-precompiles/src/prelude.rs b/engine-precompiles/src/prelude.rs index d17d21682..1e6b68f3e 100644 --- a/engine-precompiles/src/prelude.rs +++ b/engine-precompiles/src/prelude.rs @@ -1,8 +1,7 @@ pub use aurora_engine_sdk as sdk; pub use aurora_engine_types::account_id::*; +pub use aurora_engine_types::borsh::{BorshDeserialize, BorshSerialize}; pub use aurora_engine_types::parameters; pub use aurora_engine_types::storage; pub use aurora_engine_types::types; pub use aurora_engine_types::*; - -pub use borsh::{BorshDeserialize, BorshSerialize}; diff --git a/engine-precompiles/src/promise_result.rs b/engine-precompiles/src/promise_result.rs index d11b6d6ae..5b4fa8d66 100644 --- a/engine-precompiles/src/promise_result.rs +++ b/engine-precompiles/src/promise_result.rs @@ -2,8 +2,7 @@ use super::{EvmPrecompileResult, Precompile}; use crate::prelude::types::{Address, EthGas}; use crate::{utils, PrecompileOutput}; use aurora_engine_sdk::promise::ReadOnlyPromiseHandler; -use aurora_engine_types::{Cow, Vec}; -use borsh::BorshSerialize; +use aurora_engine_types::{borsh::BorshSerialize, Cow, Vec}; use evm::{Context, ExitError}; /// `get_promise_results` precompile address diff --git a/engine-precompiles/src/xcc.rs b/engine-precompiles/src/xcc.rs index 64d61fa24..3c6d36559 100644 --- a/engine-precompiles/src/xcc.rs +++ b/engine-precompiles/src/xcc.rs @@ -7,12 +7,12 @@ use crate::{utils, HandleBasedPrecompile, PrecompileOutput}; use aurora_engine_sdk::io::IO; use aurora_engine_types::{ account_id::AccountId, + borsh::{BorshDeserialize, BorshSerialize}, format, parameters::{CrossContractCallArgs, PromiseCreateArgs}, types::{balance::ZERO_YOCTO, Address, EthGas, NearGas}, vec, Cow, Vec, H160, H256, U256, }; -use borsh::{BorshDeserialize, BorshSerialize}; use evm::backend::Log; use evm::executor::stack::{PrecompileFailure, PrecompileHandle}; use evm::ExitError; @@ -238,9 +238,9 @@ pub mod state { use aurora_engine_sdk::error::ReadU32Error; use aurora_engine_sdk::io::{StorageIntermediate, IO}; + use aurora_engine_types::borsh::{self, BorshDeserialize, BorshSerialize}; use aurora_engine_types::storage::{self, KeyPrefix}; use aurora_engine_types::types::{Address, Yocto}; - use borsh::{BorshDeserialize, BorshSerialize}; pub const ERR_CORRUPTED_STORAGE: &str = "ERR_CORRUPTED_XCC_STORAGE"; pub const ERR_MISSING_WNEAR_ADDRESS: &str = "ERR_MISSING_WNEAR_ADDRESS"; diff --git a/engine-sdk/Cargo.toml b/engine-sdk/Cargo.toml index 4d8f67854..7302b594c 100644 --- a/engine-sdk/Cargo.toml +++ b/engine-sdk/Cargo.toml @@ -16,12 +16,12 @@ autobenches = false aurora-engine-types = { path = "../engine-types", default-features = false } base64 = { version = "0.21", default-features = false, features = [ "alloc" ] } -borsh = { version = "0.10", default-features = false } sha2 = { version = "0.10", default-features = false } sha3 = { version = "0.10", default-features = false } [features] -std = ["aurora-engine-types/std", "borsh/std", "sha3/std", "sha2/std", "base64/std" ] +std = ["aurora-engine-types/std", "sha3/std", "sha2/std", "base64/std" ] +borsh-compat = ["aurora-engine-types/borsh-compat"] contract = [] log = [] all-promise-actions = [] diff --git a/engine-sdk/src/io.rs b/engine-sdk/src/io.rs index 7aeb7aaa8..cb1d0102e 100644 --- a/engine-sdk/src/io.rs +++ b/engine-sdk/src/io.rs @@ -1,7 +1,7 @@ use crate::error; use crate::prelude::{vec, Vec}; +use aurora_engine_types::borsh::{BorshDeserialize, BorshSerialize}; use aurora_engine_types::U256; -use borsh::{BorshDeserialize, BorshSerialize}; /// The purpose of this trait is to represent a reference to a value that /// could be obtained by IO, but without eagerly loading it into memory. diff --git a/engine-sdk/src/prelude.rs b/engine-sdk/src/prelude.rs index 118ef3ef4..1da66d09b 100644 --- a/engine-sdk/src/prelude.rs +++ b/engine-sdk/src/prelude.rs @@ -1,3 +1,5 @@ pub use aurora_engine_types::types::{Address, NearGas, PromiseResult, STORAGE_PRICE_PER_BYTE}; -pub use aurora_engine_types::{vec, Vec, H256, U256}; -pub use borsh::{BorshDeserialize, BorshSerialize}; +pub use aurora_engine_types::{ + borsh::{BorshDeserialize, BorshSerialize}, + vec, Vec, H256, U256, +}; diff --git a/engine-standalone-storage/Cargo.toml b/engine-standalone-storage/Cargo.toml index 93075b8c1..9bb4659ff 100644 --- a/engine-standalone-storage/Cargo.toml +++ b/engine-standalone-storage/Cargo.toml @@ -19,7 +19,6 @@ aurora-engine-types = { path = "../engine-types", default-features = false, feat aurora-engine-sdk = { path = "../engine-sdk", default-features = false, features = ["std"] } aurora-engine-transactions = { path = "../engine-transactions", default-features = false, features = ["std"] } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false, features = ["std"] } -borsh = "0.10" evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } hex = "0.4.3" rocksdb = { version = "0.19.0", default-features = false } @@ -29,6 +28,7 @@ serde_json = "1.0.72" [features] default = ["snappy", "lz4", "zstd", "zlib"] +borsh-compat = ["aurora-engine-types/borsh-compat", "aurora-engine-sdk/borsh-compat", "aurora-engine-precompiles/borsh-compat", "aurora-engine/borsh-compat"] mainnet = [] testnet = [] snappy = ["rocksdb/snappy"] diff --git a/engine-standalone-storage/src/diff.rs b/engine-standalone-storage/src/diff.rs index fc9002d3a..c9a4c7111 100644 --- a/engine-standalone-storage/src/diff.rs +++ b/engine-standalone-storage/src/diff.rs @@ -1,4 +1,4 @@ -use borsh::{BorshDeserialize, BorshSerialize}; +use aurora_engine_types::borsh::{self, BorshDeserialize, BorshSerialize}; use std::collections::{btree_map, BTreeMap}; #[derive(Debug, Default, Clone, BorshDeserialize, BorshSerialize, PartialEq, Eq)] diff --git a/engine-standalone-storage/src/sync/types.rs b/engine-standalone-storage/src/sync/types.rs index 9f171df32..1b4073f0d 100644 --- a/engine-standalone-storage/src/sync/types.rs +++ b/engine-standalone-storage/src/sync/types.rs @@ -5,10 +5,10 @@ use aurora_engine_transactions::{EthTransactionKind, NormalizedEthTransaction}; use aurora_engine_types::account_id::AccountId; use aurora_engine_types::types::Address; use aurora_engine_types::{ + borsh::{self, BorshDeserialize, BorshSerialize}, types::{self, Wei}, H256, U256, }; -use borsh::{BorshDeserialize, BorshSerialize}; use std::borrow::Cow; /// Type describing the format of messages sent to the storage layer for keeping diff --git a/engine-tests/src/test_utils/erc20.rs b/engine-tests/src/test_utils/erc20.rs index 2c3432337..9fba895d5 100644 --- a/engine-tests/src/test_utils/erc20.rs +++ b/engine-tests/src/test_utils/erc20.rs @@ -60,7 +60,15 @@ impl ERC20Constructor { // if multiple tests running in parallel saw `contracts_dir` does not exist). DOWNLOAD_ONCE.call_once(|| { let url = "https://github.com/OpenZeppelin/openzeppelin-contracts"; - git2::Repository::clone(url, sources_dir).unwrap(); + let repo = git2::Repository::clone(url, sources_dir).unwrap(); + // We need to checkout a specific commit hash because the preset contract we use + // was removed from the repo later + // (https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3637). + let commit_hash = + git2::Oid::from_str("dfef6a68ee18dbd2e1f5a099061a3b8a0e404485").unwrap(); + repo.set_head_detached(commit_hash).unwrap(); + let mut opts = git2::build::CheckoutBuilder::new(); + repo.checkout_head(Some(opts.force())).unwrap(); }); } diff --git a/engine-types/src/lib.rs b/engine-types/src/lib.rs index 6f47cd984..74ec29b41 100644 --- a/engine-types/src/lib.rs +++ b/engine-types/src/lib.rs @@ -33,6 +33,11 @@ mod v0 { ops::Mul, ops::Sub, ops::SubAssign, }; pub use primitive_types::{H160, H256, U256}; + + #[cfg(not(feature = "borsh-compat"))] + pub use borsh; + #[cfg(feature = "borsh-compat")] + pub use borsh_compat::{self as borsh}; } pub use v0::*; diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 2c63735b5..448d01936 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -21,7 +21,6 @@ aurora-engine-sdk = { path = "../engine-sdk", default-features = false } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false } aurora-engine-transactions = { path = "../engine-transactions", default-features = false } bitflags = { version = "1.3", default-features = false } -borsh = { version = "0.10", default-features = false } byte-slice-cast = { version = "1.0", default-features = false } ethabi = { version = "18.0", default-features = false } evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } @@ -40,8 +39,9 @@ digest = "0.10" [features] default = ["std"] -std = ["aurora-engine-types/std", "aurora-engine-sdk/std", "aurora-engine-precompiles/std", "aurora-engine-transactions/std", "borsh/std", "byte-slice-cast/std", "ethabi/std", "evm/std", "hex/std", "rlp/std", "serde/std", "serde_json/std"] +std = ["aurora-engine-types/std", "aurora-engine-sdk/std", "aurora-engine-precompiles/std", "aurora-engine-transactions/std", "byte-slice-cast/std", "ethabi/std", "evm/std", "hex/std", "rlp/std", "serde/std", "serde_json/std"] contract = ["aurora-engine-sdk/contract", "aurora-engine-precompiles/contract"] +borsh-compat = ["aurora-engine-types/borsh-compat", "aurora-engine-sdk/borsh-compat", "aurora-engine-precompiles/borsh-compat"] evm_bully = [] log = ["aurora-engine-sdk/log", "aurora-engine-precompiles/log"] tracing = ["evm/tracing"] diff --git a/engine/src/connector.rs b/engine/src/connector.rs index c4f9b3b32..685d98e63 100644 --- a/engine/src/connector.rs +++ b/engine/src/connector.rs @@ -19,6 +19,7 @@ use crate::prelude::{PromiseBatchAction, PromiseCreateArgs, PromiseWithCallbackA use crate::proof::Proof; use aurora_engine_sdk::env::Env; use aurora_engine_sdk::io::{StorageIntermediate, IO}; +use aurora_engine_types::borsh; pub const ERR_NOT_ENOUGH_BALANCE_FOR_FEE: &str = "ERR_NOT_ENOUGH_BALANCE_FOR_FEE"; /// Indicate zero attached balance for promise call diff --git a/engine/src/deposit_event.rs b/engine/src/deposit_event.rs index f23743eb7..79c7eaf79 100644 --- a/engine/src/deposit_event.rs +++ b/engine/src/deposit_event.rs @@ -4,6 +4,7 @@ use crate::prelude::account_id::AccountId; use crate::prelude::{ vec, Address, BorshDeserialize, BorshSerialize, Fee, NEP141Wei, String, ToString, Vec, U256, }; +use aurora_engine_types::borsh; use aurora_engine_types::types::address::error::AddressError; use byte_slice_cast::AsByteSlice; use ethabi::{Event, EventParam, Hash, Log, ParamType, RawLog}; diff --git a/engine/src/fungible_token.rs b/engine/src/fungible_token.rs index 1f63006ea..146a442de 100644 --- a/engine/src/fungible_token.rs +++ b/engine/src/fungible_token.rs @@ -9,6 +9,7 @@ use crate::prelude::{ StorageBalanceBounds, StorageUsage, String, ToString, Vec, }; use aurora_engine_sdk::io::{StorageIntermediate, IO}; +use aurora_engine_types::borsh; use aurora_engine_types::types::{NEP141Wei, Yocto, ZERO_NEP141_WEI, ZERO_YOCTO}; use serde::{Deserialize, Serialize}; diff --git a/engine/src/lib.rs b/engine/src/lib.rs index b81a9b131..93570141f 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -74,7 +74,6 @@ pub unsafe fn on_alloc_error(_: core::alloc::Layout) -> ! { #[cfg(feature = "contract")] mod contract { - use borsh::{BorshDeserialize, BorshSerialize}; use parameters::{SetOwnerArgs, SetUpgradeDelayBlocksArgs}; use crate::connector::{self, EthConnectorContract}; @@ -106,6 +105,7 @@ mod contract { use aurora_engine_sdk::io::{StorageIntermediate, IO}; use aurora_engine_sdk::near_runtime::{Runtime, ViewEnv}; use aurora_engine_sdk::promise::PromiseHandler; + use aurora_engine_types::borsh::{BorshDeserialize, BorshSerialize}; #[cfg(feature = "integration-test")] use crate::prelude::NearGas; diff --git a/engine/src/parameters.rs b/engine/src/parameters.rs index e67480d7b..5557b2a90 100644 --- a/engine/src/parameters.rs +++ b/engine/src/parameters.rs @@ -3,6 +3,7 @@ use crate::fungible_token::FungibleTokenMetadata; use crate::prelude::account_id::AccountId; use crate::prelude::{Address, Balance, BorshDeserialize, BorshSerialize, RawU256, String, Vec}; use crate::proof::Proof; +use aurora_engine_types::borsh; pub use aurora_engine_types::parameters::engine::{ CallArgs, DeployErc20TokenArgs, FunctionCallArgsV1, FunctionCallArgsV2, GetErc20FromNep141CallArgs, GetStorageAtArgs, ResultLog, SubmitResult, TransactionStatus, diff --git a/engine/src/pausables.rs b/engine/src/pausables.rs index 459b5af23..4d3bc3b46 100644 --- a/engine/src/pausables.rs +++ b/engine/src/pausables.rs @@ -1,9 +1,9 @@ use crate::prelude::{AccountId, Address, BTreeSet, Vec}; use aurora_engine_precompiles::native::{exit_to_ethereum, exit_to_near}; use aurora_engine_sdk::io::{StorageIntermediate, IO}; +use aurora_engine_types::borsh::{self, BorshDeserialize, BorshSerialize}; use aurora_engine_types::storage::{bytes_to_key, KeyPrefix}; use bitflags::bitflags; -use borsh::{BorshDeserialize, BorshSerialize}; bitflags! { /// Wraps unsigned integer where each bit identifies a different precompile. diff --git a/engine/src/prelude.rs b/engine/src/prelude.rs index 81c80363c..e5684a44c 100644 --- a/engine/src/prelude.rs +++ b/engine/src/prelude.rs @@ -4,11 +4,11 @@ mod v0 { pub use aurora_engine_sdk::types::*; pub use aurora_engine_transactions as transactions; pub use aurora_engine_types::account_id::*; + pub use aurora_engine_types::borsh::{BorshDeserialize, BorshSerialize}; pub use aurora_engine_types::parameters::*; pub use aurora_engine_types::storage::*; pub use aurora_engine_types::types::*; pub use aurora_engine_types::*; - pub use borsh::{BorshDeserialize, BorshSerialize}; } pub use v0::*; diff --git a/engine/src/proof.rs b/engine/src/proof.rs index 507dc2789..3331b9e85 100644 --- a/engine/src/proof.rs +++ b/engine/src/proof.rs @@ -1,4 +1,5 @@ use crate::prelude::{sdk, BorshDeserialize, BorshSerialize, String, ToString, Vec}; +use aurora_engine_types::borsh; #[derive(Debug, Default, BorshDeserialize, BorshSerialize, Clone)] #[cfg_attr(feature = "impl-serde", derive(serde::Deserialize, serde::Serialize))] diff --git a/engine/src/state.rs b/engine/src/state.rs index 51f7ae108..248b2027d 100644 --- a/engine/src/state.rs +++ b/engine/src/state.rs @@ -1,9 +1,9 @@ use crate::parameters::{LegacyNewCallArgs, NewCallArgs, NewCallArgsV2}; use aurora_engine_sdk::io::{StorageIntermediate, IO}; use aurora_engine_types::account_id::AccountId; +use aurora_engine_types::borsh::{self, BorshDeserialize, BorshSerialize}; use aurora_engine_types::storage::{bytes_to_key, KeyPrefix}; use aurora_engine_types::{Cow, Vec}; -use borsh::{BorshDeserialize, BorshSerialize}; pub use error::EngineStateError; diff --git a/engine/src/xcc.rs b/engine/src/xcc.rs index ebeb1e16b..245b9654b 100644 --- a/engine/src/xcc.rs +++ b/engine/src/xcc.rs @@ -5,11 +5,11 @@ use aurora_engine_sdk::env::Env; use aurora_engine_sdk::io::{StorageIntermediate, IO}; use aurora_engine_sdk::promise::PromiseHandler; use aurora_engine_types::account_id::AccountId; +use aurora_engine_types::borsh::{self, BorshDeserialize, BorshSerialize}; use aurora_engine_types::parameters::{PromiseAction, PromiseBatchAction, PromiseCreateArgs}; use aurora_engine_types::storage::{self, KeyPrefix}; use aurora_engine_types::types::{Address, NearGas, Yocto, ZERO_YOCTO}; use aurora_engine_types::{format, Cow, Vec, U256}; -use borsh::{BorshDeserialize, BorshSerialize}; pub const ERR_NO_ROUTER_CODE: &str = "ERR_MISSING_XCC_BYTECODE"; pub const ERR_INVALID_ACCOUNT: &str = "ERR_INVALID_XCC_ACCOUNT"; From 5c68ee682d2ea103948a1f6713823635c7abc305 Mon Sep 17 00:00:00 2001 From: mandreyel Date: Thu, 1 Jun 2023 15:41:04 +0400 Subject: [PATCH 03/13] feat: shanghai hf support (#766) Adds Shanghai hardfork support by integrating updated aurora-sputnikvm. N/A Testing has been added to sputnikvm's test suite. All engine tests are passing. The majority of changes are in sputnikvm which have already been reviewed. N/A --------- Co-authored-by: Oleksandr Anyshchenko --- Cargo.lock | 323 ++++++++++-------------- engine-precompiles/Cargo.toml | 2 +- engine-precompiles/src/lib.rs | 10 +- engine-standalone-storage/Cargo.toml | 2 +- engine-standalone-tracing/Cargo.toml | 8 +- engine-test-doubles/Cargo.toml | 6 +- engine-tests/Cargo.toml | 6 +- engine-tests/src/test_utils/solidity.rs | 10 +- engine-transactions/Cargo.toml | 2 +- engine/Cargo.toml | 2 +- engine/src/engine.rs | 5 + 11 files changed, 161 insertions(+), 215 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3fe6a1a82..b67afd829 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -235,7 +235,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -246,7 +246,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -271,7 +271,7 @@ dependencies = [ "aurora-engine-types", "bitflags", "byte-slice-cast", - "digest 0.10.6", + "digest 0.10.7", "ethabi", "evm", "hex", @@ -318,7 +318,7 @@ name = "aurora-engine-sdk" version = "1.0.0" dependencies = [ "aurora-engine-types", - "base64 0.21.0", + "base64 0.21.1", "sha2 0.10.6", "sha3", ] @@ -440,9 +440,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105" [[package]] name = "bincode" @@ -633,9 +633,9 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bstr" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" +checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" dependencies = [ "memchr", "once_cell", @@ -645,9 +645,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.1" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "byte-slice-cast" @@ -657,9 +657,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytecheck" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fe11640a23eb24562225322cd3e452b93a3d4091d62fab69c70542fcd17d1f" +checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -668,9 +668,9 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31225543cb46f81a7e224762764f4a6a0f097b1db0b175f69e8065efaa42de5" +checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" dependencies = [ "proc-macro2", "quote", @@ -837,25 +837,25 @@ dependencies = [ [[package]] name = "clap" -version = "4.2.7" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" +checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" dependencies = [ "clap_builder", - "clap_derive 4.2.0", + "clap_derive 4.3.0", "once_cell", ] [[package]] name = "clap_builder" -version = "4.2.7" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" +checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" dependencies = [ "anstream", "anstyle", "bitflags", - "clap_lex 0.4.1", + "clap_lex 0.5.0", "strsim", ] @@ -874,14 +874,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b" dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -895,9 +895,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "cloudabi" @@ -908,16 +908,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "colorchoice" version = "1.0.0" @@ -1224,50 +1214,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "cxx" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.15", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.15", -] - [[package]] name = "darling" version = "0.20.1" @@ -1288,7 +1234,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -1299,7 +1245,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" dependencies = [ "darling_core", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -1346,9 +1292,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "crypto-common", @@ -1499,7 +1445,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -1608,8 +1554,8 @@ dependencies = [ [[package]] name = "evm" -version = "0.37.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.4-aurora#a7a0fb429d5fd479aecaa51687cad1f818772051" +version = "0.39.0" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.38.0-aurora#fcc538cc1f7f91156ef66564a8ac032a82bd4b9e" dependencies = [ "auto_impl", "environmental", @@ -1628,8 +1574,8 @@ dependencies = [ [[package]] name = "evm-core" -version = "0.37.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.4-aurora#a7a0fb429d5fd479aecaa51687cad1f818772051" +version = "0.39.0" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.38.0-aurora#fcc538cc1f7f91156ef66564a8ac032a82bd4b9e" dependencies = [ "parity-scale-codec", "primitive-types 0.12.1", @@ -1639,8 +1585,8 @@ dependencies = [ [[package]] name = "evm-gasometer" -version = "0.37.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.4-aurora#a7a0fb429d5fd479aecaa51687cad1f818772051" +version = "0.39.0" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.38.0-aurora#fcc538cc1f7f91156ef66564a8ac032a82bd4b9e" dependencies = [ "environmental", "evm-core", @@ -1650,8 +1596,8 @@ dependencies = [ [[package]] name = "evm-runtime" -version = "0.37.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.37.4-aurora#a7a0fb429d5fd479aecaa51687cad1f818772051" +version = "0.39.0" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.38.0-aurora#fcc538cc1f7f91156ef66564a8ac032a82bd4b9e" dependencies = [ "auto_impl", "environmental", @@ -1810,7 +1756,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -1933,9 +1879,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21" +checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" dependencies = [ "bytes", "fnv", @@ -2071,7 +2017,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -2171,12 +2117,11 @@ dependencies = [ [[package]] name = "iana-time-zone-haiku" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cxx", - "cxx-build", + "cc", ] [[package]] @@ -2319,9 +2264,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" dependencies = [ "wasm-bindgen", ] @@ -2349,7 +2294,7 @@ checksum = "b111244b70d4cf22aaaf8e0461ede19d623880f0f4779ee33dc35850a825bec3" dependencies = [ "lazy_static", "manifest-dir-macros", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -2493,15 +2438,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "link-cplusplus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] - [[package]] name = "linux-raw-sys" version = "0.1.4" @@ -2510,9 +2446,9 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "lock_api" @@ -2589,7 +2525,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -2607,7 +2543,7 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -2856,7 +2792,7 @@ source = "git+https://github.com/birchmd/nearcore.git?rev=71c9b3f4c62f1bff24982a dependencies = [ "actix", "atty", - "clap 4.2.7", + "clap 4.3.0", "near-crypto 0.0.0", "near-primitives-core 0.0.0", "once_cell", @@ -3033,7 +2969,7 @@ source = "git+https://github.com/birchmd/nearcore.git?rev=71c9b3f4c62f1bff24982a dependencies = [ "quote", "serde", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -3055,7 +2991,7 @@ dependencies = [ "fs2", "near-rpc-error-core 0.0.0", "serde", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -3865,22 +3801,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.16", ] [[package]] @@ -3949,7 +3885,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b7fa9f396f51dffd61546fd8573ee20592287996568e6175ceb0f8699ad75d" dependencies = [ - "base64 0.21.0", + "base64 0.21.1", "byteorder", "bytes", "fallible-iterator", @@ -4053,9 +3989,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" dependencies = [ "unicode-ident", ] @@ -4329,13 +4265,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.1", + "regex-syntax 0.7.2", ] [[package]] @@ -4355,9 +4291,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "region" @@ -4386,28 +4322,31 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] name = "rkyv" -version = "0.7.41" +version = "0.7.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21499ed91807f07ae081880aabb2ccc0235e9d88011867d984525e9a4c3cfa3e" +checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" dependencies = [ + "bitvec", "bytecheck", "hashbrown 0.12.3", "ptr_meta", "rend", "rkyv_derive", "seahash", + "tinyvec", + "uuid", ] [[package]] name = "rkyv_derive" -version = "0.7.41" +version = "0.7.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1c672430eb41556291981f45ca900a0239ad007242d1cb4b4167af842db666" +checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" dependencies = [ "proc-macro2", "quote", @@ -4493,9 +4432,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.13" +version = "0.36.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a38f9520be93aba504e8ca974197f46158de5dcaa9fa04b57c57cd6a679d658" +checksum = "14e4d67015953998ad0eb82887a0eb0129e18a7e2f3b7b0f6c422fddcd503d62" dependencies = [ "bitflags", "errno 0.3.1", @@ -4515,7 +4454,7 @@ dependencies = [ "errno 0.3.1", "io-lifetimes", "libc", - "linux-raw-sys 0.3.7", + "linux-raw-sys 0.3.8", "windows-sys 0.48.0", ] @@ -4542,9 +4481,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfdef77228a4c05dc94211441595746732131ad7f6530c6c18f045da7b7ab937" +checksum = "b569c32c806ec3abdf3b5869fb8bf1e0d275a7c1c9b0b05603d9464632649edf" dependencies = [ "bitvec", "cfg-if 1.0.0", @@ -4571,12 +4510,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "scratch" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" - [[package]] name = "seahash" version = "4.1.0" @@ -4644,9 +4577,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.162" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] @@ -4672,13 +4605,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.162" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -4700,7 +4633,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -4737,7 +4670,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -4746,7 +4679,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "keccak", ] @@ -4892,9 +4825,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" @@ -4909,9 +4842,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" dependencies = [ "proc-macro2", "quote", @@ -5016,7 +4949,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] @@ -5226,15 +5159,15 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" [[package]] name = "toml_edit" -version = "0.19.8" +version = "0.19.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f" dependencies = [ "indexmap", "toml_datetime", @@ -5348,14 +5281,14 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", "valuable", @@ -5475,12 +5408,6 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - [[package]] name = "unsafe-libyaml" version = "0.2.8" @@ -5504,6 +5431,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "uuid" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" + [[package]] name = "valuable" version = "0.1.0" @@ -5594,9 +5527,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -5604,24 +5537,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.16", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5629,22 +5562,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.16", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" [[package]] name = "wasm-encoder" @@ -5863,9 +5796,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a396af81a7c56ad976131d6a35e4b693b78a1ea0357843bd436b4577e254a7d" +checksum = "83be9e0b3f9570dc1979a33ae7b89d032c73211564232b99976553e5c155ec32" dependencies = [ "indexmap", "url", @@ -5873,12 +5806,12 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.2.56" +version = "0.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "731da2505d5437cd5d6feb09457835f76186be13be7677fe00781ae99d5bbe8a" +checksum = "50b0e5ed7a74a065637f0d7798ce5f29cadb064980d24b0c82af5200122fa0d8" dependencies = [ "anyhow", - "wasmparser 0.104.0", + "wasmparser 0.105.0", ] [[package]] @@ -6016,7 +5949,7 @@ dependencies = [ "memoffset 0.6.5", "paste", "rand 0.8.5", - "rustix 0.36.13", + "rustix 0.36.14", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-jit-debug", @@ -6037,9 +5970,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" dependencies = [ "js-sys", "wasm-bindgen", @@ -6290,7 +6223,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.16", ] [[package]] diff --git a/engine-precompiles/Cargo.toml b/engine-precompiles/Cargo.toml index 921a671a2..37e410bd4 100644 --- a/engine-precompiles/Cargo.toml +++ b/engine-precompiles/Cargo.toml @@ -17,7 +17,7 @@ aurora-engine-modexp = { path = "../engine-modexp", default-features = false } aurora-engine-types = { path = "../engine-types", default-features = false } aurora-engine-sdk = { path = "../engine-sdk", default-features = false } bn = { version = "0.5.11", package = "zeropool-bn", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false } libsecp256k1 = { version = "0.7.0", default-features = false, features = ["static-context", "hmac"] } num = { version = "0.4.0", default-features = false, features = ["alloc"] } ripemd = { version = "0.1.1", default-features = false } diff --git a/engine-precompiles/src/lib.rs b/engine-precompiles/src/lib.rs index 0792ae5fa..7b4b2fe1c 100644 --- a/engine-precompiles/src/lib.rs +++ b/engine-precompiles/src/lib.rs @@ -39,11 +39,11 @@ use aurora_engine_sdk::env::Env; use aurora_engine_sdk::io::IO; use aurora_engine_sdk::promise::ReadOnlyPromiseHandler; use aurora_engine_types::{account_id::AccountId, types::Address, vec, BTreeMap, BTreeSet, Box}; -use evm::backend::Log; use evm::executor::{ self, stack::{PrecompileFailure, PrecompileHandle}, }; +use evm::{backend::Log, executor::stack::IsPrecompileResult}; use evm::{Context, ExitError, ExitFatal, ExitSucceed}; use promise_result::PromiseResult; use xcc::cross_contract_call; @@ -154,8 +154,12 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> executor::stack::Preco Some(result.and_then(|output| post_process(output, handle))) } - fn is_precompile(&self, address: prelude::H160) -> bool { - self.all_precompiles.contains_key(&Address::new(address)) + fn is_precompile(&self, address: prelude::H160, _remaining_gas: u64) -> IsPrecompileResult { + let is_precompile = self.all_precompiles.contains_key(&Address::new(address)); + IsPrecompileResult::Answer { + is_precompile, + extra_cost: 0, + } } } diff --git a/engine-standalone-storage/Cargo.toml b/engine-standalone-storage/Cargo.toml index 9bb4659ff..a8ffb1575 100644 --- a/engine-standalone-storage/Cargo.toml +++ b/engine-standalone-storage/Cargo.toml @@ -19,7 +19,7 @@ aurora-engine-types = { path = "../engine-types", default-features = false, feat aurora-engine-sdk = { path = "../engine-sdk", default-features = false, features = ["std"] } aurora-engine-transactions = { path = "../engine-transactions", default-features = false, features = ["std"] } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false, features = ["std"] } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false } hex = "0.4.3" rocksdb = { version = "0.19.0", default-features = false } postgres = "0.19.2" diff --git a/engine-standalone-tracing/Cargo.toml b/engine-standalone-tracing/Cargo.toml index 9f1ccabe9..4d74de0ac 100644 --- a/engine-standalone-tracing/Cargo.toml +++ b/engine-standalone-tracing/Cargo.toml @@ -15,10 +15,10 @@ crate-type = ["lib"] [dependencies] aurora-engine-types = { path = "../engine-types", default-features = false, features = ["std"] } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std"] } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } -evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } -evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false, features = ["std"] } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false, features = ["std", "tracing"] } +evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false, features = ["std", "tracing"] } +evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false, features = ["std", "tracing"] } hex = { version = "0.4", default-features = false, features = ["std"] } serde = { version = "1", features = ["derive"], optional = true } diff --git a/engine-test-doubles/Cargo.toml b/engine-test-doubles/Cargo.toml index 85aa5e10d..1a9da60b8 100644 --- a/engine-test-doubles/Cargo.toml +++ b/engine-test-doubles/Cargo.toml @@ -15,8 +15,8 @@ autobenches = false [dependencies] aurora-engine-types = { path = "../engine-types", default-features = false, features = ["std"] } aurora-engine-sdk = { path = "../engine-sdk" } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } -evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } -evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false, features = ["std", "tracing"] } +evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false, features = ["std", "tracing"] } +evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false, features = ["std", "tracing"] } [dev-dependencies] diff --git a/engine-tests/Cargo.toml b/engine-tests/Cargo.toml index f6c3a3d93..9516891f2 100644 --- a/engine-tests/Cargo.toml +++ b/engine-tests/Cargo.toml @@ -28,9 +28,9 @@ criterion = "0.4.0" engine-standalone-storage = { path = "../engine-standalone-storage" } engine-standalone-tracing = { path = "../engine-standalone-tracing", default-features = false, features = ["impl-serde"] } ethabi = "18.0" -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } -evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } -evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false, features = ["std", "tracing"] } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false, features = ["std", "tracing"] } +evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false, features = ["std", "tracing"] } +evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false, features = ["std", "tracing"] } git2 = "0.17" hex = { version = "0.4.3", default-features = false } libsecp256k1 = { version = "0.7.0", default-features = false } diff --git a/engine-tests/src/test_utils/solidity.rs b/engine-tests/src/test_utils/solidity.rs index 16e860d02..68e41b174 100644 --- a/engine-tests/src/test_utils/solidity.rs +++ b/engine-tests/src/test_utils/solidity.rs @@ -2,6 +2,7 @@ use crate::prelude::{transactions::legacy::TransactionLegacy, Address, U256}; use aurora_engine_types::types::Wei; use serde::Deserialize; use std::fs; +use std::io::BufReader; use std::path::Path; use std::process::Command; @@ -69,7 +70,8 @@ impl ContractConstructor { ); let code = hex::decode(hex_rep).unwrap(); let abi_path = artifacts_base_path.as_ref().join(abi_file); - let reader = fs::File::open(abi_path).unwrap(); + let file = fs::File::open(abi_path).unwrap(); + let reader = BufReader::new(file); let abi = ethabi::Contract::load(reader).unwrap(); Self { abi, code } @@ -79,7 +81,8 @@ impl ContractConstructor { where P: AsRef, { - let reader = std::fs::File::open(contract_path).unwrap(); + let file = fs::File::open(contract_path).unwrap(); + let reader = BufReader::new(file); let contract: ExtendedJsonSolidityArtifact = serde_json::from_reader(reader).unwrap(); Self { @@ -192,9 +195,10 @@ where ]) .output() .unwrap(); + let cwd = std::env::current_dir(); assert!( output.status.success(), - "Could not compile solidity contracts in docker: {}", + "Could not compile solidity contracts in docker [source={source_mount_arg}, output={output_mount_arg}, contract={contract_arg}, workdir={cwd:?}]: {}", String::from_utf8(output.stderr).unwrap() ); } diff --git a/engine-transactions/Cargo.toml b/engine-transactions/Cargo.toml index 07aaefe73..24cca1ef1 100644 --- a/engine-transactions/Cargo.toml +++ b/engine-transactions/Cargo.toml @@ -16,7 +16,7 @@ autobenches = false aurora-engine-types = { path = "../engine-types", default-features = false } aurora-engine-sdk = { path = "../engine-sdk", default-features = false } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false } rlp = { version = "0.5.0", default-features = false } serde = { version = "1", default-features = false, features = ["alloc", "derive"], optional = true } diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 448d01936..11d03a452 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -23,7 +23,7 @@ aurora-engine-transactions = { path = "../engine-transactions", default-features bitflags = { version = "1.3", default-features = false } byte-slice-cast = { version = "1.0", default-features = false } ethabi = { version = "18.0", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.37.4-aurora", default-features = false } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.38.0-aurora", default-features = false } hex = { version = "0.4", default-features = false, features = ["alloc"] } rlp = { version = "0.5.0", default-features = false } serde = { version = "1", default-features = false, features = ["alloc", "derive"] } diff --git a/engine/src/engine.rs b/engine/src/engine.rs index e1c85c10d..66d738ec7 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -1497,6 +1497,11 @@ impl<'env, I: IO + Copy, E: Env> evm::backend::Backend for Engine<'env, I, E> { U256::zero() } + /// Get environmental block randomness. + fn block_randomness(&self) -> Option { + Some(self.env.random_seed()) + } + /// Returns the current block gas limit. /// /// Currently, this returns 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff From 7ed17b3e7d8e4ed9435507d915e2be51f8ccd69e Mon Sep 17 00:00:00 2001 From: Oleksandr Anyshchenko Date: Thu, 1 Jun 2023 13:42:11 +0200 Subject: [PATCH 04/13] chore: comment docs improvement in the eth-connector module (#764) ## Description The PR improves some comment docs in the eth-connector module and applies tiny refactoring. ## Performance / NEAR gas cost considerations No changes. ## Testing ## How should this be reviewed ## Additional information --- engine/src/connector.rs | 149 ++++++++++++++++++----------------- engine/src/deposit_event.rs | 6 +- engine/src/fungible_token.rs | 99 +++++++++++------------ engine/src/proof.rs | 4 +- 4 files changed, 133 insertions(+), 125 deletions(-) diff --git a/engine/src/connector.rs b/engine/src/connector.rs index 685d98e63..4d70ae9a9 100644 --- a/engine/src/connector.rs +++ b/engine/src/connector.rs @@ -8,9 +8,7 @@ use crate::parameters::{ SetContractDataCallArgs, StorageBalanceOfCallArgs, StorageDepositCallArgs, StorageWithdrawCallArgs, TransferCallArgs, TransferCallCallArgs, WithdrawResult, }; -use crate::prelude::{ - address::error::AddressError, NEP141Wei, Wei, U256, ZERO_NEP141_WEI, ZERO_WEI, -}; +use crate::prelude::{address::error::AddressError, NEP141Wei, Wei, ZERO_NEP141_WEI, ZERO_WEI}; use crate::prelude::{ format, sdk, str, AccountId, Address, BorshDeserialize, BorshSerialize, EthConnectorStorageId, KeyPrefix, NearGas, PromiseResult, ToString, Vec, WithdrawCallArgs, Yocto, ERR_FAILED_PARSE, @@ -50,12 +48,14 @@ pub struct EthConnectorContract { io: I, } -/// Connector specific data. It always should contain `prover account` - +/// Eth connector specific data. It always must contain `prover_account` - account id of the smart +/// contract which is used for verifying a proof used in the deposit flow. #[derive(BorshSerialize, BorshDeserialize)] pub struct EthConnector { - /// It used in the Deposit flow, to verify log entry form incoming proof. + /// The account id of the Prover NEAR smart contract. It used in the Deposit flow for verifying + /// a log entry from incoming proof. pub prover_account: AccountId, - /// It is Eth address, used in the Deposit and Withdraw logic. + /// It is Ethereum address used in the Deposit and Withdraw logic. pub eth_custodian_address: Address, } @@ -121,23 +121,23 @@ impl EthConnectorContract { Ok(()) } - /// Deposit all types of tokens + /// Deposit all types of tokens. pub fn deposit( &self, raw_proof: Vec, current_account_id: AccountId, predecessor_account_id: AccountId, ) -> Result { - // Check is current account owner + // Check if the current account is owner. let is_owner = current_account_id == predecessor_account_id; - // Check is current flow paused. If it's owner account just skip it. + // Check if the deposit flow isn't paused. If it's owner just skip it. self.assert_not_paused(PAUSE_DEPOSIT, is_owner) .map_err(|_| error::DepositError::Paused)?; sdk::log!("[Deposit tokens]"); // Get incoming deposit arguments - let proof: Proof = + let proof = Proof::try_from_slice(&raw_proof).map_err(|_| error::DepositError::ProofParseFailed)?; // Fetch event data from Proof let event = DepositedEvent::from_log_entry_data(&proof.log_entry_data) @@ -165,7 +165,7 @@ impl EthConnectorContract { return Err(error::DepositError::InsufficientAmountForFee); } - // Verify proof data with cross-contract call to prover account + // Verify the proof data by sending cross-contract call to the prover smart contract. sdk::log!( "Deposit verify_log_entry for prover: {}", self.contract.prover_account, @@ -173,8 +173,7 @@ impl EthConnectorContract { // Do not skip bridge call. This is only used for development and diagnostics. let skip_bridge_call = false.try_to_vec().unwrap(); - let mut proof_to_verify = raw_proof; - proof_to_verify.extend(skip_bridge_call); + let proof_to_verify = [raw_proof, skip_bridge_call].concat(); let verify_call = PromiseCreateArgs { target_account_id: self.contract.prover_account.clone(), @@ -241,11 +240,10 @@ impl EthConnectorContract { }) } - /// Finish deposit (private method) - /// NOTE: we should `record_proof` only after `mint` operation. The reason - /// is that in this case we only calculate the amount to be credited but - /// do not save it, however, if an error occurs during the calculation, - /// this will happen before `record_proof`. After that contract will save. + /// Finish deposit flow (private method). + /// NOTE: In the mint methods could occur an error while calculating the amount to be + /// credited and therefore we invoke `record_proof` after mint methods to avoid saving + /// proof before minting which could be potentially finished with error. pub fn finish_deposit( &mut self, predecessor_account_id: AccountId, @@ -274,7 +272,9 @@ impl EthConnectorContract { } else { // Mint - calculate new balances self.mint_eth_on_near( - &data.new_owner_id.clone(), + &data.new_owner_id, + // it's safe subtracting because we check that the amount is greater than fee in + // the deposit method. data.amount - NEP141Wei::new(data.fee.as_u128()), )?; self.mint_eth_on_near(&data.relayer_id, NEP141Wei::new(data.fee.as_u128()))?; @@ -286,7 +286,7 @@ impl EthConnectorContract { } } - /// Internal ETH withdraw ETH logic + /// Internal `ETH` withdraw (ETH on Aurora). pub(crate) fn internal_remove_eth( &mut self, amount: Wei, @@ -296,7 +296,7 @@ impl EthConnectorContract { Ok(()) } - /// Record used proof as hash key + /// Record hash of the used proof in the storage. fn record_proof(&mut self, key: &str) -> Result<(), error::ProofUsed> { sdk::log!("Record proof: {}", key); @@ -308,7 +308,7 @@ impl EthConnectorContract { Ok(()) } - /// Mint `nETH` tokens + /// Mint `nETH` tokens (ETH on NEAR). fn mint_eth_on_near( &mut self, owner_id: &AccountId, @@ -322,17 +322,17 @@ impl EthConnectorContract { self.ft.internal_deposit_eth_to_near(owner_id, amount) } - /// Mint ETH tokens + /// Mint `ETH` tokens (ETH on Aurora). fn mint_eth_on_aurora( &mut self, - owner_id: Address, + address: Address, amount: Wei, ) -> Result<(), fungible_token::error::DepositError> { - sdk::log!("Mint {} ETH tokens for: {}", amount, owner_id.encode()); - self.ft.internal_deposit_eth_to_aurora(owner_id, amount) + sdk::log!("Mint {} ETH tokens for: {}", amount, address.encode()); + self.ft.internal_deposit_eth_to_aurora(address, amount) } - /// Burn ETH tokens + /// Burn `ETH` tokens (ETH on Aurora). fn burn_eth_on_aurora( &mut self, amount: Wei, @@ -348,9 +348,9 @@ impl EthConnectorContract { predecessor_account_id: &AccountId, args: &WithdrawCallArgs, ) -> Result { - // Check is current account id is owner + // Check if the current account id is owner. let is_owner = current_account_id == predecessor_account_id; - // Check is current flow paused. If it's owner just skip asserrion. + // Check if the withdraw flow is paused. If it's owner just skip the assertion. self.assert_not_paused(PAUSE_WITHDRAW, is_owner) .map_err(|_| error::WithdrawError::Paused)?; @@ -367,7 +367,7 @@ impl EthConnectorContract { }) } - /// Returns total ETH supply on NEAR (`nETH` as NEP-141 token) + /// Returns total `nETH` supply (ETH on NEAR). pub fn ft_total_eth_supply_on_near(&mut self) { let total_supply = self.ft.ft_total_eth_supply_on_near(); sdk::log!("Total ETH supply on NEAR: {}", total_supply); @@ -375,7 +375,7 @@ impl EthConnectorContract { .return_output(format!("\"{total_supply}\"").as_bytes()); } - /// Returns total ETH supply on Aurora (ETH in Aurora EVM) + /// Returns total `ETH` supply (ETH on Aurora). pub fn ft_total_eth_supply_on_aurora(&mut self) { let total_supply = self.ft.ft_total_eth_supply_on_aurora(); sdk::log!("Total ETH supply on Aurora: {}", total_supply); @@ -383,7 +383,7 @@ impl EthConnectorContract { .return_output(format!("\"{total_supply}\"").as_bytes()); } - /// Return balance of `nETH` (ETH on Near) + /// Return `nETH` balance (ETH on NEAR). pub fn ft_balance_of(&mut self, args: &BalanceOfCallArgs) { let balance = self.ft.ft_balance_of(&args.account_id); sdk::log!("Balance of nETH [{}]: {}", args.account_id, balance); @@ -391,7 +391,7 @@ impl EthConnectorContract { self.io.return_output(format!("\"{balance}\"").as_bytes()); } - /// Return balance of ETH (ETH in Aurora EVM) + /// Return `ETH` balance (ETH on Aurora). pub fn ft_balance_of_eth_on_aurora( &mut self, args: &BalanceOfEthCallArgs, @@ -404,7 +404,7 @@ impl EthConnectorContract { Ok(()) } - /// Transfer between NEAR accounts + /// Transfer `nETH` between NEAR accounts. pub fn ft_transfer( &mut self, predecessor_account_id: &AccountId, @@ -448,10 +448,11 @@ impl EthConnectorContract { self.io.return_output(format!("\"{amount}\"").as_bytes()); } - /// FT transfer call from sender account (invoker account) to receiver - /// We starting early checking for message data to avoid `ft_on_transfer` call panics - /// But we don't check relayer exists. If relayer doesn't exist we simply not mint/burn the amount of the fee - /// We allow empty messages for cases when `receiver_id =! current_account_id` + /// FT transfer call from sender account (invoker account) to receiver. + /// We start early checking for message data to avoid `ft_on_transfer` call panics. + /// But we don't check if the relayer exists. If the relayer doesn't exist we simply + /// do not mint/burn the fee amount. + /// We allow empty messages for cases when `receiver_id =! current_account_id`. pub fn ft_transfer_call( &mut self, predecessor_account_id: AccountId, @@ -475,9 +476,10 @@ impl EthConnectorContract { return Err(error::FtTransferCallError::InsufficientAmountForFee); } - // Additional check overflow before process `ft_on_transfer` - // But don't check overflow for relayer - // Note: It can't overflow because the total supply doesn't change during transfer. + // Additional check for overflowing before `ft_on_transfer` calling. + // But skip checking for overflowing for the relayer. + // Note: It couldn't be overflowed because the total supply isn't changed during + // the transfer. let amount_for_check = self .ft .internal_unwrap_balance_of_eth_on_aurora(&message_data.recipient); @@ -514,7 +516,7 @@ impl EthConnectorContract { .map_err(Into::into) } - /// FT storage deposit logic + /// FT storage deposit logic. pub fn storage_deposit( &mut self, predecessor_account_id: AccountId, @@ -535,7 +537,7 @@ impl EthConnectorContract { Ok(maybe_promise) } - /// FT storage unregister + /// FT storage unregister. pub fn storage_unregister( &mut self, account_id: AccountId, @@ -555,7 +557,7 @@ impl EthConnectorContract { Ok(promise) } - /// FT storage withdraw + /// FT storage withdraw. pub fn storage_withdraw( &mut self, account_id: &AccountId, @@ -567,13 +569,13 @@ impl EthConnectorContract { Ok(()) } - /// Get balance of storage + /// Get the balance used by usage of the storage. pub fn storage_balance_of(&mut self, args: &StorageBalanceOfCallArgs) { self.io .return_output(&self.ft.storage_balance_of(&args.account_id).to_json_bytes()); } - /// `ft_on_transfer` callback function + /// `ft_on_transfer` callback function. pub fn ft_on_transfer( &mut self, engine: &Engine, @@ -583,41 +585,44 @@ impl EthConnectorContract { // Parse message with specific rules let message_data = FtTransferMessageData::parse_on_transfer_message(&args.msg) .map_err(error::FtTransferCallError::MessageParseFailed)?; - + let amount = Wei::new_u128(args.amount.as_u128()); // Special case when predecessor_account_id is current_account_id - let wei_fee = Wei::from(message_data.fee); + let fee = Wei::from(message_data.fee); // Mint fee to relayer let relayer = engine.get_relayer(message_data.relayer.as_bytes()); - match (wei_fee, relayer) { - (fee, Some(evm_relayer_address)) if fee > ZERO_WEI => { - let eth_amount = Wei::new_u128(args.amount.as_u128()) - .checked_sub(fee) - .ok_or(error::FtTransferCallError::InsufficientAmountForFee)?; - self.mint_eth_on_aurora(message_data.recipient, eth_amount)?; - self.mint_eth_on_aurora(evm_relayer_address, fee)?; - } - _ => self.mint_eth_on_aurora( - message_data.recipient, - Wei::new(U256::from(args.amount.as_u128())), - )?, + let (amount, relayer_fee) = + relayer + .filter(|_| fee > ZERO_WEI) + .map_or(Ok((amount, None)), |address| { + amount.checked_sub(fee).map_or( + Err(error::FtTransferCallError::InsufficientAmountForFee), + |amount| Ok((amount, Some((address, fee)))), + ) + })?; + + if let Some((address, fee)) = relayer_fee { + self.mint_eth_on_aurora(address, fee)?; } + + self.mint_eth_on_aurora(message_data.recipient, amount)?; self.save_ft_contract(); self.io.return_output(b"\"0\""); Ok(()) } - /// Get accounts counter for statistics. + /// Return account counter. /// It represents total unique accounts (all-time, including accounts which now have zero balance). pub fn get_accounts_counter(&mut self) { self.io .return_output(&self.ft.get_accounts_counter().to_le_bytes()); } + /// Return account id of the prover smart contract. pub const fn get_bridge_prover(&self) -> &AccountId { &self.contract.prover_account } - /// Save eth-connector fungible token contract data + /// Save eth-connector fungible token contract data in the storage. fn save_ft_contract(&mut self) { self.io.write_borsh( &construct_contract_key(EthConnectorStorageId::FungibleToken), @@ -625,11 +630,13 @@ impl EthConnectorContract { ); } - /// Generate key for used events from Proof + /// Generate key for used events from Proof. fn used_event_key(key: &str) -> Vec { - let mut v = construct_contract_key(EthConnectorStorageId::UsedEvent); - v.extend_from_slice(key.as_bytes()); - v + [ + &construct_contract_key(EthConnectorStorageId::UsedEvent), + key.as_bytes(), + ] + .concat() } /// Save already used event proof as hash key @@ -637,12 +644,12 @@ impl EthConnectorContract { self.io.write_borsh(&Self::used_event_key(key), &0u8); } - /// Check is event of proof already used + /// Check if the event of the proof has already been used. fn is_used_event(&self, key: &str) -> bool { self.io.storage_has_key(&Self::used_event_key(key)) } - /// Checks whether the provided proof was already used + /// Check whether the provided proof has already been used. pub fn is_used_proof(&self, proof: &Proof) -> bool { self.is_used_event(&proof.key()) } @@ -659,12 +666,12 @@ impl EthConnectorContract { } impl AdminControlled for EthConnectorContract { - /// Get current admin paused status + /// Get current admin paused status. fn get_paused(&self) -> PausedMask { self.paused_mask } - /// Set admin paused status + /// Set admin paused status. fn set_paused(&mut self, paused_mask: PausedMask) { self.paused_mask = paused_mask; self.io.write_borsh( @@ -714,7 +721,7 @@ pub fn set_contract_data( Ok(contract_data) } -/// Return metadata +/// Return FT metadata. pub fn get_metadata(io: &I) -> Option { io.read_storage(&construct_contract_key( EthConnectorStorageId::FungibleTokenMetadata, diff --git a/engine/src/deposit_event.rs b/engine/src/deposit_event.rs index 79c7eaf79..8a089310a 100644 --- a/engine/src/deposit_event.rs +++ b/engine/src/deposit_event.rs @@ -132,14 +132,14 @@ impl TokenMessageData { pub fn parse_event_message_and_prepare_token_message_data( message: &str, fee: Fee, - ) -> Result { + ) -> Result { let data: Vec<_> = message.split(':').collect(); // Data array can contain 1 or 2 elements if data.len() >= 3 { - return Err(error::ParseEventMessageError::TooManyParts); + return Err(ParseEventMessageError::TooManyParts); } let account_id = AccountId::try_from(data[0].as_bytes()) - .map_err(|_| error::ParseEventMessageError::InvalidAccount)?; + .map_err(|_| ParseEventMessageError::InvalidAccount)?; // If data array contain only one element it should return NEAR account id if data.len() == 1 { diff --git a/engine/src/fungible_token.rs b/engine/src/fungible_token.rs index 146a442de..3af46f75a 100644 --- a/engine/src/fungible_token.rs +++ b/engine/src/fungible_token.rs @@ -117,12 +117,12 @@ impl FungibleTokenOps { } } - /// Balance of ETH (ETH on Aurora) + /// Balance of ETH (ETH on Aurora). pub fn internal_unwrap_balance_of_eth_on_aurora(&self, address: &Address) -> Wei { engine::get_balance(&self.io, address) } - /// Internal ETH deposit to NEAR - `nETH` (NEP-141) + /// Internal `nETH` deposit (ETH on NEAR). pub fn internal_deposit_eth_to_near( &mut self, account_id: &AccountId, @@ -142,7 +142,7 @@ impl FungibleTokenOps { Ok(()) } - /// Internal ETH deposit to Aurora + /// Internal `ETH` deposit (ETH on Aurora). pub fn internal_deposit_eth_to_aurora( &mut self, address: Address, @@ -160,7 +160,7 @@ impl FungibleTokenOps { Ok(()) } - /// Withdraw NEAR tokens + /// Withdraw `nETH` tokens (ETH on NEAR). pub fn internal_withdraw_eth_from_near( &mut self, account_id: &AccountId, @@ -180,7 +180,7 @@ impl FungibleTokenOps { Ok(()) } - /// Withdraw ETH tokens + /// Withdraw `ETH` tokens (ETH on Aurora). pub fn internal_withdraw_eth_from_aurora( &mut self, amount: Wei, @@ -192,7 +192,7 @@ impl FungibleTokenOps { Ok(()) } - /// Transfer NEAR tokens + /// Transfer `nETH` tokens (ETH on NEAR). pub fn internal_transfer_eth_on_near( &mut self, sender_id: &AccountId, @@ -224,18 +224,22 @@ impl FungibleTokenOps { Ok(()) } + /// Register a new account with zero balance. pub fn internal_register_account(&mut self, account_id: &AccountId) { self.accounts_insert(account_id, ZERO_NEP141_WEI); } + /// Return total `nETH` supply (ETH on NEAR). pub const fn ft_total_eth_supply_on_near(&self) -> NEP141Wei { self.total_eth_supply_on_near } + /// Return total `ETH` supply (ETH on Aurora). pub const fn ft_total_eth_supply_on_aurora(&self) -> Wei { self.total_eth_supply_on_aurora } + /// Return `nETH` balance of the account (ETH on NEAR). pub fn ft_balance_of(&self, account_id: &AccountId) -> NEP141Wei { self.get_account_eth_balance(account_id) .unwrap_or(ZERO_NEP141_WEI) @@ -357,6 +361,7 @@ impl FungibleTokenOps { }; } } + (amount, ZERO_NEP141_WEI) } @@ -436,36 +441,29 @@ impl FungibleTokenOps { ) -> Result<(StorageBalance, Option), error::StorageFundingError> { let promise = if self.accounts_contains_key(account_id) { sdk::log!("The account is already registered, refunding the deposit"); - if amount > ZERO_YOCTO { - let action = PromiseAction::Transfer { amount }; - let promise = PromiseBatchAction { - target_account_id: predecessor_account_id, - actions: vec![action], - }; - Some(promise) - } else { - None - } + amount } else { let min_balance = self.storage_balance_bounds().min; + if amount < min_balance { return Err(error::StorageFundingError::InsufficientDeposit); } self.internal_register_account(account_id); - let refund = amount - min_balance; - if refund > ZERO_YOCTO { - let action = PromiseAction::Transfer { amount: refund }; - let promise = PromiseBatchAction { - target_account_id: predecessor_account_id, - actions: vec![action], - }; - Some(promise) - } else { - None - } + amount - min_balance + }; + let promise = if amount > ZERO_YOCTO { + let action = PromiseAction::Transfer { amount }; + let promise = PromiseBatchAction { + target_account_id: predecessor_account_id, + actions: vec![action], + }; + Some(promise) + } else { + None }; let balance = self.internal_storage_balance_of(account_id).unwrap(); + Ok((balance, promise)) } @@ -489,29 +487,28 @@ impl FungibleTokenOps { ) } - /// Insert account. - /// Calculate total unique accounts + /// Set account's balance and increment the account counter if the account doesn't exist. pub fn accounts_insert(&mut self, account_id: &AccountId, amount: NEP141Wei) { if !self.accounts_contains_key(account_id) { - let key = Self::get_statistic_key(); - let accounts_counter = self - .io - .read_u64(&key) - .unwrap_or(0) - .checked_add(1) - .expect(crate::errors::ERR_ACCOUNTS_COUNTER_OVERFLOW); - self.io.write_storage(&key, &accounts_counter.to_le_bytes()); + self.increment_account_counter(); } + self.io .write_borsh(&Self::account_to_key(account_id), &amount); } - /// Get accounts counter for statistics - /// It represents total unique accounts. + /// Get total unique accounts number. It represents total unique accounts. pub fn get_accounts_counter(&self) -> u64 { self.io.read_u64(&Self::get_statistic_key()).unwrap_or(0) } + /// Balance of `nETH` (ETH on NEAR). + pub fn get_account_eth_balance(&self, account_id: &AccountId) -> Option { + self.io + .read_storage(&Self::account_to_key(account_id)) + .and_then(|s| NEP141Wei::try_from_slice(&s.to_vec()).ok()) + } + fn accounts_contains_key(&self, account_id: &AccountId) -> bool { self.io.storage_has_key(&Self::account_to_key(account_id)) } @@ -520,14 +517,7 @@ impl FungibleTokenOps { self.io.remove_storage(&Self::account_to_key(account_id)); } - /// Balance of `nETH` (ETH on NEAR token) - pub fn get_account_eth_balance(&self, account_id: &AccountId) -> Option { - self.io - .read_storage(&Self::account_to_key(account_id)) - .and_then(|s| NEP141Wei::try_from_slice(&s.to_vec()).ok()) - } - - /// Fungible token key + /// Fungible token key for account id. fn account_to_key(account_id: &AccountId) -> Vec { let mut key = storage::bytes_to_key( storage::KeyPrefix::EthConnector, @@ -537,15 +527,26 @@ impl FungibleTokenOps { key } - /// Key for store contract statistics data + /// Key for storing contract statistics data. fn get_statistic_key() -> Vec { storage::bytes_to_key( - crate::prelude::storage::KeyPrefix::EthConnector, + storage::KeyPrefix::EthConnector, &[u8::from( crate::prelude::EthConnectorStorageId::StatisticsAuroraAccountsCounter, )], ) } + + fn increment_account_counter(&mut self) { + let key = Self::get_statistic_key(); + let accounts_counter = self + .io + .read_u64(&key) + .unwrap_or(0) + .checked_add(1) + .expect(crate::errors::ERR_ACCOUNTS_COUNTER_OVERFLOW); + self.io.write_storage(&key, &accounts_counter.to_le_bytes()); + } } pub mod error { diff --git a/engine/src/proof.rs b/engine/src/proof.rs index 3331b9e85..85307d5cf 100644 --- a/engine/src/proof.rs +++ b/engine/src/proof.rs @@ -18,7 +18,7 @@ impl Proof { let mut data = self.log_index.try_to_vec().unwrap(); data.extend(self.receipt_index.try_to_vec().unwrap()); data.extend(self.header_data.clone()); - sdk::sha256(&data[..]) + sdk::sha256(&data) .0 .iter() .map(ToString::to_string) @@ -42,7 +42,7 @@ mod tests { fn test_proof_key_generates_successfully() { let recipient_address = Address::new(H160([22u8; 20])); let deposit_amount = Wei::new_u64(123_456_789); - let proof = self::create_proof(recipient_address, deposit_amount); + let proof = create_proof(recipient_address, deposit_amount); let expected_key = "1297721518512077871939115641114233180253108247225100248224214775219368216419218177247"; From be2890f3d68800377fbff12a3f1652e2be2035cf Mon Sep 17 00:00:00 2001 From: Oleksandr Anyshchenko Date: Mon, 5 Jun 2023 14:02:06 +0200 Subject: [PATCH 05/13] feat(precompiles): generic modexp algorithm (#770) ## Description The PR is alternative version of #769. ## Performance / NEAR gas cost considerations ## Testing ## How should this be reviewed ## Additional information --- Cargo.lock | 152 +++++++++--------- engine-modexp/src/lib.rs | 16 ++ engine-precompiles/src/lib.rs | 60 ++++--- engine-precompiles/src/modexp.rs | 21 +-- engine-standalone-storage/Cargo.toml | 1 + engine-standalone-storage/src/sync/mod.rs | 27 ++-- engine-tests/Cargo.toml | 1 + .../src/test_utils/standalone/mocks/mod.rs | 3 +- engine-tests/src/test_utils/standalone/mod.rs | 26 +-- .../src/tests/standalone/call_tracer.rs | 15 +- engine-tests/src/tests/standalone/sanity.rs | 3 +- engine-tests/src/tests/standalone/sync.rs | 21 +-- engine/Cargo.toml | 1 + engine/src/connector.rs | 5 +- engine/src/engine.rs | 81 +++++++--- engine/src/lib.rs | 14 +- 16 files changed, 269 insertions(+), 178 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b67afd829..fefaabe4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,6 +119,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -235,7 +241,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -246,7 +252,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -264,6 +270,7 @@ dependencies = [ name = "aurora-engine" version = "2.9.1" dependencies = [ + "aurora-engine-modexp", "aurora-engine-precompiles", "aurora-engine-sdk", "aurora-engine-test-doubles", @@ -318,7 +325,7 @@ name = "aurora-engine-sdk" version = "1.0.0" dependencies = [ "aurora-engine-types", - "base64 0.21.1", + "base64 0.21.2", "sha2 0.10.6", "sha3", ] @@ -339,6 +346,7 @@ name = "aurora-engine-tests" version = "1.0.0" dependencies = [ "aurora-engine", + "aurora-engine-modexp", "aurora-engine-precompiles", "aurora-engine-sdk", "aurora-engine-test-doubles", @@ -440,9 +448,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.1" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "bincode" @@ -757,13 +765,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "serde", "time 0.1.45", @@ -837,20 +845,20 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.0" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" +checksum = "b4ed2379f8603fa2b7509891660e802b88c70a79a6427a70abb5968054de2c28" dependencies = [ "clap_builder", - "clap_derive 4.3.0", + "clap_derive 4.3.1", "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.0" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" +checksum = "72394f3339a76daf211e57d4bcb374410f3965dcc606dd0e03738c7888766980" dependencies = [ "anstream", "anstyle", @@ -874,14 +882,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.0" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b" +checksum = "59e9ef9a08ee1c0e1f2e162121665ac45ac3783b0f897db7244ae75ad9a8f65b" dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -1234,7 +1242,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -1245,18 +1253,18 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" dependencies = [ "darling_core", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] name = "derive_arbitrary" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cdeb9ec472d588e539a818b2dee436825730da08ad0017c4b1a17676bdc8b7" +checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.18", ] [[package]] @@ -1382,6 +1390,7 @@ name = "engine-standalone-storage" version = "0.1.0" dependencies = [ "aurora-engine", + "aurora-engine-modexp", "aurora-engine-precompiles", "aurora-engine-sdk", "aurora-engine-transactions", @@ -1445,7 +1454,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -1756,7 +1765,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -1858,9 +1867,9 @@ checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "git2" -version = "0.17.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7905cdfe33d31a88bb2e8419ddd054451f5432d1da9eaf2ac7804ee1ea12d5" +checksum = "7b989d6a7ca95a362cf2cfc5ad688b3a467be1f87e480b8dad07fee8c79b0044" dependencies = [ "bitflags", "libc", @@ -2217,9 +2226,9 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", @@ -2294,7 +2303,7 @@ checksum = "b111244b70d4cf22aaaf8e0461ede19d623880f0f4779ee33dc35850a825bec3" dependencies = [ "lazy_static", "manifest-dir-macros", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -2326,9 +2335,9 @@ checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "libgit2-sys" -version = "0.15.1+1.6.4" +version = "0.15.2+1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4577bde8cdfc7d6a2a4bcb7b049598597de33ffd337276e9c7db6cd4a2cee7" +checksum = "a80df2e11fb4a61f4ba2ab42dbe7f74468da143f1a75c74e11dee7c813f694fa" dependencies = [ "cc", "libc", @@ -2471,12 +2480,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" [[package]] name = "loupe" @@ -2525,7 +2531,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -2621,14 +2627,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -2792,7 +2798,7 @@ source = "git+https://github.com/birchmd/nearcore.git?rev=71c9b3f4c62f1bff24982a dependencies = [ "actix", "atty", - "clap 4.3.0", + "clap 4.3.1", "near-crypto 0.0.0", "near-primitives-core 0.0.0", "once_cell", @@ -2969,7 +2975,7 @@ source = "git+https://github.com/birchmd/nearcore.git?rev=71c9b3f4c62f1bff24982a dependencies = [ "quote", "serde", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -2991,7 +2997,7 @@ dependencies = [ "fs2", "near-rpc-error-core 0.0.0", "serde", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -3564,9 +3570,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" [[package]] name = "oorandom" @@ -3588,9 +3594,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.87" +version = "0.9.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" +checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617" dependencies = [ "cc", "libc", @@ -3816,7 +3822,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -3885,7 +3891,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b7fa9f396f51dffd61546fd8573ee20592287996568e6175ceb0f8699ad75d" dependencies = [ - "base64 0.21.1", + "base64 0.21.2", "byteorder", "bytes", "fallible-iterator", @@ -3989,9 +3995,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" +checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" dependencies = [ "unicode-ident", ] @@ -4112,9 +4118,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] @@ -4265,9 +4271,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.2" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974" +checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" dependencies = [ "aho-corasick", "memchr", @@ -4611,7 +4617,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -4633,7 +4639,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -4842,9 +4848,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" dependencies = [ "proc-macro2", "quote", @@ -4949,7 +4955,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -5165,9 +5171,9 @@ checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" [[package]] name = "toml_edit" -version = "0.19.9" +version = "0.19.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f" +checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" dependencies = [ "indexmap", "toml_datetime", @@ -5281,7 +5287,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -5389,9 +5395,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "unicode-normalization" @@ -5546,7 +5552,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", "wasm-bindgen-shared", ] @@ -5568,7 +5574,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5796,22 +5802,22 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.105.0" +version = "0.107.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83be9e0b3f9570dc1979a33ae7b89d032c73211564232b99976553e5c155ec32" +checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" dependencies = [ "indexmap", - "url", + "semver 1.0.17", ] [[package]] name = "wasmprinter" -version = "0.2.57" +version = "0.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b0e5ed7a74a065637f0d7798ce5f29cadb064980d24b0c82af5200122fa0d8" +checksum = "cc960b30b84abca377768f3c62cff3a1c74db8c0f6759ed581827da0bd3a3fed" dependencies = [ "anyhow", - "wasmparser 0.105.0", + "wasmparser 0.107.0", ] [[package]] @@ -6223,7 +6229,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] diff --git a/engine-modexp/src/lib.rs b/engine-modexp/src/lib.rs index fbcfec2fc..6bd08fa21 100644 --- a/engine-modexp/src/lib.rs +++ b/engine-modexp/src/lib.rs @@ -9,6 +9,22 @@ mod mpnat; use maybe_std::Vec; +/// Trait providing the interface for the modexp function. +/// The implementation provided by this crate is `AuroraModExp` below, +/// but other users of Aurora Engine may wish to select a different implementation. +pub trait ModExpAlgorithm: 'static { + /// Computes `(base ^ exp) % modulus`, where all values are given as big-endian encoded bytes. + fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec; +} + +pub struct AuroraModExp; + +impl ModExpAlgorithm for AuroraModExp { + fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec { + modexp(base, exp, modulus) + } +} + /// Computes `(base ^ exp) % modulus`, where all values are given as big-endian /// encoded bytes. pub fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec { diff --git a/engine-precompiles/src/lib.rs b/engine-precompiles/src/lib.rs index 7b4b2fe1c..634084d67 100644 --- a/engine-precompiles/src/lib.rs +++ b/engine-precompiles/src/lib.rs @@ -35,6 +35,7 @@ use crate::prepaid_gas::PrepaidGas; use crate::random::RandomSeed; use crate::secp256k1::ECRecover; use crate::xcc::CrossContractCall; +use aurora_engine_modexp::ModExpAlgorithm; use aurora_engine_sdk::env::Env; use aurora_engine_sdk::io::IO; use aurora_engine_sdk::promise::ReadOnlyPromiseHandler; @@ -116,8 +117,8 @@ impl HardFork for Istanbul {} impl HardFork for Berlin {} pub struct Precompiles<'a, I, E, H> { - pub all_precompiles: prelude::BTreeMap>, - pub paused_precompiles: prelude::BTreeSet
, + pub all_precompiles: BTreeMap>, + pub paused_precompiles: BTreeSet
, } impl<'a, I, E, H> Precompiles<'a, I, E, H> { @@ -197,17 +198,20 @@ fn post_process( }) } -pub struct PrecompileConstructorContext<'a, I, E, H> { +pub struct PrecompileConstructorContext<'a, I, E, H, M> { pub current_account_id: AccountId, pub random_seed: H256, pub io: I, pub env: &'a E, pub promise_handler: H, + pub mod_exp_algorithm: prelude::PhantomData, } impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> Precompiles<'a, I, E, H> { #[allow(dead_code)] - pub fn new_homestead(ctx: PrecompileConstructorContext<'a, I, E, H>) -> Self { + pub fn new_homestead( + ctx: PrecompileConstructorContext<'a, I, E, H, M>, + ) -> Self { let addresses = vec![ ECRecover::ADDRESS, SHA256::ADDRESS, @@ -215,7 +219,7 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> Precompiles<'a, I, E, RandomSeed::ADDRESS, CurrentAccount::ADDRESS, ]; - let fun: prelude::Vec> = vec![ + let fun: Vec> = vec![ Box::new(ECRecover), Box::new(SHA256), Box::new(RIPEMD160), @@ -231,25 +235,27 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> Precompiles<'a, I, E, } #[allow(dead_code)] - pub fn new_byzantium(ctx: PrecompileConstructorContext<'a, I, E, H>) -> Self { + pub fn new_byzantium( + ctx: PrecompileConstructorContext<'a, I, E, H, M>, + ) -> Self { let addresses = vec![ ECRecover::ADDRESS, SHA256::ADDRESS, RIPEMD160::ADDRESS, Identity::ADDRESS, - ModExp::::ADDRESS, + ModExp::::ADDRESS, Bn256Add::::ADDRESS, Bn256Mul::::ADDRESS, Bn256Pair::::ADDRESS, RandomSeed::ADDRESS, CurrentAccount::ADDRESS, ]; - let fun: prelude::Vec> = vec![ + let fun: Vec> = vec![ Box::new(ECRecover), Box::new(SHA256), Box::new(RIPEMD160), Box::new(Identity), - Box::new(ModExp::::new()), + Box::new(ModExp::::new()), Box::new(Bn256Add::::new()), Box::new(Bn256Mul::::new()), Box::new(Bn256Pair::::new()), @@ -265,13 +271,15 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> Precompiles<'a, I, E, Self::with_generic_precompiles(map, ctx) } - pub fn new_istanbul(ctx: PrecompileConstructorContext<'a, I, E, H>) -> Self { + pub fn new_istanbul( + ctx: PrecompileConstructorContext<'a, I, E, H, M>, + ) -> Self { let addresses = vec![ ECRecover::ADDRESS, SHA256::ADDRESS, RIPEMD160::ADDRESS, Identity::ADDRESS, - ModExp::::ADDRESS, + ModExp::::ADDRESS, Bn256Add::::ADDRESS, Bn256Mul::::ADDRESS, Bn256Pair::::ADDRESS, @@ -279,12 +287,12 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> Precompiles<'a, I, E, RandomSeed::ADDRESS, CurrentAccount::ADDRESS, ]; - let fun: prelude::Vec> = vec![ + let fun: Vec> = vec![ Box::new(ECRecover), Box::new(SHA256), Box::new(RIPEMD160), Box::new(Identity), - Box::new(ModExp::::new()), + Box::new(ModExp::::new()), Box::new(Bn256Add::::new()), Box::new(Bn256Mul::::new()), Box::new(Bn256Pair::::new()), @@ -301,13 +309,15 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> Precompiles<'a, I, E, Self::with_generic_precompiles(map, ctx) } - pub fn new_berlin(ctx: PrecompileConstructorContext<'a, I, E, H>) -> Self { + pub fn new_berlin( + ctx: PrecompileConstructorContext<'a, I, E, H, M>, + ) -> Self { let addresses = vec![ ECRecover::ADDRESS, SHA256::ADDRESS, RIPEMD160::ADDRESS, Identity::ADDRESS, - ModExp::::ADDRESS, + ModExp::::ADDRESS, Bn256Add::::ADDRESS, Bn256Mul::::ADDRESS, Bn256Pair::::ADDRESS, @@ -315,12 +325,12 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> Precompiles<'a, I, E, RandomSeed::ADDRESS, CurrentAccount::ADDRESS, ]; - let fun: prelude::Vec> = vec![ + let fun: Vec> = vec![ Box::new(ECRecover), Box::new(SHA256), Box::new(RIPEMD160), Box::new(Identity), - Box::new(ModExp::::new()), + Box::new(ModExp::::new()), Box::new(Bn256Add::::new()), Box::new(Bn256Mul::::new()), Box::new(Bn256Pair::::new()), @@ -337,14 +347,16 @@ impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> Precompiles<'a, I, E, Self::with_generic_precompiles(map, ctx) } - pub fn new_london(ctx: PrecompileConstructorContext<'a, I, E, H>) -> Self { + pub fn new_london( + ctx: PrecompileConstructorContext<'a, I, E, H, M>, + ) -> Self { // no precompile changes in London HF Self::new_berlin(ctx) } - fn with_generic_precompiles( + fn with_generic_precompiles( mut generic_precompiles: BTreeMap>, - ctx: PrecompileConstructorContext<'a, I, E, H>, + ctx: PrecompileConstructorContext<'a, I, E, H, M>, ) -> Self { let near_exit = ExitToNear::new(ctx.current_account_id.clone(), ctx.io); let ethereum_exit = ExitToEthereum::new(ctx.current_account_id.clone(), ctx.io); @@ -396,10 +408,10 @@ pub enum AllPrecompiles<'a, I, E, H> { /// Note that 32 + 128 = 160 = 20 bytes (the length of an address). This function is used /// as a convenience for specifying the addresses of the various precompiles. #[must_use] -pub const fn make_address(x: u32, y: u128) -> prelude::types::Address { +pub const fn make_address(x: u32, y: u128) -> Address { let x_bytes = x.to_be_bytes(); let y_bytes = y.to_be_bytes(); - prelude::types::Address::new(H160([ + Address::new(H160([ x_bytes[0], x_bytes[1], x_bytes[2], @@ -423,10 +435,10 @@ pub const fn make_address(x: u32, y: u128) -> prelude::types::Address { ])) } -const fn make_h256(x: u128, y: u128) -> prelude::H256 { +const fn make_h256(x: u128, y: u128) -> H256 { let x_bytes = x.to_be_bytes(); let y_bytes = y.to_be_bytes(); - prelude::H256([ + H256([ x_bytes[0], x_bytes[1], x_bytes[2], diff --git a/engine-precompiles/src/modexp.rs b/engine-precompiles/src/modexp.rs index 47eb9dd1b..8bf40513f 100644 --- a/engine-precompiles/src/modexp.rs +++ b/engine-precompiles/src/modexp.rs @@ -3,22 +3,23 @@ use crate::prelude::{Cow, PhantomData, Vec, U256}; use crate::{ utils, Berlin, Byzantium, EvmPrecompileResult, HardFork, Precompile, PrecompileOutput, }; +use aurora_engine_modexp::{AuroraModExp, ModExpAlgorithm}; use evm::{Context, ExitError}; use num::{Integer, Zero}; #[derive(Default)] -pub struct ModExp(PhantomData); +pub struct ModExp(PhantomData, PhantomData); -impl ModExp { +impl ModExp { pub const ADDRESS: Address = super::make_address(0, 5); #[must_use] pub fn new() -> Self { - Self(PhantomData::default()) + Self(PhantomData::default(), PhantomData::default()) } } -impl ModExp { +impl ModExp { // Note: the output of this function is bounded by 2^67 fn calc_iter_count(exp_len: u64, base_len: u64, bytes: &[u8]) -> Result { let start = usize::try_from(base_len).map_err(utils::err_usize_conv)?; @@ -61,7 +62,7 @@ impl ModExp { } else { let base = parse_input_range_to_slice(input, base_start, base_len); let exponent = parse_input_range_to_slice(input, exp_start, exp_len); - aurora_engine_modexp::modexp(&base, &exponent, &modulus) + M::modexp(&base, &exponent, &modulus) }; // The result must be the same length as the input modulus. @@ -78,9 +79,9 @@ impl ModExp { } } -impl ModExp { +impl ModExp { const MIN_GAS: EthGas = EthGas::new(0); - // ouput of this function is bounded by 2^128 + // output of this function is bounded by 2^128 fn mul_complexity(x: u64) -> U256 { if x <= 64 { U256::from(x * x) @@ -95,7 +96,7 @@ impl ModExp { } } -impl Precompile for ModExp { +impl Precompile for ModExp { fn required_gas(input: &[u8]) -> Result { let (base_len, exp_len, mod_len) = parse_lengths(input); if base_len == 0 && mod_len == 0 { @@ -131,7 +132,7 @@ impl Precompile for ModExp { } } -impl ModExp { +impl ModExp { const MIN_GAS: EthGas = EthGas::new(200); // output bounded by 2^122 fn mul_complexity(base_len: u64, mod_len: u64) -> U256 { @@ -141,7 +142,7 @@ impl ModExp { } } -impl Precompile for ModExp { +impl Precompile for ModExp { fn required_gas(input: &[u8]) -> Result { let (base_len, exp_len, mod_len) = parse_lengths(input); if base_len == 0 && mod_len == 0 { diff --git a/engine-standalone-storage/Cargo.toml b/engine-standalone-storage/Cargo.toml index a8ffb1575..912bc54f2 100644 --- a/engine-standalone-storage/Cargo.toml +++ b/engine-standalone-storage/Cargo.toml @@ -16,6 +16,7 @@ crate-type = ["lib"] [dependencies] aurora-engine = { path = "../engine", default-features = false, features = ["std"] } aurora-engine-types = { path = "../engine-types", default-features = false, features = ["std"] } +aurora-engine-modexp = { path = "../engine-modexp", default-features = false, features = ["std"] } aurora-engine-sdk = { path = "../engine-sdk", default-features = false, features = ["std"] } aurora-engine-transactions = { path = "../engine-transactions", default-features = false, features = ["std"] } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false, features = ["std"] } diff --git a/engine-standalone-storage/src/sync/mod.rs b/engine-standalone-storage/src/sync/mod.rs index cd3775ce3..af69ed29b 100644 --- a/engine-standalone-storage/src/sync/mod.rs +++ b/engine-standalone-storage/src/sync/mod.rs @@ -3,6 +3,7 @@ use aurora_engine::pausables::{ EnginePrecompilesPauser, PausedPrecompilesManager, PrecompileFlags, }; use aurora_engine::{connector, engine, parameters::SubmitResult, state, xcc}; +use aurora_engine_modexp::ModExpAlgorithm; use aurora_engine_sdk::env::{self, Env, DEFAULT_PREPAID_GAS}; use aurora_engine_types::{ account_id::AccountId, @@ -17,7 +18,7 @@ use crate::engine_state::EngineStateAccess; use crate::{BlockMetadata, Diff, Storage}; use types::{Message, TransactionKind, TransactionMessage}; -pub fn consume_message( +pub fn consume_message( storage: &mut Storage, message: Message, ) -> Result { @@ -46,7 +47,7 @@ pub fn consume_message( let (tx_hash, diff, result) = storage .with_engine_access(block_height, transaction_position, &[], |io| { - execute_transaction( + execute_transaction::( transaction_message.as_ref(), block_height, &block_metadata, @@ -72,7 +73,7 @@ pub fn consume_message( } } -pub fn execute_transaction_message( +pub fn execute_transaction_message( storage: &Storage, transaction_message: TransactionMessage, ) -> Result { @@ -82,7 +83,7 @@ pub fn execute_transaction_message( let block_metadata = storage.get_block_metadata(block_hash)?; let engine_account_id = storage.get_engine_account_id()?; let result = storage.with_engine_access(block_height, transaction_position, &[], |io| { - execute_transaction( + execute_transaction::( &transaction_message, block_height, &block_metadata, @@ -100,7 +101,7 @@ pub fn execute_transaction_message( Ok(outcome) } -fn execute_transaction<'db>( +fn execute_transaction<'db, M: ModExpAlgorithm + 'static>( transaction_message: &TransactionMessage, block_height: u64, block_metadata: &BlockMetadata, @@ -143,7 +144,7 @@ fn execute_transaction<'db>( }; let result = state::get_state(&io) .map(|engine_state| { - let submit_result = engine::submit( + let submit_result = engine::submit_with_alt_modexp::<_, _, _, M>( io, &env, &args, @@ -165,7 +166,7 @@ fn execute_transaction<'db>( let tx_hash = aurora_engine_sdk::keccak(&args.tx_data); let result = state::get_state(&io) .map(|engine_state| { - let submit_result = engine::submit( + let submit_result = engine::submit_with_alt_modexp::<_, _, _, M>( io, &env, args, @@ -181,7 +182,7 @@ fn execute_transaction<'db>( (tx_hash, result) } other => { - let result = non_submit_execute( + let result = non_submit_execute::( other, io, env, @@ -201,7 +202,7 @@ fn execute_transaction<'db>( /// The `submit` transaction kind is special because it is the only one where the transaction hash /// differs from the NEAR receipt hash. #[allow(clippy::too_many_lines)] -fn non_submit_execute<'db>( +fn non_submit_execute<'db, M: ModExpAlgorithm + 'static>( transaction: &TransactionKind, mut io: EngineStateAccess<'db, 'db, 'db>, env: env::Fixed, @@ -212,7 +213,7 @@ fn non_submit_execute<'db>( TransactionKind::Call(args) => { // We can ignore promises in the standalone engine (see above) let mut handler = crate::promise::NoScheduler { promise_data }; - let mut engine = + let mut engine: engine::Engine<_, _, M> = engine::Engine::new(relayer_address, env.current_account_id(), io, &env)?; let result = engine.call_with_args(args.clone(), &mut handler); @@ -223,7 +224,7 @@ fn non_submit_execute<'db>( TransactionKind::Deploy(input) => { // We can ignore promises in the standalone engine (see above) let mut handler = crate::promise::NoScheduler { promise_data }; - let mut engine = + let mut engine: engine::Engine<_, _, M> = engine::Engine::new(relayer_address, env.current_account_id(), io, &env)?; let result = engine.deploy_code_with_input(input.clone(), &mut handler); @@ -242,7 +243,7 @@ fn non_submit_execute<'db>( TransactionKind::FtOnTransfer(args) => { // No promises can be created by `ft_on_transfer` let mut handler = crate::promise::NoScheduler { promise_data }; - let mut engine = + let mut engine: engine::Engine<_, _, M> = engine::Engine::new(relayer_address, env.current_account_id(), io, &env)?; if env.predecessor_account_id == env.current_account_id { @@ -353,7 +354,7 @@ fn non_submit_execute<'db>( } TransactionKind::RegisterRelayer(evm_address) => { - let mut engine = + let mut engine: engine::Engine<_, _, M> = engine::Engine::new(relayer_address, env.current_account_id(), io, &env)?; engine.register_relayer(env.predecessor_account_id.as_bytes(), *evm_address); diff --git a/engine-tests/Cargo.toml b/engine-tests/Cargo.toml index 9516891f2..266c7df60 100644 --- a/engine-tests/Cargo.toml +++ b/engine-tests/Cargo.toml @@ -18,6 +18,7 @@ autobenches = false aurora-engine = { path = "../engine", default-features = false, features = ["std", "tracing", "impl-serde"] } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false, features = ["std"] } aurora-engine-sdk = { path = "../engine-sdk", default-features = false, features = ["std"] } +aurora-engine-modexp = { path = "../engine-modexp", default-features = false, features = ["std"] } aurora-engine-test-doubles = { path = "../engine-test-doubles", default-features = false } aurora-engine-transactions = { path = "../engine-transactions", default-features = false, features = ["std", "impl-serde"] } aurora-engine-types = { path = "../engine-types", default-features = false, features = ["std", "impl-serde"] } diff --git a/engine-tests/src/test_utils/standalone/mocks/mod.rs b/engine-tests/src/test_utils/standalone/mocks/mod.rs index 6ea5caf90..1403737e8 100644 --- a/engine-tests/src/test_utils/standalone/mocks/mod.rs +++ b/engine-tests/src/test_utils/standalone/mocks/mod.rs @@ -83,7 +83,8 @@ pub fn mint_evm_account( use evm::backend::ApplyBackend; let aurora_account_id = env.current_account_id(); - let mut engine = engine::Engine::new(address, aurora_account_id.clone(), io, env).unwrap(); + let mut engine: engine::Engine<_, _> = + engine::Engine::new(address, aurora_account_id.clone(), io, env).unwrap(); let state_change = evm::backend::Apply::Modify { address: address.raw(), basic: evm::backend::Basic { diff --git a/engine-tests/src/test_utils/standalone/mod.rs b/engine-tests/src/test_utils/standalone/mod.rs index be6541968..886709312 100644 --- a/engine-tests/src/test_utils/standalone/mod.rs +++ b/engine-tests/src/test_utils/standalone/mod.rs @@ -3,6 +3,7 @@ use aurora_engine::parameters::{ CallArgs, DeployErc20TokenArgs, PausePrecompilesCallArgs, SetOwnerArgs, SetUpgradeDelayBlocksArgs, SubmitArgs, SubmitResult, TransactionStatus, }; +use aurora_engine_modexp::AuroraModExp; use aurora_engine_sdk::env::{self, Env}; use aurora_engine_transactions::legacy::{LegacyEthSignedTransaction, TransactionLegacy}; use aurora_engine_types::types::{Address, NearGas, PromiseResult, Wei}; @@ -170,7 +171,7 @@ impl StandaloneRunner { tx_msg.position = transaction_position; tx_msg.transaction = TransactionKind::Submit(transaction_bytes.as_slice().try_into().unwrap()); - let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); + let outcome = sync::execute_transaction_message::(storage, tx_msg).unwrap(); match outcome.maybe_result.as_ref().unwrap().as_ref().unwrap() { sync::TransactionExecutionResult::Submit(result) => { @@ -218,7 +219,8 @@ impl StandaloneRunner { Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); tx_msg.transaction = TransactionKind::SubmitWithArgs(submit_args); - let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); + let outcome = + sync::execute_transaction_message::(storage, tx_msg).unwrap(); self.cumulative_diff.append(outcome.diff.clone()); storage::commit(storage, &outcome); @@ -230,7 +232,8 @@ impl StandaloneRunner { Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); tx_msg.transaction = TransactionKind::Call(call_args); - let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); + let outcome = + sync::execute_transaction_message::(storage, tx_msg).unwrap(); self.cumulative_diff.append(outcome.diff.clone()); storage::commit(storage, &outcome); @@ -242,7 +245,8 @@ impl StandaloneRunner { Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); tx_msg.transaction = TransactionKind::DeployErc20(deploy_args); - let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); + let outcome = + sync::execute_transaction_message::(storage, tx_msg).unwrap(); self.cumulative_diff.append(outcome.diff.clone()); storage::commit(storage, &outcome); @@ -263,7 +267,8 @@ impl StandaloneRunner { Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); tx_msg.transaction = TransactionKind::ResumePrecompiles(call_args); - let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); + let outcome = + sync::execute_transaction_message::(storage, tx_msg).unwrap(); self.cumulative_diff.append(outcome.diff.clone()); storage::commit(storage, &outcome); @@ -282,7 +287,8 @@ impl StandaloneRunner { Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); tx_msg.transaction = TransactionKind::PausePrecompiles(call_args); - let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); + let outcome = + sync::execute_transaction_message::(storage, tx_msg).unwrap(); self.cumulative_diff.append(outcome.diff.clone()); storage::commit(storage, &outcome); @@ -301,7 +307,8 @@ impl StandaloneRunner { Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); tx_msg.transaction = TransactionKind::SetOwner(call_args); - let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); + let outcome = + sync::execute_transaction_message::(storage, tx_msg).unwrap(); self.cumulative_diff.append(outcome.diff.clone()); storage::commit(storage, &outcome); @@ -320,7 +327,8 @@ impl StandaloneRunner { Self::template_tx_msg(storage, &env, 0, transaction_hash, promise_results); tx_msg.transaction = TransactionKind::SetUpgradeDelayBlocks(call_args); - let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); + let outcome = + sync::execute_transaction_message::(storage, tx_msg).unwrap(); self.cumulative_diff.append(outcome.diff.clone()); storage::commit(storage, &outcome); @@ -420,7 +428,7 @@ impl StandaloneRunner { ); tx_msg.transaction = TransactionKind::Submit(transaction_bytes.try_into().unwrap()); - let outcome = sync::execute_transaction_message(storage, tx_msg).unwrap(); + let outcome = sync::execute_transaction_message::(storage, tx_msg).unwrap(); cumulative_diff.append(outcome.diff.clone()); storage::commit(storage, &outcome); diff --git a/engine-tests/src/tests/standalone/call_tracer.rs b/engine-tests/src/tests/standalone/call_tracer.rs index 3439cc876..00a19761e 100644 --- a/engine-tests/src/tests/standalone/call_tracer.rs +++ b/engine-tests/src/tests/standalone/call_tracer.rs @@ -1,5 +1,6 @@ use crate::prelude::H256; use crate::test_utils::{self, standalone}; +use aurora_engine_modexp::AuroraModExp; use aurora_engine_types::{ parameters::{CrossContractCallArgs, PromiseArgs, PromiseCreateArgs}, storage, @@ -245,6 +246,7 @@ fn test_trace_contract_with_precompile_sub_call() { runner.close(); } +#[allow(clippy::too_many_lines)] #[test] fn test_trace_precompiles_with_subcalls() { // The XCC precompile does internal sub-calls. We will trace an XCC call. @@ -289,7 +291,7 @@ fn test_trace_precompiles_with_subcalls() { nep141: "wrap.near".parse().unwrap(), }, ); - let mut outcome = sync::execute_transaction_message(storage, tx).unwrap(); + let mut outcome = sync::execute_transaction_message::(storage, tx).unwrap(); let key = storage::bytes_to_key(storage::KeyPrefix::Nep141Erc20Map, b"wrap.near"); outcome.diff.modify(key, wnear_address.as_bytes().to_vec()); let key = @@ -312,8 +314,9 @@ fn test_trace_precompiles_with_subcalls() { tx.transaction = sync::types::TransactionKind::FactoryUpdate(xcc_router_bytes); tx }; - let outcome = sync::execute_transaction_message(&runner.storage, factory_update).unwrap(); - test_utils::standalone::storage::commit(&mut runner.storage, &outcome); + let outcome = + sync::execute_transaction_message::(&runner.storage, factory_update).unwrap(); + standalone::storage::commit(&mut runner.storage, &outcome); let set_wnear_address = { runner.env.block_height += 1; let storage = &mut runner.storage; @@ -324,8 +327,10 @@ fn test_trace_precompiles_with_subcalls() { tx.transaction = sync::types::TransactionKind::FactorySetWNearAddress(wnear_address); tx }; - let outcome = sync::execute_transaction_message(&runner.storage, set_wnear_address).unwrap(); - test_utils::standalone::storage::commit(&mut runner.storage, &outcome); + let outcome = + sync::execute_transaction_message::(&runner.storage, set_wnear_address) + .unwrap(); + standalone::storage::commit(&mut runner.storage, &outcome); // User calls XCC precompile let promise = PromiseCreateArgs { diff --git a/engine-tests/src/tests/standalone/sanity.rs b/engine-tests/src/tests/standalone/sanity.rs index 57a4b0d9a..55d93b504 100644 --- a/engine-tests/src/tests/standalone/sanity.rs +++ b/engine-tests/src/tests/standalone/sanity.rs @@ -34,7 +34,8 @@ fn test_deploy_code() { prepaid_gas: DEFAULT_PREPAID_GAS, }; let mut handler = PromiseTracker::default(); - let mut engine = engine::Engine::new_with_state(state, origin, owner_id, io, &env); + let mut engine: engine::Engine<_, _> = + engine::Engine::new_with_state(state, origin, owner_id, io, &env); let code_to_deploy = vec![1, 2, 3, 4, 5, 6]; let result = engine.deploy_code( origin, diff --git a/engine-tests/src/tests/standalone/sync.rs b/engine-tests/src/tests/standalone/sync.rs index 5b4b57744..595ed2f53 100644 --- a/engine-tests/src/tests/standalone/sync.rs +++ b/engine-tests/src/tests/standalone/sync.rs @@ -1,4 +1,5 @@ use aurora_engine::deposit_event::TokenMessageData; +use aurora_engine_modexp::AuroraModExp; use aurora_engine_sdk::env::{Env, Timestamp}; use aurora_engine_types::types::{Address, Balance, Fee, NEP141Wei, Wei}; use aurora_engine_types::{account_id::AccountId, H160, H256, U256}; @@ -56,7 +57,7 @@ fn test_consume_deposit_message() { promise_data: Vec::new(), }; - let outcome = sync::consume_message( + let outcome = sync::consume_message::( &mut runner.storage, sync::types::Message::Transaction(Box::new(transaction_message)), ) @@ -88,7 +89,7 @@ fn test_consume_deposit_message() { promise_data: Vec::new(), }; - let outcome = sync::consume_message( + let outcome = sync::consume_message::( &mut runner.storage, sync::types::Message::Transaction(Box::new(transaction_message)), ) @@ -118,7 +119,7 @@ fn test_consume_deposit_message() { promise_data: Vec::new(), }; - sync::consume_message( + sync::consume_message::( &mut runner.storage, sync::types::Message::Transaction(Box::new(transaction_message)), ) @@ -148,7 +149,7 @@ fn test_consume_deploy_message() { promise_data: Vec::new(), }; - sync::consume_message( + sync::consume_message::( &mut runner.storage, sync::types::Message::Transaction(Box::new(transaction_message)), ) @@ -201,7 +202,7 @@ fn test_consume_deploy_erc20_message() { }; // Deploy ERC-20 (this would be the flow for bridging a new NEP-141 to Aurora) - sync::consume_message( + sync::consume_message::( &mut runner.storage, sync::types::Message::Transaction(Box::new(transaction_message)), ) @@ -239,7 +240,7 @@ fn test_consume_deploy_erc20_message() { }; // Mint new tokens (via ft_on_transfer flow, same as the bridge) - sync::consume_message( + sync::consume_message::( &mut runner.storage, sync::types::Message::Transaction(Box::new(transaction_message)), ) @@ -295,7 +296,7 @@ fn test_consume_ft_on_transfer_message() { promise_data: Vec::new(), }; - sync::consume_message( + sync::consume_message::( &mut runner.storage, sync::types::Message::Transaction(Box::new(transaction_message)), ) @@ -339,7 +340,7 @@ fn test_consume_call_message() { promise_data: Vec::new(), }; - sync::consume_message( + sync::consume_message::( &mut runner.storage, sync::types::Message::Transaction(Box::new(transaction_message)), ) @@ -389,7 +390,7 @@ fn test_consume_submit_message() { promise_data: Vec::new(), }; - sync::consume_message( + sync::consume_message::( &mut runner.storage, sync::types::Message::Transaction(Box::new(transaction_message)), ) @@ -479,7 +480,7 @@ fn initialize() -> (StandaloneRunner, sync::types::BlockMessage) { runner.init_evm(); let block_message = sample_block(); - sync::consume_message( + sync::consume_message::( &mut runner.storage, sync::types::Message::Block(block_message.clone()), ) diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 11d03a452..41f09a551 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -18,6 +18,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] aurora-engine-types = { path = "../engine-types", default-features = false } aurora-engine-sdk = { path = "../engine-sdk", default-features = false } +aurora-engine-modexp = { path = "../engine-modexp", default-features = false } aurora-engine-precompiles = { path = "../engine-precompiles", default-features = false } aurora-engine-transactions = { path = "../engine-transactions", default-features = false } bitflags = { version = "1.3", default-features = false } diff --git a/engine/src/connector.rs b/engine/src/connector.rs index 4d70ae9a9..f8b269a16 100644 --- a/engine/src/connector.rs +++ b/engine/src/connector.rs @@ -15,6 +15,7 @@ use crate::prelude::{ }; use crate::prelude::{PromiseBatchAction, PromiseCreateArgs, PromiseWithCallbackArgs}; use crate::proof::Proof; +use aurora_engine_modexp::ModExpAlgorithm; use aurora_engine_sdk::env::Env; use aurora_engine_sdk::io::{StorageIntermediate, IO}; use aurora_engine_types::borsh; @@ -576,9 +577,9 @@ impl EthConnectorContract { } /// `ft_on_transfer` callback function. - pub fn ft_on_transfer( + pub fn ft_on_transfer( &mut self, - engine: &Engine, + engine: &Engine, args: &NEP141FtOnTransferArgs, ) -> Result<(), error::FtTransferCallError> { sdk::log!("Call ft_on_transfer"); diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 66d738ec7..73edd6823 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -1,6 +1,7 @@ use crate::parameters::{ CallArgs, NEP141FtOnTransferArgs, ResultLog, SubmitArgs, SubmitResult, ViewCallArgs, }; +use aurora_engine_types::PhantomData; use core::mem; use evm::backend::{Apply, ApplyBackend, Backend, Basic, Log}; use evm::executor; @@ -30,6 +31,7 @@ use crate::prelude::{ Yocto, ERC20_MINT_SELECTOR, H160, H256, U256, }; use crate::state::EngineState; +use aurora_engine_modexp::{AuroraModExp, ModExpAlgorithm}; use aurora_engine_precompiles::PrecompileConstructorContext; use core::cell::RefCell; use core::iter::once; @@ -347,13 +349,14 @@ impl<'env, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> StackExecutorParams< } } - fn make_executor<'a>( + #[allow(clippy::type_complexity)] + fn make_executor<'a, M: ModExpAlgorithm>( &'a self, - engine: &'a Engine<'env, I, E>, + engine: &'a Engine<'env, I, E, M>, ) -> executor::stack::StackExecutor< 'static, 'a, - executor::stack::MemoryStackState>, + executor::stack::MemoryStackState>, Precompiles<'env, I, E, H>, > { let metadata = executor::stack::StackSubstateMetadata::new(self.gas_limit, CONFIG); @@ -369,7 +372,7 @@ pub struct GasPaymentResult { pub priority_fee_per_gas: U256, } -pub struct Engine<'env, I: IO, E: Env> { +pub struct Engine<'env, I: IO, E: Env, M = AuroraModExp> { state: EngineState, origin: Address, gas_price: U256, @@ -380,11 +383,12 @@ pub struct Engine<'env, I: IO, E: Env> { account_info_cache: RefCell>, contract_code_cache: RefCell>>, contract_storage_cache: RefCell>, + modexp_algorithm: PhantomData, } pub(crate) const CONFIG: &Config = &Config::london(); -impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { +impl<'env, I: IO + Copy, E: Env, M: ModExpAlgorithm> Engine<'env, I, E, M> { pub fn new( origin: Address, current_account_id: AccountId, @@ -413,6 +417,7 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { account_info_cache: RefCell::new(FullCache::default()), contract_code_cache: RefCell::new(FullCache::default()), contract_storage_cache: RefCell::new(FullCache::default()), + modexp_algorithm: PhantomData::default(), } } @@ -790,6 +795,7 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { io, env, promise_handler: ro_promise_handler, + mod_exp_algorithm: self.modexp_algorithm, }); Self::apply_pause_flags_to_precompiles(precompiles, pause_flags) @@ -812,6 +818,31 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { } pub fn submit( + io: I, + env: &E, + args: &SubmitArgs, + state: EngineState, + current_account_id: AccountId, + relayer_address: Address, + handler: &mut P, +) -> EngineResult { + submit_with_alt_modexp::<_, _, _, AuroraModExp>( + io, + env, + args, + state, + current_account_id, + relayer_address, + handler, + ) +} + +pub fn submit_with_alt_modexp< + I: IO + Copy, + E: Env, + P: PromiseHandler, + M: ModExpAlgorithm + 'static, +>( mut io: I, env: &E, args: &SubmitArgs, @@ -859,7 +890,7 @@ pub fn submit( check_nonce(&io, &sender, &transaction.nonce)?; // Check intrinsic gas is covered by transaction gas limit - match transaction.intrinsic_gas(crate::engine::CONFIG) { + match transaction.intrinsic_gas(CONFIG) { Err(_e) => { return Err(EngineErrorKind::GasOverflow.into()); } @@ -874,7 +905,8 @@ pub fn submit( return Err(EngineErrorKind::MaxPriorityGasFeeTooLarge.into()); } - let mut engine = Engine::new_with_state(state, sender, current_account_id, io, env); + let mut engine: Engine<_, _, M> = + Engine::new_with_state(state, sender, current_account_id, io, env); let prepaid_amount = match engine.charge_gas(&sender, &transaction, args.max_gas_price.map(Into::into)) { Ok(gas_result) => gas_result, @@ -958,7 +990,7 @@ pub fn refund_on_error( if let Some(erc20_address) = args.erc20_address { // ERC-20 exit; re-mint burned tokens let erc20_admin_address = current_address(¤t_account_id); - let mut engine = + let mut engine: Engine<_, _> = Engine::new_with_state(state, erc20_admin_address, current_account_id, io, env); let erc20_address = erc20_address; let refund_address = args.recipient_address; @@ -976,8 +1008,9 @@ pub fn refund_on_error( ) } else { // ETH exit; transfer ETH back from precompile address - let exit_address = aurora_engine_precompiles::native::exit_to_near::ADDRESS; - let mut engine = Engine::new_with_state(state, exit_address, current_account_id, io, env); + let exit_address = exit_to_near::ADDRESS; + let mut engine: Engine<_, _> = + Engine::new_with_state(state, exit_address, current_account_id, io, env); let refund_address = args.recipient_address; let amount = Wei::new(U256::from_big_endian(&args.amount)); engine.call( @@ -1104,7 +1137,7 @@ pub fn deploy_erc20_token( ) -> Result { let current_account_id = env.current_account_id(); let input = setup_deploy_erc20_input(¤t_account_id); - let mut engine = Engine::new( + let mut engine: Engine<_, _> = Engine::new( aurora_engine_sdk::types::near_account_to_evm_address( env.predecessor_account_id().as_bytes(), ), @@ -1427,7 +1460,7 @@ unsafe fn schedule_promise_callback( handler.promise_attach_callback(base_id, promise) } -impl<'env, I: IO + Copy, E: Env> evm::backend::Backend for Engine<'env, I, E> { +impl<'env, I: IO + Copy, E: Env, M: ModExpAlgorithm> Backend for Engine<'env, I, E, M> { /// Returns the "effective" gas price (as defined by EIP-1559) fn gas_price(&self) -> U256 { self.gas_price @@ -1594,7 +1627,7 @@ impl<'env, I: IO + Copy, E: Env> evm::backend::Backend for Engine<'env, I, E> { } } -impl<'env, J: IO + Copy, E: Env> ApplyBackend for Engine<'env, J, E> { +impl<'env, J: IO + Copy, E: Env, M: ModExpAlgorithm> ApplyBackend for Engine<'env, J, E, M> { fn apply(&mut self, values: A, _logs: L, delete_empty: bool) where A: IntoIterator>, @@ -1738,7 +1771,7 @@ mod tests { let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); - let engine = + let engine: Engine<_, _> = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); let contract = make_address(1, 1); @@ -1763,7 +1796,7 @@ mod tests { let env = Fixed::default(); let storage = RefCell::new(Storage::default()); let io = StoragePointer(&storage); - let mut engine = + let mut engine: Engine<_, _> = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); let input = vec![]; @@ -1789,7 +1822,7 @@ mod tests { let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); - let mut engine = + let mut engine: Engine<_, _> = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); let input = Vec::::new(); @@ -1819,7 +1852,7 @@ mod tests { let env = Fixed::default(); let storage = RefCell::new(Storage::default()); let io = StoragePointer(&storage); - let mut engine = + let mut engine: Engine<_, _> = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); let input = Vec::::new(); @@ -1849,7 +1882,7 @@ mod tests { let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); - let mut engine = + let mut engine: Engine<_, _> = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); let gas_limit = u64::MAX; @@ -1877,7 +1910,7 @@ mod tests { let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); - let mut engine = + let mut engine: Engine<_, _> = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); let input = Vec::::new(); @@ -1903,7 +1936,7 @@ mod tests { let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); - let mut engine = + let mut engine: Engine<_, _> = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); let account_id = AccountId::new("relayer").unwrap(); @@ -1922,7 +1955,7 @@ mod tests { let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); set_balance(&mut io, &origin, &Wei::new_u64(22000)); - let mut engine = Engine::new_with_state( + let mut engine: Engine<_, _> = Engine::new_with_state( EngineState::default(), origin, current_account_id.clone(), @@ -1982,7 +2015,7 @@ mod tests { let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); add_balance(&mut io, &origin, Wei::new_u64(22000)).unwrap(); - let mut engine = + let mut engine: Engine<_, _> = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); let transaction = NormalizedEthTransaction { @@ -2072,7 +2105,7 @@ mod tests { let env = Fixed::default(); let storage = RefCell::new(Storage::default()); let mut io = StoragePointer(&storage); - let engine = + let engine: Engine<_, _> = Engine::new_with_state(EngineState::default(), origin, current_account_id, io, &env); let expected_value = H256::from_low_u64_le(64); @@ -2093,7 +2126,7 @@ mod tests { let mut io = StoragePointer(&storage); let expected_state = EngineState::default(); state::set_state(&mut io, &expected_state).unwrap(); - let engine = Engine::new(origin, current_account_id, io, &env).unwrap(); + let engine: Engine<_, _> = Engine::new(origin, current_account_id, io, &env).unwrap(); let actual_state = engine.state; assert_eq!(expected_state, actual_state); diff --git a/engine/src/lib.rs b/engine/src/lib.rs index 93570141f..da4935da8 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -293,7 +293,7 @@ mod contract { let io = Runtime; let input = io.read_input().to_vec(); let current_account_id = io.current_account_id(); - let mut engine = Engine::new( + let mut engine: Engine<_, _> = Engine::new( predecessor_address(&io.predecessor_account_id()), current_account_id, io, @@ -326,7 +326,7 @@ mod contract { check_promise.sdk_unwrap(); } - let mut engine = Engine::new( + let mut engine: Engine<_, _> = Engine::new( predecessor_address(&predecessor_account_id), current_account_id, io, @@ -398,7 +398,7 @@ mod contract { let current_account_id = io.current_account_id(); let predecessor_account_id = io.predecessor_account_id(); - let mut engine = Engine::new( + let mut engine: Engine<_, _> = Engine::new( predecessor_address(&predecessor_account_id), current_account_id, io, @@ -478,7 +478,7 @@ mod contract { let io = Runtime; let current_account_id = io.current_account_id(); let predecessor_account_id = io.predecessor_account_id(); - let mut engine = Engine::new( + let mut engine: Engine<_, _> = Engine::new( predecessor_address(&predecessor_account_id), current_account_id.clone(), io, @@ -561,7 +561,8 @@ mod contract { let env = ViewEnv; let args: ViewCallArgs = io.read_input_borsh().sdk_unwrap(); let current_account_id = io.current_account_id(); - let engine = Engine::new(args.sender, current_account_id, io, &env).sdk_unwrap(); + let engine: Engine<_, _> = + Engine::new(args.sender, current_account_id, io, &env).sdk_unwrap(); let result = Engine::view_with_args(&engine, args).sdk_unwrap(); io.return_output(&result.try_to_vec().sdk_expect(errors::ERR_SERIALIZE)); } @@ -1026,7 +1027,8 @@ mod contract { let nonce = U256::from(args.1); let balance = NEP141Wei::new(u128::from(args.2)); let current_account_id = io.current_account_id(); - let mut engine = Engine::new(address, current_account_id, io, &io).sdk_unwrap(); + let mut engine: Engine<_, _> = + Engine::new(address, current_account_id, io, &io).sdk_unwrap(); let state_change = evm::backend::Apply::Modify { address: address.raw(), basic: evm::backend::Basic { From 9e2ecb2b290266d1c820588583beb898ef61766f Mon Sep 17 00:00:00 2001 From: "Joshua J. Bouw" Date: Tue, 6 Jun 2023 23:05:08 +0400 Subject: [PATCH 06/13] chore(github): remove hskang9 from CODEOWNERS (#768) ## Description hskang9 is no longer part of the company, so removing him as one of the listed code owners. For now, I'll take ownership over tests libraries and in the future, may pass on ownership to another. --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4ad0f797a..1abaa359a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,6 +4,6 @@ /engine-sdk/ @aleksuss /engine-standalone-storage/ @RomanHodulak /engine-standalone-tracing/ @RomanHodulak -/engine-test-doubles/ @hskang9 -/engine-tests/ @hskang9 +/engine-test-doubles/ @joshuajbouw +/engine-tests/ @joshuajbouw /engine-transactions/ @aleksuss From 8dff39ad99fd5028a758ffd9b93b9e41c31f11d5 Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Thu, 8 Jun 2023 09:00:42 -0400 Subject: [PATCH 07/13] Fix(modexp): properly handle the case where the exponent is zero (#771) ## Description We need to specially handle the case where the exponent is zero because the main code does not do this correctly. Note: EVM treats 0^0 as equal to 1. ## Testing New test for this case. --- engine-modexp/src/mpnat.rs | 4 ++++ engine-tests/src/tests/modexp.rs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/engine-modexp/src/mpnat.rs b/engine-modexp/src/mpnat.rs index 81b6780b4..312b106aa 100644 --- a/engine-modexp/src/mpnat.rs +++ b/engine-modexp/src/mpnat.rs @@ -88,6 +88,10 @@ impl MPNat { /// Computes `self ^ exp mod modulus`. `exp` must be given as big-endian bytes. pub fn modpow(&mut self, exp: &[u8], modulus: &Self) -> Self { + if exp.iter().all(|x| x == &0) { + return Self { digits: vec![1] }; + } + if exp.len() <= core::mem::size_of::() { let exp_as_number = { let mut tmp: usize = 0; diff --git a/engine-tests/src/tests/modexp.rs b/engine-tests/src/tests/modexp.rs index 6453a8000..fa6f9942c 100644 --- a/engine-tests/src/tests/modexp.rs +++ b/engine-tests/src/tests/modexp.rs @@ -153,9 +153,11 @@ fn test_modexp_oom() { "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // exp_len: u64::MAX "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000c000000000000000000000000000000000000000000000000000000000000000071000000000000ff600000000000000000000000000000000000000000000000", + // exponent equal to zero + "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001060002", ]; - let outputs = [Vec::new(), Vec::new(), Vec::new()]; + let outputs = [Vec::new(), Vec::new(), Vec::new(), vec![0x01]]; for (input, output) in inputs.iter().zip(outputs.iter()) { check_wasm_modexp( From fffe0f7b0dcc66105c735baaefd2197c78e4e9d6 Mon Sep 17 00:00:00 2001 From: Oleksandr Anyshchenko Date: Mon, 12 Jun 2023 22:48:42 +0200 Subject: [PATCH 08/13] chore: move input parameters to aurora-engine-types (#772) ## Description The goal of the PR is to allow to use input parameters of the engine without importing the `aurora-engine` itself. ## Performance / NEAR gas cost considerations There are no changes because it's refactoring only. ## Testing Some tests were moved only. ## How should this be reviewed Pay attention that parameters correctly have been placed in corresponding modules. ## Additional information --- Cargo.lock | 2 + engine-precompiles/src/account_ids.rs | 10 +- engine-precompiles/src/alt_bn256.rs | 8 +- engine-precompiles/src/blake2.rs | 8 +- engine-precompiles/src/hash.rs | 6 +- engine-precompiles/src/identity.rs | 6 +- engine-precompiles/src/lib.rs | 59 +--- engine-precompiles/src/modexp.rs | 4 +- engine-precompiles/src/native.rs | 10 +- engine-precompiles/src/prepaid_gas.rs | 4 +- engine-precompiles/src/promise_result.rs | 4 +- engine-precompiles/src/random.rs | 5 +- engine-precompiles/src/secp256k1.rs | 4 +- engine-precompiles/src/xcc.rs | 8 +- .../src/test_utils/exit_precompile.rs | 6 +- .../src/test_utils/standalone/mocks/mod.rs | 6 +- engine-tests/src/tests/ecrecover.rs | 4 +- engine-tests/src/tests/eth_connector.rs | 4 +- engine-tests/src/tests/modexp.rs | 4 +- engine-tests/src/tests/standalone/sync.rs | 2 +- engine-types/Cargo.toml | 5 +- engine-types/src/parameters/connector.rs | 249 +++++++++++++ engine-types/src/parameters/engine.rs | 164 ++++++++- engine-types/src/parameters/mod.rs | 331 +----------------- engine-types/src/parameters/promise.rs | 327 +++++++++++++++++ engine-types/src/types/address.rs | 105 ++++-- engine/src/connector.rs | 94 ++++- engine/src/deposit_event.rs | 4 +- engine/src/engine.rs | 3 +- engine/src/fungible_token.rs | 46 +-- engine/src/lib.rs | 18 +- engine/src/log_entry.rs | 56 --- engine/src/parameters.rs | 302 ---------------- engine/src/proof.rs | 100 ------ etc/xcc-router/Cargo.lock | 8 + 35 files changed, 997 insertions(+), 979 deletions(-) create mode 100644 engine-types/src/parameters/connector.rs create mode 100644 engine-types/src/parameters/promise.rs delete mode 100644 engine/src/log_entry.rs delete mode 100644 engine/src/parameters.rs delete mode 100644 engine/src/proof.rs diff --git a/Cargo.lock b/Cargo.lock index fefaabe4a..5d4d11da5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -398,11 +398,13 @@ dependencies = [ name = "aurora-engine-types" version = "1.0.0" dependencies = [ + "base64 0.21.2", "borsh 0.10.3", "borsh 0.9.3", "hex", "primitive-types 0.12.1", "rand 0.8.5", + "rlp", "serde", "serde_json", ] diff --git a/engine-precompiles/src/account_ids.rs b/engine-precompiles/src/account_ids.rs index ec61f79ad..ec38996fc 100644 --- a/engine-precompiles/src/account_ids.rs +++ b/engine-precompiles/src/account_ids.rs @@ -1,5 +1,5 @@ use super::{EvmPrecompileResult, Precompile}; -use crate::prelude::types::{Address, EthGas}; +use crate::prelude::types::{make_address, Address, EthGas}; use crate::{utils, PrecompileOutput}; use aurora_engine_sdk::env::Env; use aurora_engine_types::account_id::AccountId; @@ -20,14 +20,13 @@ pub struct PredecessorAccount<'a, E> { } pub mod predecessor_account { - use aurora_engine_types::types::Address; + use aurora_engine_types::types::{make_address, Address}; /// `predecessor_account_id` precompile address /// /// Address: `0x723ffbaba940e75e7bf5f6d61dcbf8d9a4de0fd7` /// This address is computed as: `&keccak("predecessorAccountId")[12..]` - pub const ADDRESS: Address = - crate::make_address(0x723ffbab, 0xa940e75e7bf5f6d61dcbf8d9a4de0fd7); + pub const ADDRESS: Address = make_address(0x723ffbab, 0xa940e75e7bf5f6d61dcbf8d9a4de0fd7); } impl<'a, E> PredecessorAccount<'a, E> { @@ -73,8 +72,7 @@ impl CurrentAccount { /// /// Address: `0xfefae79e4180eb0284f261205e3f8cea737aff56` /// This address is computed as: `&keccak("currentAccountId")[12..]` - pub const ADDRESS: Address = - super::make_address(0xfefae79e, 0x4180eb0284f261205e3f8cea737aff56); + pub const ADDRESS: Address = make_address(0xfefae79e, 0x4180eb0284f261205e3f8cea737aff56); #[must_use] pub const fn new(current_account_id: AccountId) -> Self { diff --git a/engine-precompiles/src/alt_bn256.rs b/engine-precompiles/src/alt_bn256.rs index 58b8a21c0..72e36e7d7 100644 --- a/engine-precompiles/src/alt_bn256.rs +++ b/engine-precompiles/src/alt_bn256.rs @@ -1,4 +1,4 @@ -use crate::prelude::types::{Address, EthGas}; +use crate::prelude::types::{make_address, Address, EthGas}; use crate::prelude::{Borrowed, PhantomData, Vec}; use crate::utils; use crate::{Byzantium, EvmPrecompileResult, HardFork, Istanbul, Precompile, PrecompileOutput}; @@ -186,7 +186,7 @@ fn read_point(input: &[u8], pos: usize) -> Result { pub struct Bn256Add(PhantomData); impl Bn256Add { - pub const ADDRESS: Address = super::make_address(0, 6); + pub const ADDRESS: Address = make_address(0, 6); #[must_use] pub fn new() -> Self { @@ -291,7 +291,7 @@ impl Precompile for Bn256Add { pub struct Bn256Mul(PhantomData); impl Bn256Mul { - pub const ADDRESS: Address = super::make_address(0, 7); + pub const ADDRESS: Address = make_address(0, 7); #[must_use] pub fn new() -> Self { @@ -399,7 +399,7 @@ impl Precompile for Bn256Mul { pub struct Bn256Pair(PhantomData); impl Bn256Pair { - pub const ADDRESS: Address = super::make_address(0, 8); + pub const ADDRESS: Address = make_address(0, 8); #[must_use] pub fn new() -> Self { diff --git a/engine-precompiles/src/blake2.rs b/engine-precompiles/src/blake2.rs index 447bdee51..e1a47fa78 100644 --- a/engine-precompiles/src/blake2.rs +++ b/engine-precompiles/src/blake2.rs @@ -1,7 +1,11 @@ use evm::{Context, ExitError}; use crate::prelude::types::EthGas; -use crate::prelude::{mem, types::Address, Borrowed}; +use crate::prelude::{ + mem, + types::{make_address, Address}, + Borrowed, +}; use crate::{EvmPrecompileResult, Precompile, PrecompileOutput}; use aurora_engine_types::Vec; @@ -133,7 +137,7 @@ fn f(mut h: [u64; 8], m: [u64; 16], t: [u64; 2], f: bool, rounds: u32) -> Vec [u8; 20] { diff --git a/engine-precompiles/src/identity.rs b/engine-precompiles/src/identity.rs index fe493053a..bb203f5aa 100644 --- a/engine-precompiles/src/identity.rs +++ b/engine-precompiles/src/identity.rs @@ -1,10 +1,10 @@ -use crate::prelude::types::{Address, EthGas}; +use crate::prelude::types::{make_address, Address, EthGas}; use crate::{utils, EvmPrecompileResult, Precompile, PrecompileOutput}; use evm::{Context, ExitError}; /// Identity precompile costs. mod costs { - use crate::prelude::types::EthGas; + use aurora_engine_types::types::EthGas; /// The base cost of the operation. pub(super) const IDENTITY_BASE: EthGas = EthGas::new(15); @@ -21,7 +21,7 @@ mod consts { pub struct Identity; impl Identity { - pub const ADDRESS: Address = super::make_address(0, 4); + pub const ADDRESS: Address = make_address(0, 4); } impl Precompile for Identity { diff --git a/engine-precompiles/src/lib.rs b/engine-precompiles/src/lib.rs index 634084d67..49f475a8a 100644 --- a/engine-precompiles/src/lib.rs +++ b/engine-precompiles/src/lib.rs @@ -30,7 +30,7 @@ use crate::identity::Identity; use crate::modexp::ModExp; use crate::native::{exit_to_ethereum, exit_to_near, ExitToEthereum, ExitToNear}; use crate::prelude::types::EthGas; -use crate::prelude::{Vec, H160, H256}; +use crate::prelude::{Vec, H256}; use crate::prepaid_gas::PrepaidGas; use crate::random::RandomSeed; use crate::secp256k1::ECRecover; @@ -404,37 +404,6 @@ pub enum AllPrecompiles<'a, I, E, H> { Generic(Box), } -/// fn for making an address by concatenating the bytes from two given numbers, -/// Note that 32 + 128 = 160 = 20 bytes (the length of an address). This function is used -/// as a convenience for specifying the addresses of the various precompiles. -#[must_use] -pub const fn make_address(x: u32, y: u128) -> Address { - let x_bytes = x.to_be_bytes(); - let y_bytes = y.to_be_bytes(); - Address::new(H160([ - x_bytes[0], - x_bytes[1], - x_bytes[2], - x_bytes[3], - y_bytes[0], - y_bytes[1], - y_bytes[2], - y_bytes[3], - y_bytes[4], - y_bytes[5], - y_bytes[6], - y_bytes[7], - y_bytes[8], - y_bytes[9], - y_bytes[10], - y_bytes[11], - y_bytes[12], - y_bytes[13], - y_bytes[14], - y_bytes[15], - ])) -} - const fn make_h256(x: u128, y: u128) -> H256 { let x_bytes = x.to_be_bytes(); let y_bytes = y.to_be_bytes(); @@ -479,7 +448,6 @@ mod tests { use crate::prelude::H160; use crate::{prelude, Byzantium, Istanbul}; use prelude::types::Address; - use rand::Rng; #[test] fn test_precompile_addresses() { @@ -494,20 +462,6 @@ mod tests { assert_eq!(super::blake2::Blake2F::ADDRESS, u8_to_address(9)); } - #[test] - fn test_make_address() { - for i in 0..u8::MAX { - assert_eq!(super::make_address(0, i.into()), u8_to_address(i)); - } - - let mut rng = rand::thread_rng(); - for _ in 0..u8::MAX { - let address = Address::new(H160(rng.gen())); - let (x, y) = split_address(address); - assert_eq!(address, super::make_address(x, y)); - } - } - #[test] #[allow(clippy::too_many_lines)] fn test_paused_precompiles_throws_error() { @@ -638,15 +592,4 @@ mod tests { bytes[19] = x; Address::new(H160(bytes)) } - - // Inverse function of `super::make_address`. - fn split_address(a: Address) -> (u32, u128) { - let mut x_bytes = [0u8; 4]; - let mut y_bytes = [0u8; 16]; - - x_bytes.copy_from_slice(&a.raw()[0..4]); - y_bytes.copy_from_slice(&a.raw()[4..20]); - - (u32::from_be_bytes(x_bytes), u128::from_be_bytes(y_bytes)) - } } diff --git a/engine-precompiles/src/modexp.rs b/engine-precompiles/src/modexp.rs index 8bf40513f..9765b69b3 100644 --- a/engine-precompiles/src/modexp.rs +++ b/engine-precompiles/src/modexp.rs @@ -1,4 +1,4 @@ -use crate::prelude::types::{Address, EthGas}; +use crate::prelude::types::{make_address, Address, EthGas}; use crate::prelude::{Cow, PhantomData, Vec, U256}; use crate::{ utils, Berlin, Byzantium, EvmPrecompileResult, HardFork, Precompile, PrecompileOutput, @@ -11,7 +11,7 @@ use num::{Integer, Zero}; pub struct ModExp(PhantomData, PhantomData); impl ModExp { - pub const ADDRESS: Address = super::make_address(0, 5); + pub const ADDRESS: Address = make_address(0, 5); #[must_use] pub fn new() -> Self { diff --git a/engine-precompiles/src/native.rs b/engine-precompiles/src/native.rs index c92b06c07..272a76cc3 100644 --- a/engine-precompiles/src/native.rs +++ b/engine-precompiles/src/native.rs @@ -201,14 +201,13 @@ pub struct ExitToNear { } pub mod exit_to_near { - use aurora_engine_types::types::Address; + use crate::prelude::types::{make_address, Address}; /// Exit to NEAR precompile address /// /// Address: `0xe9217bc70b7ed1f598ddd3199e80b093fa71124f` /// This address is computed as: `&keccak("exitToNear")[12..]` - pub const ADDRESS: Address = - crate::make_address(0xe9217bc7, 0x0b7ed1f598ddd3199e80b093fa71124f); + pub const ADDRESS: Address = make_address(0xe9217bc7, 0x0b7ed1f598ddd3199e80b093fa71124f); } impl ExitToNear { @@ -445,14 +444,13 @@ pub struct ExitToEthereum { } pub mod exit_to_ethereum { - use aurora_engine_types::types::Address; + use crate::prelude::types::{make_address, Address}; /// Exit to Ethereum precompile address /// /// Address: `0xb0bd02f6a392af548bdf1cfaee5dfa0eefcc8eab` /// This address is computed as: `&keccak("exitToEthereum")[12..]` - pub const ADDRESS: Address = - crate::make_address(0xb0bd02f6, 0xa392af548bdf1cfaee5dfa0eefcc8eab); + pub const ADDRESS: Address = make_address(0xb0bd02f6, 0xa392af548bdf1cfaee5dfa0eefcc8eab); } impl ExitToEthereum { diff --git a/engine-precompiles/src/prepaid_gas.rs b/engine-precompiles/src/prepaid_gas.rs index ed8c61050..ad443c2fa 100644 --- a/engine-precompiles/src/prepaid_gas.rs +++ b/engine-precompiles/src/prepaid_gas.rs @@ -1,5 +1,5 @@ use super::{EvmPrecompileResult, Precompile}; -use crate::prelude::types::{Address, EthGas}; +use crate::prelude::types::{make_address, Address, EthGas}; use crate::{utils, PrecompileOutput}; use aurora_engine_sdk::env::Env; use aurora_engine_types::{vec, U256}; @@ -9,7 +9,7 @@ use evm::{Context, ExitError}; /// /// Address: `0x536822d27de53629ef1f84c60555689e9488609f` /// This address is computed as: `&keccak("prepaidGas")[12..]` -pub const ADDRESS: Address = crate::make_address(0x536822d2, 0x7de53629ef1f84c60555689e9488609f); +pub const ADDRESS: Address = make_address(0x536822d2, 0x7de53629ef1f84c60555689e9488609f); mod costs { use crate::prelude::types::EthGas; diff --git a/engine-precompiles/src/promise_result.rs b/engine-precompiles/src/promise_result.rs index 5b4fa8d66..ebd960655 100644 --- a/engine-precompiles/src/promise_result.rs +++ b/engine-precompiles/src/promise_result.rs @@ -1,5 +1,5 @@ use super::{EvmPrecompileResult, Precompile}; -use crate::prelude::types::{Address, EthGas}; +use crate::prelude::types::{make_address, Address, EthGas}; use crate::{utils, PrecompileOutput}; use aurora_engine_sdk::promise::ReadOnlyPromiseHandler; use aurora_engine_types::{borsh::BorshSerialize, Cow, Vec}; @@ -9,7 +9,7 @@ use evm::{Context, ExitError}; /// /// Address: `0x0a3540f79be10ef14890e87c1a0040a68cc6af71` /// This address is computed as: `&keccak("getPromiseResults")[12..]` -pub const ADDRESS: Address = crate::make_address(0x0a3540f7, 0x9be10ef14890e87c1a0040a68cc6af71); +pub const ADDRESS: Address = make_address(0x0a3540f7, 0x9be10ef14890e87c1a0040a68cc6af71); pub mod costs { use crate::prelude::types::EthGas; diff --git a/engine-precompiles/src/random.rs b/engine-precompiles/src/random.rs index 92bae55bd..40369ea12 100644 --- a/engine-precompiles/src/random.rs +++ b/engine-precompiles/src/random.rs @@ -1,5 +1,5 @@ use super::{EvmPrecompileResult, Precompile}; -use crate::prelude::types::{Address, EthGas}; +use crate::prelude::types::{make_address, Address, EthGas}; use crate::prelude::H256; use crate::{utils, PrecompileOutput}; use evm::{Context, ExitError}; @@ -22,8 +22,7 @@ impl RandomSeed { /// /// Address: `0xc104f4840573bed437190daf5d2898c2bdf928ac` /// This address is computed as: `&keccak("randomSeed")[12..]` - pub const ADDRESS: Address = - super::make_address(0xc104f484, 0x0573bed437190daf5d2898c2bdf928ac); + pub const ADDRESS: Address = make_address(0xc104f484, 0x0573bed437190daf5d2898c2bdf928ac); #[must_use] pub const fn new(random_seed: H256) -> Self { diff --git a/engine-precompiles/src/secp256k1.rs b/engine-precompiles/src/secp256k1.rs index a9b42cbe9..0b51e9b2d 100644 --- a/engine-precompiles/src/secp256k1.rs +++ b/engine-precompiles/src/secp256k1.rs @@ -1,4 +1,4 @@ -use crate::prelude::types::{Address, EthGas}; +use crate::prelude::types::{make_address, Address, EthGas}; use crate::prelude::{sdk, vec::Vec, Borrowed, H256}; use crate::{EvmPrecompileResult, Precompile, PrecompileOutput}; #[cfg(not(feature = "contract"))] @@ -62,7 +62,7 @@ fn internal_impl(hash: H256, signature: &[u8]) -> Result { pub struct ECRecover; impl ECRecover { - pub const ADDRESS: Address = super::make_address(0, 1); + pub const ADDRESS: Address = make_address(0, 1); } impl Precompile for ECRecover { diff --git a/engine-precompiles/src/xcc.rs b/engine-precompiles/src/xcc.rs index 3c6d36559..53d61a98c 100644 --- a/engine-precompiles/src/xcc.rs +++ b/engine-precompiles/src/xcc.rs @@ -74,14 +74,16 @@ impl CrossContractCall { } pub mod cross_contract_call { - use aurora_engine_types::{types::Address, H256}; + use aurora_engine_types::{ + types::{make_address, Address}, + H256, + }; /// Exit to Ethereum precompile address /// /// Address: `0x516cded1d16af10cad47d6d49128e2eb7d27b372` /// This address is computed as: `&keccak("nearCrossContractCall")[12..]` - pub const ADDRESS: Address = - crate::make_address(0x516cded1, 0xd16af10cad47d6d49128e2eb7d27b372); + pub const ADDRESS: Address = make_address(0x516cded1, 0xd16af10cad47d6d49128e2eb7d27b372); /// Sentinel value used to indicate the following topic field is how much NEAR the /// cross-contract call will require. diff --git a/engine-tests/src/test_utils/exit_precompile.rs b/engine-tests/src/test_utils/exit_precompile.rs index 4f86544da..2cbb6a0f4 100644 --- a/engine-tests/src/test_utils/exit_precompile.rs +++ b/engine-tests/src/test_utils/exit_precompile.rs @@ -1,5 +1,6 @@ use crate::prelude::{ - parameters::SubmitResult, transactions::legacy::TransactionLegacy, Address, Wei, U256, + make_address, parameters::SubmitResult, transactions::legacy::TransactionLegacy, Address, Wei, + U256, }; use crate::test_utils::{self, solidity, AuroraRunner, Signer}; use aurora_engine::engine::EngineError; @@ -8,8 +9,7 @@ pub struct TesterConstructor(pub solidity::ContractConstructor); const DEPLOY_CONTRACT_GAS: u64 = 1_000_000_000; pub const DEST_ACCOUNT: &str = "target.aurora"; -pub const DEST_ADDRESS: Address = - aurora_engine_precompiles::make_address(0xe0f5206b, 0xbd039e7b0592d8918820024e2a7437b9); +pub const DEST_ADDRESS: Address = make_address(0xe0f5206b, 0xbd039e7b0592d8918820024e2a7437b9); impl TesterConstructor { #[cfg(feature = "error_refund")] diff --git a/engine-tests/src/test_utils/standalone/mocks/mod.rs b/engine-tests/src/test_utils/standalone/mocks/mod.rs index 1403737e8..970621013 100644 --- a/engine-tests/src/test_utils/standalone/mocks/mod.rs +++ b/engine-tests/src/test_utils/standalone/mocks/mod.rs @@ -6,7 +6,7 @@ use aurora_engine::parameters::{ use aurora_engine::{engine, state}; use aurora_engine_sdk::env::{Env, DEFAULT_PREPAID_GAS}; use aurora_engine_sdk::io::IO; -use aurora_engine_types::types::{Address, Balance, NEP141Wei, NearGas, Wei}; +use aurora_engine_types::types::{make_address, Address, Balance, NEP141Wei, NearGas, Wei}; use aurora_engine_types::{account_id::AccountId, H256, U256}; use engine_standalone_storage::{BlockMetadata, Storage}; use near_sdk_sim::DEFAULT_GAS; @@ -14,10 +14,10 @@ use near_sdk_sim::DEFAULT_GAS; pub mod block; pub const ETH_CUSTODIAN_ADDRESS: Address = - aurora_engine_precompiles::make_address(0xd045f7e1, 0x9b2488924b97f9c145b5e51d0d895a65); + make_address(0xd045f7e1, 0x9b2488924b97f9c145b5e51d0d895a65); pub fn compute_block_hash(block_height: u64) -> H256 { - aurora_engine::engine::compute_block_hash([0u8; 32], block_height, b"aurora") + engine::compute_block_hash([0u8; 32], block_height, b"aurora") } pub fn insert_block(storage: &mut Storage, block_height: u64) { diff --git a/engine-tests/src/tests/ecrecover.rs b/engine-tests/src/tests/ecrecover.rs index ec15865c6..d2ac8e2e2 100644 --- a/engine-tests/src/tests/ecrecover.rs +++ b/engine-tests/src/tests/ecrecover.rs @@ -1,10 +1,10 @@ use super::sanity::initialize_transfer; -use crate::prelude::{Address, U256}; +use crate::prelude::{make_address, Address, U256}; use crate::prelude::{Wei, H160}; use crate::test_utils::{self, AuroraRunner, Signer}; use aurora_engine_precompiles::Precompile; -const ECRECOVER_ADDRESS: Address = aurora_engine_precompiles::make_address(0, 1); +const ECRECOVER_ADDRESS: Address = make_address(0, 1); /// ecrecover tests taken from geth #[test] diff --git a/engine-tests/src/tests/eth_connector.rs b/engine-tests/src/tests/eth_connector.rs index 99bb29693..e8dc775f5 100644 --- a/engine-tests/src/tests/eth_connector.rs +++ b/engine-tests/src/tests/eth_connector.rs @@ -651,7 +651,7 @@ fn test_deposit_with_0x_prefix() { inputs: aurora_engine::deposit_event::DepositedEvent::event_params(), anonymous: false, }; - let log_entry = aurora_engine::log_entry::LogEntry { + let log_entry = aurora_engine_types::parameters::connector::LogEntry { address: eth_custodian_address.raw(), topics: vec![ event_schema.signature(), @@ -712,7 +712,7 @@ fn generate_dummy_proof(message: String, deposit_amount: u128, log_index: u64) - inputs: aurora_engine::deposit_event::DepositedEvent::event_params(), anonymous: false, }; - let log_entry = aurora_engine::log_entry::LogEntry { + let log_entry = aurora_engine_types::parameters::connector::LogEntry { address: eth_custodian_address.raw(), topics: vec![ event_schema.signature(), diff --git a/engine-tests/src/tests/modexp.rs b/engine-tests/src/tests/modexp.rs index fa6f9942c..fa581ad7c 100644 --- a/engine-tests/src/tests/modexp.rs +++ b/engine-tests/src/tests/modexp.rs @@ -4,10 +4,10 @@ use rand::{Rng, SeedableRng}; use super::sanity::initialize_transfer; use crate::prelude::Wei; -use crate::prelude::{Address, U256}; +use crate::prelude::{make_address, Address, U256}; use crate::test_utils::{self, standalone::StandaloneRunner, AuroraRunner, Signer}; -const MODEXP_ADDRESS: Address = aurora_engine_precompiles::make_address(0, 5); +const MODEXP_ADDRESS: Address = make_address(0, 5); #[test] fn bench_modexp() { diff --git a/engine-tests/src/tests/standalone/sync.rs b/engine-tests/src/tests/standalone/sync.rs index 595ed2f53..be9a041c3 100644 --- a/engine-tests/src/tests/standalone/sync.rs +++ b/engine-tests/src/tests/standalone/sync.rs @@ -426,7 +426,7 @@ fn mock_proof(recipient_address: Address, deposit_amount: Wei) -> aurora_engine: inputs: aurora_engine::deposit_event::DepositedEvent::event_params(), anonymous: false, }; - let log_entry = aurora_engine::log_entry::LogEntry { + let log_entry = aurora_engine_types::parameters::connector::LogEntry { address: eth_custodian_address.raw(), topics: vec![ event_schema.signature(), diff --git a/engine-types/Cargo.toml b/engine-types/Cargo.toml index 4cb5b4c47..e8f2ab9fa 100644 --- a/engine-types/Cargo.toml +++ b/engine-types/Cargo.toml @@ -13,10 +13,12 @@ publish = false autobenches = false [dependencies] +base64 = { version = "0.21", default-features = false, features = [ "alloc" ] } borsh = { version = "0.10", default-features = false } borsh-compat = { version = "0.9", package = "borsh", default-features = false, optional = true } hex = { version = "0.4", default-features = false, features = ["alloc"] } primitive-types = { version = "0.12", default-features = false, features = ["rlp", "serde_no_std"] } +rlp = { version = "0.5.0", default-features = false } serde = { version = "1", default-features = false, features = ["alloc", "derive"] } serde_json = { version = "1", default-features = false, features = ["alloc"] } @@ -25,10 +27,11 @@ rand = "0.8.5" [features] default = ["std"] -std = ["borsh/std", "hex/std", "primitive-types/std", "primitive-types/serde", "serde/std", "serde_json/std"] +std = ["borsh/std", "hex/std", "primitive-types/std", "primitive-types/serde", "serde/std", "serde_json/std", "rlp/std"] # `primitive-types/std` is excluded because its `std` implementation includes a transitive # dependency on `getrandom` which uses OS call to obtain entropy. Such calls are not # available in Wasm, therefore we cannot use the `std` implementation of `primitive-types` # in other Rust contracts. contracts-std = ["borsh/std", "hex/std"] impl-serde = ["primitive-types/impl-serde"] +evm_bully = [] diff --git a/engine-types/src/parameters/connector.rs b/engine-types/src/parameters/connector.rs new file mode 100644 index 000000000..5fa2483ce --- /dev/null +++ b/engine-types/src/parameters/connector.rs @@ -0,0 +1,249 @@ +use base64::Engine; +#[cfg(not(feature = "borsh-compat"))] +use borsh::{BorshDeserialize, BorshSerialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, BorshDeserialize, BorshSerialize}; +use serde::{Deserialize, Serialize}; + +use crate::account_id::AccountId; +use crate::types::{Address, Balance, Fee, NEP141Wei, Yocto}; +use crate::{String, ToString, Vec, H160, H256}; + +/// Eth-connector initial args +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +pub struct InitCallArgs { + pub prover_account: AccountId, + pub eth_custodian_address: String, + pub metadata: FungibleTokenMetadata, +} + +/// Eth-connector Set contract data call args +pub type SetContractDataCallArgs = InitCallArgs; + +/// Proof used in deposit flow. +#[derive(Debug, Default, BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone)] +pub struct Proof { + pub log_index: u64, + pub log_entry_data: Vec, + pub receipt_index: u64, + pub receipt_data: Vec, + pub header_data: Vec, + pub proof: Vec>, +} + +/// Deposit ETH args +#[derive(Default, BorshDeserialize, BorshSerialize, Clone)] +pub struct DepositEthCallArgs { + pub proof: Proof, + pub relayer_eth_account: Address, +} + +/// Finish deposit NEAR eth-connector call args +#[derive(BorshSerialize, BorshDeserialize)] +pub struct FinishDepositEthCallArgs { + pub new_owner_id: Address, + pub amount: NEP141Wei, + pub fee: Balance, + pub relayer_eth_account: AccountId, + pub proof: Proof, +} + +/// transfer eth-connector call args +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Deserialize, Serialize, PartialEq, Eq)] +pub struct TransferCallCallArgs { + pub receiver_id: AccountId, + pub amount: NEP141Wei, + pub memo: Option, + pub msg: String, +} + +/// `storage_balance_of` eth-connector call args +#[derive(BorshSerialize, BorshDeserialize, Deserialize, Serialize)] +pub struct StorageBalanceOfCallArgs { + pub account_id: AccountId, +} + +/// `storage_deposit` eth-connector call args +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Deserialize, Serialize, PartialEq, Eq)] +pub struct StorageDepositCallArgs { + pub account_id: Option, + pub registration_only: Option, +} + +/// `storage_withdraw` eth-connector call args +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Deserialize, Serialize, PartialEq, Eq)] +pub struct StorageWithdrawCallArgs { + pub amount: Option, +} + +/// transfer args for json invocation +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Deserialize, Serialize, PartialEq, Eq)] +pub struct TransferCallArgs { + pub receiver_id: AccountId, + pub amount: NEP141Wei, + pub memo: Option, +} + +/// Eth-connector deposit arguments +#[derive(BorshSerialize, BorshDeserialize)] +pub struct DepositCallArgs { + /// Proof data + pub proof: Proof, + /// Optional relayer address + pub relayer_eth_account: Option
, +} + +/// Eth-connector `isUsedProof` arguments +#[derive(BorshSerialize, BorshDeserialize)] +pub struct IsUsedProofCallArgs { + /// Proof data + pub proof: Proof, +} + +/// withdraw result for eth-connector +#[derive(BorshSerialize, BorshDeserialize)] +pub struct WithdrawResult { + pub amount: NEP141Wei, + pub recipient_id: Address, + pub eth_custodian_address: Address, +} + +/// `ft_resolve_transfer` eth-connector call args +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +pub struct ResolveTransferCallArgs { + pub sender_id: AccountId, + pub amount: NEP141Wei, + pub receiver_id: AccountId, +} + +/// Finish deposit NEAR eth-connector call args +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +pub struct FinishDepositCallArgs { + pub new_owner_id: AccountId, + pub amount: NEP141Wei, + pub proof_key: String, + pub relayer_id: AccountId, + pub fee: Fee, + pub msg: Option>, +} + +/// `balance_of` args for json invocation +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] +pub struct BalanceOfCallArgs { + pub account_id: AccountId, +} + +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] +pub struct BalanceOfEthCallArgs { + pub address: Address, +} + +/// Borsh-encoded parameters for the `ft_transfer_call` function +/// for regular NEP-141 tokens. +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Deserialize, Serialize, PartialEq, Eq)] +pub struct NEP141FtOnTransferArgs { + pub sender_id: AccountId, + /// Balance can be for Eth on Near and for Eth to Aurora + /// `ft_on_transfer` can be called with arbitrary NEP-141 tokens attached, therefore we do not specify a particular type Wei. + pub amount: Balance, + pub msg: String, +} + +/// Fungible token Reference hash type. +/// Used for `FungibleTokenMetadata` +#[derive(Debug, BorshDeserialize, BorshSerialize, Deserialize, Serialize, Clone, PartialEq, Eq)] +pub struct FungibleReferenceHash([u8; 32]); + +impl FungibleReferenceHash { + /// Encode to base64-encoded string + #[must_use] + pub fn encode(&self) -> String { + base64::engine::general_purpose::STANDARD.encode(self.0) + } +} + +impl AsRef<[u8]> for FungibleReferenceHash { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +#[derive(Debug, BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, PartialEq, Eq)] +pub struct FungibleTokenMetadata { + pub spec: String, + pub name: String, + pub symbol: String, + pub icon: Option, + pub reference: Option, + pub reference_hash: Option, + pub decimals: u8, +} + +impl Default for FungibleTokenMetadata { + fn default() -> Self { + Self { + spec: "ft-1.0.0".to_string(), + name: "Ether".to_string(), + symbol: "ETH".to_string(), + icon: Some("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAs3SURBVHhe7Z1XqBQ9FMdFsYu999577wUfbCiiPoggFkQsCKJP9t57V7AgimLBjg8qKmLBXrD33hVUEAQ1H7+QXMb9Zndnd+/MJJf7h8Pu3c3Mzua3yTk5SeZmEZkySplADFMmEMOUCcQwZQggHz58EHfu3FF/2a0MAWTjxo2iWbNm6i+7ZT2QW7duiUWLFolixYqJQ4cOqVftlfVAZs6cKdauXSuqV68uKlWqpF61V1YDoUXMmTNHrFu3TtSoUUNCmTBhgnrXTlkL5Nu3b2Ly5MmyuwJIzZo1RaNGjUTx4sXFu3fvVCn7ZC2QVatWiQULFvwPSL169USnTp1UKftkJZCbN2+KGTNmSBiLFy/+BwhWoUIFsX//flXaLlkJZPr06WkwIoE0btxYNGzYUFSsWFGVtkvWATlw4IB05BqGGxAMBz9u3Dh1lD2yCsjXr1/THHk8IDwvVaqUeP36tTraDlkFZOXKldKRO2HEAoKD79ixozraDlkD5Pr16/848nhANBQc/N69e9VZzJc1QCIduRcgGA4eKLbICiD79u37nyN3WiwgvMZ7Y8eOVWczW8YDwZFPmTIlauvA4gHhsUSJEuLFixfqrObKeCArVqxwdeROiwUE43UcfNu2bdVZzZXRQK5duyYduRsEp8UDog1fsnPnTnV2M2U0kFiO3GlegeDgy5cvr85upowFQqg6d+5cVwCR5hUI71NuzJgx6lPMk5FAPn365Doij2ZegWCUIUX/9OlT9WlmyUggy5Yti+vInZYIEAwH37JlS/VpZsk4IJcvX5bTsl5bB5YoEMqRDd62bZv6VHNkHJBp06YlBANLFAiGgy9btqz6VHNkFJBdu3Z5duROSwYIxjEjRoxQn26GjAHy8ePHuCPyaJYsEMozgn/48KG6ivBlDJAlS5Yk5MidlgqQ+vXri+bNm6urCF9GALl48aJ05G6V7cWSBYJxDOu5Nm/erK4mXBkBJBlH7rRUgGAmOfjQgZBbSsaROy1VIBjHDxs2TF1VeAoVyPv37+WI3K2SE7H0AMKxJUuWFHfv3lVXF45CBZKKI3daegDBcPBNmzZVVxeOQgNy/vz5hEfkbsbxAGFtb6pAOL5y5cpye0NYCg1Iqo5c29KlS2WEVKdOHdGkSZOUoeDgS5cura4yeIUCZMeOHWLevHkpASEBScvAB/Xs2VMUKVJE1K1bV44pUgHDcbVq1RJDhgxRVxusAgfy5s0bMXXq1IRgOMsuX75c7gcZP368aN++vez3W7VqJfLnzy8KFCggU+tUKNncZMFwDA6eNcRBK3AgCxculOas8HiG82duffXq1WLkyJGiRYsWokGDBrI1UPHMlQOjaNGisqUUKlRIPrKclLKA0RUdWfnRDNCUD1qBAjl79qyYNWuWa6VHGq0CEGw7oHsaNGiQrCBMg9DmBKJNgylYsKAciQOFfYhUtlcwHEe3GKQCA/Lnzx/PyUMc9Zo1a+SAsV+/fvLXSgXxa3eCiAXECaZw4cISDPPpGijniweG93HwXHtQCgwIk0E4cjcAGhItAf8AuG7dukknzbgAENFgYLGAaNNgKMcibGYNdXdGxUeDgz8aOHCg+hb+KxAgr169kpUcCUKb01GzOJrKonuJB0KbFyBOAw4thgCgdu3aaWAA4AYGB8/a4iAUCBBG405Hrv2Dm6MGhFulx7JEgWjTYHisVq2a/GxapBMGgLguLAj5DuTMmTP/OHLtqPETdAW6u4h01IlYskC06e6MIICROlA0GH19vM51+y1fgfz+/TvNkWtHjR/p27ev7JboJrx2S7EsVSAYUDCgcC4CAEbtXJsGg4PnO/kpX4Fs3bpVwiB0BEz37t09O+pELD2AOE23GM5ZpkwZGeVxraRnBgwYoL6dP/INCCNyfAeOukOHDmmZVLcKTdXSG4jTNBidAaDlXLlyRX3L9JdvQPr06SObvHbU6dUa3MxPINp0d5Y3b16RJ08e9S3TX74Befz4sejcubOoWrWqdNi2AgEEj8DIkiWLdO4PHjxQ3zL95asPQQcPHpSTR/gOv6D4BUQ7+uzZs4usWbOK7du3q2/ln3wHosU+j3LlysmIxa1SUzG/gOTLl0+2ilGjRqlv4b8CA4K+fPkievXqJZt9MgPAaJbeQHT3hA9kJX6QChSI1smTJ+U4RKct3Co5EUsvIHRP2bJlEzlz5hRHjhxRVxusfANy4cIF9Sy6GLnrAZhbRXu1VIEAguiJVuHlfltbtmxRz9JfvgHhxpQMBt++fatecdfPnz/lYIvtAcmOU1IBQi4LEG3atJHXEkssEWK0fvv2bfVK+svXLosJKW4AQ3QSb07h6tWr0uEz+Eq0G0sGCAM+IieOI98WS3///hVDhw4VOXLkkAlRP+W7D9mwYYNMLtJa4n1xRBqe3bIMKL2CSQQI3VPu3Lllq+C64olsNPMnBCJdunRRr/qnQJw6IS/pdypg/vz5cff38YscPny49C9eujGvQCgDiB49eqhPii4WgJPuAQQ+Lqi1v4EAefToUVrWFzCsyWIx2q9fv1QJd92/f1+0bt1aLlaINdqPB4TuCRD80rmtbCzhR8hG66SizvKeOHFClfBXgQBBe/bskfcr0dO1pOFZU3Xs2DFVIrqY/q1SpUpa1tUrELqnXLlySRhe5jKYw2d2kHBcz4OwIjLIXVaBAUF0V5Ezh7Nnz5Z27949VSq6CBDoOphHiQYECDyyTgsQ/fv3V0dH1/Hjx2V6h7wbEAguMH4ABBlBKlAgbneE090Yd21Yv369+P79uyrtrpcvX/6TtIwEorsnlvA8efJEHeUuRuFdu3aVKR2CCCcMnpNyf/78uSodjAIFgk6fPh11txQtCGBebhlO0pLuhKSlBkISEBhMjMXTxIkTZYVzvBOEhgFQriloBQ4EEUrGWhKEryEyu3HjhjoiuggWqDxAeOnrufcW5QkUIkFoGEBiUi0MhQKEeel4q995DyjcZ/Hz58/qSHfRrcTbSUuZdu3ayTEOYawbDIz3iLDiRYB+KRQgiP/3waJrNxjagMI0MK2AKC1ZjR49Wm5/JqEZDQTGe8A4fPiwOjJ4hQYEsS3By/5CwFCOVsWAzatIAhKVed3MQznWEIepUIEg/IUzFI5lgCEgYG1XrKQlyT9CY3wFXZBb5UcaURZ+JWyFDoSs8KRJk2L6E6dRDoB0YyQtneukSGAOHjxYDu70KNut8iONckRcJvzbpNCBIAZmXrcpYBoekRpgyBQzhiE1wkDOKwiMsuSr6BJNkBFAENEU45DIyo9nwGGxNs44ERAY5QlxmQsxRcYAIcxMdKubtmS3RVOe7u3Hjx/qKsKXMUAQA0EiKbdKj2XJAiEC2717t/p0M2QUEETaw0so7LREgVCO8l4Sj0HLOCAIB+81FMYSAUIZQmGSkybKSCAs1I7MCseyRIEwaveSJwtDRgJBR48e9RwKewXC+0x0AdtUGQsEMSL3cnMaL0B4j1wWc/Qmy2ggzG/ruXg3ENq8AmHgyCSZyTIaCLp06VLce8DHA8LrrGDxMnEVtowHgjZt2hR1QguLB4R0Su/evdXZzJYVQJBe25UoELK4Nv1PQ2uAPHv2LKo/iQaEv0mNeFn4bYqsAYL4p5IsGfIChOfMb7Dp1CZZBQTRQiJDYTcgerrWNlkHhHVbkV1XJBAemXDirqe2yTog6Ny5c9LJayhOIBgrS1h1b6OsBIKocB0KO4FwtwVu7WSrrAWC9NouDYQsLstCbZbVQNjmwCwjQFjCwzTuqVOn1Lt2ymogiBk/PafOfbdsl/VAEEBs+gfEsZQhgDChxVKgjKAMASQjKROIYcoEYpgygRglIf4D6lp/+XognSwAAAAASUVORK5CYII=".to_string()), + reference: None, + reference_hash: None, + decimals: 18, + } + } +} + +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct LogEntry { + pub address: H160, + pub topics: Vec, + pub data: Vec, +} + +impl rlp::Decodable for LogEntry { + fn decode(rlp: &rlp::Rlp) -> Result { + let result = Self { + address: rlp.val_at(0usize)?, + topics: rlp.list_at(1usize)?, + data: rlp.val_at(2usize)?, + }; + Ok(result) + } +} + +impl rlp::Encodable for LogEntry { + fn rlp_append(&self, stream: &mut rlp::RlpStream) { + stream.begin_list(3usize); + stream.append(&self.address); + stream.append_list::(&self.topics); + stream.append(&self.data); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use rlp::{Decodable, Encodable, Rlp, RlpStream}; + + #[test] + fn test_roundtrip_rlp_encoding() { + let address = H160::from_low_u64_le(32u64); + let topics = vec![H256::zero()]; + let data = vec![0u8, 1u8, 2u8, 3u8]; + let expected_log_entry = LogEntry { + address, + topics, + data, + }; + + let mut stream = RlpStream::new(); + + expected_log_entry.rlp_append(&mut stream); + + let bytes = stream.out(); + let rlp = Rlp::new(bytes.as_ref()); + let actual_log_entry = LogEntry::decode(&rlp).unwrap(); + + assert_eq!(expected_log_entry, actual_log_entry); + } +} diff --git a/engine-types/src/parameters/engine.rs b/engine-types/src/parameters/engine.rs index a600cd115..70018fbb6 100644 --- a/engine-types/src/parameters/engine.rs +++ b/engine-types/src/parameters/engine.rs @@ -1,6 +1,6 @@ use crate::{ account_id::AccountId, - types::{Address, RawH256, RawU256, WeiU256}, + types::{Address, RawH256, RawU256, WeiU256, Yocto}, Vec, }; #[cfg(not(feature = "borsh-compat"))] @@ -8,6 +8,139 @@ use borsh::{BorshDeserialize, BorshSerialize}; #[cfg(feature = "borsh-compat")] use borsh_compat::{self as borsh, BorshDeserialize, BorshSerialize}; +/// Parameters for the `new` function. +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub enum NewCallArgs { + V1(LegacyNewCallArgs), + V2(NewCallArgsV2), +} + +impl NewCallArgs { + pub fn deserialize(bytes: &[u8]) -> Result { + Self::try_from_slice(bytes).map_or_else( + |_| LegacyNewCallArgs::try_from_slice(bytes).map(Self::V1), + Ok, + ) + } +} + +/// Old Borsh-encoded parameters for the `new` function. +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct LegacyNewCallArgs { + /// Chain id, according to the EIP-115 / ethereum-lists spec. + pub chain_id: RawU256, + /// Account which can upgrade this contract. + /// Use empty to disable updatability. + pub owner_id: AccountId, + /// Account of the bridge prover. + /// Use empty to not use base token as bridged asset. + pub bridge_prover_id: AccountId, + /// How many blocks after staging upgrade can deploy it. + pub upgrade_delay_blocks: u64, +} + +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct NewCallArgsV2 { + /// Chain id, according to the EIP-115 / ethereum-lists spec. + pub chain_id: RawU256, + /// Account which can upgrade this contract. + /// Use empty to disable updatability. + pub owner_id: AccountId, + /// How many blocks after staging upgrade can deploy it. + pub upgrade_delay_blocks: u64, +} + +/// Borsh-encoded parameters for the `set_owner` function. +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +#[cfg_attr(feature = "impl-serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetOwnerArgs { + pub new_owner: AccountId, +} + +/// Borsh-encoded parameters for the `set_upgrade_delay_blocks` function. +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +#[cfg_attr(feature = "impl-serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetUpgradeDelayBlocksArgs { + pub upgrade_delay_blocks: u64, +} + +/// Borsh-encoded (genesis) account balance used by the `begin_chain` function. +#[cfg(feature = "evm_bully")] +#[derive(BorshSerialize, BorshDeserialize)] +pub struct AccountBalance { + pub address: Address, + pub balance: RawU256, +} + +/// Borsh-encoded submit arguments used by the `submit_with_args` function. +#[derive(Default, Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct SubmitArgs { + /// Bytes of the transaction. + pub tx_data: Vec, + /// Max gas price the user is ready to pay for the transaction. + pub max_gas_price: Option, + /// Address of the `ERC20` token the user prefers to pay in. + pub gas_token_address: Option
, +} + +/// Borsh-encoded parameters for the `begin_chain` function. +#[cfg(feature = "evm_bully")] +#[derive(BorshSerialize, BorshDeserialize)] +pub struct BeginChainArgs { + pub chain_id: RawU256, + pub genesis_alloc: Vec, +} + +/// Borsh-encoded parameters for the `begin_block` function. +#[cfg(feature = "evm_bully")] +#[derive(BorshSerialize, BorshDeserialize)] +pub struct BeginBlockArgs { + /// The current block's hash (for replayer use). + pub hash: RawU256, + /// The current block's beneficiary address. + pub coinbase: Address, + /// The current block's timestamp (in seconds since the Unix epoch). + pub timestamp: RawU256, + /// The current block's number (the genesis block is number zero). + pub number: RawU256, + /// The current block's difficulty. + pub difficulty: RawU256, + /// The current block's gas limit. + pub gaslimit: RawU256, +} + +/// Fungible token storage balance +#[derive(Default, Debug, serde::Serialize, serde::Deserialize)] +pub struct StorageBalance { + pub total: Yocto, + pub available: Yocto, +} + +impl StorageBalance { + #[must_use] + pub fn to_json_bytes(&self) -> Vec { + serde_json::to_vec(self).unwrap_or_default() + } +} + +#[derive(BorshSerialize, BorshDeserialize)] +pub struct RegisterRelayerCallArgs { + pub address: Address, +} + +pub type PausedMask = u8; + +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +#[cfg_attr(feature = "impl-serde", derive(serde::Serialize, serde::Deserialize))] +pub struct PauseEthConnectorCallArgs { + pub paused_mask: PausedMask, +} + +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +pub struct PausePrecompilesCallArgs { + pub paused_mask: u32, +} + #[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] #[cfg_attr(feature = "impl-serde", derive(serde::Serialize, serde::Deserialize))] pub struct ResultLog { @@ -154,11 +287,40 @@ pub struct GetStorageAtArgs { } pub mod errors { + use crate::{account_id::ParseAccountError, String, ToString}; + pub const ERR_REVERT: &[u8; 10] = b"ERR_REVERT"; pub const ERR_OUT_OF_FUNDS: &[u8; 16] = b"ERR_OUT_OF_FUNDS"; pub const ERR_CALL_TOO_DEEP: &[u8; 17] = b"ERR_CALL_TOO_DEEP"; pub const ERR_OUT_OF_OFFSET: &[u8; 17] = b"ERR_OUT_OF_OFFSET"; pub const ERR_OUT_OF_GAS: &[u8; 14] = b"ERR_OUT_OF_GAS"; + + #[derive(Debug)] + pub enum ParseTypeFromJsonError { + Json(String), + InvalidAccount(ParseAccountError), + } + + impl From for ParseTypeFromJsonError { + fn from(e: serde_json::Error) -> Self { + Self::Json(e.to_string()) + } + } + + impl From for ParseTypeFromJsonError { + fn from(e: ParseAccountError) -> Self { + Self::InvalidAccount(e) + } + } + + impl AsRef<[u8]> for ParseTypeFromJsonError { + fn as_ref(&self) -> &[u8] { + match self { + Self::Json(e) => e.as_bytes(), + Self::InvalidAccount(e) => e.as_ref(), + } + } + } } #[cfg(test)] diff --git a/engine-types/src/parameters/mod.rs b/engine-types/src/parameters/mod.rs index 65521c6b1..76d19a672 100644 --- a/engine-types/src/parameters/mod.rs +++ b/engine-types/src/parameters/mod.rs @@ -1,330 +1,5 @@ -use crate::{ - account_id::AccountId, - types::{Address, NEP141Wei, NearGas, RawU256, Yocto}, - Box, String, Vec, -}; -#[cfg(not(feature = "borsh-compat"))] -use borsh::{maybestd::io, BorshDeserialize, BorshSerialize}; -#[cfg(feature = "borsh-compat")] -use borsh_compat::{self as borsh, maybestd::io, BorshDeserialize, BorshSerialize}; +pub use promise::*; +pub mod connector; pub mod engine; - -#[must_use] -#[derive(Debug, BorshSerialize, BorshDeserialize)] -pub enum PromiseArgs { - Create(PromiseCreateArgs), - Callback(PromiseWithCallbackArgs), - Recursive(NearPromise), -} - -impl PromiseArgs { - /// Counts the total number of promises this call creates (including callbacks). - #[must_use] - pub fn promise_count(&self) -> u64 { - match self { - Self::Create(_) => 1, - Self::Callback(_) => 2, - Self::Recursive(p) => p.promise_count(), - } - } - - #[must_use] - pub fn total_gas(&self) -> NearGas { - match self { - Self::Create(call) => call.attached_gas, - Self::Callback(cb) => cb.base.attached_gas + cb.callback.attached_gas, - Self::Recursive(p) => p.total_gas(), - } - } - - #[must_use] - pub fn total_near(&self) -> Yocto { - match self { - Self::Create(call) => call.attached_balance, - Self::Callback(cb) => cb.base.attached_balance + cb.callback.attached_balance, - Self::Recursive(p) => p.total_near(), - } - } -} - -#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] -pub enum SimpleNearPromise { - Create(PromiseCreateArgs), - Batch(PromiseBatchAction), -} - -impl SimpleNearPromise { - #[must_use] - pub fn total_gas(&self) -> NearGas { - match self { - Self::Create(call) => call.attached_gas, - Self::Batch(batch) => { - let total: u64 = batch - .actions - .iter() - .filter_map(|a| { - if let PromiseAction::FunctionCall { gas, .. } = a { - Some(gas.as_u64()) - } else { - None - } - }) - .sum(); - NearGas::new(total) - } - } - } - - #[must_use] - pub fn total_near(&self) -> Yocto { - match self { - Self::Create(call) => call.attached_balance, - Self::Batch(batch) => { - let total: u128 = batch - .actions - .iter() - .filter_map(|a| match a { - PromiseAction::FunctionCall { attached_yocto, .. } => { - Some(attached_yocto.as_u128()) - } - PromiseAction::Transfer { amount } => Some(amount.as_u128()), - _ => None, - }) - .sum(); - Yocto::new(total) - } - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum NearPromise { - Simple(SimpleNearPromise), - Then { - base: Box, - // Near doesn't allow arbitrary promises in the callback, - // only simple calls to contracts or batches of actions. - callback: SimpleNearPromise, - }, - And(Vec), -} - -impl NearPromise { - #[must_use] - pub fn promise_count(&self) -> u64 { - match self { - Self::Simple(_) => 1, - Self::Then { base, .. } => base.promise_count() + 1, - Self::And(ps) => ps.iter().map(Self::promise_count).sum(), - } - } - - #[must_use] - pub fn total_gas(&self) -> NearGas { - match self { - Self::Simple(x) => x.total_gas(), - Self::Then { base, callback } => base.total_gas() + callback.total_gas(), - Self::And(promises) => { - let total = promises.iter().map(|p| p.total_gas().as_u64()).sum(); - NearGas::new(total) - } - } - } - - #[must_use] - pub fn total_near(&self) -> Yocto { - match self { - Self::Simple(x) => x.total_near(), - Self::Then { base, callback } => base.total_near() + callback.total_near(), - Self::And(promises) => { - let total = promises.iter().map(|p| p.total_near().as_u128()).sum(); - Yocto::new(total) - } - } - } -} - -// Cannot use derive macro on recursive types, so we write it by hand -impl BorshSerialize for NearPromise { - fn serialize(&self, writer: &mut W) -> io::Result<()> { - match self { - Self::Simple(x) => { - writer.write_all(&[0x00])?; - x.serialize(writer) - } - Self::Then { base, callback } => { - writer.write_all(&[0x01])?; - base.serialize(writer)?; - callback.serialize(writer) - } - Self::And(promises) => { - writer.write_all(&[0x02])?; - promises.serialize(writer) - } - } - } -} - -#[cfg(not(feature = "borsh-compat"))] -impl BorshDeserialize for NearPromise { - fn deserialize_reader(reader: &mut R) -> io::Result { - let variant_byte = { - let mut buf = [0u8; 1]; - reader.read_exact(&mut buf)?; - buf[0] - }; - match variant_byte { - 0x00 => { - let inner = SimpleNearPromise::deserialize_reader(reader)?; - Ok(Self::Simple(inner)) - } - 0x01 => { - let base = Self::deserialize_reader(reader)?; - let callback = SimpleNearPromise::deserialize_reader(reader)?; - Ok(Self::Then { - base: Box::new(base), - callback, - }) - } - 0x02 => { - let promises: Vec = Vec::deserialize_reader(reader)?; - Ok(Self::And(promises)) - } - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid variant byte for NearPromise", - )), - } - } -} - -#[cfg(feature = "borsh-compat")] -impl BorshDeserialize for NearPromise { - fn deserialize(buf: &mut &[u8]) -> io::Result { - let variant_byte = buf[0]; - *buf = &buf[1..]; - match variant_byte { - 0x00 => { - let inner = SimpleNearPromise::deserialize(buf)?; - Ok(Self::Simple(inner)) - } - 0x01 => { - let base = Self::deserialize(buf)?; - let callback = SimpleNearPromise::deserialize(buf)?; - Ok(Self::Then { - base: Box::new(base), - callback, - }) - } - 0x02 => { - let promises: Vec = Vec::deserialize(buf)?; - Ok(Self::And(promises)) - } - _ => Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid variant byte for NearPromise", - )), - } - } -} - -#[must_use] -#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] -pub struct PromiseCreateArgs { - pub target_account_id: AccountId, - pub method: String, - pub args: Vec, - pub attached_balance: Yocto, - pub attached_gas: NearGas, -} - -#[must_use] -#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] -pub struct PromiseWithCallbackArgs { - pub base: PromiseCreateArgs, - pub callback: PromiseCreateArgs, -} - -#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] -pub enum PromiseAction { - CreateAccount, - Transfer { - amount: Yocto, - }, - DeployContract { - code: Vec, - }, - FunctionCall { - name: String, - args: Vec, - attached_yocto: Yocto, - gas: NearGas, - }, - Stake { - amount: Yocto, - public_key: NearPublicKey, - }, - AddFullAccessKey { - public_key: NearPublicKey, - nonce: u64, - }, - AddFunctionCallKey { - public_key: NearPublicKey, - nonce: u64, - allowance: Yocto, - receiver_id: AccountId, - function_names: String, - }, - DeleteKey { - public_key: NearPublicKey, - }, - DeleteAccount { - beneficiary_id: AccountId, - }, -} - -#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] -pub enum NearPublicKey { - /// ed25519 public keys are 32 bytes - Ed25519([u8; 32]), - /// secp256k1 keys are in the uncompressed 64 byte format - Secp256k1([u8; 64]), -} - -#[must_use] -#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] -pub struct PromiseBatchAction { - pub target_account_id: AccountId, - pub actions: Vec, -} - -/// withdraw NEAR eth-connector call args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -pub struct WithdrawCallArgs { - pub recipient_address: Address, - pub amount: NEP141Wei, -} - -/// withdraw NEAR eth-connector call args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -pub struct RefundCallArgs { - pub recipient_address: Address, - pub erc20_address: Option
, - pub amount: RawU256, -} - -/// Args passed to the the cross contract call precompile. -/// That precompile is used by Aurora contracts to make calls to the broader NEAR ecosystem. -/// See `https://github.com/aurora-is-near/AIPs/pull/2` for design details. -#[derive(Debug, BorshSerialize, BorshDeserialize)] -pub enum CrossContractCallArgs { - /// The promise is to be executed immediately (as part of the same NEAR transaction as the EVM call). - Eager(PromiseArgs), - /// The promise is to be stored in the router contract, and can be executed in a future transaction. - /// The purpose of this is to expand how much NEAR gas can be made available to a cross contract call. - /// For example, if an expensive EVM call ends with a NEAR cross contract call, then there may not be - /// much gas left to perform it. In this case, the promise could be `Delayed` (stored in the router) - /// and executed in a separate transaction with a fresh 300 Tgas available for it. - Delayed(PromiseArgs), -} +pub mod promise; diff --git a/engine-types/src/parameters/promise.rs b/engine-types/src/parameters/promise.rs new file mode 100644 index 000000000..d13519483 --- /dev/null +++ b/engine-types/src/parameters/promise.rs @@ -0,0 +1,327 @@ +use crate::account_id::AccountId; +use crate::types::{Address, NEP141Wei, NearGas, RawU256, Yocto}; +use crate::{Box, String, Vec}; + +#[cfg(not(feature = "borsh-compat"))] +use borsh::{maybestd::io, BorshDeserialize, BorshSerialize}; +#[cfg(feature = "borsh-compat")] +use borsh_compat::{self as borsh, maybestd::io, BorshDeserialize, BorshSerialize}; + +#[must_use] +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub enum PromiseArgs { + Create(PromiseCreateArgs), + Callback(PromiseWithCallbackArgs), + Recursive(NearPromise), +} + +impl PromiseArgs { + /// Counts the total number of promises this call creates (including callbacks). + #[must_use] + pub fn promise_count(&self) -> u64 { + match self { + Self::Create(_) => 1, + Self::Callback(_) => 2, + Self::Recursive(p) => p.promise_count(), + } + } + + #[must_use] + pub fn total_gas(&self) -> NearGas { + match self { + Self::Create(call) => call.attached_gas, + Self::Callback(cb) => cb.base.attached_gas + cb.callback.attached_gas, + Self::Recursive(p) => p.total_gas(), + } + } + + #[must_use] + pub fn total_near(&self) -> Yocto { + match self { + Self::Create(call) => call.attached_balance, + Self::Callback(cb) => cb.base.attached_balance + cb.callback.attached_balance, + Self::Recursive(p) => p.total_near(), + } + } +} + +#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] +pub enum SimpleNearPromise { + Create(PromiseCreateArgs), + Batch(PromiseBatchAction), +} + +impl SimpleNearPromise { + #[must_use] + pub fn total_gas(&self) -> NearGas { + match self { + Self::Create(call) => call.attached_gas, + Self::Batch(batch) => { + let total: u64 = batch + .actions + .iter() + .filter_map(|a| { + if let PromiseAction::FunctionCall { gas, .. } = a { + Some(gas.as_u64()) + } else { + None + } + }) + .sum(); + NearGas::new(total) + } + } + } + + #[must_use] + pub fn total_near(&self) -> Yocto { + match self { + Self::Create(call) => call.attached_balance, + Self::Batch(batch) => { + let total: u128 = batch + .actions + .iter() + .filter_map(|a| match a { + PromiseAction::FunctionCall { attached_yocto, .. } => { + Some(attached_yocto.as_u128()) + } + PromiseAction::Transfer { amount } => Some(amount.as_u128()), + _ => None, + }) + .sum(); + Yocto::new(total) + } + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum NearPromise { + Simple(SimpleNearPromise), + Then { + base: Box, + // Near doesn't allow arbitrary promises in the callback, + // only simple calls to contracts or batches of actions. + callback: SimpleNearPromise, + }, + And(Vec), +} + +impl NearPromise { + #[must_use] + pub fn promise_count(&self) -> u64 { + match self { + Self::Simple(_) => 1, + Self::Then { base, .. } => base.promise_count() + 1, + Self::And(ps) => ps.iter().map(Self::promise_count).sum(), + } + } + + #[must_use] + pub fn total_gas(&self) -> NearGas { + match self { + Self::Simple(x) => x.total_gas(), + Self::Then { base, callback } => base.total_gas() + callback.total_gas(), + Self::And(promises) => { + let total = promises.iter().map(|p| p.total_gas().as_u64()).sum(); + NearGas::new(total) + } + } + } + + #[must_use] + pub fn total_near(&self) -> Yocto { + match self { + Self::Simple(x) => x.total_near(), + Self::Then { base, callback } => base.total_near() + callback.total_near(), + Self::And(promises) => { + let total = promises.iter().map(|p| p.total_near().as_u128()).sum(); + Yocto::new(total) + } + } + } +} + +// Cannot use derive macro on recursive types, so we write it by hand +impl BorshSerialize for NearPromise { + fn serialize(&self, writer: &mut W) -> io::Result<()> { + match self { + Self::Simple(x) => { + writer.write_all(&[0x00])?; + x.serialize(writer) + } + Self::Then { base, callback } => { + writer.write_all(&[0x01])?; + base.serialize(writer)?; + callback.serialize(writer) + } + Self::And(promises) => { + writer.write_all(&[0x02])?; + promises.serialize(writer) + } + } + } +} + +#[cfg(not(feature = "borsh-compat"))] +impl BorshDeserialize for NearPromise { + fn deserialize_reader(reader: &mut R) -> io::Result { + let variant_byte = { + let mut buf = [0u8; 1]; + reader.read_exact(&mut buf)?; + buf[0] + }; + match variant_byte { + 0x00 => { + let inner = SimpleNearPromise::deserialize_reader(reader)?; + Ok(Self::Simple(inner)) + } + 0x01 => { + let base = Self::deserialize_reader(reader)?; + let callback = SimpleNearPromise::deserialize_reader(reader)?; + Ok(Self::Then { + base: Box::new(base), + callback, + }) + } + 0x02 => { + let promises: Vec = Vec::deserialize_reader(reader)?; + Ok(Self::And(promises)) + } + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid variant byte for NearPromise", + )), + } + } +} + +#[cfg(feature = "borsh-compat")] +impl BorshDeserialize for NearPromise { + fn deserialize(buf: &mut &[u8]) -> io::Result { + let variant_byte = buf[0]; + *buf = &buf[1..]; + match variant_byte { + 0x00 => { + let inner = SimpleNearPromise::deserialize(buf)?; + Ok(Self::Simple(inner)) + } + 0x01 => { + let base = Self::deserialize(buf)?; + let callback = SimpleNearPromise::deserialize(buf)?; + Ok(Self::Then { + base: Box::new(base), + callback, + }) + } + 0x02 => { + let promises: Vec = Vec::deserialize(buf)?; + Ok(Self::And(promises)) + } + _ => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Invalid variant byte for NearPromise", + )), + } + } +} + +#[must_use] +#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] +pub struct PromiseCreateArgs { + pub target_account_id: AccountId, + pub method: String, + pub args: Vec, + pub attached_balance: Yocto, + pub attached_gas: NearGas, +} + +#[must_use] +#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] +pub struct PromiseWithCallbackArgs { + pub base: PromiseCreateArgs, + pub callback: PromiseCreateArgs, +} + +#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] +pub enum PromiseAction { + CreateAccount, + Transfer { + amount: Yocto, + }, + DeployContract { + code: Vec, + }, + FunctionCall { + name: String, + args: Vec, + attached_yocto: Yocto, + gas: NearGas, + }, + Stake { + amount: Yocto, + public_key: NearPublicKey, + }, + AddFullAccessKey { + public_key: NearPublicKey, + nonce: u64, + }, + AddFunctionCallKey { + public_key: NearPublicKey, + nonce: u64, + allowance: Yocto, + receiver_id: AccountId, + function_names: String, + }, + DeleteKey { + public_key: NearPublicKey, + }, + DeleteAccount { + beneficiary_id: AccountId, + }, +} + +#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] +pub enum NearPublicKey { + /// ed25519 public keys are 32 bytes + Ed25519([u8; 32]), + /// secp256k1 keys are in the uncompressed 64 byte format + Secp256k1([u8; 64]), +} + +#[must_use] +#[derive(Debug, BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq)] +pub struct PromiseBatchAction { + pub target_account_id: AccountId, + pub actions: Vec, +} + +/// withdraw NEAR eth-connector call args +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +pub struct WithdrawCallArgs { + pub recipient_address: Address, + pub amount: NEP141Wei, +} + +/// withdraw NEAR eth-connector call args +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +pub struct RefundCallArgs { + pub recipient_address: Address, + pub erc20_address: Option
, + pub amount: RawU256, +} + +/// Args passed to the the cross contract call precompile. +/// That precompile is used by Aurora contracts to make calls to the broader NEAR ecosystem. +/// See `https://github.com/aurora-is-near/AIPs/pull/2` for design details. +#[derive(Debug, BorshSerialize, BorshDeserialize)] +pub enum CrossContractCallArgs { + /// The promise is to be executed immediately (as part of the same NEAR transaction as the EVM call). + Eager(PromiseArgs), + /// The promise is to be stored in the router contract, and can be executed in a future transaction. + /// The purpose of this is to expand how much NEAR gas can be made available to a cross contract call. + /// For example, if an expensive EVM call ends with a NEAR cross contract call, then there may not be + /// much gas left to perform it. In this case, the promise could be `Delayed` (stored in the router) + /// and executed in a separate transaction with a fresh 300 Tgas available for it. + Delayed(PromiseArgs), +} diff --git a/engine-types/src/types/address.rs b/engine-types/src/types/address.rs index dfa7ce54f..da6c8a28a 100755 --- a/engine-types/src/types/address.rs +++ b/engine-types/src/types/address.rs @@ -114,9 +114,84 @@ impl Default for Address { } } +/// fn for making an address by concatenating the bytes from two given numbers, +/// Note that 32 + 128 = 160 = 20 bytes (the length of an address). This function is used +/// as a convenience for specifying the addresses of the various precompiles. +#[must_use] +pub const fn make_address(x: u32, y: u128) -> Address { + let x_bytes = x.to_be_bytes(); + let y_bytes = y.to_be_bytes(); + Address::new(H160([ + x_bytes[0], + x_bytes[1], + x_bytes[2], + x_bytes[3], + y_bytes[0], + y_bytes[1], + y_bytes[2], + y_bytes[3], + y_bytes[4], + y_bytes[5], + y_bytes[6], + y_bytes[7], + y_bytes[8], + y_bytes[9], + y_bytes[10], + y_bytes[11], + y_bytes[12], + y_bytes[13], + y_bytes[14], + y_bytes[15], + ])) +} + +pub mod error { + use crate::{fmt, String}; + + #[derive(Eq, Hash, Clone, Debug, PartialEq)] + pub enum AddressError { + FailedDecodeHex, + IncorrectLength, + } + + impl AsRef<[u8]> for AddressError { + fn as_ref(&self) -> &[u8] { + match self { + Self::FailedDecodeHex => b"FAILED_DECODE_ETH_ADDRESS", + Self::IncorrectLength => b"ETH_WRONG_ADDRESS_LENGTH", + } + } + } + + impl fmt::Display for AddressError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let msg = String::from_utf8(self.as_ref().to_vec()).unwrap(); + write!(f, "{msg}") + } + } +} + #[cfg(test)] mod tests { use super::*; + use rand::Rng; + + const fn u8_to_address(x: u8) -> Address { + let mut bytes = [0u8; 20]; + bytes[19] = x; + Address::new(H160(bytes)) + } + + // Inverse function of `super::make_address`. + fn split_address(a: Address) -> (u32, u128) { + let mut x_bytes = [0u8; 4]; + let mut y_bytes = [0u8; 16]; + + x_bytes.copy_from_slice(&a.raw()[0..4]); + y_bytes.copy_from_slice(&a.raw()[4..20]); + + (u32::from_be_bytes(x_bytes), u128::from_be_bytes(y_bytes)) + } #[test] fn test_address_serializer() { @@ -169,30 +244,18 @@ mod tests { let err = addr.unwrap_err(); matches!(err, error::AddressError::IncorrectLength); } -} - -pub mod error { - use crate::{fmt, String}; - - #[derive(Eq, Hash, Clone, Debug, PartialEq)] - pub enum AddressError { - FailedDecodeHex, - IncorrectLength, - } - impl AsRef<[u8]> for AddressError { - fn as_ref(&self) -> &[u8] { - match self { - Self::FailedDecodeHex => b"FAILED_DECODE_ETH_ADDRESS", - Self::IncorrectLength => b"ETH_WRONG_ADDRESS_LENGTH", - } + #[test] + fn test_make_address() { + for i in 0..u8::MAX { + assert_eq!(make_address(0, i.into()), u8_to_address(i)); } - } - impl fmt::Display for AddressError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let msg = String::from_utf8(self.as_ref().to_vec()).unwrap(); - write!(f, "{msg}") + let mut rng = rand::thread_rng(); + for _ in 0..u8::MAX { + let address = Address::new(H160(rng.gen())); + let (x, y) = split_address(address); + assert_eq!(address, make_address(x, y)); } } } diff --git a/engine/src/connector.rs b/engine/src/connector.rs index f8b269a16..9c1e01449 100644 --- a/engine/src/connector.rs +++ b/engine/src/connector.rs @@ -8,7 +8,9 @@ use crate::parameters::{ SetContractDataCallArgs, StorageBalanceOfCallArgs, StorageDepositCallArgs, StorageWithdrawCallArgs, TransferCallArgs, TransferCallCallArgs, WithdrawResult, }; -use crate::prelude::{address::error::AddressError, NEP141Wei, Wei, ZERO_NEP141_WEI, ZERO_WEI}; +use crate::prelude::{ + address::error::AddressError, NEP141Wei, String, Wei, ZERO_NEP141_WEI, ZERO_WEI, +}; use crate::prelude::{ format, sdk, str, AccountId, Address, BorshDeserialize, BorshSerialize, EthConnectorStorageId, KeyPrefix, NearGas, PromiseResult, ToString, Vec, WithdrawCallArgs, Yocto, ERR_FAILED_PARSE, @@ -190,7 +192,7 @@ impl EthConnectorContract { TokenMessageData::Near(account_id) => FinishDepositCallArgs { new_owner_id: account_id, amount: event.amount, - proof_key: proof.key(), + proof_key: proof_key(&proof), relayer_id: predecessor_account_id, fee: event.fee, msg: None, @@ -218,7 +220,7 @@ impl EthConnectorContract { FinishDepositCallArgs { new_owner_id: current_account_id.clone(), amount: event.amount, - proof_key: proof.key(), + proof_key: proof_key(&proof), relayer_id: predecessor_account_id, fee: event.fee, msg: Some(transfer_data), @@ -652,7 +654,7 @@ impl EthConnectorContract { /// Check whether the provided proof has already been used. pub fn is_used_proof(&self, proof: &Proof) -> bool { - self.is_used_event(&proof.key()) + self.is_used_event(&proof_key(proof)) } /// Get Eth connector paused flags @@ -892,3 +894,87 @@ pub mod error { } } } + +#[must_use] +pub fn proof_key(proof: &Proof) -> String { + let mut data = proof.log_index.try_to_vec().unwrap(); + data.extend(proof.receipt_index.try_to_vec().unwrap()); + data.extend(proof.header_data.clone()); + sdk::sha256(&data) + .0 + .iter() + .map(ToString::to_string) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::deposit_event::{DepositedEvent, TokenMessageData, DEPOSITED_EVENT}; + use aurora_engine_types::parameters::connector::LogEntry; + use aurora_engine_types::types::{make_address, Address, Fee, NEP141Wei, Wei}; + use aurora_engine_types::{H160, U256}; + + const ETH_CUSTODIAN_ADDRESS: Address = + make_address(0xd045f7e1, 0x9b2488924b97f9c145b5e51d0d895a65); + + #[test] + fn test_proof_key_generates_successfully() { + let recipient_address = Address::new(H160([22u8; 20])); + let deposit_amount = Wei::new_u64(123_456_789); + let proof = create_proof(recipient_address, deposit_amount); + + let expected_key = + "1297721518512077871939115641114233180253108247225100248224214775219368216419218177247"; + let actual_key = proof_key(&proof); + + assert_eq!(expected_key, actual_key); + } + + fn create_proof(recipient_address: Address, deposit_amount: Wei) -> Proof { + let eth_custodian_address = ETH_CUSTODIAN_ADDRESS; + + let fee = Fee::new(NEP141Wei::new(0)); + let message = ["aurora", ":", recipient_address.encode().as_str()].concat(); + let token_message_data: TokenMessageData = + TokenMessageData::parse_event_message_and_prepare_token_message_data(&message, fee) + .unwrap(); + + let deposit_event = DepositedEvent { + eth_custodian_address, + sender: Address::new(H160([0u8; 20])), + token_message_data, + amount: NEP141Wei::new(deposit_amount.raw().as_u128()), + fee, + }; + + let event_schema = ethabi::Event { + name: DEPOSITED_EVENT.into(), + inputs: DepositedEvent::event_params(), + anonymous: false, + }; + let log_entry = LogEntry { + address: eth_custodian_address.raw(), + topics: vec![ + event_schema.signature(), + // the sender is not important + crate::prelude::H256::zero(), + ], + data: ethabi::encode(&[ + ethabi::Token::String(message), + ethabi::Token::Uint(U256::from(deposit_event.amount.as_u128())), + ethabi::Token::Uint(U256::from(deposit_event.fee.as_u128())), + ]), + }; + + Proof { + log_index: 1, + // Only this field matters for the purpose of this test + log_entry_data: rlp::encode(&log_entry).to_vec(), + receipt_index: 1, + receipt_data: Vec::new(), + header_data: Vec::new(), + proof: Vec::new(), + } + } +} diff --git a/engine/src/deposit_event.rs b/engine/src/deposit_event.rs index 8a089310a..c520abfdb 100644 --- a/engine/src/deposit_event.rs +++ b/engine/src/deposit_event.rs @@ -1,10 +1,10 @@ use crate::deposit_event::error::ParseEventMessageError; -use crate::log_entry::LogEntry; use crate::prelude::account_id::AccountId; use crate::prelude::{ vec, Address, BorshDeserialize, BorshSerialize, Fee, NEP141Wei, String, ToString, Vec, U256, }; use aurora_engine_types::borsh; +use aurora_engine_types::parameters::connector::LogEntry; use aurora_engine_types::types::address::error::AddressError; use byte_slice_cast::AsByteSlice; use ethabi::{Event, EventParam, Hash, Log, ParamType, RawLog}; @@ -386,7 +386,7 @@ pub mod error { mod tests { use super::*; use crate::errors; - use aurora_engine_precompiles::make_address; + use aurora_engine_types::types::address::make_address; use aurora_engine_types::H160; #[test] diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 73edd6823..6dc2400ec 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -1755,12 +1755,11 @@ impl<'env, J: IO + Copy, E: Env, M: ModExpAlgorithm> ApplyBackend for Engine<'en mod tests { use super::*; use crate::parameters::{FunctionCallArgsV1, FunctionCallArgsV2}; - use aurora_engine_precompiles::make_address; use aurora_engine_sdk::env::Fixed; use aurora_engine_sdk::promise::Noop; use aurora_engine_test_doubles::io::{Storage, StoragePointer}; use aurora_engine_test_doubles::promise::PromiseTracker; - use aurora_engine_types::types::{Balance, NearGas, RawU256}; + use aurora_engine_types::types::{make_address, Balance, NearGas, RawU256}; use std::cell::RefCell; #[test] diff --git a/engine/src/fungible_token.rs b/engine/src/fungible_token.rs index 3af46f75a..7570e1318 100644 --- a/engine/src/fungible_token.rs +++ b/engine/src/fungible_token.rs @@ -10,8 +10,8 @@ use crate::prelude::{ }; use aurora_engine_sdk::io::{StorageIntermediate, IO}; use aurora_engine_types::borsh; +pub use aurora_engine_types::parameters::connector::FungibleTokenMetadata; use aurora_engine_types::types::{NEP141Wei, Yocto, ZERO_NEP141_WEI, ZERO_YOCTO}; -use serde::{Deserialize, Serialize}; /// Gas for `resolve_transfer`: 5 `TGas` const GAS_FOR_RESOLVE_TRANSFER: NearGas = NearGas::new(5_000_000_000_000); @@ -56,50 +56,6 @@ pub struct FungibleTokenOps { io: I, } -/// Fungible token Reference hash type. -/// Used for `FungibleTokenMetadata` -#[derive(Debug, BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, PartialEq, Eq)] -pub struct FungibleReferenceHash([u8; 32]); - -impl FungibleReferenceHash { - /// Encode to base64-encoded string - #[must_use] - pub fn encode(&self) -> String { - aurora_engine_sdk::base64::encode(self) - } -} - -impl AsRef<[u8]> for FungibleReferenceHash { - fn as_ref(&self) -> &[u8] { - &self.0 - } -} - -#[derive(Debug, BorshDeserialize, BorshSerialize, Serialize, Deserialize, Clone, PartialEq, Eq)] -pub struct FungibleTokenMetadata { - pub spec: String, - pub name: String, - pub symbol: String, - pub icon: Option, - pub reference: Option, - pub reference_hash: Option, - pub decimals: u8, -} - -impl Default for FungibleTokenMetadata { - fn default() -> Self { - Self { - spec: "ft-1.0.0".to_string(), - name: "Ether".to_string(), - symbol: "ETH".to_string(), - icon: Some("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAs3SURBVHhe7Z1XqBQ9FMdFsYu999577wUfbCiiPoggFkQsCKJP9t57V7AgimLBjg8qKmLBXrD33hVUEAQ1H7+QXMb9Zndnd+/MJJf7h8Pu3c3Mzua3yTk5SeZmEZkySplADFMmEMOUCcQwZQggHz58EHfu3FF/2a0MAWTjxo2iWbNm6i+7ZT2QW7duiUWLFolixYqJQ4cOqVftlfVAZs6cKdauXSuqV68uKlWqpF61V1YDoUXMmTNHrFu3TtSoUUNCmTBhgnrXTlkL5Nu3b2Ly5MmyuwJIzZo1RaNGjUTx4sXFu3fvVCn7ZC2QVatWiQULFvwPSL169USnTp1UKftkJZCbN2+KGTNmSBiLFy/+BwhWoUIFsX//flXaLlkJZPr06WkwIoE0btxYNGzYUFSsWFGVtkvWATlw4IB05BqGGxAMBz9u3Dh1lD2yCsjXr1/THHk8IDwvVaqUeP36tTraDlkFZOXKldKRO2HEAoKD79ixozraDlkD5Pr16/848nhANBQc/N69e9VZzJc1QCIduRcgGA4eKLbICiD79u37nyN3WiwgvMZ7Y8eOVWczW8YDwZFPmTIlauvA4gHhsUSJEuLFixfqrObKeCArVqxwdeROiwUE43UcfNu2bdVZzZXRQK5duyYduRsEp8UDog1fsnPnTnV2M2U0kFiO3GlegeDgy5cvr85upowFQqg6d+5cVwCR5hUI71NuzJgx6lPMk5FAPn365Doij2ZegWCUIUX/9OlT9WlmyUggy5Yti+vInZYIEAwH37JlS/VpZsk4IJcvX5bTsl5bB5YoEMqRDd62bZv6VHNkHJBp06YlBANLFAiGgy9btqz6VHNkFJBdu3Z5duROSwYIxjEjRoxQn26GjAHy8ePHuCPyaJYsEMozgn/48KG6ivBlDJAlS5Yk5MidlgqQ+vXri+bNm6urCF9GALl48aJ05G6V7cWSBYJxDOu5Nm/erK4mXBkBJBlH7rRUgGAmOfjQgZBbSsaROy1VIBjHDxs2TF1VeAoVyPv37+WI3K2SE7H0AMKxJUuWFHfv3lVXF45CBZKKI3daegDBcPBNmzZVVxeOQgNy/vz5hEfkbsbxAGFtb6pAOL5y5cpye0NYCg1Iqo5c29KlS2WEVKdOHdGkSZOUoeDgS5cura4yeIUCZMeOHWLevHkpASEBScvAB/Xs2VMUKVJE1K1bV44pUgHDcbVq1RJDhgxRVxusAgfy5s0bMXXq1IRgOMsuX75c7gcZP368aN++vez3W7VqJfLnzy8KFCggU+tUKNncZMFwDA6eNcRBK3AgCxculOas8HiG82duffXq1WLkyJGiRYsWokGDBrI1UPHMlQOjaNGisqUUKlRIPrKclLKA0RUdWfnRDNCUD1qBAjl79qyYNWuWa6VHGq0CEGw7oHsaNGiQrCBMg9DmBKJNgylYsKAciQOFfYhUtlcwHEe3GKQCA/Lnzx/PyUMc9Zo1a+SAsV+/fvLXSgXxa3eCiAXECaZw4cISDPPpGijniweG93HwXHtQCgwIk0E4cjcAGhItAf8AuG7dukknzbgAENFgYLGAaNNgKMcibGYNdXdGxUeDgz8aOHCg+hb+KxAgr169kpUcCUKb01GzOJrKonuJB0KbFyBOAw4thgCgdu3aaWAA4AYGB8/a4iAUCBBG405Hrv2Dm6MGhFulx7JEgWjTYHisVq2a/GxapBMGgLguLAj5DuTMmTP/OHLtqPETdAW6u4h01IlYskC06e6MIICROlA0GH19vM51+y1fgfz+/TvNkWtHjR/p27ev7JboJrx2S7EsVSAYUDCgcC4CAEbtXJsGg4PnO/kpX4Fs3bpVwiB0BEz37t09O+pELD2AOE23GM5ZpkwZGeVxraRnBgwYoL6dP/INCCNyfAeOukOHDmmZVLcKTdXSG4jTNBidAaDlXLlyRX3L9JdvQPr06SObvHbU6dUa3MxPINp0d5Y3b16RJ08e9S3TX74Befz4sejcubOoWrWqdNi2AgEEj8DIkiWLdO4PHjxQ3zL95asPQQcPHpSTR/gOv6D4BUQ7+uzZs4usWbOK7du3q2/ln3wHosU+j3LlysmIxa1SUzG/gOTLl0+2ilGjRqlv4b8CA4K+fPkievXqJZt9MgPAaJbeQHT3hA9kJX6QChSI1smTJ+U4RKct3Co5EUsvIHRP2bJlEzlz5hRHjhxRVxusfANy4cIF9Sy6GLnrAZhbRXu1VIEAguiJVuHlfltbtmxRz9JfvgHhxpQMBt++fatecdfPnz/lYIvtAcmOU1IBQi4LEG3atJHXEkssEWK0fvv2bfVK+svXLosJKW4AQ3QSb07h6tWr0uEz+Eq0G0sGCAM+IieOI98WS3///hVDhw4VOXLkkAlRP+W7D9mwYYNMLtJa4n1xRBqe3bIMKL2CSQQI3VPu3Lllq+C64olsNPMnBCJdunRRr/qnQJw6IS/pdypg/vz5cff38YscPny49C9eujGvQCgDiB49eqhPii4WgJPuAQQ+Lqi1v4EAefToUVrWFzCsyWIx2q9fv1QJd92/f1+0bt1aLlaINdqPB4TuCRD80rmtbCzhR8hG66SizvKeOHFClfBXgQBBe/bskfcr0dO1pOFZU3Xs2DFVIrqY/q1SpUpa1tUrELqnXLlySRhe5jKYw2d2kHBcz4OwIjLIXVaBAUF0V5Ezh7Nnz5Z27949VSq6CBDoOphHiQYECDyyTgsQ/fv3V0dH1/Hjx2V6h7wbEAguMH4ABBlBKlAgbneE090Yd21Yv369+P79uyrtrpcvX/6TtIwEorsnlvA8efJEHeUuRuFdu3aVKR2CCCcMnpNyf/78uSodjAIFgk6fPh11txQtCGBebhlO0pLuhKSlBkISEBhMjMXTxIkTZYVzvBOEhgFQriloBQ4EEUrGWhKEryEyu3HjhjoiuggWqDxAeOnrufcW5QkUIkFoGEBiUi0MhQKEeel4q995DyjcZ/Hz58/qSHfRrcTbSUuZdu3ayTEOYawbDIz3iLDiRYB+KRQgiP/3waJrNxjagMI0MK2AKC1ZjR49Wm5/JqEZDQTGe8A4fPiwOjJ4hQYEsS3By/5CwFCOVsWAzatIAhKVed3MQznWEIepUIEg/IUzFI5lgCEgYG1XrKQlyT9CY3wFXZBb5UcaURZ+JWyFDoSs8KRJk2L6E6dRDoB0YyQtneukSGAOHjxYDu70KNut8iONckRcJvzbpNCBIAZmXrcpYBoekRpgyBQzhiE1wkDOKwiMsuSr6BJNkBFAENEU45DIyo9nwGGxNs44ERAY5QlxmQsxRcYAIcxMdKubtmS3RVOe7u3Hjx/qKsKXMUAQA0EiKbdKj2XJAiEC2717t/p0M2QUEETaw0so7LREgVCO8l4Sj0HLOCAIB+81FMYSAUIZQmGSkybKSCAs1I7MCseyRIEwaveSJwtDRgJBR48e9RwKewXC+0x0AdtUGQsEMSL3cnMaL0B4j1wWc/Qmy2ggzG/ruXg3ENq8AmHgyCSZyTIaCLp06VLce8DHA8LrrGDxMnEVtowHgjZt2hR1QguLB4R0Su/evdXZzJYVQJBe25UoELK4Nv1PQ2uAPHv2LKo/iQaEv0mNeFn4bYqsAYL4p5IsGfIChOfMb7Dp1CZZBQTRQiJDYTcgerrWNlkHhHVbkV1XJBAemXDirqe2yTog6Ny5c9LJayhOIBgrS1h1b6OsBIKocB0KO4FwtwVu7WSrrAWC9NouDYQsLstCbZbVQNjmwCwjQFjCwzTuqVOn1Lt2ymogiBk/PafOfbdsl/VAEEBs+gfEsZQhgDChxVKgjKAMASQjKROIYcoEYpgygRglIf4D6lp/+XognSwAAAAASUVORK5CYII=".to_string()), - reference: None, - reference_hash: None, - decimals: 18, - } - } -} - impl FungibleTokenOps { pub fn new(io: I) -> Self { FungibleToken::default().ops(io) diff --git a/engine/src/lib.rs b/engine/src/lib.rs index da4935da8..5b8edbcb8 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -20,9 +20,13 @@ extern crate alloc; extern crate core; mod map; -pub mod parameters; -pub mod proof; - +pub mod parameters { + pub use aurora_engine_types::parameters::connector::*; + pub use aurora_engine_types::parameters::engine::*; +} +pub mod proof { + pub use aurora_engine_types::parameters::connector::Proof; +} pub mod accounting; pub mod admin_controlled; #[cfg_attr(feature = "contract", allow(dead_code))] @@ -31,7 +35,6 @@ pub mod deposit_event; pub mod engine; pub mod errors; pub mod fungible_token; -pub mod log_entry; pub mod pausables; mod prelude; pub mod state; @@ -78,11 +81,9 @@ mod contract { use crate::connector::{self, EthConnectorContract}; use crate::engine::{self, Engine}; - use crate::fungible_token::FungibleTokenMetadata; - use crate::parameters::error::ParseTypeFromJsonError; use crate::parameters::{ - self, CallArgs, DeployErc20TokenArgs, GetErc20FromNep141CallArgs, GetStorageAtArgs, - InitCallArgs, IsUsedProofCallArgs, NEP141FtOnTransferArgs, NewCallArgs, + self, CallArgs, DeployErc20TokenArgs, FungibleTokenMetadata, GetErc20FromNep141CallArgs, + GetStorageAtArgs, InitCallArgs, IsUsedProofCallArgs, NEP141FtOnTransferArgs, NewCallArgs, PauseEthConnectorCallArgs, PausePrecompilesCallArgs, ResolveTransferCallArgs, SetContractDataCallArgs, StorageDepositCallArgs, StorageWithdrawCallArgs, SubmitArgs, TransferCallCallArgs, ViewCallArgs, @@ -106,6 +107,7 @@ mod contract { use aurora_engine_sdk::near_runtime::{Runtime, ViewEnv}; use aurora_engine_sdk::promise::PromiseHandler; use aurora_engine_types::borsh::{BorshDeserialize, BorshSerialize}; + use aurora_engine_types::parameters::engine::errors::ParseTypeFromJsonError; #[cfg(feature = "integration-test")] use crate::prelude::NearGas; diff --git a/engine/src/log_entry.rs b/engine/src/log_entry.rs deleted file mode 100644 index 8af2ee1e2..000000000 --- a/engine/src/log_entry.rs +++ /dev/null @@ -1,56 +0,0 @@ -use crate::prelude::{Vec, H160, H256}; - -#[derive(Default, Debug, Clone, PartialEq, Eq)] -pub struct LogEntry { - pub address: H160, - pub topics: Vec, - pub data: Vec, -} - -impl rlp::Decodable for LogEntry { - fn decode(rlp: &rlp::Rlp) -> Result { - let result = Self { - address: rlp.val_at(0usize)?, - topics: rlp.list_at(1usize)?, - data: rlp.val_at(2usize)?, - }; - Ok(result) - } -} - -impl rlp::Encodable for LogEntry { - fn rlp_append(&self, stream: &mut rlp::RlpStream) { - stream.begin_list(3usize); - stream.append(&self.address); - stream.append_list::(&self.topics); - stream.append(&self.data); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use rlp::{Decodable, Encodable, Rlp, RlpStream}; - - #[test] - fn test_roundtrip_rlp_encoding() { - let address = H160::from_low_u64_le(32u64); - let topics = vec![H256::zero()]; - let data = vec![0u8, 1u8, 2u8, 3u8]; - let expected_log_entry = LogEntry { - address, - topics, - data, - }; - - let mut stream = RlpStream::new(); - - expected_log_entry.rlp_append(&mut stream); - - let bytes = stream.out(); - let rlp = Rlp::new(bytes.as_ref()); - let actual_log_entry = LogEntry::decode(&rlp).unwrap(); - - assert_eq!(expected_log_entry, actual_log_entry); - } -} diff --git a/engine/src/parameters.rs b/engine/src/parameters.rs deleted file mode 100644 index 5557b2a90..000000000 --- a/engine/src/parameters.rs +++ /dev/null @@ -1,302 +0,0 @@ -use crate::admin_controlled::PausedMask; -use crate::fungible_token::FungibleTokenMetadata; -use crate::prelude::account_id::AccountId; -use crate::prelude::{Address, Balance, BorshDeserialize, BorshSerialize, RawU256, String, Vec}; -use crate::proof::Proof; -use aurora_engine_types::borsh; -pub use aurora_engine_types::parameters::engine::{ - CallArgs, DeployErc20TokenArgs, FunctionCallArgsV1, FunctionCallArgsV2, - GetErc20FromNep141CallArgs, GetStorageAtArgs, ResultLog, SubmitResult, TransactionStatus, - ViewCallArgs, -}; -use aurora_engine_types::types::{Fee, NEP141Wei, Yocto}; -use serde::{Deserialize, Serialize}; - -/// Parameters for the `new` function. -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -pub enum NewCallArgs { - V1(LegacyNewCallArgs), - V2(NewCallArgsV2), -} - -impl NewCallArgs { - pub fn deserialize(bytes: &[u8]) -> Result { - Self::try_from_slice(bytes).map_or_else( - |_| LegacyNewCallArgs::try_from_slice(bytes).map(Self::V1), - Ok, - ) - } -} - -/// Old Borsh-encoded parameters for the `new` function. -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -pub struct LegacyNewCallArgs { - /// Chain id, according to the EIP-115 / ethereum-lists spec. - pub chain_id: RawU256, - /// Account which can upgrade this contract. - /// Use empty to disable updatability. - pub owner_id: AccountId, - /// Account of the bridge prover. - /// Use empty to not use base token as bridged asset. - pub bridge_prover_id: AccountId, - /// How many blocks after staging upgrade can deploy it. - pub upgrade_delay_blocks: u64, -} - -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -pub struct NewCallArgsV2 { - /// Chain id, according to the EIP-115 / ethereum-lists spec. - pub chain_id: RawU256, - /// Account which can upgrade this contract. - /// Use empty to disable updatability. - pub owner_id: AccountId, - /// How many blocks after staging upgrade can deploy it. - pub upgrade_delay_blocks: u64, -} - -/// Borsh-encoded parameters for the `set_owner` function. -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] -pub struct SetOwnerArgs { - pub new_owner: AccountId, -} - -/// Borsh-encoded parameters for the `set_upgrade_delay_blocks` function. -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] -pub struct SetUpgradeDelayBlocksArgs { - pub upgrade_delay_blocks: u64, -} - -/// Borsh-encoded (genesis) account balance used by the `begin_chain` function. -#[cfg(feature = "evm_bully")] -#[derive(BorshSerialize, BorshDeserialize)] -pub struct AccountBalance { - pub address: Address, - pub balance: RawU256, -} - -/// Borsh-encoded submit arguments used by the `submit_with_args` function. -#[derive(Default, Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -pub struct SubmitArgs { - /// Bytes of the transaction. - pub tx_data: Vec, - /// Max gas price the user is ready to pay for the transaction. - pub max_gas_price: Option, - /// Address of the `ERC20` token the user prefers to pay in. - pub gas_token_address: Option
, -} - -/// Borsh-encoded parameters for the `begin_chain` function. -#[cfg(feature = "evm_bully")] -#[derive(BorshSerialize, BorshDeserialize)] -pub struct BeginChainArgs { - pub chain_id: RawU256, - pub genesis_alloc: Vec, -} - -/// Borsh-encoded parameters for the `begin_block` function. -#[cfg(feature = "evm_bully")] -#[derive(BorshSerialize, BorshDeserialize)] -pub struct BeginBlockArgs { - /// The current block's hash (for replayer use). - pub hash: RawU256, - /// The current block's beneficiary address. - pub coinbase: Address, - /// The current block's timestamp (in seconds since the Unix epoch). - pub timestamp: RawU256, - /// The current block's number (the genesis block is number zero). - pub number: RawU256, - /// The current block's difficulty. - pub difficulty: RawU256, - /// The current block's gas limit. - pub gaslimit: RawU256, -} - -/// Borsh-encoded parameters for the `ft_transfer_call` function -/// for regular NEP-141 tokens. -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq)] -pub struct NEP141FtOnTransferArgs { - pub sender_id: AccountId, - /// Balance can be for Eth on Near and for Eth to Aurora - /// `ft_on_transfer` can be called with arbitrary NEP-141 tokens attached, therefore we do not specify a particular type Wei. - pub amount: Balance, - pub msg: String, -} - -/// Eth-connector deposit arguments -#[derive(BorshSerialize, BorshDeserialize)] -pub struct DepositCallArgs { - /// Proof data - pub proof: Proof, - /// Optional relayer address - pub relayer_eth_account: Option
, -} - -/// Eth-connector `isUsedProof` arguments -#[derive(BorshSerialize, BorshDeserialize)] -pub struct IsUsedProofCallArgs { - /// Proof data - pub proof: Proof, -} - -/// withdraw result for eth-connector -#[derive(BorshSerialize)] -#[cfg_attr(not(target_arch = "wasm32"), derive(BorshDeserialize))] -pub struct WithdrawResult { - pub amount: NEP141Wei, - pub recipient_id: Address, - pub eth_custodian_address: Address, -} - -/// Fungible token storage balance -#[derive(Default, Deserialize, Serialize)] -pub struct StorageBalance { - pub total: Yocto, - pub available: Yocto, -} - -impl StorageBalance { - #[must_use] - pub fn to_json_bytes(&self) -> Vec { - serde_json::to_vec(self).unwrap_or_default() - } -} - -/// `ft_resolve_transfer` eth-connector call args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -pub struct ResolveTransferCallArgs { - pub sender_id: AccountId, - pub amount: NEP141Wei, - pub receiver_id: AccountId, -} - -/// Finish deposit NEAR eth-connector call args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -pub struct FinishDepositCallArgs { - pub new_owner_id: AccountId, - pub amount: NEP141Wei, - pub proof_key: String, - pub relayer_id: AccountId, - pub fee: Fee, - pub msg: Option>, -} - -/// Deposit ETH args -#[derive(Default, BorshDeserialize, BorshSerialize, Clone)] -pub struct DepositEthCallArgs { - pub proof: Proof, - pub relayer_eth_account: Address, -} - -/// Finish deposit NEAR eth-connector call args -#[derive(BorshSerialize, BorshDeserialize)] -pub struct FinishDepositEthCallArgs { - pub new_owner_id: Address, - pub amount: NEP141Wei, - pub fee: Balance, - pub relayer_eth_account: AccountId, - pub proof: Proof, -} - -/// Eth-connector initial args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -pub struct InitCallArgs { - pub prover_account: AccountId, - pub eth_custodian_address: String, - pub metadata: FungibleTokenMetadata, -} - -/// Eth-connector Set contract data call args -pub type SetContractDataCallArgs = InitCallArgs; - -/// transfer eth-connector call args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq)] -pub struct TransferCallCallArgs { - pub receiver_id: AccountId, - pub amount: NEP141Wei, - pub memo: Option, - pub msg: String, -} - -/// `storage_balance_of` eth-connector call args -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize)] -pub struct StorageBalanceOfCallArgs { - pub account_id: AccountId, -} - -/// `storage_deposit` eth-connector call args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq)] -pub struct StorageDepositCallArgs { - pub account_id: Option, - pub registration_only: Option, -} - -/// `storage_withdraw` eth-connector call args -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq)] -pub struct StorageWithdrawCallArgs { - pub amount: Option, -} - -/// transfer args for json invocation -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq)] -pub struct TransferCallArgs { - pub receiver_id: AccountId, - pub amount: NEP141Wei, - pub memo: Option, -} - -/// `balance_of` args for json invocation -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] -pub struct BalanceOfCallArgs { - pub account_id: AccountId, -} - -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] -pub struct BalanceOfEthCallArgs { - pub address: Address, -} - -#[derive(BorshSerialize, BorshDeserialize)] -pub struct RegisterRelayerCallArgs { - pub address: Address, -} - -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] -pub struct PauseEthConnectorCallArgs { - pub paused_mask: PausedMask, -} - -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, PartialEq, Eq)] -pub struct PausePrecompilesCallArgs { - pub paused_mask: u32, -} - -pub mod error { - use aurora_engine_types::{account_id::ParseAccountError, String, ToString}; - - #[derive(Debug)] - pub enum ParseTypeFromJsonError { - Json(String), - InvalidAccount(ParseAccountError), - } - - impl From for ParseTypeFromJsonError { - fn from(e: serde_json::Error) -> Self { - Self::Json(e.to_string()) - } - } - - impl From for ParseTypeFromJsonError { - fn from(e: ParseAccountError) -> Self { - Self::InvalidAccount(e) - } - } - - impl AsRef<[u8]> for ParseTypeFromJsonError { - fn as_ref(&self) -> &[u8] { - match self { - Self::Json(e) => e.as_bytes(), - Self::InvalidAccount(e) => e.as_ref(), - } - } - } -} diff --git a/engine/src/proof.rs b/engine/src/proof.rs deleted file mode 100644 index 85307d5cf..000000000 --- a/engine/src/proof.rs +++ /dev/null @@ -1,100 +0,0 @@ -use crate::prelude::{sdk, BorshDeserialize, BorshSerialize, String, ToString, Vec}; -use aurora_engine_types::borsh; - -#[derive(Debug, Default, BorshDeserialize, BorshSerialize, Clone)] -#[cfg_attr(feature = "impl-serde", derive(serde::Deserialize, serde::Serialize))] -pub struct Proof { - pub log_index: u64, - pub log_entry_data: Vec, - pub receipt_index: u64, - pub receipt_data: Vec, - pub header_data: Vec, - pub proof: Vec>, -} - -impl Proof { - #[must_use] - pub fn key(&self) -> String { - let mut data = self.log_index.try_to_vec().unwrap(); - data.extend(self.receipt_index.try_to_vec().unwrap()); - data.extend(self.header_data.clone()); - sdk::sha256(&data) - .0 - .iter() - .map(ToString::to_string) - .collect() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::deposit_event::{DepositedEvent, TokenMessageData, DEPOSITED_EVENT}; - use crate::log_entry::LogEntry; - use aurora_engine_precompiles::make_address; - use aurora_engine_types::types::{Address, Fee, NEP141Wei, Wei}; - use aurora_engine_types::{H160, U256}; - - const ETH_CUSTODIAN_ADDRESS: Address = - make_address(0xd045f7e1, 0x9b2488924b97f9c145b5e51d0d895a65); - - #[test] - fn test_proof_key_generates_successfully() { - let recipient_address = Address::new(H160([22u8; 20])); - let deposit_amount = Wei::new_u64(123_456_789); - let proof = create_proof(recipient_address, deposit_amount); - - let expected_key = - "1297721518512077871939115641114233180253108247225100248224214775219368216419218177247"; - let actual_key = proof.key(); - - assert_eq!(expected_key, actual_key); - } - - fn create_proof(recipient_address: Address, deposit_amount: Wei) -> Proof { - let eth_custodian_address = ETH_CUSTODIAN_ADDRESS; - - let fee = Fee::new(NEP141Wei::new(0)); - let message = ["aurora", ":", recipient_address.encode().as_str()].concat(); - let token_message_data: TokenMessageData = - TokenMessageData::parse_event_message_and_prepare_token_message_data(&message, fee) - .unwrap(); - - let deposit_event = DepositedEvent { - eth_custodian_address, - sender: Address::new(H160([0u8; 20])), - token_message_data, - amount: NEP141Wei::new(deposit_amount.raw().as_u128()), - fee, - }; - - let event_schema = ethabi::Event { - name: DEPOSITED_EVENT.into(), - inputs: DepositedEvent::event_params(), - anonymous: false, - }; - let log_entry = LogEntry { - address: eth_custodian_address.raw(), - topics: vec![ - event_schema.signature(), - // the sender is not important - crate::prelude::H256::zero(), - ], - data: ethabi::encode(&[ - ethabi::Token::String(message), - ethabi::Token::Uint(U256::from(deposit_event.amount.as_u128())), - ethabi::Token::Uint(U256::from(deposit_event.fee.as_u128())), - ]), - }; - - Proof { - log_index: 1, - // Only this field matters for the purpose of this test - log_entry_data: rlp::encode(&log_entry).to_vec(), - receipt_index: 1, - receipt_data: Vec::new(), - header_data: Vec::new(), - proof: Vec::new(), - } - } -} diff --git a/etc/xcc-router/Cargo.lock b/etc/xcc-router/Cargo.lock index a4bd9ebae..c520814a7 100644 --- a/etc/xcc-router/Cargo.lock +++ b/etc/xcc-router/Cargo.lock @@ -41,10 +41,12 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" name = "aurora-engine-types" version = "1.0.0" dependencies = [ + "base64 0.21.2", "borsh 0.10.2", "borsh 0.9.3", "hex", "primitive-types 0.12.1", + "rlp", "serde", "serde_json", ] @@ -67,6 +69,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + [[package]] name = "bitvec" version = "0.20.4" From 47f9691eb1d0c82e9d0a55f5802910c88164fff6 Mon Sep 17 00:00:00 2001 From: Oleksandr Anyshchenko Date: Wed, 21 Jun 2023 09:42:53 +0200 Subject: [PATCH 09/13] chore: add bench-modexp flow to CI script (#762) ## Description The goal of the PR is to speed up passing CI flow. Also, it adds an additional job for testing the `bech_modexp` flow. --- .github/workflows/lints.yml | 2 -- .github/workflows/tests.yml | 23 +++++++++++++++++++++++ Makefile.toml | 15 ++++++++++++--- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 90162f3b2..a096430aa 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -31,8 +31,6 @@ jobs: - run: cargo make build-contracts - name: Run Contract cargo clippy run: cargo make clippy - - name: Run cargo clippy - run: cargo clippy udeps: name: Udeps runs-on: [self-hosted, heavy] diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d3f5ea72b..c1047ada0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -41,6 +41,29 @@ jobs: run: | cache-util save cargo_git cargo_registry yarn_cache cache-util msave aurora-engine-target@generic@${{ hashFiles('**/Cargo.lock') }}:target + + test_modexp: + name: Test modexp suite (mainnet, testnet) + runs-on: [ self-hosted, heavy ] + steps: + - name: Potential broken submodules fix + run: | + git checkout -f $(git -c user.name=x -c user.email=x@x commit-tree $(git hash-object -t tree /dev/null) < /dev/null) || : + - name: Clone the repository + uses: actions/checkout@v3 + - name: Restore cache + run: | + cache-util restore cargo_git cargo_registry yarn_cache + cache-util restore aurora-engine-target@generic@${{ hashFiles('**/Cargo.lock') }}:target + - name: Test mainnet bench-modexp + run: cargo make --profile mainnet bench-modexp + - name: Test testnet bench-modexp + run: cargo make --profile testnet bench-modexp + - name: Save cache + run: | + cache-util save cargo_git cargo_registry yarn_cache + cache-util msave aurora-engine-target@generic@${{ hashFiles('**/Cargo.lock') }}:target + env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 diff --git a/Makefile.toml b/Makefile.toml index cf3c8e760..0734de4b1 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -333,7 +333,7 @@ args = [ "${CARGO_FEATURES_TEST}", ] -[tasks.bench-modexp] +[tasks.bench-modexp-test] condition = { profiles = ["mainnet", "testnet", "custom"] } category = "Test" command = "${CARGO}" @@ -353,12 +353,21 @@ dependencies = [ "build-test", "test-contracts", "test-workspace", - "bench-modexp", +] + +[tasks.bench-modexp] +category = "Test" +dependencies = [ + "build-test", + "bench-modexp-test", ] [tasks.test] category = "Test" -run_task = "test-flow" +dependencies = [ + "test-flow", + "bench-modexp-test", +] [tasks.default] condition = { profiles = ["mainnet", "testnet", "localnet", "development", "custom"] } From bf5605c79d76fa9e4ac18d0eb970c1e3d20fad1f Mon Sep 17 00:00:00 2001 From: Alexey Lapitsky Date: Wed, 21 Jun 2023 20:32:07 +0200 Subject: [PATCH 10/13] chore(backstage): add testnet address (#761) ## Description ## Performance / NEAR gas cost considerations ## Testing ## How should this be reviewed ## Additional information --- engine/.catalog-info.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/.catalog-info.yaml b/engine/.catalog-info.yaml index 069046f3f..c56f6eb86 100644 --- a/engine/.catalog-info.yaml +++ b/engine/.catalog-info.yaml @@ -19,4 +19,5 @@ spec: system: aurora-engine deployedAt: - contract:near/mainnet/aurora + - contract:near/testnet/aurora interactsWith: [] From 9ddcc8c7af3a9640717cdbaa9a7447eea035b5fe Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Wed, 21 Jun 2023 15:18:59 -0400 Subject: [PATCH 11/13] Fix(modexp): use ibig implementation (#778) ## Description Switch to using the `ibig` implementation for modexp. Its performance is better than current Aurora implementation in some (but not all) cases, and it is more battle-tested in terms of correctness. --- engine-modexp/Cargo.toml | 6 +++--- engine-modexp/src/lib.rs | 3 +-- engine-tests/src/tests/modexp.rs | 4 ++-- engine-tests/src/tests/repro.rs | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/engine-modexp/Cargo.toml b/engine-modexp/Cargo.toml index f8f24fe9a..f6a83cb4d 100644 --- a/engine-modexp/Cargo.toml +++ b/engine-modexp/Cargo.toml @@ -13,7 +13,7 @@ publish = false autobenches = false [dependencies] -ibig = { version = "0.3.6", default-features = false, features = ["num-traits"], optional = true } +ibig = { version = "0.3.6", default-features = false, features = ["num-traits"] } num = { version = "0.4.0", default-features = false, features = ["alloc"] } hex = { version = "0.4", default-features = false, features = ["alloc"] } @@ -21,5 +21,5 @@ hex = { version = "0.4", default-features = false, features = ["alloc"] } [features] default = ["std"] -std = ["num/std", "hex/std"] -bench = ["ibig"] +std = ["num/std", "ibig/std", "hex/std"] +bench = [] diff --git a/engine-modexp/src/lib.rs b/engine-modexp/src/lib.rs index 6bd08fa21..fbb5ff2ba 100644 --- a/engine-modexp/src/lib.rs +++ b/engine-modexp/src/lib.rs @@ -21,7 +21,7 @@ pub struct AuroraModExp; impl ModExpAlgorithm for AuroraModExp { fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec { - modexp(base, exp, modulus) + modexp_ibig(base, exp, modulus) } } @@ -37,7 +37,6 @@ pub fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec { result.to_big_endian() } -#[cfg(feature = "bench")] pub fn modexp_ibig(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec { use num::Zero; diff --git a/engine-tests/src/tests/modexp.rs b/engine-tests/src/tests/modexp.rs index fa581ad7c..7fcbfe7af 100644 --- a/engine-tests/src/tests/modexp.rs +++ b/engine-tests/src/tests/modexp.rs @@ -135,11 +135,11 @@ fn bench_modexp_standalone() { &mut signer, "../etc/tests/modexp-bench/res/evm_contract_1.hex", ); - do_bench( + /*do_bench( // TODO: re-enable this in the future &mut standalone, &mut signer, "../etc/tests/modexp-bench/res/evm_contract_2.hex", - ); + );*/ } #[test] diff --git a/engine-tests/src/tests/repro.rs b/engine-tests/src/tests/repro.rs index f39479122..3d4d37c6c 100644 --- a/engine-tests/src/tests/repro.rs +++ b/engine-tests/src/tests/repro.rs @@ -126,7 +126,7 @@ fn repro_Emufid2() { block_timestamp: 1_662_118_048_636_713_538, input_path: "src/tests/res/input_Emufid2.hex", evm_gas_used: 1_156_364, - near_gas_used: 296, + near_gas_used: 285, }); } From 30926b1b494274be2ff26eda4b6b84c884ac57d6 Mon Sep 17 00:00:00 2001 From: "Joshua J. Bouw" Date: Thu, 22 Jun 2023 21:28:51 +0700 Subject: [PATCH 12/13] release: 2.9.2 release notes and details (#782) ## Description Release notes for 2.9.2. I am doing this first to develop intentionally, to prevent back porting later. --- CHANGES.md | 8 ++++++++ VERSION | 2 +- engine/Cargo.toml | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4630676fa..307b3e827 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [2.9.2] 2023-06-22 + +### Fixes + +- Use ibig implemenation of modexp by [@birchmd]. ([#778]) + +[#778]: https://github.com/aurora-is-near/aurora-engine/pull/778 + ## [2.9.1] 2023-05-11 ### Changes diff --git a/VERSION b/VERSION index dedcc7d43..5d9ade10c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.9.1 +2.9.2 diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 41f09a551..7b70d93b3 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aurora-engine" -version = "2.9.1" +version = "2.9.2" authors = ["Aurora Labs "] edition = "2021" description = "" From a06da38f350244672184e0d8371e8eae069ede69 Mon Sep 17 00:00:00 2001 From: "Joshua J. Bouw" Date: Thu, 22 Jun 2023 23:47:42 +0700 Subject: [PATCH 13/13] chore: fix changelog links for 2.9.2 (#784) ## Description Adding links was missed in the changelog for 2.9.2 release, adding in those now. --- CHANGES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 307b3e827..22402723e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -421,7 +421,8 @@ struct SubmitResult { ## [1.0.0] - 2021-05-12 -[Unreleased]: https://github.com/aurora-is-near/aurora-engine/compare/2.9.1...develop +[Unreleased]: https://github.com/aurora-is-near/aurora-engine/compare/2.9.2...develop +[2.9.2]: https://github.com/aurora-is-near/aurora-engine/compare/2.9.1...2.9.2 [2.9.1]: https://github.com/aurora-is-near/aurora-engine/compare/2.9.0...2.9.1 [2.9.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.8.0...2.9.0 [2.8.0]: https://github.com/aurora-is-near/aurora-engine/compare/2.7.0...2.8.0