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

EVM + Weight v2 support #1039

Merged
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
4bab80e
wip `record_extarnal_cost`
tgmichel Apr 11, 2023
416d618
Add support for external cost recording from the EVM
tgmichel Apr 13, 2023
24c91b5
Add refund external cost support
tgmichel Apr 14, 2023
3dff83e
Separate dispatchables with weight limit
tgmichel Apr 17, 2023
3ace0af
introduce tbd EthereumWeigher
tgmichel Apr 17, 2023
6deaacb
Validate gas to weight conversion
tgmichel Apr 19, 2023
74708f5
Add static opcode recording with temp costs
tgmichel Apr 20, 2023
8ea977b
Add optional `transaction_len` parameter to `GasWeightMapping`
tgmichel Apr 20, 2023
dc95f98
Account for pallet and call indexes
tgmichel Apr 20, 2023
ac5ed2d
Rollback `transaction_len` param, use MAX_POV_SIZE ratio instead
tgmichel Apr 21, 2023
45c9e25
wip tests
tgmichel Apr 25, 2023
dc33686
Add `uncached_account_code_proof_size_accounting_works` test
tgmichel Apr 26, 2023
312146f
wip tests
tgmichel Apr 26, 2023
88c7c7c
Temp remove static external cost accounting
tgmichel Apr 27, 2023
163b0c5
fix build
tgmichel Apr 27, 2023
a17e331
Temp remove static external cost accounting 2
tgmichel Apr 27, 2023
8cc4568
warning cleanup
tgmichel Apr 27, 2023
3646639
fmt
tgmichel Apr 27, 2023
87e5f6f
clippy
tgmichel Apr 27, 2023
cc4e173
taplo
tgmichel Apr 27, 2023
eb2afed
Add `evm-with-weight-limit` to ci
tgmichel Apr 27, 2023
7814419
Temp set evm fork + update Cargo.lock
tgmichel Apr 27, 2023
255f663
Merge branch 'master' into tgm-record-external-costs
tgmichel Apr 27, 2023
00ffebc
handle `code_hash`
tgmichel Apr 27, 2023
5ab6432
taplo
tgmichel Apr 27, 2023
4bb5e70
fmt
tgmichel Apr 27, 2023
538c072
Handle `transact_with_weight_limit` as self contained
tgmichel Apr 28, 2023
7686543
fix ts tests
tgmichel Apr 28, 2023
e12afd7
suggestion
tgmichel Apr 28, 2023
cd77d2d
remove precompile test
tgmichel Apr 28, 2023
91ce2ed
some suggestions
tgmichel Apr 28, 2023
d6d7a00
remove `transact_with_weight_limit`
tgmichel Apr 28, 2023
83e228a
configurable `MaxPovSize`
tgmichel May 3, 2023
c369476
test pov size constants
tgmichel May 3, 2023
296cb2a
accessed storage overlayed cache
tgmichel May 4, 2023
c8138af
`new_from_weight_limit` suggestion
tgmichel May 4, 2023
34be73b
remove unnecessary check
tgmichel May 4, 2023
44c93c0
warnings cleanup
tgmichel May 5, 2023
17abbd3
set constant gas limit max pov size ratio
tgmichel May 5, 2023
3572aad
check state version for suicide
tgmichel May 5, 2023
4bbbe3d
just completely remove suicide accounting
tgmichel May 5, 2023
bd734b1
- `code` must be able to oog
tgmichel May 11, 2023
0a22130
Merge branch 'master' into tgm-record-external-costs
tgmichel May 12, 2023
1a1a47f
`is_empty` accounting
tgmichel May 12, 2023
a63f1d2
fix build
tgmichel May 12, 2023
e59eb9c
`SSTORE` must record account storage proof size
tgmichel May 12, 2023
91a5259
suggestion: move weight_limit checks
tgmichel May 16, 2023
3915652
editorconfig
tgmichel May 16, 2023
d09fc5b
fmt
tgmichel May 16, 2023
e9df020
rename `transaction_len` to `proof_size_base_cost` in runner
tgmichel May 16, 2023
a8fd45e
move `proof_size_base_cost` to validation primitive
tgmichel May 16, 2023
caefbec
gas limit saturated conversion
tgmichel May 24, 2023
df032b5
remove transaction proof size check outside validation
tgmichel May 24, 2023
e53da69
Merge branch 'master' into tgm-record-external-costs
tgmichel May 25, 2023
76c2f6c
pin evm
tgmichel May 25, 2023
6f6827a
pin evm+
tgmichel May 25, 2023
0154cc9
fix todos
tgmichel May 25, 2023
881f690
fix build
tgmichel May 25, 2023
eddef23
scope of already recorded codes and storages must be per transaction
tgmichel Jun 9, 2023
d6d4765
pin evm + implement new `record_external_operation`
tgmichel Jun 14, 2023
12fbeee
fix runtime api versioning + legacy `ExecutionInfo` handling
tgmichel Jun 19, 2023
8a968e9
Merge branch 'master' into tgm-record-external-costs
tgmichel Jun 19, 2023
da32bba
editorconfig
tgmichel Jun 19, 2023
5ba5fcc
cargo fmt
tgmichel Jun 19, 2023
6d3bfb3
clippy
tgmichel Jun 19, 2023
ebd1486
suggestion remove `evm-with-weight-limit` feature
tgmichel Jun 21, 2023
7198ca4
fmt
tgmichel Jun 21, 2023
d95b7ed
update comment
tgmichel Jun 21, 2023
d9f12de
update tests for additional `AccountBasicRead` in the evm
tgmichel Jun 21, 2023
074711b
update evm pin
tgmichel Jun 21, 2023
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 changes: 3 additions & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run tests
run: cargo test --locked --verbose --all
- name: Run tests (evm-with-weight-limit)
run: cargo test --locked --verbose --all --features evm-with-weight-limit

integration:
name: 'Run integration tests'
Expand Down Expand Up @@ -89,4 +91,4 @@ jobs:
- name: Rustfmt
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all --features runtime-benchmarks,try-runtime -- -D warnings
run: cargo clippy --all --features runtime-benchmarks,try-runtime,evm-with-weight-limit -- -D warnings
16 changes: 7 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ bn = { package = "substrate-bn", version = "0.6", default-features = false }
environmental = { version = "1.1.4", default-features = false }
ethereum = { version = "0.14.0", default-features = false }
ethereum-types = { version = "0.14.1", default-features = false }
evm = { version = "0.39.0", default-features = false }
evm = { git = "https://github.com/purestake/evm", branch = "tgm-record-external-cost", default-features = false }
tgmichel marked this conversation as resolved.
Show resolved Hide resolved
hex-literal = { version = "0.3.4" }
impl-serde = { version = "0.4.0", default-features = false }
jsonrpsee = "0.16.2"
Expand Down
4 changes: 2 additions & 2 deletions client/rpc/src/eth/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ where
.map_err(|err| internal_err(format!("execution fatal: {:?}", err)))?
};

(info.exit_reason, info.value, info.used_gas)
(info.exit_reason, info.value, info.used_gas.effective)
}
None => {
let info = if api_version == 1 {
Expand Down Expand Up @@ -627,7 +627,7 @@ where
.map_err(|err| internal_err(format!("execution fatal: {:?}", err)))?
};

(info.exit_reason, Vec::new(), info.used_gas)
(info.exit_reason, Vec::new(), info.used_gas.effective)
}
};
Ok(ExecutableResult {
Expand Down
1 change: 1 addition & 0 deletions frame/ethereum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,4 @@ try-runtime = [
"pallet-evm/try-runtime",
]
forbid-evm-reentrancy = ["pallet-evm/forbid-evm-reentrancy"]
evm-with-weight-limit = ["evm/with-substrate", "pallet-evm/evm-with-weight-limit"]
75 changes: 68 additions & 7 deletions frame/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,16 @@ pub mod pallet {
}

impl<T: Config> Pallet<T> {
fn transaction_len(transaction: &Transaction) -> u64 {
transaction
.encode()
.len()
// pallet index
.saturating_add(1)
// call index
.saturating_add(1) as u64
}

fn recover_signer(transaction: &Transaction) -> Option<H160> {
let mut sig = [0u8; 65];
let mut msg = [0u8; 32];
Expand Down Expand Up @@ -473,6 +483,17 @@ impl<T: Config> Pallet<T> {
let transaction_data: TransactionData = transaction.into();
let transaction_nonce = transaction_data.nonce;

let (weight_limit, proof_size_base_cost) =
match <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(Self::transaction_len(transaction)))
}
_ => (None, None),
};
tgmichel marked this conversation as resolved.
Show resolved Hide resolved

let (base_fee, _) = T::FeeCalculator::min_gas_price();
let (who, _) = pallet_evm::Pallet::<T>::account_basic(&origin);

Expand All @@ -485,6 +506,8 @@ impl<T: Config> Pallet<T> {
is_transactional: true,
},
transaction_data.clone().into(),
weight_limit,
proof_size_base_cost,
)
.validate_in_pool_for(&who)
.and_then(|v| v.with_chain_id())
Expand Down Expand Up @@ -540,7 +563,7 @@ impl<T: Config> Pallet<T> {
let transaction_hash = transaction.hash();
let transaction_index = pending.len() as u32;

let (reason, status, used_gas, dest, extra_data) = match info {
let (reason, status, weight_info, used_gas, dest, extra_data) = match info {
CallOrCreateInfo::Call(info) => (
info.exit_reason.clone(),
TransactionStatus {
Expand All @@ -556,6 +579,7 @@ impl<T: Config> Pallet<T> {
bloom
},
},
info.weight_info,
info.used_gas,
to,
match info.exit_reason {
Expand Down Expand Up @@ -599,6 +623,7 @@ impl<T: Config> Pallet<T> {
bloom
},
},
info.weight_info,
info.used_gas,
Some(info.value),
Vec::new(),
Expand All @@ -615,11 +640,11 @@ impl<T: Config> Pallet<T> {
let cumulative_gas_used = if let Some((_, _, receipt)) = pending.last() {
match receipt {
Receipt::Legacy(d) | Receipt::EIP2930(d) | Receipt::EIP1559(d) => {
d.used_gas.saturating_add(used_gas)
d.used_gas.saturating_add(used_gas.effective)
}
}
} else {
used_gas
used_gas.effective
};
match &transaction {
Transaction::Legacy(_) => Receipt::Legacy(ethereum::EIP658ReceiptData {
Expand Down Expand Up @@ -654,10 +679,18 @@ impl<T: Config> Pallet<T> {
});

Ok(PostDispatchInfo {
actual_weight: Some(T::GasWeightMapping::gas_to_weight(
used_gas.unique_saturated_into(),
true,
)),
actual_weight: {
let mut gas_to_weight = T::GasWeightMapping::gas_to_weight(
used_gas.standard.unique_saturated_into(),
true,
);
if let Some(weight_info) = weight_info {
if let Some(proof_size_usage) = weight_info.proof_size_usage {
*gas_to_weight.proof_size_mut() = proof_size_usage;
tgmichel marked this conversation as resolved.
Show resolved Hide resolved
}
}
Some(gas_to_weight)
},
pays_fee: Pays::No,
})
}
Expand Down Expand Up @@ -738,6 +771,17 @@ impl<T: Config> Pallet<T> {

let is_transactional = true;
let validate = false;

let (transaction_len, weight_limit) =
match <T as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
gas_limit.unique_saturated_into(),
true,
) {
weight_limit if weight_limit.proof_size() > 0 => {
(Some(Self::transaction_len(transaction)), Some(weight_limit))
}
_ => (None, None),
};
match action {
ethereum::TransactionAction::Call(target) => {
let res = match T::Runner::call(
Expand All @@ -752,6 +796,8 @@ impl<T: Config> Pallet<T> {
access_list,
is_transactional,
validate,
weight_limit,
transaction_len,
config.as_ref().unwrap_or_else(|| T::config()),
) {
Ok(res) => res,
Expand Down Expand Up @@ -780,6 +826,8 @@ impl<T: Config> Pallet<T> {
access_list,
is_transactional,
validate,
weight_limit,
transaction_len,
config.as_ref().unwrap_or_else(|| T::config()),
) {
Ok(res) => res,
Expand Down Expand Up @@ -812,6 +860,17 @@ impl<T: Config> Pallet<T> {
let (base_fee, _) = T::FeeCalculator::min_gas_price();
let (who, _) = pallet_evm::Pallet::<T>::account_basic(&origin);

let (weight_limit, proof_size_base_cost) =
match <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(Self::transaction_len(transaction)))
}
_ => (None, None),
};

let _ = CheckEvmTransaction::<InvalidTransactionWrapper>::new(
CheckEvmTransactionConfig {
evm_config: T::config(),
Expand All @@ -821,6 +880,8 @@ impl<T: Config> Pallet<T> {
is_transactional: true,
},
transaction_data.into(),
weight_limit,
proof_size_base_cost,
)
.validate_in_block_for(&who)
.and_then(|v| v.with_chain_id())
Expand Down
7 changes: 6 additions & 1 deletion frame/ethereum/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,15 @@ impl FindAuthor<H160> for FindAuthorTruncated {
}
}

const BLOCK_GAS_LIMIT: u64 = 150_000_000;
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;

parameter_types! {
pub const TransactionByteFee: u64 = 1;
pub const ChainId: u64 = 42;
pub const EVMModuleId: PalletId = PalletId(*b"py/evmpa");
pub const BlockGasLimit: U256 = U256::MAX;
pub BlockGasLimit: U256 = U256::from(BLOCK_GAS_LIMIT);
pub const GasLimitPovSizeRatio: u64 = BLOCK_GAS_LIMIT.saturating_div(MAX_POV_SIZE);
pub const WeightPerGas: Weight = Weight::from_parts(20_000, 0);
}

Expand Down Expand Up @@ -169,6 +173,7 @@ impl pallet_evm::Config for Test {
type OnChargeTransaction = ();
type OnCreate = ();
type FindAuthor = FindAuthorTruncated;
type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
type Timestamp = Timestamp;
type WeightInfo = ();
}
Expand Down
42 changes: 38 additions & 4 deletions frame/ethereum/src/tests/eip1559.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ fn transaction_should_generate_correct_gas_used() {

match info {
CallOrCreateInfo::Create(info) => {
assert_eq!(info.used_gas, expected_gas);
assert_eq!(info.used_gas.standard, expected_gas);
}
CallOrCreateInfo::Call(_) => panic!("expected create info"),
}
Expand Down Expand Up @@ -422,7 +422,7 @@ fn event_extra_data_should_be_handle_properly() {
input: hex::decode(TEST_CONTRACT_CODE).unwrap(),
}
.sign(&alice.private_key, None);
assert_ok!(Ethereum::apply_validated_transaction(alice.address, t));
assert_ok!(Ethereum::apply_validated_transaction(alice.address, t,));
tgmichel marked this conversation as resolved.
Show resolved Hide resolved

let contract_address = hex::decode("32dcab0ef3fb2de2fce1d2e0799d36239671f04a").unwrap();
let foo = hex::decode("c2985578").unwrap();
Expand All @@ -440,7 +440,7 @@ fn event_extra_data_should_be_handle_properly() {
.sign(&alice.private_key, None);

// calling foo
assert_ok!(Ethereum::apply_validated_transaction(alice.address, t2));
assert_ok!(Ethereum::apply_validated_transaction(alice.address, t2,));
tgmichel marked this conversation as resolved.
Show resolved Hide resolved
System::assert_last_event(RuntimeEvent::Ethereum(Event::Executed {
from: alice.address,
to: H160::from_slice(&contract_address),
Expand All @@ -464,7 +464,7 @@ fn event_extra_data_should_be_handle_properly() {
.sign(&alice.private_key, None);

// calling bar revert
assert_ok!(Ethereum::apply_validated_transaction(alice.address, t3));
assert_ok!(Ethereum::apply_validated_transaction(alice.address, t3,));
tgmichel marked this conversation as resolved.
Show resolved Hide resolved
System::assert_last_event(RuntimeEvent::Ethereum(Event::Executed {
from: alice.address,
to: H160::from_slice(&contract_address),
Expand Down Expand Up @@ -553,3 +553,37 @@ fn validated_transaction_apply_zero_gas_price_works() {
assert_eq!(Balances::free_balance(&substrate_bob), 1_100);
});
}

#[cfg(feature = "evm-with-weight-limit")]
#[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()
);
});
}
Loading