Commit 8612f32b authored by Adrian Sutton's avatar Adrian Sutton

op-service: Add unit tests for verifying receipts.

parent 57413031
......@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"math/big"
"math/rand"
"testing"
"time"
......@@ -17,6 +18,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
......@@ -338,3 +340,233 @@ func TestEthClient_FetchReceipts(t *testing.T) {
t.Run(tc.name, tc.Run)
}
}
func TestVerifyReceipts(t *testing.T) {
validData := func() (eth.BlockID, common.Hash, []common.Hash, []*types.Receipt) {
block := eth.BlockID{
Hash: common.HexToHash("0x40fb7cc5fbc1ec594230a60648a442412116d50ae43d517ea458d8ea4e60bd1b"),
Number: 9998910,
}
txHashes := []common.Hash{
common.HexToHash("0x61e4872004a80843fcbede236527bf24707f4e8f44a2704ed9c4fb91c87b0f29"),
common.HexToHash("0x0ae25ad9ff01fd74fa1b0c11f12fbb623a3f0553a0eed465a6dbf0962898c3b6"),
common.HexToHash("0x2de33b18143039dcdf88cb62c3f3dd8f3f5d9f29807edfd3b0507246c55f9cb8"),
common.HexToHash("0xb6a381d3c31df47da82ac807c3000ae4adf55e981715f56d13a27b220de20198"),
}
receipts := []*types.Receipt{
{
Type: 2,
Status: 0,
CumulativeGasUsed: 0x3035b,
Bloom: types.BytesToBloom(common.Hex2Bytes("0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")),
Logs: nil,
TxHash: txHashes[0],
GasUsed: 0x3035b,
EffectiveGasPrice: big.NewInt(0x12a05f20a),
BlockHash: block.Hash,
BlockNumber: new(big.Int).SetUint64(block.Number),
TransactionIndex: 0,
},
{
Type: 2,
Status: 1,
CumulativeGasUsed: 0xa9ae4,
Bloom: types.BytesToBloom(common.Hex2Bytes("0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")),
Logs: nil,
TxHash: txHashes[1],
GasUsed: 0x79789,
EffectiveGasPrice: big.NewInt(0xb2d05e0a),
BlockHash: block.Hash,
BlockNumber: new(big.Int).SetUint64(block.Number),
TransactionIndex: 1,
},
{
Type: 0,
Status: 1,
CumulativeGasUsed: 0x101f09,
Bloom: types.BytesToBloom(common.Hex2Bytes("0x00000000000000000000000000000200000400000000000000000000000000800000000000040000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000800000000000000000000000000000000000000000000000000000400000000000000020000000000000000000000000002000000000000000000000000000000000000000000")),
Logs: []*types.Log{
{
Address: common.HexToAddress("0x759c5e44a9e4be8b7e9bd25a790ceb662c924c45"),
Topics: []common.Hash{
common.HexToHash("0x33830f93f4b524630176cdcbc04070b30ada13c6ad27081289131b77f178ff89"),
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000426a80"),
common.HexToHash("0x000000000000000000000000a6275ee214f80a532c3abee0a4cbbc2d1dc22a72"),
},
Data: common.Hex2Bytes("0x00000000000000000000000000000000000000000000000000000000000005dc"),
BlockNumber: block.Number,
TxHash: txHashes[2],
TxIndex: 2,
BlockHash: block.Hash,
Index: 0,
Removed: false,
},
},
TxHash: txHashes[2],
GasUsed: 0x58425,
EffectiveGasPrice: big.NewInt(0xb2d05e00),
BlockHash: block.Hash,
BlockNumber: new(big.Int).SetUint64(block.Number),
TransactionIndex: 2,
},
{
Type: 0,
Status: 1,
CumulativeGasUsed: 0x1227ab,
Bloom: types.BytesToBloom(common.Hex2Bytes("0x00000000000000000000000000000200000400000000000000000000000000800000000000040000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000800000000000000000000000000000000000000000000000000000400000000000000020000000000000000000000000002000000000000000000000000000000000000000000")),
Logs: []*types.Log{
{
Address: common.HexToAddress("0x759c5e44a9e4be8b7e9bd25a790ceb662c924c45"),
Topics: []common.Hash{
common.HexToHash("0x33830f93f4b524630176cdcbc04070b30ada13c6ad27081289131b77f178ff89"),
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000426a80"),
common.HexToHash("0x000000000000000000000000a6275ee214f80a532c3abee0a4cbbc2d1dc22a72"),
},
Data: common.Hex2Bytes("0x00000000000000000000000000000000000000000000000000000000000005dc"),
BlockNumber: block.Number,
TxHash: txHashes[3],
TxIndex: 3,
BlockHash: block.Hash,
Index: 1,
Removed: false,
},
},
TxHash: txHashes[3],
GasUsed: 0x208a2,
EffectiveGasPrice: big.NewInt(0x59682f0a),
BlockHash: block.Hash,
BlockNumber: new(big.Int).SetUint64(block.Number),
TransactionIndex: 3,
},
}
receiptsHash := types.DeriveSha(types.Receipts(receipts), trie.NewStackTrie(nil))
return block, receiptsHash, txHashes, receipts
}
t.Run("Valid", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.NoError(t, err)
})
t.Run("NotEnoughReceipts", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
err := validateReceipts(block, receiptHash, txHashes, receipts[1:])
require.ErrorContains(t, err, fmt.Sprintf("got %d receipts but expected %d", len(receipts)-1, len(receipts)))
})
t.Run("TooManyReceipts", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
err := validateReceipts(block, receiptHash, txHashes, append(receipts, receipts[0]))
require.ErrorContains(t, err, fmt.Sprintf("got %d receipts but expected %d", len(receipts)+1, len(receipts)))
})
t.Run("NoTxButNotEmptyTrieRoot", func(t *testing.T) {
block, receiptHash, _, _ := validData()
err := validateReceipts(block, receiptHash, nil, nil)
require.ErrorContains(t, err, "no transactions, but got non-empty receipt trie root")
})
t.Run("NoTxWithEmptyTrieRoot", func(t *testing.T) {
block, _, _, _ := validData()
err := validateReceipts(block, types.EmptyRootHash, nil, nil)
require.NoError(t, err)
})
t.Run("IncorrectReceiptRoot", func(t *testing.T) {
block, _, txHashes, receipts := validData()
err := validateReceipts(block, common.Hash{0x35}, txHashes, receipts)
require.ErrorContains(t, err, "failed to fetch list of receipts: expected receipt root")
})
t.Run("NilReceipt", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[0] = nil
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "returns nil on retrieval")
})
t.Run("IncorrectTxIndex", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[0].TransactionIndex = 2
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has unexpected tx index")
})
t.Run("Missing block number", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[0].BlockNumber = nil
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has unexpected nil block number")
})
t.Run("IncorrectBlockNumber", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[0].BlockNumber = big.NewInt(1234)
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has unexpected block number")
})
t.Run("IncorrectBlockHash", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[0].BlockHash = common.Hash{0x48}
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has unexpected block hash")
})
t.Run("IncorrectCumulativeUsed", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[1].CumulativeGasUsed = receipts[0].CumulativeGasUsed
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has invalid gas used metadata")
})
t.Run("IncorrectLogIndex", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[2].Logs[0].Index = 4
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has unexpected log index")
})
t.Run("LogIndexNotBlockBased", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[3].Logs[0].Index = 0
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has unexpected log index")
})
t.Run("IncorrectLogTxIndex", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[2].Logs[0].TxIndex = 1
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has unexpected tx index")
})
t.Run("IncorrectLogBlockHash", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[2].Logs[0].BlockHash = common.Hash{0x64}
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has unexpected block hash")
})
t.Run("IncorrectLogBlockNumber", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[2].Logs[0].BlockNumber = 4727923
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has unexpected block number")
})
t.Run("IncorrectLogTxHash", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[2].Logs[0].TxHash = common.Hash{0x87}
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "has unexpected tx hash")
})
t.Run("Removed", func(t *testing.T) {
block, receiptHash, txHashes, receipts := validData()
receipts[2].Logs[0].Removed = true
err := validateReceipts(block, receiptHash, txHashes, receipts)
require.ErrorContains(t, err, "must never be removed due to reorg")
})
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment