diff --git a/Cargo.lock b/Cargo.lock index 5d4bfcc649..fde29f78c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1448,7 +1448,7 @@ dependencies = [ "darwinia-support", "frame-support", "frame-system", - "libsecp256k1", + "libsecp256k1 0.3.5", "log", "parity-scale-codec", "serde", @@ -1652,9 +1652,9 @@ dependencies = [ "darwinia-balances", "darwinia-support", "dp-evm", - "evm", - "evm-gasometer", - "evm-runtime", + "evm 0.27.0", + "evm-gasometer 0.27.0", + "evm-runtime 0.27.0", "frame-support", "frame-system", "log", @@ -1675,7 +1675,7 @@ name = "darwinia-evm-precompile-blake2" version = "2.5.0" dependencies = [ "dp-evm", - "evm", + "evm 0.27.0", "sp-core", "sp-io", ] @@ -1685,7 +1685,7 @@ name = "darwinia-evm-precompile-bn128" version = "2.5.0" dependencies = [ "dp-evm", - "evm", + "evm 0.27.0", "sp-core", "sp-io", "substrate-bn", @@ -1697,7 +1697,7 @@ version = "2.5.0" dependencies = [ "curve25519-dalek 3.1.0", "dp-evm", - "evm", + "evm 0.27.0", "sp-core", "sp-io", ] @@ -1708,7 +1708,7 @@ version = "2.5.0" dependencies = [ "darwinia-evm", "dp-evm", - "evm", + "evm 0.27.0", "frame-support", "parity-scale-codec", "sp-core", @@ -1721,7 +1721,7 @@ version = "2.5.0" dependencies = [ "dp-evm", "ed25519-dalek", - "evm", + "evm 0.27.0", "sp-core", "sp-io", ] @@ -1731,7 +1731,7 @@ name = "darwinia-evm-precompile-empty" version = "2.5.0" dependencies = [ "dp-evm", - "evm", + "evm 0.27.0", ] [[package]] @@ -1743,7 +1743,7 @@ dependencies = [ "darwinia-support", "dp-contract", "dp-evm", - "evm", + "evm 0.27.0", "frame-support", "log", "parity-scale-codec", @@ -1758,7 +1758,7 @@ version = "2.5.0" dependencies = [ "darwinia-evm", "dp-evm", - "evm", + "evm 0.27.0", ] [[package]] @@ -1766,7 +1766,7 @@ name = "darwinia-evm-precompile-modexp" version = "2.5.0" dependencies = [ "dp-evm", - "evm", + "evm 0.27.0", "hex", "num", "sp-core", @@ -1778,7 +1778,7 @@ name = "darwinia-evm-precompile-sha3fips" version = "2.0.0" dependencies = [ "dp-evm", - "evm", + "evm 0.27.0", "sp-core", "sp-io", "tiny-keccak", @@ -1789,7 +1789,7 @@ name = "darwinia-evm-precompile-simple" version = "2.5.0" dependencies = [ "dp-evm", - "evm", + "evm 0.27.0", "ripemd160", "sp-core", "sp-io", @@ -1805,7 +1805,7 @@ dependencies = [ "dp-evm", "ethabi", "ethereum-types", - "evm", + "evm 0.27.0", "frame-support", "frame-system", "log", @@ -1953,11 +1953,11 @@ dependencies = [ "dvm-ethereum", "ethereum-primitives", "ethereum-types", - "evm", + "evm 0.25.0", "frame-benchmarking", "frame-support", "frame-system", - "libsecp256k1", + "libsecp256k1 0.3.5", "log", "pallet-timestamp", "parity-scale-codec", @@ -2154,13 +2154,13 @@ dependencies = [ "dvm-rpc-runtime-api", "ethereum", "ethereum-types", - "evm", + "evm 0.27.0", "futures 0.3.15", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", "jsonrpc-pubsub", - "libsecp256k1", + "libsecp256k1 0.3.5", "log", "parity-scale-codec", "rand 0.7.3", @@ -2295,7 +2295,7 @@ dependencies = [ name = "dp-evm" version = "2.5.0" dependencies = [ - "evm", + "evm 0.27.0", "impl-trait-for-tuples", "parity-scale-codec", "serde", @@ -2446,10 +2446,10 @@ dependencies = [ "ethabi", "ethereum", "ethereum-types", - "evm", + "evm 0.27.0", "frame-support", "frame-system", - "libsecp256k1", + "libsecp256k1 0.5.0", "log", "pallet-timestamp", "parity-scale-codec", @@ -2761,9 +2761,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b4bd1fb06a4962a243c8be285d8a9b2493ffa79acb32633ad07a0bc523b1acd" dependencies = [ "ethereum", - "evm-core", - "evm-gasometer", - "evm-runtime", + "evm-core 0.25.1", + "evm-gasometer 0.25.0", + "evm-runtime 0.25.0", + "log", + "parity-scale-codec", + "primitive-types", + "rlp", + "sha3 0.8.2", +] + +[[package]] +name = "evm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f833b0e642bec8286b80f00ad6cc6a95e50210c77949b9cb484637e6a05ed596" +dependencies = [ + "environmental", + "ethereum", + "evm-core 0.27.1", + "evm-gasometer 0.27.0", + "evm-runtime 0.27.0", "log", "parity-scale-codec", "primitive-types", @@ -2777,6 +2795,17 @@ name = "evm-core" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1e6640dd44ba663316c7121e0c6fee38000d8249127fd9221bfdc331f75cbfe" +dependencies = [ + "funty", + "parity-scale-codec", + "primitive-types", +] + +[[package]] +name = "evm-core" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "908739da31125d17a69533c290a6c818b494176e59a2ce8accbf122f7d76835c" dependencies = [ "funty", "parity-scale-codec", @@ -2790,8 +2819,20 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a8f04dcc8b0296652eabfa443a08ebed6071a1178e0f42a7f7b63a612bddf0b" dependencies = [ - "evm-core", - "evm-runtime", + "evm-core 0.25.1", + "evm-runtime 0.25.0", + "primitive-types", +] + +[[package]] +name = "evm-gasometer" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4118f952ce320c11e1b7b8a575e477d70bc86a3b92ea23e427174d979cf1da26" +dependencies = [ + "environmental", + "evm-core 0.27.1", + "evm-runtime 0.27.0", "primitive-types", ] @@ -2801,7 +2842,19 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54c302f29ca8bba82a382aa52d427869964179e4f24eae57bde70958ce9b7607" dependencies = [ - "evm-core", + "evm-core 0.25.1", + "primitive-types", + "sha3 0.8.2", +] + +[[package]] +name = "evm-runtime" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "952296b416c3b334b26933ad1f9cfa9203e251691586fb317e411872886ca31b" +dependencies = [ + "environmental", + "evm-core 0.27.1", "primitive-types", "sha3 0.8.2", ] @@ -2969,7 +3022,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "3.0.0" -source = "git+https://github.com/darwinia-network/substrate.git?branch=main#1d7f6e12c651d776fc0dc1adefd007bb60f60b63" +source = "git+https://github.com/darwinia-network/substrate?branch=main#1d7f6e12c651d776fc0dc1adefd007bb60f60b63" dependencies = [ "Inflector", "chrono", @@ -3108,7 +3161,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" version = "3.0.0" -source = "git+https://github.com/darwinia-network/substrate.git?branch=main#1d7f6e12c651d776fc0dc1adefd007bb60f60b63" +source = "git+https://github.com/darwinia-network/substrate?branch=main#1d7f6e12c651d776fc0dc1adefd007bb60f60b63" dependencies = [ "frame-benchmarking", "frame-support", @@ -3617,6 +3670,17 @@ dependencies = [ "hmac 0.7.1", ] +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array 0.14.4", + "hmac 0.8.1", +] + [[package]] name = "hostname" version = "0.3.1" @@ -4395,7 +4459,7 @@ dependencies = [ "futures 0.3.15", "futures-timer 3.0.2", "lazy_static", - "libsecp256k1", + "libsecp256k1 0.3.5", "log", "multihash", "multistream-select", @@ -4797,13 +4861,61 @@ dependencies = [ "arrayref", "crunchy", "digest 0.8.1", - "hmac-drbg", + "hmac-drbg 0.2.0", "rand 0.7.3", "sha2 0.8.2", "subtle 2.4.0", "typenum", ] +[[package]] +name = "libsecp256k1" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd1137239ab33b41aa9637a88a28249e5e70c40a42ccc92db7f12cc356c1fcd7" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "hmac-drbg 0.3.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.5", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee11012b293ea30093c129173cac4335513064094619f4639a25b310fd33c11" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle 2.4.0", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32239626ffbb6a095b83b37a02ceb3672b2443a87a000a884fc3c4d16925c9c0" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76acb433e21d10f5f9892b1962c2856c58c7f39a9e4bd68ac82b9436a0ffd5b9" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "libz-sys" version = "1.1.3" @@ -5964,7 +6076,7 @@ dependencies = [ "dvm-ethereum", "dvm-rpc-runtime-api", "ethereum-primitives", - "evm", + "evm 0.27.0", "frame-benchmarking", "frame-executive", "frame-support", @@ -7563,7 +7675,7 @@ source = "git+https://github.com/darwinia-network/substrate?branch=main#1d7f6e12 dependencies = [ "derive_more", "lazy_static", - "libsecp256k1", + "libsecp256k1 0.3.5", "log", "parity-scale-codec", "parity-wasm 0.41.0", @@ -8822,7 +8934,7 @@ dependencies = [ "hex", "impl-serde", "lazy_static", - "libsecp256k1", + "libsecp256k1 0.3.5", "log", "merlin", "num-traits", @@ -8918,7 +9030,7 @@ source = "git+https://github.com/darwinia-network/substrate?branch=main#1d7f6e12 dependencies = [ "futures 0.3.15", "hash-db", - "libsecp256k1", + "libsecp256k1 0.3.5", "log", "parity-scale-codec", "parking_lot 0.11.1", diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index a2c2caafb9..568ab67be3 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -179,7 +179,16 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.database)) + runner.sync_run(|config| { + // Remove dvm offchain db + let dvm_database_config = sc_service::DatabaseConfig::RocksDb { + path: service::dvm_database_dir(&config), + cache_size: 0, + }; + cmd.run(dvm_database_config)?; + + cmd.run(config.database) + }) } Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 4a5c1b51ce..13cc8a454b 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -26,6 +26,7 @@ pub use pangolin_runtime; // --- std --- use std::{ collections::{BTreeMap, HashMap}, + path::PathBuf, sync::{Arc, Mutex}, time::Duration, }; @@ -176,7 +177,7 @@ fn set_prometheus_registry(config: &mut Configuration) -> Result<(), ServiceErro Ok(()) } -fn open_frontier_backend(config: &Configuration) -> Result>, String> { +pub fn dvm_database_dir(config: &Configuration) -> PathBuf { let config_dir = config .base_path .as_ref() @@ -185,11 +186,14 @@ fn open_frontier_backend(config: &Configuration) -> Result>, BasePath::from_project("", "", &crate::cli::Cli::executable_name()) .config_dir(config.chain_spec.id()) }); - let database_dir = config_dir.join("dvm").join("db"); + config_dir.join("dvm").join("db") +} + +pub fn open_dvm_backend(config: &Configuration) -> Result>, String> { Ok(Arc::new(Backend::::new(&DatabaseSettings { source: DatabaseSettingsSrc::RocksDb { - path: database_dir, + path: dvm_database_dir(&config), cache_size: 0, }, })?)) @@ -274,7 +278,7 @@ where task_manager.spawn_handle(), client.clone(), ); - let frontier_backend = open_frontier_backend(config)?; + let dvm_backend = open_dvm_backend(config)?; let grandpa_hard_forks = vec![]; let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import_with_authority_set_hard_forks( @@ -340,7 +344,7 @@ where let select_chain = select_chain.clone(); let chain_spec = config.chain_spec.cloned_box(); let pending_transactions = pending_transactions.clone(); - let frontier_backend = frontier_backend.clone(); + let dvm_backend = dvm_backend.clone(); let filter_pool = filter_pool.clone(); let max_past_logs = cli.run.max_past_logs; @@ -366,7 +370,7 @@ where finality_provider: finality_proof_provider.clone(), }, pending_transactions: pending_transactions.clone(), - backend: frontier_backend.clone(), + backend: dvm_backend.clone(), filter_pool: filter_pool.clone(), max_past_logs, }; @@ -389,7 +393,7 @@ where rpc_setup, telemetry, pending_transactions, - frontier_backend, + dvm_backend, filter_pool, ), }) @@ -444,7 +448,7 @@ where rpc_setup, mut telemetry, pending_transactions, - frontier_backend, + dvm_backend, filter_pool, ), } = new_partial::(&mut config, cli)?; @@ -673,7 +677,7 @@ where Duration::new(6, 0), client.clone(), backend.clone(), - frontier_backend.clone(), + dvm_backend.clone(), ) .for_each(|()| futures::future::ready(())), ); diff --git a/bin/node/runtime/pangolin/Cargo.toml b/bin/node/runtime/pangolin/Cargo.toml index 673afe14ed..78597f2847 100644 --- a/bin/node/runtime/pangolin/Cargo.toml +++ b/bin/node/runtime/pangolin/Cargo.toml @@ -13,7 +13,7 @@ version = "2.5.0" # crates.io array-bytes = { version = "1.3.3" } codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } log = { version = "0.4.14" } serde = { version = "1.0.126", optional = true } smallvec = { version = "1.6.1" } diff --git a/bin/node/runtime/pangolin/src/lib.rs b/bin/node/runtime/pangolin/src/lib.rs index 664c0e84b6..51c56b8b02 100644 --- a/bin/node/runtime/pangolin/src/lib.rs +++ b/bin/node/runtime/pangolin/src/lib.rs @@ -247,6 +247,7 @@ use darwinia_evm::{Account as EVMAccount, Runner}; use darwinia_header_mmr_rpc_runtime_api::RuntimeDispatchInfo as HeaderMMRRuntimeDispatchInfo; use darwinia_staking_rpc_runtime_api::RuntimeDispatchInfo as StakingRuntimeDispatchInfo; use drml_primitives::*; +use dvm_ethereum::{Call::transact, Transaction as EthereumTransaction}; use dvm_rpc_runtime_api::TransactionStatus; use impls::*; use pangolin_bridge_primitives::PANGOLIN_CHAIN_ID; @@ -682,7 +683,7 @@ impl_runtime_apis! { } fn author() -> H160 { - >::find_author() + >::find_author() } fn storage_at(address: H160, index: U256) -> H256 { @@ -773,6 +774,15 @@ impl_runtime_apis! { Ethereum::current_transaction_statuses() ) } + + fn extrinsic_filter( + xts: Vec<::Extrinsic>, + ) -> Vec { + xts.into_iter().filter_map(|xt| match xt.function { + Call::Ethereum(transact(t)) => Some(t), + _ => None + }).collect::>() + } } impl millau_primitives::MillauFinalityApi for Runtime { diff --git a/bin/node/runtime/pangolin/src/pallets/dvm.rs b/bin/node/runtime/pangolin/src/pallets/dvm.rs index b0270b8d3e..71c3e59a0b 100644 --- a/bin/node/runtime/pangolin/src/pallets/dvm.rs +++ b/bin/node/runtime/pangolin/src/pallets/dvm.rs @@ -1,27 +1,9 @@ -// --- substrate --- -use frame_support::{traits::FindAuthor, ConsensusEngineId}; -use sp_core::{crypto::Public, H160}; // --- darwinia --- use crate::*; use dvm_ethereum::{Config, IntermediateStateRoot}; -pub struct EthereumFindAuthor(sp_std::marker::PhantomData); -impl> FindAuthor for EthereumFindAuthor { - fn find_author<'a, I>(digests: I) -> Option - where - I: 'a + IntoIterator, - { - if let Some(author_index) = F::find_author(digests) { - let authority_id = Babe::authorities()[author_index as usize].clone(); - return Some(H160::from_slice(&authority_id.0.to_raw_vec()[4..24])); - } - None - } -} - impl Config for Runtime { type Event = Event; - type FindAuthor = EthereumFindAuthor; type StateRoot = IntermediateStateRoot; type RingCurrency = Ring; type KtonCurrency = Kton; diff --git a/bin/node/runtime/pangolin/src/pallets/evm_.rs b/bin/node/runtime/pangolin/src/pallets/evm_.rs index 9811c6b172..ac1766290d 100644 --- a/bin/node/runtime/pangolin/src/pallets/evm_.rs +++ b/bin/node/runtime/pangolin/src/pallets/evm_.rs @@ -5,19 +5,40 @@ pub use darwinia_evm_precompile_simple::{ECRecover, Identity, Ripemd160, Sha256} pub use darwinia_evm_precompile_transfer::Transfer; // --- crates.io --- -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError}; // --- substrate --- use codec::{Decode, Encode}; -use frame_support::dispatch::{Dispatchable, GetDispatchInfo, PostDispatchInfo}; -use sp_core::{H160, U256}; -use sp_std::{marker::PhantomData, vec::Vec}; +use frame_support::{ + dispatch::{Dispatchable, GetDispatchInfo, PostDispatchInfo}, + traits::FindAuthor, + ConsensusEngineId, +}; +use sp_core::{crypto::Public, H160, U256}; +use sp_std::marker::PhantomData; // --- darwinia --- use crate::*; use darwinia_evm::{ runner::stack::Runner, ConcatAddressMapping, Config, EnsureAddressTruncated, GasWeightMapping, }; use dp_evm::{Precompile, PrecompileSet}; -use dvm_ethereum::account_basic::{DvmAccountBasic, KtonRemainBalance, RingRemainBalance}; +use dvm_ethereum::{ + account_basic::{DvmAccountBasic, KtonRemainBalance, RingRemainBalance}, + EthereumBlockHashMapping, +}; + +pub struct EthereumFindAuthor(sp_std::marker::PhantomData); +impl> FindAuthor for EthereumFindAuthor { + fn find_author<'a, I>(digests: I) -> Option + where + I: 'a + IntoIterator, + { + if let Some(author_index) = F::find_author(digests) { + let authority_id = Babe::authorities()[author_index as usize].clone(); + return Some(H160::from_slice(&authority_id.0.to_raw_vec()[4..24])); + } + None + } +} pub struct PangolinPrecompiles(PhantomData); impl PrecompileSet for PangolinPrecompiles @@ -32,7 +53,7 @@ where input: &[u8], target_gas: Option, context: &Context, - ) -> Option, u64), ExitError>> { + ) -> Option> { let addr = |n: u64| -> H160 { H160::from_low_u64_be(n) }; match address { @@ -71,6 +92,8 @@ impl Config for Runtime { type GasWeightMapping = DarwiniaGasWeightMapping; type CallOrigin = EnsureAddressTruncated; type AddressMapping = ConcatAddressMapping; + type FindAuthor = EthereumFindAuthor; + type BlockHashMapping = EthereumBlockHashMapping; type RingCurrency = Ring; type KtonCurrency = Kton; type Event = Event; diff --git a/bin/node/runtime/pangolin/src/pallets/system/mod.rs b/bin/node/runtime/pangolin/src/pallets/system/mod.rs index 8e43b758c1..49fc28554d 100644 --- a/bin/node/runtime/pangolin/src/pallets/system/mod.rs +++ b/bin/node/runtime/pangolin/src/pallets/system/mod.rs @@ -9,7 +9,7 @@ use sp_version::RuntimeVersion; use crate::*; frame_support::parameter_types! { - pub const BlockHashCount: BlockNumber = 2400; + pub const BlockHashCount: BlockNumber = 256; pub const Version: RuntimeVersion = VERSION; pub const SS58Prefix: u8 = 18; } diff --git a/client/dvm/rpc/Cargo.toml b/client/dvm/rpc/Cargo.toml index 0fea4dd1c8..d310365f93 100644 --- a/client/dvm/rpc/Cargo.toml +++ b/client/dvm/rpc/Cargo.toml @@ -15,7 +15,7 @@ array-bytes = { version = "1.3.3" } codec = { package = "parity-scale-codec", version = "2.1.1" } ethereum = { version = "0.7.1", features = ["with-codec"] } ethereum-types = { version = "0.11.0" } -evm = { version = "0.25.0" } +evm = { version = "0.27.0" } futures = { version = "0.3.13", features = ["compat"] } jsonrpc-core = { version = "15.1.0" } jsonrpc-core-client = { version = "15.1.0" } diff --git a/client/dvm/rpc/src/eth_pubsub.rs b/client/dvm/rpc/src/eth_pubsub.rs index 4aab49e18b..5f83435cd0 100644 --- a/client/dvm/rpc/src/eth_pubsub.rs +++ b/client/dvm/rpc/src/eth_pubsub.rs @@ -6,7 +6,7 @@ use dp_rpc::{ Bytes, FilteredParams, Header, Log, Rich, }; use dvm_rpc_core::EthPubSubApi::{self as EthPubSubApiT}; -use dvm_rpc_runtime_api::{EthereumRuntimeRPCApi, TransactionStatus}; +use dvm_rpc_runtime_api::EthereumRuntimeRPCApi; // --- substrate --- use sc_client_api::{ backend::{Backend, StateBackend, StorageProvider}, @@ -16,12 +16,9 @@ use sc_network::{ExHashT, NetworkService}; use sc_rpc::Metadata; use sp_api::{BlockId, ProvideRuntimeApi}; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; -use sp_io::hashing::twox_128; use sp_runtime::traits::{BlakeTwo256, Block as BlockT, UniqueSaturatedInto}; -use sp_storage::{StorageData, StorageKey}; use sp_transaction_pool::TransactionPool; // --- std --- -use codec::Decode; use ethereum_types::{H256, U256}; use futures::{StreamExt as _, TryStreamExt as _}; use jsonrpc_core::{ @@ -65,7 +62,7 @@ impl IdProvider for HexEncodedIdProvider { } pub struct EthPubSubApi { - _pool: Arc

, + pool: Arc

, client: Arc, network: Arc>, subscriptions: SubscriptionManager, @@ -80,14 +77,14 @@ where C: Send + Sync + 'static, { pub fn new( - _pool: Arc

, + pool: Arc

, client: Arc, network: Arc>, subscriptions: SubscriptionManager, overrides: Arc>, ) -> Self { Self { - _pool, + pool: pool.clone(), client: client.clone(), network, subscriptions, @@ -207,10 +204,6 @@ impl SubscriptionResult { } } -fn storage_prefix_build(module: &[u8], storage: &[u8]) -> Vec { - [twox_128(module), twox_128(storage)].concat().to_vec() -} - impl EthPubSubApiT for EthPubSubApi where B: BlockT + Send + Sync + 'static, @@ -235,6 +228,7 @@ where _ => FilteredParams::default(), }; let client = self.client.clone(); + let pool = self.pool.clone(); let network = self.network.clone(); let overrides = self.overrides.clone(); match kind { @@ -318,53 +312,43 @@ where }); } Kind::NewPendingTransactions => { - if let Ok(stream) = client.storage_changes_notification_stream( - Some(&[StorageKey(storage_prefix_build(b"Ethereum", b"Pending"))]), - None, - ) { - self.subscriptions.add(subscriber, |sink| { - let stream = stream - .flat_map(|(_block, changes)| { - let mut transactions: Vec = vec![]; - let storage: Vec> = changes - .iter() - .filter_map(|(o_sk, _k, v)| { - if o_sk.is_none() { - Some(v.cloned()) + use sp_transaction_pool::InPoolTransaction; + self.subscriptions.add(subscriber, move |sink| { + let stream = pool + .import_notification_stream() + .filter_map(move |txhash| { + if let Some(xt) = pool.ready_transaction(&txhash) { + let best_block: BlockId = BlockId::Hash(client.info().best_hash); + let res = match client + .runtime_api() + .extrinsic_filter(&best_block, vec![xt.data().clone()]) + { + Ok(txs) => { + if txs.len() == 1 { + Some(txs[0].clone()) } else { None } - }) - .collect(); - for change in storage { - if let Some(data) = change { - let storage: Vec<( - ethereum::Transaction, - TransactionStatus, - ethereum::Receipt, - )> = Decode::decode(&mut &data.0[..]).unwrap(); - let tmp: Vec = - storage.iter().map(|x| x.0.clone()).collect(); - transactions.extend(tmp); } - } - futures::stream::iter(transactions) - }) - .map(|transaction| { - return Ok::< - Result, - (), - >(Ok(PubSubResult::TransactionHash(H256::from_slice( + _ => None, + }; + futures::future::ready(res) + } else { + futures::future::ready(None) + } + }) + .map(|transaction| { + return Ok::, ()>( + Ok(PubSubResult::TransactionHash(H256::from_slice( Keccak256::digest(&rlp::encode(&transaction)).as_slice(), - )))); - }) - .compat(); - - sink.sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) - .send_all(stream) - .map(|_| ()) - }); - } + ))), + ); + }) + .compat(); + sink.sink_map_err(|e| warn!("Error sending notifications: {:?}", e)) + .send_all(stream) + .map(|_| ()) + }); } Kind::Syncing => { self.subscriptions.add(subscriber, |sink| { diff --git a/frame/bridge/s2s/issuing/src/tests.rs b/frame/bridge/s2s/issuing/src/tests.rs index 2ef068cf2f..ae4a674415 100644 --- a/frame/bridge/s2s/issuing/src/tests.rs +++ b/frame/bridge/s2s/issuing/src/tests.rs @@ -22,7 +22,9 @@ use std::str::FromStr; // darwinia use crate::*; use crate::{self as s2s_issuing}; -use darwinia_evm::{AddressMapping, EnsureAddressTruncated, FeeCalculator}; +use darwinia_evm::{ + AddressMapping, EnsureAddressTruncated, FeeCalculator, SubstrateBlockHashMapping, +}; use dvm_ethereum::{ account_basic::{DvmAccountBasic, KtonRemainBalance, RingRemainBalance}, IntermediateStateRoot, @@ -106,7 +108,6 @@ impl frame_system::Config for Test { impl dvm_ethereum::Config for Test { type Event = (); - type FindAuthor = (); type StateRoot = IntermediateStateRoot; type RingCurrency = Ring; type KtonCurrency = Kton; @@ -141,6 +142,8 @@ impl darwinia_evm::Config for Test { type KtonCurrency = Kton; type Event = (); type Precompiles = (); + type FindAuthor = (); + type BlockHashMapping = SubstrateBlockHashMapping; type ChainId = ChainId; type BlockGasLimit = BlockGasLimit; type Runner = darwinia_evm::runner::stack::Runner; diff --git a/frame/dvm/Cargo.toml b/frame/dvm/Cargo.toml index efaba267f8..da977bd76d 100644 --- a/frame/dvm/Cargo.toml +++ b/frame/dvm/Cargo.toml @@ -14,8 +14,8 @@ version = "2.5.0" codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } ethereum = { version = "0.7.1", default-features = false, features = ["with-codec"] } ethereum-types = { version = "0.11.0", default-features = false } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } -libsecp256k1 = { version = "0.3.5", default-features = false } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } +libsecp256k1 = { version = "0.5", default-features = false, features = ["static-context", "hmac"] } log = { version = "0.4.14", optional = true } rlp = { version = "0.5.0", default-features = false } serde = { version = "1.0.126", optional = true } diff --git a/frame/dvm/rpc/runtime-api/src/lib.rs b/frame/dvm/rpc/runtime-api/src/lib.rs index d475d122ff..2f726cd4a1 100644 --- a/frame/dvm/rpc/runtime-api/src/lib.rs +++ b/frame/dvm/rpc/runtime-api/src/lib.rs @@ -22,6 +22,7 @@ use darwinia_support::evm::INTERNAL_CALLER; use ethereum::{Block as EthereumBlock, Log}; use ethereum_types::Bloom; use sp_core::{H160, H256, U256}; +use sp_runtime::traits::Block as BlockT; use sp_std::vec::Vec; #[derive(Eq, PartialEq, Clone, Encode, Decode, sp_runtime::RuntimeDebug)] @@ -108,6 +109,7 @@ sp_api::decl_runtime_apis! { /// For a given account address and index, returns darwinia_evm::AccountStorages. fn storage_at(address: H160, index: U256) -> H256; /// Returns a dvm_ethereum::call response. + #[skip_initialize_block] fn call( from: H160, to: H160, @@ -119,6 +121,7 @@ sp_api::decl_runtime_apis! { estimate: bool, ) -> Result; /// Returns a frame_ethereum::create response. + #[skip_initialize_block] fn create( from: H160, data: Vec, @@ -140,6 +143,10 @@ sp_api::decl_runtime_apis! { Option>, Option> ); + /// Receives a `Vec` and filters all the ethereum transactions. + fn extrinsic_filter( + xts: Vec<::Extrinsic>, + ) -> Vec; } } diff --git a/frame/dvm/src/account_basic.rs b/frame/dvm/src/account_basic.rs index 1eb294876d..0febaf98df 100644 --- a/frame/dvm/src/account_basic.rs +++ b/frame/dvm/src/account_basic.rs @@ -16,16 +16,19 @@ // You should have received a copy of the GNU General Public License // along with Darwinia. If not, see . -use crate::{Config, KtonBalance, RemainingKtonBalance, RemainingRingBalance, RingBalance}; -use darwinia_evm::{Account as EVMAccount, AccountBasic, AddressMapping}; -use darwinia_support::evm::POW_9; +// --- crates.io --- use evm::ExitError; +// --- paritytech --- use frame_support::{ensure, traits::Currency}; use sp_core::{H160, U256}; use sp_runtime::{ traits::{Saturating, UniqueSaturatedInto}, SaturatedConversion, }; +// --- darwinia-network --- +use crate::{Config, KtonBalance, RemainingKtonBalance, RemainingRingBalance, RingBalance}; +use darwinia_evm::{Account as EVMAccount, AccountBasic, AddressMapping}; +use darwinia_support::evm::POW_9; pub trait RemainBalanceOp { /// Get the remaining balance diff --git a/frame/dvm/src/lib.rs b/frame/dvm/src/lib.rs index 09fd07c555..221ce8660a 100644 --- a/frame/dvm/src/lib.rs +++ b/frame/dvm/src/lib.rs @@ -26,12 +26,11 @@ pub mod account_basic; +use dvm_rpc_runtime_api::{DVMTransaction, TransactionStatus}; pub use ethereum::{ Block, Log, Receipt, Transaction, TransactionAction, TransactionMessage, TransactionSignature, }; -pub use dvm_rpc_runtime_api::{DVMTransaction, TransactionStatus}; - #[cfg(all(feature = "std", test))] mod mock; #[cfg(all(feature = "std", test))] @@ -48,22 +47,24 @@ use frame_support::storage::unhashed; use frame_support::{ dispatch::DispatchResultWithPostInfo, ensure, - traits::FindAuthor, traits::{Currency, Get}, - weights::Weight, + weights::{Pays, PostDispatchInfo, Weight}, }; use frame_system::ensure_none; use sp_runtime::{ generic::DigestItem, - traits::UniqueSaturatedInto, + traits::{One, Saturating, UniqueSaturatedInto, Zero}, transaction_validity::{ InvalidTransaction, TransactionSource, TransactionValidity, ValidTransactionBuilder, }, DispatchError, }; +use sp_std::marker::PhantomData; use sp_std::prelude::*; // --- darwinia --- -use darwinia_evm::{AccountBasic, FeeCalculator, GasWeightMapping, Runner}; +use darwinia_evm::{ + runner::Runner, AccountBasic, BlockHashMapping, FeeCalculator, GasWeightMapping, +}; use darwinia_support::evm::INTERNAL_CALLER; use dp_consensus::{PostLog, PreLog, FRONTIER_ENGINE_ID}; use dp_evm::CallOrCreateInfo; @@ -91,8 +92,6 @@ pub mod pallet { { /// The overarching event type. type Event: From + IsType<::Event>; - /// Find author for Ethereum. - type FindAuthor: FindAuthor; /// How Ethereum state root is calculated. type StateRoot: Get; // RING Balance module @@ -107,13 +106,24 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { - fn on_finalize(_block_number: T::BlockNumber) { + fn on_finalize(n: T::BlockNumber) { >::store_block( dp_consensus::find_pre_log(&>::digest()).is_err(), U256::from(UniqueSaturatedInto::::unique_saturated_into( frame_system::Pallet::::block_number(), )), ); + // move block hash pruning window by one block + let block_hash_count = T::BlockHashCount::get(); + let to_remove = n + .saturating_sub(block_hash_count) + .saturating_sub(One::one()); + // keep genesis hash + if !to_remove.is_zero() { + >::remove(U256::from( + UniqueSaturatedInto::::unique_saturated_into(to_remove), + )); + } } fn on_initialize(_block_number: T::BlockNumber) -> Weight { @@ -211,13 +221,7 @@ pub mod pallet { let mut builder = ValidTransactionBuilder::default() .and_provides((origin, transaction.nonce)) - .priority(if min_gas_price == U256::zero() { - 0 - } else { - let target_gas = - (transaction.gas_limit * transaction.gas_price) / min_gas_price; - T::GasWeightMapping::gas_to_weight(target_gas.unique_saturated_into()) - }); + .priority(transaction.gas_price.unique_saturated_into()); if transaction.nonce > account_data.nonce { if let Some(prev_nonce) = transaction.nonce.checked_sub(1.into()) { @@ -264,6 +268,10 @@ pub mod pallet { pub(super) type RemainingKtonBalance = StorageMap<_, Blake2_128Concat, T::AccountId, KtonBalance, ValueQuery>; + // Mapping for block number and hashes. + #[pallet::storage] + pub(super) type BlockHash = StorageMap<_, Twox64Concat, U256, H256, ValueQuery>; + #[pallet::genesis_config] pub struct GenesisConfig {} @@ -331,7 +339,7 @@ impl Pallet { let ommers = Vec::::new(); let partial_header = ethereum::PartialHeader { parent_hash: Self::current_block_hash().unwrap_or_default(), - beneficiary: >::find_author(), + beneficiary: darwinia_evm::Pallet::::find_author(), // TODO: figure out if there's better way to get a sort-of-valid state root. state_root: H256::default(), receipts_root: H256::from_slice( @@ -358,6 +366,7 @@ impl Pallet { CurrentBlock::::put(block.clone()); CurrentReceipts::::put(receipts.clone()); CurrentTransactionStatuses::::put(statuses.clone()); + BlockHash::::insert(block_number, block.header.hash()); if post_log { let digest = DigestItem::::Consensus( @@ -494,18 +503,13 @@ impl Pallet { transaction_hash, reason, )); - Ok(Some(T::GasWeightMapping::gas_to_weight( - used_gas.unique_saturated_into(), - )) - .into()) - } - - /// Get the author using the FindAuthor trait. - pub fn find_author() -> H160 { - let digest = >::digest(); - let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); - - T::FindAuthor::find_author(pre_runtime_digests).unwrap_or_default() + Ok(PostDispatchInfo { + actual_weight: Some(T::GasWeightMapping::gas_to_weight( + used_gas.unique_saturated_into(), + )), + pays_fee: Pays::No, + }) + .into() } /// Get the transaction status with given index. @@ -572,6 +576,14 @@ impl Pallet { } } +/// Returns the Ethereum block hash by number. +pub struct EthereumBlockHashMapping(PhantomData); +impl BlockHashMapping for EthereumBlockHashMapping { + fn block_hash(number: u32) -> H256 { + BlockHash::::get(U256::from(number)) + } +} + /// The schema version for Pallet Ethereum's storage #[derive(Clone, Debug, Encode, Decode, PartialEq, Eq, PartialOrd, Ord)] pub enum EthereumStorageSchema { diff --git a/frame/dvm/src/mock.rs b/frame/dvm/src/mock.rs index 2c79adf191..1214aebda5 100644 --- a/frame/dvm/src/mock.rs +++ b/frame/dvm/src/mock.rs @@ -21,10 +21,10 @@ // --- crates.io --- use codec::{Decode, Encode}; use ethereum::{TransactionAction, TransactionSignature}; -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError}; use rlp::*; // --- substrate --- -use frame_support::{traits::GenesisBuild, ConsensusEngineId}; +use frame_support::{traits::FindAuthor, traits::GenesisBuild, ConsensusEngineId}; use frame_system::mocking::*; use sp_core::{H160, H256, U256}; use sp_runtime::{ @@ -125,8 +125,8 @@ impl FeeCalculator for FixedGasPrice { 1.into() } } -pub struct EthereumFindAuthor; -impl FindAuthor for EthereumFindAuthor { +pub struct FindAuthorTruncated; +impl FindAuthor for FindAuthorTruncated { fn find_author<'a, I>(_digests: I) -> Option where I: 'a + IntoIterator, @@ -161,7 +161,7 @@ where input: &[u8], target_gas: Option, context: &Context, - ) -> Option, u64), ExitError>> { + ) -> Option> { let to_address = |n: u64| -> H160 { H160::from_low_u64_be(n) }; match address { @@ -190,6 +190,8 @@ impl darwinia_evm::Config for Test { type Precompiles = MockPrecompiles; type ChainId = ChainId; type BlockGasLimit = BlockGasLimit; + type FindAuthor = FindAuthorTruncated; + type BlockHashMapping = EthereumBlockHashMapping; type Runner = Runner; type RingAccountBasic = DvmAccountBasic; type KtonAccountBasic = DvmAccountBasic; @@ -198,7 +200,6 @@ impl darwinia_evm::Config for Test { impl dvm_ethereum::Config for Test { type Event = (); - type FindAuthor = EthereumFindAuthor; type StateRoot = IntermediateStateRoot; type RingCurrency = Ring; type KtonCurrency = Kton; @@ -255,8 +256,11 @@ impl UnsignedTransaction { pub fn sign(&self, key: &H256) -> Transaction { let hash = self.signing_hash(); - let msg = secp256k1::Message::parse(hash.as_fixed_bytes()); - let s = secp256k1::sign(&msg, &secp256k1::SecretKey::parse_slice(&key[..]).unwrap()); + let msg = libsecp256k1::Message::parse(hash.as_fixed_bytes()); + let s = libsecp256k1::sign( + &msg, + &libsecp256k1::SecretKey::parse_slice(&key[..]).unwrap(), + ); let sig = s.0.serialize(); let sig = TransactionSignature::new( @@ -280,8 +284,8 @@ impl UnsignedTransaction { fn address_build(seed: u8) -> AccountInfo { let raw_private_key = [seed + 1; 32]; - let secret_key = secp256k1::SecretKey::parse_slice(&raw_private_key).unwrap(); - let raw_public_key = &secp256k1::PublicKey::from_secret_key(&secret_key).serialize()[1..65]; + let secret_key = libsecp256k1::SecretKey::parse_slice(&raw_private_key).unwrap(); + let raw_public_key = &libsecp256k1::PublicKey::from_secret_key(&secret_key).serialize()[1..65]; let raw_address = { let mut s = [0; 20]; diff --git a/frame/dvm/src/tests.rs b/frame/dvm/src/tests.rs index 683b48e86d..5ae89e9f61 100644 --- a/frame/dvm/src/tests.rs +++ b/frame/dvm/src/tests.rs @@ -288,7 +288,7 @@ fn transaction_with_invalid_nonce_should_not_work() { Ethereum::validate_unsigned(TransactionSource::External, &Call::transact(signed)), ValidTransactionBuilder::default() .and_provides((alice.address, U256::from(1))) - .priority(1048576 as u64) + .priority(1u64) .and_requires((alice.address, U256::from(0))) .build() ); @@ -307,7 +307,6 @@ fn transaction_with_invalid_nonce_should_not_work() { )); transaction.nonce = U256::from(0); - let signed2 = transaction.sign(&alice.private_key); assert_err!( diff --git a/frame/evm/Cargo.toml b/frame/evm/Cargo.toml index ede27586e2..4db674a0d0 100644 --- a/frame/evm/Cargo.toml +++ b/frame/evm/Cargo.toml @@ -12,9 +12,9 @@ version = "2.5.0" [dependencies] # crates.io codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } -evm-gasometer = { version = "0.25.0", default-features = false } -evm-runtime = { version = "0.25.0", default-features = false } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } +evm-gasometer = { version = "0.27.0", default-features = false } +evm-runtime = { version = "0.27.0", default-features = false } log = { version = "0.4.14" } primitive-types = { version = "0.9.0", default-features = false, features = ["rlp", "byteorder"] } rlp = { version = "0.5.0", default-features = false } diff --git a/frame/evm/precompile/contracts/blake2/Cargo.toml b/frame/evm/precompile/contracts/blake2/Cargo.toml index 1a494a9b5d..74b1c1f45b 100644 --- a/frame/evm/precompile/contracts/blake2/Cargo.toml +++ b/frame/evm/precompile/contracts/blake2/Cargo.toml @@ -12,7 +12,7 @@ version = "2.5.0" [dependencies] # crates.io -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } # darwinia-network dp-evm = { default-features = false, path = "../../../../../primitives/evm" } # paritytech diff --git a/frame/evm/precompile/contracts/blake2/src/lib.rs b/frame/evm/precompile/contracts/blake2/src/lib.rs index 8a731eac4f..1369096ee6 100644 --- a/frame/evm/precompile/contracts/blake2/src/lib.rs +++ b/frame/evm/precompile/contracts/blake2/src/lib.rs @@ -21,10 +21,9 @@ extern crate alloc; mod eip_152; -use alloc::vec::Vec; use core::mem::size_of; use dp_evm::Precompile; -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError, ExitSucceed}; pub struct Blake2F; @@ -39,7 +38,7 @@ impl Precompile for Blake2F { input: &[u8], target_gas: Option, _context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { const BLAKE2_F_ARG_LEN: usize = 213; if input.len() != BLAKE2_F_ARG_LEN { @@ -108,6 +107,11 @@ impl Precompile for Blake2F { output_buf[i * 8..(i + 1) * 8].copy_from_slice(&state_word.to_le_bytes()); } - Ok((ExitSucceed::Returned, output_buf.to_vec(), gas_cost)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: output_buf.to_vec(), + logs: Default::default(), + }) } } diff --git a/frame/evm/precompile/contracts/bn128/Cargo.toml b/frame/evm/precompile/contracts/bn128/Cargo.toml index 4b8d145e78..b7cc2ee149 100644 --- a/frame/evm/precompile/contracts/bn128/Cargo.toml +++ b/frame/evm/precompile/contracts/bn128/Cargo.toml @@ -13,7 +13,7 @@ version = "2.5.0" [dependencies] # crates.io bn = { package = "substrate-bn", version = "0.6" } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } # darwinia-network dp-evm = { default-features = false, path = "../../../../../primitives/evm" } # paritytech diff --git a/frame/evm/precompile/contracts/bn128/src/lib.rs b/frame/evm/precompile/contracts/bn128/src/lib.rs index 0692619bc5..893a66c40d 100644 --- a/frame/evm/precompile/contracts/bn128/src/lib.rs +++ b/frame/evm/precompile/contracts/bn128/src/lib.rs @@ -21,7 +21,7 @@ extern crate alloc; use alloc::vec::Vec; use dp_evm::Precompile; -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError, ExitSucceed}; use sp_core::U256; fn read_fr(input: &[u8], start_inx: usize) -> Result { @@ -65,7 +65,7 @@ impl Precompile for Bn128Add { input: &[u8], _target_gas: Option, _context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { use bn::AffineG1; let p1 = read_point(input, 0)?; @@ -82,7 +82,12 @@ impl Precompile for Bn128Add { })?; } - Ok((ExitSucceed::Returned, buf.to_vec(), Bn128Add::GAS_COST)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: Bn128Add::GAS_COST, + output: buf.to_vec(), + logs: Default::default(), + }) } } @@ -98,7 +103,7 @@ impl Precompile for Bn128Mul { input: &[u8], _target_gas: Option, _context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { use bn::AffineG1; let p = read_point(input, 0)?; @@ -115,7 +120,12 @@ impl Precompile for Bn128Mul { })?; } - Ok((ExitSucceed::Returned, buf.to_vec(), Bn128Mul::GAS_COST)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: Bn128Mul::GAS_COST, + output: buf.to_vec(), + logs: Default::default(), + }) } } @@ -133,7 +143,7 @@ impl Precompile for Bn128Pairing { input: &[u8], target_gas: Option, _context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { use bn::{pairing_batch, AffineG1, AffineG2, Fq, Fq2, Group, Gt, G1, G2}; let (ret_val, gas_cost) = if input.is_empty() { @@ -209,6 +219,11 @@ impl Precompile for Bn128Pairing { let mut buf = [0u8; 32]; ret_val.to_big_endian(&mut buf); - Ok((ExitSucceed::Returned, buf.to_vec(), gas_cost)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: buf.to_vec(), + logs: Default::default(), + }) } } diff --git a/frame/evm/precompile/contracts/curve25519/Cargo.toml b/frame/evm/precompile/contracts/curve25519/Cargo.toml index 6b3787673d..23bb58cdf0 100644 --- a/frame/evm/precompile/contracts/curve25519/Cargo.toml +++ b/frame/evm/precompile/contracts/curve25519/Cargo.toml @@ -12,7 +12,7 @@ version = "2.5.0" [dependencies] # crates.io curve25519-dalek = { version = "3.0.0", default-features = false, features = ["alloc", "u64_backend"] } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } # darwinia-network dp-evm = { default-features = false, path = "../../../../../primitives/evm" } # paritytech diff --git a/frame/evm/precompile/contracts/dispatch/Cargo.toml b/frame/evm/precompile/contracts/dispatch/Cargo.toml index 65cddb5b37..dc71ac3211 100644 --- a/frame/evm/precompile/contracts/dispatch/Cargo.toml +++ b/frame/evm/precompile/contracts/dispatch/Cargo.toml @@ -13,7 +13,7 @@ version = "2.5.0" [dependencies] # crates.io codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } # darwinia-network darwinia-evm = { default-features = false, path = "../../../../evm" } dp-evm = { default-features = false, path = "../../../../../primitives/evm" } diff --git a/frame/evm/precompile/contracts/dispatch/src/lib.rs b/frame/evm/precompile/contracts/dispatch/src/lib.rs index df98c7f177..7e4303671f 100644 --- a/frame/evm/precompile/contracts/dispatch/src/lib.rs +++ b/frame/evm/precompile/contracts/dispatch/src/lib.rs @@ -17,14 +17,11 @@ #![cfg_attr(not(feature = "std"), no_std)] -extern crate alloc; - -use alloc::vec::Vec; use codec::Decode; use core::marker::PhantomData; use darwinia_evm::{AddressMapping, GasWeightMapping}; use dp_evm::Precompile; -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError, ExitSucceed}; use frame_support::{ dispatch::{Dispatchable, GetDispatchInfo, PostDispatchInfo}, weights::{DispatchClass, Pays}, @@ -44,7 +41,7 @@ where input: &[u8], target_gas: Option, context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { let call = T::Call::decode(&mut &input[..]) .map_err(|_| ExitError::Other("decode failed".into()))?; let info = call.get_dispatch_info(); @@ -68,7 +65,12 @@ where let cost = T::GasWeightMapping::weight_to_gas( post_info.actual_weight.unwrap_or(info.weight), ); - Ok((ExitSucceed::Stopped, Default::default(), cost)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Stopped, + cost, + output: Default::default(), + logs: Default::default(), + }) } Err(_) => Err(ExitError::Other("dispatch execution failed".into())), } diff --git a/frame/evm/precompile/contracts/ed25519/Cargo.toml b/frame/evm/precompile/contracts/ed25519/Cargo.toml index 3e6ceb26d7..bce05f8753 100644 --- a/frame/evm/precompile/contracts/ed25519/Cargo.toml +++ b/frame/evm/precompile/contracts/ed25519/Cargo.toml @@ -12,7 +12,7 @@ version = "2.5.0" [dependencies] # crates.io ed25519-dalek = { version = "1.0.0", default-features = false, features = ["alloc", "u64_backend"] } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } # darwinia-network dp-evm = { default-features = false, path = "../../../../../primitives/evm" } # paritytech diff --git a/frame/evm/precompile/contracts/empty/Cargo.toml b/frame/evm/precompile/contracts/empty/Cargo.toml index 76d124954b..b3ebeefeda 100644 --- a/frame/evm/precompile/contracts/empty/Cargo.toml +++ b/frame/evm/precompile/contracts/empty/Cargo.toml @@ -12,7 +12,7 @@ version = "2.5.0" [dependencies] # crates.io dp-evm = { default-features = false, path = "../../../../../primitives/evm" } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } [features] default = ["std"] diff --git a/frame/evm/precompile/contracts/encoder/Cargo.toml b/frame/evm/precompile/contracts/encoder/Cargo.toml index 9413e0ba21..f26e1e73e7 100644 --- a/frame/evm/precompile/contracts/encoder/Cargo.toml +++ b/frame/evm/precompile/contracts/encoder/Cargo.toml @@ -13,7 +13,7 @@ version = "2.5.0" [dependencies] # crates.io codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } log = { version = "0.4.14" } sha3 = { version = "0.9.1", default-features = false } # darwinia-network diff --git a/frame/evm/precompile/contracts/encoder/src/lib.rs b/frame/evm/precompile/contracts/encoder/src/lib.rs index bbf347ae28..51e33c570d 100644 --- a/frame/evm/precompile/contracts/encoder/src/lib.rs +++ b/frame/evm/precompile/contracts/encoder/src/lib.rs @@ -18,14 +18,11 @@ #![cfg_attr(not(feature = "std"), no_std)] -extern crate alloc; -use alloc::vec::Vec; - // --- core --- use core::marker::PhantomData; // --- crates --- use codec::Encode; -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError, ExitSucceed}; // --- darwinia --- use darwinia_support::evm::SELECTOR; use dp_evm::Precompile; @@ -47,7 +44,7 @@ where input: &[u8], _target_gas: Option, _context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { if input.len() < SELECTOR { return Err(ExitError::Other("input length less than 4 bytes".into())); } @@ -63,6 +60,12 @@ where } }; let call: T::Call = inner_call.into(); - Ok((ExitSucceed::Stopped, call.encode(), 0)) + // TODO: The cost should not be zero + Ok(PrecompileOutput { + exit_status: ExitSucceed::Stopped, + cost: 0, + output: call.encode(), + logs: Default::default(), + }) } } diff --git a/frame/evm/precompile/contracts/issuing/Cargo.toml b/frame/evm/precompile/contracts/issuing/Cargo.toml index caaef97b31..544acd59df 100644 --- a/frame/evm/precompile/contracts/issuing/Cargo.toml +++ b/frame/evm/precompile/contracts/issuing/Cargo.toml @@ -11,7 +11,7 @@ version = "2.5.0" [dependencies] # crates.io -evm = { default-features = false, version = "0.25.0", features = ["with-codec"] } +evm = { default-features = false, version = "0.27.0", features = ["with-codec"] } # darwinia-network darwinia-evm = { default-features = false, path = "../../../" } dp-evm = { default-features = false, path = "../../../../../primitives/evm" } diff --git a/frame/evm/precompile/contracts/issuing/src/lib.rs b/frame/evm/precompile/contracts/issuing/src/lib.rs index 5ed4cacc76..9909055d5c 100644 --- a/frame/evm/precompile/contracts/issuing/src/lib.rs +++ b/frame/evm/precompile/contracts/issuing/src/lib.rs @@ -22,10 +22,8 @@ extern crate alloc; // --- core --- use core::marker::PhantomData; -// --- alloc --- -use alloc::vec::Vec; // --- crates --- -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError, ExitSucceed}; // --- darwinia --- use darwinia_evm::{Config, IssuingHandler}; use dp_evm::Precompile; @@ -41,9 +39,14 @@ impl Precompile for Issuing { input: &[u8], _: Option, context: &Context, - ) -> Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> Result { T::IssuingHandler::handle(context.address, context.caller, input) .map_err(|_| ExitError::Other("contract handle failed".into()))?; - Ok((ExitSucceed::Returned, Default::default(), 20000)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: 20000, + output: Default::default(), + logs: Default::default(), + }) } } diff --git a/frame/evm/precompile/contracts/modexp/Cargo.toml b/frame/evm/precompile/contracts/modexp/Cargo.toml index 940eb7c5fb..a48b97ceff 100644 --- a/frame/evm/precompile/contracts/modexp/Cargo.toml +++ b/frame/evm/precompile/contracts/modexp/Cargo.toml @@ -13,7 +13,7 @@ version = "2.5.0" [dependencies] # crates.io dp-evm = { default-features = false, path = "../../../../../primitives/evm" } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } num = { version = "0.3", default-features = false, features = ["alloc"] } # paritytech sp-core = { default-features = false, git = "https://github.com/darwinia-network/substrate", branch = "main" } diff --git a/frame/evm/precompile/contracts/modexp/src/lib.rs b/frame/evm/precompile/contracts/modexp/src/lib.rs index 97da77fba2..4a0f5461f2 100644 --- a/frame/evm/precompile/contracts/modexp/src/lib.rs +++ b/frame/evm/precompile/contracts/modexp/src/lib.rs @@ -21,7 +21,7 @@ extern crate alloc; use alloc::vec::Vec; use dp_evm::Precompile; -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError, ExitSucceed}; use num::{BigUint, FromPrimitive, One, ToPrimitive, Zero}; use core::cmp::max; @@ -100,7 +100,7 @@ impl Precompile for Modexp { input: &[u8], target_gas: Option, _context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { if input.len() < 96 { return Err(ExitError::Other( "input must contain at least 96 bytes".into(), @@ -181,12 +181,22 @@ impl Precompile for Modexp { // always true except in the case of zero-length modulus, which leads to // output of length and value 1. if bytes.len() == mod_len { - Ok((ExitSucceed::Returned, bytes.to_vec(), gas_cost)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: bytes.to_vec(), + logs: Default::default(), + }) } else if bytes.len() < mod_len { let mut ret = Vec::with_capacity(mod_len); ret.extend(core::iter::repeat(0).take(mod_len - bytes.len())); ret.extend_from_slice(&bytes[..]); - Ok((ExitSucceed::Returned, ret.to_vec(), gas_cost)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: gas_cost, + output: ret.to_vec(), + logs: Default::default(), + }) } else { Err(ExitError::Other("failed".into())) } @@ -211,7 +221,7 @@ mod tests { }; match Modexp::execute(&input, Some(cost), &context) { - Ok((_, _, _)) => { + Ok(_) => { panic!("Test not expected to pass"); } Err(e) => { @@ -242,7 +252,7 @@ mod tests { }; match Modexp::execute(&input, Some(cost), &context) { - Ok((_, _, _)) => { + Ok(_) => { panic!("Test not expected to pass"); } Err(e) => { @@ -270,7 +280,7 @@ mod tests { }; match Modexp::execute(&input, Some(cost), &context) { - Ok((_, _, _)) => { + Ok(_) => { panic!("Test not expected to pass"); } Err(e) => { @@ -303,9 +313,9 @@ mod tests { }; match Modexp::execute(&input, Some(cost), &context) { - Ok((_, output, _)) => { - assert_eq!(output.len(), 1); // should be same length as mod - let result = BigUint::from_bytes_be(&output[..]); + Ok(precompile_result) => { + assert_eq!(precompile_result.output.len(), 1); // should be same length as mod + let result = BigUint::from_bytes_be(&precompile_result.output[..]); let expected = BigUint::parse_bytes(b"5", 10).unwrap(); assert_eq!(result, expected); } @@ -338,9 +348,9 @@ mod tests { }; match Modexp::execute(&input, Some(cost), &context) { - Ok((_, output, _)) => { - assert_eq!(output.len(), 32); // should be same length as mod - let result = BigUint::from_bytes_be(&output[..]); + Ok(precompile_result) => { + assert_eq!(precompile_result.output.len(), 32); // should be same length as mod + let result = BigUint::from_bytes_be(&precompile_result.output[..]); let expected = BigUint::parse_bytes(b"10055", 10).unwrap(); assert_eq!(result, expected); } @@ -371,9 +381,9 @@ mod tests { }; match Modexp::execute(&input, Some(cost), &context) { - Ok((_, output, _)) => { - assert_eq!(output.len(), 32); // should be same length as mod - let result = BigUint::from_bytes_be(&output[..]); + Ok(precompile_result) => { + assert_eq!(precompile_result.output.len(), 32); // should be same length as mod + let result = BigUint::from_bytes_be(&precompile_result.output[..]); let expected = BigUint::parse_bytes(b"1", 10).unwrap(); assert_eq!(result, expected); } diff --git a/frame/evm/precompile/contracts/sha3fips/Cargo.toml b/frame/evm/precompile/contracts/sha3fips/Cargo.toml index e7ea20968a..d3af2f3d33 100644 --- a/frame/evm/precompile/contracts/sha3fips/Cargo.toml +++ b/frame/evm/precompile/contracts/sha3fips/Cargo.toml @@ -13,7 +13,7 @@ version = "2.0.0" [dependencies] # crates.io dp-evm = { default-features = false, path = "../../../../../primitives/evm" } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } tiny-keccak = { version = "2.0", features = ["fips202"] } # paritytech sp-core = { default-features = false, git = "https://github.com/darwinia-network/substrate", branch = "main" } diff --git a/frame/evm/precompile/contracts/simple/Cargo.toml b/frame/evm/precompile/contracts/simple/Cargo.toml index 457cde0631..9e01aaeb20 100644 --- a/frame/evm/precompile/contracts/simple/Cargo.toml +++ b/frame/evm/precompile/contracts/simple/Cargo.toml @@ -12,7 +12,7 @@ version = "2.5.0" [dependencies] # crates.io dp-evm = { default-features = false, path = "../../../../../primitives/evm" } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } ripemd160 = { version = "0.9", default-features = false } # paritytech sp-core = { default-features = false, git = "https://github.com/darwinia-network/substrate", branch = "main" } diff --git a/frame/evm/precompile/contracts/transfer/Cargo.toml b/frame/evm/precompile/contracts/transfer/Cargo.toml index 10ac01563d..f9fe5747be 100644 --- a/frame/evm/precompile/contracts/transfer/Cargo.toml +++ b/frame/evm/precompile/contracts/transfer/Cargo.toml @@ -14,7 +14,7 @@ version = "2.5.0" array-bytes = { version = "1.3.3" } codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } ethereum-types = { version = "0.11.0", default-features = false } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", features = ["with-codec"], default-features = false } log = { version = "0.4.14" } ripemd160 = { version = "0.9.1", default-features = false } sha3 = { version = "0.9.1", default-features = false } diff --git a/frame/evm/precompile/contracts/transfer/src/kton.rs b/frame/evm/precompile/contracts/transfer/src/kton.rs index 690e1ca6bc..59aba9dcff 100644 --- a/frame/evm/precompile/contracts/transfer/src/kton.rs +++ b/frame/evm/precompile/contracts/transfer/src/kton.rs @@ -21,14 +21,13 @@ use frame_support::ensure; use sp_core::{H160, U256}; use sp_std::{borrow::ToOwned, prelude::*, vec::Vec}; // --- darwinia --- -use crate::util; -use crate::AccountId; -use darwinia_evm::{AccountBasic, Config, Pallet, Runner}; +use crate::{util, AccountId}; +use darwinia_evm::{runner::Runner, AccountBasic, Config, Pallet}; use darwinia_support::evm::{SELECTOR, TRANSFER_ADDR}; // --- crates --- use codec::Decode; use ethabi::{Function, Param, ParamType, Token}; -use evm::{Context, ExitError, ExitReason, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError, ExitReason, ExitSucceed}; use sha3::Digest; const TRANSFER_AND_CALL_ACTION: &[u8] = b"transfer_and_call(address,uint256)"; @@ -46,7 +45,7 @@ impl Kton { input: &[u8], target_gas: Option, context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { let action = which_action::(&input)?; match action { @@ -92,7 +91,12 @@ impl Kton { } } - Ok((ExitSucceed::Returned, vec![], 20000)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: 20000, + output: Default::default(), + logs: Default::default(), + }) } Kton::Withdraw(wd) => { let (source, to, value) = (context.caller, wd.to_account_id, wd.kton_value); @@ -117,7 +121,12 @@ impl Kton { let target_kton = T::KtonAccountBasic::account_balance(&to); let new_target_kton_balance = target_kton.saturating_add(value); T::KtonAccountBasic::mutate_account_balance(&to, new_target_kton_balance); - Ok((ExitSucceed::Returned, vec![], 20000)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: 20000, + output: Default::default(), + logs: Default::default(), + }) } } } diff --git a/frame/evm/precompile/contracts/transfer/src/lib.rs b/frame/evm/precompile/contracts/transfer/src/lib.rs index d5f13118d8..c67c48ce50 100644 --- a/frame/evm/precompile/contracts/transfer/src/lib.rs +++ b/frame/evm/precompile/contracts/transfer/src/lib.rs @@ -41,7 +41,7 @@ pub mod ring; pub mod util; // --- substrate --- -use sp_std::{marker::PhantomData, vec::Vec}; +use sp_std::marker::PhantomData; // --- darwinia --- use darwinia_evm::Config; use darwinia_support::evm::SELECTOR; @@ -49,7 +49,7 @@ use dp_evm::Precompile; use kton::Kton; use ring::RingBack; // --- crate --- -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError}; pub type AccountId = ::AccountId; @@ -66,7 +66,7 @@ impl Precompile for Transfer { input: &[u8], target_gas: Option, context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { match which_transfer::(&input) { Ok(Transfer::RingTransfer) => >::transfer(&input, target_gas, context), Ok(Transfer::KtonTransfer) => >::transfer(&input, target_gas, context), diff --git a/frame/evm/precompile/contracts/transfer/src/ring.rs b/frame/evm/precompile/contracts/transfer/src/ring.rs index 13c4e6471d..ac250a4a41 100644 --- a/frame/evm/precompile/contracts/transfer/src/ring.rs +++ b/frame/evm/precompile/contracts/transfer/src/ring.rs @@ -18,14 +18,14 @@ // --- substrate --- use frame_support::ensure; -use sp_std::{marker::PhantomData, prelude::*, vec::Vec}; +use sp_std::{marker::PhantomData, prelude::*}; // --- darwinia --- use crate::AccountId; use darwinia_evm::{AccountBasic, Config}; use darwinia_support::evm::TRANSFER_ADDR; // --- crates --- use codec::Decode; -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError, ExitSucceed}; pub struct RingBack { _maker: PhantomData, @@ -41,7 +41,7 @@ impl RingBack { input: &[u8], _: Option, context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { // Decode input data let input = InputData::::decode(&input)?; let (source, to, value) = (context.address, input.dest, context.apparent_value); @@ -65,7 +65,12 @@ impl RingBack { let new_target_balance = target_balance.saturating_add(value); T::RingAccountBasic::mutate_account_balance(&to, new_target_balance); - Ok((ExitSucceed::Returned, vec![], 20000)) + Ok(PrecompileOutput { + exit_status: ExitSucceed::Returned, + cost: 20000, + output: Default::default(), + logs: Default::default(), + }) } } diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index 63f9b92932..0752832b5c 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -38,10 +38,9 @@ use codec::{Decode, Encode}; use evm::{Config as EvmConfig, ExitError, ExitReason}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; - -// --- substrate --- +// --- paritytech --- use frame_support::{ - traits::Currency, + traits::{Currency, FindAuthor}, weights::{PostDispatchInfo, Weight}, }; use frame_system::RawOrigin; @@ -68,29 +67,35 @@ pub mod pallet { type FeeCalculator: FeeCalculator; /// Maps Ethereum gas to Substrate weight. type GasWeightMapping: GasWeightMapping; + /// The block gas limit. Can be a simple constant, or an adjustment algorithm in another pallet. + type BlockGasLimit: Get; + /// Allow the origin to call on behalf of given address. type CallOrigin: EnsureAddressOrigin; + /// The overarching event type. + type Event: From> + IsType<::Event>; + /// Chain ID of EVM. + type ChainId: Get; /// Mapping from address to account id. type AddressMapping: AddressMapping; + /// Block number to block hash. + type BlockHashMapping: BlockHashMapping; + /// Find author for the current block. + type FindAuthor: FindAuthor; + /// Ring Currency type type RingCurrency: Currency; /// Kton Currency type type KtonCurrency: Currency; + /// The account basic mapping way + type RingAccountBasic: AccountBasic; + type KtonAccountBasic: AccountBasic; - /// The overarching event type. - type Event: From> + IsType<::Event>; /// Precompiles associated with this EVM engine. type Precompiles: PrecompileSet; - /// Chain ID of EVM. - type ChainId: Get; - /// The block gas limit. Can be a simple constant, or an adjustment algorithm in another pallet. - type BlockGasLimit: Get; /// EVM execution runner. type Runner: Runner; - /// The account basic mapping way - type RingAccountBasic: AccountBasic; - type KtonAccountBasic: AccountBasic; /// Issuing contracts handler type IssuingHandler: IssuingHandler; @@ -376,6 +381,14 @@ pub mod pallet { T::RingAccountBasic::mutate_account_basic_balance(&address, new_account_balance); } + + /// Get the author using the FindAuthor trait. + pub fn find_author() -> H160 { + let digest = >::digest(); + let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); + + T::FindAuthor::find_author(pre_runtime_digests).unwrap_or_default() + } } } pub use pallet::*; @@ -442,6 +455,20 @@ impl GasWeightMapping for () { } } +/// A trait for getting a block hash by number. +pub trait BlockHashMapping { + fn block_hash(number: u32) -> H256; +} + +/// Returns the Substrate block hash by number. +pub struct SubstrateBlockHashMapping(sp_std::marker::PhantomData); +impl BlockHashMapping for SubstrateBlockHashMapping { + fn block_hash(number: u32) -> H256 { + let number = T::BlockNumber::from(number); + H256::from_slice(frame_system::Pallet::::block_hash(number).as_ref()) + } +} + /// A contract handle for ethereum issuing pub trait IssuingHandler { fn handle(address: H160, caller: H160, input: &[u8]) -> DispatchResult; diff --git a/frame/evm/src/runner/stack.rs b/frame/evm/src/runner/stack.rs index ef0b50446e..e365adb452 100644 --- a/frame/evm/src/runner/stack.rs +++ b/frame/evm/src/runner/stack.rs @@ -25,15 +25,15 @@ use evm::{ ExitError, ExitReason, Transfer, }; use sha3::{Digest, Keccak256}; -// --- substrate --- +// --- paritytech --- use frame_support::{ensure, traits::Get}; use sp_core::{H160, H256, U256}; use sp_runtime::{traits::UniqueSaturatedInto, ArithmeticError, DispatchError}; use sp_std::{collections::btree_set::BTreeSet, marker::PhantomData, mem, prelude::*}; -// --- darwinia --- +// --- darwinia-network --- use crate::{ - runner::Runner as RunnerT, AccountBasic, AccountCodes, AccountStorages, AddressMapping, Config, - Error, Event, FeeCalculator, Pallet, PrecompileSet, + runner::Runner as RunnerT, AccountBasic, AccountCodes, AccountStorages, AddressMapping, + BlockHashMapping, Config, Error, Event, FeeCalculator, Pallet, PrecompileSet, }; use dp_evm::{CallInfo, CreateInfo, ExecutionInfo, Log, Vicinity}; @@ -351,8 +351,7 @@ impl<'vicinity, 'config, T: Config> BackendT for SubstrateStackState<'vicinity, if number > U256::from(u32::max_value()) { H256::default() } else { - let number = T::BlockNumber::from(number.as_u32()); - H256::from_slice(>::block_hash(number).as_ref()) + T::BlockHashMapping::block_hash(number.as_u32()) } } @@ -362,7 +361,7 @@ impl<'vicinity, 'config, T: Config> BackendT for SubstrateStackState<'vicinity, } fn block_coinbase(&self) -> H160 { - H160::default() + Pallet::::find_author() } fn block_timestamp(&self) -> U256 { @@ -375,7 +374,7 @@ impl<'vicinity, 'config, T: Config> BackendT for SubstrateStackState<'vicinity, } fn block_gas_limit(&self) -> U256 { - U256::zero() + T::BlockGasLimit::get() } fn chain_id(&self) -> U256 { diff --git a/frame/evm/src/tests.rs b/frame/evm/src/tests.rs index 6cdc55701e..9427153dda 100644 --- a/frame/evm/src/tests.rs +++ b/frame/evm/src/tests.rs @@ -19,7 +19,7 @@ // --- std --- use std::{collections::BTreeMap, str::FromStr}; // --- substrate --- -use frame_support::{assert_ok, traits::GenesisBuild}; +use frame_support::{assert_ok, traits::GenesisBuild, ConsensusEngineId}; use frame_system::mocking::*; use sp_core::H256; use sp_runtime::{ @@ -108,6 +108,16 @@ impl FeeCalculator for FixedGasPrice { } } +pub struct FindAuthorTruncated; +impl FindAuthor for FindAuthorTruncated { + fn find_author<'a, I>(_digests: I) -> Option + where + I: 'a + IntoIterator, + { + Some(H160::default()) + } +} + pub struct RawAccountBasic(sp_std::marker::PhantomData); impl AccountBasic for RawAccountBasic { /// Get the account basic in EVM format. @@ -168,6 +178,9 @@ impl Config for Test { type CallOrigin = EnsureAddressRoot; type AddressMapping = ConcatAddressMapping; + type BlockHashMapping = SubstrateBlockHashMapping; + type FindAuthor = FindAuthorTruncated; + type RingCurrency = Ring; type KtonCurrency = Kton; diff --git a/primitives/evm/Cargo.toml b/primitives/evm/Cargo.toml index e76e8fbc63..ca3416e03e 100644 --- a/primitives/evm/Cargo.toml +++ b/primitives/evm/Cargo.toml @@ -12,7 +12,7 @@ version = "2.5.0" [dependencies] # crates.io codec = { package = "parity-scale-codec", version = "2.1.1", default-features = false } -evm = { version = "0.25.0", default-features = false, features = ["with-codec"] } +evm = { version = "0.27.0", default-features = false, features = ["with-codec"] } impl-trait-for-tuples = { version = "0.2.1" } serde = { version = "1.0.126", optional = true, features = ["derive"] } # paritytech diff --git a/primitives/evm/src/precompile.rs b/primitives/evm/src/precompile.rs index bec306410d..e2a8348eda 100644 --- a/primitives/evm/src/precompile.rs +++ b/primitives/evm/src/precompile.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use evm::{Context, ExitError, ExitSucceed}; +use evm::{executor::PrecompileOutput, Context, ExitError, ExitSucceed}; use impl_trait_for_tuples::impl_for_tuples; use sp_core::H160; use sp_std::vec::Vec; @@ -32,7 +32,7 @@ pub trait PrecompileSet { input: &[u8], target_gas: Option, context: &Context, - ) -> Option, u64), ExitError>>; + ) -> Option>; } #[impl_for_tuples(30)] #[tuple_types_no_default_trait_bound] @@ -44,7 +44,7 @@ impl PrecompileSet for Tuple { input: &[u8], target_gas: Option, context: &Context, - ) -> Option, u64), ExitError>> { + ) -> Option> { let mut index = 0; for_tuples!( #( @@ -67,7 +67,7 @@ pub trait Precompile { input: &[u8], target_gas: Option, context: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError>; + ) -> core::result::Result; } impl Precompile for T where @@ -77,11 +77,15 @@ where input: &[u8], target_gas: Option, _: &Context, - ) -> core::result::Result<(ExitSucceed, Vec, u64), ExitError> { + ) -> core::result::Result { let cost = ensure_linear_cost(target_gas, input.len() as u64, T::BASE, T::WORD)?; - let (succeed, out) = T::execute(input, cost)?; - - Ok((succeed, out, cost)) + let (exit_status, output) = T::execute(input, cost)?; + Ok(PrecompileOutput { + exit_status, + cost, + output, + logs: Default::default(), + }) } }