11use crate :: { ExecutionPayloadBaseV1 , FlashBlock } ;
22use alloy_eips:: eip2718:: WithEncoded ;
3+ use eyre:: { bail, OptionExt } ;
34use reth_primitives_traits:: { Recovered , SignedTransaction } ;
45use std:: collections:: BTreeMap ;
56use tracing:: trace;
67
78/// An ordered B-tree keeping the track of a sequence of [`FlashBlock`]s by their indices.
89#[ derive( Debug ) ]
9- pub ( crate ) struct FlashBlockSequence < T > {
10+ pub ( crate ) struct FlashBlockPendingSequence < T > {
1011 /// tracks the individual flashblocks in order
1112 ///
1213 /// With a blocktime of 2s and flashblock tick-rate of 200ms plus one extra flashblock per new
1314 /// pending block, we expect 11 flashblocks per slot.
1415 inner : BTreeMap < u64 , PreparedFlashBlock < T > > ,
1516}
1617
17- impl < T > FlashBlockSequence < T >
18+ impl < T > FlashBlockPendingSequence < T >
1819where
1920 T : SignedTransaction ,
2021{
4546 Ok ( ( ) )
4647 }
4748
48- /// Returns the first block number
49- pub ( crate ) fn block_number ( & self ) -> Option < u64 > {
50- Some ( self . inner . values ( ) . next ( ) ?. block ( ) . metadata . block_number )
51- }
52-
53- /// Returns the payload base of the first tracked flashblock.
54- pub ( crate ) fn payload_base ( & self ) -> Option < ExecutionPayloadBaseV1 > {
55- self . inner . values ( ) . next ( ) ?. block ( ) . base . clone ( )
56- }
57-
5849 /// Iterator over sequence of executable transactions.
5950 ///
6051 /// A flashblocks is not ready if there's missing previous flashblocks, i.e. there's a gap in
@@ -74,13 +65,77 @@ where
7465 . flat_map ( |( _, block) | block. txs . clone ( ) )
7566 }
7667
68+ fn clear ( & mut self ) {
69+ self . inner . clear ( ) ;
70+ }
71+
72+ /// Returns the first block number
73+ pub ( crate ) fn block_number ( & self ) -> Option < u64 > {
74+ Some ( self . inner . values ( ) . next ( ) ?. block ( ) . metadata . block_number )
75+ }
76+
77+ /// Returns the payload base of the first tracked flashblock.
78+ pub ( crate ) fn payload_base ( & self ) -> Option < ExecutionPayloadBaseV1 > {
79+ self . inner . values ( ) . next ( ) ?. block ( ) . base . clone ( )
80+ }
81+
7782 /// Returns the number of tracked flashblocks.
7883 pub ( crate ) fn count ( & self ) -> usize {
7984 self . inner . len ( )
8085 }
86+ }
8187
82- fn clear ( & mut self ) {
83- self . inner . clear ( ) ;
88+ /// A complete sequence of flashblocks, often corresponding to a full block.
89+ /// Ensure invariants of a complete flashblocks sequence.
90+ #[ derive( Debug ) ]
91+ pub struct FlashBlockCompleteSequence ( Vec < FlashBlock > ) ;
92+
93+ impl FlashBlockCompleteSequence {
94+ /// Create a complete sequence from a vector of flashblocks.
95+ /// Ensure that:
96+ /// * vector is not empty
97+ /// * first flashblock have the base payload
98+ /// * sequence of flashblocks is sound (successive index from 0, same payload id, ...)
99+ pub fn new ( blocks : Vec < FlashBlock > ) -> eyre:: Result < Self > {
100+ let first_block = blocks. first ( ) . ok_or_eyre ( "No flashblocks in sequence" ) ?;
101+
102+ // Ensure that first flashblock have base
103+ first_block. base . as_ref ( ) . ok_or_eyre ( "Flashblock at index 0 has no base" ) ?;
104+
105+ // Ensure that index are successive from 0, have same block number and payload id
106+ if !blocks. iter ( ) . enumerate ( ) . all ( |( idx, block) | {
107+ idx == block. index as usize &&
108+ block. payload_id == first_block. payload_id &&
109+ block. metadata . block_number == first_block. metadata . block_number
110+ } ) {
111+ bail ! ( "Flashblock inconsistencies detected in sequence" ) ;
112+ }
113+
114+ Ok ( Self ( blocks) )
115+ }
116+
117+ /// Returns the block number
118+ pub fn block_number ( & self ) -> u64 {
119+ self . 0 . first ( ) . unwrap ( ) . metadata . block_number
120+ }
121+
122+ /// Returns the payload base of the first flashblock.
123+ pub fn payload_base ( & self ) -> & ExecutionPayloadBaseV1 {
124+ self . 0 . first ( ) . unwrap ( ) . base . as_ref ( ) . unwrap ( )
125+ }
126+
127+ /// Returns the number of flashblocks in the sequence.
128+ pub const fn count ( & self ) -> usize {
129+ self . 0 . len ( )
130+ }
131+ }
132+
133+ impl < T > TryFrom < FlashBlockPendingSequence < T > > for FlashBlockCompleteSequence {
134+ type Error = eyre:: Error ;
135+ fn try_from ( sequence : FlashBlockPendingSequence < T > ) -> Result < Self , Self :: Error > {
136+ Self :: new (
137+ sequence. inner . into_values ( ) . map ( |block| block. block ( ) . clone ( ) ) . collect :: < Vec < _ > > ( ) ,
138+ )
84139 }
85140}
86141
@@ -130,7 +185,7 @@ mod tests {
130185
131186 #[ test]
132187 fn test_sequence_stops_before_gap ( ) {
133- let mut sequence = FlashBlockSequence :: new ( ) ;
188+ let mut sequence = FlashBlockPendingSequence :: new ( ) ;
134189 let tx = EthereumTxEnvelope :: new_unhashed (
135190 EthereumTypedTransaction :: < TxEip1559 > :: Eip1559 ( TxEip1559 {
136191 chain_id : 4 ,
0 commit comments