From 8b5524901ce77e00a50f8742de89832e94f7ad94 Mon Sep 17 00:00:00 2001 From: Daniil Polyakov Date: Tue, 24 Feb 2026 19:41:01 +0300 Subject: [PATCH] feat: configurable block size limit --- Cargo.lock | 13 ++ Cargo.toml | 3 +- common/Cargo.toml | 1 + .../sequencer/sequencer_config.json | 1 + integration_tests/Cargo.toml | 1 + integration_tests/src/config.rs | 5 + integration_tests/src/lib.rs | 1 + integration_tests/tests/block_size_limit.rs | 185 ++++++++++++++++++ integration_tests/tests/tps.rs | 2 + mempool/src/lib.rs | 38 +++- nssa/src/merkle_tree/mod.rs | 2 +- nssa/src/state.rs | 5 +- sequencer_core/Cargo.toml | 1 + sequencer_core/src/config.rs | 8 + sequencer_core/src/lib.rs | 47 ++++- sequencer_rpc/Cargo.toml | 1 + sequencer_rpc/src/lib.rs | 1 + sequencer_rpc/src/net_utils.rs | 9 +- sequencer_rpc/src/process.rs | 24 +++ sequencer_rpc/src/types/err_rpc.rs | 5 +- .../configs/debug/sequencer_config.json | 1 + .../configs/docker/sequencer_config.json | 1 + sequencer_runner/src/lib.rs | 3 +- wallet/src/cli/mod.rs | 2 +- 24 files changed, 339 insertions(+), 21 deletions(-) create mode 100644 integration_tests/tests/block_size_limit.rs diff --git a/Cargo.lock b/Cargo.lock index 85856c94..39e14e72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1488,6 +1488,15 @@ dependencies = [ "serde", ] +[[package]] +name = "bytesize" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd91ee7b2422bcb158d90ef4d14f75ef67f340943fc4149891dcce8f8b972a3" +dependencies = [ + "serde_core", +] + [[package]] name = "bytestring" version = "1.5.0" @@ -1743,6 +1752,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "borsh", + "bytesize", "hex", "log", "logos-blockchain-common-http-client", @@ -3835,6 +3845,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "borsh", + "bytesize", "common", "env_logger", "futures", @@ -7430,6 +7441,7 @@ dependencies = [ "base58", "bedrock_client", "borsh", + "bytesize", "chrono", "common", "futures", @@ -7460,6 +7472,7 @@ dependencies = [ "base64 0.22.1", "bedrock_client", "borsh", + "bytesize", "common", "futures", "hex", diff --git a/Cargo.toml b/Cargo.toml index 520844b6..8d6388bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,8 +25,6 @@ members = [ "indexer/service/protocol", "indexer/service/rpc", "explorer_service", - "programs/token/core", - "programs/token", "program_methods", "program_methods/guest", "test_program_methods", @@ -89,6 +87,7 @@ thiserror = "2.0.12" sha2 = "0.10.8" hex = "0.4.3" bytemuck = "1.24.0" +bytesize = { version = "2.3.1", features = ["serde"] } aes-gcm = "0.10.3" toml = "0.7.4" bincode = "1.3.3" diff --git a/common/Cargo.toml b/common/Cargo.toml index 2ef707f3..f7658304 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -18,6 +18,7 @@ sha2.workspace = true log.workspace = true hex.workspace = true borsh.workspace = true +bytesize.workspace = true base64.workspace = true url.workspace = true logos-blockchain-common-http-client.workspace = true diff --git a/configs/docker-all-in-one/sequencer/sequencer_config.json b/configs/docker-all-in-one/sequencer/sequencer_config.json index 579253dc..566e0e43 100644 --- a/configs/docker-all-in-one/sequencer/sequencer_config.json +++ b/configs/docker-all-in-one/sequencer/sequencer_config.json @@ -4,6 +4,7 @@ "genesis_id": 1, "is_genesis_random": true, "max_num_tx_in_block": 20, + "max_block_size": "1 MiB", "mempool_max_size": 10000, "block_create_timeout_millis": 10000, "retry_pending_blocks_timeout_millis": 7000, diff --git a/integration_tests/Cargo.toml b/integration_tests/Cargo.toml index 101488e0..ac14d183 100644 --- a/integration_tests/Cargo.toml +++ b/integration_tests/Cargo.toml @@ -28,5 +28,6 @@ tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } hex.workspace = true tempfile.workspace = true borsh.workspace = true +bytesize.workspace = true futures.workspace = true testcontainers = { version = "0.27.0", features = ["docker-compose"] } diff --git a/integration_tests/src/config.rs b/integration_tests/src/config.rs index 445929dd..730f3439 100644 --- a/integration_tests/src/config.rs +++ b/integration_tests/src/config.rs @@ -1,6 +1,7 @@ use std::{net::SocketAddr, path::PathBuf}; use anyhow::{Context, Result}; +use bytesize::ByteSize; use common::block::{AccountInitialData, CommitmentsInitialData}; use indexer_service::{BackoffConfig, ChannelId, ClientConfig, IndexerConfig}; use key_protocol::key_management::KeyChain; @@ -39,6 +40,7 @@ pub fn indexer_config( /// Sequencer config options available for custom changes in integration tests. pub struct SequencerPartialConfig { pub max_num_tx_in_block: usize, + pub max_block_size: ByteSize, pub mempool_max_size: usize, pub block_create_timeout_millis: u64, } @@ -47,6 +49,7 @@ impl Default for SequencerPartialConfig { fn default() -> Self { Self { max_num_tx_in_block: 20, + max_block_size: ByteSize::mib(1), mempool_max_size: 10_000, block_create_timeout_millis: 10_000, } @@ -62,6 +65,7 @@ pub fn sequencer_config( ) -> Result { let SequencerPartialConfig { max_num_tx_in_block, + max_block_size, mempool_max_size, block_create_timeout_millis, } = partial; @@ -72,6 +76,7 @@ pub fn sequencer_config( genesis_id: 1, is_genesis_random: true, max_num_tx_in_block, + max_block_size, mempool_max_size, block_create_timeout_millis, retry_pending_blocks_timeout_millis: 120_000, diff --git a/integration_tests/src/lib.rs b/integration_tests/src/lib.rs index abf72bfe..f0111735 100644 --- a/integration_tests/src/lib.rs +++ b/integration_tests/src/lib.rs @@ -21,6 +21,7 @@ pub mod config; // TODO: Remove this and control time from tests pub const TIME_TO_WAIT_FOR_BLOCK_SECONDS: u64 = 12; pub const NSSA_PROGRAM_FOR_TEST_DATA_CHANGER: &str = "data_changer.bin"; +pub const NSSA_PROGRAM_FOR_TEST_NOOP: &str = "noop.bin"; const BEDROCK_SERVICE_WITH_OPEN_PORT: &str = "logos-blockchain-node-0"; const BEDROCK_SERVICE_PORT: u16 = 18080; diff --git a/integration_tests/tests/block_size_limit.rs b/integration_tests/tests/block_size_limit.rs new file mode 100644 index 00000000..9b626452 --- /dev/null +++ b/integration_tests/tests/block_size_limit.rs @@ -0,0 +1,185 @@ +use std::time::Duration; + +use anyhow::Result; +use bytesize::ByteSize; +use common::{block::HashableBlockData, transaction::NSSATransaction}; +use integration_tests::{ + TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, config::SequencerPartialConfig, +}; +use nssa::program::Program; +use tokio::test; + +#[test] +async fn reject_oversized_transaction() -> Result<()> { + let ctx = TestContext::builder() + .with_sequencer_partial_config(SequencerPartialConfig { + max_num_tx_in_block: 100, + max_block_size: ByteSize::mib(1), + mempool_max_size: 1000, + block_create_timeout_millis: 10_000, + }) + .build() + .await?; + + // Create a transaction that's definitely too large + // Block size is 1 MiB (1,048,576 bytes), minus ~200 bytes for header = ~1,048,376 bytes max tx + // Create a 1.1 MiB binary to ensure it exceeds the limit + let oversized_binary = vec![0u8; 1100 * 1024]; // 1.1 MiB binary + + let message = nssa::program_deployment_transaction::Message::new(oversized_binary); + let tx = nssa::ProgramDeploymentTransaction::new(message); + + // Try to submit the transaction and expect an error + let result = ctx.sequencer_client().send_tx_program(tx).await; + + assert!( + result.is_err(), + "Expected error when submitting oversized transaction" + ); + + let err = result.unwrap_err(); + let err_str = format!("{:?}", err); + + // Check if the error contains information about transaction being too large + assert!( + err_str.contains("TransactionTooLarge") || err_str.contains("too large"), + "Expected TransactionTooLarge error, got: {}", + err_str + ); + + Ok(()) +} + +#[test] +async fn accept_transaction_within_limit() -> Result<()> { + let ctx = TestContext::builder() + .with_sequencer_partial_config(SequencerPartialConfig { + max_num_tx_in_block: 100, + max_block_size: ByteSize::mib(1), + mempool_max_size: 1000, + block_create_timeout_millis: 10_000, + }) + .build() + .await?; + + // Create a small program deployment that should fit + let small_binary = vec![0u8; 1024]; // 1 KiB binary + + let message = nssa::program_deployment_transaction::Message::new(small_binary); + let tx = nssa::ProgramDeploymentTransaction::new(message); + + // This should succeed + let result = ctx.sequencer_client().send_tx_program(tx).await; + + assert!( + result.is_ok(), + "Expected successful submission of small transaction, got error: {:?}", + result.as_ref().unwrap_err() + ); + + Ok(()) +} + +#[test] +async fn transaction_deferred_to_next_block_when_current_full() -> Result<()> { + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let artifacts_dir = + std::path::PathBuf::from(manifest_dir).join("../artifacts/test_program_methods"); + + let burner_bytecode = std::fs::read(artifacts_dir.join("burner.bin"))?; + let chain_caller_bytecode = std::fs::read(artifacts_dir.join("chain_caller.bin"))?; + + // Calculate block size to fit only one of the two transactions, leaving some room for headers + // (e.g., 10 KiB) + let max_program_size = burner_bytecode.len().max(chain_caller_bytecode.len()); + let block_size = ByteSize::b((max_program_size + 10 * 1024) as u64); + + let ctx = TestContext::builder() + .with_sequencer_partial_config(SequencerPartialConfig { + max_num_tx_in_block: 100, + max_block_size: block_size, + mempool_max_size: 1000, + block_create_timeout_millis: 10_000, + }) + .build() + .await?; + + let burner_id = Program::new(burner_bytecode.clone())?.id(); + let chain_caller_id = Program::new(chain_caller_bytecode.clone())?.id(); + + let initial_block_height = ctx.sequencer_client().get_last_block().await?.last_block; + + // Submit both program deployments + ctx.sequencer_client() + .send_tx_program(nssa::ProgramDeploymentTransaction::new( + nssa::program_deployment_transaction::Message::new(burner_bytecode), + )) + .await?; + + ctx.sequencer_client() + .send_tx_program(nssa::ProgramDeploymentTransaction::new( + nssa::program_deployment_transaction::Message::new(chain_caller_bytecode), + )) + .await?; + + // Wait for first block + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + let block1_response = ctx + .sequencer_client() + .get_block(initial_block_height + 1) + .await?; + let block1: HashableBlockData = borsh::from_slice(&block1_response.block)?; + + // Check which program is in block 1 + let get_program_ids = |block: &HashableBlockData| -> Vec { + block + .transactions + .iter() + .filter_map(|tx| { + if let NSSATransaction::ProgramDeployment(deployment) = tx { + let bytecode = deployment.message.clone().into_bytecode(); + Program::new(bytecode).ok().map(|p| p.id()) + } else { + None + } + }) + .collect() + }; + + let block1_program_ids = get_program_ids(&block1); + + // First program should be in block 1, but not both due to block size limit + assert_eq!( + block1_program_ids.len(), + 1, + "Expected exactly one program deployment in block 1" + ); + assert_eq!( + block1_program_ids[0], burner_id, + "Expected burner program to be deployed in block 1" + ); + + // Wait for second block + tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await; + + let block2_response = ctx + .sequencer_client() + .get_block(initial_block_height + 2) + .await?; + let block2: HashableBlockData = borsh::from_slice(&block2_response.block)?; + let block2_program_ids = get_program_ids(&block2); + + // The other program should be in block 2 + assert_eq!( + block2_program_ids.len(), + 1, + "Expected exactly one program deployment in block 2" + ); + assert_eq!( + block2_program_ids[0], chain_caller_id, + "Expected chain_caller program to be deployed in block 2" + ); + + Ok(()) +} diff --git a/integration_tests/tests/tps.rs b/integration_tests/tests/tps.rs index 2c58721e..19b6bcef 100644 --- a/integration_tests/tests/tps.rs +++ b/integration_tests/tests/tps.rs @@ -1,6 +1,7 @@ use std::time::{Duration, Instant}; use anyhow::Result; +use bytesize::ByteSize; use integration_tests::{ TestContext, config::{InitialData, SequencerPartialConfig}, @@ -178,6 +179,7 @@ impl TpsTestManager { fn generate_sequencer_partial_config() -> SequencerPartialConfig { SequencerPartialConfig { max_num_tx_in_block: 300, + max_block_size: ByteSize::mb(500), mempool_max_size: 10_000, block_create_timeout_millis: 12_000, } diff --git a/mempool/src/lib.rs b/mempool/src/lib.rs index ff6163ff..fae52b3e 100644 --- a/mempool/src/lib.rs +++ b/mempool/src/lib.rs @@ -2,13 +2,17 @@ use tokio::sync::mpsc::{Receiver, Sender}; pub struct MemPool { receiver: Receiver, + front_buffer: Vec, } impl MemPool { pub fn new(max_size: usize) -> (Self, MemPoolHandle) { let (sender, receiver) = tokio::sync::mpsc::channel(max_size); - let mem_pool = Self { receiver }; + let mem_pool = Self { + receiver, + front_buffer: Vec::new(), + }; let sender = MemPoolHandle::new(sender); (mem_pool, sender) } @@ -16,6 +20,13 @@ impl MemPool { pub fn pop(&mut self) -> Option { use tokio::sync::mpsc::error::TryRecvError; + // First check if there are any items in the front buffer (LIFO) + if let Some(item) = self.front_buffer.pop() { + return Some(item); + } + + // Otherwise, try to receive from the channel (FIFO) + match self.receiver.try_recv() { Ok(item) => Some(item), Err(TryRecvError::Empty) => None, @@ -24,6 +35,11 @@ impl MemPool { } } } + + /// Push an item to the front of the mempool (will be popped first) + pub fn push_front(&mut self, item: T) { + self.front_buffer.push(item); + } } pub struct MemPoolHandle { @@ -96,4 +112,24 @@ mod tests { assert_eq!(pool.pop(), Some(1)); assert_eq!(pool.pop(), Some(2)); } + + #[test] + async fn test_push_front() { + let (mut pool, handle) = MemPool::new(10); + + handle.push(1).await.unwrap(); + handle.push(2).await.unwrap(); + + // Push items to the front - these should be popped first + pool.push_front(10); + pool.push_front(20); + + // Items pushed to front are popped in LIFO order + assert_eq!(pool.pop(), Some(20)); + assert_eq!(pool.pop(), Some(10)); + // Original items are then popped in FIFO order + assert_eq!(pool.pop(), Some(1)); + assert_eq!(pool.pop(), Some(2)); + assert_eq!(pool.pop(), None); + } } diff --git a/nssa/src/merkle_tree/mod.rs b/nssa/src/merkle_tree/mod.rs index b3637b13..9c981b62 100644 --- a/nssa/src/merkle_tree/mod.rs +++ b/nssa/src/merkle_tree/mod.rs @@ -21,7 +21,7 @@ fn hash_value(value: &Value) -> Node { } #[cfg_attr(test, derive(Debug, PartialEq, Eq))] -#[derive(BorshSerialize, BorshDeserialize)] +#[derive(Clone, BorshSerialize, BorshDeserialize)] pub struct MerkleTree { nodes: Vec, capacity: usize, diff --git a/nssa/src/state.rs b/nssa/src/state.rs index f5ec2b46..e8d52be9 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -16,7 +16,7 @@ use crate::{ pub const MAX_NUMBER_CHAINED_CALLS: usize = 10; -#[derive(BorshSerialize, BorshDeserialize)] +#[derive(Clone, BorshSerialize, BorshDeserialize)] #[cfg_attr(test, derive(Debug, PartialEq, Eq))] pub(crate) struct CommitmentSet { merkle_tree: MerkleTree, @@ -64,6 +64,7 @@ impl CommitmentSet { } #[cfg_attr(test, derive(Debug, PartialEq, Eq))] +#[derive(Clone)] struct NullifierSet(BTreeSet); impl NullifierSet { @@ -104,7 +105,7 @@ impl BorshDeserialize for NullifierSet { } } -#[derive(BorshSerialize, BorshDeserialize)] +#[derive(Clone, BorshSerialize, BorshDeserialize)] #[cfg_attr(test, derive(Debug, PartialEq, Eq))] pub struct V02State { public_state: HashMap, diff --git a/sequencer_core/Cargo.toml b/sequencer_core/Cargo.toml index 870e22df..1a291830 100644 --- a/sequencer_core/Cargo.toml +++ b/sequencer_core/Cargo.toml @@ -24,6 +24,7 @@ logos-blockchain-key-management-system-service.workspace = true logos-blockchain-core.workspace = true rand.workspace = true borsh.workspace = true +bytesize.workspace = true url.workspace = true jsonrpsee = { workspace = true, features = ["ws-client"] } diff --git a/sequencer_core/src/config.rs b/sequencer_core/src/config.rs index 27175917..f8ebc57f 100644 --- a/sequencer_core/src/config.rs +++ b/sequencer_core/src/config.rs @@ -6,6 +6,7 @@ use std::{ use anyhow::Result; use bedrock_client::BackoffConfig; +use bytesize::ByteSize; use common::{ block::{AccountInitialData, CommitmentsInitialData}, config::BasicAuth, @@ -27,6 +28,9 @@ pub struct SequencerConfig { pub is_genesis_random: bool, /// Maximum number of transactions in block pub max_num_tx_in_block: usize, + /// Maximum block size (includes header and transactions) + #[serde(default = "default_max_block_size")] + pub max_block_size: ByteSize, /// Mempool maximum size pub mempool_max_size: usize, /// Interval in which blocks produced @@ -68,3 +72,7 @@ impl SequencerConfig { Ok(serde_json::from_reader(reader)?) } } + +fn default_max_block_size() -> ByteSize { + ByteSize::mib(1) +} diff --git a/sequencer_core/src/lib.rs b/sequencer_core/src/lib.rs index 525eb117..fffafc4a 100644 --- a/sequencer_core/src/lib.rs +++ b/sequencer_core/src/lib.rs @@ -48,6 +48,7 @@ pub struct SequencerCore< pub enum TransactionMalformationError { InvalidSignature, FailedToDecode { tx: HashType }, + TransactionTooLarge { size: usize, max: usize }, } impl Display for TransactionMalformationError { @@ -204,13 +205,49 @@ impl SequencerCore max_block_size { + // Block would exceed size limit, remove last transaction and push back + warn!( + "Transaction with hash {tx_hash} deferred to next block: \ + block size {block_size} bytes would exceed limit of {max_block_size} bytes", + ); + + self.mempool.push_front(tx); + break; + } + match self.execute_check_transaction_on_state(tx) { Ok(valid_tx) => { - info!("Validated transaction with hash {tx_hash}, including it in block",); valid_transactions.push(valid_tx); + info!("Validated transaction with hash {tx_hash}, including it in block"); + if valid_transactions.len() >= self.sequencer_config.max_num_tx_in_block { break; } @@ -224,13 +261,6 @@ impl SequencerCore { sequencer_state: Arc>>, mempool_handle: MemPoolHandle, + max_block_size: usize, } fn respond(val: T) -> Result { diff --git a/sequencer_rpc/src/net_utils.rs b/sequencer_rpc/src/net_utils.rs index ee9f6aa1..b2fd0dc7 100644 --- a/sequencer_rpc/src/net_utils.rs +++ b/sequencer_rpc/src/net_utils.rs @@ -52,7 +52,7 @@ fn get_cors(cors_allowed_origins: &[String]) -> Cors { .max_age(3600) } -pub fn new_http_server( +pub async fn new_http_server( config: RpcConfig, seuquencer_core: Arc>, mempool_handle: MemPoolHandle, @@ -63,9 +63,16 @@ pub fn new_http_server( limits_config, } = config; info!(target:NETWORK, "Starting HTTP server at {addr}"); + let max_block_size = seuquencer_core + .lock() + .await + .sequencer_config() + .max_block_size + .as_u64() as usize; let handler = web::Data::new(JsonHandler { sequencer_state: seuquencer_core.clone(), mempool_handle, + max_block_size, }); // HTTP server diff --git a/sequencer_rpc/src/process.rs b/sequencer_rpc/src/process.rs index f1173bce..b725b270 100644 --- a/sequencer_rpc/src/process.rs +++ b/sequencer_rpc/src/process.rs @@ -94,6 +94,27 @@ impl JsonHandler let tx = borsh::from_slice::(&send_tx_req.transaction).unwrap(); let tx_hash = tx.hash(); + // Check transaction size against block size limit + // Reserve ~200 bytes for block header overhead + const BLOCK_HEADER_OVERHEAD: usize = 200; + let tx_size = borsh::to_vec(&tx) + .map_err( + |_| sequencer_core::TransactionMalformationError::FailedToDecode { tx: tx_hash }, + )? + .len(); + + let max_tx_size = self.max_block_size.saturating_sub(BLOCK_HEADER_OVERHEAD); + + if tx_size > max_tx_size { + return Err( + sequencer_core::TransactionMalformationError::TransactionTooLarge { + size: tx_size, + max: max_tx_size, + } + .into(), + ); + } + let authenticated_tx = tx .transaction_stateless_check() .inspect_err(|err| warn!("Error at pre_check {err:#?}"))?; @@ -377,6 +398,7 @@ mod tests { genesis_id: 1, is_genesis_random: false, max_num_tx_in_block: 10, + max_block_size: bytesize::ByteSize::mib(1), mempool_max_size: 1000, block_create_timeout_millis: 1000, port: 8080, @@ -437,12 +459,14 @@ mod tests { .produce_new_block_with_mempool_transactions() .unwrap(); + let max_block_size = sequencer_core.sequencer_config().max_block_size.as_u64() as usize; let sequencer_core = Arc::new(Mutex::new(sequencer_core)); ( JsonHandlerWithMockClients { sequencer_state: sequencer_core, mempool_handle, + max_block_size, }, initial_accounts, tx, diff --git a/sequencer_rpc/src/types/err_rpc.rs b/sequencer_rpc/src/types/err_rpc.rs index f9f44051..92214c54 100644 --- a/sequencer_rpc/src/types/err_rpc.rs +++ b/sequencer_rpc/src/types/err_rpc.rs @@ -44,10 +44,7 @@ impl RpcErrKind for RpcErrInternal { impl RpcErrKind for TransactionMalformationError { fn into_rpc_err(self) -> RpcError { - RpcError::new_internal_error( - Some(serde_json::to_value(self).unwrap()), - "transaction not accepted", - ) + RpcError::invalid_params(Some(serde_json::to_value(self).unwrap())) } } diff --git a/sequencer_runner/configs/debug/sequencer_config.json b/sequencer_runner/configs/debug/sequencer_config.json index 3f8cce67..9c3505be 100644 --- a/sequencer_runner/configs/debug/sequencer_config.json +++ b/sequencer_runner/configs/debug/sequencer_config.json @@ -4,6 +4,7 @@ "genesis_id": 1, "is_genesis_random": true, "max_num_tx_in_block": 20, + "max_block_size": "1 MiB", "mempool_max_size": 1000, "block_create_timeout_millis": 15000, "retry_pending_blocks_timeout_millis": 5000, diff --git a/sequencer_runner/configs/docker/sequencer_config.json b/sequencer_runner/configs/docker/sequencer_config.json index 4dd817c9..cee02bd9 100644 --- a/sequencer_runner/configs/docker/sequencer_config.json +++ b/sequencer_runner/configs/docker/sequencer_config.json @@ -4,6 +4,7 @@ "genesis_id": 1, "is_genesis_random": true, "max_num_tx_in_block": 20, + "max_block_size": "1 MiB", "mempool_max_size": 10000, "block_create_timeout_millis": 10000, "port": 3040, diff --git a/sequencer_runner/src/lib.rs b/sequencer_runner/src/lib.rs index c80ae989..0b36f7b7 100644 --- a/sequencer_runner/src/lib.rs +++ b/sequencer_runner/src/lib.rs @@ -114,7 +114,8 @@ pub async fn startup_sequencer(app_config: SequencerConfig) -> Result