Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.

Commit 1ed56e3

Browse files
authored
improve testool for scroll mode (#831)
* default: 97.6 * 98.6 * 98.9% * 99.0% * create gadget: disable reading callee codehash if !pre_check_ok * fix base fee * solved all * fixed finally? * ... * done
1 parent 4a043fc commit 1ed56e3

File tree

11 files changed

+134
-50
lines changed

11 files changed

+134
-50
lines changed

bus-mapping/src/circuit_input_builder/l2.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,18 @@ impl From<&ZktrieState> for StateDB {
4040
}
4141

4242
for (storage_key, data) in mpt_state.storage() {
43-
if !data.as_ref().is_zero() {
44-
//TODO: add an warning on non-existed account?
45-
let (_, acc) = sdb.get_account_mut(&storage_key.0);
46-
acc.storage.insert(storage_key.1, *data.as_ref());
47-
}
43+
// Since the StateDB is a partical db, 0 means we know it is zero instead of "unknown".
44+
//if !data.as_ref().is_zero() {
45+
log::trace!(
46+
"trace sdb: addr {:?} key {:?} value {:?}",
47+
storage_key.0,
48+
storage_key.1,
49+
*data.as_ref()
50+
);
51+
//TODO: add an warning on non-existed account?
52+
let (_, acc) = sdb.get_account_mut(&storage_key.0);
53+
acc.storage.insert(storage_key.1, *data.as_ref());
54+
//}
4855
}
4956
sdb
5057
}

bus-mapping/src/evm/opcodes/create.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -192,22 +192,25 @@ impl<const IS_CREATE2: bool> Opcode for Create<IS_CREATE2> {
192192
H256::zero()
193193
};
194194

