|
1 | | -use std::{collections::HashMap, path::Path}; |
| 1 | +use std::{collections::HashMap, path::Path, sync::Arc}; |
2 | 2 |
|
3 | 3 | use crate::{ |
4 | 4 | fork::Fork, |
5 | 5 | types::{BlockChainExpectedException, BlockExpectedException, BlockWithRLP, TestUnit}, |
6 | 6 | }; |
7 | 7 | use ethrex_blockchain::{ |
8 | | - Blockchain, BlockchainOptions, |
| 8 | + Blockchain, |
9 | 9 | error::{ChainError, InvalidBlockError}, |
10 | 10 | fork_choice::apply_fork_choice, |
11 | 11 | }; |
| 12 | + |
| 13 | +thread_local! { |
| 14 | + /// Per-OS-thread merkleization pool, lazily built on first use. Mirrors the |
| 15 | + /// pattern used by `ef_tests/engine` so the ~10k+ blockchain tests |
| 16 | + /// don't each spawn a fresh 17-thread rayon pool inside `Blockchain::new`. |
| 17 | + /// The merkle protocol's 16 worker jobs cross-communicate via channels, so |
| 18 | + /// each pool may have only one concurrent `in_place_scope` caller; keying by |
| 19 | + /// `thread_local!` makes the calling test-runner thread the natural |
| 20 | + /// exclusive owner. |
| 21 | + static MERKLE_POOL: std::cell::OnceCell<Arc<rayon::ThreadPool>> = |
| 22 | + const { std::cell::OnceCell::new() }; |
| 23 | +} |
| 24 | + |
| 25 | +fn merkle_pool() -> Arc<rayon::ThreadPool> { |
| 26 | + MERKLE_POOL.with(|cell| cell.get_or_init(Blockchain::build_merkle_pool).clone()) |
| 27 | +} |
12 | 28 | #[cfg(feature = "stateless")] |
13 | 29 | use ethrex_common::types::block_execution_witness::RpcExecutionWitness; |
14 | 30 | use ethrex_common::{ |
@@ -85,7 +101,7 @@ pub async fn run_ef_test( |
85 | 101 | check_prestate_against_db(test_key, test, &store); |
86 | 102 |
|
87 | 103 | // Blockchain EF tests are meant for L1. |
88 | | - let blockchain = Blockchain::new(store.clone(), BlockchainOptions::default()); |
| 104 | + let blockchain = Blockchain::default_with_store_and_pool(store.clone(), merkle_pool()); |
89 | 105 |
|
90 | 106 | // Early return if the exception is in the rlp decoding of the block |
91 | 107 | for bf in &test.blocks { |
@@ -188,7 +204,7 @@ async fn run( |
188 | 204 | async fn run_two_pass_parallel(test_key: &str, test: &TestUnit) -> Result<(), String> { |
189 | 205 | // ---- Pass 1: sequential, collect BALs ---- |
190 | 206 | let store1 = build_store_for_test(test).await; |
191 | | - let blockchain1 = Blockchain::new(store1.clone(), BlockchainOptions::default()); |
| 207 | + let blockchain1 = Blockchain::default_with_store_and_pool(store1.clone(), merkle_pool()); |
192 | 208 |
|
193 | 209 | let mut bals: Vec<BlockAccessList> = Vec::with_capacity(test.blocks.len()); |
194 | 210 |
|
@@ -220,7 +236,7 @@ async fn run_two_pass_parallel(test_key: &str, test: &TestUnit) -> Result<(), St |
220 | 236 |
|
221 | 237 | // ---- Pass 2: parallel (BAL-driven), verify post-state ---- |
222 | 238 | let store2 = build_store_for_test(test).await; |
223 | | - let blockchain2 = Blockchain::new(store2.clone(), BlockchainOptions::default()); |
| 239 | + let blockchain2 = Blockchain::default_with_store_and_pool(store2.clone(), merkle_pool()); |
224 | 240 |
|
225 | 241 | for (block_fixture, bal) in test.blocks.iter().zip(bals.iter()) { |
226 | 242 | let block: CoreBlock = block_fixture.block().unwrap().clone().into(); |
|
0 commit comments