@@ -46,6 +46,7 @@ class GethKeys:
46
46
headerHashSuffix = b'n'
47
47
48
48
blockBodyPrefix = b'b'
49
+ blockReceiptsPrefix = b'r'
49
50
50
51
@classmethod
51
52
def header_hash_for_block_number (cls , block_number : int ) -> bytes :
@@ -68,6 +69,11 @@ def block_body(cls, block_number: int, header_hash: bytes) -> bytes:
68
69
packed_block_number = struct .pack ('>Q' , block_number )
69
70
return cls .blockBodyPrefix + packed_block_number + header_hash
70
71
72
+ @classmethod
73
+ def block_receipts (cls , block_number : int , header_hash : bytes ) -> bytes :
74
+ packed_block_number = struct .pack ('>Q' , block_number )
75
+ return cls .blockReceiptsPrefix + packed_block_number + header_hash
76
+
71
77
72
78
class GethFreezerIndexEntry :
73
79
def __init__ (self , filenum : int , offset : int ):
@@ -182,6 +188,7 @@ def __init__(self, path):
182
188
self .ancient_hashes = GethFreezerTable (ancient_path , 'hashes' , False )
183
189
self .ancient_headers = GethFreezerTable (ancient_path , 'headers' , True )
184
190
self .ancient_bodies = GethFreezerTable (ancient_path , 'bodies' , True )
191
+ self .ancient_receipts = GethFreezerTable (ancient_path , 'receipts' , True )
185
192
186
193
if self .database_version != b'\x07 ' :
187
194
raise Exception (f'geth database version { self .database_version } is not supported' )
@@ -230,6 +237,17 @@ def block_body(self, block_number: int, header_hash: bytes = None):
230
237
raw_data = self .ancient_bodies .get (block_number )
231
238
return rlp .decode (raw_data , sedes = BlockBody )
232
239
240
+ def block_receipts (self , block_number : int , header_hash : bytes = None ):
241
+ if header_hash is None :
242
+ header_hash = self .header_hash_for_block_number (block_number )
243
+
244
+ raw_data = self .db .get (GethKeys .block_receipts (block_number , header_hash ))
245
+ if raw_data is not None :
246
+ return raw_data
247
+
248
+ raw_data = self .ancient_receipts .get (block_number )
249
+ return raw_data
250
+
233
251
234
252
class ImportDatabase :
235
253
"Creates a 'ChainDB' which can be passed to the trie_iteration utils"
@@ -455,6 +473,22 @@ def process_blocks(gethdb, chain, end_block):
455
473
logger .debug (f'imported block: { imported_block } ' )
456
474
457
475
476
+ def read_receipts (gethdb , block_number ):
477
+ logger .info (f'reading receipts for block. block_number={ block_number } ' )
478
+
479
+ raw_data = gethdb .block_receipts (block_number )
480
+ decoded = rlp .decode (raw_data )
481
+
482
+ logger .info (f'- receipt_count={ len (decoded )} ' )
483
+
484
+ for receipt in decoded :
485
+ post_state , raw_gas_used , logs = receipt
486
+ if len (raw_gas_used ) < 8 :
487
+ padded = (b'\x00 ' * (8 - len (raw_gas_used ))) + raw_gas_used
488
+ gas_used = struct .unpack ('>Q' , padded )[0 ]
489
+ logger .info (f'- post_state_or_status={ post_state } gas_used={ gas_used } len(logs)={ len (logs )} ' )
490
+
491
+
458
492
if __name__ == "__main__" :
459
493
logging .basicConfig (
460
494
level = logging .DEBUG ,
@@ -478,6 +512,9 @@ def process_blocks(gethdb, chain, end_block):
478
512
process_blocks_parser = subparsers .add_parser ('process_blocks' )
479
513
process_blocks_parser .add_argument ('-endblock' , type = int , required = True )
480
514
515
+ read_receipts_parser = subparsers .add_parser ('read_receipts' )
516
+ read_receipts_parser .add_argument ('-block' , type = int , required = True )
517
+
481
518
args = parser .parse_args ()
482
519
483
520
if args .command == 'import_body_range' :
@@ -488,6 +525,9 @@ def process_blocks(gethdb, chain, end_block):
488
525
gethdb = open_gethdb (args .gethdb )
489
526
chain = open_trinitydb (args .destdb )
490
527
process_blocks (gethdb , chain , args .endblock )
528
+ elif args .command == 'read_receipts' :
529
+ gethdb = open_gethdb (args .gethdb )
530
+ read_receipts (gethdb , args .block )
491
531
else :
492
532
main (args )
493
533
0 commit comments