diff --git a/Cargo.lock b/Cargo.lock index f4be38e6cd..83171215a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,11 +73,11 @@ dependencies = [ "evm", "frame-support", "hex-literal 0.3.3", + "module-evm-utiltity-macro", "num_enum", "nutsfinance-stable-asset", "parity-scale-codec", "parity-util-mem", - "primitives-proc-macro", "scale-info", "serde", "serde_json", @@ -5505,13 +5505,13 @@ dependencies = [ "frame-system", "impl-trait-for-tuples 0.2.1", "module-evm", + "module-evm-utiltity-macro", "module-support", "num_enum", "pallet-balances", "pallet-timestamp", "parity-scale-codec", "primitive-types", - "primitives-proc-macro", "scale-info", "serde", "sp-core", @@ -5557,6 +5557,23 @@ dependencies = [ "sp-std", ] +[[package]] +name = "module-evm-utiltity" +version = "1.5.1" +dependencies = [ + "sha3 0.9.1", +] + +[[package]] +name = "module-evm-utiltity-macro" +version = "1.5.1" +dependencies = [ + "module-evm-utiltity", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "module-example" version = "1.5.1" @@ -9199,17 +9216,6 @@ dependencies = [ "uint", ] -[[package]] -name = "primitives-proc-macro" -version = "1.5.1" -dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "sha3 0.9.1", - "syn", -] - [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -9869,6 +9875,7 @@ dependencies = [ "module-evm", "module-evm-bridge", "module-evm-manager", + "module-evm-utiltity-macro", "module-nft", "module-prices", "module-staking-pool", @@ -9887,7 +9894,6 @@ dependencies = [ "pallet-timestamp", "pallet-utility", "parity-scale-codec", - "primitives-proc-macro", "scale-info", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 36182a9420..3fd30f1ce0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,9 @@ members = [ "node/service", "modules/*", + "modules/evm-utiltity/macro", "inspect", "primitives", - "primitives/proc-macro", "rpc", "runtime/common", diff --git a/modules/evm-bridge/Cargo.toml b/modules/evm-bridge/Cargo.toml index 647f75cc37..4ab4fb451e 100644 --- a/modules/evm-bridge/Cargo.toml +++ b/modules/evm-bridge/Cargo.toml @@ -21,9 +21,9 @@ primitive-types = { version = "0.10.1", default-features = false, features = ["r impl-trait-for-tuples = "0.2.1" ethereum-types = { version = "0.12.0", default-features = false } primitives = { package = "acala-primitives", path = "../../primitives", default-features = false } -primitives-proc-macro = { path = "../../primitives/proc-macro" } support = { package = "module-support", path = "../support", default-features = false } module-evm = { path = "../evm", default-features = false } +module-evm-utiltity-macro = { path = "../evm-utiltity/macro" } num_enum = { version = "0.5.1", default-features = false } [dev-dependencies] diff --git a/modules/evm-bridge/src/lib.rs b/modules/evm-bridge/src/lib.rs index 92a305d95a..5e767f0fb0 100644 --- a/modules/evm-bridge/src/lib.rs +++ b/modules/evm-bridge/src/lib.rs @@ -35,7 +35,7 @@ use support::{EVMBridge as EVMBridgeTrait, ExecutionMode, InvokeContext, EVM}; type AccountIdOf = ::AccountId; type BalanceOf = <::EVM as EVM>>::Balance; -#[primitives_proc_macro::generate_function_selector] +#[module_evm_utiltity_macro::generate_function_selector] #[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] #[repr(u32)] pub enum Action { diff --git a/modules/evm-utiltity/Cargo.toml b/modules/evm-utiltity/Cargo.toml new file mode 100644 index 0000000000..31f4dceea3 --- /dev/null +++ b/modules/evm-utiltity/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "module-evm-utiltity" +version = "1.5.1" +authors = ["Acala Developers"] +edition = "2018" + +[dependencies] +sha3 = { version = "0.9.1" } diff --git a/modules/evm-utiltity/macro/Cargo.toml b/modules/evm-utiltity/macro/Cargo.toml new file mode 100644 index 0000000000..122e184572 --- /dev/null +++ b/modules/evm-utiltity/macro/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "module-evm-utiltity-macro" +version = "1.5.1" +authors = ["Acala Developers"] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +quote = "1.0.10" +syn = { version = "1.0.80", features = ["full", "fold", "extra-traits", "visit"] } +proc-macro2 = "1.0.30" +module-evm-utiltity = { path = ".." } diff --git a/primitives/proc-macro/src/lib.rs b/modules/evm-utiltity/macro/src/lib.rs similarity index 82% rename from primitives/proc-macro/src/lib.rs rename to modules/evm-utiltity/macro/src/lib.rs index 0644ad2f43..3c91352932 100644 --- a/primitives/proc-macro/src/lib.rs +++ b/modules/evm-utiltity/macro/src/lib.rs @@ -19,9 +19,7 @@ use proc_macro::TokenStream; use proc_macro2::Literal; use quote::quote; -use sha3::{Digest, Keccak256}; -use std::convert::TryInto; -use syn::{parse_macro_input, Expr, ExprLit, Ident, ItemEnum, Lit}; +use syn::{parse_macro_input, Expr, ExprLit, Ident, ItemEnum, Lit, LitByteStr, LitStr}; #[proc_macro_attribute] pub fn generate_function_selector(_: TokenStream, input: TokenStream) -> TokenStream { @@ -41,7 +39,7 @@ pub fn generate_function_selector(_: TokenStream, input: TokenStream) -> TokenSt for variant in variants { if let Some((_, Expr::Lit(ExprLit { lit, .. }))) = variant.discriminant { if let Lit::Str(token) = lit { - let selector = get_function_selector(&token.value()); + let selector = module_evm_utiltity::get_function_selector(&token.value()); // println!("method: {:?}, selector: {:?}", token.value(), selector); ident_expressions.push(variant.ident); variant_expressions.push(Expr::Lit(ExprLit { @@ -67,12 +65,13 @@ pub fn generate_function_selector(_: TokenStream, input: TokenStream) -> TokenSt .into() } -fn get_function_selector(s: &str) -> u32 { - // create a SHA3-256 object - let mut hasher = Keccak256::new(); - // write input message - hasher.update(s); - // read hash digest - let result = hasher.finalize(); - u32::from_be_bytes(result[..4].try_into().unwrap()) +#[proc_macro] +pub fn keccak256(input: TokenStream) -> TokenStream { + let lit_str = parse_macro_input!(input as LitStr); + + let result = module_evm_utiltity::sha3_256(&lit_str.value()); + + let eval = Lit::ByteStr(LitByteStr::new(&result.to_vec(), proc_macro2::Span::call_site())); + + quote!(#eval).into() } diff --git a/modules/evm-utiltity/macro/tests/test.rs b/modules/evm-utiltity/macro/tests/test.rs new file mode 100644 index 0000000000..b2e0ab7757 --- /dev/null +++ b/modules/evm-utiltity/macro/tests/test.rs @@ -0,0 +1,54 @@ +// This file is part of Acala. + +// Copyright (C) 2020-2021 Acala Foundation. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#[cfg(test)] +mod tests { + #[test] + fn generate_function_selector_works() { + #[module_evm_utiltity_macro::generate_function_selector] + #[derive(Debug, Eq, PartialEq)] + #[repr(u32)] + pub enum Action { + Name = "name()", + Symbol = "symbol()", + Decimals = "decimals()", + TotalSupply = "totalSupply()", + BalanceOf = "balanceOf(address)", + Transfer = "transfer(address,uint256)", + } + + assert_eq!(Action::Name as u32, 0x06fdde03_u32); + assert_eq!(Action::Symbol as u32, 0x95d89b41_u32); + assert_eq!(Action::Decimals as u32, 0x313ce567_u32); + assert_eq!(Action::TotalSupply as u32, 0x18160ddd_u32); + assert_eq!(Action::BalanceOf as u32, 0x70a08231_u32); + assert_eq!(Action::Transfer as u32, 0xa9059cbb_u32); + } + + #[test] + fn keccak256_works() { + assert_eq!( + module_evm_utiltity_macro::keccak256!(""), + &module_evm_utiltity::sha3_256("") + ); + assert_eq!( + module_evm_utiltity_macro::keccak256!("keccak256"), + &module_evm_utiltity::sha3_256("keccak256") + ); + } +} diff --git a/modules/evm-utiltity/src/lib.rs b/modules/evm-utiltity/src/lib.rs new file mode 100644 index 0000000000..919117d85c --- /dev/null +++ b/modules/evm-utiltity/src/lib.rs @@ -0,0 +1,42 @@ +// This file is part of Acala. + +// Copyright (C) 2020-2021 Acala Foundation. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! # Evm utiltity Module +//! +//! A pallet provides some utility methods. + +use sha3::{Digest, Keccak256}; +use std::convert::TryInto; + +pub fn sha3_256(s: &str) -> [u8; 32] { + let mut result = [0u8; 32]; + + // create a SHA3-256 object + let mut hasher = Keccak256::new(); + // write input message + hasher.update(s); + // read hash digest + result.copy_from_slice(&hasher.finalize()[..32]); + + result +} + +pub fn get_function_selector(s: &str) -> u32 { + let result = sha3_256(s); + u32::from_be_bytes(result[..4].try_into().unwrap()) +} diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 8d9c696042..ef3be14a82 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -27,11 +27,11 @@ ethereum = { git = "https://github.com/PureStake/ethereum", branch = "joshy-scal evm = { git = "https://github.com/PureStake/evm", branch = "joshy-scale-info", default-features = false, features = ["with-codec"] } nutsfinance-stable-asset = { version = "0.1.0", default-features = false, path = "../ecosystem-modules/stable-asset/lib/stable-asset", package = "nutsfinance-stable-asset" } +module-evm-utiltity-macro = { path = "../modules/evm-utiltity/macro" } [dev-dependencies] serde_json = { version = "1.0.64" } hex-literal = "0.3.1" -primitives-proc-macro = { path = "./proc-macro" } [features] default = ["std"] diff --git a/primitives/proc-macro/Cargo.toml b/primitives/proc-macro/Cargo.toml deleted file mode 100644 index 33e79c859c..0000000000 --- a/primitives/proc-macro/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "primitives-proc-macro" -version = "1.5.1" -authors = ["Acala Developers"] -edition = "2018" - -[lib] -proc-macro = true - -[dependencies] -sha3 = { version = "0.9.1" } -quote = "1.0.3" -syn = { version = "1.0.58", features = ["full", "fold", "extra-traits", "visit"] } -proc-macro2 = "1.0.6" -proc-macro-crate = "1.0.0" diff --git a/primitives/src/tests.rs b/primitives/src/tests.rs index db7ec5c129..e55f01d595 100644 --- a/primitives/src/tests.rs +++ b/primitives/src/tests.rs @@ -121,7 +121,7 @@ fn currency_id_try_into_evm_address_works() { #[test] fn generate_function_selector_works() { - #[primitives_proc_macro::generate_function_selector] + #[module_evm_utiltity_macro::generate_function_selector] #[derive(RuntimeDebug, Eq, PartialEq)] #[repr(u32)] pub enum Action { diff --git a/primitives/src/unchecked_extrinsic.rs b/primitives/src/unchecked_extrinsic.rs index 6ed1c06a67..d4ab34048f 100644 --- a/primitives/src/unchecked_extrinsic.rs +++ b/primitives/src/unchecked_extrinsic.rs @@ -27,6 +27,7 @@ use frame_support::{ traits::ExtrinsicCall, weights::{DispatchInfo, GetDispatchInfo}, }; +use module_evm_utiltity_macro::keccak256; use scale_info::TypeInfo; use sp_core::{H160, H256, U256}; use sp_io::{crypto::secp256k1_ecdsa_recover, hashing::keccak_256}; @@ -206,16 +207,12 @@ fn recover_signer(sig: &[u8; 65], msg_hash: &[u8; 32]) -> Option { } fn verify_eip712_signature(eth_msg: EthereumTransactionMessage, sig: [u8; 65]) -> Option { - // TODO: do the hash at compile time - let eip712_domain = b"EIP712Domain(string name,string version,uint256 chainId,bytes32 salt)"; - let tx_type = b"Transaction(string action,address to,uint256 nonce,uint256 tip,bytes data,uint256 value,uint256 gasLimit,uint256 storageLimit,uint256 validUntil)"; - - let domain_hash = keccak_256(eip712_domain); - let tx_type_hash = keccak_256(tx_type); + let domain_hash = keccak256!("EIP712Domain(string name,string version,uint256 chainId,bytes32 salt)"); + let tx_type_hash = keccak256!("Transaction(string action,address to,uint256 nonce,uint256 tip,bytes data,uint256 value,uint256 gasLimit,uint256 storageLimit,uint256 validUntil)"); let mut domain_seperator_msg = domain_hash.to_vec(); - domain_seperator_msg.extend_from_slice(&keccak_256(b"Acala EVM")); // name - domain_seperator_msg.extend_from_slice(&keccak_256(b"1")); // version + domain_seperator_msg.extend_from_slice(keccak256!("Acala EVM")); // name + domain_seperator_msg.extend_from_slice(keccak256!("1")); // version domain_seperator_msg.extend_from_slice(&to_bytes(eth_msg.chain_id)); // chain id domain_seperator_msg.extend_from_slice(eth_msg.genesis.as_bytes()); // salt let domain_separator = keccak_256(domain_seperator_msg.as_slice()); @@ -223,11 +220,11 @@ fn verify_eip712_signature(eth_msg: EthereumTransactionMessage, sig: [u8; 65]) - let mut tx_msg = tx_type_hash.to_vec(); match eth_msg.action { TransactionAction::Call(to) => { - tx_msg.extend_from_slice(&keccak_256(b"Call")); + tx_msg.extend_from_slice(keccak256!("Call")); tx_msg.extend_from_slice(H256::from(to).as_bytes()); } TransactionAction::Create => { - tx_msg.extend_from_slice(&keccak_256(b"Create")); + tx_msg.extend_from_slice(keccak256!("Create")); tx_msg.extend_from_slice(H256::default().as_bytes()); } } diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index def4405238..62c1d6f18b 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -27,10 +27,10 @@ orml-oracle = { path = "../../orml/oracle", default-features = false } orml-traits = { path = "../../orml/traits", default-features = false } module-evm = { path = "../../modules/evm", default-features = false } +module-evm-utiltity-macro = { path = "../../modules/evm-utiltity/macro" } module-staking-pool = { path = "../../modules/staking-pool", default-features = false } module-support = { path = "../../modules/support", default-features = false } primitives = { package = "acala-primitives", path = "../../primitives", default-features = false } -primitives-proc-macro = { path = "../../primitives/proc-macro" } [dev-dependencies] serde_json = "1.0.64" diff --git a/runtime/common/src/precompile/dex.rs b/runtime/common/src/precompile/dex.rs index 74c6410417..5c9893d4f1 100644 --- a/runtime/common/src/precompile/dex.rs +++ b/runtime/common/src/precompile/dex.rs @@ -39,7 +39,7 @@ pub struct DexPrecompile( PhantomData<(AccountId, AddressMapping, CurrencyIdMapping, Dex)>, ); -#[primitives_proc_macro::generate_function_selector] +#[module_evm_utiltity_macro::generate_function_selector] #[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] #[repr(u32)] pub enum Action { diff --git a/runtime/common/src/precompile/multicurrency.rs b/runtime/common/src/precompile/multicurrency.rs index 0f8f6092b2..d5d3d95cde 100644 --- a/runtime/common/src/precompile/multicurrency.rs +++ b/runtime/common/src/precompile/multicurrency.rs @@ -42,7 +42,7 @@ pub struct MultiCurrencyPrecompile, ); -#[primitives_proc_macro::generate_function_selector] +#[module_evm_utiltity_macro::generate_function_selector] #[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] #[repr(u32)] pub enum Action { diff --git a/runtime/common/src/precompile/nft.rs b/runtime/common/src/precompile/nft.rs index 185f8f8c1d..e2c4885091 100644 --- a/runtime/common/src/precompile/nft.rs +++ b/runtime/common/src/precompile/nft.rs @@ -42,7 +42,7 @@ pub struct NFTPrecompile( PhantomData<(AccountId, AddressMapping, CurrencyIdMapping, NFT)>, ); -#[primitives_proc_macro::generate_function_selector] +#[module_evm_utiltity_macro::generate_function_selector] #[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] #[repr(u32)] pub enum Action { diff --git a/runtime/common/src/precompile/oracle.rs b/runtime/common/src/precompile/oracle.rs index 7b15618435..bf3423d73d 100644 --- a/runtime/common/src/precompile/oracle.rs +++ b/runtime/common/src/precompile/oracle.rs @@ -40,7 +40,7 @@ pub struct OraclePrecompile, ); -#[primitives_proc_macro::generate_function_selector] +#[module_evm_utiltity_macro::generate_function_selector] #[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] #[repr(u32)] pub enum Action { diff --git a/runtime/common/src/precompile/schedule_call.rs b/runtime/common/src/precompile/schedule_call.rs index 9e95632620..5c9c98c2b1 100644 --- a/runtime/common/src/precompile/schedule_call.rs +++ b/runtime/common/src/precompile/schedule_call.rs @@ -85,7 +85,7 @@ pub struct ScheduleCallPrecompile< )>, ); -#[primitives_proc_macro::generate_function_selector] +#[module_evm_utiltity_macro::generate_function_selector] #[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] #[repr(u32)] pub enum Action { diff --git a/runtime/common/src/precompile/state_rent.rs b/runtime/common/src/precompile/state_rent.rs index a4a818ea76..ee1594260a 100644 --- a/runtime/common/src/precompile/state_rent.rs +++ b/runtime/common/src/precompile/state_rent.rs @@ -43,7 +43,7 @@ pub struct StateRentPrecompile, ); -#[primitives_proc_macro::generate_function_selector] +#[module_evm_utiltity_macro::generate_function_selector] #[derive(RuntimeDebug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] #[repr(u32)] pub enum Action {