Skip to content

Commit cb86b65

Browse files
committed
core/rawdb: add lightweight types for block logs
1 parent 4e9b9f5 commit cb86b65

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

0 commit comments

Comments
 (0)