diff --git a/frame/ethereum/src/lib.rs b/frame/ethereum/src/lib.rs index 56eb6b3fd4..676109dfdd 100644 --- a/frame/ethereum/src/lib.rs +++ b/frame/ethereum/src/lib.rs @@ -33,9 +33,7 @@ mod tests; use ethereum_types::{Bloom, BloomInput, H160, H256, H64, U256}; use evm::ExitReason; use fp_consensus::{PostLog, PreLog, FRONTIER_ENGINE_ID}; -use fp_ethereum::{ - TransactionData, TransactionValidationError, ValidatedTransaction as ValidatedTransactionT, -}; +use fp_ethereum::{TransactionValidationError, ValidatedTransaction as ValidatedTransactionT}; use fp_evm::{ CallOrCreateInfo, CheckEvmTransaction, CheckEvmTransactionConfig, InvalidEvmTransactionError, }; @@ -63,6 +61,7 @@ pub use ethereum::{ AccessListItem, BlockV2 as Block, LegacyTransactionMessage, Log, ReceiptV3 as Receipt, TransactionAction, TransactionV2 as Transaction, }; +pub use fp_ethereum::TransactionData; pub use fp_rpc::TransactionStatus; #[derive(Clone, Eq, PartialEq, RuntimeDebug)] @@ -353,15 +352,17 @@ pub mod pallet { } impl Pallet { - /// The call wrapped in the extrinsic is part of the PoV, record this as a base cost for the size of the proof. - fn proof_size_base_cost(transaction: &Transaction) -> u64 { - transaction - .encode() - .len() - // pallet index - .saturating_add(1) - // call index - .saturating_add(1) as u64 + pub fn transaction_weight(transaction_data: &TransactionData) -> (Option, Option) { + match ::GasWeightMapping::gas_to_weight( + transaction_data.gas_limit.unique_saturated_into(), + true, + ) { + weight_limit if weight_limit.proof_size() > 0 => ( + Some(weight_limit), + Some(transaction_data.proof_size_base_cost.unwrap_or_default()), + ), + _ => (None, None), + } } fn recover_signer(transaction: &Transaction) -> Option { @@ -483,19 +484,7 @@ impl Pallet { ) -> TransactionValidity { let transaction_data: TransactionData = transaction.into(); let transaction_nonce = transaction_data.nonce; - - let (weight_limit, proof_size_base_cost) = - match ::GasWeightMapping::gas_to_weight( - transaction_data.gas_limit.unique_saturated_into(), - true, - ) { - weight_limit if weight_limit.proof_size() > 0 => ( - Some(weight_limit), - Some(Self::proof_size_base_cost(transaction)), - ), - _ => (None, None), - }; - + let (weight_limit, proof_size_base_cost) = Self::transaction_weight(&transaction_data); let (base_fee, _) = T::FeeCalculator::min_gas_price(); let (who, _) = pallet_evm::Pallet::::account_basic(&origin); @@ -714,6 +703,11 @@ impl Pallet { (Option, Option, CallOrCreateInfo), DispatchErrorWithPostInfo, > { + let transaction_data: TransactionData = transaction.into(); + let (weight_limit, proof_size_base_cost) = Self::transaction_weight(&transaction_data); + let is_transactional = true; + let validate = false; + let ( input, value, @@ -774,20 +768,6 @@ impl Pallet { } }; - let is_transactional = true; - let validate = false; - - let (proof_size_base_cost, weight_limit) = - match ::GasWeightMapping::gas_to_weight( - gas_limit.unique_saturated_into(), - true, - ) { - weight_limit if weight_limit.proof_size() > 0 => ( - Some(Self::proof_size_base_cost(transaction)), - Some(weight_limit), - ), - _ => (None, None), - }; match action { ethereum::TransactionAction::Call(target) => { let res = match T::Runner::call( @@ -862,22 +842,10 @@ impl Pallet { transaction: &Transaction, ) -> Result<(), TransactionValidityError> { let transaction_data: TransactionData = transaction.into(); - + let (weight_limit, proof_size_base_cost) = Self::transaction_weight(&transaction_data); let (base_fee, _) = T::FeeCalculator::min_gas_price(); let (who, _) = pallet_evm::Pallet::::account_basic(&origin); - let (weight_limit, proof_size_base_cost) = - match ::GasWeightMapping::gas_to_weight( - transaction_data.gas_limit.unique_saturated_into(), - true, - ) { - weight_limit if weight_limit.proof_size() > 0 => ( - Some(weight_limit), - Some(Self::proof_size_base_cost(transaction)), - ), - _ => (None, None), - }; - let _ = CheckEvmTransaction::::new( CheckEvmTransactionConfig { evm_config: T::config(), diff --git a/primitives/ethereum/src/lib.rs b/primitives/ethereum/src/lib.rs index 03d7092ea3..b9e9726cba 100644 --- a/primitives/ethereum/src/lib.rs +++ b/primitives/ethereum/src/lib.rs @@ -59,6 +59,49 @@ pub struct TransactionData { pub value: U256, pub chain_id: Option, pub access_list: Vec<(H160, Vec)>, + pub proof_size_base_cost: Option, +} + +impl TransactionData { + #[allow(clippy::too_many_arguments)] + pub fn new( + action: TransactionAction, + input: Vec, + nonce: U256, + gas_limit: U256, + gas_price: Option, + max_fee_per_gas: Option, + max_priority_fee_per_gas: Option, + value: U256, + chain_id: Option, + access_list: Vec<(H160, Vec)>, + ) -> Self { + let mut transaction_data = Self { + action, + input, + nonce, + gas_limit, + gas_price, + max_fee_per_gas, + max_priority_fee_per_gas, + value, + chain_id, + access_list, + proof_size_base_cost: None, + }; + let proof_size_base_cost = transaction_data + .encode() + .len() + // signature + .saturating_add(65) + // pallet index + .saturating_add(1) + // call index + .saturating_add(1) as u64; + transaction_data.proof_size_base_cost = Some(proof_size_base_cost); + + transaction_data + } } impl From for CheckEvmTransactionInput { @@ -84,6 +127,15 @@ impl From for CheckEvmTransactionInput { impl From<&Transaction> for TransactionData { fn from(t: &Transaction) -> Self { + // The call wrapped in the extrinsic is part of the PoV, record this as a base cost for the size of the proof. + let proof_size_base_cost = t + .encode() + .len() + // pallet index + .saturating_add(1) + // call index + .saturating_add(1) as u64; + match t { Transaction::Legacy(t) => TransactionData { action: t.action, @@ -96,6 +148,7 @@ impl From<&Transaction> for TransactionData { value: t.value, chain_id: t.signature.chain_id(), access_list: Vec::new(), + proof_size_base_cost: Some(proof_size_base_cost), }, Transaction::EIP2930(t) => TransactionData { action: t.action, @@ -112,6 +165,7 @@ impl From<&Transaction> for TransactionData { .iter() .map(|d| (d.address, d.storage_keys.clone())) .collect(), + proof_size_base_cost: Some(proof_size_base_cost), }, Transaction::EIP1559(t) => TransactionData { action: t.action, @@ -128,6 +182,7 @@ impl From<&Transaction> for TransactionData { .iter() .map(|d| (d.address, d.storage_keys.clone())) .collect(), + proof_size_base_cost: Some(proof_size_base_cost), }, } } diff --git a/template/runtime/src/lib.rs b/template/runtime/src/lib.rs index 6beb1a6c80..72675b8f0a 100644 --- a/template/runtime/src/lib.rs +++ b/template/runtime/src/lib.rs @@ -46,10 +46,12 @@ use pallet_transaction_payment::CurrencyAdapter; 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_ethereum::{ + Call::transact, PostLogContent, Transaction as EthereumTransaction, TransactionAction, + TransactionData, +}; use pallet_evm::{ - Account as EVMAccount, EnsureAccountId20, FeeCalculator, GasWeightMapping, - IdentityAddressMapping, Runner, + Account as EVMAccount, EnsureAccountId20, FeeCalculator, IdentityAddressMapping, Runner, }; // A few exports that help ease life for downstream crates. @@ -687,43 +689,20 @@ impl_runtime_apis! { None }; - let is_transactional = false; - let validate = true; - let evm_config = config.as_ref().unwrap_or(::config()); - - let mut estimated_transaction_len = data.len() + - 20 + // to - 20 + // from - 32 + // value - 32 + // gas_limit - 32 + // nonce - 1 + // TransactionAction - 8 + // chain id - 65; // signature - - if max_fee_per_gas.is_some() { - estimated_transaction_len += 32; - } - if max_priority_fee_per_gas.is_some() { - estimated_transaction_len += 32; - } - if access_list.is_some() { - estimated_transaction_len += access_list.encoded_size(); - } - - let gas_limit = gas_limit.min(u64::MAX.into()).low_u64(); - let without_base_extrinsic_weight = true; - - let (weight_limit, proof_size_base_cost) = - match ::GasWeightMapping::gas_to_weight( - gas_limit, - without_base_extrinsic_weight - ) { - weight_limit if weight_limit.proof_size() > 0 => { - (Some(weight_limit), Some(estimated_transaction_len as u64)) - } - _ => (None, None), - }; + let gas_limit = gas_limit.min(u64::MAX.into()); + let transaction_data = TransactionData::new( + TransactionAction::Call(to), + data.clone(), + nonce.unwrap_or_default(), + gas_limit, + None, + max_fee_per_gas, + max_priority_fee_per_gas, + value, + Some(::ChainId::get()), + access_list.clone().unwrap_or_default(), + ); + let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::::transaction_weight(&transaction_data); ::Runner::call( from, @@ -735,11 +714,11 @@ impl_runtime_apis! { max_priority_fee_per_gas, nonce, access_list.unwrap_or_default(), - is_transactional, - validate, + false, + true, weight_limit, proof_size_base_cost, - evm_config, + config.as_ref().unwrap_or(::config()), ).map_err(|err| err.error.into()) } @@ -762,46 +741,19 @@ impl_runtime_apis! { None }; - let is_transactional = false; - let validate = true; - let evm_config = config.as_ref().unwrap_or(::config()); - - let mut estimated_transaction_len = data.len() + - 20 + // from - 32 + // value - 32 + // gas_limit - 32 + // nonce - 1 + // TransactionAction - 8 + // chain id - 65; // signature - - if max_fee_per_gas.is_some() { - estimated_transaction_len += 32; - } - if max_priority_fee_per_gas.is_some() { - estimated_transaction_len += 32; - } - if access_list.is_some() { - estimated_transaction_len += access_list.encoded_size(); - } - - let gas_limit = if gas_limit > U256::from(u64::MAX) { - u64::MAX - } else { - gas_limit.low_u64() - }; - let without_base_extrinsic_weight = true; - - let (weight_limit, proof_size_base_cost) = - match ::GasWeightMapping::gas_to_weight( - gas_limit, - without_base_extrinsic_weight - ) { - weight_limit if weight_limit.proof_size() > 0 => { - (Some(weight_limit), Some(estimated_transaction_len as u64)) - } - _ => (None, None), - }; + let transaction_data = TransactionData::new( + TransactionAction::Create, + data.clone(), + nonce.unwrap_or_default(), + gas_limit, + None, + max_fee_per_gas, + max_priority_fee_per_gas, + value, + Some(::ChainId::get()), + access_list.clone().unwrap_or_default(), + ); + let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::::transaction_weight(&transaction_data); ::Runner::create( from, @@ -812,11 +764,11 @@ impl_runtime_apis! { max_priority_fee_per_gas, nonce, access_list.unwrap_or_default(), - is_transactional, - validate, + false, + true, weight_limit, proof_size_base_cost, - evm_config, + config.as_ref().unwrap_or(::config()), ).map_err(|err| err.error.into()) }