2026-02-24 20:52:14 +03:00
|
|
|
use std::{net::SocketAddr, path::PathBuf, time::Duration};
|
2026-02-02 19:07:24 +03:00
|
|
|
|
2026-03-04 18:42:33 +03:00
|
|
|
use anyhow::{Context as _, Result};
|
2026-02-24 19:41:01 +03:00
|
|
|
use bytesize::ByteSize;
|
2026-04-29 10:33:07 +02:00
|
|
|
use indexer_service::{ChannelId, ClientConfig, IndexerConfig};
|
2026-04-10 20:23:25 +03:00
|
|
|
use nssa::{AccountId, PrivateKey, PublicKey};
|
|
|
|
|
use sequencer_core::config::{BedrockConfig, GenesisTransaction, SequencerConfig};
|
2026-02-02 19:07:24 +03:00
|
|
|
use url::Url;
|
2026-04-10 20:23:25 +03:00
|
|
|
use wallet::config::WalletConfig;
|
|
|
|
|
|
|
|
|
|
pub const INITIAL_PUBLIC_BALANCES_FOR_WALLET: [u128; 2] = [20_000, 40_000];
|
|
|
|
|
pub const INITIAL_PRIVATE_BALANCES_FOR_WALLET: [u128; 2] = [10_000, 20_000];
|
2026-02-02 19:07:24 +03:00
|
|
|
|
2026-01-29 22:20:42 +03:00
|
|
|
/// Sequencer config options available for custom changes in integration tests.
|
2026-03-03 23:21:08 +03:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
2026-01-29 22:20:42 +03:00
|
|
|
pub struct SequencerPartialConfig {
|
|
|
|
|
pub max_num_tx_in_block: usize,
|
2026-02-24 19:41:01 +03:00
|
|
|
pub max_block_size: ByteSize,
|
2026-01-29 22:20:42 +03:00
|
|
|
pub mempool_max_size: usize,
|
2026-02-24 20:52:14 +03:00
|
|
|
pub block_create_timeout: Duration,
|
2026-01-29 22:20:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for SequencerPartialConfig {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
max_num_tx_in_block: 20,
|
2026-02-24 19:41:01 +03:00
|
|
|
max_block_size: ByteSize::mib(1),
|
2026-01-29 22:20:42 +03:00
|
|
|
mempool_max_size: 10_000,
|
2026-02-24 20:52:14 +03:00
|
|
|
block_create_timeout: Duration::from_secs(10),
|
2026-01-29 22:20:42 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-03 23:21:08 +03:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
2026-01-29 22:20:42 +03:00
|
|
|
pub enum UrlProtocol {
|
|
|
|
|
Http,
|
|
|
|
|
Ws,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for UrlProtocol {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
match self {
|
2026-03-09 18:27:56 +03:00
|
|
|
Self::Http => write!(f, "http"),
|
|
|
|
|
Self::Ws => write!(f, "ws"),
|
2026-01-29 22:20:42 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-18 16:57:13 +01:00
|
|
|
pub fn sequencer_config(
|
|
|
|
|
partial: SequencerPartialConfig,
|
|
|
|
|
home: PathBuf,
|
|
|
|
|
bedrock_addr: SocketAddr,
|
2026-04-10 20:23:25 +03:00
|
|
|
genesis_transactions: Vec<GenesisTransaction>,
|
2026-03-18 16:57:13 +01:00
|
|
|
) -> Result<SequencerConfig> {
|
|
|
|
|
let SequencerPartialConfig {
|
|
|
|
|
max_num_tx_in_block,
|
|
|
|
|
max_block_size,
|
|
|
|
|
mempool_max_size,
|
|
|
|
|
block_create_timeout,
|
|
|
|
|
} = partial;
|
|
|
|
|
|
|
|
|
|
Ok(SequencerConfig {
|
|
|
|
|
home,
|
|
|
|
|
is_genesis_random: true,
|
|
|
|
|
max_num_tx_in_block,
|
|
|
|
|
max_block_size,
|
|
|
|
|
mempool_max_size,
|
|
|
|
|
block_create_timeout,
|
2026-04-09 14:35:51 +02:00
|
|
|
retry_pending_blocks_timeout: Duration::from_secs(5),
|
2026-04-10 20:23:25 +03:00
|
|
|
genesis: genesis_transactions,
|
2026-03-18 16:57:13 +01:00
|
|
|
signing_key: [37; 32],
|
|
|
|
|
bedrock_config: BedrockConfig {
|
|
|
|
|
channel_id: bedrock_channel_id(),
|
|
|
|
|
node_url: addr_to_url(UrlProtocol::Http, bedrock_addr)
|
|
|
|
|
.context("Failed to convert bedrock addr to URL")?,
|
|
|
|
|
auth: None,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-10 20:23:25 +03:00
|
|
|
#[must_use]
|
|
|
|
|
pub fn default_public_accounts_for_wallet() -> Vec<(PrivateKey, u128)> {
|
|
|
|
|
let mut first_private_key = PrivateKey::new_os_random();
|
|
|
|
|
let first_public_key = PublicKey::new_from_private_key(&first_private_key);
|
|
|
|
|
let mut first_account_id = AccountId::from(&first_public_key);
|
|
|
|
|
|
|
|
|
|
let mut second_private_key = PrivateKey::new_os_random();
|
|
|
|
|
let second_public_key = PublicKey::new_from_private_key(&second_private_key);
|
|
|
|
|
let mut second_account_id = AccountId::from(&second_public_key);
|
|
|
|
|
|
|
|
|
|
// Keep account ordering deterministic for tests that index into account lists.
|
|
|
|
|
if first_account_id > second_account_id {
|
|
|
|
|
std::mem::swap(&mut first_private_key, &mut second_private_key);
|
|
|
|
|
std::mem::swap(&mut first_account_id, &mut second_account_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
(first_private_key, INITIAL_PUBLIC_BALANCES_FOR_WALLET[0]),
|
|
|
|
|
(second_private_key, INITIAL_PUBLIC_BALANCES_FOR_WALLET[1]),
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[must_use]
|
|
|
|
|
pub fn genesis_from_public_accounts(
|
|
|
|
|
public_accounts: &[(PrivateKey, u128)],
|
|
|
|
|
) -> Vec<GenesisTransaction> {
|
|
|
|
|
public_accounts
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|(private_key, balance)| {
|
|
|
|
|
let public_key = PublicKey::new_from_private_key(private_key);
|
|
|
|
|
let account_id = AccountId::from(&public_key);
|
|
|
|
|
GenesisTransaction::SupplyPublicAccount {
|
|
|
|
|
account_id,
|
|
|
|
|
balance: *balance,
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn wallet_config(sequencer_addr: SocketAddr) -> Result<WalletConfig> {
|
2026-03-18 16:57:13 +01:00
|
|
|
Ok(WalletConfig {
|
|
|
|
|
sequencer_addr: addr_to_url(UrlProtocol::Http, sequencer_addr)
|
|
|
|
|
.context("Failed to convert sequencer addr to URL")?,
|
|
|
|
|
seq_poll_timeout: Duration::from_secs(30),
|
|
|
|
|
seq_tx_poll_max_blocks: 15,
|
|
|
|
|
seq_poll_max_retries: 10,
|
|
|
|
|
seq_block_poll_max_amount: 100,
|
|
|
|
|
basic_auth: None,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-10 20:23:25 +03:00
|
|
|
pub fn indexer_config(bedrock_addr: SocketAddr, home: PathBuf) -> Result<IndexerConfig> {
|
2026-03-04 18:42:33 +03:00
|
|
|
Ok(IndexerConfig {
|
|
|
|
|
home,
|
|
|
|
|
consensus_info_polling_interval: Duration::from_secs(1),
|
2026-04-29 14:05:23 +02:00
|
|
|
bedrock_config: ClientConfig {
|
2026-03-04 18:42:33 +03:00
|
|
|
addr: addr_to_url(UrlProtocol::Http, bedrock_addr)
|
|
|
|
|
.context("Failed to convert bedrock addr to URL")?,
|
|
|
|
|
auth: None,
|
|
|
|
|
},
|
|
|
|
|
channel_id: bedrock_channel_id(),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-29 22:20:42 +03:00
|
|
|
pub fn addr_to_url(protocol: UrlProtocol, addr: SocketAddr) -> Result<Url> {
|
2026-02-02 19:07:24 +03:00
|
|
|
// Convert 0.0.0.0 to 127.0.0.1 for client connections
|
|
|
|
|
// When binding to port 0, the server binds to 0.0.0.0:<random_port>
|
|
|
|
|
// but clients need to connect to 127.0.0.1:<port> to work reliably
|
|
|
|
|
let url_string = if addr.ip().is_unspecified() {
|
2026-01-29 22:20:42 +03:00
|
|
|
format!("{protocol}://127.0.0.1:{}", addr.port())
|
2026-02-02 19:07:24 +03:00
|
|
|
} else {
|
2026-01-29 22:20:42 +03:00
|
|
|
format!("{protocol}://{addr}")
|
2026-02-02 19:07:24 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
url_string.parse().map_err(Into::into)
|
|
|
|
|
}
|
2026-01-29 22:20:42 +03:00
|
|
|
|
|
|
|
|
fn bedrock_channel_id() -> ChannelId {
|
2026-03-04 18:42:33 +03:00
|
|
|
let channel_id: [u8; 32] = [0_u8, 1]
|
2026-01-29 22:20:42 +03:00
|
|
|
.repeat(16)
|
|
|
|
|
.try_into()
|
|
|
|
|
.unwrap_or_else(|_| unreachable!());
|
|
|
|
|
ChannelId::from(channel_id)
|
|
|
|
|
}
|