Skip to content

Commit afefb13

Browse files
authored
Add support both with and without EIP-7610 in jsontests (#372)
* Add support both with and without EIP-7610 * Format and clippy * Avoid generic We have several thousands of tests. With generic it will create an instance for each of them!
1 parent f7083c5 commit afefb13

File tree

14 files changed

+182
-26
lines changed

14 files changed

+182
-26
lines changed

docs/development.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Development
2+
3+
## Config naming conventions
4+
5+
The name for a `Config` feature flag should be of the following format: `eipXXXX_short_description_name`. For example:
6+
7+
```
8+
eip161_empty_check
9+
eip7610_create_check_storage
10+
```

interpreter/src/eval/system.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ pub fn extcodehash<
146146
handler: &mut H,
147147
) -> Control<Tr> {
148148
pop_h256!(machine, address);
149-
let eip161 = AsRef::<RuntimeConfig>::as_ref(&machine.state).eip161;
149+
let eip161 = AsRef::<RuntimeConfig>::as_ref(&machine.state).eip161_empty_check;
150150
let is_empty = if eip161 {
151151
handler.is_empty(address.into())
152152
} else {

interpreter/src/runtime.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub struct RuntimeState {
2828
#[derive(Clone, Debug)]
2929
pub struct RuntimeConfig {
3030
/// Whether EIP-161 is enabled.
31-
pub eip161: bool,
31+
pub eip161_empty_check: bool,
3232
}
3333

3434
/// Runtime state and config.
@@ -40,7 +40,9 @@ pub struct RuntimeStateAndConfig<'config> {
4040
pub config: &'config RuntimeConfig,
4141
}
4242

43-
static DEFAULT_RUNTIME_CONFIG: RuntimeConfig = RuntimeConfig { eip161: true };
43+
static DEFAULT_RUNTIME_CONFIG: RuntimeConfig = RuntimeConfig {
44+
eip161_empty_check: true,
45+
};
4446

4547
impl RuntimeStateAndConfig<'static> {
4648
/// Used for testing, if you don't care about the config but simply want to

jsontests/proc-macro/src/lib.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,33 @@ use syn::{
1111
struct Input {
1212
prefix: LitStr,
1313
folder: LitStr,
14+
flags: Vec<Ident>,
1415
}
1516

1617
impl Parse for Input {
1718
fn parse(input: ParseStream) -> syn::Result<Self> {
1819
let prefix = input.parse()?;
1920
input.parse::<Token![,]>()?;
2021
let folder = input.parse()?;
21-
Ok(Input { prefix, folder })
22+
23+
if input.is_empty() {
24+
return Ok(Input {
25+
prefix,
26+
folder,
27+
flags: Vec::new(),
28+
});
29+
}
30+
31+
input.parse::<Token![;]>()?;
32+
let flags = input
33+
.parse_terminated(Ident::parse, Token![,])?
34+
.into_iter()
35+
.collect();
36+
Ok(Input {
37+
prefix,
38+
folder,
39+
flags,
40+
})
2241
}
2342
}
2443

@@ -41,23 +60,37 @@ pub fn statetest_folder(item: TokenStream) -> TokenStream {
4160
jsontests::run::collect_test_files(folder.to_str().expect("non-utf8 filename"))
4261
.expect("uninitialized submodule");
4362

63+
let mut disable_eip7610 = false;
64+
for flag in input.flags {
65+
if flag == "disable_eip7610" {
66+
disable_eip7610 = true;
67+
} else {
68+
panic!("unknown flag");
69+
}
70+
}
71+
4472
let mut tests = Vec::new();
4573
for (test_file_name, test_file_path) in test_files {
4674
let mut name = format!("{prefix:}/{test_file_name:}");
4775
name = name.replace("/", "__");
4876
let ident = Ident::new(&name, Span::call_site());
77+
let modify_config = if disable_eip7610 {
78+
quote! { jsontests::run::disable_eip7610 }
79+
} else {
80+
quote! { jsontests::run::empty_config_change }
81+
};
4982
tests.push(quote! {
5083
#[test]
5184
fn #ident() -> Result<(), jsontests::error::Error> {
52-
let tests_status = jsontests::run::run_file(#test_file_path, false, None);
85+
let tests_status = jsontests::run::run_file(#test_file_path, false, None, #modify_config);
5386
match tests_status {
5487
Ok(tests_status) => {
5588
tests_status.print_total();
5689
Ok(())
5790
},
5891
Err(err) => {
5992
// Rerun tests with debug flag.
60-
jsontests::run::run_file(#test_file_path, true, Some("failed.json"))?;
93+
jsontests::run::run_file(#test_file_path, true, Some("failed.json"), #modify_config)?;
6194
Err(err)
6295
},
6396
}

jsontests/src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ fn main() -> Result<(), Error> {
1919

2020
let mut tests_status = TestCompletionStatus::default();
2121
for filename in cli.filenames {
22-
tests_status += run::run_single(&filename, cli.debug, cli.write_failed.as_deref())?;
22+
tests_status += run::run_single(
23+
&filename,
24+
cli.debug,
25+
cli.write_failed.as_deref(),
26+
run::empty_config_change,
27+
)?;
2328
}
2429
tests_status.print_total();
2530

jsontests/src/run.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,20 @@ fn get_short_file_name(filename: &str) -> String {
3333
short_file_name.clone().to_string()
3434
}
3535

36+
/// Don't do any config change.
37+
pub fn empty_config_change(_config: &mut Config) {}
38+
39+
/// Disable EIP-7610.
40+
pub fn disable_eip7610(config: &mut Config) {
41+
config.eip7610_create_check_storage = false;
42+
}
43+
3644
/// Run tests for specific json file with debug flag
3745
pub fn run_file(
3846
filename: &str,
3947
debug: bool,
4048
write_failed: Option<&str>,
49+
config_change: fn(&mut Config),
4150
) -> Result<TestCompletionStatus, Error> {
4251
let test_multi: BTreeMap<String, TestMulti> =
4352
serde_json::from_reader(BufReader::new(File::open(filename)?))?;
@@ -58,7 +67,14 @@ pub fn run_file(
5867
test.fork, short_file_name, test_name, test.index
5968
);
6069
}
61-
match run_test(filename, &test_name, test.clone(), debug, write_failed) {
70+
match run_test(
71+
filename,
72+
&test_name,
73+
test.clone(),
74+
debug,
75+
write_failed,
76+
config_change,
77+
) {
6278
Ok(()) => {
6379
tests_status.inc_completed();
6480
println!("ok")
@@ -88,6 +104,7 @@ pub fn run_single(
88104
filename: &str,
89105
debug: bool,
90106
write_failed: Option<&str>,
107+
config_change: fn(&mut Config),
91108
) -> Result<TestCompletionStatus, Error> {
92109
if fs::metadata(filename)?.is_dir() {
93110
let mut tests_status = TestCompletionStatus::default();
@@ -98,13 +115,13 @@ pub fn run_single(
98115

99116
if filename.ends_with(".json") {
100117
println!("RUN for: {filename}");
101-
tests_status += run_file(filename, debug, write_failed)?;
118+
tests_status += run_file(filename, debug, write_failed, config_change)?;
102119
}
103120
}
104121
tests_status.print_total_for_dir(filename);
105122
Ok(tests_status)
106123
} else {
107-
run_file(filename, debug, write_failed)
124+
run_file(filename, debug, write_failed, config_change)
108125
}
109126
}
110127

@@ -159,11 +176,13 @@ pub fn run_test(
159176
test: TestData,
160177
debug: bool,
161178
write_failed: Option<&str>,
179+
config_change: fn(&mut Config),
162180
) -> Result<(), Error> {
163-
let config = match test.fork {
181+
let mut config = match test.fork {
164182
Fork::Istanbul => Config::istanbul(),
165183
_ => return Err(Error::UnsupportedFork),
166184
};
185+
config_change(&mut config);
167186

168187
if test.post.expect_exception == Some(TestExpectException::TR_TypeNotSupported) {
169188
// The `evm` crate does not understand transaction format, only the `ethereum` crate. So

jsontests/src/types.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,28 @@ pub enum TestExpectException {
211211
TR_InitCodeLimitExceeded,
212212
IntrinsicGas,
213213
SenderNotEOA,
214+
#[serde(rename = "TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS")]
215+
TE_INSUFFICIENT_MAX_FEE_PER_BLOB_GAS,
216+
#[serde(rename = "TransactionException.INSUFFICIENT_ACCOUNT_FUNDS")]
217+
TE_INSUFFICIENT_ACCOUNT_FUNDS,
218+
#[serde(rename = "TransactionException.TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH")]
219+
TE_TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH,
220+
#[serde(
221+
rename = "TransactionException.TYPE_3_TX_PRE_FORK|TransactionException.TYPE_3_TX_ZERO_BLOBS"
222+
)]
223+
TE_TYPE_3_TX_PER_FORK_OR_TX_ZERO_BLOBS,
224+
#[serde(rename = "TransactionException.INSUFFICIENT_MAX_FEE_PER_GAS")]
225+
TE_INSUFFICIENT_MAX_FEE_PER_GAS,
226+
#[serde(rename = "TransactionException.TYPE_3_TX_ZERO_BLOBS")]
227+
TE_TYPE_3_TX_ZERO_BLOBS,
228+
#[serde(rename = "TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED")]
229+
TE_TYPE_3_TX_BLOB_COUNT_EXCEEDED,
230+
#[serde(rename = "TransactionException.TYPE_3_TX_PRE_FORK")]
231+
TE_TYPE_3_TX_PER_FORK,
232+
#[serde(rename = "TransactionException.INITCODE_SIZE_EXCEEDED")]
233+
TE_INITCODE_SIZE_EXCEEDED,
234+
#[serde(rename = "TransactionException.INTRINSIC_GAS_TOO_LOW")]
235+
TE_INTRINSIC_GAS_TOO_LOW,
214236
}
215237

216238
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]

jsontests/tests/legacytests.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
// use jsontests_proc_macro::statetest_folder;
2-
//
3-
// statetest_folder!("legacytests_constaninople", "../res/legacytests/Constantinople/GeneralStateTests");
1+
use jsontests_proc_macro::statetest_folder;
2+
3+
statetest_folder!(
4+
"legacytests_constaninople",
5+
"../res/legacytests/Constantinople/GeneralStateTests"
6+
);
47
// statetest_folder!("legacytests_constaninople_vmtests", "../res/legacytests/Constantinople/VMTests");
5-
// statetest_folder!("legacytests_cancun", "../res/legacytests/Cancun/GeneralStateTests");
8+
statetest_folder!(
9+
"legacytests_cancun",
10+
"../res/legacytests/Cancun/GeneralStateTests"
11+
);

jsontests/tests/oldethtests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
use jsontests_proc_macro::statetest_folder;
22

3-
statetest_folder!("oldethtests", "../res/ethtests/GeneralStateTests");
3+
statetest_folder!("oldethtests", "../res/ethtests/GeneralStateTests"; disable_eip7610);

src/backend/in_memory.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,16 @@ impl RuntimeBaseBackend for InMemoryBackend {
204204
.unwrap_or(Default::default())
205205
.nonce
206206
}
207+
208+
fn can_create(&self, address: H160) -> bool {
209+
self.nonce(address) == U256::zero()
210+
&& self.code_size(address) == U256::zero()
211+
&& self
212+
.state
213+
.get(&address)
214+
.cloned()
215+
.unwrap_or(Default::default())
216+
.storage
217+
.is_empty()
218+
}
207219
}

0 commit comments

Comments
 (0)