mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-03-26 04:03:06 +00:00
feat: use human-readable byte sizes and durations
This commit is contained in:
parent
8b5524901c
commit
437e5addb4
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -1210,6 +1210,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"common",
|
"common",
|
||||||
"futures",
|
"futures",
|
||||||
|
"humantime-serde",
|
||||||
"log",
|
"log",
|
||||||
"logos-blockchain-chain-broadcast-service",
|
"logos-blockchain-chain-broadcast-service",
|
||||||
"logos-blockchain-chain-service",
|
"logos-blockchain-chain-service",
|
||||||
@ -3440,6 +3441,16 @@ version = "2.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
|
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime-serde"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c"
|
||||||
|
dependencies = [
|
||||||
|
"humantime",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hydration_context"
|
name = "hydration_context"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -3735,6 +3746,7 @@ dependencies = [
|
|||||||
"borsh",
|
"borsh",
|
||||||
"common",
|
"common",
|
||||||
"futures",
|
"futures",
|
||||||
|
"humantime-serde",
|
||||||
"log",
|
"log",
|
||||||
"logos-blockchain-core",
|
"logos-blockchain-core",
|
||||||
"nssa",
|
"nssa",
|
||||||
@ -5573,6 +5585,7 @@ dependencies = [
|
|||||||
"base58",
|
"base58",
|
||||||
"borsh",
|
"borsh",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
|
"bytesize",
|
||||||
"chacha20",
|
"chacha20",
|
||||||
"k256",
|
"k256",
|
||||||
"risc0-zkvm",
|
"risc0-zkvm",
|
||||||
@ -7445,6 +7458,7 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"common",
|
"common",
|
||||||
"futures",
|
"futures",
|
||||||
|
"humantime-serde",
|
||||||
"jsonrpsee",
|
"jsonrpsee",
|
||||||
"log",
|
"log",
|
||||||
"logos-blockchain-core",
|
"logos-blockchain-core",
|
||||||
@ -8981,6 +8995,8 @@ dependencies = [
|
|||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
"hex",
|
"hex",
|
||||||
|
"humantime",
|
||||||
|
"humantime-serde",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"key_protocol",
|
"key_protocol",
|
||||||
|
|||||||
@ -88,6 +88,8 @@ sha2 = "0.10.8"
|
|||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
bytemuck = "1.24.0"
|
bytemuck = "1.24.0"
|
||||||
bytesize = { version = "2.3.1", features = ["serde"] }
|
bytesize = { version = "2.3.1", features = ["serde"] }
|
||||||
|
humantime-serde = "1.1"
|
||||||
|
humantime = "2.1"
|
||||||
aes-gcm = "0.10.3"
|
aes-gcm = "0.10.3"
|
||||||
toml = "0.7.4"
|
toml = "0.7.4"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
|
|||||||
@ -13,6 +13,7 @@ tokio-retry.workspace = true
|
|||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
humantime-serde.workspace = true
|
||||||
logos-blockchain-common-http-client.workspace = true
|
logos-blockchain-common-http-client.workspace = true
|
||||||
logos-blockchain-core.workspace = true
|
logos-blockchain-core.workspace = true
|
||||||
logos-blockchain-chain-broadcast-service.workspace = true
|
logos-blockchain-chain-broadcast-service.workspace = true
|
||||||
|
|||||||
@ -3,6 +3,8 @@ use std::time::Duration;
|
|||||||
use anyhow::{Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
use common::config::BasicAuth;
|
use common::config::BasicAuth;
|
||||||
use futures::{Stream, TryFutureExt};
|
use futures::{Stream, TryFutureExt};
|
||||||
|
#[expect(clippy::single_component_path_imports, reason = "Satisfy machete")]
|
||||||
|
use humantime_serde;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
pub use logos_blockchain_chain_broadcast_service::BlockInfo;
|
pub use logos_blockchain_chain_broadcast_service::BlockInfo;
|
||||||
use logos_blockchain_chain_service::CryptarchiaInfo;
|
use logos_blockchain_chain_service::CryptarchiaInfo;
|
||||||
@ -15,14 +17,15 @@ use tokio_retry::Retry;
|
|||||||
/// Fibonacci backoff retry strategy configuration
|
/// Fibonacci backoff retry strategy configuration
|
||||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub struct BackoffConfig {
|
pub struct BackoffConfig {
|
||||||
pub start_delay_millis: u64,
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub start_delay: Duration,
|
||||||
pub max_retries: usize,
|
pub max_retries: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BackoffConfig {
|
impl Default for BackoffConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
start_delay_millis: 100,
|
start_delay: Duration::from_millis(100),
|
||||||
max_retries: 5,
|
max_retries: 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +96,9 @@ impl BedrockClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn backoff_strategy(&self) -> impl Iterator<Item = Duration> {
|
fn backoff_strategy(&self) -> impl Iterator<Item = Duration> {
|
||||||
tokio_retry::strategy::FibonacciBackoff::from_millis(self.backoff.start_delay_millis)
|
tokio_retry::strategy::FibonacciBackoff::from_millis(
|
||||||
.take(self.backoff.max_retries)
|
self.backoff.start_delay.as_millis() as u64
|
||||||
|
)
|
||||||
|
.take(self.backoff.max_retries)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use bytesize::ByteSize;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
@ -8,13 +9,13 @@ pub mod requests;
|
|||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct RpcLimitsConfig {
|
pub struct RpcLimitsConfig {
|
||||||
/// Maximum byte size of the json payload.
|
/// Maximum byte size of the json payload.
|
||||||
pub json_payload_max_size: usize,
|
pub json_payload_max_size: ByteSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RpcLimitsConfig {
|
impl Default for RpcLimitsConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
json_payload_max_size: 10 * 1024 * 1024,
|
json_payload_max_size: ByteSize::mib(10),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -103,4 +103,6 @@ pub enum TransactionMalformationError {
|
|||||||
InvalidSignature,
|
InvalidSignature,
|
||||||
#[error("Failed to decode transaction with hash: {tx:?}")]
|
#[error("Failed to decode transaction with hash: {tx:?}")]
|
||||||
FailedToDecode { tx: HashType },
|
FailedToDecode { tx: HashType },
|
||||||
|
#[error("Transaction size {size} exceeds maximum allowed size of {max} bytes")]
|
||||||
|
TransactionTooLarge { size: usize, max: usize },
|
||||||
}
|
}
|
||||||
|
|||||||
@ -346,7 +346,7 @@ _wallet_config() {
|
|||||||
'all'
|
'all'
|
||||||
'override_rust_log'
|
'override_rust_log'
|
||||||
'sequencer_addr'
|
'sequencer_addr'
|
||||||
'seq_poll_timeout_millis'
|
'seq_poll_timeout'
|
||||||
'seq_tx_poll_max_blocks'
|
'seq_tx_poll_max_blocks'
|
||||||
'seq_poll_max_retries'
|
'seq_poll_max_retries'
|
||||||
'seq_block_poll_max_amount'
|
'seq_block_poll_max_amount'
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"resubscribe_interval_millis": 1000,
|
"resubscribe_interval": "1s",
|
||||||
"bedrock_client_config": {
|
"bedrock_client_config": {
|
||||||
"addr": "http://logos-blockchain-node-0:18080",
|
"addr": "http://logos-blockchain-node-0:18080",
|
||||||
"backoff": {
|
"backoff": {
|
||||||
"start_delay_millis": 100,
|
"start_delay": "100ms",
|
||||||
"max_retries": 5
|
"max_retries": 5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,12 +6,12 @@
|
|||||||
"max_num_tx_in_block": 20,
|
"max_num_tx_in_block": 20,
|
||||||
"max_block_size": "1 MiB",
|
"max_block_size": "1 MiB",
|
||||||
"mempool_max_size": 10000,
|
"mempool_max_size": 10000,
|
||||||
"block_create_timeout_millis": 10000,
|
"block_create_timeout": "10s",
|
||||||
"retry_pending_blocks_timeout_millis": 7000,
|
"retry_pending_blocks_timeout": "7s",
|
||||||
"port": 3040,
|
"port": 3040,
|
||||||
"bedrock_config": {
|
"bedrock_config": {
|
||||||
"backoff": {
|
"backoff": {
|
||||||
"start_delay_millis": 100,
|
"start_delay": "100ms",
|
||||||
"max_retries": 5
|
"max_retries": 5
|
||||||
},
|
},
|
||||||
"channel_id": "0101010101010101010101010101010101010101010101010101010101010101",
|
"channel_id": "0101010101010101010101010101010101010101010101010101010101010101",
|
||||||
|
|||||||
@ -14,6 +14,7 @@ storage.workspace = true
|
|||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
humantime-serde.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
borsh.workspace = true
|
borsh.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
|
|||||||
@ -2,6 +2,7 @@ use std::{
|
|||||||
fs::File,
|
fs::File,
|
||||||
io::BufReader,
|
io::BufReader,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
@ -10,6 +11,7 @@ use common::{
|
|||||||
block::{AccountInitialData, CommitmentsInitialData},
|
block::{AccountInitialData, CommitmentsInitialData},
|
||||||
config::BasicAuth,
|
config::BasicAuth,
|
||||||
};
|
};
|
||||||
|
use humantime_serde;
|
||||||
pub use logos_blockchain_core::mantle::ops::channel::ChannelId;
|
pub use logos_blockchain_core::mantle::ops::channel::ChannelId;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@ -33,7 +35,8 @@ pub struct IndexerConfig {
|
|||||||
pub initial_commitments: Vec<CommitmentsInitialData>,
|
pub initial_commitments: Vec<CommitmentsInitialData>,
|
||||||
/// Sequencers signing key
|
/// Sequencers signing key
|
||||||
pub signing_key: [u8; 32],
|
pub signing_key: [u8; 32],
|
||||||
pub consensus_info_polling_interval_millis: u64,
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub consensus_info_polling_interval: Duration,
|
||||||
pub bedrock_client_config: ClientConfig,
|
pub bedrock_client_config: ClientConfig,
|
||||||
pub channel_id: ChannelId,
|
pub channel_id: ChannelId,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -174,13 +174,10 @@ impl IndexerCore {
|
|||||||
break Ok(next_lib);
|
break Ok(next_lib);
|
||||||
} else {
|
} else {
|
||||||
info!(
|
info!(
|
||||||
"Wait {}ms to not spam the node",
|
"Wait {:?} to not spam the node",
|
||||||
self.config.consensus_info_polling_interval_millis
|
self.config.consensus_info_polling_interval
|
||||||
);
|
);
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(
|
tokio::time::sleep(self.config.consensus_info_polling_interval).await;
|
||||||
self.config.consensus_info_polling_interval_millis,
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"home": "./indexer/service",
|
"home": "./indexer/service",
|
||||||
"consensus_info_polling_interval_millis": 10000,
|
"consensus_info_polling_interval": "1s",
|
||||||
"bedrock_client_config": {
|
"bedrock_client_config": {
|
||||||
"addr": "http://localhost:8080",
|
"addr": "http://localhost:8080",
|
||||||
"backoff": {
|
"backoff": {
|
||||||
"start_delay_millis": 100,
|
"start_delay": "100ms",
|
||||||
"max_retries": 5
|
"max_retries": 5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use std::{net::SocketAddr, path::PathBuf};
|
use std::{net::SocketAddr, path::PathBuf, time::Duration};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use bytesize::ByteSize;
|
use bytesize::ByteSize;
|
||||||
@ -20,13 +20,13 @@ pub fn indexer_config(
|
|||||||
) -> Result<IndexerConfig> {
|
) -> Result<IndexerConfig> {
|
||||||
Ok(IndexerConfig {
|
Ok(IndexerConfig {
|
||||||
home,
|
home,
|
||||||
consensus_info_polling_interval_millis: 10000,
|
consensus_info_polling_interval: Duration::from_secs(1),
|
||||||
bedrock_client_config: ClientConfig {
|
bedrock_client_config: ClientConfig {
|
||||||
addr: addr_to_url(UrlProtocol::Http, bedrock_addr)
|
addr: addr_to_url(UrlProtocol::Http, bedrock_addr)
|
||||||
.context("Failed to convert bedrock addr to URL")?,
|
.context("Failed to convert bedrock addr to URL")?,
|
||||||
auth: None,
|
auth: None,
|
||||||
backoff: BackoffConfig {
|
backoff: BackoffConfig {
|
||||||
start_delay_millis: 100,
|
start_delay: Duration::from_millis(100),
|
||||||
max_retries: 10,
|
max_retries: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -42,7 +42,7 @@ pub struct SequencerPartialConfig {
|
|||||||
pub max_num_tx_in_block: usize,
|
pub max_num_tx_in_block: usize,
|
||||||
pub max_block_size: ByteSize,
|
pub max_block_size: ByteSize,
|
||||||
pub mempool_max_size: usize,
|
pub mempool_max_size: usize,
|
||||||
pub block_create_timeout_millis: u64,
|
pub block_create_timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SequencerPartialConfig {
|
impl Default for SequencerPartialConfig {
|
||||||
@ -51,7 +51,7 @@ impl Default for SequencerPartialConfig {
|
|||||||
max_num_tx_in_block: 20,
|
max_num_tx_in_block: 20,
|
||||||
max_block_size: ByteSize::mib(1),
|
max_block_size: ByteSize::mib(1),
|
||||||
mempool_max_size: 10_000,
|
mempool_max_size: 10_000,
|
||||||
block_create_timeout_millis: 10_000,
|
block_create_timeout: Duration::from_secs(10),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ pub fn sequencer_config(
|
|||||||
max_num_tx_in_block,
|
max_num_tx_in_block,
|
||||||
max_block_size,
|
max_block_size,
|
||||||
mempool_max_size,
|
mempool_max_size,
|
||||||
block_create_timeout_millis,
|
block_create_timeout,
|
||||||
} = partial;
|
} = partial;
|
||||||
|
|
||||||
Ok(SequencerConfig {
|
Ok(SequencerConfig {
|
||||||
@ -78,15 +78,15 @@ pub fn sequencer_config(
|
|||||||
max_num_tx_in_block,
|
max_num_tx_in_block,
|
||||||
max_block_size,
|
max_block_size,
|
||||||
mempool_max_size,
|
mempool_max_size,
|
||||||
block_create_timeout_millis,
|
block_create_timeout,
|
||||||
retry_pending_blocks_timeout_millis: 120_000,
|
retry_pending_blocks_timeout: Duration::from_secs(120),
|
||||||
port: 0,
|
port: 0,
|
||||||
initial_accounts: initial_data.sequencer_initial_accounts(),
|
initial_accounts: initial_data.sequencer_initial_accounts(),
|
||||||
initial_commitments: initial_data.sequencer_initial_commitments(),
|
initial_commitments: initial_data.sequencer_initial_commitments(),
|
||||||
signing_key: [37; 32],
|
signing_key: [37; 32],
|
||||||
bedrock_config: BedrockConfig {
|
bedrock_config: BedrockConfig {
|
||||||
backoff: BackoffConfig {
|
backoff: BackoffConfig {
|
||||||
start_delay_millis: 100,
|
start_delay: Duration::from_millis(100),
|
||||||
max_retries: 5,
|
max_retries: 5,
|
||||||
},
|
},
|
||||||
channel_id: bedrock_channel_id(),
|
channel_id: bedrock_channel_id(),
|
||||||
@ -107,7 +107,7 @@ pub fn wallet_config(
|
|||||||
override_rust_log: None,
|
override_rust_log: None,
|
||||||
sequencer_addr: addr_to_url(UrlProtocol::Http, sequencer_addr)
|
sequencer_addr: addr_to_url(UrlProtocol::Http, sequencer_addr)
|
||||||
.context("Failed to convert sequencer addr to URL")?,
|
.context("Failed to convert sequencer addr to URL")?,
|
||||||
seq_poll_timeout_millis: 30_000,
|
seq_poll_timeout: Duration::from_secs(30),
|
||||||
seq_tx_poll_max_blocks: 15,
|
seq_tx_poll_max_blocks: 15,
|
||||||
seq_poll_max_retries: 10,
|
seq_poll_max_retries: 10,
|
||||||
seq_block_poll_max_amount: 100,
|
seq_block_poll_max_amount: 100,
|
||||||
|
|||||||
@ -16,7 +16,7 @@ async fn reject_oversized_transaction() -> Result<()> {
|
|||||||
max_num_tx_in_block: 100,
|
max_num_tx_in_block: 100,
|
||||||
max_block_size: ByteSize::mib(1),
|
max_block_size: ByteSize::mib(1),
|
||||||
mempool_max_size: 1000,
|
mempool_max_size: 1000,
|
||||||
block_create_timeout_millis: 10_000,
|
block_create_timeout: Duration::from_secs(10),
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
.await?;
|
.await?;
|
||||||
@ -57,7 +57,7 @@ async fn accept_transaction_within_limit() -> Result<()> {
|
|||||||
max_num_tx_in_block: 100,
|
max_num_tx_in_block: 100,
|
||||||
max_block_size: ByteSize::mib(1),
|
max_block_size: ByteSize::mib(1),
|
||||||
mempool_max_size: 1000,
|
mempool_max_size: 1000,
|
||||||
block_create_timeout_millis: 10_000,
|
block_create_timeout: Duration::from_secs(10),
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
.await?;
|
.await?;
|
||||||
@ -99,7 +99,7 @@ async fn transaction_deferred_to_next_block_when_current_full() -> Result<()> {
|
|||||||
max_num_tx_in_block: 100,
|
max_num_tx_in_block: 100,
|
||||||
max_block_size: block_size,
|
max_block_size: block_size,
|
||||||
mempool_max_size: 1000,
|
mempool_max_size: 1000,
|
||||||
block_create_timeout_millis: 10_000,
|
block_create_timeout: Duration::from_secs(10),
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
@ -8,22 +8,22 @@ use wallet::cli::{Command, config::ConfigSubcommand};
|
|||||||
async fn modify_config_field() -> Result<()> {
|
async fn modify_config_field() -> Result<()> {
|
||||||
let mut ctx = TestContext::new().await?;
|
let mut ctx = TestContext::new().await?;
|
||||||
|
|
||||||
let old_seq_poll_timeout_millis = ctx.wallet().config().seq_poll_timeout_millis;
|
let old_seq_poll_timeout = ctx.wallet().config().seq_poll_timeout;
|
||||||
|
|
||||||
// Change config field
|
// Change config field
|
||||||
let command = Command::Config(ConfigSubcommand::Set {
|
let command = Command::Config(ConfigSubcommand::Set {
|
||||||
key: "seq_poll_timeout_millis".to_string(),
|
key: "seq_poll_timeout".to_string(),
|
||||||
value: "1000".to_string(),
|
value: "1s".to_string(),
|
||||||
});
|
});
|
||||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||||
|
|
||||||
let new_seq_poll_timeout_millis = ctx.wallet().config().seq_poll_timeout_millis;
|
let new_seq_poll_timeout = ctx.wallet().config().seq_poll_timeout;
|
||||||
assert_eq!(new_seq_poll_timeout_millis, 1000);
|
assert_eq!(new_seq_poll_timeout, std::time::Duration::from_secs(1));
|
||||||
|
|
||||||
// Return how it was at the beginning
|
// Return how it was at the beginning
|
||||||
let command = Command::Config(ConfigSubcommand::Set {
|
let command = Command::Config(ConfigSubcommand::Set {
|
||||||
key: "seq_poll_timeout_millis".to_string(),
|
key: "seq_poll_timeout".to_string(),
|
||||||
value: old_seq_poll_timeout_millis.to_string(),
|
value: format!("{:?}", old_seq_poll_timeout),
|
||||||
});
|
});
|
||||||
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
wallet::cli::execute_subcommand(ctx.wallet_mut(), command).await?;
|
||||||
|
|
||||||
|
|||||||
@ -181,7 +181,7 @@ impl TpsTestManager {
|
|||||||
max_num_tx_in_block: 300,
|
max_num_tx_in_block: 300,
|
||||||
max_block_size: ByteSize::mb(500),
|
max_block_size: ByteSize::mb(500),
|
||||||
mempool_max_size: 10_000,
|
mempool_max_size: 10_000,
|
||||||
block_create_timeout_millis: 12_000,
|
block_create_timeout: Duration::from_secs(12),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ serde.workspace = true
|
|||||||
serde_with.workspace = true
|
serde_with.workspace = true
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
bytemuck.workspace = true
|
bytemuck.workspace = true
|
||||||
|
bytesize.workspace = true
|
||||||
base58.workspace = true
|
base58.workspace = true
|
||||||
k256 = { workspace = true, optional = true }
|
k256 = { workspace = true, optional = true }
|
||||||
chacha20 = { version = "0.9", default-features = false }
|
chacha20 = { version = "0.9", default-features = false }
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use borsh::{BorshDeserialize, BorshSerialize};
|
use borsh::{BorshDeserialize, BorshSerialize};
|
||||||
|
use bytesize::ByteSize;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub const DATA_MAX_LENGTH_IN_BYTES: usize = 100 * 1024; // 100 KiB
|
pub const DATA_MAX_LENGTH: ByteSize = ByteSize::kib(100);
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, BorshSerialize)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, BorshSerialize)]
|
||||||
pub struct Data(Vec<u8>);
|
pub struct Data(Vec<u8>);
|
||||||
@ -22,7 +23,7 @@ impl Data {
|
|||||||
let mut u32_bytes = [0u8; 4];
|
let mut u32_bytes = [0u8; 4];
|
||||||
cursor.read_exact(&mut u32_bytes)?;
|
cursor.read_exact(&mut u32_bytes)?;
|
||||||
let data_length = u32::from_le_bytes(u32_bytes);
|
let data_length = u32::from_le_bytes(u32_bytes);
|
||||||
if data_length as usize > DATA_MAX_LENGTH_IN_BYTES {
|
if data_length as usize > DATA_MAX_LENGTH.as_u64() as usize {
|
||||||
return Err(
|
return Err(
|
||||||
std::io::Error::new(std::io::ErrorKind::InvalidData, DataTooBigError).into(),
|
std::io::Error::new(std::io::ErrorKind::InvalidData, DataTooBigError).into(),
|
||||||
);
|
);
|
||||||
@ -35,7 +36,7 @@ impl Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, thiserror::Error, Clone, Copy, PartialEq, Eq)]
|
||||||
#[error("data length exceeds maximum allowed length of {DATA_MAX_LENGTH_IN_BYTES} bytes")]
|
#[error("data length exceeds maximum allowed length of {} bytes", DATA_MAX_LENGTH.as_u64())]
|
||||||
pub struct DataTooBigError;
|
pub struct DataTooBigError;
|
||||||
|
|
||||||
impl From<Data> for Vec<u8> {
|
impl From<Data> for Vec<u8> {
|
||||||
@ -48,7 +49,7 @@ impl TryFrom<Vec<u8>> for Data {
|
|||||||
type Error = DataTooBigError;
|
type Error = DataTooBigError;
|
||||||
|
|
||||||
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
||||||
if value.len() > DATA_MAX_LENGTH_IN_BYTES {
|
if value.len() > DATA_MAX_LENGTH.as_u64() as usize {
|
||||||
Err(DataTooBigError)
|
Err(DataTooBigError)
|
||||||
} else {
|
} else {
|
||||||
Ok(Self(value))
|
Ok(Self(value))
|
||||||
@ -78,7 +79,7 @@ impl<'de> Deserialize<'de> for Data {
|
|||||||
/// Data deserialization visitor.
|
/// Data deserialization visitor.
|
||||||
///
|
///
|
||||||
/// Compared to a simple deserialization into a `Vec<u8>`, this visitor enforces
|
/// Compared to a simple deserialization into a `Vec<u8>`, this visitor enforces
|
||||||
/// early length check defined by [`DATA_MAX_LENGTH_IN_BYTES`].
|
/// early length check defined by [`DATA_MAX_LENGTH`].
|
||||||
struct DataVisitor;
|
struct DataVisitor;
|
||||||
|
|
||||||
impl<'de> serde::de::Visitor<'de> for DataVisitor {
|
impl<'de> serde::de::Visitor<'de> for DataVisitor {
|
||||||
@ -88,7 +89,7 @@ impl<'de> Deserialize<'de> for Data {
|
|||||||
write!(
|
write!(
|
||||||
formatter,
|
formatter,
|
||||||
"a byte array with length not exceeding {} bytes",
|
"a byte array with length not exceeding {} bytes",
|
||||||
DATA_MAX_LENGTH_IN_BYTES
|
DATA_MAX_LENGTH.as_u64()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,11 +97,14 @@ impl<'de> Deserialize<'de> for Data {
|
|||||||
where
|
where
|
||||||
A: serde::de::SeqAccess<'de>,
|
A: serde::de::SeqAccess<'de>,
|
||||||
{
|
{
|
||||||
let mut vec =
|
let mut vec = Vec::with_capacity(
|
||||||
Vec::with_capacity(seq.size_hint().unwrap_or(0).min(DATA_MAX_LENGTH_IN_BYTES));
|
seq.size_hint()
|
||||||
|
.unwrap_or(0)
|
||||||
|
.min(DATA_MAX_LENGTH.as_u64() as usize),
|
||||||
|
);
|
||||||
|
|
||||||
while let Some(value) = seq.next_element()? {
|
while let Some(value) = seq.next_element()? {
|
||||||
if vec.len() >= DATA_MAX_LENGTH_IN_BYTES {
|
if vec.len() >= DATA_MAX_LENGTH.as_u64() as usize {
|
||||||
return Err(serde::de::Error::custom(DataTooBigError));
|
return Err(serde::de::Error::custom(DataTooBigError));
|
||||||
}
|
}
|
||||||
vec.push(value);
|
vec.push(value);
|
||||||
@ -121,7 +125,7 @@ impl BorshDeserialize for Data {
|
|||||||
let len = u32::deserialize_reader(reader)?;
|
let len = u32::deserialize_reader(reader)?;
|
||||||
match len {
|
match len {
|
||||||
0 => Ok(Self::default()),
|
0 => Ok(Self::default()),
|
||||||
len if len as usize > DATA_MAX_LENGTH_IN_BYTES => Err(std::io::Error::new(
|
len if len as usize > DATA_MAX_LENGTH.as_u64() as usize => Err(std::io::Error::new(
|
||||||
std::io::ErrorKind::InvalidData,
|
std::io::ErrorKind::InvalidData,
|
||||||
DataTooBigError,
|
DataTooBigError,
|
||||||
)),
|
)),
|
||||||
@ -140,21 +144,21 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_data_max_length_allowed() {
|
fn test_data_max_length_allowed() {
|
||||||
let max_vec = vec![0u8; DATA_MAX_LENGTH_IN_BYTES];
|
let max_vec = vec![0u8; DATA_MAX_LENGTH.as_u64() as usize];
|
||||||
let result = Data::try_from(max_vec);
|
let result = Data::try_from(max_vec);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_data_too_big_error() {
|
fn test_data_too_big_error() {
|
||||||
let big_vec = vec![0u8; DATA_MAX_LENGTH_IN_BYTES + 1];
|
let big_vec = vec![0u8; DATA_MAX_LENGTH.as_u64() as usize + 1];
|
||||||
let result = Data::try_from(big_vec);
|
let result = Data::try_from(big_vec);
|
||||||
assert!(matches!(result, Err(DataTooBigError)));
|
assert!(matches!(result, Err(DataTooBigError)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_borsh_deserialize_exceeding_limit_error() {
|
fn test_borsh_deserialize_exceeding_limit_error() {
|
||||||
let too_big_data = vec![0u8; DATA_MAX_LENGTH_IN_BYTES + 1];
|
let too_big_data = vec![0u8; DATA_MAX_LENGTH.as_u64() as usize + 1];
|
||||||
let mut serialized = Vec::new();
|
let mut serialized = Vec::new();
|
||||||
<_ as BorshSerialize>::serialize(&too_big_data, &mut serialized).unwrap();
|
<_ as BorshSerialize>::serialize(&too_big_data, &mut serialized).unwrap();
|
||||||
|
|
||||||
@ -164,7 +168,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_json_deserialize_exceeding_limit_error() {
|
fn test_json_deserialize_exceeding_limit_error() {
|
||||||
let data = vec![0u8; DATA_MAX_LENGTH_IN_BYTES + 1];
|
let data = vec![0u8; DATA_MAX_LENGTH.as_u64() as usize + 1];
|
||||||
let json = serde_json::to_string(&data).unwrap();
|
let json = serde_json::to_string(&data).unwrap();
|
||||||
|
|
||||||
let result: Result<Data, _> = serde_json::from_str(&json);
|
let result: Result<Data, _> = serde_json::from_str(&json);
|
||||||
|
|||||||
@ -1332,7 +1332,8 @@ pub mod tests {
|
|||||||
AccountId::new([0; 32]),
|
AccountId::new([0; 32]),
|
||||||
);
|
);
|
||||||
|
|
||||||
let large_data: Vec<u8> = vec![0; nssa_core::account::data::DATA_MAX_LENGTH_IN_BYTES + 1];
|
let large_data: Vec<u8> =
|
||||||
|
vec![0; nssa_core::account::data::DATA_MAX_LENGTH.as_u64() as usize + 1];
|
||||||
|
|
||||||
let result = execute_and_prove(
|
let result = execute_and_prove(
|
||||||
vec![public_account],
|
vec![public_account],
|
||||||
|
|||||||
@ -16,6 +16,7 @@ base58.workspace = true
|
|||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
humantime-serde.workspace = true
|
||||||
tempfile.workspace = true
|
tempfile.workspace = true
|
||||||
chrono.workspace = true
|
chrono.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
|||||||
@ -2,6 +2,7 @@ use std::{
|
|||||||
fs::File,
|
fs::File,
|
||||||
io::BufReader,
|
io::BufReader,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
@ -11,6 +12,7 @@ use common::{
|
|||||||
block::{AccountInitialData, CommitmentsInitialData},
|
block::{AccountInitialData, CommitmentsInitialData},
|
||||||
config::BasicAuth,
|
config::BasicAuth,
|
||||||
};
|
};
|
||||||
|
use humantime_serde;
|
||||||
use logos_blockchain_core::mantle::ops::channel::ChannelId;
|
use logos_blockchain_core::mantle::ops::channel::ChannelId;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@ -34,9 +36,11 @@ pub struct SequencerConfig {
|
|||||||
/// Mempool maximum size
|
/// Mempool maximum size
|
||||||
pub mempool_max_size: usize,
|
pub mempool_max_size: usize,
|
||||||
/// Interval in which blocks produced
|
/// Interval in which blocks produced
|
||||||
pub block_create_timeout_millis: u64,
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub block_create_timeout: Duration,
|
||||||
/// Interval in which pending blocks are retried
|
/// Interval in which pending blocks are retried
|
||||||
pub retry_pending_blocks_timeout_millis: u64,
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub retry_pending_blocks_timeout: Duration,
|
||||||
/// Port to listen
|
/// Port to listen
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
/// List of initial accounts data
|
/// List of initial accounts data
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use std::{fmt::Display, path::Path, time::Instant};
|
use std::{path::Path, time::Instant};
|
||||||
|
|
||||||
use anyhow::{Context as _, Result, anyhow};
|
use anyhow::{Context as _, Result, anyhow};
|
||||||
use bedrock_client::SignedMantleTx;
|
use bedrock_client::SignedMantleTx;
|
||||||
@ -13,7 +13,6 @@ use config::SequencerConfig;
|
|||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use logos_blockchain_key_management_system_service::keys::{ED25519_SECRET_KEY_SIZE, Ed25519Key};
|
use logos_blockchain_key_management_system_service::keys::{ED25519_SECRET_KEY_SIZE, Ed25519Key};
|
||||||
use mempool::{MemPool, MemPoolHandle};
|
use mempool::{MemPool, MemPoolHandle};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
block_settlement_client::{BlockSettlementClient, BlockSettlementClientTrait, MsgId},
|
block_settlement_client::{BlockSettlementClient, BlockSettlementClientTrait, MsgId},
|
||||||
@ -44,21 +43,6 @@ pub struct SequencerCore<
|
|||||||
indexer_client: IC,
|
indexer_client: IC,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub enum TransactionMalformationError {
|
|
||||||
InvalidSignature,
|
|
||||||
FailedToDecode { tx: HashType },
|
|
||||||
TransactionTooLarge { size: usize, max: usize },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for TransactionMalformationError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{self:#?}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for TransactionMalformationError {}
|
|
||||||
|
|
||||||
impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, IC> {
|
impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, IC> {
|
||||||
/// Starts the sequencer using the provided configuration.
|
/// Starts the sequencer using the provided configuration.
|
||||||
/// If an existing database is found, the sequencer state is loaded from it and
|
/// If an existing database is found, the sequencer state is loaded from it and
|
||||||
@ -376,7 +360,7 @@ fn load_or_create_signing_key(path: &Path) -> Result<Ed25519Key> {
|
|||||||
|
|
||||||
#[cfg(all(test, feature = "mock"))]
|
#[cfg(all(test, feature = "mock"))]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{pin::pin, str::FromStr as _};
|
use std::{pin::pin, str::FromStr as _, time::Duration};
|
||||||
|
|
||||||
use base58::ToBase58;
|
use base58::ToBase58;
|
||||||
use bedrock_client::BackoffConfig;
|
use bedrock_client::BackoffConfig;
|
||||||
@ -407,21 +391,21 @@ mod tests {
|
|||||||
max_num_tx_in_block: 10,
|
max_num_tx_in_block: 10,
|
||||||
max_block_size: bytesize::ByteSize::mib(1),
|
max_block_size: bytesize::ByteSize::mib(1),
|
||||||
mempool_max_size: 10000,
|
mempool_max_size: 10000,
|
||||||
block_create_timeout_millis: 1000,
|
block_create_timeout: Duration::from_secs(1),
|
||||||
port: 8080,
|
port: 8080,
|
||||||
initial_accounts,
|
initial_accounts,
|
||||||
initial_commitments: vec![],
|
initial_commitments: vec![],
|
||||||
signing_key: *sequencer_sign_key_for_testing().value(),
|
signing_key: *sequencer_sign_key_for_testing().value(),
|
||||||
bedrock_config: BedrockConfig {
|
bedrock_config: BedrockConfig {
|
||||||
backoff: BackoffConfig {
|
backoff: BackoffConfig {
|
||||||
start_delay_millis: 100,
|
start_delay: Duration::from_millis(100),
|
||||||
max_retries: 5,
|
max_retries: 5,
|
||||||
},
|
},
|
||||||
channel_id: ChannelId::from([0; 32]),
|
channel_id: ChannelId::from([0; 32]),
|
||||||
node_url: "http://not-used-in-unit-tests".parse().unwrap(),
|
node_url: "http://not-used-in-unit-tests".parse().unwrap(),
|
||||||
auth: None,
|
auth: None,
|
||||||
},
|
},
|
||||||
retry_pending_blocks_timeout_millis: 1000 * 60 * 4,
|
retry_pending_blocks_timeout: Duration::from_secs(60 * 4),
|
||||||
indexer_rpc_url: "ws://localhost:8779".parse().unwrap(),
|
indexer_rpc_url: "ws://localhost:8779".parse().unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,7 +80,10 @@ pub async fn new_http_server(
|
|||||||
App::new()
|
App::new()
|
||||||
.wrap(get_cors(&cors_allowed_origins))
|
.wrap(get_cors(&cors_allowed_origins))
|
||||||
.app_data(handler.clone())
|
.app_data(handler.clone())
|
||||||
.app_data(web::JsonConfig::default().limit(limits_config.json_payload_max_size))
|
.app_data(
|
||||||
|
web::JsonConfig::default()
|
||||||
|
.limit(limits_config.json_payload_max_size.as_u64() as usize),
|
||||||
|
)
|
||||||
.wrap(middleware::Logger::default())
|
.wrap(middleware::Logger::default())
|
||||||
.service(web::resource("/").route(web::post().to(rpc_handler::<JsonHandler>)))
|
.service(web::resource("/").route(web::post().to(rpc_handler::<JsonHandler>)))
|
||||||
})
|
})
|
||||||
|
|||||||
@ -20,7 +20,7 @@ use common::{
|
|||||||
SendTxResponse,
|
SendTxResponse,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
transaction::NSSATransaction,
|
transaction::{NSSATransaction, TransactionMalformationError},
|
||||||
};
|
};
|
||||||
use itertools::Itertools as _;
|
use itertools::Itertools as _;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
@ -98,21 +98,17 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> JsonHandler<BC, IC>
|
|||||||
// Reserve ~200 bytes for block header overhead
|
// Reserve ~200 bytes for block header overhead
|
||||||
const BLOCK_HEADER_OVERHEAD: usize = 200;
|
const BLOCK_HEADER_OVERHEAD: usize = 200;
|
||||||
let tx_size = borsh::to_vec(&tx)
|
let tx_size = borsh::to_vec(&tx)
|
||||||
.map_err(
|
.map_err(|_| TransactionMalformationError::FailedToDecode { tx: tx_hash })?
|
||||||
|_| sequencer_core::TransactionMalformationError::FailedToDecode { tx: tx_hash },
|
|
||||||
)?
|
|
||||||
.len();
|
.len();
|
||||||
|
|
||||||
let max_tx_size = self.max_block_size.saturating_sub(BLOCK_HEADER_OVERHEAD);
|
let max_tx_size = self.max_block_size.saturating_sub(BLOCK_HEADER_OVERHEAD);
|
||||||
|
|
||||||
if tx_size > max_tx_size {
|
if tx_size > max_tx_size {
|
||||||
return Err(
|
return Err(TransactionMalformationError::TransactionTooLarge {
|
||||||
sequencer_core::TransactionMalformationError::TransactionTooLarge {
|
size: tx_size,
|
||||||
size: tx_size,
|
max: max_tx_size,
|
||||||
max: max_tx_size,
|
}
|
||||||
}
|
.into());
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let authenticated_tx = tx
|
let authenticated_tx = tx
|
||||||
@ -344,7 +340,7 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> JsonHandler<BC, IC>
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{str::FromStr as _, sync::Arc};
|
use std::{str::FromStr as _, sync::Arc, time::Duration};
|
||||||
|
|
||||||
use base58::ToBase58;
|
use base58::ToBase58;
|
||||||
use base64::{Engine, engine::general_purpose};
|
use base64::{Engine, engine::general_purpose};
|
||||||
@ -400,15 +396,15 @@ mod tests {
|
|||||||
max_num_tx_in_block: 10,
|
max_num_tx_in_block: 10,
|
||||||
max_block_size: bytesize::ByteSize::mib(1),
|
max_block_size: bytesize::ByteSize::mib(1),
|
||||||
mempool_max_size: 1000,
|
mempool_max_size: 1000,
|
||||||
block_create_timeout_millis: 1000,
|
block_create_timeout: Duration::from_secs(1),
|
||||||
port: 8080,
|
port: 8080,
|
||||||
initial_accounts,
|
initial_accounts,
|
||||||
initial_commitments: vec![],
|
initial_commitments: vec![],
|
||||||
signing_key: *sequencer_sign_key_for_testing().value(),
|
signing_key: *sequencer_sign_key_for_testing().value(),
|
||||||
retry_pending_blocks_timeout_millis: 1000 * 60 * 4,
|
retry_pending_blocks_timeout: Duration::from_secs(60 * 4),
|
||||||
bedrock_config: BedrockConfig {
|
bedrock_config: BedrockConfig {
|
||||||
backoff: BackoffConfig {
|
backoff: BackoffConfig {
|
||||||
start_delay_millis: 100,
|
start_delay: Duration::from_millis(100),
|
||||||
max_retries: 5,
|
max_retries: 5,
|
||||||
},
|
},
|
||||||
channel_id: [42; 32].into(),
|
channel_id: [42; 32].into(),
|
||||||
|
|||||||
@ -6,12 +6,12 @@
|
|||||||
"max_num_tx_in_block": 20,
|
"max_num_tx_in_block": 20,
|
||||||
"max_block_size": "1 MiB",
|
"max_block_size": "1 MiB",
|
||||||
"mempool_max_size": 1000,
|
"mempool_max_size": 1000,
|
||||||
"block_create_timeout_millis": 15000,
|
"block_create_timeout": "15s",
|
||||||
"retry_pending_blocks_timeout_millis": 5000,
|
"retry_pending_blocks_timeout": "5s",
|
||||||
"port": 3040,
|
"port": 3040,
|
||||||
"bedrock_config": {
|
"bedrock_config": {
|
||||||
"backoff": {
|
"backoff": {
|
||||||
"start_delay_millis": 100,
|
"start_delay": "100ms",
|
||||||
"max_retries": 5
|
"max_retries": 5
|
||||||
},
|
},
|
||||||
"channel_id": "0101010101010101010101010101010101010101010101010101010101010101",
|
"channel_id": "0101010101010101010101010101010101010101010101010101010101010101",
|
||||||
|
|||||||
@ -6,12 +6,12 @@
|
|||||||
"max_num_tx_in_block": 20,
|
"max_num_tx_in_block": 20,
|
||||||
"max_block_size": "1 MiB",
|
"max_block_size": "1 MiB",
|
||||||
"mempool_max_size": 10000,
|
"mempool_max_size": 10000,
|
||||||
"block_create_timeout_millis": 10000,
|
"block_create_timeout": "10s",
|
||||||
"port": 3040,
|
"port": 3040,
|
||||||
"retry_pending_blocks_timeout_millis": 7000,
|
"retry_pending_blocks_timeout": "7s",
|
||||||
"bedrock_config": {
|
"bedrock_config": {
|
||||||
"backoff": {
|
"backoff": {
|
||||||
"start_delay_millis": 100,
|
"start_delay": "100ms",
|
||||||
"max_retries": 5
|
"max_retries": 5
|
||||||
},
|
},
|
||||||
"channel_id": "0101010101010101010101010101010101010101010101010101010101010101",
|
"channel_id": "0101010101010101010101010101010101010101010101010101010101010101",
|
||||||
|
|||||||
@ -99,9 +99,8 @@ impl Drop for SequencerHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn startup_sequencer(app_config: SequencerConfig) -> Result<SequencerHandle> {
|
pub async fn startup_sequencer(app_config: SequencerConfig) -> Result<SequencerHandle> {
|
||||||
let block_timeout = Duration::from_millis(app_config.block_create_timeout_millis);
|
let block_timeout = app_config.block_create_timeout;
|
||||||
let retry_pending_blocks_timeout =
|
let retry_pending_blocks_timeout = app_config.retry_pending_blocks_timeout;
|
||||||
Duration::from_millis(app_config.retry_pending_blocks_timeout_millis);
|
|
||||||
let port = app_config.port;
|
let port = app_config.port;
|
||||||
|
|
||||||
let (sequencer_core, mempool_handle) = SequencerCore::start_from_config(app_config).await;
|
let (sequencer_core, mempool_handle) = SequencerCore::start_from_config(app_config).await;
|
||||||
|
|||||||
@ -17,6 +17,8 @@ serde_json.workspace = true
|
|||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
humantime-serde.workspace = true
|
||||||
|
humantime.workspace = true
|
||||||
tokio = { workspace = true, features = ["macros"] }
|
tokio = { workspace = true, features = ["macros"] }
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
base64.workspace = true
|
base64.workspace = true
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"override_rust_log": null,
|
"override_rust_log": null,
|
||||||
"sequencer_addr": "http://127.0.0.1:3040",
|
"sequencer_addr": "http://127.0.0.1:3040",
|
||||||
"seq_poll_timeout_millis": 30000,
|
"seq_poll_timeout": "30s",
|
||||||
"seq_tx_poll_max_blocks": 15,
|
"seq_tx_poll_max_blocks": 15,
|
||||||
"seq_poll_max_retries": 10,
|
"seq_poll_max_retries": 10,
|
||||||
"seq_block_poll_max_amount": 100,
|
"seq_block_poll_max_amount": 100,
|
||||||
|
|||||||
@ -262,7 +262,7 @@ mod tests {
|
|||||||
WalletConfig {
|
WalletConfig {
|
||||||
override_rust_log: None,
|
override_rust_log: None,
|
||||||
sequencer_addr: "http://127.0.0.1".parse().unwrap(),
|
sequencer_addr: "http://127.0.0.1".parse().unwrap(),
|
||||||
seq_poll_timeout_millis: 12000,
|
seq_poll_timeout: std::time::Duration::from_secs(12),
|
||||||
seq_tx_poll_max_blocks: 5,
|
seq_tx_poll_max_blocks: 5,
|
||||||
seq_poll_max_retries: 10,
|
seq_poll_max_retries: 10,
|
||||||
seq_block_poll_max_amount: 100,
|
seq_block_poll_max_amount: 100,
|
||||||
|
|||||||
@ -49,11 +49,8 @@ impl WalletSubcommand for ConfigSubcommand {
|
|||||||
"sequencer_addr" => {
|
"sequencer_addr" => {
|
||||||
println!("{}", wallet_core.storage.wallet_config.sequencer_addr);
|
println!("{}", wallet_core.storage.wallet_config.sequencer_addr);
|
||||||
}
|
}
|
||||||
"seq_poll_timeout_millis" => {
|
"seq_poll_timeout" => {
|
||||||
println!(
|
println!("{:?}", wallet_core.storage.wallet_config.seq_poll_timeout);
|
||||||
"{}",
|
|
||||||
wallet_core.storage.wallet_config.seq_poll_timeout_millis
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
"seq_tx_poll_max_blocks" => {
|
"seq_tx_poll_max_blocks" => {
|
||||||
println!(
|
println!(
|
||||||
@ -97,9 +94,10 @@ impl WalletSubcommand for ConfigSubcommand {
|
|||||||
"sequencer_addr" => {
|
"sequencer_addr" => {
|
||||||
wallet_core.storage.wallet_config.sequencer_addr = value.parse()?;
|
wallet_core.storage.wallet_config.sequencer_addr = value.parse()?;
|
||||||
}
|
}
|
||||||
"seq_poll_timeout_millis" => {
|
"seq_poll_timeout" => {
|
||||||
wallet_core.storage.wallet_config.seq_poll_timeout_millis =
|
wallet_core.storage.wallet_config.seq_poll_timeout =
|
||||||
value.parse()?;
|
humantime::parse_duration(&value)
|
||||||
|
.map_err(|e| anyhow::anyhow!("Invalid duration: {}", e))?;
|
||||||
}
|
}
|
||||||
"seq_tx_poll_max_blocks" => {
|
"seq_tx_poll_max_blocks" => {
|
||||||
wallet_core.storage.wallet_config.seq_tx_poll_max_blocks = value.parse()?;
|
wallet_core.storage.wallet_config.seq_tx_poll_max_blocks = value.parse()?;
|
||||||
@ -131,9 +129,9 @@ impl WalletSubcommand for ConfigSubcommand {
|
|||||||
"sequencer_addr" => {
|
"sequencer_addr" => {
|
||||||
println!("HTTP V4 account_id of sequencer");
|
println!("HTTP V4 account_id of sequencer");
|
||||||
}
|
}
|
||||||
"seq_poll_timeout_millis" => {
|
"seq_poll_timeout" => {
|
||||||
println!(
|
println!(
|
||||||
"Sequencer client retry variable: how much time to wait between retries in milliseconds(can be zero)"
|
"Sequencer client retry variable: how much time to wait between retries (human readable duration)"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
"seq_tx_poll_max_blocks" => {
|
"seq_tx_poll_max_blocks" => {
|
||||||
|
|||||||
@ -191,10 +191,7 @@ pub async fn execute_continuous_run(wallet_core: &mut WalletCore) -> Result<()>
|
|||||||
.last_block;
|
.last_block;
|
||||||
wallet_core.sync_to_block(latest_block_num).await?;
|
wallet_core.sync_to_block(latest_block_num).await?;
|
||||||
|
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(
|
tokio::time::sleep(wallet_core.config().seq_poll_timeout).await;
|
||||||
wallet_core.config().seq_poll_timeout_millis,
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,12 @@ use std::{
|
|||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io::{BufReader, Write as _},
|
io::{BufReader, Write as _},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
use common::config::BasicAuth;
|
use common::config::BasicAuth;
|
||||||
|
use humantime_serde;
|
||||||
use key_protocol::key_management::{
|
use key_protocol::key_management::{
|
||||||
KeyChain,
|
KeyChain,
|
||||||
key_tree::{
|
key_tree::{
|
||||||
@ -184,8 +186,9 @@ pub struct WalletConfig {
|
|||||||
pub override_rust_log: Option<String>,
|
pub override_rust_log: Option<String>,
|
||||||
/// Sequencer URL
|
/// Sequencer URL
|
||||||
pub sequencer_addr: Url,
|
pub sequencer_addr: Url,
|
||||||
/// Sequencer polling duration for new blocks in milliseconds
|
/// Sequencer polling duration for new blocks
|
||||||
pub seq_poll_timeout_millis: u64,
|
#[serde(with = "humantime_serde")]
|
||||||
|
pub seq_poll_timeout: Duration,
|
||||||
/// Sequencer polling max number of blocks to find transaction
|
/// Sequencer polling max number of blocks to find transaction
|
||||||
pub seq_tx_poll_max_blocks: usize,
|
pub seq_tx_poll_max_blocks: usize,
|
||||||
/// Sequencer polling max number error retries
|
/// Sequencer polling max number error retries
|
||||||
@ -204,7 +207,7 @@ impl Default for WalletConfig {
|
|||||||
Self {
|
Self {
|
||||||
override_rust_log: None,
|
override_rust_log: None,
|
||||||
sequencer_addr: "http://127.0.0.1:3040".parse().unwrap(),
|
sequencer_addr: "http://127.0.0.1:3040".parse().unwrap(),
|
||||||
seq_poll_timeout_millis: 12000,
|
seq_poll_timeout: Duration::from_secs(12),
|
||||||
seq_tx_poll_max_blocks: 5,
|
seq_tx_poll_max_blocks: 5,
|
||||||
seq_poll_max_retries: 5,
|
seq_poll_max_retries: 5,
|
||||||
seq_block_poll_max_amount: 100,
|
seq_block_poll_max_amount: 100,
|
||||||
@ -539,7 +542,7 @@ impl WalletConfig {
|
|||||||
let WalletConfig {
|
let WalletConfig {
|
||||||
override_rust_log,
|
override_rust_log,
|
||||||
sequencer_addr,
|
sequencer_addr,
|
||||||
seq_poll_timeout_millis,
|
seq_poll_timeout,
|
||||||
seq_tx_poll_max_blocks,
|
seq_tx_poll_max_blocks,
|
||||||
seq_poll_max_retries,
|
seq_poll_max_retries,
|
||||||
seq_block_poll_max_amount,
|
seq_block_poll_max_amount,
|
||||||
@ -550,7 +553,7 @@ impl WalletConfig {
|
|||||||
let WalletConfigOverrides {
|
let WalletConfigOverrides {
|
||||||
override_rust_log: o_override_rust_log,
|
override_rust_log: o_override_rust_log,
|
||||||
sequencer_addr: o_sequencer_addr,
|
sequencer_addr: o_sequencer_addr,
|
||||||
seq_poll_timeout_millis: o_seq_poll_timeout_millis,
|
seq_poll_timeout: o_seq_poll_timeout,
|
||||||
seq_tx_poll_max_blocks: o_seq_tx_poll_max_blocks,
|
seq_tx_poll_max_blocks: o_seq_tx_poll_max_blocks,
|
||||||
seq_poll_max_retries: o_seq_poll_max_retries,
|
seq_poll_max_retries: o_seq_poll_max_retries,
|
||||||
seq_block_poll_max_amount: o_seq_block_poll_max_amount,
|
seq_block_poll_max_amount: o_seq_block_poll_max_amount,
|
||||||
@ -566,9 +569,9 @@ impl WalletConfig {
|
|||||||
warn!("Overriding wallet config 'sequencer_addr' to {v}");
|
warn!("Overriding wallet config 'sequencer_addr' to {v}");
|
||||||
*sequencer_addr = v;
|
*sequencer_addr = v;
|
||||||
}
|
}
|
||||||
if let Some(v) = o_seq_poll_timeout_millis {
|
if let Some(v) = o_seq_poll_timeout {
|
||||||
warn!("Overriding wallet config 'seq_poll_timeout_millis' to {v}");
|
warn!("Overriding wallet config 'seq_poll_timeout' to {v:?}");
|
||||||
*seq_poll_timeout_millis = v;
|
*seq_poll_timeout = v;
|
||||||
}
|
}
|
||||||
if let Some(v) = o_seq_tx_poll_max_blocks {
|
if let Some(v) = o_seq_tx_poll_max_blocks {
|
||||||
warn!("Overriding wallet config 'seq_tx_poll_max_blocks' to {v}");
|
warn!("Overriding wallet config 'seq_tx_poll_max_blocks' to {v}");
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use std::sync::Arc;
|
use std::{sync::Arc, time::Duration};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use common::{HashType, block::HashableBlockData, sequencer_client::SequencerClient};
|
use common::{HashType, block::HashableBlockData, sequencer_client::SequencerClient};
|
||||||
@ -11,8 +11,7 @@ use crate::config::WalletConfig;
|
|||||||
pub struct TxPoller {
|
pub struct TxPoller {
|
||||||
polling_max_blocks_to_query: usize,
|
polling_max_blocks_to_query: usize,
|
||||||
polling_max_error_attempts: u64,
|
polling_max_error_attempts: u64,
|
||||||
// TODO: This should be Duration
|
polling_delay: Duration,
|
||||||
polling_delay_millis: u64,
|
|
||||||
block_poll_max_amount: u64,
|
block_poll_max_amount: u64,
|
||||||
client: Arc<SequencerClient>,
|
client: Arc<SequencerClient>,
|
||||||
}
|
}
|
||||||
@ -20,7 +19,7 @@ pub struct TxPoller {
|
|||||||
impl TxPoller {
|
impl TxPoller {
|
||||||
pub fn new(config: WalletConfig, client: Arc<SequencerClient>) -> Self {
|
pub fn new(config: WalletConfig, client: Arc<SequencerClient>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
polling_delay_millis: config.seq_poll_timeout_millis,
|
polling_delay: config.seq_poll_timeout,
|
||||||
polling_max_blocks_to_query: config.seq_tx_poll_max_blocks,
|
polling_max_blocks_to_query: config.seq_tx_poll_max_blocks,
|
||||||
polling_max_error_attempts: config.seq_poll_max_retries,
|
polling_max_error_attempts: config.seq_poll_max_retries,
|
||||||
block_poll_max_amount: config.seq_block_poll_max_amount,
|
block_poll_max_amount: config.seq_block_poll_max_amount,
|
||||||
@ -62,7 +61,7 @@ impl TxPoller {
|
|||||||
return Ok(tx);
|
return Ok(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(self.polling_delay_millis)).await;
|
tokio::time::sleep(self.polling_delay).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
anyhow::bail!("Transaction not found in preconfigured amount of blocks");
|
anyhow::bail!("Transaction not found in preconfigured amount of blocks");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user