Skip to content

Commit 4455a0d

Browse files
boundless-forestfrank0528
authored andcommitted
Update the approach to obtain (weight_limit, proof_size_base_cost) (polkadot-evm#1121)
* Move `proof_size_base_cost` out to reuse it * Add field * Reuse `transaction_weight` * Code clean * Fix clippy
1 parent e5a3ed0 commit 4455a0d

3 files changed

Lines changed: 113 additions & 138 deletions

File tree

frame/ethereum/src/lib.rs

Lines changed: 20 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ mod tests;
3333
use ethereum_types::{Bloom, BloomInput, H160, H256, H64, U256};
3434
use evm::ExitReason;
3535
use fp_consensus::{PostLog, PreLog, FRONTIER_ENGINE_ID};
36-
use fp_ethereum::{
37-
TransactionData, TransactionValidationError, ValidatedTransaction as ValidatedTransactionT,
38-
};
36+
use fp_ethereum::{TransactionValidationError, ValidatedTransaction as ValidatedTransactionT};
3937
use fp_evm::{
4038
CallOrCreateInfo, CheckEvmTransaction, CheckEvmTransactionConfig, InvalidEvmTransactionError,
4139
};
@@ -63,6 +61,7 @@ pub use ethereum::{
6361
AccessListItem, BlockV2 as Block, LegacyTransactionMessage, Log, ReceiptV3 as Receipt,
6462
TransactionAction, TransactionV2 as Transaction,
6563
};
64+
pub use fp_ethereum::TransactionData;
6665
pub use fp_rpc::TransactionStatus;
6766

6867
#[derive(Clone, Eq, PartialEq, RuntimeDebug)]
@@ -353,15 +352,17 @@ pub mod pallet {
353352
}
354353

355354
impl<T: Config> Pallet<T> {
356-
/// The call wrapped in the extrinsic is part of the PoV, record this as a base cost for the size of the proof.
357-
fn proof_size_base_cost(transaction: &Transaction) -> u64 {
358-
transaction
359-
.encode()
360-
.len()
361-
// pallet index
362-
.saturating_add(1)
363-
// call index
364-
.saturating_add(1) as u64
355+
pub fn transaction_weight(transaction_data: &TransactionData) -> (Option<Weight>, Option<u64>) {
356+
match <T as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
357+
transaction_data.gas_limit.unique_saturated_into(),
358+
true,
359+
) {
360+
weight_limit if weight_limit.proof_size() > 0 => (
361+
Some(weight_limit),
362+
Some(transaction_data.proof_size_base_cost.unwrap_or_default()),
363+
),
364+
_ => (None, None),
365+
}
365366
}
366367

367368
fn recover_signer(transaction: &Transaction) -> Option<H160> {
@@ -483,19 +484,7 @@ impl<T: Config> Pallet<T> {
483484
) -> TransactionValidity {
484485
let transaction_data: TransactionData = transaction.into();
485486
let transaction_nonce = transaction_data.nonce;
486-
487-
let (weight_limit, proof_size_base_cost) =
488-
match <T as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
489-
transaction_data.gas_limit.unique_saturated_into(),
490-
true,
491-
) {
492-
weight_limit if weight_limit.proof_size() > 0 => (
493-
Some(weight_limit),
494-
Some(Self::proof_size_base_cost(transaction)),
495-
),
496-
_ => (None, None),
497-
};
498-
487+
let (weight_limit, proof_size_base_cost) = Self::transaction_weight(&transaction_data);
499488
let (base_fee, _) = T::FeeCalculator::min_gas_price();
500489
let (who, _) = pallet_evm::Pallet::<T>::account_basic(&origin);
501490

@@ -714,6 +703,11 @@ impl<T: Config> Pallet<T> {
714703
(Option<H160>, Option<H160>, CallOrCreateInfo),
715704
DispatchErrorWithPostInfo<PostDispatchInfo>,
716705
> {
706+
let transaction_data: TransactionData = transaction.into();
707+
let (weight_limit, proof_size_base_cost) = Self::transaction_weight(&transaction_data);
708+
let is_transactional = true;
709+
let validate = false;
710+
717711
let (
718712
input,
719713
value,
@@ -774,20 +768,6 @@ impl<T: Config> Pallet<T> {
774768
}
775769
};
776770

777-
let is_transactional = true;
778-
let validate = false;
779-
780-
let (proof_size_base_cost, weight_limit) =
781-
match <T as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
782-
gas_limit.unique_saturated_into(),
783-
true,
784-
) {
785-
weight_limit if weight_limit.proof_size() > 0 => (
786-
Some(Self::proof_size_base_cost(transaction)),
787-
Some(weight_limit),
788-
),
789-
_ => (None, None),
790-
};
791771
match action {
792772
ethereum::TransactionAction::Call(target) => {
793773
let res = match T::Runner::call(
@@ -862,22 +842,10 @@ impl<T: Config> Pallet<T> {
862842
transaction: &Transaction,
863843
) -> Result<(), TransactionValidityError> {
864844
let transaction_data: TransactionData = transaction.into();
865-
845+
let (weight_limit, proof_size_base_cost) = Self::transaction_weight(&transaction_data);
866846
let (base_fee, _) = T::FeeCalculator::min_gas_price();
867847
let (who, _) = pallet_evm::Pallet::<T>::account_basic(&origin);
868848

869-
let (weight_limit, proof_size_base_cost) =
870-
match <T as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
871-
transaction_data.gas_limit.unique_saturated_into(),
872-
true,
873-
) {
874-
weight_limit if weight_limit.proof_size() > 0 => (
875-
Some(weight_limit),
876-
Some(Self::proof_size_base_cost(transaction)),
877-
),
878-
_ => (None, None),
879-
};
880-
881849
let _ = CheckEvmTransaction::<InvalidTransactionWrapper>::new(
882850
CheckEvmTransactionConfig {
883851
evm_config: T::config(),

primitives/ethereum/src/lib.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,49 @@ pub struct TransactionData {
5959
pub value: U256,
6060
pub chain_id: Option<u64>,
6161
pub access_list: Vec<(H160, Vec<H256>)>,
62+
pub proof_size_base_cost: Option<u64>,
63+
}
64+
65+
impl TransactionData {
66+
#[allow(clippy::too_many_arguments)]
67+
pub fn new(
68+
action: TransactionAction,
69+
input: Vec<u8>,
70+
nonce: U256,
71+
gas_limit: U256,
72+
gas_price: Option<U256>,
73+
max_fee_per_gas: Option<U256>,
74+
max_priority_fee_per_gas: Option<U256>,
75+
value: U256,
76+
chain_id: Option<u64>,
77+
access_list: Vec<(H160, Vec<H256>)>,
78+
) -> Self {
79+
let mut transaction_data = Self {
80+
action,
81+
input,
82+
nonce,
83+
gas_limit,
84+
gas_price,
85+
max_fee_per_gas,
86+
max_priority_fee_per_gas,
87+
value,
88+
chain_id,
89+
access_list,
90+
proof_size_base_cost: None,
91+
};
92+
let proof_size_base_cost = transaction_data
93+
.encode()
94+
.len()
95+
// signature
96+
.saturating_add(65)
97+
// pallet index
98+
.saturating_add(1)
99+
// call index
100+
.saturating_add(1) as u64;
101+
transaction_data.proof_size_base_cost = Some(proof_size_base_cost);
102+
103+
transaction_data
104+
}
62105
}
63106

64107
impl From<TransactionData> for CheckEvmTransactionInput {
@@ -84,6 +127,15 @@ impl From<TransactionData> for CheckEvmTransactionInput {
84127

85128
impl From<&Transaction> for TransactionData {
86129
fn from(t: &Transaction) -> Self {
130+
// The call wrapped in the extrinsic is part of the PoV, record this as a base cost for the size of the proof.
131+
let proof_size_base_cost = t
132+
.encode()
133+
.len()
134+
// pallet index
135+
.saturating_add(1)
136+
// call index
137+
.saturating_add(1) as u64;
138+
87139
match t {
88140
Transaction::Legacy(t) => TransactionData {
89141
action: t.action,
@@ -96,6 +148,7 @@ impl From<&Transaction> for TransactionData {
96148
value: t.value,
97149
chain_id: t.signature.chain_id(),
98150
access_list: Vec::new(),
151+
proof_size_base_cost: Some(proof_size_base_cost),
99152
},
100153
Transaction::EIP2930(t) => TransactionData {
101154
action: t.action,
@@ -112,6 +165,7 @@ impl From<&Transaction> for TransactionData {
112165
.iter()
113166
.map(|d| (d.address, d.storage_keys.clone()))
114167
.collect(),
168+
proof_size_base_cost: Some(proof_size_base_cost),
115169
},
116170
Transaction::EIP1559(t) => TransactionData {
117171
action: t.action,
@@ -128,6 +182,7 @@ impl From<&Transaction> for TransactionData {
128182
.iter()
129183
.map(|d| (d.address, d.storage_keys.clone()))
130184
.collect(),
185+
proof_size_base_cost: Some(proof_size_base_cost),
131186
},
132187
}
133188
}

template/runtime/src/lib.rs

Lines changed: 38 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@ use pallet_transaction_payment::CurrencyAdapter;
4646
use fp_account::EthereumSignature;
4747
use fp_evm::weight_per_gas;
4848
use fp_rpc::TransactionStatus;
49-
use pallet_ethereum::{Call::transact, PostLogContent, Transaction as EthereumTransaction};
49+
use pallet_ethereum::{
50+
Call::transact, PostLogContent, Transaction as EthereumTransaction, TransactionAction,
51+
TransactionData,
52+
};
5053
use pallet_evm::{
51-
Account as EVMAccount, EnsureAccountId20, FeeCalculator, GasWeightMapping,
52-
IdentityAddressMapping, Runner,
54+
Account as EVMAccount, EnsureAccountId20, FeeCalculator, IdentityAddressMapping, Runner,
5355
};
5456

5557
// A few exports that help ease life for downstream crates.
@@ -687,43 +689,20 @@ impl_runtime_apis! {
687689
None
688690
};
689691

690-
let is_transactional = false;
691-
let validate = true;
692-
let evm_config = config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config());
693-
694-
let mut estimated_transaction_len = data.len() +
695-
20 + // to
696-
20 + // from
697-
32 + // value
698-
32 + // gas_limit
699-
32 + // nonce
700-
1 + // TransactionAction
701-
8 + // chain id
702-
65; // signature
703-
704-
if max_fee_per_gas.is_some() {
705-
estimated_transaction_len += 32;
706-
}
707-
if max_priority_fee_per_gas.is_some() {
708-
estimated_transaction_len += 32;
709-
}
710-
if access_list.is_some() {
711-
estimated_transaction_len += access_list.encoded_size();
712-
}
713-
714-
let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
715-
let without_base_extrinsic_weight = true;
716-
717-
let (weight_limit, proof_size_base_cost) =
718-
match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
719-
gas_limit,
720-
without_base_extrinsic_weight
721-
) {
722-
weight_limit if weight_limit.proof_size() > 0 => {
723-
(Some(weight_limit), Some(estimated_transaction_len as u64))
724-
}
725-
_ => (None, None),
726-
};
692+
let gas_limit = gas_limit.min(u64::MAX.into());
693+
let transaction_data = TransactionData::new(
694+
TransactionAction::Call(to),
695+
data.clone(),
696+
nonce.unwrap_or_default(),
697+
gas_limit,
698+
None,
699+
max_fee_per_gas,
700+
max_priority_fee_per_gas,
701+
value,
702+
Some(<Runtime as pallet_evm::Config>::ChainId::get()),
703+
access_list.clone().unwrap_or_default(),
704+
);
705+
let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
727706

728707
<Runtime as pallet_evm::Config>::Runner::call(
729708
from,
@@ -735,11 +714,11 @@ impl_runtime_apis! {
735714
max_priority_fee_per_gas,
736715
nonce,
737716
access_list.unwrap_or_default(),
738-
is_transactional,
739-
validate,
717+
false,
718+
true,
740719
weight_limit,
741720
proof_size_base_cost,
742-
evm_config,
721+
config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
743722
).map_err(|err| err.error.into())
744723
}
745724

@@ -762,46 +741,19 @@ impl_runtime_apis! {
762741
None
763742
};
764743

765-
let is_transactional = false;
766-
let validate = true;
767-
let evm_config = config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config());
768-
769-
let mut estimated_transaction_len = data.len() +
770-
20 + // from
771-
32 + // value
772-
32 + // gas_limit
773-
32 + // nonce
774-
1 + // TransactionAction
775-
8 + // chain id
776-
65; // signature
777-
778-
if max_fee_per_gas.is_some() {
779-
estimated_transaction_len += 32;
780-
}
781-
if max_priority_fee_per_gas.is_some() {
782-
estimated_transaction_len += 32;
783-
}
784-
if access_list.is_some() {
785-
estimated_transaction_len += access_list.encoded_size();
786-
}
787-
788-
let gas_limit = if gas_limit > U256::from(u64::MAX) {
789-
u64::MAX
790-
} else {
791-
gas_limit.low_u64()
792-
};
793-
let without_base_extrinsic_weight = true;
794-
795-
let (weight_limit, proof_size_base_cost) =
796-
match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
797-
gas_limit,
798-
without_base_extrinsic_weight
799-
) {
800-
weight_limit if weight_limit.proof_size() > 0 => {
801-
(Some(weight_limit), Some(estimated_transaction_len as u64))
802-
}
803-
_ => (None, None),
804-
};
744+
let transaction_data = TransactionData::new(
745+
TransactionAction::Create,
746+
data.clone(),
747+
nonce.unwrap_or_default(),
748+
gas_limit,
749+
None,
750+
max_fee_per_gas,
751+
max_priority_fee_per_gas,
752+
value,
753+
Some(<Runtime as pallet_evm::Config>::ChainId::get()),
754+
access_list.clone().unwrap_or_default(),
755+
);
756+
let (weight_limit, proof_size_base_cost) = pallet_ethereum::Pallet::<Runtime>::transaction_weight(&transaction_data);
805757

806758
<Runtime as pallet_evm::Config>::Runner::create(
807759
from,
@@ -812,11 +764,11 @@ impl_runtime_apis! {
812764
max_priority_fee_per_gas,
813765
nonce,
814766
access_list.unwrap_or_default(),
815-
is_transactional,
816-
validate,
767+
false,
768+
true,
817769
weight_limit,
818770
proof_size_base_cost,
819-
evm_config,
771+
config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
820772
).map_err(|err| err.error.into())
821773
}
822774

0 commit comments

Comments
 (0)