@@ -4,7 +4,8 @@ use acropolis_common::{
44 crypto:: keyhash,
55 messages:: { CardanoMessage , Message , StateQuery , StateQueryResponse } ,
66 queries:: blocks:: {
7- BlockInfo , BlocksStateQuery , BlocksStateQueryResponse , DEFAULT_BLOCKS_QUERY_TOPIC ,
7+ BlockInfo , BlocksStateQuery , BlocksStateQueryResponse , NextBlocks , PreviousBlocks ,
8+ DEFAULT_BLOCKS_QUERY_TOPIC ,
89 } ,
910} ;
1011use anyhow:: { bail, Result } ;
@@ -115,81 +116,167 @@ impl ChainStore {
115116 None => Ok ( BlocksStateQueryResponse :: NotFound ) ,
116117 }
117118 }
119+ BlocksStateQuery :: GetNextBlocks {
120+ block_key,
121+ limit,
122+ skip,
123+ } => {
124+ if * limit == 0 {
125+ return Ok ( BlocksStateQueryResponse :: NextBlocks ( NextBlocks {
126+ blocks : vec ! [ ] ,
127+ } ) ) ;
128+ }
129+ match store. get_block_by_hash ( & block_key) ? {
130+ Some ( block) => {
131+ let number = Self :: get_block_number ( & block) ?;
132+ let min_number = number + 1 + skip;
133+ let max_number = min_number + limit - 1 ;
134+ let blocks = store. get_blocks_by_number_range ( min_number, max_number) ?;
135+ let info = Self :: to_block_info_bulk ( blocks, store, false ) ?;
136+ Ok ( BlocksStateQueryResponse :: NextBlocks ( NextBlocks {
137+ blocks : info,
138+ } ) )
139+ }
140+ None => Ok ( BlocksStateQueryResponse :: NotFound ) ,
141+ }
142+ }
143+ BlocksStateQuery :: GetPreviousBlocks {
144+ block_key,
145+ limit,
146+ skip,
147+ } => {
148+ if * limit == 0 {
149+ return Ok ( BlocksStateQueryResponse :: PreviousBlocks ( PreviousBlocks {
150+ blocks : vec ! [ ] ,
151+ } ) ) ;
152+ }
153+ match store. get_block_by_hash ( & block_key) ? {
154+ Some ( block) => {
155+ let number = Self :: get_block_number ( & block) ?;
156+ let Some ( max_number) = number. checked_sub ( 1 + skip) else {
157+ return Ok ( BlocksStateQueryResponse :: PreviousBlocks ( PreviousBlocks {
158+ blocks : vec ! [ ] ,
159+ } ) ) ;
160+ } ;
161+ let min_number = max_number. saturating_sub ( limit - 1 ) ;
162+ let blocks = store. get_blocks_by_number_range ( min_number, max_number) ?;
163+ let info = Self :: to_block_info_bulk ( blocks, store, false ) ?;
164+ Ok ( BlocksStateQueryResponse :: PreviousBlocks ( PreviousBlocks {
165+ blocks : info,
166+ } ) )
167+ }
168+ None => Ok ( BlocksStateQueryResponse :: NotFound ) ,
169+ }
170+ }
171+
118172 other => bail ! ( "{other:?} not yet supported" ) ,
119173 }
120174 }
121175
176+ fn get_block_number ( block : & Block ) -> Result < u64 > {
177+ Ok ( pallas_traverse:: MultiEraBlock :: decode ( & block. bytes ) ?. number ( ) )
178+ }
179+
122180 fn to_block_info ( block : Block , store : & Arc < dyn Store > , is_latest : bool ) -> Result < BlockInfo > {
123- let decoded = pallas_traverse:: MultiEraBlock :: decode ( & block. bytes ) ?;
124- let header = decoded. header ( ) ;
125- let mut output = None ;
126- let mut fees = None ;
127- for tx in decoded. txs ( ) {
128- if let Some ( new_fee) = tx. fee ( ) {
129- fees = Some ( fees. unwrap_or_default ( ) + new_fee) ;
130- }
131- for o in tx. outputs ( ) {
132- output = Some ( output. unwrap_or_default ( ) + o. value ( ) . coin ( ) )
133- }
181+ let blocks = vec ! [ block] ;
182+ let mut info = Self :: to_block_info_bulk ( blocks, store, is_latest) ?;
183+ Ok ( info. remove ( 0 ) )
184+ }
185+
186+ fn to_block_info_bulk (
187+ blocks : Vec < Block > ,
188+ store : & Arc < dyn Store > ,
189+ final_block_is_latest : bool ,
190+ ) -> Result < Vec < BlockInfo > > {
191+ if blocks. is_empty ( ) {
192+ return Ok ( vec ! [ ] ) ;
134193 }
135- let ( op_cert_hot_vkey, op_cert_counter) = match & header {
136- pallas_traverse:: MultiEraHeader :: BabbageCompatible ( h) => {
137- let cert = & h. header_body . operational_cert ;
138- (
139- Some ( & cert. operational_cert_hot_vkey ) ,
140- Some ( cert. operational_cert_sequence_number ) ,
141- )
142- }
143- pallas_traverse:: MultiEraHeader :: ShelleyCompatible ( h) => (
144- Some ( & h. header_body . operational_cert_hot_vkey ) ,
145- Some ( h. header_body . operational_cert_sequence_number ) ,
146- ) ,
147- _ => ( None , None ) ,
194+ let mut decoded_blocks = vec ! [ ] ;
195+ for block in & blocks {
196+ decoded_blocks. push ( pallas_traverse:: MultiEraBlock :: decode ( & block. bytes ) ?) ;
197+ }
198+
199+ let ( latest_number, latest_hash) = if final_block_is_latest {
200+ let latest = decoded_blocks. last ( ) . unwrap ( ) ;
201+ ( latest. number ( ) , latest. hash ( ) )
202+ } else {
203+ let raw_latest = store. get_latest_block ( ) ?. unwrap ( ) ;
204+ let latest = pallas_traverse:: MultiEraBlock :: decode ( & raw_latest. bytes ) ?;
205+ ( latest. number ( ) , latest. hash ( ) )
148206 } ;
149- let op_cert = op_cert_hot_vkey. map ( |vkey| keyhash ( vkey) ) ;
150207
151- let ( next_block , confirmations ) = if is_latest {
152- ( None , 0 )
208+ let mut next_hash = if final_block_is_latest {
209+ None
153210 } else {
154- let number = header. number ( ) ;
155- let raw_latest_block = store. get_latest_block ( ) ?. unwrap ( ) ;
156- let latest_block = pallas_traverse:: MultiEraBlock :: decode ( & raw_latest_block. bytes ) ?;
157- let latest_block_number = latest_block. number ( ) ;
158- let confirmations = latest_block_number - number;
159-
160- let next_block_number = number + 1 ;
161- let next_block_hash = if next_block_number == latest_block_number {
162- Some ( latest_block. hash ( ) . to_vec ( ) )
211+ let next_number = decoded_blocks. last ( ) . unwrap ( ) . number ( ) + 1 ;
212+ if next_number > latest_number {
213+ None
214+ } else if next_number == latest_number {
215+ Some ( latest_hash)
163216 } else {
164- let raw_next_block = store. get_block_by_number ( next_block_number ) ?;
165- if let Some ( raw_block ) = raw_next_block {
166- let block = pallas_traverse:: MultiEraBlock :: decode ( & raw_block . bytes ) ?;
167- Some ( block . hash ( ) . to_vec ( ) )
217+ let raw_next = store. get_block_by_number ( next_number ) ?;
218+ if let Some ( raw_next ) = raw_next {
219+ let next = pallas_traverse:: MultiEraBlock :: decode ( & raw_next . bytes ) ?;
220+ Some ( next . hash ( ) )
168221 } else {
169222 None
170223 }
171- } ;
172- ( next_block_hash, confirmations)
224+ }
173225 } ;
174226
175- Ok ( BlockInfo {
176- timestamp : block. extra . timestamp ,
177- number : header. number ( ) ,
178- hash : header. hash ( ) . to_vec ( ) ,
179- slot : header. slot ( ) ,
180- epoch : block. extra . epoch ,
181- epoch_slot : block. extra . epoch_slot ,
182- issuer_vkey : header. issuer_vkey ( ) . map ( |key| key. to_vec ( ) ) ,
183- size : block. bytes . len ( ) as u64 ,
184- tx_count : decoded. tx_count ( ) as u64 ,
185- output,
186- fees,
187- block_vrf : header. vrf_vkey ( ) . map ( |key| key. to_vec ( ) ) ,
188- op_cert,
189- op_cert_counter,
190- previous_block : header. previous_hash ( ) . map ( |x| x. to_vec ( ) ) ,
191- next_block,
192- confirmations,
193- } )
227+ let mut block_info = vec ! [ ] ;
228+ for ( block, decoded) in blocks. iter ( ) . zip ( decoded_blocks) . rev ( ) {
229+ let header = decoded. header ( ) ;
230+ let mut output = None ;
231+ let mut fees = None ;
232+ for tx in decoded. txs ( ) {
233+ if let Some ( new_fee) = tx. fee ( ) {
234+ fees = Some ( fees. unwrap_or_default ( ) + new_fee) ;
235+ }
236+ for o in tx. outputs ( ) {
237+ output = Some ( output. unwrap_or_default ( ) + o. value ( ) . coin ( ) )
238+ }
239+ }
240+ let ( op_cert_hot_vkey, op_cert_counter) = match & header {
241+ pallas_traverse:: MultiEraHeader :: BabbageCompatible ( h) => {
242+ let cert = & h. header_body . operational_cert ;
243+ (
244+ Some ( & cert. operational_cert_hot_vkey ) ,
245+ Some ( cert. operational_cert_sequence_number ) ,
246+ )
247+ }
248+ pallas_traverse:: MultiEraHeader :: ShelleyCompatible ( h) => (
249+ Some ( & h. header_body . operational_cert_hot_vkey ) ,
250+ Some ( h. header_body . operational_cert_sequence_number ) ,
251+ ) ,
252+ _ => ( None , None ) ,
253+ } ;
254+ let op_cert = op_cert_hot_vkey. map ( |vkey| keyhash ( vkey) ) ;
255+
256+ block_info. push ( BlockInfo {
257+ timestamp : block. extra . timestamp ,
258+ number : header. number ( ) ,
259+ hash : header. hash ( ) . to_vec ( ) ,
260+ slot : header. slot ( ) ,
261+ epoch : block. extra . epoch ,
262+ epoch_slot : block. extra . epoch_slot ,
263+ issuer_vkey : header. issuer_vkey ( ) . map ( |key| key. to_vec ( ) ) ,
264+ size : block. bytes . len ( ) as u64 ,
265+ tx_count : decoded. tx_count ( ) as u64 ,
266+ output,
267+ fees,
268+ block_vrf : header. vrf_vkey ( ) . map ( |key| key. to_vec ( ) ) ,
269+ op_cert,
270+ op_cert_counter,
271+ previous_block : header. previous_hash ( ) . map ( |h| h. to_vec ( ) ) ,
272+ next_block : next_hash. map ( |h| h. to_vec ( ) ) ,
273+ confirmations : latest_number - header. number ( ) ,
274+ } ) ;
275+
276+ next_hash = Some ( header. hash ( ) ) ;
277+ }
278+
279+ block_info. reverse ( ) ;
280+ Ok ( block_info)
194281 }
195282}
0 commit comments