From 61f64ed283259a211ee6df3289d856eeb22786f0 Mon Sep 17 00:00:00 2001 From: Emily Wang Date: Thu, 24 Sep 2026 16:16:20 +0000 Subject: [PATCH] proto: add block marker support --- proto/block_marker.options | 26 ++++ proto/block_marker.proto | 126 +++++++++++++++++ src/generated/file_descriptor_set.bin | Bin 66905 -> 73575 bytes src/generated/org.solana.sealevel.v1.rs | 171 ++++++++++++++++++++++++ 4 files changed, 323 insertions(+) create mode 100644 proto/block_marker.options create mode 100644 proto/block_marker.proto diff --git a/proto/block_marker.options b/proto/block_marker.options new file mode 100644 index 0000000..297501a --- /dev/null +++ b/proto/block_marker.options @@ -0,0 +1,26 @@ +block_marker.proto package:"fd_exec_test" +block_marker.proto include:"../../../../ballet/nanopb/pb_firedancer.h" + +fd_exec_test.BlockMarkerContext.data type:FT_POINTER + +fd_exec_test.BlockMarkerBitmap.signers type:FT_POINTER + +fd_exec_test.BlockMarkerVotesAggregate.signature max_size:96 fixed_length:true + +fd_exec_test.BlockMarkerFinalizationCert.block_id max_size:32 fixed_length:true + +fd_exec_test.BlockMarkerSkipRewardCert.signature max_size:96 fixed_length:true + +fd_exec_test.BlockMarkerNotarRewardCert.block_id max_size:32 fixed_length:true +fd_exec_test.BlockMarkerNotarRewardCert.signature max_size:96 fixed_length:true + +fd_exec_test.BlockMarkerHeader.parent_block_id max_size:32 fixed_length:true + +fd_exec_test.BlockMarkerUpdateParent.new_parent_block_id max_size:32 fixed_length:true + +fd_exec_test.BlockMarkerFooter.bank_hash max_size:32 fixed_length:true +fd_exec_test.BlockMarkerFooter.block_user_agent max_size:255 + +fd_exec_test.BlockMarkerGenesisCert.block_id max_size:32 fixed_length:true +fd_exec_test.BlockMarkerGenesisCert.signature max_size:192 fixed_length:true +fd_exec_test.BlockMarkerGenesisCert.bitmap type:FT_POINTER diff --git a/proto/block_marker.proto b/proto/block_marker.proto new file mode 100644 index 0000000..af2d07d --- /dev/null +++ b/proto/block_marker.proto @@ -0,0 +1,126 @@ +syntax = "proto3"; +package org.solana.sealevel.v1; + +import "metadata.proto"; + +/* Protobuf definitions for the Alpenglow block marker differential + fuzzer. The testing scope is deserialization of a single block + component that carries a BlockMarker (BlockComponent with a zero + entry count followed by a VersionedBlockMarker), i.e.: + + * BlockComponent / VersionedBlockMarker / BlockMarkerV1 framing and + LengthPrefixed length checks + * BlockHeaderV1, UpdateParentV1, BlockFooterV1 and + GenesisCertBlockMarker field decoding + * Base2 signer bitmap decoding for every certificate in the footer + + Checks that need bank state (parent slot, clock bounds, reward slot + ranges, stake / rank maps, BLS signature verification) are out of + scope. Signatures are reported as raw bytes and never verified. + + Bitmaps are decoded against a fixed validator cap of 2000 (the VAT + cap), not the epoch's rank map size. */ + +message BlockMarkerContext { + // Raw bytes of one data batch + bytes data = 1; +} + +enum BlockMarkerParseResult { + BLOCK_MARKER_PARSE_RESULT_ACCEPTED = 0; + // The component is a marker but failed to deserialize. + BLOCK_MARKER_PARSE_RESULT_REJECTED = 1; + // The component's entry count is nonzero (or data is shorter than the + // entry count), so it is an entry batch, not a marker. + BLOCK_MARKER_PARSE_RESULT_NOT_A_MARKER = 2; +} + +message BlockMarkerBitmap { + // Number of validator ranks the bitmap covers. + uint32 bit_cnt = 1; + // Ranks whose bit is set, ascending. + repeated uint32 signers = 2; +} + +message BlockMarkerVotesAggregate { + // Compressed BLS signature. Exactly 96 bytes. + bytes signature = 1; + BlockMarkerBitmap bitmap = 2; +} + +message BlockMarkerFinalizationCert { + uint64 slot = 1; + // Exactly 32 bytes. + bytes block_id = 2; + BlockMarkerVotesAggregate final_aggregate = 3; + // Unset for fast finalization. + BlockMarkerVotesAggregate notar_aggregate = 4; +} + +message BlockMarkerSkipRewardCert { + uint64 slot = 1; + // Compressed BLS signature. Exactly 96 bytes. + bytes signature = 2; + BlockMarkerBitmap bitmap = 3; +} + +message BlockMarkerNotarRewardCert { + uint64 slot = 1; + // Exactly 32 bytes. + bytes block_id = 2; + // Compressed BLS signature. Exactly 96 bytes. + bytes signature = 3; + BlockMarkerBitmap bitmap = 4; +} + +message BlockMarkerHeader { + uint64 parent_slot = 1; + // Exactly 32 bytes. + bytes parent_block_id = 2; +} + +message BlockMarkerUpdateParent { + uint64 new_parent_slot = 1; + // Exactly 32 bytes. + bytes new_parent_block_id = 2; +} + +message BlockMarkerFooter { + // Exactly 32 bytes. + bytes bank_hash = 1; + uint64 block_producer_time_nanos = 2; + // At most 255 bytes. + bytes block_user_agent = 3; + // Each is unset when the footer does not carry it. + BlockMarkerFinalizationCert block_final_cert = 4; + BlockMarkerSkipRewardCert skip_reward_cert = 5; + BlockMarkerNotarRewardCert notar_reward_cert = 6; +} + +message BlockMarkerGenesisCert { + uint64 slot = 1; + // Exactly 32 bytes. + bytes block_id = 2; + // Uncompressed BLS signature. Exactly 192 bytes. + bytes signature = 3; + // Raw bitmap bytes, not decoded. + bytes bitmap = 4; +} + +message BlockMarkerEffects { + BlockMarkerParseResult result = 1; + + // Set iff result is ACCEPTED. + oneof marker { + BlockMarkerFooter footer = 2; + BlockMarkerHeader header = 3; + BlockMarkerUpdateParent update_parent = 4; + BlockMarkerGenesisCert genesis_cert = 5; + } +} + +message BlockMarkerFixture { + FixtureMetadata metadata = 1; + BlockMarkerContext input = 2; + BlockMarkerEffects output = 3; +} diff --git a/src/generated/file_descriptor_set.bin b/src/generated/file_descriptor_set.bin index 4aa17bb8e9472e55687c050de8d845350240ec12..c5ada2d3ce2804f4af980f90ad9c63a84dc9ab3b 100644 GIT binary patch delta 6022 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 A=>Px# delta 14 WcmaF9kL6|;%ZAl~n|Eff+YA6ZCkOQa diff --git a/src/generated/org.solana.sealevel.v1.rs b/src/generated/org.solana.sealevel.v1.rs index 81a83bf..ba541cf 100644 --- a/src/generated/org.solana.sealevel.v1.rs +++ b/src/generated/org.solana.sealevel.v1.rs @@ -514,6 +514,177 @@ impl WarmupCooldownRate { } } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerContext { + /// Raw bytes of one data batch + #[prost(bytes = "vec", tag = "1")] + pub data: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerBitmap { + /// Number of validator ranks the bitmap covers. + #[prost(uint32, tag = "1")] + pub bit_cnt: u32, + /// Ranks whose bit is set, ascending. + #[prost(uint32, repeated, tag = "2")] + pub signers: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerVotesAggregate { + /// Compressed BLS signature. Exactly 96 bytes. + #[prost(bytes = "vec", tag = "1")] + pub signature: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "2")] + pub bitmap: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerFinalizationCert { + #[prost(uint64, tag = "1")] + pub slot: u64, + /// Exactly 32 bytes. + #[prost(bytes = "vec", tag = "2")] + pub block_id: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "3")] + pub final_aggregate: ::core::option::Option, + /// Unset for fast finalization. + #[prost(message, optional, tag = "4")] + pub notar_aggregate: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerSkipRewardCert { + #[prost(uint64, tag = "1")] + pub slot: u64, + /// Compressed BLS signature. Exactly 96 bytes. + #[prost(bytes = "vec", tag = "2")] + pub signature: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "3")] + pub bitmap: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerNotarRewardCert { + #[prost(uint64, tag = "1")] + pub slot: u64, + /// Exactly 32 bytes. + #[prost(bytes = "vec", tag = "2")] + pub block_id: ::prost::alloc::vec::Vec, + /// Compressed BLS signature. Exactly 96 bytes. + #[prost(bytes = "vec", tag = "3")] + pub signature: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag = "4")] + pub bitmap: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerHeader { + #[prost(uint64, tag = "1")] + pub parent_slot: u64, + /// Exactly 32 bytes. + #[prost(bytes = "vec", tag = "2")] + pub parent_block_id: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerUpdateParent { + #[prost(uint64, tag = "1")] + pub new_parent_slot: u64, + /// Exactly 32 bytes. + #[prost(bytes = "vec", tag = "2")] + pub new_parent_block_id: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerFooter { + /// Exactly 32 bytes. + #[prost(bytes = "vec", tag = "1")] + pub bank_hash: ::prost::alloc::vec::Vec, + #[prost(uint64, tag = "2")] + pub block_producer_time_nanos: u64, + /// At most 255 bytes. + #[prost(bytes = "vec", tag = "3")] + pub block_user_agent: ::prost::alloc::vec::Vec, + /// Each is unset when the footer does not carry it. + #[prost(message, optional, tag = "4")] + pub block_final_cert: ::core::option::Option, + #[prost(message, optional, tag = "5")] + pub skip_reward_cert: ::core::option::Option, + #[prost(message, optional, tag = "6")] + pub notar_reward_cert: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerGenesisCert { + #[prost(uint64, tag = "1")] + pub slot: u64, + /// Exactly 32 bytes. + #[prost(bytes = "vec", tag = "2")] + pub block_id: ::prost::alloc::vec::Vec, + /// Uncompressed BLS signature. Exactly 192 bytes. + #[prost(bytes = "vec", tag = "3")] + pub signature: ::prost::alloc::vec::Vec, + /// Raw bitmap bytes, not decoded. + #[prost(bytes = "vec", tag = "4")] + pub bitmap: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerEffects { + #[prost(enumeration = "BlockMarkerParseResult", tag = "1")] + pub result: i32, + /// Set iff result is ACCEPTED. + #[prost(oneof = "block_marker_effects::Marker", tags = "2, 3, 4, 5")] + pub marker: ::core::option::Option, +} +/// Nested message and enum types in `BlockMarkerEffects`. +pub mod block_marker_effects { + /// Set iff result is ACCEPTED. + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Marker { + #[prost(message, tag = "2")] + Footer(super::BlockMarkerFooter), + #[prost(message, tag = "3")] + Header(super::BlockMarkerHeader), + #[prost(message, tag = "4")] + UpdateParent(super::BlockMarkerUpdateParent), + #[prost(message, tag = "5")] + GenesisCert(super::BlockMarkerGenesisCert), + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct BlockMarkerFixture { + #[prost(message, optional, tag = "1")] + pub metadata: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub input: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub output: ::core::option::Option, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum BlockMarkerParseResult { + Accepted = 0, + /// The component is a marker but failed to deserialize. + Rejected = 1, + /// The component's entry count is nonzero (or data is shorter than the + /// entry count), so it is an entry batch, not a marker. + NotAMarker = 2, +} +impl BlockMarkerParseResult { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Accepted => "BLOCK_MARKER_PARSE_RESULT_ACCEPTED", + Self::Rejected => "BLOCK_MARKER_PARSE_RESULT_REJECTED", + Self::NotAMarker => "BLOCK_MARKER_PARSE_RESULT_NOT_A_MARKER", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "BLOCK_MARKER_PARSE_RESULT_ACCEPTED" => Some(Self::Accepted), + "BLOCK_MARKER_PARSE_RESULT_REJECTED" => Some(Self::Rejected), + "BLOCK_MARKER_PARSE_RESULT_NOT_A_MARKER" => Some(Self::NotAMarker), + _ => None, + } + } +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct StakeDelta { #[prost(bytes = "vec", tag = "1")] pub address: ::prost::alloc::vec::Vec,