@ -22,69 +22,87 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
)
// Tests that positional lookup metadata can be stored and retrieved.
func TestLookupStorage ( t * testing . T ) {
db := NewMemoryDatabase ( )
tests := [ ] struct {
name string
writeTxLookupEntries func ( ethdb . Writer , * types . Block )
} {
{
"DatabaseV6" ,
func ( db ethdb . Writer , block * types . Block ) {
WriteTxLookupEntries ( db , block )
} ,
} ,
{
"DatabaseV4-V5" ,
func ( db ethdb . Writer , block * types . Block ) {
for _ , tx := range block . Transactions ( ) {
db . Put ( txLookupKey ( tx . Hash ( ) ) , block . Hash ( ) . Bytes ( ) )
}
} ,
} ,
{
"DatabaseV3" ,
func ( db ethdb . Writer , block * types . Block ) {
for index , tx := range block . Transactions ( ) {
entry := LegacyTxLookupEntry {
BlockHash : block . Hash ( ) ,
BlockIndex : block . NumberU64 ( ) ,
Index : uint64 ( index ) ,
}
data , _ := rlp . EncodeToBytes ( entry )
db . Put ( txLookupKey ( tx . Hash ( ) ) , data )
}
} ,
} ,
}
tx1 := types . NewTransaction ( 1 , common . BytesToAddress ( [ ] byte { 0x11 } ) , big . NewInt ( 111 ) , 1111 , big . NewInt ( 11111 ) , [ ] byte { 0x11 , 0x11 , 0x11 } )
tx2 := types . NewTransaction ( 2 , common . BytesToAddress ( [ ] byte { 0x22 } ) , big . NewInt ( 222 ) , 2222 , big . NewInt ( 22222 ) , [ ] byte { 0x22 , 0x22 , 0x22 } )
tx3 := types . NewTransaction ( 3 , common . BytesToAddress ( [ ] byte { 0x33 } ) , big . NewInt ( 333 ) , 3333 , big . NewInt ( 33333 ) , [ ] byte { 0x33 , 0x33 , 0x33 } )
txs := [ ] * types . Transaction { tx1 , tx2 , tx3 }
for _ , tc := range tests {
t . Run ( tc . name , func ( t * testing . T ) {
db := NewMemoryDatabase ( )
block := types . NewBlock ( & types . Header { Number : big . NewInt ( 314 ) } , txs , nil , nil )
tx1 := types . NewTransaction ( 1 , common . BytesToAddress ( [ ] byte { 0x11 } ) , big . NewInt ( 111 ) , 1111 , big . NewInt ( 11111 ) , [ ] byte { 0x11 , 0x11 , 0x11 } )
tx2 := types . NewTransaction ( 2 , common . BytesToAddress ( [ ] byte { 0x22 } ) , big . NewInt ( 222 ) , 2222 , big . NewInt ( 22222 ) , [ ] byte { 0x22 , 0x22 , 0x22 } )
tx3 := types . NewTransaction ( 3 , common . BytesToAddress ( [ ] byte { 0x33 } ) , big . NewInt ( 333 ) , 3333 , big . NewInt ( 33333 ) , [ ] byte { 0x33 , 0x33 , 0x33 } )
txs := [ ] * types . Transaction { tx1 , tx2 , tx3 }
// Check that no transactions entries are in a pristine database
for i , tx := range txs {
if txn , _ , _ , _ := ReadTransaction ( db , tx . Hash ( ) ) ; txn != nil {
t . Fatalf ( "tx #%d [%x]: non existent transaction returned: %v" , i , tx . Hash ( ) , txn )
}
}
// Insert all the transactions into the database, and verify contents
WriteBlock ( db , block )
WriteTxLookupEntries ( db , block )
block := types . NewBlock ( & types . Header { Number : big . NewInt ( 314 ) } , txs , nil , nil )
for i , tx := range txs {
if txn , hash , number , index := ReadTransaction ( db , tx . Hash ( ) ) ; txn == nil {
t . Fatalf ( "tx #%d [%x]: transaction not found" , i , tx . Hash ( ) )
} else {
if hash != block . Hash ( ) || number != block . NumberU64 ( ) || index != uint64 ( i ) {
t . Fatalf ( "tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v" , i , tx . Hash ( ) , hash , number , index , block . Hash ( ) , block . NumberU64 ( ) , i )
// Check that no transactions entries are in a pristine database
for i , tx := range txs {
if txn , _ , _ , _ := ReadTransaction ( db , tx . Hash ( ) ) ; txn != nil {
t . Fatalf ( "tx #%d [%x]: non existent transaction returned: %v" , i , tx . Hash ( ) , txn )
}
}
if tx . Hash ( ) != txn . Hash ( ) {
t . Fatalf ( "tx #%d [%x]: transaction mismatch: have %v, want %v" , i , tx . Hash ( ) , txn , tx )
}
}
}
// Delete the transactions and check purge
for i , tx := range txs {
DeleteTxLookupEntry ( db , tx . Hash ( ) )
if txn , _ , _ , _ := ReadTransaction ( db , tx . Hash ( ) ) ; txn != nil {
t . Fatalf ( "tx #%d [%x]: deleted transaction returned: %v" , i , tx . Hash ( ) , txn )
}
}
// Insert legacy txlookup and verify the data retrieval
for index , tx := range block . Transactions ( ) {
entry := LegacyTxLookupEntry {
BlockHash : block . Hash ( ) ,
BlockIndex : block . NumberU64 ( ) ,
Index : uint64 ( index ) ,
}
data , _ := rlp . EncodeToBytes ( entry )
db . Put ( txLookupKey ( tx . Hash ( ) ) , data )
}
for i , tx := range txs {
if txn , hash , number , index := ReadTransaction ( db , tx . Hash ( ) ) ; txn == nil {
t . Fatalf ( "tx #%d [%x]: transaction not found" , i , tx . Hash ( ) )
} else {
if hash != block . Hash ( ) || number != block . NumberU64 ( ) || index != uint64 ( i ) {
t . Fatalf ( "tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v" , i , tx . Hash ( ) , hash , number , index , block . Hash ( ) , block . NumberU64 ( ) , i )
// Insert all the transactions into the database, and verify contents
WriteCanonicalHash ( db , block . Hash ( ) , block . NumberU64 ( ) )
WriteBlock ( db , block )
tc . writeTxLookupEntries ( db , block )
for i , tx := range txs {
if txn , hash , number , index := ReadTransaction ( db , tx . Hash ( ) ) ; txn == nil {
t . Fatalf ( "tx #%d [%x]: transaction not found" , i , tx . Hash ( ) )
} else {
if hash != block . Hash ( ) || number != block . NumberU64 ( ) || index != uint64 ( i ) {
t . Fatalf ( "tx #%d [%x]: positional metadata mismatch: have %x/%d/%d, want %x/%v/%v" , i , tx . Hash ( ) , hash , number , index , block . Hash ( ) , block . NumberU64 ( ) , i )
}
if tx . Hash ( ) != txn . Hash ( ) {
t . Fatalf ( "tx #%d [%x]: transaction mismatch: have %v, want %v" , i , tx . Hash ( ) , txn , tx )
}
}
}
if tx . Hash ( ) != txn . Hash ( ) {
t . Fatalf ( "tx #%d [%x]: transaction mismatch: have %v, want %v" , i , tx . Hash ( ) , txn , tx )
// Delete the transactions and check purge
for i , tx := range txs {
DeleteTxLookupEntry ( db , tx . Hash ( ) )
if txn , _ , _ , _ := ReadTransaction ( db , tx . Hash ( ) ) ; txn != nil {
t . Fatalf ( "tx #%d [%x]: deleted transaction returned: %v" , i , tx . Hash ( ) , txn )
}
}
}
} )
}
}