Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement Optimistic block grpc streams #1709

Open
wants to merge 32 commits into
base: main
Choose a base branch
from

Conversation

bharath-123
Copy link
Contributor

@bharath-123 bharath-123 commented Oct 22, 2024

Summary

This PR implements the Optimistic block grpc stream apis protos of which were defined in #1519. These stream apis are used by auctioneer in order to optimistically simulate incoming bundles which are competing to be placed at the top-of-block for the given rollup.

Background

We have use cases where users of a given rollup would want to simulate a bundle on top of the latest block. The issue with simulating for rollup users is that the sequencer block times are too small and it would be difficult to simulate a bundle on top of the current latest block and submit it to the sequencer in time to get the bundle included in the next subsequent block.

To increase the time available for bundle simulation, the rollup can simulate on top of a block which has not yet been committed yet i.e a block which has not yet been finalized and is undergoing consensus.

This PR provides two grpc streams in order to enable that:

  1. getOptimisticBlockStream: This grpc method returns a stream given a rollup id. The returned stream produces the latest optimistic blocks which are blocks which have finished process_proposal.
  2. getBlockCommitmentStream: This grpc methods returns a stream which produces the block hash and block height of the latest committed blocks. These are blocks which have finished finalize_block.

The Optimistic block grpc streams are flagged behind ASTRIA_SEQUENCER_NO_OPTIMISTIC_BLOCKS. Ideally the grpc streams would run on a dedicated full node which is not validating.

Changes

  • Add ASTRIA_SEQUENCER_NO_OPTIMISTIC_BLOCKS to the sequencer environment which feature flags the optimistic block grpc streams
  • Add an EventBus which can be subscribed to, to listen to blocks undergoing consensus in process_proposal and blocks being finalized in finalize_block.
  • Add EventReceivers and EventSender types which are generic types which contains watches over which the specified data can be sent.
  • Add OptimisticBlockFacade which is the struct over which the optimistic block service apis are implemented.
  • Add OptimisticBlockServiceInner which is a struct which contains a Joinset of the stream tasks. This struct defines a long lived task which in turn spawns stream tasks on the joinset when clients try to subscribe to the optimistic block api streams.
  • Move start_grpc_server to crate::grpc::mod.rs and renamed it to start_server

Testing

Deployed a sequencer network locally and wrote a grpc client to read from the stream.

Related Issues

closes #1563

@github-actions github-actions bot added proto pertaining to the Astria Protobuf spec sequencer pertaining to the astria-sequencer crate labels Oct 22, 2024
@github-actions github-actions bot added the cd label Oct 22, 2024
.wrap_err("failed to run post execute transactions handler")?;

if let Some(optimistic_block_channels) = &self.optimistic_block_channels {
if let Err(e) = optimistic_block_channels
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we do not want to fail process_proposal if sending on the watch fails.

@@ -892,7 +952,7 @@ impl App {
proposer_address: account::Id,
txs: Vec<bytes::Bytes>,
tx_results: Vec<ExecTxResult>,
) -> Result<()> {
) -> Result<SequencerBlock> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this would be faster since we do not have again read the SequencerBlock from state when we want to send it via the optimistic block channels.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not change this function, at least for now. As mentioned below, you are not in fact writing or reading to disk at this point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bharath-123 What was the decision for this? Why did we decide to keep it for now instead of just reading it from the ephemeral state?

@@ -942,7 +1002,7 @@ impl App {
)
.wrap_err("failed to convert block info and data to SequencerBlock")?;
state_tx
.put_sequencer_block(sequencer_block)
.put_sequencer_block(sequencer_block.clone())
Copy link
Contributor Author

@bharath-123 bharath-123 Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this may or may not be a bad idea, since we are cloning a potentially big struct? In my mind, reads and writes to memory are much faster than disk but I do not have a proper understanding on how the statedb works in our sequencer app.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are not writing to disk. You are at most incurrring another deserialization step.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as for my comment above: we briefly discussed this, but I don't recall why we decided to clone the block here instead of reading it from the ephemeral state.

};

let (tx, rx) =
tokio::sync::mpsc::channel::<Result<GetOptimisticBlockStreamResponse, Status>>(128);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

128 seems arbitrary, but what is the best way to decide this number?

@bharath-123
Copy link
Contributor Author

This PR is blocked on #1707


match tx.send(Ok(get_optimistic_block_stream_response)).await {
Ok(()) => {
debug!("sent optimistic block");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we log this? this will log multiple times with each new listener of the stream.

@@ -1,5 +1,6 @@
pub mod block;
pub mod celestia;
pub mod optimistic_block;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final proto definitions are being worked on at #1707

@bharath-123 bharath-123 force-pushed the bharath/optimistic-sequencer-apis branch from 9ea11d9 to 1e06c3c Compare October 30, 2024 05:58
pub(crate) fn send_committed_block(&self, block: Option<SequencerBlockCommit>) {
if self.committed_block_sender().receiver_count() > 0 {
if let Err(e) = self.committed_block_sender.send(block) {
error!(error = %e, "failed to send committed block");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not error out process_proposal or finalize_block if sending a block on the watch fails

@bharath-123 bharath-123 marked this pull request as ready for review October 30, 2024 06:16
@bharath-123 bharath-123 requested review from a team as code owners October 30, 2024 06:16
@bharath-123 bharath-123 force-pushed the bharath/optimistic-sequencer-apis branch from d066e78 to b356f59 Compare December 13, 2024 05:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cd proto pertaining to the Astria Protobuf spec sequencer pertaining to the astria-sequencer crate
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Sequencer-side implementation for Optimistic Block
2 participants