195-
// use CodeHash rw not zero to check address already exists
196-
state.account_read(
197-
&mut exec_step,
198-
address,
199-
AccountField::CodeHash,
200-
code_hash_previous.to_word(),
201-
);
202-
203-
// read callee nonce for address collision checking
204-
if !code_hash_previous.is_zero() {
195+
// If precheck is not ok, we even do not need to read codehash of callee.
196+
if is_precheck_ok {
197+
// use CodeHash rw not zero to check address already exists
205198
state.account_read(
206199
&mut exec_step,
207200
address,
208-
AccountField::Nonce,
209-
callee_account.nonce,
201+
AccountField::CodeHash,
202+
code_hash_previous.to_word(),
210203
);
204+
205+
// read callee nonce for address collision checking
206+
if !code_hash_previous.is_zero() {
207+
state.account_read(
208+
&mut exec_step,
209+
address,
210+
AccountField::Nonce,
211+
callee_account.nonce,
212+
);
213+
}
211214
}
212215

213216
if is_precheck_ok && !is_address_collision {

bus-mapping/src/util.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,20 @@ pub static CHECK_MEM_STRICT: Lazy<bool> = Lazy::new(|| read_env_var("CHECK_MEM_S
1818
pub const POSEIDON_HASH_BYTES_IN_FIELD: usize = 31;
1919

2020
/// Default code hash
21-
pub(crate) fn hash_code(code: &[u8]) -> Hash {
21+
pub fn hash_code(code: &[u8]) -> Hash {
2222
#[cfg(feature = "scroll")]
2323
return hash_code_poseidon(code);
2424
#[cfg(not(feature = "scroll"))]
2525
return hash_code_keccak(code);
2626
}
2727

28-
pub(crate) fn hash_code_keccak(code: &[u8]) -> Hash {
28+
/// Keccak code hash
29+
pub fn hash_code_keccak(code: &[u8]) -> Hash {
2930
eth_types::H256(ethers_core::utils::keccak256(code))
3031
}
3132

32-
pub(crate) fn hash_code_poseidon(code: &[u8]) -> Hash {
33+
/// Poseidon code hash
34+
pub fn hash_code_poseidon(code: &[u8]) -> Hash {
3335
use poseidon_circuit::hash::{Hashable, MessageHashable, HASHABLE_DOMAIN_SPEC};
3436

3537
let bytes_in_field = POSEIDON_HASH_BYTES_IN_FIELD;

external-tracer/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ pub fn l2trace(config: &TraceConfig) -> Result<BlockTrace, Error> {
120120

121121
log::trace!("trace: {}", trace_string);
122122

123-
let trace = serde_json::from_str(&trace_string).map_err(Error::SerdeError)?;
123+
let mut trace: BlockTrace = serde_json::from_str(&trace_string).map_err(Error::SerdeError)?;
124+
// l2 geth returns nil base_fee even if it is not 0..
125+
trace.header.base_fee_per_gas = Some(config.block_constants.base_fee);
124126
Ok(trace)
125127
}
126128

geth-utils/l2geth/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.18
55
require (
66
github.com/holiman/uint256 v1.2.0
77
github.com/imdario/mergo v0.3.15
8-
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827010026-8e452d413b6f
8+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827145523-9be082146425
99
)
1010

1111
require (

geth-utils/l2geth/go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,16 @@ github.com/scroll-tech/go-ethereum v1.10.14-0.20230820103920-be1600f07899 h1:bEx
109109
github.com/scroll-tech/go-ethereum v1.10.14-0.20230820103920-be1600f07899/go.mod h1:DiN3p2inoXOxGffxSswDKqWjQ7bU+Mp0c9v0XQXKmaA=
110110
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827010026-8e452d413b6f h1:FaxROT7QkVZ0ezyW0VxLDjc3yy0h1DDRNC12vitsYmA=
111111
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827010026-8e452d413b6f/go.mod h1:DiN3p2inoXOxGffxSswDKqWjQ7bU+Mp0c9v0XQXKmaA=
112+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827094559-de45f08802ca h1:tbbaZgk0dI7ZMCJCcYVnQiy1B2xfN4qqOqeELRIYLJE=
113+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827094559-de45f08802ca/go.mod h1:DiN3p2inoXOxGffxSswDKqWjQ7bU+Mp0c9v0XQXKmaA=
114+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827133453-e17c463eaee2 h1:0OVWWVN6VL5zR+OIrl1j2cBto5s44aoNHw7xKIqBVvU=
115+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827133453-e17c463eaee2/go.mod h1:DiN3p2inoXOxGffxSswDKqWjQ7bU+Mp0c9v0XQXKmaA=
116+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827134248-41544bfba4db h1:P2qM3/F3CPfGUyxivM9GEVZyGdn7ausd4/3y0QVS6IE=
117+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827134248-41544bfba4db/go.mod h1:DiN3p2inoXOxGffxSswDKqWjQ7bU+Mp0c9v0XQXKmaA=
118+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827135613-d4f288562708 h1:4O2FUl4E5NiW8vRlUKISOD2QqcKU/BBG7+VARSFSVKQ=
119+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827135613-d4f288562708/go.mod h1:DiN3p2inoXOxGffxSswDKqWjQ7bU+Mp0c9v0XQXKmaA=
120+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827145523-9be082146425 h1:xyKoHzmC7yekIvRouztNS6NP7EW7UPh+tjA6jLMP7Q8=
121+
github.com/scroll-tech/go-ethereum v1.10.14-0.20230827145523-9be082146425/go.mod h1:DiN3p2inoXOxGffxSswDKqWjQ7bU+Mp0c9v0XQXKmaA=
112122
github.com/scroll-tech/zktrie v0.6.0 h1:xLrMAO31Yo2BiPg1jtYKzcjpEFnXy8acbB7iIsyshPs=
113123
github.com/scroll-tech/zktrie v0.6.0/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk=
114124
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=

testool/src/statetest/executor.rs

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
use super::{AccountMatch, StateTest, StateTestResult};
22
use crate::config::TestSuite;
3-
use bus_mapping::circuit_input_builder::{CircuitInputBuilder, CircuitsParams, PrecompileEcParams};
3+
use bus_mapping::{
4+
circuit_input_builder::{CircuitInputBuilder, CircuitsParams, PrecompileEcParams},
5+
state_db::CodeDB,
6+
};
47
use eth_types::{
5-
geth_types, geth_types::TxType, Address, Bytes, GethExecTrace, ToBigEndian, U256, U64,
8+
geth_types, geth_types::TxType, Address, Bytes, GethExecTrace, ToBigEndian, ToWord, H256, U256,
9+
U64,
610
};
711
use ethers_core::{
812
types::{transaction::eip2718::TypedTransaction, TransactionRequest},
@@ -43,6 +47,9 @@ pub enum StateTestError {
4347
SkipTestMaxSteps(usize),
4448
#[error("SkipTestSelfDestruct")]
4549
SkipTestSelfDestruct,
50+
#[error("SkipTestDifficulty")]
51+
// scroll evm always returns 0 for "difficulty" opcode
52+
SkipTestDifficulty,
4653
#[error("SkipTestBalanceOverflow")]
4754
SkipTestBalanceOverflow,
4855
#[error("Exception(expected:{expected:?}, found:{found:?})")]
@@ -53,12 +60,15 @@ impl StateTestError {
5360
pub fn is_skip(&self) -> bool {
5461
// Avoid lint `variant is never constructed` if no feature skip-self-destruct.
5562
let _ = StateTestError::SkipTestSelfDestruct;
63+
let _ = StateTestError::SkipTestDifficulty;
5664

5765
matches!(
5866
self,
5967
StateTestError::SkipTestMaxSteps(_)
6068
| StateTestError::SkipTestMaxGasLimit(_)
6169
| StateTestError::SkipTestSelfDestruct
70+
| StateTestError::SkipTestBalanceOverflow
71+
| StateTestError::SkipTestDifficulty
6272
)
6373
}
6474
}
@@ -214,12 +224,22 @@ fn check_geth_traces(
214224
verbose: bool,
215225
) -> Result<(), StateTestError> {
216226
#[cfg(feature = "skip-self-destruct")]
227+
if geth_traces.iter().any(|gt| {
228+
gt.struct_logs.iter().any(|sl| {
229+
sl.op == eth_types::evm_types::OpcodeId::SELFDESTRUCT
230+
|| sl.op == eth_types::evm_types::OpcodeId::INVALID(0xff)
231+
})
232+
}) {
233+
return Err(StateTestError::SkipTestSelfDestruct);
234+
}
235+
236+
#[cfg(feature = "scroll")]
217237
if geth_traces.iter().any(|gt| {
218238
gt.struct_logs
219239
.iter()
220-
.any(|sl| sl.op == eth_types::evm_types::OpcodeId::SELFDESTRUCT)
240+
.any(|sl| sl.op == eth_types::evm_types::OpcodeId::DIFFICULTY)
221241
}) {
222-
return Err(StateTestError::SkipTestSelfDestruct);
242+
return Err(StateTestError::SkipTestDifficulty);
223243
}
224244

225245
if geth_traces[0].struct_logs.len() as u64 > suite.max_steps {
@@ -508,22 +528,22 @@ pub fn run_test(
508528

509529
#[cfg(feature = "scroll")]
510530
let result = trace_config_to_witness_block_l2(
511-
trace_config,
531+
trace_config.clone(),
512532
st,
513533
suite,
514534
circuits_params,
515535
circuits_config.verbose,
516536
)?;
517537
#[cfg(not(feature = "scroll"))]
518538
let result = trace_config_to_witness_block_l1(
519-
trace_config,
539+
trace_config.clone(),
520540
st,
521541
suite,
522542
circuits_params,
523543
circuits_config.verbose,
524544
)?;
525545

526-
let (witness_block, builder) = match result {
546+
let (witness_block, mut builder) = match result {
527547
Some((witness_block, builder)) => (witness_block, builder),
528548
None => return Ok(()),
529549
};
@@ -545,6 +565,35 @@ pub fn run_test(
545565
prover.assert_satisfied_par();
546566
};
547567

568+
//#[cfg(feature = "scroll")]
569+
{
570+
// fill these "untouched" storage slots
571+
// It is better to fill these info after (instead of before) bus-mapping re-exec.
572+
// To prevent these data being used unexpectedly.
573+
for account in trace_config.accounts.values() {
574+
builder.code_db.insert(account.code.to_vec());
575+
let (exist, acc_in_local_sdb) = builder.sdb.get_account_mut(&account.address);
576+
if !exist {
577+
// modified from bus-mapping/src/mock.rs
578+
let keccak_code_hash = H256(keccak256(account.code.to_vec()));
579+
let code_hash = CodeDB::hash(&account.code.to_vec());
580+
*acc_in_local_sdb = bus_mapping::state_db::Account {
581+
nonce: account.nonce,
582+
balance: account.balance,
583+
storage: account.storage.clone(),
584+
code_hash,
585+
keccak_code_hash,
586+
code_size: account.code.len().to_word(),
587+
};
588+
} else {
589+
for (k, v) in &account.storage {
590+
if !acc_in_local_sdb.storage.contains_key(k) {
591+
acc_in_local_sdb.storage.insert(*k, *v);
592+
}
593+
}
594+
}
595+
}
596+
}
548597
check_post(&builder, &post)?;
549598

550599
Ok(())

testool/src/statetest/spec.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ use eth_types::{geth_types::Account, Address, Bytes, Word, H256, U256};
33
use ethers_core::{k256::ecdsa::SigningKey, utils::secret_key_to_address};
44
use std::{collections::HashMap, str::FromStr};
55

6-
/// TODO: Explain this
7-
#[cfg(feature = "scroll")]
8-
pub const DEFAULT_BASE_FEE: u32 = 0;
9-
#[cfg(not(feature = "scroll"))]
6+
/// https://github.com/ethereum/tests/pull/857 "set default gasPrice to 10"
107
pub const DEFAULT_BASE_FEE: u32 = 10;
118

129
#[derive(PartialEq, Eq, Debug, Clone)]

zkevm-circuits/src/evm_circuit/execution/create.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -285,20 +285,22 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
285285
);
286286
});
287287

288-
// check for address collision case by code hash previous
289-
cb.account_read(
290-
new_address.clone(),
291-
AccountFieldTag::CodeHash,
292-
code_hash_previous.expr(),
293-
);
294288
// callee address's nonce
295289
let code_hash_is_zero = IsZeroGadget::construct(cb, code_hash_previous.expr());
296-
cb.condition(not::expr(code_hash_is_zero.expr()), |cb| {
290+
// check for address collision case by code hash previous
291+
cb.condition(is_precheck_ok.expr(), |cb| {
297292
cb.account_read(
298293
new_address.clone(),
299-
AccountFieldTag::Nonce,
300-
callee_nonce.expr(),
294+
AccountFieldTag::CodeHash,
295+
code_hash_previous.expr(),
301296
);
297+
cb.condition(not::expr(code_hash_is_zero.expr()), |cb| {
298+
cb.account_read(
299+
new_address.clone(),
300+
AccountFieldTag::Nonce,
301+
callee_nonce.expr(),
302+
);
303+
});
302304
});
303305

304306
let code_hash_is_empty =
@@ -651,7 +653,7 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
651653
let is_precheck_ok =
652654
call.depth < 1025 && caller_balance >= value && caller_nonce < u64::MAX;
653655
if is_precheck_ok {
654-
rws.next();
656+
rws.next(); // caller nonce += 1
655657
}
656658
let [callee_rw_counter_end_of_reversion, callee_is_persistent] =
657659
[(); 2].map(|_| rws.next().call_context_value());
@@ -667,14 +669,18 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
667669
)?;
668670

669671
// retrieve code_hash for creating address
670-
let code_hash_previous = rws.next().account_codehash_pair();
671-
let callee_nonce = if !code_hash_previous.0.is_zero() {
672+
let code_hash_previous = if is_precheck_ok {
673+
rws.next().account_codehash_pair().0
674+
} else {
675+
0.into()
676+
};
677+
let callee_nonce = if !code_hash_previous.is_zero() {
672678
rws.next().account_nonce_pair().1.low_u64()
673679
} else {
674680
0
675681
};
676682

677-
let code_hash_previous_rlc = region.code_hash(code_hash_previous.0);
683+
let code_hash_previous_rlc = region.code_hash(code_hash_previous);
678684
self.code_hash_previous
679685
.assign(region, offset, code_hash_previous_rlc)?;
680686
self.code_hash_is_zero
@@ -692,8 +698,8 @@ impl<F: Field, const IS_CREATE2: bool, const S: ExecutionState> ExecutionGadget<
692698
.assign(region, offset, F::from(callee_nonce))?;
693699

694700
let callee_nonce_is_zero = callee_nonce == 0;
695-
let codehash_non_empty = !code_hash_previous.0.is_zero()
696-
&& code_hash_previous.0 != CodeDB::empty_code_hash().to_word();
701+
let codehash_non_empty = !code_hash_previous.is_zero()
702+
&& code_hash_previous != CodeDB::empty_code_hash().to_word();
697703
let is_address_collision = !callee_nonce_is_zero || codehash_non_empty;
698704
if is_precheck_ok && !is_address_collision {
699705
/*

zkevm-circuits/src/super_circuit/test.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ use rand_chacha::ChaCha20Rng;
1818
use std::env::set_var;
1919

2020
use crate::witness::block_apply_mpt_state;
21-
use eth_types::{address, bytecode, l2_types::BlockTrace, word, Bytecode, ToWord, Word};
21+
#[cfg(feature = "scroll")]
22+
use eth_types::l2_types::BlockTrace;
23+
use eth_types::{address, bytecode, word, Bytecode, ToWord, Word};
2224

2325
#[test]
2426
fn super_circuit_degree() {

0 commit comments

Comments
 (0)