mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 21:56:43 +00:00
core/rawdb: add more unit tests
This commit is contained in:
parent
a42332e750
commit
feed0d8a3a
2 changed files with 145 additions and 31 deletions
|
|
@ -129,6 +129,46 @@ func DeleteAllTxLookupEntries(db ethdb.KeyValueStore, condition func(common.Hash
|
|||
}
|
||||
}
|
||||
|
||||
// traverseBlockBody traverses the given RLP-encoded block body, searching for
|
||||
// the transaction specified by its hash.
|
||||
func traverseBlockBody(data rlp.RawValue, target common.Hash) (*types.Transaction, uint64, error) {
|
||||
txnListRLP, _, err := rlp.SplitList(data)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
iter, err := rlp.NewListIterator(txnListRLP)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
txIndex := uint64(0)
|
||||
for iter.Next() {
|
||||
if iter.Err() != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
// The preimage for the hash calculation of legacy transactions
|
||||
// is just their RLP encoding. For typed (EIP-2718) transactions,
|
||||
// which are encoded as byte arrays, the preimage is the content of
|
||||
// the byte array, so trim their prefix here.
|
||||
txRLP := iter.Value()
|
||||
kind, txHashPayload, _, err := rlp.Split(txRLP)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if kind == rlp.List { // Legacy transaction
|
||||
txHashPayload = txRLP
|
||||
}
|
||||
if crypto.Keccak256Hash(txHashPayload) == target {
|
||||
var tx types.Transaction
|
||||
if err := rlp.DecodeBytes(txRLP, &tx); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return &tx, txIndex, nil
|
||||
}
|
||||
txIndex++
|
||||
}
|
||||
return nil, 0, errors.New("transaction not found")
|
||||
}
|
||||
|
||||
// ReadTransaction retrieves a specific transaction from the database, along with
|
||||
// its added positional metadata.
|
||||
func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, common.Hash, uint64, uint64) {
|
||||
|
|
@ -145,40 +185,12 @@ func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, com
|
|||
log.Error("Transaction referenced missing", "number", *blockNumber, "hash", blockHash)
|
||||
return nil, common.Hash{}, 0, 0
|
||||
}
|
||||
txnListRLP, _, err := rlp.SplitList(bodyRLP)
|
||||
tx, txIndex, err := traverseBlockBody(bodyRLP, hash)
|
||||
if err != nil {
|
||||
log.Error("Transaction not found", "number", *blockNumber, "hash", blockHash, "txhash", hash, "err", err)
|
||||
return nil, common.Hash{}, 0, 0
|
||||
}
|
||||
txnIterator, err := rlp.NewListIterator(txnListRLP)
|
||||
if err != nil {
|
||||
return nil, common.Hash{}, 0, 0
|
||||
}
|
||||
|
||||
txIndex := uint64(0)
|
||||
for txnIterator.Next() && txnIterator.Err() == nil {
|
||||
// The preimage for the hash calculation of legacy transactions
|
||||
// is just their RLP encoding. For typed (EIP-2718) transactions,
|
||||
// which are encoded as byte arrays, the preimage is the content of
|
||||
// the byte array, so trim their prefix here.
|
||||
txRLP := txnIterator.Value()
|
||||
kind, txHashPayload, _, err := rlp.Split(txRLP)
|
||||
if err != nil {
|
||||
return nil, common.Hash{}, 0, 0
|
||||
}
|
||||
if kind == rlp.List {
|
||||
txHashPayload = txRLP
|
||||
}
|
||||
if crypto.Keccak256Hash(txHashPayload) == hash {
|
||||
var tx types.Transaction
|
||||
if err := rlp.DecodeBytes(txRLP, &tx); err != nil {
|
||||
return nil, common.Hash{}, 0, 0
|
||||
}
|
||||
return &tx, blockHash, *blockNumber, txIndex
|
||||
}
|
||||
txIndex++
|
||||
}
|
||||
log.Error("Transaction not found", "number", *blockNumber, "hash", blockHash, "txhash", hash)
|
||||
return nil, common.Hash{}, 0, 0
|
||||
return tx, blockHash, *blockNumber, txIndex
|
||||
}
|
||||
|
||||
// ReadReceipt retrieves a specific transaction receipt from the database, along with
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
package rawdb
|
||||
|
||||
import (
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/holiman/uint256"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
|
|
@ -117,3 +119,103 @@ func TestLookupStorage(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTraverseBlockBody(t *testing.T) {
|
||||
tx1 := types.NewTx(&types.LegacyTx{
|
||||
Nonce: 1,
|
||||
GasPrice: big.NewInt(1),
|
||||
Gas: 1,
|
||||
To: new(common.Address),
|
||||
Value: big.NewInt(5),
|
||||
Data: []byte{0x11, 0x11, 0x11},
|
||||
})
|
||||
tx2 := types.NewTx(&types.AccessListTx{
|
||||
Nonce: 1,
|
||||
GasPrice: big.NewInt(1),
|
||||
Gas: 1,
|
||||
To: new(common.Address),
|
||||
Value: big.NewInt(5),
|
||||
Data: []byte{0x11, 0x11, 0x11},
|
||||
AccessList: []types.AccessTuple{
|
||||
{
|
||||
Address: common.Address{0x1},
|
||||
StorageKeys: []common.Hash{{0x1}, {0x2}},
|
||||
},
|
||||
},
|
||||
})
|
||||
tx3 := types.NewTx(&types.DynamicFeeTx{
|
||||
Nonce: 1,
|
||||
Gas: 1,
|
||||
To: new(common.Address),
|
||||
Value: big.NewInt(5),
|
||||
Data: []byte{0x11, 0x11, 0x11},
|
||||
GasTipCap: big.NewInt(55),
|
||||
GasFeeCap: big.NewInt(1055),
|
||||
AccessList: []types.AccessTuple{
|
||||
{
|
||||
Address: common.Address{0x1},
|
||||
StorageKeys: []common.Hash{{0x1}, {0x2}},
|
||||
},
|
||||
},
|
||||
})
|
||||
tx4 := types.NewTx(&types.BlobTx{
|
||||
Nonce: 1,
|
||||
Gas: 1,
|
||||
To: common.Address{0x1},
|
||||
Value: uint256.NewInt(5),
|
||||
Data: []byte{0x11, 0x11, 0x11},
|
||||
GasTipCap: uint256.NewInt(55),
|
||||
GasFeeCap: uint256.NewInt(1055),
|
||||
AccessList: []types.AccessTuple{
|
||||
{
|
||||
Address: common.Address{0x1},
|
||||
StorageKeys: []common.Hash{{0x1}, {0x2}},
|
||||
},
|
||||
},
|
||||
BlobFeeCap: uint256.NewInt(1),
|
||||
BlobHashes: []common.Hash{{0x1}, {0x2}},
|
||||
})
|
||||
tx5 := types.NewTx(&types.SetCodeTx{
|
||||
Nonce: 1,
|
||||
Gas: 1,
|
||||
To: common.Address{0x1},
|
||||
Value: uint256.NewInt(5),
|
||||
Data: []byte{0x11, 0x11, 0x11},
|
||||
GasTipCap: uint256.NewInt(55),
|
||||
GasFeeCap: uint256.NewInt(1055),
|
||||
AccessList: []types.AccessTuple{
|
||||
{
|
||||
Address: common.Address{0x1},
|
||||
StorageKeys: []common.Hash{{0x1}, {0x2}},
|
||||
},
|
||||
},
|
||||
AuthList: []types.SetCodeAuthorization{
|
||||
{
|
||||
ChainID: uint256.Int{1},
|
||||
Address: common.Address{0x1},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
txs := []*types.Transaction{tx1, tx2, tx3, tx4, tx5}
|
||||
|
||||
block := types.NewBlock(&types.Header{Number: big.NewInt(314)}, &types.Body{Transactions: txs}, nil, newTestHasher())
|
||||
db := NewMemoryDatabase()
|
||||
WriteBlock(db, block)
|
||||
|
||||
rlp := ReadBodyRLP(db, block.Hash(), block.NumberU64())
|
||||
for i := 0; i < len(txs); i++ {
|
||||
tx, txIndex, err := traverseBlockBody(rlp, txs[i].Hash())
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to retrieve tx, err: %v", err)
|
||||
}
|
||||
if txIndex != uint64(i) {
|
||||
t.Fatalf("Unexpected transaction index, want: %d, got: %d", i, txIndex)
|
||||
}
|
||||
if tx.Hash() != txs[i].Hash() {
|
||||
want := spew.Sdump(txs[i])
|
||||
got := spew.Sdump(tx)
|
||||
t.Fatalf("Unexpected transaction, want: %s, got: %s", want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue