mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-06-30 10:59:33 +00:00
test(fixtures): parameterize Bedrock channel per zone, add two-zone harness test
This commit is contained in:
parent
62d9ba10f8
commit
26bc23482a
@ -57,9 +57,12 @@ pub fn setup_indexer_ffi(
|
||||
temp_indexer_dir.path().display()
|
||||
);
|
||||
|
||||
let indexer_config =
|
||||
integration_tests::config::indexer_config(bedrock_addr, temp_indexer_dir.path().to_owned())
|
||||
.context("Failed to create Indexer config")?;
|
||||
let indexer_config = integration_tests::config::indexer_config(
|
||||
bedrock_addr,
|
||||
temp_indexer_dir.path().to_owned(),
|
||||
integration_tests::config::bedrock_channel_id(),
|
||||
)
|
||||
.context("Failed to create Indexer config")?;
|
||||
|
||||
let config_json = serde_json::to_vec(&indexer_config)?;
|
||||
let config_path = temp_indexer_dir.path().join("indexer_config.json");
|
||||
|
||||
109
integration_tests/tests/two_zone.rs
Normal file
109
integration_tests/tests/two_zone.rs
Normal file
@ -0,0 +1,109 @@
|
||||
#![expect(
|
||||
clippy::tests_outside_test_module,
|
||||
clippy::arithmetic_side_effects,
|
||||
reason = "We don't care about these in tests"
|
||||
)]
|
||||
|
||||
//! Two zones (sequencer + indexer each, on separate channels) sharing one
|
||||
//! Bedrock node, each producing and finalizing blocks independently.
|
||||
|
||||
use std::{net::SocketAddr, time::Duration};
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use indexer_service_rpc::RpcClient as _;
|
||||
use integration_tests::{
|
||||
config::{self, SequencerPartialConfig},
|
||||
indexer_client::IndexerClient,
|
||||
setup::{setup_bedrock_node, setup_indexer, setup_sequencer},
|
||||
};
|
||||
use sequencer_service_rpc::{RpcClient as _, SequencerClientBuilder};
|
||||
use tokio::test;
|
||||
|
||||
const ZONE_LIVE_TIMEOUT: Duration = Duration::from_secs(360);
|
||||
|
||||
// Genesis is block 1, so reaching 2 means a block was produced past it.
|
||||
const MIN_BLOCK_ID: u64 = 2;
|
||||
|
||||
#[test]
|
||||
async fn two_zones_share_one_bedrock_and_both_advance() -> Result<()> {
|
||||
// Declared first so it outlives both zones (drops run in reverse order).
|
||||
let (_bedrock, bedrock_addr) = setup_bedrock_node()
|
||||
.await
|
||||
.context("Failed to set up shared Bedrock node")?;
|
||||
|
||||
let partial = SequencerPartialConfig::default();
|
||||
let channel_a = config::bedrock_channel_id();
|
||||
let channel_b = config::bedrock_channel_id_b();
|
||||
|
||||
// Empty genesis is enough: the clock transaction drives block production.
|
||||
let (seq_a, _seq_a_home) = setup_sequencer(partial, bedrock_addr, vec![], channel_a)
|
||||
.await
|
||||
.context("Failed to set up zone A sequencer")?;
|
||||
let (idx_a, _idx_a_home) = setup_indexer(bedrock_addr, channel_a)
|
||||
.await
|
||||
.context("Failed to set up zone A indexer")?;
|
||||
let (seq_b, _seq_b_home) = setup_sequencer(partial, bedrock_addr, vec![], channel_b)
|
||||
.await
|
||||
.context("Failed to set up zone B sequencer")?;
|
||||
let (idx_b, _idx_b_home) = setup_indexer(bedrock_addr, channel_b)
|
||||
.await
|
||||
.context("Failed to set up zone B indexer")?;
|
||||
|
||||
let (height_a, height_b) = tokio::try_join!(
|
||||
wait_until_zone_live("A", seq_a.addr(), idx_a.addr()),
|
||||
wait_until_zone_live("B", seq_b.addr(), idx_b.addr()),
|
||||
)?;
|
||||
|
||||
assert!(
|
||||
height_a >= MIN_BLOCK_ID,
|
||||
"Zone A indexer only reached block {height_a}, expected >= {MIN_BLOCK_ID}"
|
||||
);
|
||||
assert!(
|
||||
height_b >= MIN_BLOCK_ID,
|
||||
"Zone B indexer only reached block {height_b}, expected >= {MIN_BLOCK_ID}"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Wait for the sequencer to produce past genesis and the indexer to finalize up
|
||||
/// to it. Returns the indexer's finalized block id.
|
||||
async fn wait_until_zone_live(
|
||||
label: &str,
|
||||
sequencer_addr: SocketAddr,
|
||||
indexer_addr: SocketAddr,
|
||||
) -> Result<u64> {
|
||||
let sequencer_url = config::addr_to_url(config::UrlProtocol::Http, sequencer_addr)
|
||||
.context("Failed to build sequencer URL")?;
|
||||
let sequencer = SequencerClientBuilder::default()
|
||||
.build(sequencer_url)
|
||||
.context("Failed to build sequencer client")?;
|
||||
|
||||
let indexer_url = config::addr_to_url(config::UrlProtocol::Ws, indexer_addr)
|
||||
.context("Failed to build indexer URL")?;
|
||||
let indexer = IndexerClient::new(&indexer_url)
|
||||
.await
|
||||
.context("Failed to build indexer client")?;
|
||||
|
||||
let wait = async {
|
||||
loop {
|
||||
if sequencer.get_last_block_id().await? >= MIN_BLOCK_ID {
|
||||
break;
|
||||
}
|
||||
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
let target = sequencer.get_last_block_id().await?;
|
||||
loop {
|
||||
let finalized = indexer.get_last_finalized_block_id().await?.unwrap_or(0);
|
||||
if finalized >= target {
|
||||
log::info!("Zone {label} live: sequencer at {target}, indexer finalized {finalized}");
|
||||
return Ok::<u64, anyhow::Error>(finalized);
|
||||
}
|
||||
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||
}
|
||||
};
|
||||
|
||||
tokio::time::timeout(ZONE_LIVE_TIMEOUT, wait)
|
||||
.await
|
||||
.with_context(|| format!("Zone {label} did not become live within {ZONE_LIVE_TIMEOUT:?}"))?
|
||||
}
|
||||
@ -67,6 +67,7 @@ pub fn sequencer_config(
|
||||
home: PathBuf,
|
||||
bedrock_addr: SocketAddr,
|
||||
genesis_transactions: Vec<GenesisAction>,
|
||||
channel_id: ChannelId,
|
||||
) -> Result<SequencerConfig> {
|
||||
let SequencerPartialConfig {
|
||||
max_num_tx_in_block,
|
||||
@ -85,7 +86,7 @@ pub fn sequencer_config(
|
||||
genesis: genesis_transactions,
|
||||
signing_key: [37; 32],
|
||||
bedrock_config: BedrockConfig {
|
||||
channel_id: bedrock_channel_id(),
|
||||
channel_id,
|
||||
node_url: addr_to_url(UrlProtocol::Http, bedrock_addr)
|
||||
.context("Failed to convert bedrock addr to URL")?,
|
||||
auth: None,
|
||||
@ -163,7 +164,11 @@ pub fn wallet_config(sequencer_addr: SocketAddr) -> Result<WalletConfig> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn indexer_config(bedrock_addr: SocketAddr, home: PathBuf) -> Result<IndexerConfig> {
|
||||
pub fn indexer_config(
|
||||
bedrock_addr: SocketAddr,
|
||||
home: PathBuf,
|
||||
channel_id: ChannelId,
|
||||
) -> Result<IndexerConfig> {
|
||||
Ok(IndexerConfig {
|
||||
home,
|
||||
consensus_info_polling_interval: Duration::from_secs(1),
|
||||
@ -172,7 +177,7 @@ pub fn indexer_config(bedrock_addr: SocketAddr, home: PathBuf) -> Result<Indexer
|
||||
.context("Failed to convert bedrock addr to URL")?,
|
||||
auth: None,
|
||||
},
|
||||
channel_id: bedrock_channel_id(),
|
||||
channel_id,
|
||||
})
|
||||
}
|
||||
|
||||
@ -197,3 +202,15 @@ pub fn bedrock_channel_id() -> ChannelId {
|
||||
.unwrap_or_else(|_| unreachable!());
|
||||
ChannelId::from(channel_id)
|
||||
}
|
||||
|
||||
/// Second channel on the same Bedrock node, for two-zone tests.
|
||||
/// Distinct from [`bedrock_channel_id`] so two zones settle independently on
|
||||
/// one shared L1.
|
||||
#[must_use]
|
||||
pub fn bedrock_channel_id_b() -> ChannelId {
|
||||
let channel_id: [u8; 32] = [0_u8, 2]
|
||||
.repeat(16)
|
||||
.try_into()
|
||||
.unwrap_or_else(|_| unreachable!());
|
||||
ChannelId::from(channel_id)
|
||||
}
|
||||
|
||||
@ -307,9 +307,10 @@ impl TestContextBuilder {
|
||||
.context("Failed to setup Bedrock node")?;
|
||||
|
||||
let indexer_components = if enable_indexer {
|
||||
let (indexer_handle, temp_indexer_dir) = setup_indexer(bedrock_addr)
|
||||
.await
|
||||
.context("Failed to setup Indexer")?;
|
||||
let (indexer_handle, temp_indexer_dir) =
|
||||
setup_indexer(bedrock_addr, config::bedrock_channel_id())
|
||||
.await
|
||||
.context("Failed to setup Indexer")?;
|
||||
let indexer_url = config::addr_to_url(config::UrlProtocol::Ws, indexer_handle.addr())
|
||||
.context("Failed to convert indexer addr to URL")?;
|
||||
let indexer_client = IndexerClient::new(&indexer_url)
|
||||
@ -342,6 +343,7 @@ impl TestContextBuilder {
|
||||
sequencer_partial_config.unwrap_or_default(),
|
||||
bedrock_addr,
|
||||
genesis,
|
||||
config::bedrock_channel_id(),
|
||||
)
|
||||
.await
|
||||
.context("Failed to setup Sequencer")?;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::{net::SocketAddr, path::PathBuf};
|
||||
|
||||
use anyhow::{Context as _, Result, bail};
|
||||
use indexer_service::IndexerHandle;
|
||||
use indexer_service::{ChannelId, IndexerHandle};
|
||||
use lee::{AccountId, PrivateKey, PublicKey};
|
||||
use log::{debug, warn};
|
||||
use sequencer_service::{GenesisAction, SequencerHandle};
|
||||
@ -89,7 +89,10 @@ pub async fn setup_bedrock_node() -> Result<(DockerCompose, SocketAddr)> {
|
||||
Ok((compose, addr))
|
||||
}
|
||||
|
||||
pub async fn setup_indexer(bedrock_addr: SocketAddr) -> Result<(IndexerHandle, TempDir)> {
|
||||
pub async fn setup_indexer(
|
||||
bedrock_addr: SocketAddr,
|
||||
channel_id: ChannelId,
|
||||
) -> Result<(IndexerHandle, TempDir)> {
|
||||
let temp_indexer_dir =
|
||||
tempfile::tempdir().context("Failed to create temp dir for indexer home")?;
|
||||
|
||||
@ -98,8 +101,9 @@ pub async fn setup_indexer(bedrock_addr: SocketAddr) -> Result<(IndexerHandle, T
|
||||
temp_indexer_dir.path().display()
|
||||
);
|
||||
|
||||
let indexer_config = config::indexer_config(bedrock_addr, temp_indexer_dir.path().to_owned())
|
||||
.context("Failed to create Indexer config")?;
|
||||
let indexer_config =
|
||||
config::indexer_config(bedrock_addr, temp_indexer_dir.path().to_owned(), channel_id)
|
||||
.context("Failed to create Indexer config")?;
|
||||
|
||||
indexer_service::run_server(indexer_config, 0)
|
||||
.await
|
||||
@ -111,6 +115,7 @@ pub async fn setup_sequencer(
|
||||
partial: config::SequencerPartialConfig,
|
||||
bedrock_addr: SocketAddr,
|
||||
genesis_transactions: Vec<GenesisAction>,
|
||||
channel_id: ChannelId,
|
||||
) -> Result<(SequencerHandle, TempDir)> {
|
||||
let temp_sequencer_dir =
|
||||
tempfile::tempdir().context("Failed to create temp dir for sequencer home")?;
|
||||
@ -125,6 +130,7 @@ pub async fn setup_sequencer(
|
||||
temp_sequencer_dir.path().to_owned(),
|
||||
bedrock_addr,
|
||||
genesis_transactions,
|
||||
channel_id,
|
||||
)
|
||||
.context("Failed to create Sequencer config")?;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user