From b91925a48e53181476e7e97ad122d81153b78616 Mon Sep 17 00:00:00 2001 From: itamar Date: Wed, 18 Sep 2024 16:58:21 -0400 Subject: [PATCH] add auctioneer draft move optimistic_block to sequencerblock remove prev_rollup_block_hash from BaseBlock move bundle service to executionapis request type for baseblock separate bundle service into OptimisticExecutionService and BundleService --- .../generated/astria.auctioneer.v1alpha1.rs | 498 ++++++++++++ .../astria.auctioneer.v1alpha1.serde.rs | 430 ++++++++++ .../src/generated/astria.bundle.v1alpha1.rs | 747 ++++++++++++++++++ .../generated/astria.bundle.v1alpha1.serde.rs | 559 +++++++++++++ .../astria.sequencerblock.v1alpha1.rs | 484 ++++++++++++ .../astria.sequencerblock.v1alpha1.serde.rs | 369 +++++++++ .../astria/bundle/v1alpha1/bundle.proto | 67 ++ .../v1alpha1/optimistic_block.proto | 35 + 8 files changed, 3189 insertions(+) create mode 100644 crates/astria-core/src/generated/astria.auctioneer.v1alpha1.rs create mode 100644 crates/astria-core/src/generated/astria.auctioneer.v1alpha1.serde.rs create mode 100644 crates/astria-core/src/generated/astria.bundle.v1alpha1.rs create mode 100644 crates/astria-core/src/generated/astria.bundle.v1alpha1.serde.rs create mode 100644 proto/executionapis/astria/bundle/v1alpha1/bundle.proto create mode 100644 proto/sequencerblockapis/astria/sequencerblock/v1alpha1/optimistic_block.proto diff --git a/crates/astria-core/src/generated/astria.auctioneer.v1alpha1.rs b/crates/astria-core/src/generated/astria.auctioneer.v1alpha1.rs new file mode 100644 index 0000000000..d9c5d91c2e --- /dev/null +++ b/crates/astria-core/src/generated/astria.auctioneer.v1alpha1.rs @@ -0,0 +1,498 @@ +/// Information for the bundle submitter to know how to submit the bundle. +/// The fee and base_sequencer_block_hash are not necessarily strictly necessary +/// it allows for the case where the server doesn't always send the highest fee +/// bundles after the previous but could just stream any confirmed bundles. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Bundle { + /// The fee that can be expected to be received for submitting this bundle. + /// This allows the bundle producer to stream any confirmed bundles they would be ok + /// with submitting. Used to avoid race conditions in received bundle packets. Could + /// also be used by a bundle submitter to allow multiple entities to submit bundles. + #[prost(uint64, tag = "1")] + pub fee: u64, + /// The byte list of transactions to be included. + #[prost(bytes = "bytes", repeated, tag = "2")] + pub transactions: ::prost::alloc::vec::Vec<::prost::bytes::Bytes>, + /// The base_sequencer_block_hash is the hash from the base block this bundle + /// is based on. This is used to verify that the bundle is based on the correct + /// Sequencer block. + #[prost(bytes = "bytes", tag = "3")] + pub base_sequencer_block_hash: ::prost::bytes::Bytes, + /// The hash of previous rollup block, on top of which the bundle will be executed as ToB. + #[prost(bytes = "bytes", tag = "4")] + pub prev_rollup_block_hash: ::prost::bytes::Bytes, +} +impl ::prost::Name for Bundle { + const NAME: &'static str = "Bundle"; + const PACKAGE: &'static str = "astria.auctioneer.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.auctioneer.v1alpha1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamExecuteOptimisticBlockRequest { + #[prost(message, optional, tag = "1")] + pub base_block: ::core::option::Option< + super::super::sequencerblock::v1alpha1::BaseBlock, + >, +} +impl ::prost::Name for StreamExecuteOptimisticBlockRequest { + const NAME: &'static str = "StreamExecuteOptimisticBlockRequest"; + const PACKAGE: &'static str = "astria.auctioneer.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.auctioneer.v1alpha1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamExecuteOptimisticBlockResponse { + #[prost(message, optional, tag = "1")] + pub block: ::core::option::Option, +} +impl ::prost::Name for StreamExecuteOptimisticBlockResponse { + const NAME: &'static str = "StreamExecuteOptimisticBlockResponse"; + const PACKAGE: &'static str = "astria.auctioneer.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.auctioneer.v1alpha1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamBundlesRequest { + #[prost(message, optional, tag = "1")] + pub empty: ::core::option::Option<::pbjson_types::Empty>, +} +impl ::prost::Name for StreamBundlesRequest { + const NAME: &'static str = "StreamBundlesRequest"; + const PACKAGE: &'static str = "astria.auctioneer.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.auctioneer.v1alpha1.{}", Self::NAME) + } +} +/// Generated client implementations. +#[cfg(feature = "client")] +pub mod bundle_service_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// Geth will serve this to the Auctioneer + #[derive(Debug, Clone)] + pub struct BundleServiceClient { + inner: tonic::client::Grpc, + } + impl BundleServiceClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl BundleServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> BundleServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + BundleServiceClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Stream blocks from the Auctioneer to Geth for optimistic execution. Geth will stream back + /// metadata from the executed blocks. + pub async fn stream_execute_optimistic_block( + &mut self, + request: impl tonic::IntoStreamingRequest< + Message = super::StreamExecuteOptimisticBlockRequest, + >, + ) -> std::result::Result< + tonic::Response< + tonic::codec::Streaming, + >, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/astria.auctioneer.v1alpha1.BundleService/StreamExecuteOptimisticBlock", + ); + let mut req = request.into_streaming_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "astria.auctioneer.v1alpha1.BundleService", + "StreamExecuteOptimisticBlock", + ), + ); + self.inner.streaming(req, path, codec).await + } + /// A bundle submitter requests bundles given a new optimistic Sequencer block, + /// and receives a stream of potential bundles for submission, until either a timeout + /// or the connection is closed by the client. + pub async fn stream_bundles( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/astria.auctioneer.v1alpha1.BundleService/StreamBundles", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "astria.auctioneer.v1alpha1.BundleService", + "StreamBundles", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + } +} +/// Generated server implementations. +#[cfg(feature = "server")] +pub mod bundle_service_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with BundleServiceServer. + #[async_trait] + pub trait BundleService: Send + Sync + 'static { + /// Server streaming response type for the StreamExecuteOptimisticBlock method. + type StreamExecuteOptimisticBlockStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result< + super::StreamExecuteOptimisticBlockResponse, + tonic::Status, + >, + > + + Send + + 'static; + /// Stream blocks from the Auctioneer to Geth for optimistic execution. Geth will stream back + /// metadata from the executed blocks. + async fn stream_execute_optimistic_block( + self: std::sync::Arc, + request: tonic::Request< + tonic::Streaming, + >, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Server streaming response type for the StreamBundles method. + type StreamBundlesStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + Send + + 'static; + /// A bundle submitter requests bundles given a new optimistic Sequencer block, + /// and receives a stream of potential bundles for submission, until either a timeout + /// or the connection is closed by the client. + async fn stream_bundles( + self: std::sync::Arc, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + /// Geth will serve this to the Auctioneer + #[derive(Debug)] + pub struct BundleServiceServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl BundleServiceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for BundleServiceServer + where + T: BundleService, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/astria.auctioneer.v1alpha1.BundleService/StreamExecuteOptimisticBlock" => { + #[allow(non_camel_case_types)] + struct StreamExecuteOptimisticBlockSvc(pub Arc); + impl< + T: BundleService, + > tonic::server::StreamingService< + super::StreamExecuteOptimisticBlockRequest, + > for StreamExecuteOptimisticBlockSvc { + type Response = super::StreamExecuteOptimisticBlockResponse; + type ResponseStream = T::StreamExecuteOptimisticBlockStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + tonic::Streaming, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::stream_execute_optimistic_block( + inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = StreamExecuteOptimisticBlockSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/astria.auctioneer.v1alpha1.BundleService/StreamBundles" => { + #[allow(non_camel_case_types)] + struct StreamBundlesSvc(pub Arc); + impl< + T: BundleService, + > tonic::server::ServerStreamingService + for StreamBundlesSvc { + type Response = super::Bundle; + type ResponseStream = T::StreamBundlesStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::stream_bundles(inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = StreamBundlesSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for BundleServiceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for BundleServiceServer { + const NAME: &'static str = "astria.auctioneer.v1alpha1.BundleService"; + } +} diff --git a/crates/astria-core/src/generated/astria.auctioneer.v1alpha1.serde.rs b/crates/astria-core/src/generated/astria.auctioneer.v1alpha1.serde.rs new file mode 100644 index 0000000000..ba3ee436fe --- /dev/null +++ b/crates/astria-core/src/generated/astria.auctioneer.v1alpha1.serde.rs @@ -0,0 +1,430 @@ +impl serde::Serialize for Bundle { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.fee != 0 { + len += 1; + } + if !self.transactions.is_empty() { + len += 1; + } + if !self.base_sequencer_block_hash.is_empty() { + len += 1; + } + if !self.prev_rollup_block_hash.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.auctioneer.v1alpha1.Bundle", len)?; + if self.fee != 0 { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("fee", ToString::to_string(&self.fee).as_str())?; + } + if !self.transactions.is_empty() { + struct_ser.serialize_field("transactions", &self.transactions.iter().map(pbjson::private::base64::encode).collect::>())?; + } + if !self.base_sequencer_block_hash.is_empty() { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("baseSequencerBlockHash", pbjson::private::base64::encode(&self.base_sequencer_block_hash).as_str())?; + } + if !self.prev_rollup_block_hash.is_empty() { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("prevRollupBlockHash", pbjson::private::base64::encode(&self.prev_rollup_block_hash).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for Bundle { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "fee", + "transactions", + "base_sequencer_block_hash", + "baseSequencerBlockHash", + "prev_rollup_block_hash", + "prevRollupBlockHash", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Fee, + Transactions, + BaseSequencerBlockHash, + PrevRollupBlockHash, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "fee" => Ok(GeneratedField::Fee), + "transactions" => Ok(GeneratedField::Transactions), + "baseSequencerBlockHash" | "base_sequencer_block_hash" => Ok(GeneratedField::BaseSequencerBlockHash), + "prevRollupBlockHash" | "prev_rollup_block_hash" => Ok(GeneratedField::PrevRollupBlockHash), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = Bundle; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.auctioneer.v1alpha1.Bundle") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut fee__ = None; + let mut transactions__ = None; + let mut base_sequencer_block_hash__ = None; + let mut prev_rollup_block_hash__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Fee => { + if fee__.is_some() { + return Err(serde::de::Error::duplicate_field("fee")); + } + fee__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Transactions => { + if transactions__.is_some() { + return Err(serde::de::Error::duplicate_field("transactions")); + } + transactions__ = + Some(map_.next_value::>>()? + .into_iter().map(|x| x.0).collect()) + ; + } + GeneratedField::BaseSequencerBlockHash => { + if base_sequencer_block_hash__.is_some() { + return Err(serde::de::Error::duplicate_field("baseSequencerBlockHash")); + } + base_sequencer_block_hash__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::PrevRollupBlockHash => { + if prev_rollup_block_hash__.is_some() { + return Err(serde::de::Error::duplicate_field("prevRollupBlockHash")); + } + prev_rollup_block_hash__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + } + } + Ok(Bundle { + fee: fee__.unwrap_or_default(), + transactions: transactions__.unwrap_or_default(), + base_sequencer_block_hash: base_sequencer_block_hash__.unwrap_or_default(), + prev_rollup_block_hash: prev_rollup_block_hash__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("astria.auctioneer.v1alpha1.Bundle", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for StreamBundlesRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.empty.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.auctioneer.v1alpha1.StreamBundlesRequest", len)?; + if let Some(v) = self.empty.as_ref() { + struct_ser.serialize_field("empty", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for StreamBundlesRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "empty", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Empty, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "empty" => Ok(GeneratedField::Empty), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = StreamBundlesRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.auctioneer.v1alpha1.StreamBundlesRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut empty__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Empty => { + if empty__.is_some() { + return Err(serde::de::Error::duplicate_field("empty")); + } + empty__ = map_.next_value()?; + } + } + } + Ok(StreamBundlesRequest { + empty: empty__, + }) + } + } + deserializer.deserialize_struct("astria.auctioneer.v1alpha1.StreamBundlesRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for StreamExecuteOptimisticBlockRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.base_block.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.auctioneer.v1alpha1.StreamExecuteOptimisticBlockRequest", len)?; + if let Some(v) = self.base_block.as_ref() { + struct_ser.serialize_field("baseBlock", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for StreamExecuteOptimisticBlockRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "base_block", + "baseBlock", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + BaseBlock, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "baseBlock" | "base_block" => Ok(GeneratedField::BaseBlock), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = StreamExecuteOptimisticBlockRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.auctioneer.v1alpha1.StreamExecuteOptimisticBlockRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut base_block__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::BaseBlock => { + if base_block__.is_some() { + return Err(serde::de::Error::duplicate_field("baseBlock")); + } + base_block__ = map_.next_value()?; + } + } + } + Ok(StreamExecuteOptimisticBlockRequest { + base_block: base_block__, + }) + } + } + deserializer.deserialize_struct("astria.auctioneer.v1alpha1.StreamExecuteOptimisticBlockRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for StreamExecuteOptimisticBlockResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.block.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.auctioneer.v1alpha1.StreamExecuteOptimisticBlockResponse", len)?; + if let Some(v) = self.block.as_ref() { + struct_ser.serialize_field("block", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for StreamExecuteOptimisticBlockResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "block", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Block, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "block" => Ok(GeneratedField::Block), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = StreamExecuteOptimisticBlockResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.auctioneer.v1alpha1.StreamExecuteOptimisticBlockResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut block__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Block => { + if block__.is_some() { + return Err(serde::de::Error::duplicate_field("block")); + } + block__ = map_.next_value()?; + } + } + } + Ok(StreamExecuteOptimisticBlockResponse { + block: block__, + }) + } + } + deserializer.deserialize_struct("astria.auctioneer.v1alpha1.StreamExecuteOptimisticBlockResponse", FIELDS, GeneratedVisitor) + } +} diff --git a/crates/astria-core/src/generated/astria.bundle.v1alpha1.rs b/crates/astria-core/src/generated/astria.bundle.v1alpha1.rs new file mode 100644 index 0000000000..70380401fb --- /dev/null +++ b/crates/astria-core/src/generated/astria.bundle.v1alpha1.rs @@ -0,0 +1,747 @@ +/// The "BaseBlock" is the information needed to simulate bundles on top of +/// a Sequencer block which may not have been committed yet. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BaseBlock { + /// This is the block hash for the proposed block. + #[prost(bytes = "bytes", tag = "1")] + pub sequencer_block_hash: ::prost::bytes::Bytes, + /// List of transactions to include in the new block. + #[prost(message, repeated, tag = "2")] + pub transactions: ::prost::alloc::vec::Vec< + super::super::sequencerblock::v1alpha1::RollupData, + >, + /// Timestamp to be used for new block. + #[prost(message, optional, tag = "3")] + pub timestamp: ::core::option::Option<::pbjson_types::Timestamp>, +} +impl ::prost::Name for BaseBlock { + const NAME: &'static str = "BaseBlock"; + const PACKAGE: &'static str = "astria.bundle.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.bundle.v1alpha1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamExecuteOptimisticBlockRequest { + #[prost(message, optional, tag = "1")] + pub block: ::core::option::Option, +} +impl ::prost::Name for StreamExecuteOptimisticBlockRequest { + const NAME: &'static str = "StreamExecuteOptimisticBlockRequest"; + const PACKAGE: &'static str = "astria.bundle.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.bundle.v1alpha1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamExecuteOptimisticBlockResponse { + /// Metadata identifying the block resulting from executing a block. Includes number, hash, + /// parent hash and timestamp. + #[prost(message, optional, tag = "1")] + pub block: ::core::option::Option, + /// The base_sequencer_block_hash is the hash from the base sequencer block this block + /// is based on. This is used to associate an optimistic execution result with the hash + /// received once a sequencer block is committed. + #[prost(bytes = "bytes", tag = "2")] + pub base_sequencer_block_hash: ::prost::bytes::Bytes, +} +impl ::prost::Name for StreamExecuteOptimisticBlockResponse { + const NAME: &'static str = "StreamExecuteOptimisticBlockResponse"; + const PACKAGE: &'static str = "astria.bundle.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.bundle.v1alpha1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamBundlesRequest {} +impl ::prost::Name for StreamBundlesRequest { + const NAME: &'static str = "StreamBundlesRequest"; + const PACKAGE: &'static str = "astria.bundle.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.bundle.v1alpha1.{}", Self::NAME) + } +} +/// Information for the bundle submitter to know how to submit the bundle. +/// The fee and base_sequencer_block_hash are not necessarily strictly necessary +/// it allows for the case where the server doesn't always send the highest fee +/// bundles after the previous but could just stream any confirmed bundles. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Bundle { + /// The fee that can be expected to be received for submitting this bundle. + /// This allows the bundle producer to stream any confirmed bundles they would be ok + /// with submitting. Used to avoid race conditions in received bundle packets. Could + /// also be used by a bundle submitter to allow multiple entities to submit bundles. + #[prost(uint64, tag = "1")] + pub fee: u64, + /// The byte list of transactions to be included. + #[prost(bytes = "bytes", repeated, tag = "2")] + pub transactions: ::prost::alloc::vec::Vec<::prost::bytes::Bytes>, + /// The base_sequencer_block_hash is the hash from the base block this bundle + /// is based on. This is used to verify that the bundle is based on the correct + /// Sequencer block. + #[prost(bytes = "bytes", tag = "3")] + pub base_sequencer_block_hash: ::prost::bytes::Bytes, + /// The hash of previous rollup block, on top of which the bundle will be executed as ToB. + #[prost(bytes = "bytes", tag = "4")] + pub prev_rollup_block_hash: ::prost::bytes::Bytes, +} +impl ::prost::Name for Bundle { + const NAME: &'static str = "Bundle"; + const PACKAGE: &'static str = "astria.bundle.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.bundle.v1alpha1.{}", Self::NAME) + } +} +/// Generated client implementations. +#[cfg(feature = "client")] +pub mod optimistic_execution_service_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct OptimisticExecutionServiceClient { + inner: tonic::client::Grpc, + } + impl OptimisticExecutionServiceClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl OptimisticExecutionServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> OptimisticExecutionServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + OptimisticExecutionServiceClient::new( + InterceptedService::new(inner, interceptor), + ) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// Stream blocks from the Auctioneer to Geth for optimistic execution. Geth will stream back + /// metadata from the executed blocks. + pub async fn stream_execute_optimistic_block( + &mut self, + request: impl tonic::IntoStreamingRequest< + Message = super::StreamExecuteOptimisticBlockRequest, + >, + ) -> std::result::Result< + tonic::Response< + tonic::codec::Streaming, + >, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/astria.bundle.v1alpha1.OptimisticExecutionService/StreamExecuteOptimisticBlock", + ); + let mut req = request.into_streaming_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "astria.bundle.v1alpha1.OptimisticExecutionService", + "StreamExecuteOptimisticBlock", + ), + ); + self.inner.streaming(req, path, codec).await + } + } +} +/// Generated client implementations. +#[cfg(feature = "client")] +pub mod bundle_service_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct BundleServiceClient { + inner: tonic::client::Grpc, + } + impl BundleServiceClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl BundleServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> BundleServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + BundleServiceClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// A bundle submitter requests bundles given a new optimistic Sequencer block, + /// and receives a stream of potential bundles for submission, until either a timeout + /// or the connection is closed by the client. + pub async fn stream_bundles( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/astria.bundle.v1alpha1.BundleService/StreamBundles", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "astria.bundle.v1alpha1.BundleService", + "StreamBundles", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + } +} +/// Generated server implementations. +#[cfg(feature = "server")] +pub mod optimistic_execution_service_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with OptimisticExecutionServiceServer. + #[async_trait] + pub trait OptimisticExecutionService: Send + Sync + 'static { + /// Server streaming response type for the StreamExecuteOptimisticBlock method. + type StreamExecuteOptimisticBlockStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result< + super::StreamExecuteOptimisticBlockResponse, + tonic::Status, + >, + > + + Send + + 'static; + /// Stream blocks from the Auctioneer to Geth for optimistic execution. Geth will stream back + /// metadata from the executed blocks. + async fn stream_execute_optimistic_block( + self: std::sync::Arc, + request: tonic::Request< + tonic::Streaming, + >, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct OptimisticExecutionServiceServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl OptimisticExecutionServiceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> + for OptimisticExecutionServiceServer + where + T: OptimisticExecutionService, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/astria.bundle.v1alpha1.OptimisticExecutionService/StreamExecuteOptimisticBlock" => { + #[allow(non_camel_case_types)] + struct StreamExecuteOptimisticBlockSvc< + T: OptimisticExecutionService, + >( + pub Arc, + ); + impl< + T: OptimisticExecutionService, + > tonic::server::StreamingService< + super::StreamExecuteOptimisticBlockRequest, + > for StreamExecuteOptimisticBlockSvc { + type Response = super::StreamExecuteOptimisticBlockResponse; + type ResponseStream = T::StreamExecuteOptimisticBlockStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + tonic::Streaming, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::stream_execute_optimistic_block( + inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = StreamExecuteOptimisticBlockSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for OptimisticExecutionServiceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService + for OptimisticExecutionServiceServer { + const NAME: &'static str = "astria.bundle.v1alpha1.OptimisticExecutionService"; + } +} +/// Generated server implementations. +#[cfg(feature = "server")] +pub mod bundle_service_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with BundleServiceServer. + #[async_trait] + pub trait BundleService: Send + Sync + 'static { + /// Server streaming response type for the StreamBundles method. + type StreamBundlesStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + Send + + 'static; + /// A bundle submitter requests bundles given a new optimistic Sequencer block, + /// and receives a stream of potential bundles for submission, until either a timeout + /// or the connection is closed by the client. + async fn stream_bundles( + self: std::sync::Arc, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct BundleServiceServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl BundleServiceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for BundleServiceServer + where + T: BundleService, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/astria.bundle.v1alpha1.BundleService/StreamBundles" => { + #[allow(non_camel_case_types)] + struct StreamBundlesSvc(pub Arc); + impl< + T: BundleService, + > tonic::server::ServerStreamingService + for StreamBundlesSvc { + type Response = super::Bundle; + type ResponseStream = T::StreamBundlesStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::stream_bundles(inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = StreamBundlesSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for BundleServiceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for BundleServiceServer { + const NAME: &'static str = "astria.bundle.v1alpha1.BundleService"; + } +} diff --git a/crates/astria-core/src/generated/astria.bundle.v1alpha1.serde.rs b/crates/astria-core/src/generated/astria.bundle.v1alpha1.serde.rs new file mode 100644 index 0000000000..dab3fd07a2 --- /dev/null +++ b/crates/astria-core/src/generated/astria.bundle.v1alpha1.serde.rs @@ -0,0 +1,559 @@ +impl serde::Serialize for BaseBlock { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.sequencer_block_hash.is_empty() { + len += 1; + } + if !self.transactions.is_empty() { + len += 1; + } + if self.timestamp.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.bundle.v1alpha1.BaseBlock", len)?; + if !self.sequencer_block_hash.is_empty() { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("sequencerBlockHash", pbjson::private::base64::encode(&self.sequencer_block_hash).as_str())?; + } + if !self.transactions.is_empty() { + struct_ser.serialize_field("transactions", &self.transactions)?; + } + if let Some(v) = self.timestamp.as_ref() { + struct_ser.serialize_field("timestamp", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for BaseBlock { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "sequencer_block_hash", + "sequencerBlockHash", + "transactions", + "timestamp", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + SequencerBlockHash, + Transactions, + Timestamp, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "sequencerBlockHash" | "sequencer_block_hash" => Ok(GeneratedField::SequencerBlockHash), + "transactions" => Ok(GeneratedField::Transactions), + "timestamp" => Ok(GeneratedField::Timestamp), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = BaseBlock; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.bundle.v1alpha1.BaseBlock") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut sequencer_block_hash__ = None; + let mut transactions__ = None; + let mut timestamp__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::SequencerBlockHash => { + if sequencer_block_hash__.is_some() { + return Err(serde::de::Error::duplicate_field("sequencerBlockHash")); + } + sequencer_block_hash__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::Transactions => { + if transactions__.is_some() { + return Err(serde::de::Error::duplicate_field("transactions")); + } + transactions__ = Some(map_.next_value()?); + } + GeneratedField::Timestamp => { + if timestamp__.is_some() { + return Err(serde::de::Error::duplicate_field("timestamp")); + } + timestamp__ = map_.next_value()?; + } + } + } + Ok(BaseBlock { + sequencer_block_hash: sequencer_block_hash__.unwrap_or_default(), + transactions: transactions__.unwrap_or_default(), + timestamp: timestamp__, + }) + } + } + deserializer.deserialize_struct("astria.bundle.v1alpha1.BaseBlock", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for Bundle { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.fee != 0 { + len += 1; + } + if !self.transactions.is_empty() { + len += 1; + } + if !self.base_sequencer_block_hash.is_empty() { + len += 1; + } + if !self.prev_rollup_block_hash.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.bundle.v1alpha1.Bundle", len)?; + if self.fee != 0 { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("fee", ToString::to_string(&self.fee).as_str())?; + } + if !self.transactions.is_empty() { + struct_ser.serialize_field("transactions", &self.transactions.iter().map(pbjson::private::base64::encode).collect::>())?; + } + if !self.base_sequencer_block_hash.is_empty() { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("baseSequencerBlockHash", pbjson::private::base64::encode(&self.base_sequencer_block_hash).as_str())?; + } + if !self.prev_rollup_block_hash.is_empty() { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("prevRollupBlockHash", pbjson::private::base64::encode(&self.prev_rollup_block_hash).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for Bundle { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "fee", + "transactions", + "base_sequencer_block_hash", + "baseSequencerBlockHash", + "prev_rollup_block_hash", + "prevRollupBlockHash", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Fee, + Transactions, + BaseSequencerBlockHash, + PrevRollupBlockHash, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "fee" => Ok(GeneratedField::Fee), + "transactions" => Ok(GeneratedField::Transactions), + "baseSequencerBlockHash" | "base_sequencer_block_hash" => Ok(GeneratedField::BaseSequencerBlockHash), + "prevRollupBlockHash" | "prev_rollup_block_hash" => Ok(GeneratedField::PrevRollupBlockHash), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = Bundle; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.bundle.v1alpha1.Bundle") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut fee__ = None; + let mut transactions__ = None; + let mut base_sequencer_block_hash__ = None; + let mut prev_rollup_block_hash__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Fee => { + if fee__.is_some() { + return Err(serde::de::Error::duplicate_field("fee")); + } + fee__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Transactions => { + if transactions__.is_some() { + return Err(serde::de::Error::duplicate_field("transactions")); + } + transactions__ = + Some(map_.next_value::>>()? + .into_iter().map(|x| x.0).collect()) + ; + } + GeneratedField::BaseSequencerBlockHash => { + if base_sequencer_block_hash__.is_some() { + return Err(serde::de::Error::duplicate_field("baseSequencerBlockHash")); + } + base_sequencer_block_hash__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::PrevRollupBlockHash => { + if prev_rollup_block_hash__.is_some() { + return Err(serde::de::Error::duplicate_field("prevRollupBlockHash")); + } + prev_rollup_block_hash__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + } + } + Ok(Bundle { + fee: fee__.unwrap_or_default(), + transactions: transactions__.unwrap_or_default(), + base_sequencer_block_hash: base_sequencer_block_hash__.unwrap_or_default(), + prev_rollup_block_hash: prev_rollup_block_hash__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("astria.bundle.v1alpha1.Bundle", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for StreamBundlesRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let len = 0; + let struct_ser = serializer.serialize_struct("astria.bundle.v1alpha1.StreamBundlesRequest", len)?; + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for StreamBundlesRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + Err(serde::de::Error::unknown_field(value, FIELDS)) + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = StreamBundlesRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.bundle.v1alpha1.StreamBundlesRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + while map_.next_key::()?.is_some() { + let _ = map_.next_value::()?; + } + Ok(StreamBundlesRequest { + }) + } + } + deserializer.deserialize_struct("astria.bundle.v1alpha1.StreamBundlesRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for StreamExecuteOptimisticBlockRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.block.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.bundle.v1alpha1.StreamExecuteOptimisticBlockRequest", len)?; + if let Some(v) = self.block.as_ref() { + struct_ser.serialize_field("block", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for StreamExecuteOptimisticBlockRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "block", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Block, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "block" => Ok(GeneratedField::Block), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = StreamExecuteOptimisticBlockRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.bundle.v1alpha1.StreamExecuteOptimisticBlockRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut block__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Block => { + if block__.is_some() { + return Err(serde::de::Error::duplicate_field("block")); + } + block__ = map_.next_value()?; + } + } + } + Ok(StreamExecuteOptimisticBlockRequest { + block: block__, + }) + } + } + deserializer.deserialize_struct("astria.bundle.v1alpha1.StreamExecuteOptimisticBlockRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for StreamExecuteOptimisticBlockResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.block.is_some() { + len += 1; + } + if !self.base_sequencer_block_hash.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.bundle.v1alpha1.StreamExecuteOptimisticBlockResponse", len)?; + if let Some(v) = self.block.as_ref() { + struct_ser.serialize_field("block", v)?; + } + if !self.base_sequencer_block_hash.is_empty() { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("baseSequencerBlockHash", pbjson::private::base64::encode(&self.base_sequencer_block_hash).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for StreamExecuteOptimisticBlockResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "block", + "base_sequencer_block_hash", + "baseSequencerBlockHash", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Block, + BaseSequencerBlockHash, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "block" => Ok(GeneratedField::Block), + "baseSequencerBlockHash" | "base_sequencer_block_hash" => Ok(GeneratedField::BaseSequencerBlockHash), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = StreamExecuteOptimisticBlockResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.bundle.v1alpha1.StreamExecuteOptimisticBlockResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut block__ = None; + let mut base_sequencer_block_hash__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Block => { + if block__.is_some() { + return Err(serde::de::Error::duplicate_field("block")); + } + block__ = map_.next_value()?; + } + GeneratedField::BaseSequencerBlockHash => { + if base_sequencer_block_hash__.is_some() { + return Err(serde::de::Error::duplicate_field("baseSequencerBlockHash")); + } + base_sequencer_block_hash__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + } + } + Ok(StreamExecuteOptimisticBlockResponse { + block: block__, + base_sequencer_block_hash: base_sequencer_block_hash__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("astria.bundle.v1alpha1.StreamExecuteOptimisticBlockResponse", FIELDS, GeneratedVisitor) + } +} diff --git a/crates/astria-core/src/generated/astria.sequencerblock.v1alpha1.rs b/crates/astria-core/src/generated/astria.sequencerblock.v1alpha1.rs index 56385a3ca7..4c42a1cb95 100644 --- a/crates/astria-core/src/generated/astria.sequencerblock.v1alpha1.rs +++ b/crates/astria-core/src/generated/astria.sequencerblock.v1alpha1.rs @@ -330,6 +330,490 @@ impl ::prost::Name for SubmittedMetadata { } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamBlockCommitmentsRequest {} +impl ::prost::Name for StreamBlockCommitmentsRequest { + const NAME: &'static str = "StreamBlockCommitmentsRequest"; + const PACKAGE: &'static str = "astria.sequencerblock.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.sequencerblock.v1alpha1.{}", Self::NAME) + } +} +/// Identifying metadata for blocks that have been successfully committed in the Sequencer. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SequencerBlockCommit { + /// Height of the sequencer block that was committed. + #[prost(uint64, tag = "1")] + pub height: u64, + /// Hash of the sequencer block that was committed. + #[prost(bytes = "bytes", tag = "2")] + pub block_hash: ::prost::bytes::Bytes, +} +impl ::prost::Name for SequencerBlockCommit { + const NAME: &'static str = "SequencerBlockCommit"; + const PACKAGE: &'static str = "astria.sequencerblock.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.sequencerblock.v1alpha1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamOptimisticBlockRequest { + /// The rollup id for which the Sequencer block is being streamed. + #[prost(message, optional, tag = "1")] + pub rollup_id: ::core::option::Option, +} +impl ::prost::Name for StreamOptimisticBlockRequest { + const NAME: &'static str = "StreamOptimisticBlockRequest"; + const PACKAGE: &'static str = "astria.sequencerblock.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.sequencerblock.v1alpha1.{}", Self::NAME) + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamOptimisticBlockResponse { + /// The optimistic Sequencer block that is being streamed, filtered for the provided rollup id. + #[prost(message, optional, tag = "1")] + pub block: ::core::option::Option, +} +impl ::prost::Name for StreamOptimisticBlockResponse { + const NAME: &'static str = "StreamOptimisticBlockResponse"; + const PACKAGE: &'static str = "astria.sequencerblock.v1alpha1"; + fn full_name() -> ::prost::alloc::string::String { + ::prost::alloc::format!("astria.sequencerblock.v1alpha1.{}", Self::NAME) + } +} +/// Generated client implementations. +#[cfg(feature = "client")] +pub mod optimistic_block_service_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + /// The Sequencer will serve this to the aucitoneer + #[derive(Debug, Clone)] + pub struct OptimisticBlockServiceClient { + inner: tonic::client::Grpc, + } + impl OptimisticBlockServiceClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl OptimisticBlockServiceClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> OptimisticBlockServiceClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + OptimisticBlockServiceClient::new( + InterceptedService::new(inner, interceptor), + ) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + /// The Sequencer will stream the optimistic Sequencer block (filtered for the provided + /// rollup id) to the Auctioneer. + pub async fn stream_optimistic_block( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response< + tonic::codec::Streaming, + >, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/astria.sequencerblock.v1alpha1.OptimisticBlockService/StreamOptimisticBlock", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "astria.sequencerblock.v1alpha1.OptimisticBlockService", + "StreamOptimisticBlock", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + /// The Sequencer will stream the block commits to the Auctioneer. + pub async fn stream_block_commitments( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/astria.sequencerblock.v1alpha1.OptimisticBlockService/StreamBlockCommitments", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "astria.sequencerblock.v1alpha1.OptimisticBlockService", + "StreamBlockCommitments", + ), + ); + self.inner.server_streaming(req, path, codec).await + } + } +} +/// Generated server implementations. +#[cfg(feature = "server")] +pub mod optimistic_block_service_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with OptimisticBlockServiceServer. + #[async_trait] + pub trait OptimisticBlockService: Send + Sync + 'static { + /// Server streaming response type for the StreamOptimisticBlock method. + type StreamOptimisticBlockStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result< + super::StreamOptimisticBlockResponse, + tonic::Status, + >, + > + + Send + + 'static; + /// The Sequencer will stream the optimistic Sequencer block (filtered for the provided + /// rollup id) to the Auctioneer. + async fn stream_optimistic_block( + self: std::sync::Arc, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + /// Server streaming response type for the StreamBlockCommitments method. + type StreamBlockCommitmentsStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + Send + + 'static; + /// The Sequencer will stream the block commits to the Auctioneer. + async fn stream_block_commitments( + self: std::sync::Arc, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + /// The Sequencer will serve this to the aucitoneer + #[derive(Debug)] + pub struct OptimisticBlockServiceServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl OptimisticBlockServiceServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> + for OptimisticBlockServiceServer + where + T: OptimisticBlockService, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/astria.sequencerblock.v1alpha1.OptimisticBlockService/StreamOptimisticBlock" => { + #[allow(non_camel_case_types)] + struct StreamOptimisticBlockSvc( + pub Arc, + ); + impl< + T: OptimisticBlockService, + > tonic::server::ServerStreamingService< + super::StreamOptimisticBlockRequest, + > for StreamOptimisticBlockSvc { + type Response = super::StreamOptimisticBlockResponse; + type ResponseStream = T::StreamOptimisticBlockStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::stream_optimistic_block( + inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = StreamOptimisticBlockSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/astria.sequencerblock.v1alpha1.OptimisticBlockService/StreamBlockCommitments" => { + #[allow(non_camel_case_types)] + struct StreamBlockCommitmentsSvc( + pub Arc, + ); + impl< + T: OptimisticBlockService, + > tonic::server::ServerStreamingService< + super::StreamBlockCommitmentsRequest, + > for StreamBlockCommitmentsSvc { + type Response = super::SequencerBlockCommit; + type ResponseStream = T::StreamBlockCommitmentsStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::stream_block_commitments( + inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = StreamBlockCommitmentsSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for OptimisticBlockServiceServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService + for OptimisticBlockServiceServer { + const NAME: &'static str = "astria.sequencerblock.v1alpha1.OptimisticBlockService"; + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct GetSequencerBlockRequest { /// The height of the block to retrieve. #[prost(uint64, tag = "1")] diff --git a/crates/astria-core/src/generated/astria.sequencerblock.v1alpha1.serde.rs b/crates/astria-core/src/generated/astria.sequencerblock.v1alpha1.serde.rs index 2a7168de53..c0c74674c7 100644 --- a/crates/astria-core/src/generated/astria.sequencerblock.v1alpha1.serde.rs +++ b/crates/astria-core/src/generated/astria.sequencerblock.v1alpha1.serde.rs @@ -1181,6 +1181,121 @@ impl<'de> serde::Deserialize<'de> for SequencerBlock { deserializer.deserialize_struct("astria.sequencerblock.v1alpha1.SequencerBlock", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for SequencerBlockCommit { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.height != 0 { + len += 1; + } + if !self.block_hash.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.sequencerblock.v1alpha1.SequencerBlockCommit", len)?; + if self.height != 0 { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("height", ToString::to_string(&self.height).as_str())?; + } + if !self.block_hash.is_empty() { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("blockHash", pbjson::private::base64::encode(&self.block_hash).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SequencerBlockCommit { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "height", + "block_hash", + "blockHash", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Height, + BlockHash, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "height" => Ok(GeneratedField::Height), + "blockHash" | "block_hash" => Ok(GeneratedField::BlockHash), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SequencerBlockCommit; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.sequencerblock.v1alpha1.SequencerBlockCommit") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut height__ = None; + let mut block_hash__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Height => { + if height__.is_some() { + return Err(serde::de::Error::duplicate_field("height")); + } + height__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::BlockHash => { + if block_hash__.is_some() { + return Err(serde::de::Error::duplicate_field("blockHash")); + } + block_hash__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + } + } + Ok(SequencerBlockCommit { + height: height__.unwrap_or_default(), + block_hash: block_hash__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("astria.sequencerblock.v1alpha1.SequencerBlockCommit", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for SequencerBlockHeader { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -1373,6 +1488,260 @@ impl<'de> serde::Deserialize<'de> for SequencerBlockHeader { deserializer.deserialize_struct("astria.sequencerblock.v1alpha1.SequencerBlockHeader", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for StreamBlockCommitmentsRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let len = 0; + let struct_ser = serializer.serialize_struct("astria.sequencerblock.v1alpha1.StreamBlockCommitmentsRequest", len)?; + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for StreamBlockCommitmentsRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + Err(serde::de::Error::unknown_field(value, FIELDS)) + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = StreamBlockCommitmentsRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.sequencerblock.v1alpha1.StreamBlockCommitmentsRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + while map_.next_key::()?.is_some() { + let _ = map_.next_value::()?; + } + Ok(StreamBlockCommitmentsRequest { + }) + } + } + deserializer.deserialize_struct("astria.sequencerblock.v1alpha1.StreamBlockCommitmentsRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for StreamOptimisticBlockRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.rollup_id.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.sequencerblock.v1alpha1.StreamOptimisticBlockRequest", len)?; + if let Some(v) = self.rollup_id.as_ref() { + struct_ser.serialize_field("rollupId", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for StreamOptimisticBlockRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "rollup_id", + "rollupId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + RollupId, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "rollupId" | "rollup_id" => Ok(GeneratedField::RollupId), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = StreamOptimisticBlockRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.sequencerblock.v1alpha1.StreamOptimisticBlockRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut rollup_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::RollupId => { + if rollup_id__.is_some() { + return Err(serde::de::Error::duplicate_field("rollupId")); + } + rollup_id__ = map_.next_value()?; + } + } + } + Ok(StreamOptimisticBlockRequest { + rollup_id: rollup_id__, + }) + } + } + deserializer.deserialize_struct("astria.sequencerblock.v1alpha1.StreamOptimisticBlockRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for StreamOptimisticBlockResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.block.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("astria.sequencerblock.v1alpha1.StreamOptimisticBlockResponse", len)?; + if let Some(v) = self.block.as_ref() { + struct_ser.serialize_field("block", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for StreamOptimisticBlockResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "block", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Block, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "block" => Ok(GeneratedField::Block), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = StreamOptimisticBlockResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct astria.sequencerblock.v1alpha1.StreamOptimisticBlockResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut block__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Block => { + if block__.is_some() { + return Err(serde::de::Error::duplicate_field("block")); + } + block__ = map_.next_value()?; + } + } + } + Ok(StreamOptimisticBlockResponse { + block: block__, + }) + } + } + deserializer.deserialize_struct("astria.sequencerblock.v1alpha1.StreamOptimisticBlockResponse", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for SubmittedMetadata { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/proto/executionapis/astria/bundle/v1alpha1/bundle.proto b/proto/executionapis/astria/bundle/v1alpha1/bundle.proto new file mode 100644 index 0000000000..c077f28a0e --- /dev/null +++ b/proto/executionapis/astria/bundle/v1alpha1/bundle.proto @@ -0,0 +1,67 @@ +syntax = "proto3"; + +package astria.bundle.v1alpha1; + +import "astria/execution/v1alpha2/execution.proto"; +import "astria/sequencerblock/v1alpha1/block.proto"; +import "google/protobuf/timestamp.proto"; + +// The "BaseBlock" is the information needed to simulate bundles on top of +// a Sequencer block which may not have been committed yet. +message BaseBlock { + // This is the block hash for the proposed block. + bytes sequencer_block_hash = 1; + // List of transactions to include in the new block. + repeated astria.sequencerblock.v1alpha1.RollupData transactions = 2; + // Timestamp to be used for new block. + google.protobuf.Timestamp timestamp = 3; +} + +message StreamExecuteOptimisticBlockRequest { + BaseBlock block = 1; +} + +message StreamExecuteOptimisticBlockResponse { + // Metadata identifying the block resulting from executing a block. Includes number, hash, + // parent hash and timestamp. + astria.execution.v1alpha2.Block block = 1; + // The base_sequencer_block_hash is the hash from the base sequencer block this block + // is based on. This is used to associate an optimistic execution result with the hash + // received once a sequencer block is committed. + bytes base_sequencer_block_hash = 2; +} + +message StreamBundlesRequest {} + +// Information for the bundle submitter to know how to submit the bundle. +// The fee and base_sequencer_block_hash are not necessarily strictly necessary +// it allows for the case where the server doesn't always send the highest fee +// bundles after the previous but could just stream any confirmed bundles. +message Bundle { + // The fee that can be expected to be received for submitting this bundle. + // This allows the bundle producer to stream any confirmed bundles they would be ok + // with submitting. Used to avoid race conditions in received bundle packets. Could + // also be used by a bundle submitter to allow multiple entities to submit bundles. + uint64 fee = 1; + // The byte list of transactions to be included. + repeated bytes transactions = 2; + // The base_sequencer_block_hash is the hash from the base block this bundle + // is based on. This is used to verify that the bundle is based on the correct + // Sequencer block. + bytes base_sequencer_block_hash = 3; + // The hash of previous rollup block, on top of which the bundle will be executed as ToB. + bytes prev_rollup_block_hash = 4; +} + +service OptimisticExecutionService { + // Stream blocks from the Auctioneer to Geth for optimistic execution. Geth will stream back + // metadata from the executed blocks. + rpc StreamExecuteOptimisticBlock(stream StreamExecuteOptimisticBlockRequest) returns (stream StreamExecuteOptimisticBlockResponse); +} + +service BundleService { + // A bundle submitter requests bundles given a new optimistic Sequencer block, + // and receives a stream of potential bundles for submission, until either a timeout + // or the connection is closed by the client. + rpc StreamBundles(StreamBundlesRequest) returns (stream Bundle); +} diff --git a/proto/sequencerblockapis/astria/sequencerblock/v1alpha1/optimistic_block.proto b/proto/sequencerblockapis/astria/sequencerblock/v1alpha1/optimistic_block.proto new file mode 100644 index 0000000000..02c4ae0c35 --- /dev/null +++ b/proto/sequencerblockapis/astria/sequencerblock/v1alpha1/optimistic_block.proto @@ -0,0 +1,35 @@ +syntax = "proto3"; + +package astria.sequencerblock.v1alpha1; + +import "astria/primitive/v1/types.proto"; +import "astria/sequencerblock/v1alpha1/block.proto"; + +message StreamBlockCommitmentsRequest {} + +// Identifying metadata for blocks that have been successfully committed in the Sequencer. +message SequencerBlockCommit { + // Height of the sequencer block that was committed. + uint64 height = 1; + // Hash of the sequencer block that was committed. + bytes block_hash = 2; +} + +message StreamOptimisticBlockRequest { + // The rollup id for which the Sequencer block is being streamed. + astria.primitive.v1.RollupId rollup_id = 1; +} + +message StreamOptimisticBlockResponse { + // The optimistic Sequencer block that is being streamed, filtered for the provided rollup id. + astria.sequencerblock.v1alpha1.FilteredSequencerBlock block = 1; +} + +// The Sequencer will serve this to the aucitoneer +service OptimisticBlockService { + // The Sequencer will stream the optimistic Sequencer block (filtered for the provided + // rollup id) to the Auctioneer. + rpc StreamOptimisticBlock(StreamOptimisticBlockRequest) returns (stream StreamOptimisticBlockResponse); + // The Sequencer will stream the block commits to the Auctioneer. + rpc StreamBlockCommitments(StreamBlockCommitmentsRequest) returns (stream SequencerBlockCommit); +}