Skip to content

Commit

Permalink
chore: rewrite trin-bridge simulator increasing test accuracy + test …
Browse files Browse the repository at this point in the history
…automation (#115)
  • Loading branch information
KolbyML authored Nov 29, 2023
1 parent 5e8b988 commit a29ef7f
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 39 deletions.
19 changes: 19 additions & 0 deletions clients/trin-bridge/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM portalnetwork/trin:latest-bridge

ADD test_data_collection_of_forks_blocks.yaml /test_data_collection_of_forks_blocks.yaml
ADD trin_bridge.sh /trin_bridge.sh
RUN chmod +x /trin_bridge.sh

ADD trin_bridge_version.sh /trin_bridge_version.sh
RUN chmod +x /trin_bridge_version.sh

RUN /trin_bridge_version.sh > /version.txt

# Export the usual networking ports to allow outside access to the node
EXPOSE 8545 9009/udp

# add fake secrets for bridge activation
ENV PANDAOPS_CLIENT_ID=xxx
ENV PANDAOPS_CLIENT_SECRET=xxx

ENTRYPOINT ["/trin_bridge.sh"]
38 changes: 38 additions & 0 deletions clients/trin-bridge/test_data_collection_of_forks_blocks.yaml

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions clients/trin-bridge/trin_bridge.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

# Immediately abort the script on any error encountered
set -e

IP_ADDR=$(hostname -i | awk '{print $1}')
FLAGS=""

if [ "$HIVE_BOOTNODES" != "" ]; then
FLAGS="$FLAGS --bootnodes=$HIVE_BOOTNODES"
else
echo "Warning: HIVE_BOOTNODES wasn't provided"
exit 1
fi

RUST_LOG=debug portal-bridge --node-count 1 $FLAGS --executable-path ./usr/bin/trin --mode test:/test_data_collection_of_forks_blocks.yaml --external-ip $IP_ADDR --epoch-accumulator-path . trin
7 changes: 7 additions & 0 deletions clients/trin-bridge/trin_bridge_version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

# Immediately abort the script on any error encountered
set -e

#trin --version | tail -1 | sed "s/ /\//g"
echo "latest"
2 changes: 0 additions & 2 deletions simulators/trin-bridge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ edition = "2021"

[dependencies]
ethportal-api = { git = "https://github.com/ethereum/trin", rev = "b530dc3d40d51c21c800089eacb2852ebd8c4d45" }
portal-bridge = { git = "https://github.com/ethereum/trin", rev = "b530dc3d40d51c21c800089eacb2852ebd8c4d45" }
trin-validation = { git = "https://github.com/ethereum/trin", rev = "b530dc3d40d51c21c800089eacb2852ebd8c4d45" }
hivesim = { path = "../../hivesim-rs" }
itertools = "0.10.5"
serde_yaml = "0.9"
Expand Down
14 changes: 14 additions & 0 deletions simulators/trin-bridge/src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Execution Layer hard forks https://ethereum.org/en/history/
pub const SHANGHAI_BLOCK_NUMBER: u64 = 17034870;
pub const MERGE_BLOCK_NUMBER: u64 = 15537394;
pub const LONDON_BLOCK_NUMBER: u64 = 12965000;
pub const BERLIN_BLOCK_NUMBER: u64 = 12244000;
pub const ISTANBUL_BLOCK_NUMBER: u64 = 9069000;
pub const CONSTANTINOPLE_BLOCK_NUMBER: u64 = 7280000;
pub const BYZANTIUM_BLOCK_NUMBER: u64 = 4370000;
pub const HOMESTEAD_BLOCK_NUMBER: u64 = 1150000;

pub const TRIN_BRIDGE_CLIENT_TYPE: &str = "trin-bridge";
pub const BOOTNODES_ENVIRONMENT_VARIABLE: &str = "HIVE_BOOTNODES";
pub const HIVE_CHECK_LIVE_PORT: &str = "HIVE_CHECK_LIVE_PORT";
pub const TEST_DATA_FILE_PATH: &str = "./test-data/test_data_collection_of_forks_blocks.yaml";
122 changes: 85 additions & 37 deletions simulators/trin-bridge/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,73 @@
mod constants;

use crate::constants::{
BERLIN_BLOCK_NUMBER, BOOTNODES_ENVIRONMENT_VARIABLE, BYZANTIUM_BLOCK_NUMBER,
CONSTANTINOPLE_BLOCK_NUMBER, HIVE_CHECK_LIVE_PORT, HOMESTEAD_BLOCK_NUMBER,
ISTANBUL_BLOCK_NUMBER, LONDON_BLOCK_NUMBER, MERGE_BLOCK_NUMBER, SHANGHAI_BLOCK_NUMBER,
TEST_DATA_FILE_PATH, TRIN_BRIDGE_CLIENT_TYPE,
};
use ethportal_api::HistoryContentKey;
use ethportal_api::HistoryContentValue;
use ethportal_api::PossibleHistoryContentValue;
use ethportal_api::{Discv5ApiClient, HistoryNetworkApiClient};
use hivesim::types::ClientDefinition;
use hivesim::{dyn_async, Client, Simulation, Suite, Test, TestSpec, TwoClientTestSpec};
use itertools::Itertools;
use portal_bridge::bridge::Bridge;
use portal_bridge::execution_api::ExecutionApi;
use portal_bridge::mode::BridgeMode;
use portal_bridge::pandaops::PandaOpsMiddleware;
use serde_yaml::Value;
use std::collections::HashMap;
use tokio::time::Duration;
use trin_validation::accumulator::MasterAccumulator;
use trin_validation::oracle::HeaderOracle;

fn get_flair(block_number: u64) -> String {
if block_number > SHANGHAI_BLOCK_NUMBER {
" (post-shanghai)".to_string()
} else if block_number > MERGE_BLOCK_NUMBER {
" (post-merge)".to_string()
} else if block_number > LONDON_BLOCK_NUMBER {
" (post-london)".to_string()
} else if block_number > BERLIN_BLOCK_NUMBER {
" (post-berlin)".to_string()
} else if block_number > ISTANBUL_BLOCK_NUMBER {
" (post-istanbul)".to_string()
} else if block_number > CONSTANTINOPLE_BLOCK_NUMBER {
" (post-constantinople)".to_string()
} else if block_number > BYZANTIUM_BLOCK_NUMBER {
" (post-byzantium)".to_string()
} else if block_number > HOMESTEAD_BLOCK_NUMBER {
" (post-homestead)".to_string()
} else {
"".to_string()
}
}

fn process_content(content: Vec<(HistoryContentKey, HistoryContentValue)>) -> Vec<String> {
let mut last_header = content.get(0).unwrap().clone();

let mut result: Vec<String> = vec![];
for history_content in content.into_iter() {
if let HistoryContentKey::BlockHeaderWithProof(_) = &history_content.0 {
last_header = history_content.clone();
}
let comment =
if let HistoryContentValue::BlockHeaderWithProof(header_with_proof) = &last_header.1 {
let content_type = match &history_content.0 {
HistoryContentKey::BlockHeaderWithProof(_) => "header".to_string(),
HistoryContentKey::BlockBody(_) => "body".to_string(),
HistoryContentKey::BlockReceipts(_) => "receipt".to_string(),
HistoryContentKey::EpochAccumulator(_) => "epoch accumulator".to_string(),
};
format!(
"{}{} {}",
header_with_proof.header.number,
get_flair(header_with_proof.header.number),
content_type
)
} else {
unreachable!("History test dated is formatted incorrectly")
};
result.push(comment)
}
result
}

#[tokio::main]
async fn main() {
Expand Down Expand Up @@ -52,6 +108,10 @@ dyn_async! {
async fn test_portal_bridge<'a> (test: &'a mut Test, _client: Option<Client>) {
// Get all available portal clients
let clients = test.sim.client_types().await;
if !clients.iter().any(|client_definition| client_definition.name == *TRIN_BRIDGE_CLIENT_TYPE) {
panic!("This simulator is required to be ran with client `trin-portal`")
}
let clients: Vec<ClientDefinition> = clients.into_iter().filter(|client| client.name != *TRIN_BRIDGE_CLIENT_TYPE).collect();

// Iterate over all possible pairings of clients and run the tests (including self-pairings)
for (client_a, client_b) in clients.iter().cartesian_product(clients.iter()) {
Expand All @@ -71,15 +131,6 @@ dyn_async! {

dyn_async! {
async fn test_bridge<'a> (client_a: Client, client_b: Client) {
let master_acc = MasterAccumulator::default();
let header_oracle = HeaderOracle::new(master_acc);
let portal_clients = vec![client_a.rpc.clone()];
let epoch_acc_path = "validation_assets/epoch_acc.bin".into();
let mode = BridgeMode::Test("./test-data/test_data_collection_of_forks_blocks.yaml".into());
let pandaops_middleware = PandaOpsMiddleware::default();
let execution_api = ExecutionApi::new(pandaops_middleware);

// connect clients
let client_b_enr = match client_b.rpc.node_info().await {
Ok(node_info) => node_info.enr,
Err(err) => {
Expand All @@ -93,37 +144,34 @@ dyn_async! {
Err(err) => panic!("{}", &err.to_string()),
}

// start the bridge
let bridge = Bridge::new(
mode,
execution_api,
portal_clients,
header_oracle,
epoch_acc_path,
);
bridge.launch().await;

// wait 2 seconds for data to propagate
// This value is determined by how long the sleeps are in the bridge code
// So we may lower this or remove it depending on what we find.
tokio::time::sleep(Duration::from_secs(2)).await;
let client_a_enr = match client_a.rpc.node_info().await {
Ok(node_info) => node_info.enr,
Err(err) => {
panic!("Error getting node info: {err:?}");
}
};
client_a.test.start_client(TRIN_BRIDGE_CLIENT_TYPE.to_string(), Some(HashMap::from([(BOOTNODES_ENVIRONMENT_VARIABLE.to_string(), client_a_enr.to_base64()), (HIVE_CHECK_LIVE_PORT.to_string(), 0.to_string())]))).await;



// With default node settings nodes should be storing all content
let values = std::fs::read_to_string("./test-data/test_data_collection_of_forks_blocks.yaml")
let values = std::fs::read_to_string(TEST_DATA_FILE_PATH)
.expect("cannot find test asset");
let values: Value = serde_yaml::from_str(&values).unwrap();
let comments = vec!["1 header", "1 block body", "100 header",
"100 block body", "7000000 header", "7000000 block body",
"7000000 receipt", "15600000 (post-merge) header", "15600000 (post-merge) block body", "15600000 (post-merge) receipt",
"17510000 (post-shanghai) header", "17510000 (post-shanghai) block body", "17510000 (post-shanghai) receipt"];

let mut result = vec![];
for (index, value) in values.as_sequence().unwrap().iter().enumerate() {
let content_vec: Vec<(HistoryContentKey, HistoryContentValue)> = values.as_sequence().unwrap().iter().map(|value| {
let content_key: HistoryContentKey =
serde_yaml::from_value(value.get("content_key").unwrap().clone()).unwrap();
let content_value: HistoryContentValue =
serde_yaml::from_value(value.get("content_value").unwrap().clone()).unwrap();
(content_key, content_value)
}).collect();
let comments = process_content(content_vec.clone());

// wait content_vec.len() seconds for data to propagate, giving more time if more items are propagating
tokio::time::sleep(Duration::from_secs(content_vec.len() as u64)).await;

let mut result = vec![];
for (index, (content_key, content_value)) in content_vec.into_iter().enumerate() {
match client_b.rpc.local_content(content_key.clone()).await {
Ok(possible_content) => {
match possible_content {
Expand Down

0 comments on commit a29ef7f

Please sign in to comment.