Skip to content

Commit d3546cc

Browse files
committed
core/rawdb: add lightweight types for block logs
1 parent d0263ab commit d3546cc

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

core/rawdb/accessors_chain.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package rawdb
1919
import (
2020
"bytes"
2121
"encoding/binary"
22+
"errors"
2223
"math/big"
2324
"sort"
2425

@@ -631,6 +632,54 @@ func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
631632
}
632633
}
633634

635+
// storedReceiptRLP is the storage encoding of a receipt.
636+
// Re-definition in core/types/receipt.go.
637+
type storedReceiptRLP struct {
638+
PostStateOrStatus []byte
639+
CumulativeGasUsed uint64
640+
Logs []*types.LogForStorage
641+
}
642+
643+
// ReceiptLogs is a barebone version of ReceiptForStorage which only keeps
644+
// the list of logs.
645+
type receiptLogs struct {
646+
Logs []*types.Log
647+
}
648+
649+
// DecodeRLP implements rlp.Decoder.
650+
func (r *receiptLogs) DecodeRLP(s *rlp.Stream) error {
651+
var stored storedReceiptRLP
652+
if err := s.Decode(&stored); err != nil {
653+
return err
654+
}
655+
r.Logs = make([]*types.Log, len(stored.Logs))
656+
for i, log := range stored.Logs {
657+
r.Logs[i] = (*types.Log)(log)
658+
}
659+
return nil
660+
}
661+
662+
// DeriveLogFields fills the logs in receiptLogs with information such as block number, txhash, etc.
663+
func deriveLogFields(receipts []*receiptLogs, hash common.Hash, number uint64, txs types.Transactions) error {
664+
logIndex := uint(0)
665+
if len(txs) != len(receipts) {
666+
return errors.New("transaction and receipt count mismatch")
667+
}
668+
for i := 0; i < len(receipts); i++ {
669+
txHash := txs[i].Hash()
670+
// The derived log fields can simply be set from the block and transaction
671+
for j := 0; j < len(receipts[i].Logs); j++ {
672+
receipts[i].Logs[j].BlockNumber = number
673+
receipts[i].Logs[j].BlockHash = hash
674+
receipts[i].Logs[j].TxHash = txHash
675+
receipts[i].Logs[j].TxIndex = uint(i)
676+
receipts[i].Logs[j].Index = logIndex
677+
logIndex++
678+
}
679+
}
680+
return nil
681+
}
682+
634683
// ReadBlock retrieves an entire block corresponding to the hash, assembling it
635684
// back from the stored header and body. If either the header or body could not
636685
// be retrieved nil is returned.

core/rawdb/accessors_chain_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,82 @@ func TestCanonicalHashIteration(t *testing.T) {
528528
}
529529
}
530530
}
531+
532+
func TestDeriveLogFields(t *testing.T) {
533+
// Create a few transactions to have receipts for
534+
to2 := common.HexToAddress("0x2")
535+
to3 := common.HexToAddress("0x3")
536+
txs := types.Transactions{
537+
types.NewTx(&types.LegacyTx{
538+
Nonce: 1,
539+
Value: big.NewInt(1),
540+
Gas: 1,
541+
GasPrice: big.NewInt(1),
542+
}),
543+
types.NewTx(&types.LegacyTx{
544+
To: &to2,
545+
Nonce: 2,
546+
Value: big.NewInt(2),
547+
Gas: 2,
548+
GasPrice: big.NewInt(2),
549+
}),
550+
types.NewTx(&types.AccessListTx{
551+
To: &to3,
552+
Nonce: 3,
553+
Value: big.NewInt(3),
554+
Gas: 3,
555+
GasPrice: big.NewInt(3),
556+
}),
557+
}
558+
// Create the corresponding receipts
559+
receipts := []*receiptLogs{
560+
{
561+
Logs: []*types.Log{
562+
{Address: common.BytesToAddress([]byte{0x11})},
563+
{Address: common.BytesToAddress([]byte{0x01, 0x11})},
564+
},
565+
},
566+
{
567+
Logs: []*types.Log{
568+
{Address: common.BytesToAddress([]byte{0x22})},
569+
{Address: common.BytesToAddress([]byte{0x02, 0x22})},
570+
},
571+
},
572+
{
573+
Logs: []*types.Log{
574+
{Address: common.BytesToAddress([]byte{0x33})},
575+
{Address: common.BytesToAddress([]byte{0x03, 0x33})},
576+
},
577+
},
578+
}
579+
580+
// Derive log metadata fields
581+
number := big.NewInt(1)
582+
hash := common.BytesToHash([]byte{0x03, 0x14})
583+
if err := deriveLogFields(receipts, hash, number.Uint64(), txs); err != nil {
584+
t.Fatal(err)
585+
}
586+
587+
// Iterate over all the computed fields and check that they're correct
588+
logIndex := uint(0)
589+
for i := range receipts {
590+
for j := range receipts[i].Logs {
591+
if receipts[i].Logs[j].BlockNumber != number.Uint64() {
592+
t.Errorf("receipts[%d].Logs[%d].BlockNumber = %d, want %d", i, j, receipts[i].Logs[j].BlockNumber, number.Uint64())
593+
}
594+
if receipts[i].Logs[j].BlockHash != hash {
595+
t.Errorf("receipts[%d].Logs[%d].BlockHash = %s, want %s", i, j, receipts[i].Logs[j].BlockHash.String(), hash.String())
596+
}
597+
if receipts[i].Logs[j].TxHash != txs[i].Hash() {
598+
t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String())
599+
}
600+
if receipts[i].Logs[j].TxIndex != uint(i) {
601+
t.Errorf("receipts[%d].Logs[%d].TransactionIndex = %d, want %d", i, j, receipts[i].Logs[j].TxIndex, i)
602+
}
603+
if receipts[i].Logs[j].Index != logIndex {
604+
t.Errorf("receipts[%d].Logs[%d].Index = %d, want %d", i, j, receipts[i].Logs[j].Index, logIndex)
605+
}
606+
logIndex++
607+
}
608+
}
609+
}

0 commit comments

Comments
 (0)