Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record the storage proof_size with hostfunction #1490

Draft
wants to merge 26 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ac7999b
Compile OK
boundless-forest Aug 1, 2024
17f2fe5
Compile with runtime
boundless-forest Aug 1, 2024
cb6deef
Compile with node
boundless-forest Aug 1, 2024
4b8a1d3
A simple test
boundless-forest Aug 1, 2024
04b744d
Delete debug information
boundless-forest Aug 1, 2024
3bba36f
Use local path debug
boundless-forest Aug 2, 2024
a01b802
Rewrite with hostfunction
boundless-forest Aug 2, 2024
94c5e3f
Finish runner part
boundless-forest Aug 2, 2024
36c7b29
Fix the proof_size over limit case
boundless-forest Aug 6, 2024
9bdb875
Upgrade to the stable2407
boundless-forest Aug 6, 2024
cba4edd
Fix primitive test cases
boundless-forest Aug 6, 2024
79e77b8
Fix evm test cases 1
boundless-forest Aug 7, 2024
d6f4858
Add proof_size tests
boundless-forest Aug 9, 2024
e6f1d30
Finish test cases
boundless-forest Aug 9, 2024
c2ced0e
Fix ethereum test cases
boundless-forest Aug 12, 2024
8815811
Add nonce check test case
boundless-forest Aug 12, 2024
cb2b278
Use github link
boundless-forest Aug 12, 2024
40af527
Merge branch 'master' into bear-proof-size-cal
boundless-forest Aug 12, 2024
33b7cd6
Code clean
boundless-forest Aug 12, 2024
0303d46
Rewrite the storage clean precompile
boundless-forest Aug 12, 2024
9c26bdc
Fix toml format
boundless-forest Aug 12, 2024
278a720
Upgrade evm version and fix test cases
boundless-forest Aug 13, 2024
47a6ccd
Revert polkadot-sdk commit and update lock
boundless-forest Aug 14, 2024
bd730eb
Fix the clippy error due to introduce the pallet-staking
boundless-forest Aug 14, 2024
71dfcb7
Don't take the transaction length into proof size anymore
boundless-forest Aug 14, 2024
8291389
Fix CI
boundless-forest Aug 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,835 changes: 4,352 additions & 483 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ derive_more = "0.99"
environmental = { version = "1.1.4", default-features = false }
ethereum = { version = "0.15.0", default-features = false }
ethereum-types = { version = "0.14.1", default-features = false }
evm = { version = "0.41.1", default-features = false }
evm = { git = "https://github.com/rust-ethereum/evm", branch = "v0.x", default-features = false }
futures = "0.3.30"
hash-db = { version = "0.16.0", default-features = false }
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
Expand Down Expand Up @@ -129,6 +129,7 @@ sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2
sp-storage = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407", default-features = false }
sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407", default-features = false }
sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407", default-features = false }
sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407", default-features = false }
sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407", default-features = false }
sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407", default-features = false }
# Substrate FRAME
Expand All @@ -155,6 +156,11 @@ substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk
substrate-test-runtime-client = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407" }
substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407" }

# Cumulus
cumulus-client-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407" }
cumulus-primitives-storage-weight-reclaim = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407", default-features = false }
polkadot-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407" }

# XCM
xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "stable2407", default-features = false }

