Commit 715e630b authored by inphi's avatar inphi

refactor stubs

parent a4a3ff36
......@@ -16,20 +16,17 @@ type CachingOracle struct {
blocks *simplelru.LRU[common.Hash, eth.BlockInfo]
txs *simplelru.LRU[common.Hash, types.Transactions]
rcpts *simplelru.LRU[common.Hash, types.Receipts]
outputs *simplelru.LRU[common.Hash, eth.Output]
}
func NewCachingOracle(oracle Oracle) *CachingOracle {
blockLRU, _ := simplelru.NewLRU[common.Hash, eth.BlockInfo](cacheSize, nil)
txsLRU, _ := simplelru.NewLRU[common.Hash, types.Transactions](cacheSize, nil)
rcptsLRU, _ := simplelru.NewLRU[common.Hash, types.Receipts](cacheSize, nil)
outputsLRU, _ := simplelru.NewLRU[common.Hash, eth.Output](cacheSize, nil)
return &CachingOracle{
oracle: oracle,
blocks: blockLRU,
txs: txsLRU,
rcpts: rcptsLRU,
outputs: outputsLRU,
}
}
......@@ -64,13 +61,3 @@ func (o *CachingOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInf
o.rcpts.Add(blockHash, rcpts)
return block, rcpts
}
func (o *CachingOracle) L2OutputByRoot(l2OutputRoot common.Hash) eth.Output {
output, ok := o.outputs.Get(l2OutputRoot)
if ok {
return output
}
output = o.oracle.L2OutputByRoot(l2OutputRoot)
o.outputs.Add(l2OutputRoot, output)
return output
}
......@@ -7,7 +7,6 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum-optimism/optimism/op-program/client/l1/test"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
......@@ -72,29 +71,3 @@ func TestCachingOracle_ReceiptsByBlockHash(t *testing.T) {
require.Equal(t, eth.BlockToInfo(block), actualBlock)
require.EqualValues(t, rcpts, actualRcpts)
}
func TestCachingOracle_L2OutputByRoot(t *testing.T) {
rng := rand.New(rand.NewSource(1))
stub := test.NewStubOracle(t)
oracle := NewCachingOracle(stub)
block, _ := testutils.RandomBlock(rng, 3)
var storageRoot [32]byte
rng.Read(storageRoot[:])
l2Output := &eth.OutputV0{
StateRoot: eth.Bytes32(block.Root()),
MessagePasserStorageRoot: storageRoot,
BlockHash: block.Hash(),
}
l2OutputRoot := common.Hash(eth.OutputRoot(l2Output))
// Initial call retrieves from the stub
stub.L2Outputs[l2OutputRoot] = l2Output
result := oracle.L2OutputByRoot(l2OutputRoot)
require.Equal(t, l2Output.Marshal(), result)
// Later calls should retrieve from cache
delete(stub.L2Outputs, l2OutputRoot)
result = oracle.L2OutputByRoot(l2OutputRoot)
require.Equal(t, l2Output.Marshal(), result)
}
......@@ -80,7 +80,3 @@ func (o *OracleL1Client) InfoAndTxsByHash(ctx context.Context, hash common.Hash)
info, txs := o.oracle.TransactionsByBlockHash(hash)
return info, txs, nil
}
func (o *OracleL1Client) L2OutputByRoot(ctx context.Context, root common.Hash) (eth.Output, error) {
return o.oracle.L2OutputByRoot(root), nil
}
......@@ -10,7 +10,6 @@ const (
HintL1BlockHeader = "l1-block-header"
HintL1Transactions = "l1-transactions"
HintL1Receipts = "l1-receipts"
HintL2Output = "l1-l2-output"
)
type BlockHeaderHint common.Hash
......@@ -36,11 +35,3 @@ var _ preimage.Hint = ReceiptsHint{}
func (l ReceiptsHint) Hint() string {
return HintL1Receipts + " " + (common.Hash)(l).String()
}
type L2OutputHint common.Hash
var _ preimage.Hint = L2OutputHint{}
func (l L2OutputHint) Hint() string {
return HintL2Output + " " + (common.Hash)(l).String()
}
......@@ -21,9 +21,6 @@ type Oracle interface {
// ReceiptsByBlockHash retrieves the receipts from the block with the given hash.
ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Receipts)
// L2OutputByRoot retrieves the L2 output for the given L2 output root.
L2OutputByRoot(l2OutputRoot common.Hash) eth.Output
}
// PreimageOracle implements Oracle using by interfacing with the pure preimage.Oracle
......@@ -89,13 +86,3 @@ func (p *PreimageOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockIn
return info, receipts
}
func (p *PreimageOracle) L2OutputByRoot(l2OutputRoot common.Hash) eth.Output {
p.hint.Hint(L2OutputHint(l2OutputRoot))
data := p.oracle.Get(preimage.Keccak256Key(l2OutputRoot))
output, err := eth.UnmarshalOutput(data)
if err != nil {
panic(fmt.Errorf("invalidd L2 output data for root %s: %w", l2OutputRoot, err))
}
return output
}
......@@ -19,9 +19,6 @@ type StubOracle struct {
// Rcpts maps Block hash to receipts
Rcpts map[common.Hash]types.Receipts
// L2Outputs maps L2 output roots to L2 outputs
L2Outputs map[common.Hash]eth.Output
}
func NewStubOracle(t *testing.T) *StubOracle {
......@@ -30,7 +27,6 @@ func NewStubOracle(t *testing.T) *StubOracle {
Blocks: make(map[common.Hash]eth.BlockInfo),
Txs: make(map[common.Hash]types.Transactions),
Rcpts: make(map[common.Hash]types.Receipts),
L2Outputs: make(map[common.Hash]eth.Output),
}
}
func (o StubOracle) HeaderByBlockHash(blockHash common.Hash) eth.BlockInfo {
......@@ -56,11 +52,3 @@ func (o StubOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, t
}
return o.HeaderByBlockHash(blockHash), rcpts
}
func (o StubOracle) L2OutputByRoot(l2OutputRoot common.Hash) eth.Output {
output, ok := o.L2Outputs[l2OutputRoot]
if !ok {
o.t.Fatalf("unknown output %s", l2OutputRoot)
}
return output
}
package l2
import (
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/hashicorp/golang-lru/v2/simplelru"
......@@ -17,17 +18,20 @@ type CachingOracle struct {
blocks *simplelru.LRU[common.Hash, *types.Block]
nodes *simplelru.LRU[common.Hash, []byte]
codes *simplelru.LRU[common.Hash, []byte]
outputs *simplelru.LRU[common.Hash, eth.Output]
}
func NewCachingOracle(oracle Oracle) *CachingOracle {
blockLRU, _ := simplelru.NewLRU[common.Hash, *types.Block](blockCacheSize, nil)
nodeLRU, _ := simplelru.NewLRU[common.Hash, []byte](nodeCacheSize, nil)
codeLRU, _ := simplelru.NewLRU[common.Hash, []byte](codeCacheSize, nil)
outputLRU, _ := simplelru.NewLRU[common.Hash, eth.Output](codeCacheSize, nil)
return &CachingOracle{
oracle: oracle,
blocks: blockLRU,
nodes: nodeLRU,
codes: codeLRU,
outputs: outputLRU,
}
}
......@@ -60,3 +64,13 @@ func (o *CachingOracle) BlockByHash(blockHash common.Hash) *types.Block {
o.blocks.Add(blockHash, block)
return block
}
func (o *CachingOracle) L2OutputByRoot(root common.Hash) eth.Output {
output, ok := o.outputs.Get(root)
if ok {
return output
}
output = o.oracle.L2OutputByRoot(root)
o.outputs.Add(root, output)
return output
}
......@@ -4,6 +4,7 @@ import (
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-program/client/l2/engineapi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
......@@ -39,8 +40,13 @@ type OracleBackedL2Chain struct {
var _ engineapi.EngineBackend = (*OracleBackedL2Chain)(nil)
func NewOracleBackedL2Chain(logger log.Logger, oracle Oracle, chainCfg *params.ChainConfig, l2Head common.Hash) (*OracleBackedL2Chain, error) {
head := oracle.BlockByHash(l2Head)
func NewOracleBackedL2Chain(logger log.Logger, oracle Oracle, chainCfg *params.ChainConfig, l2OutputRoot common.Hash) (*OracleBackedL2Chain, error) {
output := oracle.L2OutputByRoot(l2OutputRoot)
outputV0, ok := output.(*eth.OutputV0)
if !ok {
return nil, fmt.Errorf("unsupported L2 output version: %d", output.Version())
}
head := oracle.BlockByHash(outputV0.BlockHash)
logger.Info("Loaded L2 head", "hash", head.Hash(), "number", head.Number())
return &OracleBackedL2Chain{
log: logger,
......
......@@ -11,6 +11,7 @@ const (
HintL2Transactions = "l2-transactions"
HintL2Code = "l2-code"
HintL2StateNode = "l2-state-node"
HintL2Output = "l2-output"
)
type BlockHeaderHint common.Hash
......@@ -44,3 +45,11 @@ var _ preimage.Hint = StateNodeHint{}
func (l StateNodeHint) Hint() string {
return HintL2StateNode + " " + (common.Hash)(l).String()
}
type L2OutputHint common.Hash
var _ preimage.Hint = L2OutputHint{}
func (l L2OutputHint) Hint() string {
return HintL2Output + " " + (common.Hash)(l).String()
}
......@@ -32,6 +32,8 @@ type Oracle interface {
// BlockByHash retrieves the block with the given hash.
BlockByHash(blockHash common.Hash) *types.Block
L2OutputByRoot(root common.Hash) eth.Output
}
// PreimageOracle implements Oracle using by interfacing with the pure preimage.Oracle
......@@ -85,3 +87,13 @@ func (p *PreimageOracle) CodeByHash(codeHash common.Hash) []byte {
p.hint.Hint(CodeHint(codeHash))
return p.oracle.Get(preimage.Keccak256Key(codeHash))
}
func (p *PreimageOracle) L2OutputByRoot(l2OutputRoot common.Hash) eth.Output {
p.hint.Hint(L2OutputHint(l2OutputRoot))
data := p.oracle.Get(preimage.Keccak256Key(l2OutputRoot))
output, err := eth.UnmarshalOutput(data)
if err != nil {
panic(fmt.Errorf("invalid L2 output data for root %s: %w", l2OutputRoot, err))
}
return output
}
......@@ -3,6 +3,7 @@ package test
import (
"testing"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
......@@ -18,6 +19,7 @@ type stateOracle interface {
type StubBlockOracle struct {
t *testing.T
Blocks map[common.Hash]*types.Block
L2Outputs map[common.Hash]eth.Output
stateOracle
}
......@@ -50,6 +52,14 @@ func (o StubBlockOracle) BlockByHash(blockHash common.Hash) *types.Block {
return block
}
func (o StubBlockOracle) L2OutputByRoot(root common.Hash) eth.Output {
output, ok := o.L2Outputs[root]
if !ok {
o.t.Fatalf("requested unknown output root %s", root)
}
return output
}
// KvStateOracle loads data from a source ethdb.KeyValueStore
type KvStateOracle struct {
t *testing.T
......
......@@ -64,16 +64,7 @@ func RunProgram(logger log.Logger, preimageOracle io.ReadWriter, preimageHinter
// runDerivation executes the L2 state transition, given a minimal interface to retrieve data.
func runDerivation(logger log.Logger, cfg *rollup.Config, l2Cfg *params.ChainConfig, l1Head common.Hash, l2OutputRoot common.Hash, l2Claim common.Hash, l2ClaimBlockNum uint64, l1Oracle l1.Oracle, l2Oracle l2.Oracle) error {
l1Source := l1.NewOracleL1Client(logger, l1Oracle, l1Head)
output, err := l1Source.L2OutputByRoot(context.Background(), l2OutputRoot)
if err != nil {
return fmt.Errorf("failed to find L2 output for %s: %w", l2OutputRoot, err)
}
outputV0, ok := output.(*eth.OutputV0)
if !ok {
return fmt.Errorf("unsupported L2 output version: %d", output.Version())
}
l2Head := outputV0.BlockHash
engineBackend, err := l2.NewOracleBackedL2Chain(logger, l2Oracle, l2Cfg, l2Head)
engineBackend, err := l2.NewOracleBackedL2Chain(logger, l2Oracle, l2Cfg, l2OutputRoot)
if err != nil {
return fmt.Errorf("failed to create oracle-backed L2 chain: %w", err)
}
......
......@@ -99,12 +99,6 @@ func (p *Prefetcher) prefetch(ctx context.Context, hint string) error {
return fmt.Errorf("failed to fetch L1 block %s receipts: %w", hash, err)
}
return p.storeReceipts(receipts)
case l1.HintL2Output:
output, err := p.l2Fetcher.L2OutputByRoot(ctx, hash)
if err != nil {
return fmt.Errorf("failed to fetch L2 output root %s: %w", hash, err)
}
return p.kvStore.Put(preimage.Keccak256Key(hash).PreimageKey(), output.Marshal())
case l2.HintL2BlockHeader:
header, txs, err := p.l2Fetcher.InfoAndTxsByHash(ctx, hash)
if err != nil {
......@@ -131,6 +125,12 @@ func (p *Prefetcher) prefetch(ctx context.Context, hint string) error {
return fmt.Errorf("failed to fetch L2 contract code %s: %w", hash, err)
}
return p.kvStore.Put(preimage.Keccak256Key(hash).PreimageKey(), code)
case l2.HintL2Output:
output, err := p.l2Fetcher.L2OutputByRoot(ctx, hash)
if err != nil {
return fmt.Errorf("failed to fetch L2 output root %s: %w", hash, err)
}
return p.kvStore.Put(preimage.Keccak256Key(hash).PreimageKey(), output.Marshal())
}
return fmt.Errorf("unknown hint type: %v", hintType)
}
......
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