@@ -43,11 +43,15 @@ var (
43
43
bodySuffix = []byte ("-body" )
44
44
tdSuffix = []byte ("-td" )
45
45
46
- ExpDiffPeriod = big .NewInt (100000 )
47
- blockHashPre = []byte ("block-hash-" ) // [deprecated by eth/63]
46
+ txMetaSuffix = []byte {0x01 }
47
+ receiptsPrefix = []byte ("receipts-" )
48
+ blockReceiptsPrefix = []byte ("receipts-block-" )
48
49
49
50
mipmapPre = []byte ("mipmap-log-bloom-" )
50
51
MIPMapLevels = []uint64 {1000000 , 500000 , 100000 , 50000 , 1000 }
52
+
53
+ ExpDiffPeriod = big .NewInt (100000 )
54
+ blockHashPrefix = []byte ("block-hash-" ) // [deprecated by the header/block split, remove eventually]
51
55
)
52
56
53
57
// CalcDifficulty is the difficulty adjustment algorithm. It returns
@@ -234,6 +238,67 @@ func GetBlock(db ethdb.Database, hash common.Hash) *types.Block {
234
238
return types .NewBlockWithHeader (header ).WithBody (body .Transactions , body .Uncles )
235
239
}
236
240
241
+ // GetBlockReceipts retrieves the receipts generated by the transactions included
242
+ // in a block given by its hash.
243
+ func GetBlockReceipts (db ethdb.Database , hash common.Hash ) types.Receipts {
244
+ data , _ := db .Get (append (blockReceiptsPrefix , hash [:]... ))
245
+ if len (data ) == 0 {
246
+ return nil
247
+ }
248
+ storageReceipts := []* types.ReceiptForStorage {}
249
+ if err := rlp .DecodeBytes (data , & storageReceipts ); err != nil {
250
+ glog .V (logger .Error ).Infof ("invalid receipt array RLP for hash %x: %v" , hash , err )
251
+ return nil
252
+ }
253
+ receipts := make (types.Receipts , len (storageReceipts ))
254
+ for i , receipt := range storageReceipts {
255
+ receipts [i ] = (* types .Receipt )(receipt )
256
+ }
257
+ return receipts
258
+ }
259
+
260
+ // GetTransaction retrieves a specific transaction from the database, along with
261
+ // its added positional metadata.
262
+ func GetTransaction (db ethdb.Database , hash common.Hash ) (* types.Transaction , common.Hash , uint64 , uint64 ) {
263
+ // Retrieve the transaction itself from the database
264
+ data , _ := db .Get (hash .Bytes ())
265
+ if len (data ) == 0 {
266
+ return nil , common.Hash {}, 0 , 0
267
+ }
268
+ var tx types.Transaction
269
+ if err := rlp .DecodeBytes (data , & tx ); err != nil {
270
+ return nil , common.Hash {}, 0 , 0
271
+ }
272
+ // Retrieve the blockchain positional metadata
273
+ data , _ = db .Get (append (hash .Bytes (), txMetaSuffix ... ))
274
+ if len (data ) == 0 {
275
+ return nil , common.Hash {}, 0 , 0
276
+ }
277
+ var meta struct {
278
+ BlockHash common.Hash
279
+ BlockIndex uint64
280
+ Index uint64
281
+ }
282
+ if err := rlp .DecodeBytes (data , & meta ); err != nil {
283
+ return nil , common.Hash {}, 0 , 0
284
+ }
285
+ return & tx , meta .BlockHash , meta .BlockIndex , meta .Index
286
+ }
287
+
288
+ // GetReceipt returns a receipt by hash
289
+ func GetReceipt (db ethdb.Database , txHash common.Hash ) * types.Receipt {
290
+ data , _ := db .Get (append (receiptsPrefix , txHash [:]... ))
291
+ if len (data ) == 0 {
292
+ return nil
293
+ }
294
+ var receipt types.ReceiptForStorage
295
+ err := rlp .DecodeBytes (data , & receipt )
296
+ if err != nil {
297
+ glog .V (logger .Core ).Infoln ("GetReceipt err:" , err )
298
+ }
299
+ return (* types .Receipt )(& receipt )
300
+ }
301
+
237
302
// WriteCanonicalHash stores the canonical hash for the given block number.
238
303
func WriteCanonicalHash (db ethdb.Database , hash common.Hash , number uint64 ) error {
239
304
key := append (blockNumPrefix , big .NewInt (int64 (number )).Bytes ()... )
@@ -329,6 +394,94 @@ func WriteBlock(db ethdb.Database, block *types.Block) error {
329
394
return nil
330
395
}
331
396
397
+ // WriteBlockReceipts stores all the transaction receipts belonging to a block
398
+ // as a single receipt slice. This is used during chain reorganisations for
399
+ // rescheduling dropped transactions.
400
+ func WriteBlockReceipts (db ethdb.Database , hash common.Hash , receipts types.Receipts ) error {
401
+ // Convert the receipts into their storage form and serialize them
402
+ storageReceipts := make ([]* types.ReceiptForStorage , len (receipts ))
403
+ for i , receipt := range receipts {
404
+ storageReceipts [i ] = (* types .ReceiptForStorage )(receipt )
405
+ }
406
+ bytes , err := rlp .EncodeToBytes (storageReceipts )
407
+ if err != nil {
408
+ return err
409
+ }
410
+ // Store the flattened receipt slice
411
+ if err := db .Put (append (blockReceiptsPrefix , hash .Bytes ()... ), bytes ); err != nil {
412
+ glog .Fatalf ("failed to store block receipts into database: %v" , err )
413
+ return err
414
+ }
415
+ glog .V (logger .Debug ).Infof ("stored block receipts [%x…]" , hash .Bytes ()[:4 ])
416
+ return nil
417
+ }
418
+
419
+ // WriteTransactions stores the transactions associated with a specific block
420
+ // into the given database. Beside writing the transaction, the function also
421
+ // stores a metadata entry along with the transaction, detailing the position
422
+ // of this within the blockchain.
423
+ func WriteTransactions (db ethdb.Database , block * types.Block ) error {
424
+ batch := db .NewBatch ()
425
+
426
+ // Iterate over each transaction and encode it with its metadata
427
+ for i , tx := range block .Transactions () {
428
+ // Encode and queue up the transaction for storage
429
+ data , err := rlp .EncodeToBytes (tx )
430
+ if err != nil {
431
+ return err
432
+ }
433
+ if err := batch .Put (tx .Hash ().Bytes (), data ); err != nil {
434
+ return err
435
+ }
436
+ // Encode and queue up the transaction metadata for storage
437
+ meta := struct {
438
+ BlockHash common.Hash
439
+ BlockIndex uint64
440
+ Index uint64
441
+ }{
442
+ BlockHash : block .Hash (),
443
+ BlockIndex : block .NumberU64 (),
444
+ Index : uint64 (i ),
445
+ }
446
+ data , err = rlp .EncodeToBytes (meta )
447
+ if err != nil {
448
+ return err
449
+ }
450
+ if err := batch .Put (append (tx .Hash ().Bytes (), txMetaSuffix ... ), data ); err != nil {
451
+ return err
452
+ }
453
+ }
454
+ // Write the scheduled data into the database
455
+ if err := batch .Write (); err != nil {
456
+ glog .Fatalf ("failed to store transactions into database: %v" , err )
457
+ return err
458
+ }
459
+ return nil
460
+ }
461
+
462
+ // WriteReceipts stores a batch of transaction receipts into the database.
463
+ func WriteReceipts (db ethdb.Database , receipts types.Receipts ) error {
464
+ batch := db .NewBatch ()
465
+
466
+ // Iterate over all the receipts and queue them for database injection
467
+ for _ , receipt := range receipts {
468
+ storageReceipt := (* types .ReceiptForStorage )(receipt )
469
+ data , err := rlp .EncodeToBytes (storageReceipt )
470
+ if err != nil {
471
+ return err
472
+ }
473
+ if err := batch .Put (append (receiptsPrefix , receipt .TxHash .Bytes ()... ), data ); err != nil {
474
+ return err
475
+ }
476
+ }
477
+ // Write the scheduled data into the database
478
+ if err := batch .Write (); err != nil {
479
+ glog .Fatalf ("failed to store receipts into database: %v" , err )
480
+ return err
481
+ }
482
+ return nil
483
+ }
484
+
332
485
// DeleteCanonicalHash removes the number to hash canonical mapping.
333
486
func DeleteCanonicalHash (db ethdb.Database , number uint64 ) {
334
487
db .Delete (append (blockNumPrefix , big .NewInt (int64 (number )).Bytes ()... ))
@@ -351,18 +504,35 @@ func DeleteTd(db ethdb.Database, hash common.Hash) {
351
504
352
505
// DeleteBlock removes all block data associated with a hash.
353
506
func DeleteBlock (db ethdb.Database , hash common.Hash ) {
507
+ DeleteBlockReceipts (db , hash )
354
508
DeleteHeader (db , hash )
355
509
DeleteBody (db , hash )
356
510
DeleteTd (db , hash )
357
511
}
358
512
359
- // [deprecated by eth/63]
513
+ // DeleteBlockReceipts removes all receipt data associated with a block hash.
514
+ func DeleteBlockReceipts (db ethdb.Database , hash common.Hash ) {
515
+ db .Delete (append (blockReceiptsPrefix , hash .Bytes ()... ))
516
+ }
517
+
518
+ // DeleteTransaction removes all transaction data associated with a hash.
519
+ func DeleteTransaction (db ethdb.Database , hash common.Hash ) {
520
+ db .Delete (hash .Bytes ())
521
+ db .Delete (append (hash .Bytes (), txMetaSuffix ... ))
522
+ }
523
+
524
+ // DeleteReceipt removes all receipt data associated with a transaction hash.
525
+ func DeleteReceipt (db ethdb.Database , hash common.Hash ) {
526
+ db .Delete (append (receiptsPrefix , hash .Bytes ()... ))
527
+ }
528
+
529
+ // [deprecated by the header/block split, remove eventually]
360
530
// GetBlockByHashOld returns the old combined block corresponding to the hash
361
531
// or nil if not found. This method is only used by the upgrade mechanism to
362
532
// access the old combined block representation. It will be dropped after the
363
533
// network transitions to eth/63.
364
534
func GetBlockByHashOld (db ethdb.Database , hash common.Hash ) * types.Block {
365
- data , _ := db .Get (append (blockHashPre , hash [:]... ))
535
+ data , _ := db .Get (append (blockHashPrefix , hash [:]... ))
366
536
if len (data ) == 0 {
367
537
return nil
368
538
}
0 commit comments