Expand Down
1 change: 1 addition & 0 deletions client/rpc/src/eth/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ impl Geth {
VError::InvalidChainId => "invalid chain id".into(),
VError::InvalidSignature => "invalid sender".into(),
VError::GasLimitTooLow => "intrinsic gas too low".into(),
VError::ProofLimitTooLow => "intrinsic proof size too low".into(),
VError::GasLimitTooHigh => "exceeds block gas limit".into(),
VError::GasPriceTooLow => "gas price less than block base fee".into(),
VError::PriorityFeeTooHigh => {
Expand Down
4 changes: 4 additions & 0 deletions frame/ethereum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ frame-support = { workspace = true }
frame-system = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
# Cumulus
cumulus-primitives-storage-weight-reclaim = { workspace = true }
# Frontier
fp-consensus = { workspace = true }
fp-ethereum = { workspace = true }
Expand Down Expand Up @@ -49,6 +51,8 @@ std = [
"rlp/std",
"scale-codec/std",
"scale-info/std",
# Cumulus
"cumulus-primitives-storage-weight-reclaim/std",
# Substrate
"frame-support/std",
"frame-system/std",
Expand Down
40 changes: 18 additions & 22 deletions frame/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ use fp_consensus::{PostLog, PreLog, FRONTIER_ENGINE_ID};
pub use fp_ethereum::TransactionData;
use fp_ethereum::ValidatedTransaction as ValidatedTransactionT;
use fp_evm::{
CallOrCreateInfo, CheckEvmTransaction, CheckEvmTransactionConfig, TransactionValidationError,
CallOrCreateInfo, CheckEvmTransaction, CheckEvmTransactionConfig, TransactionPov,
TransactionValidationError,
};
pub use fp_rpc::TransactionStatus;
use fp_storage::{EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA};
Expand Down Expand Up @@ -294,7 +295,6 @@ pub mod pallet {
fp_consensus::find_pre_log(&frame_system::Pallet::<T>::digest()).is_err(),
"pre log already exists; block is invalid",
);

Self::apply_validated_transaction(source, transaction).map(|(post_info, _)| post_info)
}
}
Expand Down Expand Up @@ -361,17 +361,14 @@ pub mod pallet {
}

impl<T: Config> Pallet<T> {
pub fn transaction_weight(transaction_data: &TransactionData) -> (Option<Weight>, Option<u64>) {
match <T as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
pub fn transaction_pov(transaction_data: &TransactionData) -> Option<TransactionPov> {
let weight_limit = <T as pallet_evm::Config>::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()),
),
_ => (None, None),
}
);
cumulus_primitives_storage_weight_reclaim::get_proof_size().map(
|proof_size_pre_execution| TransactionPov::new(weight_limit, proof_size_pre_execution),
)
}

fn recover_signer(transaction: &Transaction) -> Option<H160> {
Expand Down Expand Up @@ -493,7 +490,7 @@ impl<T: Config> Pallet<T> {
) -> TransactionValidity {
let transaction_data: TransactionData = transaction.into();
let transaction_nonce = transaction_data.nonce;
let (weight_limit, proof_size_base_cost) = Self::transaction_weight(&transaction_data);
let transaction_pov = Self::transaction_pov(&transaction_data);
let (base_fee, _) = T::FeeCalculator::min_gas_price();
let (who, _) = pallet_evm::Pallet::<T>::account_basic(&origin);

Expand All @@ -506,8 +503,7 @@ impl<T: Config> Pallet<T> {
is_transactional: true,
},
transaction_data.clone().into(),
weight_limit,
proof_size_base_cost,
transaction_pov,
)
.validate_in_pool_for(&who)
.and_then(|v| v.with_chain_id())
Expand Down Expand Up @@ -723,7 +719,7 @@ impl<T: Config> Pallet<T> {
config: Option<evm::Config>,
) -> Result<(Option<H160>, Option<H160>, CallOrCreateInfo), DispatchErrorWithPostInfo> {
let transaction_data: TransactionData = transaction.into();
let (weight_limit, proof_size_base_cost) = Self::transaction_weight(&transaction_data);
let transaction_pov = Self::transaction_pov(&transaction_data);
let is_transactional = true;
let validate = false;

Expand Down Expand Up @@ -801,8 +797,7 @@ impl<T: Config> Pallet<T> {
access_list,
is_transactional,
validate,
weight_limit,
proof_size_base_cost,
transaction_pov,
config.as_ref().unwrap_or_else(|| T::config()),
) {
Ok(res) => res,
Expand Down Expand Up @@ -831,8 +826,7 @@ impl<T: Config> Pallet<T> {
access_list,
is_transactional,
validate,
weight_limit,
proof_size_base_cost,
transaction_pov,
config.as_ref().unwrap_or_else(|| T::config()),
) {
Ok(res) => res,
Expand Down Expand Up @@ -861,7 +855,7 @@ impl<T: Config> Pallet<T> {
transaction: &Transaction,
) -> Result<(), TransactionValidityError> {
let transaction_data: TransactionData = transaction.into();
let (weight_limit, proof_size_base_cost) = Self::transaction_weight(&transaction_data);
let transaction_pov = Self::transaction_pov(&transaction_data);
let (base_fee, _) = T::FeeCalculator::min_gas_price();
let (who, _) = pallet_evm::Pallet::<T>::account_basic(&origin);

Expand All @@ -874,8 +868,7 @@ impl<T: Config> Pallet<T> {
is_transactional: true,
},
transaction_data.into(),
weight_limit,
proof_size_base_cost,
transaction_pov,
)
.validate_in_block_for(&who)
.and_then(|v| v.with_chain_id())
Expand Down Expand Up @@ -989,6 +982,9 @@ pub struct InvalidTransactionWrapper(InvalidTransaction);
impl From<TransactionValidationError> for InvalidTransactionWrapper {
fn from(validation_error: TransactionValidationError) -> Self {
match validation_error {
TransactionValidationError::ProofLimitTooLow => InvalidTransactionWrapper(
InvalidTransaction::Custom(TransactionValidationError::ProofLimitTooLow as u8),
),
TransactionValidationError::GasLimitTooLow => InvalidTransactionWrapper(
InvalidTransaction::Custom(TransactionValidationError::GasLimitTooLow as u8),
),
Expand Down
29 changes: 5 additions & 24 deletions frame/ethereum/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use sp_runtime::{
traits::{BlakeTwo256, Dispatchable, IdentityLookup},
AccountId32, BuildStorage,
};

// Frontier
use pallet_evm::{AddressMapping, EnsureAddressTruncated, FeeCalculator};

Expand Down Expand Up @@ -271,36 +272,12 @@ fn address_build(seed: u8) -> AccountInfo {
}
}

// This function basically just builds a genesis storage key/value store according to
// our desired mockup.
pub fn new_test_ext(accounts_len: usize) -> (Vec<AccountInfo>, sp_io::TestExternalities) {
// sc_cli::init_logger("");
let mut ext = frame_system::GenesisConfig::<Test>::default()
.build_storage()
.unwrap();

let pairs = (0..accounts_len)
.map(|i| address_build(i as u8))
.collect::<Vec<_>>();

let balances: Vec<_> = (0..accounts_len)
.map(|i| (pairs[i].account_id.clone(), 10_000_000))
.collect();

pallet_balances::GenesisConfig::<Test> { balances }
.assimilate_storage(&mut ext)
.unwrap();

(pairs, ext.into())
}

// This function basically just builds a genesis storage key/value store according to
// our desired mockup.
pub fn new_test_ext_with_initial_balance(
accounts_len: usize,
initial_balance: u64,
) -> (Vec<AccountInfo>, sp_io::TestExternalities) {
// sc_cli::init_logger("");
let mut ext = frame_system::GenesisConfig::<Test>::default()
.build_storage()
.unwrap();
Expand All @@ -320,6 +297,10 @@ pub fn new_test_ext_with_initial_balance(
(pairs, ext.into())
}

pub fn new_test_ext(accounts_len: usize) -> (Vec<AccountInfo>, sp_io::TestExternalities) {
new_test_ext_with_initial_balance(accounts_len, 10_000_000)
}

pub fn contract_address(sender: H160, nonce: u64) -> H160 {
let mut rlp = RlpStream::new_list(2);
rlp.append(&sender);
Expand Down
78 changes: 4 additions & 74 deletions frame/ethereum/src/tests/eip1559.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@

use super::*;
use evm::{ExitReason, ExitRevert, ExitSucceed};
use fp_ethereum::{TransactionData, ValidatedTransaction};
use fp_ethereum::ValidatedTransaction;
use frame_support::{dispatch::DispatchClass, traits::Get, weights::Weight};
use frame_system::limits::BlockWeights;
use pallet_evm::{AddressMapping, GasWeightMapping};

fn eip1559_erc20_creation_unsigned_transaction() -> EIP1559UnsignedTransaction {
Expand All @@ -45,8 +46,7 @@ fn transaction_with_max_extrinsic_gas_limit_should_success_pre_dispatch() {
let alice = &pairs[0];
let bob = &pairs[1];

let limits: frame_system::limits::BlockWeights =
<Test as frame_system::Config>::BlockWeights::get();
let limits: BlockWeights = <Test as frame_system::Config>::BlockWeights::get();
let max_extrinsic = limits.get(DispatchClass::Normal).max_extrinsic.unwrap();
let max_extrinsic_gas =
<Test as pallet_evm::Config>::GasWeightMapping::weight_to_gas(max_extrinsic);
Expand Down Expand Up @@ -82,8 +82,7 @@ fn transaction_with_gas_limit_greater_than_max_extrinsic_should_fail_pre_dispatc
let alice = &pairs[0];
let bob = &pairs[1];

let limits: frame_system::limits::BlockWeights =
<Test as frame_system::Config>::BlockWeights::get();
let limits: BlockWeights = <Test as frame_system::Config>::BlockWeights::get();
let max_extrinsic = limits.get(DispatchClass::Normal).max_extrinsic.unwrap();
let base_extrinsic = limits.get(DispatchClass::Normal).base_extrinsic;
let max_extrinsic_gas = <Test as pallet_evm::Config>::GasWeightMapping::weight_to_gas(
Expand Down Expand Up @@ -552,72 +551,3 @@ fn validated_transaction_apply_zero_gas_price_works() {
assert_eq!(Balances::free_balance(&substrate_bob), 1_100);
});
}

#[test]
fn proof_size_weight_limit_validation_works() {
let (pairs, mut ext) = new_test_ext(1);
let alice = &pairs[0];

ext.execute_with(|| {
let mut tx = EIP1559UnsignedTransaction {
nonce: U256::from(2),
max_priority_fee_per_gas: U256::zero(),
max_fee_per_gas: U256::from(1),
gas_limit: U256::from(0x100000),
action: ethereum::TransactionAction::Call(alice.address),
value: U256::from(1),
input: Vec::new(),
};

let gas_limit: u64 = 1_000_000;
tx.gas_limit = U256::from(gas_limit);

let weight_limit =
<Test as pallet_evm::Config>::GasWeightMapping::gas_to_weight(gas_limit, true);

// Gas limit cannot afford the extra byte and thus is expected to exhaust.
tx.input = vec![0u8; (weight_limit.proof_size() + 1) as usize];
let tx = tx.sign(&alice.private_key, None);

// Execute
assert!(
Ethereum::transact(RawOrigin::EthereumTransaction(alice.address).into(), tx,).is_err()
);
});
}

#[test]
fn proof_size_base_cost_should_keep_the_same_in_execution_and_estimate() {
let (pairs, mut ext) = new_test_ext(1);
let alice = &pairs[0];

ext.execute_with(|| {
let raw_tx = EIP1559UnsignedTransaction {
nonce: U256::zero(),
max_priority_fee_per_gas: U256::zero(),
max_fee_per_gas: U256::zero(),
gas_limit: U256::from(21_000),
action: ethereum::TransactionAction::Create,
value: U256::from(100),
input: vec![9; 100],
};

let tx_data: TransactionData = (&raw_tx.sign(&alice.private_key, Some(100))).into();
let estimate_tx_data = TransactionData::new(
raw_tx.action,
raw_tx.input,
raw_tx.nonce,
raw_tx.gas_limit,
None,
Some(raw_tx.max_fee_per_gas),
Some(raw_tx.max_priority_fee_per_gas),
raw_tx.value,
Some(100),
vec![],
);
assert_eq!(
estimate_tx_data.proof_size_base_cost(),
tx_data.proof_size_base_cost()
);
});
}
Loading
Loading