Skip to content

Commit 94ab4ea

Browse files
authored
core/rawdb: fix transaction indexing/unindexing hashing error (ethereum#22457)
* core/rawdb: more verbose error logs + better hashing * core/rawdb: add failing testcase * core/rawdb: properly hash transactions while indexing/unindexing * core/rawdb: exit on error + better log msg
1 parent 7cbf1d7 commit 94ab4ea

File tree

3 files changed

+65
-38
lines changed

3 files changed

+65
-38
lines changed

core/rawdb/chain_iterator.go

+6-23
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ import (
2323

2424
"github.com/ethereum/go-ethereum/common"
2525
"github.com/ethereum/go-ethereum/common/prque"
26+
"github.com/ethereum/go-ethereum/core/types"
2627
"github.com/ethereum/go-ethereum/ethdb"
2728
"github.com/ethereum/go-ethereum/log"
2829
"github.com/ethereum/go-ethereum/rlp"
29-
"golang.org/x/crypto/sha3"
3030
)
3131

3232
// InitDatabaseFromFreezer reinitializes an empty database from a previous batch
@@ -135,32 +135,15 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
135135
close(hashesCh)
136136
}
137137
}()
138-
139-
var hasher = sha3.NewLegacyKeccak256()
140138
for data := range rlpCh {
141-
it, err := rlp.NewListIterator(data.rlp)
142-
if err != nil {
143-
log.Warn("tx iteration error", "error", err)
144-
return
145-
}
146-
it.Next()
147-
txs := it.Value()
148-
txIt, err := rlp.NewListIterator(txs)
149-
if err != nil {
150-
log.Warn("tx iteration error", "error", err)
139+
var body types.Body
140+
if err := rlp.DecodeBytes(data.rlp, &body); err != nil {
141+
log.Warn("Failed to decode block body", "block", data.number, "error", err)
151142
return
152143
}
153144
var hashes []common.Hash
154-
for txIt.Next() {
155-
if err := txIt.Err(); err != nil {
156-
log.Warn("tx iteration error", "error", err)
157-
return
158-
}
159-
var txHash common.Hash
160-
hasher.Reset()
161-
hasher.Write(txIt.Value())
162-
hasher.Sum(txHash[:0])
163-
hashes = append(hashes, txHash)
145+
for _, tx := range body.Transactions {
146+
hashes = append(hashes, tx.Hash())
164147
}
165148
result := &blockTxHashes{
166149
hashes: hashes,

core/rawdb/chain_iterator_test.go

+58-15
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,34 @@ func TestChainIterator(t *testing.T) {
3333

3434
var block *types.Block
3535
var txs []*types.Transaction
36-
for i := uint64(0); i <= 10; i++ {
37-
if i == 0 {
38-
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, nil, nil, nil, newHasher()) // Empty genesis block
36+
to := common.BytesToAddress([]byte{0x11})
37+
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(0))}, nil, nil, nil, newHasher()) // Empty genesis block
38+
WriteBlock(chainDb, block)
39+
WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
40+
for i := uint64(1); i <= 10; i++ {
41+
var tx *types.Transaction
42+
if i%2 == 0 {
43+
tx = types.NewTx(&types.LegacyTx{
44+
Nonce: i,
45+
GasPrice: big.NewInt(11111),
46+
Gas: 1111,
47+
To: &to,
48+
Value: big.NewInt(111),
49+
Data: []byte{0x11, 0x11, 0x11},
50+
})
3951
} else {
40-
tx := types.NewTransaction(i, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11})
41-
txs = append(txs, tx)
42-
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newHasher())
52+
tx = types.NewTx(&types.AccessListTx{
53+
ChainID: big.NewInt(1337),
54+
Nonce: i,
55+
GasPrice: big.NewInt(11111),
56+
Gas: 1111,
57+
To: &to,
58+
Value: big.NewInt(111),
59+
Data: []byte{0x11, 0x11, 0x11},
60+
})
4361
}
62+
txs = append(txs, tx)
63+
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newHasher())
4464
WriteBlock(chainDb, block)
4565
WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
4666
}
@@ -66,7 +86,7 @@ func TestChainIterator(t *testing.T) {
6686
numbers = append(numbers, int(h.number))
6787
if len(h.hashes) > 0 {
6888
if got, exp := h.hashes[0], txs[h.number-1].Hash(); got != exp {
69-
t.Fatalf("hash wrong, got %x exp %x", got, exp)
89+
t.Fatalf("block %d: hash wrong, got %x exp %x", h.number, got, exp)
7090
}
7191
}
7292
}
@@ -88,14 +108,37 @@ func TestIndexTransactions(t *testing.T) {
88108

89109
var block *types.Block
90110
var txs []*types.Transaction
91-
for i := uint64(0); i <= 10; i++ {
92-
if i == 0 {
93-
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, nil, nil, nil, newHasher()) // Empty genesis block
111+
to := common.BytesToAddress([]byte{0x11})
112+
113+
// Write empty genesis block
114+
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(0))}, nil, nil, nil, newHasher())
115+
WriteBlock(chainDb, block)
116+
WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
117+
118+
for i := uint64(1); i <= 10; i++ {
119+
var tx *types.Transaction
120+
if i%2 == 0 {
121+
tx = types.NewTx(&types.LegacyTx{
122+
Nonce: i,
123+
GasPrice: big.NewInt(11111),
124+
Gas: 1111,
125+
To: &to,
126+
Value: big.NewInt(111),
127+
Data: []byte{0x11, 0x11, 0x11},
128+
})
94129
} else {
95-
tx := types.NewTransaction(i, common.BytesToAddress([]byte{0x11}), big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11})
96-
txs = append(txs, tx)
97-
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newHasher())
130+
tx = types.NewTx(&types.AccessListTx{
131+
ChainID: big.NewInt(1337),
132+
Nonce: i,
133+
GasPrice: big.NewInt(11111),
134+
Gas: 1111,
135+
To: &to,
136+
Value: big.NewInt(111),
137+
Data: []byte{0x11, 0x11, 0x11},
138+
})
98139
}
140+
txs = append(txs, tx)
141+
block = types.NewBlock(&types.Header{Number: big.NewInt(int64(i))}, []*types.Transaction{tx}, nil, nil, newHasher())
99142
WriteBlock(chainDb, block)
100143
WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
101144
}
@@ -108,10 +151,10 @@ func TestIndexTransactions(t *testing.T) {
108151
}
109152
number := ReadTxLookupEntry(chainDb, txs[i-1].Hash())
110153
if exist && number == nil {
111-
t.Fatalf("Transaction indice missing")
154+
t.Fatalf("Transaction index %d missing", i)
112155
}
113156
if !exist && number != nil {
114-
t.Fatalf("Transaction indice is not deleted")
157+
t.Fatalf("Transaction index %d is not deleted", i)
115158
}
116159
}
117160
number := ReadTxIndexTail(chainDb)

rlp/iterator.go

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type listIterator struct {
2323
}
2424

2525
// NewListIterator creates an iterator for the (list) represented by data
26+
// TODO: Consider removing this implementation, as it is no longer used.
2627
func NewListIterator(data RawValue) (*listIterator, error) {
2728
k, t, c, err := readKind(data)
2829
if err != nil {

0 commit comments

Comments
 (0)