Skip to content

Commit 4bd2d8a

Browse files
authored
simulators/portal: initialize clients during history tests with HistoricalSummaries (#1284)
1 parent bd98353 commit 4bd2d8a

File tree

6 files changed

+255
-81
lines changed

6 files changed

+255
-81
lines changed

simulators/portal/Cargo.lock

Lines changed: 10 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

simulators/portal/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@ alloy-rlp = "0.3.11"
1010
alloy-primitives = "1.1"
1111
anyhow = "1.0"
1212
chrono = "0.4"
13-
ethportal-api = { git = "https://github.com/ethereum/trin", rev = "743475f5ebac00c1359a7b61c45125b22efd841c" }
13+
ethereum_ssz = "0.9"
14+
ethportal-api = { git = "https://github.com/ethereum/trin", rev = "fd0b3c19c20c68059370a51d9b433ed34daa0591" }
1415
futures = "0.3.25"
1516
hivesim = { git = "https://github.com/ethereum/hive", rev = "4408fc1de3fee3ac23acd25a812c117756af2f39" }
1617
itertools = "0.14"
1718
lazy_static = "1.4.0"
1819
reqwest = { version = "0.12.7", features = ["json"] }
1920
serde_json = "1.0.95"
2021
serde_yaml = "0.9.33"
22+
snap = "1.1"
2123
ssz_types = "0.11"
2224
tokio = { version = "1.14.0", features = ["full"] }
2325
tracing = "0.1.37"

simulators/portal/src/suites/beacon/bridge/provider.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use alloy_primitives::B256;
22
use anyhow::{anyhow, Result};
33
use ethportal_api::{
44
light_client::{
5-
bootstrap::LightClientBootstrapDeneb, finality_update::LightClientFinalityUpdateDeneb,
6-
optimistic_update::LightClientOptimisticUpdateDeneb,
5+
bootstrap::LightClientBootstrapElectra, finality_update::LightClientFinalityUpdateElectra,
6+
optimistic_update::LightClientOptimisticUpdateElectra,
77
},
88
types::content_key::beacon::{
99
LightClientBootstrapKey, LightClientFinalityUpdateKey, LightClientOptimisticUpdateKey,
@@ -82,7 +82,7 @@ impl ConsensusProvider {
8282
let content_key = BeaconContentKey::LightClientBootstrap(LightClientBootstrapKey {
8383
block_hash: block_hash.into(),
8484
});
85-
let bootstrap: LightClientBootstrapDeneb = serde_json::from_value(data)?;
85+
let bootstrap: LightClientBootstrapElectra = serde_json::from_value(data)?;
8686
let content_value = BeaconContentValue::LightClientBootstrap(bootstrap.into());
8787

8888
Ok((content_key, content_value))
@@ -97,7 +97,7 @@ impl ConsensusProvider {
9797
self.base_url
9898
);
9999
let data = make_request(&self.client, &url).await?;
100-
let update: LightClientFinalityUpdateDeneb = serde_json::from_value(data)?;
100+
let update: LightClientFinalityUpdateElectra = serde_json::from_value(data)?;
101101
let new_finalized_slot = update.finalized_header.beacon.slot;
102102
let content_key = BeaconContentKey::LightClientFinalityUpdate(
103103
LightClientFinalityUpdateKey::new(new_finalized_slot),
@@ -116,7 +116,7 @@ impl ConsensusProvider {
116116
self.base_url
117117
);
118118
let data = make_request(&self.client, &url).await?;
119-
let update: LightClientOptimisticUpdateDeneb = serde_json::from_value(data)?;
119+
let update: LightClientOptimisticUpdateElectra = serde_json::from_value(data)?;
120120
let content_key = BeaconContentKey::LightClientOptimisticUpdate(
121121
LightClientOptimisticUpdateKey::new(update.signature_slot),
122122
);

simulators/portal/src/suites/history/constants.rs

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,111 @@
11
use alloy_primitives::Bytes;
2-
use anyhow::bail;
3-
use ethportal_api::{ContentValue, HistoryContentKey, HistoryContentValue};
2+
use anyhow::{anyhow, bail, ensure};
3+
use ethportal_api::{
4+
types::{
5+
content_key::beacon::HistoricalSummariesWithProofKey,
6+
content_value::beacon::ForkVersionedHistoricalSummariesWithProof,
7+
},
8+
BeaconContentKey, BeaconContentValue, ContentValue, HistoryContentKey, HistoryContentValue,
9+
};
410
use serde_yaml::Value;
5-
use std::str::FromStr;
11+
use ssz::Decode;
12+
use std::{
13+
fs::{self, File},
14+
io::Read,
15+
path::PathBuf,
16+
str::FromStr,
17+
sync::{Arc, LazyLock},
18+
};
619

720
// trin-bridge constants
821
pub const TRIN_BRIDGE_CLIENT_TYPE: &str = "trin-bridge";
922

10-
pub const TEST_DATA_FILE_PATH: &str = "./portal-spec-tests/tests/mainnet/history/hive/success";
23+
pub const BASE_TEST_PATH: &str = "./portal-spec-tests/tests/mainnet/history/hive";
24+
const HISTORICAL_SUMMARIES_FILE_PREFIX: &str = "fork_digest_historical_summaries_";
25+
const HISTORICAL_SUMMARIES_FILE_SUFFIX: &str = ".ssz_snappy";
1126

12-
pub fn get_test_data() -> anyhow::Result<Vec<(HistoryContentKey, HistoryContentValue)>> {
27+
/// The content key and value for the latest historical summaries
28+
///
29+
/// This is a static variable that is initialized once and can be reused
30+
pub static LATEST_HISTORICAL_SUMMARIES: LazyLock<Arc<(BeaconContentKey, BeaconContentValue)>> =
31+
LazyLock::new(|| {
32+
let (content_key, content_value) =
33+
get_latest_historical_summaries().expect("Failed to load latest historical summaries");
34+
Arc::new((content_key, content_value))
35+
});
36+
37+
/// Get the latest historical summaries
38+
///
39+
/// This should only be used in LATEST_HISTORICAL_SUMMARIES
40+
fn get_latest_historical_summaries() -> anyhow::Result<(BeaconContentKey, BeaconContentValue)> {
41+
let mut latest_epoch = 0;
42+
let mut latest_file: Option<PathBuf> = None;
43+
44+
for entry in fs::read_dir(BASE_TEST_PATH)? {
45+
let entry = entry?;
46+
if entry.path().is_dir() {
47+
continue;
48+
}
49+
let file_name = entry.file_name();
50+
let file_name_str = file_name.to_string_lossy();
51+
52+
if file_name_str.starts_with(HISTORICAL_SUMMARIES_FILE_PREFIX)
53+
&& file_name_str.ends_with(HISTORICAL_SUMMARIES_FILE_SUFFIX)
54+
{
55+
let epoch_str = &file_name_str[HISTORICAL_SUMMARIES_FILE_PREFIX.len()
56+
..file_name_str.len() - HISTORICAL_SUMMARIES_FILE_SUFFIX.len()];
57+
if let Ok(epoch) = epoch_str.parse::<u64>() {
58+
if epoch > latest_epoch {
59+
latest_epoch = epoch;
60+
latest_file = Some(entry.path());
61+
}
62+
} else {
63+
bail!("Unable to parse epoch from file name: {file_name_str}");
64+
}
65+
}
66+
}
67+
68+
let Some(path) = latest_file else {
69+
bail!("No historical summaries files found in the directory");
70+
};
71+
72+
let mut encoded = vec![];
73+
let historical_summaries = File::open(path)?.read_to_end(&mut encoded)?;
74+
ensure!(
75+
historical_summaries > 0,
76+
"Historical summaries file is empty",
77+
);
78+
79+
let mut decoder = snap::read::FrameDecoder::new(&*encoded);
80+
let mut decoded: Vec<u8> = vec![];
81+
decoder.read_to_end(&mut decoded)?;
82+
83+
let historical_summaries_with_proof =
84+
ForkVersionedHistoricalSummariesWithProof::from_ssz_bytes(&decoded).map_err(|err| {
85+
anyhow!("Failed to decoded ForkVersionedHistoricalSummariesWithProof {err:?}")
86+
})?;
87+
88+
let content_key =
89+
BeaconContentKey::HistoricalSummariesWithProof(HistoricalSummariesWithProofKey {
90+
epoch: historical_summaries_with_proof
91+
.historical_summaries_with_proof
92+
.epoch,
93+
});
94+
let content_value =
95+
BeaconContentValue::HistoricalSummariesWithProof(historical_summaries_with_proof);
96+
97+
Ok((content_key, content_value))
98+
}
99+
100+
pub fn get_success_test_data() -> anyhow::Result<Vec<(HistoryContentKey, HistoryContentValue)>> {
101+
get_test_data("success")
102+
}
103+
104+
fn get_test_data(test_case: &str) -> anyhow::Result<Vec<(HistoryContentKey, HistoryContentValue)>> {
13105
let mut content = vec![];
14106

15-
for entry in std::fs::read_dir(TEST_DATA_FILE_PATH)? {
107+
let success_test_path = format!("{BASE_TEST_PATH}/{test_case}");
108+
for entry in std::fs::read_dir(success_test_path)? {
16109
let entry = entry?;
17110
let test_path = entry.path();
18111
if !test_path.is_file() {

0 commit comments

Comments
 (0)