Skip to content

Commit

Permalink
reject transactions with size greater than max block size (#1852)
Browse files Browse the repository at this point in the history
Closes #1777

This PR

Rejects any transaction whose payload length is more than the max block
size. The max block size parameter is found in the chain config, which
can be updated through an upgrade. Therefore, we use the chain config
from the validated state first, as the validated state is the mutable
state of the node and the chain config, if present, will be the latest
chain config.

If the chain config is not present in the validated state, which may
occur if the node has not seen an upgrade, we use the chain config from
the node state. The node will automatically catch up and have an updated
chain config in the validated state when building the header for the
next block.
  • Loading branch information
imabdulbasit authored Aug 13, 2024
2 parents c35113d + c78bddd commit 45611f2
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 14 deletions.
4 changes: 3 additions & 1 deletion node-metrics/src/service/client_state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,7 @@ pub mod tests {
let (internal_client_message_sender, internal_client_message_receiver) = mpsc::channel(1);
let (server_message_sender_1, mut server_message_receiver_1) = mpsc::channel(1);
let (server_message_sender_2, mut server_message_receiver_2) = mpsc::channel(1);
let _process_internal_client_message_handle = InternalClientMessageProcessingTask::new(
let process_internal_client_message_handle = InternalClientMessageProcessingTask::new(
internal_client_message_receiver,
data_state,
client_thread_state,
Expand Down Expand Up @@ -1359,6 +1359,8 @@ pub mod tests {
voters_1, voters_2
]))),
);

drop(process_internal_client_message_handle)
}

#[async_std::test]
Expand Down
34 changes: 29 additions & 5 deletions sequencer/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,36 @@ impl<N: ConnectedNetwork<PubKey>, Ver: StaticVersionType + 'static, P: Sequencer
SubmitDataSource<N, P> for ApiState<N, P, Ver>
{
async fn submit(&self, tx: Transaction) -> anyhow::Result<()> {
self.consensus()
.await
.read()
let handle = self.consensus().await;

let consensus_read_lock = handle.read().await;

// Fetch full chain config from the validated state, if present.
// This is necessary because we support chain config upgrades,
// so the updated chain config is found in the validated state.
let cf = consensus_read_lock
.decided_state()
.await
.submit_transaction(tx)
.await?;
.chain_config
.resolve();

// Use the chain config from the validated state if available,
// otherwise, use the node state's chain config
// The node state's chain config is the node's base version chain config
let cf = match cf {
Some(cf) => cf,
None => self.node_state().await.chain_config,
};

let max_block_size: u64 = cf.max_block_size.into();
let txn_size = tx.payload().len() as u64;

// reject transaction bigger than block size
if txn_size > max_block_size {
bail!("transaction size ({txn_size}) is greater than max_block_size ({max_block_size})")
}

consensus_read_lock.submit_transaction(tx).await?;
Ok(())
}
}
Expand Down
12 changes: 4 additions & 8 deletions sequencer/src/bin/espresso-dev-node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,20 +672,16 @@ mod tests {
.await;
}

// Now the `submit/submit` endpoint allows the extremely large transactions to be in the mempool.
// And we need to check whether this extremely large transaction blocks the building process.
// Currently the default value of `max_block_size` is 30720, and this transaction exceeds the limit.
// TODO: https://github.com/EspressoSystems/espresso-sequencer/issues/1777
{
// transactions with size larger than max_block_size result in an error
let extremely_large_tx = Transaction::new(100_u32.into(), vec![0; 50120]);
let extremely_large_hash: Commitment<Transaction> = api_client
.post("submit/submit")
api_client
.post::<Commitment<Transaction>>("submit/submit")
.body_json(&extremely_large_tx)
.unwrap()
.send()
.await
.unwrap();
assert_eq!(extremely_large_tx.commit(), extremely_large_hash);
.unwrap_err();

// Now we send a small transaction to make sure this transaction can be included in a hotshot block.
let tx = Transaction::new(100_u32.into(), vec![0; 3]);
Expand Down

0 comments on commit 45611f2

Please sign in to comment.