diff --git a/Cargo.lock b/Cargo.lock index 2dc55b391f..671c9004be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2154,6 +2154,23 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fp-account" +version = "1.0.0-dev" +dependencies = [ + "hex", + "impl-serde", + "libsecp256k1", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "fp-consensus" version = "2.0.0-dev" @@ -2465,6 +2482,7 @@ dependencies = [ "fc-rpc", "fc-rpc-core", "fc-storage", + "fp-account", "fp-dynamic-fee", "fp-evm", "fp-rpc", @@ -2482,6 +2500,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", "sc-basic-authorship", + "sc-chain-spec", "sc-cli", "sc-client-api", "sc-consensus", @@ -2505,7 +2524,6 @@ dependencies = [ "sp-core", "sp-finality-grandpa", "sp-inherents", - "sp-keyring", "sp-offchain", "sp-runtime", "sp-session", @@ -2522,6 +2540,7 @@ dependencies = [ name = "frontier-template-runtime" version = "0.0.0" dependencies = [ + "fp-account", "fp-evm", "fp-rpc", "fp-self-contained", @@ -4874,6 +4893,7 @@ version = "6.0.0-dev" dependencies = [ "environmental", "evm", + "fp-account", "fp-evm", "frame-benchmarking", "frame-support", @@ -5154,6 +5174,7 @@ name = "pallet-utility" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=master#1837f423b494254e1d27834b1c9da34b2c0c2375" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", diff --git a/Cargo.toml b/Cargo.toml index 93769f35d1..ceb42d3fda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ members = [ "client/db", "client/storage", "client/mapping-sync", + "primitives/account", "primitives/consensus", "primitives/dynamic-fee", "primitives/evm", @@ -41,9 +42,11 @@ environmental = { version = "1.1.3", default-features = false } ethereum = { version = "0.14.0", default-features = false } ethereum-types = { version = "0.14.1", default-features = false } evm = { version = "0.37.0", default-features = false } +impl-serde = { version = "0.4.0", default-features = false } jsonrpsee = "0.16.2" kvdb-rocksdb = "0.17.0" -libsecp256k1 = "0.7.1" +libsecp256k1 = { version = "0.7.1", default-features = false } +log = { version = "0.4.17", default-features = false } parity-db = "0.4.2" rlp = { version = "0.5", default-features = false } scale-codec = { package = "parity-scale-codec", version = "3.2.1", default-features = false, features = ["derive"] } @@ -53,6 +56,7 @@ serde_json = "1.0" # Substrate Client sc-basic-authorship = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } sc-block-builder = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } +sc-chain-spec = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } sc-cli = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } sc-client-api = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } sc-client-db = { version = "0.10.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } @@ -124,6 +128,7 @@ fc-rpc = { version = "2.0.0-dev", path = "client/rpc" } fc-rpc-core = { version = "1.1.0-dev", path = "client/rpc-core" } fc-storage = { version = "1.0.0-dev", path = "client/storage" } # Frontier Primitive +fp-account = { version = "1.0.0-dev", path = "primitives/account", default-features = false } fp-consensus = { version = "2.0.0-dev", path = "primitives/consensus", default-features = false } fp-dynamic-fee = { version = "1.0.0", path = "primitives/dynamic-fee", default-features = false } fp-ethereum = { version = "1.0.0-dev", path = "primitives/ethereum", default-features = false } diff --git a/client/cli/src/lib.rs b/client/cli/src/lib.rs index 1d4c7e668f..e30cb5f4e3 100644 --- a/client/cli/src/lib.rs +++ b/client/cli/src/lib.rs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#![deny(unused_crate_dependencies)] + mod frontier_db_cmd; pub use self::frontier_db_cmd::FrontierDbCmd; diff --git a/client/consensus/src/lib.rs b/client/consensus/src/lib.rs index 39b17cce14..d65655427d 100644 --- a/client/consensus/src/lib.rs +++ b/client/consensus/src/lib.rs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#![deny(unused_crate_dependencies)] + use std::{collections::HashMap, marker::PhantomData, sync::Arc}; // Substrate diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index 8f7499dde7..f54defe718 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#![deny(unused_crate_dependencies)] + #[cfg(feature = "parity-db")] mod parity_db_adapter; mod upgrade; diff --git a/client/mapping-sync/src/lib.rs b/client/mapping-sync/src/lib.rs index 774ad93cef..1853a9688b 100644 --- a/client/mapping-sync/src/lib.rs +++ b/client/mapping-sync/src/lib.rs @@ -17,6 +17,7 @@ // along with this program. If not, see . #![allow(clippy::too_many_arguments)] +#![deny(unused_crate_dependencies)] mod worker; diff --git a/client/rpc-core/src/lib.rs b/client/rpc-core/src/lib.rs index c595bf8a1e..701c095e2f 100644 --- a/client/rpc-core/src/lib.rs +++ b/client/rpc-core/src/lib.rs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#![deny(unused_crate_dependencies)] + pub mod types; mod eth; diff --git a/client/rpc-core/src/types/filter.rs b/client/rpc-core/src/types/filter.rs index 76cfd4824e..72ffe325ce 100644 --- a/client/rpc-core/src/types/filter.rs +++ b/client/rpc-core/src/types/filter.rs @@ -67,7 +67,7 @@ where /// Filter Address pub type FilterAddress = VariadicValue; -/// Topic, supports `A` | `null` | `[A,B,C]` | `[A,[B,C]]` | [null,[B,C]] | [null,[null,C]] +/// Topic, supports `A` | `null` | `[A,B,C]` | `[A,[B,C]]` | `[null,[B,C]]` | `[null,[null,C]]` pub type Topic = VariadicValue>>>; /// FlatTopic, simplifies the matching logic. pub type FlatTopic = VariadicValue>; diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index 85676f2547..5593004641 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -24,6 +24,7 @@ clippy::len_zero, clippy::new_without_default )] +#![deny(unused_crate_dependencies)] mod eth; mod eth_pubsub; diff --git a/client/storage/src/lib.rs b/client/storage/src/lib.rs index b9496a6e69..93ecc035ab 100644 --- a/client/storage/src/lib.rs +++ b/client/storage/src/lib.rs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#![deny(unused_crate_dependencies)] + mod overrides; pub use self::overrides::*; diff --git a/docs/accounts.md b/docs/accounts.md new file mode 100644 index 0000000000..e0b278c408 --- /dev/null +++ b/docs/accounts.md @@ -0,0 +1,18 @@ +Frontier provides two different strategies for handling `H160` addresses. + +# H256 -> H160 mapping + +The first strategy consists of of a truncated hash scheme, where the first 160 LE bytes of a `H256` address are used to form the `H160` address. + +`AccountId32` is the Account type used for `frame_system::pallet::Config::AccountId`. + +The Runtime's `Signature` type is configured as [`sp_runtime::MultiSignature`](https://docs.rs/sp-runtime/2.0.1/sp_runtime/enum.MultiSignature.html), which means signatures can be: +- `Sr25519` +- `Ed25519` +- `ECDSA` + +# Native H160 via AccountId20 + +The second strategy consists of using `fp-account` so that `AccountId20` is the Account type used for `frame_system::pallet::Config::AccountId`. + +The Runtime's `Signature` type is configured as `EthereumSigner`, which means only `ECDSA` signatures are supported. \ No newline at end of file diff --git a/docs/yarn.lock b/docs/yarn.lock index d31524cd79..e551b16dbd 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -2226,9 +2226,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001219: - version "1.0.30001230" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71" - integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ== + version "1.0.30001468" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001468.tgz#0101837c6a4e38e6331104c33dcfb3bdf367a4b7" + integrity sha512-zgAo8D5kbOyUcRAgSmgyuvBkjrGk5CGYG5TYgFdpQv+ywcyEpo1LOWoG8YmoflGnh+V+UsNuKYedsoYs0hzV5A== caseless@~0.12.0: version "0.12.0" diff --git a/frame/base-fee/Cargo.toml b/frame/base-fee/Cargo.toml index df30cc2a1f..dc89a53b4b 100644 --- a/frame/base-fee/Cargo.toml +++ b/frame/base-fee/Cargo.toml @@ -23,7 +23,7 @@ fp-evm = { workspace = true } [dev-dependencies] # Substrate -sp-io = { workspace = true } +sp-io = { workspace = true, features = ["default"] } [features] default = ["std"] diff --git a/frame/base-fee/src/lib.rs b/frame/base-fee/src/lib.rs index 2d562d7a51..4cb182032e 100644 --- a/frame/base-fee/src/lib.rs +++ b/frame/base-fee/src/lib.rs @@ -17,6 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::comparison_chain)] +#![deny(unused_crate_dependencies)] #[cfg(test)] mod tests; diff --git a/frame/dynamic-fee/Cargo.toml b/frame/dynamic-fee/Cargo.toml index d08dfd43ae..b26de76fc0 100644 --- a/frame/dynamic-fee/Cargo.toml +++ b/frame/dynamic-fee/Cargo.toml @@ -18,7 +18,6 @@ frame-support = { workspace = true } frame-system = { workspace = true } sp-core = { workspace = true } sp-inherents = { workspace = true } -sp-runtime = { workspace = true } sp-std = { workspace = true } # Frontier fp-dynamic-fee = { workspace = true } @@ -26,8 +25,9 @@ fp-evm = { workspace = true } [dev-dependencies] # Substrate -pallet-timestamp = { workspace = true } -sp-io = { workspace = true } +pallet-timestamp = { workspace = true, features = ["default"] } +sp-io = { workspace = true, features = ["default"] } +sp-runtime = { workspace = true, features = ["default"] } [features] default = ["std"] @@ -37,7 +37,6 @@ std = [ # Substrate "sp-core/std", "sp-inherents/std", - "sp-runtime/std", "sp-std/std", # Substrate "frame-system/std", diff --git a/frame/dynamic-fee/src/lib.rs b/frame/dynamic-fee/src/lib.rs index 4351364b28..64b5f3d3df 100644 --- a/frame/dynamic-fee/src/lib.rs +++ b/frame/dynamic-fee/src/lib.rs @@ -17,6 +17,7 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] #[cfg(test)] mod tests; diff --git a/frame/ethereum/Cargo.toml b/frame/ethereum/Cargo.toml index e6c6f3c836..1d58fb1303 100644 --- a/frame/ethereum/Cargo.toml +++ b/frame/ethereum/Cargo.toml @@ -14,7 +14,6 @@ targets = ["x86_64-unknown-linux-gnu"] ethereum = { workspace = true, features = ["with-codec"] } ethereum-types = { workspace = true } evm = { workspace = true, features = ["with-codec"] } -rlp = { workspace = true } scale-codec = { package = "parity-scale-codec", workspace = true } scale-info = { workspace = true } @@ -31,16 +30,18 @@ fp-consensus = { workspace = true } fp-ethereum = { workspace = true } fp-evm = { workspace = true } fp-rpc = { workspace = true } -fp-self-contained = { workspace = true } fp-storage = { workspace = true } pallet-evm = { workspace = true } [dev-dependencies] hex = "0.4.3" libsecp256k1 = { workspace = true, features = ["static-context", "hmac"] } +rlp = { workspace = true } # Substrate pallet-balances = { workspace = true, features = ["default"] } -sp-core = { workspace = true } +sp-core = { workspace = true, features = ["default"] } +# Frontier +fp-self-contained = { workspace = true, features = ["default"] } [features] default = ["std"] diff --git a/frame/ethereum/src/lib.rs b/frame/ethereum/src/lib.rs index 3a474bfdf5..72e47a4c6a 100644 --- a/frame/ethereum/src/lib.rs +++ b/frame/ethereum/src/lib.rs @@ -23,6 +23,7 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::comparison_chain, clippy::large_enum_variant)] +#![deny(unused_crate_dependencies)] #[cfg(all(feature = "std", test))] mod mock; @@ -64,7 +65,8 @@ pub use ethereum::{ }; pub use fp_rpc::TransactionStatus; -#[derive(Clone, Eq, PartialEq, RuntimeDebug, Encode, Decode, MaxEncodedLen, TypeInfo)] +#[derive(Clone, Eq, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo)] pub enum RawOrigin { EthereumTransaction(H160), } diff --git a/frame/evm-chain-id/src/lib.rs b/frame/evm-chain-id/src/lib.rs index 589019f06e..04dd317814 100644 --- a/frame/evm-chain-id/src/lib.rs +++ b/frame/evm-chain-id/src/lib.rs @@ -26,6 +26,7 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] pub use pallet::*; diff --git a/frame/evm/Cargo.toml b/frame/evm/Cargo.toml index d5bd7084cf..8a82b5a60e 100644 --- a/frame/evm/Cargo.toml +++ b/frame/evm/Cargo.toml @@ -16,7 +16,7 @@ environmental = { workspace = true, optional = true } evm = { workspace = true, features = ["with-codec"] } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } impl-trait-for-tuples = "0.2.2" -log = { version = "0.4.17", default-features = false } +log = { workspace = true } rlp = { workspace = true } scale-codec = { package = "parity-scale-codec", workspace = true } scale-info = { workspace = true } @@ -30,12 +30,13 @@ sp-io = { workspace = true } sp-runtime = { workspace = true } sp-std = { workspace = true } # Frontier +fp-account = { workspace = true } fp-evm = { workspace = true } [dev-dependencies] # Substrate pallet-balances = { workspace = true, features = ["default"] } -pallet-evm-precompile-simple = { workspace = true } +pallet-evm-precompile-simple = { workspace = true, features = ["default"] } [features] default = ["std"] @@ -58,6 +59,7 @@ std = [ "sp-runtime/std", "sp-std/std", # Frontier + "fp-account/std", "fp-evm/std", ] runtime-benchmarks = [ diff --git a/frame/evm/precompile/blake2/src/lib.rs b/frame/evm/precompile/blake2/src/lib.rs index 50441f913b..09561c73b6 100644 --- a/frame/evm/precompile/blake2/src/lib.rs +++ b/frame/evm/precompile/blake2/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] extern crate alloc; diff --git a/frame/evm/precompile/bn128/src/lib.rs b/frame/evm/precompile/bn128/src/lib.rs index 10ca750c2a..1fd3060c8a 100644 --- a/frame/evm/precompile/bn128/src/lib.rs +++ b/frame/evm/precompile/bn128/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] extern crate alloc; diff --git a/frame/evm/precompile/curve25519/src/lib.rs b/frame/evm/precompile/curve25519/src/lib.rs index d2aa0d0d4f..29d62149d9 100644 --- a/frame/evm/precompile/curve25519/src/lib.rs +++ b/frame/evm/precompile/curve25519/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] extern crate alloc; use alloc::vec::Vec; diff --git a/frame/evm/precompile/dispatch/Cargo.toml b/frame/evm/precompile/dispatch/Cargo.toml index b2be365313..782f3b404f 100644 --- a/frame/evm/precompile/dispatch/Cargo.toml +++ b/frame/evm/precompile/dispatch/Cargo.toml @@ -18,14 +18,14 @@ pallet-evm = { workspace = true } scale-codec = { package = "parity-scale-codec", workspace = true } scale-info = { workspace = true } # Substrate -frame-system = { workspace = true } +frame-system = { workspace = true, features = ["default"] } pallet-balances = { workspace = true, features = ["default"] } -pallet-timestamp = { workspace = true } -pallet-utility = { workspace = true } -sp-core = { workspace = true } -sp-io = { workspace = true } -sp-runtime = { workspace = true } -sp-std = { workspace = true } +pallet-timestamp = { workspace = true, features = ["default"] } +pallet-utility = { workspace = true, features = ["default"] } +sp-core = { workspace = true, features = ["default"] } +sp-io = { workspace = true, features = ["default"] } +sp-runtime = { workspace = true, features = ["default"] } +sp-std = { workspace = true, features = ["default"] } [features] default = ["std"] diff --git a/frame/evm/precompile/dispatch/src/lib.rs b/frame/evm/precompile/dispatch/src/lib.rs index 958a4a86cc..82aee787e7 100644 --- a/frame/evm/precompile/dispatch/src/lib.rs +++ b/frame/evm/precompile/dispatch/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] extern crate alloc; diff --git a/frame/evm/precompile/ed25519/src/lib.rs b/frame/evm/precompile/ed25519/src/lib.rs index 971730a579..8c1c841ce1 100644 --- a/frame/evm/precompile/ed25519/src/lib.rs +++ b/frame/evm/precompile/ed25519/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] extern crate alloc; diff --git a/frame/evm/precompile/modexp/src/lib.rs b/frame/evm/precompile/modexp/src/lib.rs index 6932df40ab..87da646bce 100644 --- a/frame/evm/precompile/modexp/src/lib.rs +++ b/frame/evm/precompile/modexp/src/lib.rs @@ -17,13 +17,14 @@ #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::comparison_chain)] +#![deny(unused_crate_dependencies)] extern crate alloc; use alloc::{vec, vec::Vec}; use core::cmp::max; -use num::{BigUint, FromPrimitive, One, ToPrimitive, Zero}; +use num::{BigUint, FromPrimitive, Integer, One, ToPrimitive, Zero}; use fp_evm::{ ExitError, ExitSucceed, Precompile, PrecompileFailure, PrecompileHandle, PrecompileOutput, @@ -41,6 +42,7 @@ fn calculate_gas_cost( mod_length: u64, exponent: &BigUint, exponent_bytes: &[u8], + mod_is_even: bool, ) -> u64 { fn calculate_multiplication_complexity(base_length: u64, mod_length: u64) -> u64 { let max_length = max(base_length, mod_length); @@ -91,6 +93,7 @@ fn calculate_gas_cost( MIN_GAS_COST, multiplication_complexity * iteration_count / 3, ) + .saturating_mul(if mod_is_even { 20 } else { 1 }) } /// Copy bytes from input to target. @@ -196,7 +199,13 @@ impl Precompile for Modexp { let modulus = BigUint::from_bytes_be(&mod_buf); // do our gas accounting - let gas_cost = calculate_gas_cost(base_len as u64, mod_len as u64, &exponent, &exp_buf); + let gas_cost = calculate_gas_cost( + base_len as u64, + mod_len as u64, + &exponent, + &exp_buf, + modulus.is_even(), + ); handle.record_cost(gas_cost)?; @@ -510,6 +519,6 @@ mod tests { let _ = Modexp::execute(&mut handle).expect("Modexp::execute() returned error"); - assert_eq!(handle.gas_used, 7104); // gas used when ran in geth + assert_eq!(handle.gas_used, 7104 * 20); // gas used when ran in geth (x20) } } diff --git a/frame/evm/precompile/sha3fips/src/lib.rs b/frame/evm/precompile/sha3fips/src/lib.rs index d76f9650bb..6f951d35e8 100644 --- a/frame/evm/precompile/sha3fips/src/lib.rs +++ b/frame/evm/precompile/sha3fips/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] extern crate alloc; diff --git a/frame/evm/precompile/simple/src/lib.rs b/frame/evm/precompile/simple/src/lib.rs index df4366679a..0791111fd0 100644 --- a/frame/evm/precompile/simple/src/lib.rs +++ b/frame/evm/precompile/simple/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] extern crate alloc; diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index a6b1406e2d..fdabd8b4ab 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -52,8 +52,9 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -#![allow(clippy::too_many_arguments)] #![cfg_attr(test, feature(assert_matches))] +#![cfg_attr(feature = "runtime-benchmarks", deny(unused_crate_dependencies))] +#![allow(clippy::too_many_arguments)] #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; @@ -84,6 +85,7 @@ use sp_std::{cmp::min, vec::Vec}; pub use evm::{ Config as EvmConfig, Context, ExitError, ExitFatal, ExitReason, ExitRevert, ExitSucceed, }; +use fp_account::AccountId20; #[cfg(feature = "std")] use fp_evm::GenesisAccount; pub use fp_evm::{ @@ -603,6 +605,24 @@ where } } +/// Ensure that the address is AccountId20. +pub struct EnsureAccountId20; + +impl EnsureAddressOrigin for EnsureAccountId20 +where + OuterOrigin: Into, OuterOrigin>> + From>, +{ + type Success = AccountId20; + + fn try_address_origin(address: &H160, origin: OuterOrigin) -> Result { + let acc: AccountId20 = AccountId20::from(*address); + origin.into().and_then(|o| match o { + RawOrigin::Signed(who) if who == acc => Ok(who), + r => Err(OuterOrigin::from(r)), + }) + } +} + pub trait AddressMapping { fn into_account_id(address: H160) -> A; } @@ -610,9 +630,9 @@ pub trait AddressMapping { /// Identity address mapping. pub struct IdentityAddressMapping; -impl AddressMapping for IdentityAddressMapping { - fn into_account_id(address: H160) -> H160 { - address +impl> AddressMapping for IdentityAddressMapping { + fn into_account_id(address: H160) -> T { + address.into() } } diff --git a/frame/evm/src/runner/stack.rs b/frame/evm/src/runner/stack.rs index be39912a48..3193b1c049 100644 --- a/frame/evm/src/runner/stack.rs +++ b/frame/evm/src/runner/stack.rs @@ -130,6 +130,10 @@ where >, ) -> (ExitReason, R), { + // Only check the restrictions of EIP-3607 if the source of the EVM operation is from an external transaction. + // If the source of this EVM operation is from an internal call, like from `eth_call` or `eth_estimateGas` RPC, + // we will skip the checks for the EIP-3607. + // // EIP-3607: https://eips.ethereum.org/EIPS/eip-3607 // Do not allow transactions for which `tx.sender` has any code deployed. // @@ -137,7 +141,9 @@ where // of a precompile. While mainnet Ethereum currently only has stateless precompiles, // projects using Frontier can have stateful precompiles that can manage funds or // which calls other contracts that expects this precompile address to be trustworthy. - if !>::get(source).is_empty() || precompiles.is_precompile(source) { + if is_transactional + && (!>::get(source).is_empty() || precompiles.is_precompile(source)) + { return Err(RunnerError { error: Error::::TransactionMustComeFromEOA, weight, diff --git a/frame/evm/src/tests.rs b/frame/evm/src/tests.rs index 1e8202ea43..65fc0e033b 100644 --- a/frame/evm/src/tests.rs +++ b/frame/evm/src/tests.rs @@ -414,8 +414,10 @@ fn handle_sufficient_reference() { new_test_ext().execute_with(|| { let addr = H160::from_str("1230000000000000000000000000000000000001").unwrap(); let addr_2 = H160::from_str("1234000000000000000000000000000000000001").unwrap(); - let substrate_addr = ::AddressMapping::into_account_id(addr); - let substrate_addr_2 = ::AddressMapping::into_account_id(addr_2); + let substrate_addr: ::AccountId = + ::AddressMapping::into_account_id(addr); + let substrate_addr_2: ::AccountId = + ::AddressMapping::into_account_id(addr_2); // Sufficients should increase when creating EVM accounts. let _ = >::insert(addr, &vec![0]); @@ -559,8 +561,9 @@ fn runner_max_fee_per_gas_gte_max_priority_fee_per_gas() { } #[test] -fn eip3607_transaction_from_contract_should_fail() { +fn eip3607_transaction_from_contract() { new_test_ext().execute_with(|| { + // external transaction match ::Runner::call( // Contract address. H160::from_str("1000000000000000000000000000000000000001").unwrap(), @@ -572,8 +575,8 @@ fn eip3607_transaction_from_contract_should_fail() { None, None, Vec::new(), - false, // non-transactional - true, // must be validated + true, // transactional + false, // not sure be validated &::config().clone(), ) { Err(RunnerError { @@ -582,12 +585,31 @@ fn eip3607_transaction_from_contract_should_fail() { }) => (), _ => panic!("Should have failed"), } + + // internal call + assert!(::Runner::call( + // Contract address. + H160::from_str("1000000000000000000000000000000000000001").unwrap(), + H160::from_str("1000000000000000000000000000000000000001").unwrap(), + Vec::new(), + U256::from(1u32), + 1000000, + None, + None, + None, + Vec::new(), + false, // non-transactional + true, // must be validated + &::config().clone(), + ) + .is_ok()); }); } #[test] -fn eip3607_transaction_from_precompile_should_fail() { +fn eip3607_transaction_from_precompile() { new_test_ext().execute_with(|| { + // external transaction match ::Runner::call( // Precompile address. H160::from_str("0000000000000000000000000000000000000001").unwrap(), @@ -599,8 +621,8 @@ fn eip3607_transaction_from_precompile_should_fail() { None, None, Vec::new(), - false, // non-transactional - true, // must be validated + true, // transactional + false, // not sure be validated &::config().clone(), ) { Err(RunnerError { @@ -609,5 +631,23 @@ fn eip3607_transaction_from_precompile_should_fail() { }) => (), _ => panic!("Should have failed"), } + + // internal call + assert!(::Runner::call( + // Contract address. + H160::from_str("0000000000000000000000000000000000000001").unwrap(), + H160::from_str("1000000000000000000000000000000000000001").unwrap(), + Vec::new(), + U256::from(1u32), + 1000000, + None, + None, + None, + Vec::new(), + false, // non-transactional + true, // must be validated + &::config().clone(), + ) + .is_ok()); }); } diff --git a/frame/evm/test-vector-support/Cargo.toml b/frame/evm/test-vector-support/Cargo.toml index 6434383e44..bfa85744c8 100644 --- a/frame/evm/test-vector-support/Cargo.toml +++ b/frame/evm/test-vector-support/Cargo.toml @@ -13,6 +13,6 @@ hex = "0.4.3" serde = { workspace = true } serde_json = { workspace = true } # Substrate -sp-core = { workspace = true } +sp-core = { workspace = true, features = ["default"] } # Frontier fp-evm = { workspace = true, features = ["default"] } diff --git a/frame/evm/test-vector-support/src/lib.rs b/frame/evm/test-vector-support/src/lib.rs index 5b12131725..fd67f747f9 100644 --- a/frame/evm/test-vector-support/src/lib.rs +++ b/frame/evm/test-vector-support/src/lib.rs @@ -15,6 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![deny(unused_crate_dependencies)] + use std::fs; use evm::{Context, ExitError, ExitReason, ExitSucceed, Transfer}; diff --git a/frame/hotfix-sufficients/Cargo.toml b/frame/hotfix-sufficients/Cargo.toml index 0fbaff4322..e7c75cddda 100644 --- a/frame/hotfix-sufficients/Cargo.toml +++ b/frame/hotfix-sufficients/Cargo.toml @@ -26,7 +26,7 @@ pallet-evm = { workspace = true } [dev-dependencies] # Substrate -sp-io = { workspace = true } +sp-io = { workspace = true, features = ["default"] } [features] default = ["std"] diff --git a/frame/hotfix-sufficients/src/lib.rs b/frame/hotfix-sufficients/src/lib.rs index 37f9f6628b..86a45be36f 100644 --- a/frame/hotfix-sufficients/src/lib.rs +++ b/frame/hotfix-sufficients/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "runtime-benchmarks", deny(unused_crate_dependencies))] #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; diff --git a/frame/hotfix-sufficients/src/tests.rs b/frame/hotfix-sufficients/src/tests.rs index eedbf06aa2..d5effd936e 100644 --- a/frame/hotfix-sufficients/src/tests.rs +++ b/frame/hotfix-sufficients/src/tests.rs @@ -62,8 +62,10 @@ fn test_hotfix_inc_account_sufficients_increments_if_nonce_nonzero() { let addr_2 = "1234000000000000000000000000000000000001" .parse::() .unwrap(); - let substrate_addr_1 = ::AddressMapping::into_account_id(addr_1); - let substrate_addr_2 = ::AddressMapping::into_account_id(addr_2); + let substrate_addr_1: ::AccountId = + ::AddressMapping::into_account_id(addr_1); + let substrate_addr_2: ::AccountId = + ::AddressMapping::into_account_id(addr_2); frame_system::Pallet::::inc_account_nonce(&substrate_addr_1); @@ -95,7 +97,8 @@ fn test_hotfix_inc_account_sufficients_increments_with_saturation_if_nonce_nonze let addr = "1230000000000000000000000000000000000001" .parse::() .unwrap(); - let substrate_addr = ::AddressMapping::into_account_id(addr); + let substrate_addr: ::AccountId = + ::AddressMapping::into_account_id(addr); frame_system::Account::::mutate(substrate_addr, |x| { x.nonce = 1; @@ -125,7 +128,8 @@ fn test_hotfix_inc_account_sufficients_does_not_increment_if_both_nonce_and_refs let addr = "1230000000000000000000000000000000000001" .parse::() .unwrap(); - let substrate_addr = ::AddressMapping::into_account_id(addr); + let substrate_addr: ::AccountId = + ::AddressMapping::into_account_id(addr); frame_system::Account::::mutate(substrate_addr, |x| { x.nonce = 1; diff --git a/primitives/account/Cargo.toml b/primitives/account/Cargo.toml new file mode 100644 index 0000000000..a56506cca1 --- /dev/null +++ b/primitives/account/Cargo.toml @@ -0,0 +1,42 @@ +[package] +name = "fp-account" +version = "1.0.0-dev" +license = "Apache-2.0" +description = "Primitives for Frontier AccountId20." +authors = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } + +[dependencies] +hex = { version = "0.4.3", default-features = false } +impl-serde = { workspace = true, optional = true } +libsecp256k1 = { workspace = true } +log = { workspace = true } +scale-codec = { package = "parity-scale-codec", workspace = true } +scale-info = { workspace = true } +serde = { workspace = true, optional = true } + +# Substrate +sp-core = { workspace = true } +sp-io = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } + +[dev-dependencies] + +[features] +default = ["std"] +std = [ + "hex/std", + "impl-serde/std", + "libsecp256k1/std", + "log/std", + "scale-codec/std", + "scale-info/std", + "serde", + # Substrate + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/primitives/account/src/lib.rs b/primitives/account/src/lib.rs new file mode 100644 index 0000000000..d1be0e8e29 --- /dev/null +++ b/primitives/account/src/lib.rs @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: Apache-2.0 +// This file is part of Frontier. +// +// Copyright (c) 2020-2023 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] + +use scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +// Substrate +use sp_core::{ecdsa, H160, H256}; +use sp_io::hashing::keccak_256; + +/// A fully Ethereum-compatible `AccountId`. +/// Conforms to H160 address and ECDSA key standards. +/// Alternative to H256->H160 mapping. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default)] +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo)] +pub struct AccountId20(pub [u8; 20]); + +#[cfg(feature = "std")] +impl_serde::impl_fixed_hash_serde!(AccountId20, 20); + +#[cfg(feature = "std")] +impl std::str::FromStr for AccountId20 { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + H160::from_str(s) + .map(Into::into) + .map_err(|_| "invalid hex address.") + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for AccountId20 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let address = hex::encode(self.0).trim_start_matches("0x").to_lowercase(); + let address_hash = hex::encode(keccak_256(address.as_bytes())); + + let checksum: String = + address + .char_indices() + .fold(String::from("0x"), |mut acc, (index, address_char)| { + let n = u16::from_str_radix(&address_hash[index..index + 1], 16) + .expect("Keccak256 hashed; qed"); + + if n > 7 { + // make char uppercase if ith character is 9..f + acc.push_str(&address_char.to_uppercase().to_string()) + } else { + // already lowercased + acc.push(address_char) + } + + acc + }); + write!(f, "{}", checksum) + } +} + +impl sp_std::fmt::Debug for AccountId20 { + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + write!(f, "{:?}", H160(self.0)) + } +} + +impl From<[u8; 20]> for AccountId20 { + fn from(bytes: [u8; 20]) -> Self { + Self(bytes) + } +} + +impl From for [u8; 20] { + fn from(val: AccountId20) -> Self { + val.0 + } +} + +impl From for AccountId20 { + fn from(h160: H160) -> Self { + Self(h160.0) + } +} + +impl From for H160 { + fn from(val: AccountId20) -> Self { + H160(val.0) + } +} + +impl From for AccountId20 { + fn from(pk: ecdsa::Public) -> Self { + let decompressed = libsecp256k1::PublicKey::parse_compressed(&pk.0) + .expect("Wrong compressed public key provided") + .serialize(); + let mut m = [0u8; 64]; + m.copy_from_slice(&decompressed[1..65]); + let account = H160::from(H256::from(keccak_256(&m))); + Self(account.into()) + } +} + +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +#[derive(Eq, PartialEq, Clone, Encode, Decode, sp_core::RuntimeDebug, TypeInfo)] +pub struct EthereumSignature(ecdsa::Signature); + +impl sp_runtime::traits::Verify for EthereumSignature { + type Signer = EthereumSigner; + fn verify>(&self, mut msg: L, signer: &AccountId20) -> bool { + let m = keccak_256(msg.get()); + match sp_io::crypto::secp256k1_ecdsa_recover(self.0.as_ref(), &m) { + Ok(pubkey) => AccountId20(H160::from(H256::from(keccak_256(&pubkey))).0) == *signer, + Err(sp_io::EcdsaVerifyError::BadRS) => { + log::error!(target: "evm", "Error recovering: Incorrect value of R or S"); + false + } + Err(sp_io::EcdsaVerifyError::BadV) => { + log::error!(target: "evm", "Error recovering: Incorrect value of V"); + false + } + Err(sp_io::EcdsaVerifyError::BadSignature) => { + log::error!(target: "evm", "Error recovering: Invalid signature"); + false + } + } + } +} + +impl EthereumSignature { + pub fn new(s: ecdsa::Signature) -> Self { + EthereumSignature(s) + } +} + +pub struct EthereumSigner([u8; 20]); + +impl From<[u8; 20]> for EthereumSigner { + fn from(x: [u8; 20]) -> Self { + EthereumSigner(x) + } +} + +impl sp_runtime::traits::IdentifyAccount for EthereumSigner { + type AccountId = AccountId20; + fn into_account(self) -> AccountId20 { + AccountId20(self.0) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Display for EthereumSigner { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "{:?}", H160::from(self.0)) + } +} + +impl From for EthereumSigner { + fn from(pk: ecdsa::Public) -> Self { + let decompressed = libsecp256k1::PublicKey::parse_compressed(&pk.0) + .expect("Wrong compressed public key provided") + .serialize(); + let mut m = [0u8; 64]; + m.copy_from_slice(&decompressed[1..65]); + let account = H160::from(H256::from(keccak_256(&m))); + EthereumSigner(account.into()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::{ecdsa, Pair, H256}; + use sp_runtime::traits::IdentifyAccount; + + #[test] + fn test_derive_from_secret_key() { + let sk = hex::decode("eb3d6b0b0c794f6fd8964b4a28df99d4baa5f9c8d33603c4cc62504daa259358") + .unwrap(); + let hex_acc: [u8; 20] = hex::decode("98fa2838ee6471ae87135880f870a785318e6787") + .unwrap() + .try_into() + .unwrap(); + let acc = AccountId20::from(hex_acc); + + let pk = ecdsa::Pair::from_seed_slice(&sk).unwrap().public(); + let signer: EthereumSigner = pk.into(); + + assert_eq!(signer.into_account(), acc); + } + + #[test] + fn test_from_h160() { + let m = hex::decode("28490327ff4e60d44b8aadf5478266422ed01232cc712c2d617e5c650ca15b85") + .unwrap(); + let old: AccountId20 = H160::from(H256::from(keccak_256(&m))).into(); + let new: AccountId20 = H160::from_slice(&keccak_256(&m)[12..32]).into(); + assert_eq!(new, old); + } + + #[test] + fn test_account_display() { + let pk = ecdsa::Pair::from_string("//Alice", None) + .expect("static values are valid; qed") + .public(); + let signer: EthereumSigner = pk.into(); + let account: AccountId20 = signer.into_account(); + let account_fmt = format!("{}", account); + assert_eq!(account_fmt, "0xE04CC55ebEE1cBCE552f250e85c57B70B2E2625b"); + } +} diff --git a/primitives/consensus/src/lib.rs b/primitives/consensus/src/lib.rs index 370d3a40c6..e9643d8eee 100644 --- a/primitives/consensus/src/lib.rs +++ b/primitives/consensus/src/lib.rs @@ -17,6 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::large_enum_variant)] +#![deny(unused_crate_dependencies)] use scale_codec::{Decode, Encode}; use sp_core::H256; diff --git a/primitives/dynamic-fee/Cargo.toml b/primitives/dynamic-fee/Cargo.toml index 0ddb16636c..6ecd0fefae 100644 --- a/primitives/dynamic-fee/Cargo.toml +++ b/primitives/dynamic-fee/Cargo.toml @@ -11,7 +11,7 @@ repository = { workspace = true } targets = ["x86_64-unknown-linux-gnu"] [dependencies] -async-trait = "0.1" +async-trait = { version = "0.1", optional = true } # Substrate sp-core = { workspace = true } sp-inherents = { workspace = true } @@ -19,6 +19,7 @@ sp-inherents = { workspace = true } [features] default = ["std"] std = [ + "async-trait", # Substrate "sp-core/std", "sp-inherents/std", diff --git a/primitives/dynamic-fee/src/lib.rs b/primitives/dynamic-fee/src/lib.rs index c3f098818a..f2a8101e45 100644 --- a/primitives/dynamic-fee/src/lib.rs +++ b/primitives/dynamic-fee/src/lib.rs @@ -18,6 +18,7 @@ //! Core types and inherents for dynamic fee. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] use sp_core::U256; use sp_inherents::InherentIdentifier; diff --git a/primitives/ethereum/src/lib.rs b/primitives/ethereum/src/lib.rs index eeead1b777..03d7092ea3 100644 --- a/primitives/ethereum/src/lib.rs +++ b/primitives/ethereum/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] pub use ethereum::{ AccessListItem, BlockV2 as Block, LegacyTransactionMessage, Log, ReceiptV3 as Receipt, diff --git a/primitives/evm/src/lib.rs b/primitives/evm/src/lib.rs index 43e0929cda..b7e8e38741 100644 --- a/primitives/evm/src/lib.rs +++ b/primitives/evm/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] mod precompile; mod validation; diff --git a/primitives/rpc/src/lib.rs b/primitives/rpc/src/lib.rs index e3db39a597..6193ba8bad 100644 --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -17,6 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::too_many_arguments)] +#![deny(unused_crate_dependencies)] use ethereum::Log; use ethereum_types::Bloom; diff --git a/primitives/self-contained/src/lib.rs b/primitives/self-contained/src/lib.rs index 3cc392cb94..e3590f6e55 100644 --- a/primitives/self-contained/src/lib.rs +++ b/primitives/self-contained/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] mod checked_extrinsic; mod unchecked_extrinsic; diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs index 81a9e89c7d..db845bc2e2 100644 --- a/primitives/storage/src/lib.rs +++ b/primitives/storage/src/lib.rs @@ -16,6 +16,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![deny(unused_crate_dependencies)] use scale_codec::{Decode, Encode}; diff --git a/rustfmt.toml b/rustfmt.toml index d66360b1bf..67966db319 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,4 @@ hard_tabs = true imports_granularity = "Crate" use_field_init_shorthand = true +merge_derives = false diff --git a/shell.nix b/shell.nix index 51b64ce669..b4c47b9b6f 100644 --- a/shell.nix +++ b/shell.nix @@ -2,7 +2,7 @@ let mozillaOverlay = import (builtins.fetchGit { url = "https://github.com/mozilla/nixpkgs-mozilla.git"; - rev = "4a07484cf0e49047f82d83fd119acffbad3b235f"; + rev = "78e723925daf5c9e8d0a1837ec27059e61649cb6"; }); nixpkgs = import { overlays = [ mozillaOverlay ]; }; rust-nightly = with nixpkgs; ((rustChannelOf { date = "2022-11-16"; channel = "nightly"; }).rust.override { diff --git a/template/node/Cargo.toml b/template/node/Cargo.toml index 24659746e6..d0c60a4119 100644 --- a/template/node/Cargo.toml +++ b/template/node/Cargo.toml @@ -24,6 +24,7 @@ serde = { workspace = true } # Substrate prometheus-endpoint = { package = "substrate-prometheus-endpoint", workspace = true } sc-basic-authorship = { workspace = true } +sc-chain-spec = { workspace = true } sc-cli = { workspace = true } sc-client-api = { workspace = true } sc-consensus = { workspace = true } @@ -46,7 +47,6 @@ sp-consensus-aura = { workspace = true, features = ["default"] } sp-core = { workspace = true, features = ["default"] } sp-finality-grandpa = { workspace = true, features = ["default"] } sp-inherents = { workspace = true, features = ["default"] } -sp-keyring = { workspace = true } sp-offchain = { workspace = true, features = ["default"] } sp-runtime = { workspace = true, features = ["default"] } sp-session = { workspace = true, features = ["default"] } @@ -74,6 +74,7 @@ fc-mapping-sync = { workspace = true } fc-rpc = { workspace = true } fc-rpc-core = { workspace = true } fc-storage = { workspace = true } +fp-account = { workspace = true } fp-dynamic-fee = { workspace = true, features = ["default"] } fp-evm = { workspace = true, features = ["default"] } fp-rpc = { workspace = true, features = ["default"] } diff --git a/template/node/src/benchmarking.rs b/template/node/src/benchmarking.rs index d0d5b5d584..81b88077b5 100644 --- a/template/node/src/benchmarking.rs +++ b/template/node/src/benchmarking.rs @@ -25,11 +25,11 @@ use scale_codec::Encode; // Substrate use sc_cli::Result; use sc_client_api::BlockBackend; -use sp_core::{sr25519, Pair}; +use sp_core::{ecdsa, Pair}; use sp_inherents::{InherentData, InherentDataProvider}; -use sp_keyring::Sr25519Keyring; -use sp_runtime::{generic::Era, AccountId32, OpaqueExtrinsic, SaturatedConversion}; +use sp_runtime::{generic::Era, OpaqueExtrinsic, SaturatedConversion}; // Frontier +use fp_account::AccountId20; use frontier_template_runtime::{self as runtime, AccountId, Balance, BalancesCall, SystemCall}; use crate::client::Client; @@ -58,7 +58,7 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder { } fn build(&self, nonce: u32) -> std::result::Result { - let acc = Sr25519Keyring::Bob.pair(); + let acc = ecdsa::Pair::from_string("//Bob", None).expect("static values are valid; qed"); let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( self.client.as_ref(), acc, @@ -101,12 +101,12 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { } fn build(&self, nonce: u32) -> std::result::Result { - let acc = Sr25519Keyring::Bob.pair(); + let acc = ecdsa::Pair::from_string("//Bob", None).expect("static values are valid; qed"); let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( self.client.as_ref(), acc, BalancesCall::transfer_keep_alive { - dest: self.dest.clone().into(), + dest: self.dest.into(), value: self.value, } .into(), @@ -123,7 +123,7 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { /// Note: Should only be used for benchmarking. pub fn create_benchmark_extrinsic( client: &Client, - sender: sr25519::Pair, + sender: ecdsa::Pair, call: runtime::RuntimeCall, nonce: u32, ) -> runtime::UncheckedExtrinsic { @@ -171,8 +171,8 @@ pub fn create_benchmark_extrinsic( runtime::UncheckedExtrinsic::new_signed( call, - AccountId32::from(sender.public()).into(), - runtime::Signature::Sr25519(signature), + AccountId20::from(sender.public()).into(), + runtime::Signature::new(signature), extra, ) } diff --git a/template/node/src/chain_spec.rs b/template/node/src/chain_spec.rs index b4b1ffe392..e09fa944c2 100644 --- a/template/node/src/chain_spec.rs +++ b/template/node/src/chain_spec.rs @@ -2,15 +2,15 @@ use std::{collections::BTreeMap, str::FromStr}; use serde::{Deserialize, Serialize}; // Substrate -use sc_service::ChainType; +use sc_chain_spec::{ChainType, Properties}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_core::{sr25519, storage::Storage, Pair, Public, H160, U256}; +use sp_core::{ecdsa, storage::Storage, Pair, Public, H160, U256}; use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; use sp_state_machine::BasicExternalities; // Frontier use frontier_template_runtime::{ - AccountId, EnableManualSeal, GenesisConfig, Signature, WASM_BINARY, + AccountId, EnableManualSeal, GenesisConfig, SS58Prefix, Signature, WASM_BINARY, }; // The URL for the telemetry server. @@ -64,6 +64,13 @@ pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { (get_from_seed::(s), get_from_seed::(s)) } +fn properties() -> Properties { + let mut properties = Properties::new(); + properties.insert("tokenDecimals".into(), 18.into()); + properties.insert("ss58Format".into(), SS58Prefix::get().into()); + properties +} + pub fn development_config(enable_manual_seal: Option) -> DevChainSpec { let wasm_binary = WASM_BINARY.expect("WASM not available"); @@ -78,17 +85,18 @@ pub fn development_config(enable_manual_seal: Option) -> DevChainSpec { genesis_config: testnet_genesis( wasm_binary, // Sudo account - get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Alice"), // Pre-funded accounts vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), ], // Initial PoA authorities vec![authority_keys_from_seed("Alice")], - 42, + // Ethereum chain ID + SS58Prefix::get() as u64, ), enable_manual_seal, } @@ -99,9 +107,10 @@ pub fn development_config(enable_manual_seal: Option) -> DevChainSpec { None, // Protocol ID None, + // Fork ID None, // Properties - None, + Some(properties()), // Extensions None, ) @@ -121,21 +130,21 @@ pub fn local_testnet_config() -> ChainSpec { wasm_binary, // Initial PoA authorities // Sudo account - get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Alice"), // Pre-funded accounts vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), ], vec![ authority_keys_from_seed("Alice"), diff --git a/template/node/src/command.rs b/template/node/src/command.rs index 975ee556b4..f8dc8e30e3 100644 --- a/template/node/src/command.rs +++ b/template/node/src/command.rs @@ -27,6 +27,9 @@ use crate::{ service::{self, db_config_dir}, }; +#[cfg(feature = "runtime-benchmarks")] +use crate::chain_spec::get_account_id_from_seed; + impl SubstrateCli for Cli { fn impl_name() -> String { "Frontier Node".into() @@ -187,7 +190,7 @@ pub fn run() -> sc_cli::Result<()> { Box::new(RemarkBuilder::new(client.clone())), Box::new(TransferKeepAliveBuilder::new( client.clone(), - sp_keyring::Sr25519Keyring::Alice.to_account_id(), + get_account_id_from_seed::("Alice"), ExistentialDeposit::get(), )), ]); diff --git a/template/node/src/main.rs b/template/node/src/main.rs index 3adb9624c0..94c4643c1b 100644 --- a/template/node/src/main.rs +++ b/template/node/src/main.rs @@ -6,6 +6,7 @@ clippy::too_many_arguments, clippy::large_enum_variant )] +#![cfg_attr(feature = "runtime-benchmarks", deny(unused_crate_dependencies))] #[cfg(feature = "runtime-benchmarks")] mod benchmarking; diff --git a/template/runtime/Cargo.toml b/template/runtime/Cargo.toml index e20acb7a9f..a870753908 100644 --- a/template/runtime/Cargo.toml +++ b/template/runtime/Cargo.toml @@ -43,6 +43,7 @@ pallet-transaction-payment = { workspace = true } pallet-transaction-payment-rpc-runtime-api = { workspace = true } # Frontier +fp-account = { workspace = true } fp-evm = { workspace = true } fp-rpc = { workspace = true } fp-self-contained = { workspace = true } @@ -95,6 +96,7 @@ std = [ "pallet-transaction-payment/std", "pallet-transaction-payment-rpc-runtime-api/std", # Frontier + "fp-account/std", "fp-evm/std", "fp-rpc/std", "fp-self-contained/std", diff --git a/template/runtime/src/lib.rs b/template/runtime/src/lib.rs index 4b0aec6759..b196b4d97f 100644 --- a/template/runtime/src/lib.rs +++ b/template/runtime/src/lib.rs @@ -4,6 +4,7 @@ // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit = "256"] #![allow(clippy::new_without_default, clippy::or_fun_call)] +#![cfg_attr(feature = "runtime-benchmarks", deny(unused_crate_dependencies))] // Make the WASM binary available. #[cfg(feature = "std")] @@ -23,7 +24,7 @@ use sp_runtime::{ IdentifyAccount, NumberFor, PostDispatchInfoOf, UniqueSaturatedInto, Verify, }, transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, - ApplyExtrinsicResult, ConsensusEngineId, MultiSignature, Perbill, Permill, + ApplyExtrinsicResult, ConsensusEngineId, Perbill, Permill, }; use sp_std::{marker::PhantomData, prelude::*}; use sp_version::RuntimeVersion; @@ -42,11 +43,12 @@ use pallet_grandpa::{ }; use pallet_transaction_payment::CurrencyAdapter; // Frontier +use fp_account::EthereumSignature; use fp_evm::weight_per_gas; use fp_rpc::TransactionStatus; use pallet_ethereum::{Call::transact, PostLogContent, Transaction as EthereumTransaction}; use pallet_evm::{ - Account as EVMAccount, EnsureAddressTruncated, FeeCalculator, HashedAddressMapping, Runner, + Account as EVMAccount, EnsureAccountId20, FeeCalculator, IdentityAddressMapping, Runner, }; // A few exports that help ease life for downstream crates. @@ -61,7 +63,7 @@ use precompiles::FrontierPrecompiles; pub type BlockNumber = u32; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; +pub type Signature = EthereumSignature; /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. @@ -108,8 +110,8 @@ pub mod opaque { } pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("node-frontier-template"), - impl_name: create_runtime_str!("node-frontier-template"), + spec_name: create_runtime_str!("frontier-template"), + impl_name: create_runtime_str!("frontier-template"), authoring_version: 1, spec_version: 1, impl_version: 1, @@ -330,9 +332,9 @@ impl pallet_evm::Config for Runtime { type GasWeightMapping = pallet_evm::FixedGasWeightMapping; type WeightPerGas = WeightPerGas; type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping; - type CallOrigin = EnsureAddressTruncated; - type WithdrawOrigin = EnsureAddressTruncated; - type AddressMapping = HashedAddressMapping; + type CallOrigin = EnsureAccountId20; + type WithdrawOrigin = EnsureAccountId20; + type AddressMapping = IdentityAddressMapping; type Currency = Balances; type RuntimeEvent = RuntimeEvent; type PrecompilesType = FrontierPrecompiles; @@ -389,7 +391,7 @@ impl pallet_base_fee::Config for Runtime { } impl pallet_hotfix_sufficients::Config for Runtime { - type AddressMapping = HashedAddressMapping; + type AddressMapping = IdentityAddressMapping; type WeightInfo = pallet_hotfix_sufficients::weights::SubstrateWeight; } diff --git a/ts-tests/tests/config.ts b/ts-tests/tests/config.ts index 8fa1702b75..aae797f0e8 100644 --- a/ts-tests/tests/config.ts +++ b/ts-tests/tests/config.ts @@ -6,7 +6,7 @@ export const FIRST_CONTRACT_ADDRESS = "0xc2bf5f29a4384b1ab0c063e1c666f02121b6084 export const NODE_BINARY_NAME = "frontier-template-node"; -export const RUNTIME_SPEC_NAME = "node-frontier-template"; +export const RUNTIME_SPEC_NAME = "frontier-template"; export const RUNTIME_SPEC_VERSION = 1; export const RUNTIME_IMPL_VERSION = 1;