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

Commit 6ed1831

Browse files
authored
feat: initial support dencun (#677)
* feat(wip): initial support dencun * feat: add option to skip an entire directory * feat: ignore BEACON_ROOT address in post_state * feat: add fallback mechanism if secretKey is not found * adapt blockchain-tests-skip.yml * fix: fmt * feat: support multi-tx blocks * refactor: check case name end for fork name * comment on multi-tx blocks' * fix: add specific fork-filter case for Pyspec tests * move secret_key fallback in secret_key() * feat: base filter on formatted test identifier * address review
1 parent 5d0b86e commit 6ed1831

File tree

12 files changed

+317
-126
lines changed

12 files changed

+317
-126
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ifneq ("$(wildcard .env)","")
66
endif
77

88
# The release tag of https://github.com/ethereum/tests to use for EF tests
9-
EF_TESTS_TAG := v12.4
9+
EF_TESTS_TAG := v13.2
1010
EF_TESTS_URL := https://github.com/ethereum/tests/archive/refs/tags/$(EF_TESTS_TAG).tar.gz
1111
EF_TESTS_DIR := ./crates/ef-testing/ethereum-tests
1212

blockchain-tests-skip.yml

Lines changed: 54 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,66 @@
22
# The first level corresponds to the directory, the second to the list of file names regex to ignore.
33
# In the ef-tests repo, we skip all tests but the vmArithmeticTest.
44

5+
directories:
6+
- Pyspecs
7+
- Cancun
8+
59
filename:
610
None:
711
- None
812

913
testname:
1014
vmArithmeticTest:
11-
- addmod_d10g0v0_Shanghai
12-
- addmod_d11g0v0_Shanghai
13-
- addmod_d8g0v0_Shanghai
14-
- addmod_d9g0v0_Shanghai
15-
- divByZero_d63g0v0_Shanghai
16-
- divByZero_d64g0v0_Shanghai
17-
- divByZero_d65g0v0_Shanghai
18-
- divByZero_d66g0v0_Shanghai
19-
- divByZero_d67g0v0_Shanghai
20-
- divByZero_d68g0v0_Shanghai
21-
- divByZero_d69g0v0_Shanghai
22-
- divByZero_d70g0v0_Shanghai
23-
- divByZero_d71g0v0_Shanghai
24-
- divByZero_d72g0v0_Shanghai
25-
- divByZero_d73g0v0_Shanghai
26-
- divByZero_d74g0v0_Shanghai
27-
- divByZero_d75g0v0_Shanghai
28-
- divByZero_d76g0v0_Shanghai
29-
- divByZero_d77g0v0_Shanghai
30-
- divByZero_d78g0v0_Shanghai
31-
- divByZero_d79g0v0_Shanghai
32-
- divByZero_d80g0v0_Shanghai
33-
- divByZero_d81g0v0_Shanghai
34-
- divByZero_d82g0v0_Shanghai
35-
- divByZero_d83g0v0_Shanghai
36-
- divByZero_d84g0v0_Shanghai
37-
- divByZero_d85g0v0_Shanghai
38-
- divByZero_d86g0v0_Shanghai
39-
- divByZero_d87g0v0_Shanghai
40-
- divByZero_d88g0v0_Shanghai
41-
- divByZero_d89g0v0_Shanghai
42-
- divByZero_d90g0v0_Shanghai
43-
- divByZero_d91g0v0_Shanghai
44-
- divByZero_d92g0v0_Shanghai
45-
- divByZero_d93g0v0_Shanghai
46-
- divByZero_d94g0v0_Shanghai
47-
- divByZero_d95g0v0_Shanghai
48-
- divByZero_d96g0v0_Shanghai
49-
- divByZero_d97g0v0_Shanghai
50-
- expPower256Of256_d0g0v0_Shanghai
51-
- exp_d1g0v0_Shanghai
52-
- exp_d3g0v0_Shanghai
53-
- exp_d8g0v0_Shanghai
54-
- exp_d9g0v0_Shanghai
55-
- expPower256_d0g0v0_Shanghai
56-
- mulmod_d12g0v0_Shanghai
57-
- mulmod_d13g0v0_Shanghai
58-
- mulmod_d14g0v0_Shanghai
59-
- mulmod_d15g0v0_Shanghai
60-
- twoOps_d0g0v0_Shanghai
15+
- addmod_d10g0v0_Cancun
16+
- addmod_d11g0v0_Cancun
17+
- addmod_d8g0v0_Cancun
18+
- addmod_d9g0v0_Cancun
19+
- divByZero_d63g0v0_Cancun
20+
- divByZero_d64g0v0_Cancun
21+
- divByZero_d65g0v0_Cancun
22+
- divByZero_d66g0v0_Cancun
23+
- divByZero_d67g0v0_Cancun
24+
- divByZero_d68g0v0_Cancun
25+
- divByZero_d69g0v0_Cancun
26+
- divByZero_d70g0v0_Cancun
27+
- divByZero_d71g0v0_Cancun
28+
- divByZero_d72g0v0_Cancun
29+
- divByZero_d73g0v0_Cancun
30+
- divByZero_d74g0v0_Cancun
31+
- divByZero_d75g0v0_Cancun
32+
- divByZero_d76g0v0_Cancun
33+
- divByZero_d77g0v0_Cancun
34+
- divByZero_d78g0v0_Cancun
35+
- divByZero_d79g0v0_Cancun
36+
- divByZero_d80g0v0_Cancun
37+
- divByZero_d81g0v0_Cancun
38+
- divByZero_d82g0v0_Cancun
39+
- divByZero_d83g0v0_Cancun
40+
- divByZero_d84g0v0_Cancun
41+
- divByZero_d85g0v0_Cancun
42+
- divByZero_d86g0v0_Cancun
43+
- divByZero_d87g0v0_Cancun
44+
- divByZero_d88g0v0_Cancun
45+
- divByZero_d89g0v0_Cancun
46+
- divByZero_d90g0v0_Cancun
47+
- divByZero_d91g0v0_Cancun
48+
- divByZero_d92g0v0_Cancun
49+
- divByZero_d93g0v0_Cancun
50+
- divByZero_d94g0v0_Cancun
51+
- divByZero_d95g0v0_Cancun
52+
- divByZero_d96g0v0_Cancun
53+
- divByZero_d97g0v0_Cancun
54+
- expPower256Of256_d0g0v0_Cancun
55+
- exp_d1g0v0_Cancun
56+
- exp_d3g0v0_Cancun
57+
- exp_d8g0v0_Cancun
58+
- exp_d9g0v0_Cancun
59+
- expPower256_d0g0v0_Cancun
60+
- mulmod_d12g0v0_Cancun
61+
- mulmod_d13g0v0_Cancun
62+
- mulmod_d14g0v0_Cancun
63+
- mulmod_d15g0v0_Cancun
64+
- twoOps_d0g0v0_Cancun
6165

6266
regex:
6367
stArgsZeroOneBalance:

crates/build-utils/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ serde = { workspace = true }
1919
serde_json = { workspace = true }
2020
serde_yaml = { workspace = true }
2121
walkdir = { workspace = true }
22+
reth-primitives = { workspace = true }

crates/build-utils/src/constants.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,33 @@
1+
use lazy_static::lazy_static;
2+
use reth_primitives::alloy_primitives::{address, Address};
3+
use std::collections::HashMap;
4+
15
pub const ROOT: &str = "GeneralStateTests";
2-
pub const FORK: &str = "Shanghai";
6+
pub const FORK: &str = "Cancun";
7+
8+
lazy_static! {
9+
// A registry of the most common addresses and their associated secret keys.
10+
// Most secret keys can be read from filler files directly - however, for python-based
11+
// tests, the secret keys are not present in the filler files. This registry
12+
// is used to fill in the missing secret keys (only two used in pyspec tests).
13+
pub static ref ADDRESSES_KEYS: HashMap<Address, &'static str> = {
14+
let mut registry = HashMap::new();
15+
registry.insert(
16+
address!("a94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
17+
"0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
18+
);
19+
registry.insert(
20+
address!("8a0a19589531694250d570040a0c4b74576919b8"),
21+
"0x9e7645d0cfd9c3a04eb7a9db59a4eb7d359f2e75c9164a9d6b9a7d54e1b6a36f",
22+
);
23+
registry.insert(
24+
address!("d02d72e067e77158444ef2020ff2d325f929b363"),
25+
"41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298",
26+
);
27+
registry.insert(
28+
address!("97a7cb1de3cc7d556d0aa32433b035067709e1fc"),
29+
"0x0b2986cc45bd8a8d028c3fcf6f7a11a52f1df61f3ea5d63f05ca109dd73a3fa0"
30+
);
31+
registry
32+
};
33+
}

crates/build-utils/src/content_reader.rs

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
use std::collections::BTreeMap;
22

3+
use reth_primitives::{revm_primitives::FixedBytes, Address};
34
use serde_json::Value;
45

5-
use crate::{path::PathWrapper, utils::blockchain_tests_to_general_state_tests_path};
6+
use crate::{
7+
constants::ADDRESSES_KEYS, path::PathWrapper,
8+
utils::blockchain_tests_to_general_state_tests_path,
9+
};
610

711
/// The `ContentReader` is used to read the content of the ef-test tests files.
812
/// The tests files are located in the `BlockchainTests` folder and contain
@@ -22,20 +26,45 @@ impl ContentReader {
2226
///
2327
/// Test location: BlockchainTests/GeneralStateTests/stRandom/randomStatetest0.json
2428
/// Secret key location: GeneralStateTests/stRandom/randomStatetest0.json
25-
pub fn secret_key(path: PathWrapper) -> Result<Option<Value>, eyre::Error> {
29+
pub fn secret_key(
30+
path: PathWrapper,
31+
case_without_secret: &Value,
32+
) -> Result<String, eyre::Error> {
2633
let path = blockchain_tests_to_general_state_tests_path(path);
27-
let content = path.read_file_to_string()?;
34+
let maybe_content_with_secret = path.read_file_to_string();
35+
let case = match maybe_content_with_secret {
36+
Ok(content) => {
37+
let cases: BTreeMap<String, Value> = serde_json::from_str(&content)?;
38+
cases.into_values().next()
39+
}
40+
Err(_) => Some(case_without_secret.clone()),
41+
};
2842

29-
let cases: BTreeMap<String, Value> = serde_json::from_str(&content)?;
30-
let case = cases.into_values().next();
31-
32-
Ok(case
43+
let key = match case
3344
.as_ref()
3445
.and_then(|value| value.get("transaction"))
3546
.and_then(|value| value.get("secretKey"))
36-
.cloned())
37-
}
47+
{
48+
Some(key) => key.to_string(),
49+
None => {
50+
let block = Self::block(case_without_secret)?;
51+
let transaction = Self::transaction(case_without_secret, &block)?;
52+
let sender = transaction
53+
.get("sender")
54+
.and_then(|value| value.as_str())
55+
.ok_or_else(|| eyre::eyre!("Key 'sender' not found"))?;
3856

57+
let sender_address: Address = sender.parse::<FixedBytes<20>>()?.into();
58+
ADDRESSES_KEYS
59+
.get(&sender_address)
60+
.map(|addr| format!("\"{}\"", addr))
61+
.unwrap_or_else(|| panic!("No secret key found for {sender_address}"))
62+
}
63+
};
64+
Ok(key)
65+
}
66+
// Ok(
67+
// ))
3968
pub fn pre_state(test_case: &Value) -> Result<Value, eyre::Error> {
4069
Ok(serde_json::from_value(
4170
test_case
@@ -71,4 +100,31 @@ impl ContentReader {
71100
// Return a clone of the block
72101
Ok(first_block.clone())
73102
}
103+
104+
pub fn transaction(test_case: &Value, block: &Value) -> Result<Value, eyre::Error> {
105+
let maybe_transaction = block.get("transactions");
106+
107+
match maybe_transaction {
108+
Some(transaction) => {
109+
// Ensure it's an array
110+
let transaction_array = transaction
111+
.as_array()
112+
.ok_or_else(|| eyre::eyre!("'transactions' is not an array"))?;
113+
114+
// Get the first transaction - multi-txs tests are not supported by the runner
115+
let first_tx = transaction_array
116+
.first()
117+
.ok_or_else(|| eyre::eyre!("'transactions' array is empty"))?;
118+
119+
Ok(first_tx.clone())
120+
}
121+
None => {
122+
let transaction = test_case
123+
.get("transaction")
124+
.ok_or_else(|| eyre::eyre!("key 'transaction' not found"))?;
125+
126+
Ok(transaction.clone())
127+
}
128+
}
129+
}
74130
}

crates/build-utils/src/converter.rs

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,26 @@ use crate::{
1515
///
1616
/// Test location: BlockchainTests/GeneralStateTests/stRandom/
1717
/// List of tests: [randomStatetest0.json, randomStatetest1.json, ...]
18-
/// Inner tests: [`randomStatetest0_d0g0v0_Shanghai`, `randomStatetest0_d1g0v0_Shanghai`,
19-
/// ..., `randomStatetest1_d0g0v0_Shanghai`, `randomStatetest1_d1g0v0_Shanghai`, ...]
18+
/// Inner tests: [`randomStatetest0_d0g0v0_Cancun`, `randomStatetest0_d1g0v0_Cancun`,
19+
/// ..., `randomStatetest1_d0g0v0_Cancun`, `randomStatetest1_d1g0v0_Cancun`, ...]
2020
/// Generated String:
2121
/// r#"
2222
/// mod randomStatetest0 {
2323
/// use super::*;
2424
/// #[test]
25-
/// fn test_randomStatetest0_d0g0v0_Shanghai() {
25+
/// fn test_randomStatetest0_d0g0v0_Cancun() {
2626
/// ...
2727
/// }
2828
/// #[test]
29-
/// fn test_randomStatetest0_d1g0v0_Shanghai() {
29+
/// fn test_randomStatetest0_d1g0v0_Cancun() {
3030
/// ...
3131
/// }
3232
/// #[test]
33-
/// fn test_randomStatetest1_d0g0v0_Shanghai() {
33+
/// fn test_randomStatetest1_d0g0v0_Cancun() {
3434
/// ...
3535
/// }
3636
/// #[test]
37-
/// fn test_randomStatetest1_d1g0v0_Shanghai() {
37+
/// fn test_randomStatetest1_d1g0v0_Cancun() {
3838
/// ...
3939
/// }
4040
/// ...
@@ -93,12 +93,16 @@ impl<'a> EfTests<'a> {
9393
let file_contents = cases
9494
.par_iter()
9595
.map(|(case_name, content)| {
96-
if !case_name.contains(FORK) {
96+
if !(case_name.ends_with(FORK) || case_name.contains(&format!("fork_{}", FORK)))
97+
{
9798
return Ok(String::new());
9899
}
99-
let secret_key = ContentReader::secret_key(file_path.clone())?
100-
.ok_or_else(|| eyre::eyre!("Missing secret key"))?;
101100
let is_skipped = self.filter.is_skipped(file_path, Some(case_name.clone()));
101+
let secret_key = if is_skipped {
102+
String::default() // secret key is not needed if the test is skipped
103+
} else {
104+
ContentReader::secret_key(file_path.clone(), content)?
105+
};
102106
Self::format_to_test(case_name, parent_dir, &secret_key, content, is_skipped)
103107
})
104108
.collect::<Result<Vec<String>, eyre::Error>>()?;
@@ -140,7 +144,7 @@ impl<'a> EfTests<'a> {
140144
fn format_to_test(
141145
case_name: &str,
142146
parent_dir: &str,
143-
secret_key: &Value,
147+
secret_key: &String,
144148
content: &Value,
145149
is_skipped: bool,
146150
) -> Result<String, eyre::Error> {
@@ -166,7 +170,7 @@ impl<'a> EfTests<'a> {
166170
fn format_test_content(
167171
case_name: &str,
168172
parent_dir: &str,
169-
secret_key: &Value,
173+
secret_key: &String,
170174
content: &Value,
171175
is_skipped: bool,
172176
) -> Result<String, eyre::Error> {
@@ -198,9 +202,37 @@ impl<'a> EfTests<'a> {
198202
}
199203

200204
/// Formats the given string into a valid rust identifier.
201-
fn format_into_identifier(s: &str) -> String {
202-
s.replace('-', "_minus_")
203-
.replace('+', "_plus_")
204-
.replace('^', "_xor_")
205+
pub fn format_into_identifier(s: &str) -> String {
206+
// Pyspec tests are in form test_src/GeneralStateTestsFillerFiller/Pyspecs/berlin/eip2930_access_list/test_acl.py::test_access_list[fork_Cancun_minus_blockchain_test]()
207+
// We only keep the test name and its parameters.
208+
if s.contains("Pyspecs") {
209+
let test_name = s
210+
.split('/')
211+
.last()
212+
.unwrap_or_default()
213+
.split("::")
214+
.last()
215+
.unwrap_or_default();
216+
217+
let test_name = test_name
218+
.to_string()
219+
.replace("test_", "")
220+
.replace('(', "_lpar_")
221+
.replace(')', "_rpar")
222+
.replace('[', "__")
223+
.replace(']', "")
224+
.replace('-', "_minus_")
225+
.split(',')
226+
.map(|part| part.trim())
227+
.collect::<Vec<_>>()
228+
.join("_");
229+
230+
// add the fork name after the test name
231+
test_name
232+
} else {
233+
s.replace('-', "_minus_")
234+
.replace('+', "_plus_")
235+
.replace('^', "_xor_")
236+
}
205237
}
206238
}

0 commit comments

Comments
 (0)