Commit edb6603f authored by OptimismBot's avatar OptimismBot Committed by GitHub

Merge pull request #5465 from ethereum-optimism/aj/fpp-test-stubs

op-program: Extract stub oracles to a reusable test package
parents 77194e21 404cee1b
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/testutils" "github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum-optimism/optimism/op-program/client/l1/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -14,37 +15,37 @@ var _ Oracle = (*CachingOracle)(nil) ...@@ -14,37 +15,37 @@ var _ Oracle = (*CachingOracle)(nil)
func TestCachingOracle_HeaderByBlockHash(t *testing.T) { func TestCachingOracle_HeaderByBlockHash(t *testing.T) {
rng := rand.New(rand.NewSource(1)) rng := rand.New(rand.NewSource(1))
stub := newStubOracle(t) stub := test.NewStubOracle(t)
oracle := NewCachingOracle(stub) oracle := NewCachingOracle(stub)
block := testutils.RandomBlockInfo(rng) block := testutils.RandomBlockInfo(rng)
// Initial call retrieves from the stub // Initial call retrieves from the stub
stub.blocks[block.Hash()] = block stub.Blocks[block.Hash()] = block
result := oracle.HeaderByBlockHash(block.Hash()) result := oracle.HeaderByBlockHash(block.Hash())
require.Equal(t, block, result) require.Equal(t, block, result)
// Later calls should retrieve from cache // Later calls should retrieve from cache
delete(stub.blocks, block.Hash()) delete(stub.Blocks, block.Hash())
result = oracle.HeaderByBlockHash(block.Hash()) result = oracle.HeaderByBlockHash(block.Hash())
require.Equal(t, block, result) require.Equal(t, block, result)
} }
func TestCachingOracle_TransactionsByBlockHash(t *testing.T) { func TestCachingOracle_TransactionsByBlockHash(t *testing.T) {
rng := rand.New(rand.NewSource(1)) rng := rand.New(rand.NewSource(1))
stub := newStubOracle(t) stub := test.NewStubOracle(t)
oracle := NewCachingOracle(stub) oracle := NewCachingOracle(stub)
block, _ := testutils.RandomBlock(rng, 3) block, _ := testutils.RandomBlock(rng, 3)
// Initial call retrieves from the stub // Initial call retrieves from the stub
stub.blocks[block.Hash()] = eth.BlockToInfo(block) stub.Blocks[block.Hash()] = eth.BlockToInfo(block)
stub.txs[block.Hash()] = block.Transactions() stub.Txs[block.Hash()] = block.Transactions()
actualBlock, actualTxs := oracle.TransactionsByBlockHash(block.Hash()) actualBlock, actualTxs := oracle.TransactionsByBlockHash(block.Hash())
require.Equal(t, eth.BlockToInfo(block), actualBlock) require.Equal(t, eth.BlockToInfo(block), actualBlock)
require.Equal(t, block.Transactions(), actualTxs) require.Equal(t, block.Transactions(), actualTxs)
// Later calls should retrieve from cache // Later calls should retrieve from cache
delete(stub.blocks, block.Hash()) delete(stub.Blocks, block.Hash())
delete(stub.txs, block.Hash()) delete(stub.Txs, block.Hash())
actualBlock, actualTxs = oracle.TransactionsByBlockHash(block.Hash()) actualBlock, actualTxs = oracle.TransactionsByBlockHash(block.Hash())
require.Equal(t, eth.BlockToInfo(block), actualBlock) require.Equal(t, eth.BlockToInfo(block), actualBlock)
require.Equal(t, block.Transactions(), actualTxs) require.Equal(t, block.Transactions(), actualTxs)
...@@ -52,20 +53,20 @@ func TestCachingOracle_TransactionsByBlockHash(t *testing.T) { ...@@ -52,20 +53,20 @@ func TestCachingOracle_TransactionsByBlockHash(t *testing.T) {
func TestCachingOracle_ReceiptsByBlockHash(t *testing.T) { func TestCachingOracle_ReceiptsByBlockHash(t *testing.T) {
rng := rand.New(rand.NewSource(1)) rng := rand.New(rand.NewSource(1))
stub := newStubOracle(t) stub := test.NewStubOracle(t)
oracle := NewCachingOracle(stub) oracle := NewCachingOracle(stub)
block, rcpts := testutils.RandomBlock(rng, 3) block, rcpts := testutils.RandomBlock(rng, 3)
// Initial call retrieves from the stub // Initial call retrieves from the stub
stub.blocks[block.Hash()] = eth.BlockToInfo(block) stub.Blocks[block.Hash()] = eth.BlockToInfo(block)
stub.rcpts[block.Hash()] = rcpts stub.Rcpts[block.Hash()] = rcpts
actualBlock, actualRcpts := oracle.ReceiptsByBlockHash(block.Hash()) actualBlock, actualRcpts := oracle.ReceiptsByBlockHash(block.Hash())
require.Equal(t, eth.BlockToInfo(block), actualBlock) require.Equal(t, eth.BlockToInfo(block), actualBlock)
require.EqualValues(t, rcpts, actualRcpts) require.EqualValues(t, rcpts, actualRcpts)
// Later calls should retrieve from cache // Later calls should retrieve from cache
delete(stub.blocks, block.Hash()) delete(stub.Blocks, block.Hash())
delete(stub.rcpts, block.Hash()) delete(stub.Rcpts, block.Hash())
actualBlock, actualRcpts = oracle.ReceiptsByBlockHash(block.Hash()) actualBlock, actualRcpts = oracle.ReceiptsByBlockHash(block.Hash())
require.Equal(t, eth.BlockToInfo(block), actualBlock) require.Equal(t, eth.BlockToInfo(block), actualBlock)
require.EqualValues(t, rcpts, actualRcpts) require.EqualValues(t, rcpts, actualRcpts)
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/testutils" "github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum-optimism/optimism/op-program/client/l1/test"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -24,7 +25,7 @@ func TestInfoByHash(t *testing.T) { ...@@ -24,7 +25,7 @@ func TestInfoByHash(t *testing.T) {
client, oracle := newClient(t) client, oracle := newClient(t)
hash := common.HexToHash("0xAABBCC") hash := common.HexToHash("0xAABBCC")
expected := &testutils.MockBlockInfo{} expected := &testutils.MockBlockInfo{}
oracle.blocks[hash] = expected oracle.Blocks[hash] = expected
info, err := client.InfoByHash(context.Background(), hash) info, err := client.InfoByHash(context.Background(), hash)
require.NoError(t, err) require.NoError(t, err)
...@@ -35,7 +36,7 @@ func TestL1BlockRefByHash(t *testing.T) { ...@@ -35,7 +36,7 @@ func TestL1BlockRefByHash(t *testing.T) {
client, oracle := newClient(t) client, oracle := newClient(t)
hash := common.HexToHash("0xAABBCC") hash := common.HexToHash("0xAABBCC")
header := &testutils.MockBlockInfo{} header := &testutils.MockBlockInfo{}
oracle.blocks[hash] = header oracle.Blocks[hash] = header
expected := eth.InfoToL1BlockRef(header) expected := eth.InfoToL1BlockRef(header)
ref, err := client.L1BlockRefByHash(context.Background(), hash) ref, err := client.L1BlockRefByHash(context.Background(), hash)
...@@ -50,8 +51,8 @@ func TestFetchReceipts(t *testing.T) { ...@@ -50,8 +51,8 @@ func TestFetchReceipts(t *testing.T) {
expectedReceipts := types.Receipts{ expectedReceipts := types.Receipts{
&types.Receipt{}, &types.Receipt{},
} }
oracle.blocks[hash] = expectedInfo oracle.Blocks[hash] = expectedInfo
oracle.rcpts[hash] = expectedReceipts oracle.Rcpts[hash] = expectedReceipts
info, rcpts, err := client.FetchReceipts(context.Background(), hash) info, rcpts, err := client.FetchReceipts(context.Background(), hash)
require.NoError(t, err) require.NoError(t, err)
...@@ -66,8 +67,8 @@ func TestInfoAndTxsByHash(t *testing.T) { ...@@ -66,8 +67,8 @@ func TestInfoAndTxsByHash(t *testing.T) {
expectedTxs := types.Transactions{ expectedTxs := types.Transactions{
&types.Transaction{}, &types.Transaction{},
} }
oracle.blocks[hash] = expectedInfo oracle.Blocks[hash] = expectedInfo
oracle.txs[hash] = expectedTxs oracle.Txs[hash] = expectedTxs
info, txs, err := client.InfoAndTxsByHash(context.Background(), hash) info, txs, err := client.InfoAndTxsByHash(context.Background(), hash)
require.NoError(t, err) require.NoError(t, err)
...@@ -119,7 +120,7 @@ func TestL1BlockRefByNumber(t *testing.T) { ...@@ -119,7 +120,7 @@ func TestL1BlockRefByNumber(t *testing.T) {
t.Run("ParentOfHead", func(t *testing.T) { t.Run("ParentOfHead", func(t *testing.T) {
client, oracle := newClient(t) client, oracle := newClient(t)
parent := blockNum(head.NumberU64() - 1) parent := blockNum(head.NumberU64() - 1)
oracle.blocks[parent.Hash()] = parent oracle.Blocks[parent.Hash()] = parent
ref, err := client.L1BlockRefByNumber(context.Background(), parent.NumberU64()) ref, err := client.L1BlockRefByNumber(context.Background(), parent.NumberU64())
require.NoError(t, err) require.NoError(t, err)
...@@ -131,7 +132,7 @@ func TestL1BlockRefByNumber(t *testing.T) { ...@@ -131,7 +132,7 @@ func TestL1BlockRefByNumber(t *testing.T) {
blocks := []eth.BlockInfo{block} blocks := []eth.BlockInfo{block}
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
block = blockNum(block.NumberU64() - 1) block = blockNum(block.NumberU64() - 1)
oracle.blocks[block.Hash()] = block oracle.Blocks[block.Hash()] = block
blocks = append(blocks, block) blocks = append(blocks, block)
} }
...@@ -143,9 +144,9 @@ func TestL1BlockRefByNumber(t *testing.T) { ...@@ -143,9 +144,9 @@ func TestL1BlockRefByNumber(t *testing.T) {
}) })
} }
func newClient(t *testing.T) (*OracleL1Client, *stubOracle) { func newClient(t *testing.T) (*OracleL1Client, *test.StubOracle) {
stub := newStubOracle(t) stub := test.NewStubOracle(t)
stub.blocks[head.Hash()] = head stub.Blocks[head.Hash()] = head
client := NewOracleL1Client(testlog.Logger(t, log.LvlDebug), stub, head.Hash()) client := NewOracleL1Client(testlog.Logger(t, log.LvlDebug), stub, head.Hash())
return client, stub return client, stub
} }
......
package l1 package test
import ( import (
"testing" "testing"
...@@ -8,45 +8,45 @@ import ( ...@@ -8,45 +8,45 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
) )
type stubOracle struct { type StubOracle struct {
t *testing.T t *testing.T
// blocks maps block hash to eth.BlockInfo // Blocks maps block hash to eth.BlockInfo
blocks map[common.Hash]eth.BlockInfo Blocks map[common.Hash]eth.BlockInfo
// txs maps block hash to transactions // Txs maps block hash to transactions
txs map[common.Hash]types.Transactions Txs map[common.Hash]types.Transactions
// rcpts maps Block hash to receipts // Rcpts maps Block hash to receipts
rcpts map[common.Hash]types.Receipts Rcpts map[common.Hash]types.Receipts
} }
func newStubOracle(t *testing.T) *stubOracle { func NewStubOracle(t *testing.T) *StubOracle {
return &stubOracle{ return &StubOracle{
t: t, t: t,
blocks: make(map[common.Hash]eth.BlockInfo), Blocks: make(map[common.Hash]eth.BlockInfo),
txs: make(map[common.Hash]types.Transactions), Txs: make(map[common.Hash]types.Transactions),
rcpts: make(map[common.Hash]types.Receipts), Rcpts: make(map[common.Hash]types.Receipts),
} }
} }
func (o stubOracle) HeaderByBlockHash(blockHash common.Hash) eth.BlockInfo { func (o StubOracle) HeaderByBlockHash(blockHash common.Hash) eth.BlockInfo {
info, ok := o.blocks[blockHash] info, ok := o.Blocks[blockHash]
if !ok { if !ok {
o.t.Fatalf("unknown block %s", blockHash) o.t.Fatalf("unknown block %s", blockHash)
} }
return info return info
} }
func (o stubOracle) TransactionsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Transactions) { func (o StubOracle) TransactionsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Transactions) {
txs, ok := o.txs[blockHash] txs, ok := o.Txs[blockHash]
if !ok { if !ok {
o.t.Fatalf("unknown txs %s", blockHash) o.t.Fatalf("unknown txs %s", blockHash)
} }
return o.HeaderByBlockHash(blockHash), txs return o.HeaderByBlockHash(blockHash), txs
} }
func (o stubOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Receipts) { func (o StubOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Receipts) {
rcpts, ok := o.rcpts[blockHash] rcpts, ok := o.Rcpts[blockHash]
if !ok { if !ok {
o.t.Fatalf("unknown rcpts %s", blockHash) o.t.Fatalf("unknown rcpts %s", blockHash)
} }
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-node/testutils" "github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum-optimism/optimism/op-program/client/l2/test"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -13,55 +14,55 @@ import ( ...@@ -13,55 +14,55 @@ import (
var _ Oracle = (*CachingOracle)(nil) var _ Oracle = (*CachingOracle)(nil)
func TestBlockByHash(t *testing.T) { func TestBlockByHash(t *testing.T) {
stub, _ := newStubOracle(t) stub, _ := test.NewStubOracle(t)
oracle := NewCachingOracle(stub) oracle := NewCachingOracle(stub)
rng := rand.New(rand.NewSource(1)) rng := rand.New(rand.NewSource(1))
block, _ := testutils.RandomBlock(rng, 1) block, _ := testutils.RandomBlock(rng, 1)
// Initial call retrieves from the stub // Initial call retrieves from the stub
stub.blocks[block.Hash()] = block stub.Blocks[block.Hash()] = block
actual := oracle.BlockByHash(block.Hash()) actual := oracle.BlockByHash(block.Hash())
require.Equal(t, block, actual) require.Equal(t, block, actual)
// Later calls should retrieve from cache // Later calls should retrieve from cache
delete(stub.blocks, block.Hash()) delete(stub.Blocks, block.Hash())
actual = oracle.BlockByHash(block.Hash()) actual = oracle.BlockByHash(block.Hash())
require.Equal(t, block, actual) require.Equal(t, block, actual)
} }
func TestNodeByHash(t *testing.T) { func TestNodeByHash(t *testing.T) {
stub, stateStub := newStubOracle(t) stub, stateStub := test.NewStubOracle(t)
oracle := NewCachingOracle(stub) oracle := NewCachingOracle(stub)
node := []byte{12, 3, 4} node := []byte{12, 3, 4}
hash := common.Hash{0xaa} hash := common.Hash{0xaa}
// Initial call retrieves from the stub // Initial call retrieves from the stub
stateStub.data[hash] = node stateStub.Data[hash] = node
actual := oracle.NodeByHash(hash) actual := oracle.NodeByHash(hash)
require.Equal(t, node, actual) require.Equal(t, node, actual)
// Later calls should retrieve from cache // Later calls should retrieve from cache
delete(stateStub.data, hash) delete(stateStub.Data, hash)
actual = oracle.NodeByHash(hash) actual = oracle.NodeByHash(hash)
require.Equal(t, node, actual) require.Equal(t, node, actual)
} }
func TestCodeByHash(t *testing.T) { func TestCodeByHash(t *testing.T) {
stub, stateStub := newStubOracle(t) stub, stateStub := test.NewStubOracle(t)
oracle := NewCachingOracle(stub) oracle := NewCachingOracle(stub)
node := []byte{12, 3, 4} node := []byte{12, 3, 4}
hash := common.Hash{0xaa} hash := common.Hash{0xaa}
// Initial call retrieves from the stub // Initial call retrieves from the stub
stateStub.code[hash] = node stateStub.Code[hash] = node
actual := oracle.CodeByHash(hash) actual := oracle.CodeByHash(hash)
require.Equal(t, node, actual) require.Equal(t, node, actual)
// Later calls should retrieve from cache // Later calls should retrieve from cache
delete(stateStub.code, hash) delete(stateStub.Code, hash)
actual = oracle.CodeByHash(hash) actual = oracle.CodeByHash(hash)
require.Equal(t, node, actual) require.Equal(t, node, actual)
} }
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"math/big" "math/big"
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-program/client/l2/test"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
...@@ -27,7 +28,7 @@ var _ ethdb.KeyValueStore = (*OracleKeyValueStore)(nil) ...@@ -27,7 +28,7 @@ var _ ethdb.KeyValueStore = (*OracleKeyValueStore)(nil)
func TestGet(t *testing.T) { func TestGet(t *testing.T) {
t.Run("IncorrectLengthKey", func(t *testing.T) { t.Run("IncorrectLengthKey", func(t *testing.T) {
oracle := newStubStateOracle(t) oracle := test.NewStubStateOracle(t)
db := NewOracleBackedDB(oracle) db := NewOracleBackedDB(oracle)
val, err := db.Get([]byte{1, 2, 3}) val, err := db.Get([]byte{1, 2, 3})
require.ErrorIs(t, err, ErrInvalidKeyLength) require.ErrorIs(t, err, ErrInvalidKeyLength)
...@@ -35,13 +36,13 @@ func TestGet(t *testing.T) { ...@@ -35,13 +36,13 @@ func TestGet(t *testing.T) {
}) })
t.Run("KeyWithCodePrefix", func(t *testing.T) { t.Run("KeyWithCodePrefix", func(t *testing.T) {
oracle := newStubStateOracle(t) oracle := test.NewStubStateOracle(t)
db := NewOracleBackedDB(oracle) db := NewOracleBackedDB(oracle)
key := common.HexToHash("0x12345678") key := common.HexToHash("0x12345678")
prefixedKey := append(rawdb.CodePrefix, key.Bytes()...) prefixedKey := append(rawdb.CodePrefix, key.Bytes()...)
expected := []byte{1, 2, 3} expected := []byte{1, 2, 3}
oracle.code[key] = expected oracle.Code[key] = expected
val, err := db.Get(prefixedKey) val, err := db.Get(prefixedKey)
require.NoError(t, err) require.NoError(t, err)
...@@ -49,13 +50,13 @@ func TestGet(t *testing.T) { ...@@ -49,13 +50,13 @@ func TestGet(t *testing.T) {
}) })
t.Run("NormalKeyThatHappensToStartWithCodePrefix", func(t *testing.T) { t.Run("NormalKeyThatHappensToStartWithCodePrefix", func(t *testing.T) {
oracle := newStubStateOracle(t) oracle := test.NewStubStateOracle(t)
db := NewOracleBackedDB(oracle) db := NewOracleBackedDB(oracle)
key := make([]byte, common.HashLength) key := make([]byte, common.HashLength)
copy(rawdb.CodePrefix, key) copy(rawdb.CodePrefix, key)
println(key[0]) println(key[0])
expected := []byte{1, 2, 3} expected := []byte{1, 2, 3}
oracle.data[common.BytesToHash(key)] = expected oracle.Data[common.BytesToHash(key)] = expected
val, err := db.Get(key) val, err := db.Get(key)
require.NoError(t, err) require.NoError(t, err)
...@@ -65,8 +66,8 @@ func TestGet(t *testing.T) { ...@@ -65,8 +66,8 @@ func TestGet(t *testing.T) {
t.Run("KnownKey", func(t *testing.T) { t.Run("KnownKey", func(t *testing.T) {
key := common.HexToHash("0xAA4488") key := common.HexToHash("0xAA4488")
expected := []byte{2, 6, 3, 8} expected := []byte{2, 6, 3, 8}
oracle := newStubStateOracle(t) oracle := test.NewStubStateOracle(t)
oracle.data[key] = expected oracle.Data[key] = expected
db := NewOracleBackedDB(oracle) db := NewOracleBackedDB(oracle)
val, err := db.Get(key.Bytes()) val, err := db.Get(key.Bytes())
require.NoError(t, err) require.NoError(t, err)
...@@ -76,7 +77,7 @@ func TestGet(t *testing.T) { ...@@ -76,7 +77,7 @@ func TestGet(t *testing.T) {
func TestPut(t *testing.T) { func TestPut(t *testing.T) {
t.Run("NewKey", func(t *testing.T) { t.Run("NewKey", func(t *testing.T) {
oracle := newStubStateOracle(t) oracle := test.NewStubStateOracle(t)
db := NewOracleBackedDB(oracle) db := NewOracleBackedDB(oracle)
key := common.HexToHash("0xAA4488") key := common.HexToHash("0xAA4488")
value := []byte{2, 6, 3, 8} value := []byte{2, 6, 3, 8}
...@@ -88,7 +89,7 @@ func TestPut(t *testing.T) { ...@@ -88,7 +89,7 @@ func TestPut(t *testing.T) {
require.Equal(t, value, actual) require.Equal(t, value, actual)
}) })
t.Run("ReplaceKey", func(t *testing.T) { t.Run("ReplaceKey", func(t *testing.T) {
oracle := newStubStateOracle(t) oracle := test.NewStubStateOracle(t)
db := NewOracleBackedDB(oracle) db := NewOracleBackedDB(oracle)
key := common.HexToHash("0xAA4488") key := common.HexToHash("0xAA4488")
value1 := []byte{2, 6, 3, 8} value1 := []byte{2, 6, 3, 8}
...@@ -109,16 +110,13 @@ func TestSupportsStateDBOperations(t *testing.T) { ...@@ -109,16 +110,13 @@ func TestSupportsStateDBOperations(t *testing.T) {
realDb := rawdb.NewDatabase(memorydb.New()) realDb := rawdb.NewDatabase(memorydb.New())
genesisBlock := l2Genesis.MustCommit(realDb) genesisBlock := l2Genesis.MustCommit(realDb)
loader := &kvStateOracle{ loader := test.NewKvStateOracle(t, realDb)
t: t,
source: realDb,
}
assertStateDataAvailable(t, NewOracleBackedDB(loader), l2Genesis, genesisBlock) assertStateDataAvailable(t, NewOracleBackedDB(loader), l2Genesis, genesisBlock)
} }
func TestUpdateState(t *testing.T) { func TestUpdateState(t *testing.T) {
l2Genesis := createGenesis() l2Genesis := createGenesis()
oracle := newStubStateOracle(t) oracle := test.NewStubStateOracle(t)
db := rawdb.NewDatabase(NewOracleBackedDB(oracle)) db := rawdb.NewDatabase(NewOracleBackedDB(oracle))
genesisBlock := l2Genesis.MustCommit(db) genesisBlock := l2Genesis.MustCommit(db)
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi" "github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi/test" "github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi/test"
l2test "github.com/ethereum-optimism/optimism/op-program/client/l2/test"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/beacon" "github.com/ethereum/go-ethereum/consensus/beacon"
...@@ -143,7 +144,7 @@ func setupOracleBackedChainWithLowerHead(t *testing.T, blockCount int, headBlock ...@@ -143,7 +144,7 @@ func setupOracleBackedChainWithLowerHead(t *testing.T, blockCount int, headBlock
return blocks, chain return blocks, chain
} }
func setupOracle(t *testing.T, blockCount int, headBlockNumber int) (*params.ChainConfig, []*types.Block, *stubBlockOracle) { func setupOracle(t *testing.T, blockCount int, headBlockNumber int) (*params.ChainConfig, []*types.Block, *l2test.StubBlockOracle) {
deployConfig := &genesis.DeployConfig{ deployConfig := &genesis.DeployConfig{
L1ChainID: 900, L1ChainID: 900,
L2ChainID: 901, L2ChainID: 901,
...@@ -171,7 +172,7 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int) (*params.Cha ...@@ -171,7 +172,7 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int) (*params.Cha
genesisBlock := l2Genesis.MustCommit(db) genesisBlock := l2Genesis.MustCommit(db)
blocks, _ := core.GenerateChain(chainCfg, genesisBlock, consensus, db, blockCount, func(i int, gen *core.BlockGen) {}) blocks, _ := core.GenerateChain(chainCfg, genesisBlock, consensus, db, blockCount, func(i int, gen *core.BlockGen) {})
blocks = append([]*types.Block{genesisBlock}, blocks...) blocks = append([]*types.Block{genesisBlock}, blocks...)
oracle := newStubOracleWithBlocks(t, blocks[:headBlockNumber+1], db) oracle := l2test.NewStubOracleWithBlocks(t, blocks[:headBlockNumber+1], db)
return chainCfg, blocks, oracle return chainCfg, blocks, oracle
} }
......
package l2 package test
import ( import (
"testing" "testing"
...@@ -9,84 +9,97 @@ import ( ...@@ -9,84 +9,97 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
) )
type stubBlockOracle struct { // Same as l2.StateOracle but need to use our own copy to avoid dependency loops
type stateOracle interface {
NodeByHash(nodeHash common.Hash) []byte
CodeByHash(codeHash common.Hash) []byte
}
type StubBlockOracle struct {
t *testing.T t *testing.T
blocks map[common.Hash]*types.Block Blocks map[common.Hash]*types.Block
StateOracle stateOracle
} }
func newStubOracle(t *testing.T) (*stubBlockOracle, *stubStateOracle) { func NewStubOracle(t *testing.T) (*StubBlockOracle, *StubStateOracle) {
stateOracle := newStubStateOracle(t) stateOracle := NewStubStateOracle(t)
blockOracle := stubBlockOracle{ blockOracle := StubBlockOracle{
t: t, t: t,
blocks: make(map[common.Hash]*types.Block), Blocks: make(map[common.Hash]*types.Block),
StateOracle: stateOracle, stateOracle: stateOracle,
} }
return &blockOracle, stateOracle return &blockOracle, stateOracle
} }
func newStubOracleWithBlocks(t *testing.T, chain []*types.Block, db ethdb.Database) *stubBlockOracle { func NewStubOracleWithBlocks(t *testing.T, chain []*types.Block, db ethdb.Database) *StubBlockOracle {
blocks := make(map[common.Hash]*types.Block, len(chain)) blocks := make(map[common.Hash]*types.Block, len(chain))
for _, block := range chain { for _, block := range chain {
blocks[block.Hash()] = block blocks[block.Hash()] = block
} }
return &stubBlockOracle{ return &StubBlockOracle{
blocks: blocks, Blocks: blocks,
StateOracle: &kvStateOracle{t: t, source: db}, stateOracle: &KvStateOracle{t: t, Source: db},
} }
} }
func (o stubBlockOracle) BlockByHash(blockHash common.Hash) *types.Block { func (o StubBlockOracle) BlockByHash(blockHash common.Hash) *types.Block {
block, ok := o.blocks[blockHash] block, ok := o.Blocks[blockHash]
if !ok { if !ok {
o.t.Fatalf("requested unknown block %s", blockHash) o.t.Fatalf("requested unknown block %s", blockHash)
} }
return block return block
} }
// kvStateOracle loads data from a source ethdb.KeyValueStore // KvStateOracle loads data from a source ethdb.KeyValueStore
type kvStateOracle struct { type KvStateOracle struct {
t *testing.T t *testing.T
source ethdb.KeyValueStore Source ethdb.KeyValueStore
}
func NewKvStateOracle(t *testing.T, db ethdb.KeyValueStore) *KvStateOracle {
return &KvStateOracle{
t: t,
Source: db,
}
} }
func (o *kvStateOracle) NodeByHash(nodeHash common.Hash) []byte { func (o *KvStateOracle) NodeByHash(nodeHash common.Hash) []byte {
val, err := o.source.Get(nodeHash.Bytes()) val, err := o.Source.Get(nodeHash.Bytes())
if err != nil { if err != nil {
o.t.Fatalf("error retrieving node %v: %v", nodeHash, err) o.t.Fatalf("error retrieving node %v: %v", nodeHash, err)
} }
return val return val
} }
func (o *kvStateOracle) CodeByHash(hash common.Hash) []byte { func (o *KvStateOracle) CodeByHash(hash common.Hash) []byte {
return rawdb.ReadCode(o.source, hash) return rawdb.ReadCode(o.Source, hash)
} }
func newStubStateOracle(t *testing.T) *stubStateOracle { func NewStubStateOracle(t *testing.T) *StubStateOracle {
return &stubStateOracle{ return &StubStateOracle{
t: t, t: t,
data: make(map[common.Hash][]byte), Data: make(map[common.Hash][]byte),
code: make(map[common.Hash][]byte), Code: make(map[common.Hash][]byte),
} }
} }
// Stub StateOracle implementation that reads from simple maps // StubStateOracle is a StateOracle implementation that reads from simple maps
type stubStateOracle struct { type StubStateOracle struct {
t *testing.T t *testing.T
data map[common.Hash][]byte Data map[common.Hash][]byte
code map[common.Hash][]byte Code map[common.Hash][]byte
} }
func (o *stubStateOracle) NodeByHash(nodeHash common.Hash) []byte { func (o *StubStateOracle) NodeByHash(nodeHash common.Hash) []byte {
data, ok := o.data[nodeHash] data, ok := o.Data[nodeHash]
if !ok { if !ok {
o.t.Fatalf("no value for node %v", nodeHash) o.t.Fatalf("no value for node %v", nodeHash)
} }
return data return data
} }
func (o *stubStateOracle) CodeByHash(hash common.Hash) []byte { func (o *StubStateOracle) CodeByHash(hash common.Hash) []byte {
data, ok := o.code[hash] data, ok := o.Code[hash]
if !ok { if !ok {
o.t.Fatalf("no value for code %v", hash) o.t.Fatalf("no value for code %v", hash)
} }
......
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