Commit 89c9fef1 authored by clabby's avatar clabby Committed by GitHub

feat: Run `op-program` in `op-e2e` action tests (#11846)

* feat: Run `op-program` in `op-e2e` action tests

* configurable forks

* golint / op-program test

* use correct endpoint
parent 06a62ea8
......@@ -240,7 +240,7 @@ func (s *L1Miner) ActL1EndBlock(t Testing) {
for _, sidecar := range s.l1BuildingBlobSidecars {
for i, h := range sidecar.BlobHashes() {
blob := (*eth.Blob)(&sidecar.Blobs[i])
s.blobStore.StoreBlob(block.Hash(), h, blob)
s.blobStore.StoreBlob(block.Time(), h, blob)
}
}
_, err = s.l1Chain.InsertChain(types.Blocks{block})
......
package actions
import (
"context"
"math/rand"
"os"
"testing"
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-program/host"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
var dumpFixtures = false
func init() {
if os.Getenv("OP_E2E_DUMP_FIXTURES") == "1" {
dumpFixtures = true
}
}
// L2FaultProofEnv is a test harness for a fault provable L2 chain.
type L2FaultProofEnv struct {
log log.Logger
batcher *L2Batcher
sequencer *L2Sequencer
engine *L2Engine
engCl *sources.EngineClient
sd *e2eutils.SetupData
dp *e2eutils.DeployParams
miner *L1Miner
alice *CrossLayerUser
}
func NewL2FaultProofEnv(t Testing, tp *e2eutils.TestParams, dp *e2eutils.DeployParams, batcherCfg *BatcherCfg) *L2FaultProofEnv {
log := testlog.Logger(t, log.LvlDebug)
sd := e2eutils.Setup(t, dp, defaultAlloc)
miner, engine, sequencer := setupSequencerTest(t, sd, log)
miner.ActL1SetFeeRecipient(common.Address{0xCA, 0xFE, 0xBA, 0xBE})
sequencer.ActL2PipelineFull(t)
engCl := engine.EngineClient(t, sd.RollupCfg)
// Set the batcher key to the secret key of the batcher
batcherCfg.BatcherKey = dp.Secrets.Batcher
batcher := NewL2Batcher(log, sd.RollupCfg, batcherCfg, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engCl)
addresses := e2eutils.CollectAddresses(sd, dp)
cl := engine.EthClient()
l2UserEnv := &BasicUserEnv[*L2Bindings]{
EthCl: cl,
Signer: types.LatestSigner(sd.L2Cfg.Config),
AddressCorpora: addresses,
Bindings: NewL2Bindings(t, cl, engine.GethClient()),
}
alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b)))
alice.L2.SetUserEnv(l2UserEnv)
return &L2FaultProofEnv{
log: log,
batcher: batcher,
sequencer: sequencer,
engine: engine,
engCl: engCl,
sd: sd,
dp: dp,
miner: miner,
alice: alice,
}
}
type TestParam func(p *e2eutils.TestParams)
func NewTestParams(params ...TestParam) *e2eutils.TestParams {
dfault := defaultRollupTestParams
for _, apply := range params {
apply(dfault)
}
return dfault
}
type DeployParam func(p *e2eutils.DeployParams)
func NewDeployParams(t Testing, params ...DeployParam) *e2eutils.DeployParams {
dfault := e2eutils.MakeDeployParams(t, NewTestParams())
for _, apply := range params {
apply(dfault)
}
return dfault
}
type BatcherCfgParam func(c *BatcherCfg)
func NewBatcherCfg(params ...BatcherCfgParam) *BatcherCfg {
dfault := &BatcherCfg{
MinL1TxSize: 0,
MaxL1TxSize: 128_000,
DataAvailabilityType: batcherFlags.BlobsType,
}
for _, apply := range params {
apply(dfault)
}
return dfault
}
type OpProgramCfgParam func(p *config.Config)
func NewOpProgramCfg(
t Testing,
env *L2FaultProofEnv,
l1Head common.Hash,
l2Head common.Hash,
l2OutputRoot common.Hash,
l2Claim common.Hash,
l2ClaimBlockNum uint64,
params ...OpProgramCfgParam,
) *config.Config {
dfault := config.NewConfig(env.sd.RollupCfg, env.sd.L2Cfg.Config, l1Head, l2Head, l2OutputRoot, l2Claim, l2ClaimBlockNum)
// Set up in-process L1 sources
dfault.L1ProcessSource = env.miner.L1Client(t, env.sd.RollupCfg)
dfault.L1BeaconProcessSource = env.miner.blobStore
// Set up in-process L2 source
l2ClCfg := sources.L2ClientDefaultConfig(env.sd.RollupCfg, true)
l2RPC := env.engine.RPCClient()
l2Client, err := host.NewL2Client(l2RPC, env.log, nil, &host.L2ClientConfig{L2ClientConfig: l2ClCfg, L2Head: l2Head})
require.NoError(t, err, "failed to create L2 client")
l2DebugCl := &host.L2Source{L2Client: l2Client, DebugClient: sources.NewDebugClient(l2RPC.CallContext)}
dfault.L2ProcessSource = l2DebugCl
for _, apply := range params {
apply(dfault)
}
return dfault
}
func Test_ProgramAction_SimpleEmptyChain_HonestClaim_Granite(gt *testing.T) {
t := NewDefaultTesting(gt)
tp := NewTestParams()
dp := NewDeployParams(t, func(dp *e2eutils.DeployParams) {
genesisBlock := hexutil.Uint64(0)
// Enable Cancun on L1 & Granite on L2 at genesis
dp.DeployConfig.L1CancunTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisFjordTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisGraniteTimeOffset = &genesisBlock
})
bCfg := NewBatcherCfg()
env := NewL2FaultProofEnv(t, tp, dp, bCfg)
// Build an empty block on L2
env.sequencer.ActL2StartBlock(t)
env.sequencer.ActL2EndBlock(t)
// Instruct the batcher to submit the block to L1, and include the transaction.
env.batcher.ActSubmitAll(t)
env.miner.ActL1StartBlock(12)(t)
env.miner.ActL1IncludeTxByHash(env.batcher.LastSubmitted.Hash())(t)
env.miner.ActL1EndBlock(t)
// Finalize the block with the batch on L1.
env.miner.ActL1SafeNext(t)
env.miner.ActL1FinalizeNext(t)
// Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted.
env.sequencer.ActL1HeadSignal(t)
env.sequencer.ActL2PipelineFull(t)
l1Head := env.miner.l1Chain.CurrentBlock()
l2SafeHead := env.engine.l2Chain.CurrentSafeBlock()
// Ensure there is only 1 block on L1.
require.Equal(t, uint64(1), l1Head.Number.Uint64())
// Ensure the block is marked as safe before we attempt to fault prove it.
require.Equal(t, uint64(1), l2SafeHead.Number.Uint64())
// Fetch the pre and post output roots for the fault proof.
preRoot, err := env.sequencer.RollupClient().OutputAtBlock(context.Background(), l2SafeHead.Number.Uint64()-1)
require.NoError(t, err)
claimRoot, err := env.sequencer.RollupClient().OutputAtBlock(context.Background(), l2SafeHead.Number.Uint64())
require.NoError(t, err)
// Run the fault proof program from the state transition from L2 block 0 -> 1.
programCfg := NewOpProgramCfg(
t,
env,
l1Head.Hash(),
preRoot.BlockRef.Hash,
common.Hash(preRoot.OutputRoot),
common.Hash(claimRoot.OutputRoot),
l2SafeHead.Number.Uint64(),
)
err = host.FaultProofProgram(context.Background(), env.log, programCfg)
require.NoError(t, err)
}
func Test_ProgramAction_SimpleEmptyChain_JunkClaim_Granite(gt *testing.T) {
t := NewDefaultTesting(gt)
tp := NewTestParams()
dp := NewDeployParams(t, func(dp *e2eutils.DeployParams) {
genesisBlock := hexutil.Uint64(0)
// Enable Cancun on L1 & Granite on L2 at genesis
dp.DeployConfig.L1CancunTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisFjordTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisGraniteTimeOffset = &genesisBlock
})
bCfg := NewBatcherCfg()
env := NewL2FaultProofEnv(t, tp, dp, bCfg)
// Build an empty block on L2
env.sequencer.ActL2StartBlock(t)
env.sequencer.ActL2EndBlock(t)
// Instruct the batcher to submit the block to L1, and include the transaction.
env.batcher.ActSubmitAll(t)
env.miner.ActL1StartBlock(12)(t)
env.miner.ActL1IncludeTxByHash(env.batcher.LastSubmitted.Hash())(t)
env.miner.ActL1EndBlock(t)
// Finalize the block with the batch on L1.
env.miner.ActL1SafeNext(t)
env.miner.ActL1FinalizeNext(t)
// Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted.
env.sequencer.ActL1HeadSignal(t)
env.sequencer.ActL2PipelineFull(t)
l1Head := env.miner.l1Chain.CurrentBlock()
l2SafeHead := env.engine.l2Chain.CurrentSafeBlock()
// Ensure there is only 1 block on L1.
require.Equal(t, uint64(1), l1Head.Number.Uint64())
// Ensure the block is marked as safe before we attempt to fault prove it.
require.Equal(t, uint64(1), l2SafeHead.Number.Uint64())
// Fetch the pre and post output roots for the fault proof.
preRoot, err := env.sequencer.RollupClient().OutputAtBlock(context.Background(), l2SafeHead.Number.Uint64()-1)
require.NoError(t, err)
// Run the fault proof program from the state transition from L2 block 0 -> 1, with a junk claim.
programCfg := NewOpProgramCfg(
t,
env,
l1Head.Hash(),
preRoot.BlockRef.Hash,
common.Hash(preRoot.OutputRoot),
common.HexToHash("0xdeadbeef"),
l2SafeHead.Number.Uint64(),
)
err = host.FaultProofProgram(context.Background(), env.log, programCfg)
require.Error(t, err)
}
......@@ -6,33 +6,35 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-program/host/sources"
"github.com/ethereum-optimism/optimism/op-service/eth"
)
// BlobsStore is a simple in-memory store of blobs, for testing purposes
type BlobsStore struct {
// blockhash -> blob versioned hash -> blob
blobs map[common.Hash]map[common.Hash]*eth.Blob
// block timestamp -> blob versioned hash -> blob
blobs map[uint64]map[common.Hash]*eth.Blob
}
func NewBlobStore() *BlobsStore {
return &BlobsStore{blobs: make(map[common.Hash]map[common.Hash]*eth.Blob)}
return &BlobsStore{blobs: make(map[uint64]map[common.Hash]*eth.Blob)}
}
func (store *BlobsStore) StoreBlob(blockHash common.Hash, versionedHash common.Hash, blob *eth.Blob) {
m, ok := store.blobs[blockHash]
func (store *BlobsStore) StoreBlob(blockTime uint64, versionedHash common.Hash, blob *eth.Blob) {
m, ok := store.blobs[blockTime]
if !ok {
m = make(map[common.Hash]*eth.Blob)
store.blobs[blockHash] = m
store.blobs[blockTime] = m
}
m[versionedHash] = blob
}
func (store *BlobsStore) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) {
out := make([]*eth.Blob, 0, len(hashes))
m, ok := store.blobs[ref.Hash]
m, ok := store.blobs[ref.Time]
if !ok {
return nil, fmt.Errorf("no blobs known with given time: %w", ethereum.NotFound)
}
......@@ -46,4 +48,35 @@ func (store *BlobsStore) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashe
return out, nil
}
var _ derive.L1BlobsFetcher = (*BlobsStore)(nil)
func (store *BlobsStore) GetBlobSidecars(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.BlobSidecar, error) {
out := make([]*eth.BlobSidecar, 0, len(hashes))
m, ok := store.blobs[ref.Time]
if !ok {
return nil, fmt.Errorf("no blobs known with given time: %w", ethereum.NotFound)
}
for _, h := range hashes {
b, ok := m[h.Hash]
if !ok {
return nil, fmt.Errorf("blob %d %s is not in store: %w", h.Index, h.Hash, ethereum.NotFound)
}
if b == nil {
return nil, fmt.Errorf("blob %d %s is nil, cannot copy: %w", h.Index, h.Hash, ethereum.NotFound)
}
commitment, err := kzg4844.BlobToCommitment(b.KZGBlob())
if err != nil {
return nil, fmt.Errorf("failed to convert blob to commitment: %w", err)
}
out = append(out, &eth.BlobSidecar{
Index: eth.Uint64String(h.Index),
Blob: *b,
KZGCommitment: eth.Bytes48(commitment),
})
}
return out, nil
}
var (
_ derive.L1BlobsFetcher = (*BlobsStore)(nil)
_ sources.L1BlobSource = (*BlobsStore)(nil)
)
......@@ -281,6 +281,7 @@ func testFaultProofProgramScenario(t *testing.T, ctx context.Context, sys *Syste
fppConfig := oppconf.NewConfig(sys.RollupConfig, sys.L2GenesisCfg.Config, s.L1Head, s.L2Head, s.L2OutputRoot, common.Hash(s.L2Claim), s.L2ClaimBlockNumber)
fppConfig.L1URL = sys.NodeEndpoint("l1").RPC()
fppConfig.L2URL = sys.NodeEndpoint("sequencer").RPC()
fppConfig.L1BeaconURL = sys.L1BeaconEndpoint().RestHTTP()
fppConfig.DataDir = preimageDir
if s.Detached {
// When running in detached mode we need to compile the client executable since it will be called directly.
......
......@@ -13,6 +13,7 @@ import (
opnode "github.com/ethereum-optimism/optimism/op-node"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-program/host/flags"
hostSources "github.com/ethereum-optimism/optimism/op-program/host/sources"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
......@@ -73,6 +74,11 @@ type Config struct {
// IsCustomChainConfig indicates that the program uses a custom chain configuration
IsCustomChainConfig bool
// Optional process sources. Will be favored over the RPC sources if set.
L1ProcessSource hostSources.L1Source
L1BeaconProcessSource hostSources.L1BlobSource
L2ProcessSource hostSources.L2Source
}
func (c *Config) Check() error {
......@@ -113,8 +119,11 @@ func (c *Config) Check() error {
}
func (c *Config) FetchingEnabled() bool {
// TODO: Include Beacon URL once cancun is active on all chains we fault prove.
return c.L1URL != "" && c.L2URL != ""
return (c.L1URL != "" && c.L2URL != "" && c.L1BeaconURL != "") || c.InProcessSourcesEnabled()
}
func (c *Config) InProcessSourcesEnabled() bool {
return c.L1ProcessSource != nil && c.L1BeaconProcessSource != nil && c.L2ProcessSource != nil
}
// NewConfig creates a Config with all optional values set to the CLI default value
......
......@@ -140,7 +140,8 @@ func TestFetchingEnabled(t *testing.T) {
t.Run("FetchingEnabledWhenBothFetcherUrlsSpecified", func(t *testing.T) {
cfg := validConfig()
cfg.L1URL = "https://example.com:1234"
cfg.L2URL = "https://example.com:5678"
cfg.L1BeaconURL = "https://example.com:5678"
cfg.L2URL = "https://example.com:91011"
require.True(t, cfg.FetchingEnabled(), "Should enable fetching when node URL supplied")
})
}
......
......@@ -16,6 +16,7 @@ import (
"github.com/ethereum-optimism/optimism/op-program/host/flags"
"github.com/ethereum-optimism/optimism/op-program/host/kvstore"
"github.com/ethereum-optimism/optimism/op-program/host/prefetcher"
hostSources "github.com/ethereum-optimism/optimism/op-program/host/sources"
"github.com/ethereum-optimism/optimism/op-program/host/types"
opservice "github.com/ethereum-optimism/optimism/op-service"
"github.com/ethereum-optimism/optimism/op-service/client"
......@@ -205,31 +206,42 @@ func PreimageServer(ctx context.Context, logger log.Logger, cfg *config.Config,
}
func makePrefetcher(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (*prefetcher.Prefetcher, error) {
logger.Info("Connecting to L1 node", "l1", cfg.L1URL)
l1RPC, err := client.NewRPC(ctx, logger, cfg.L1URL, client.WithDialBackoff(10))
if err != nil {
return nil, fmt.Errorf("failed to setup L1 RPC: %w", err)
}
var l1Cl hostSources.L1Source
var l1BlobFetcher hostSources.L1BlobSource
var l2DebugCl hostSources.L2Source
logger.Info("Connecting to L2 node", "l2", cfg.L2URL)
l2RPC, err := client.NewRPC(ctx, logger, cfg.L2URL, client.WithDialBackoff(10))
if err != nil {
return nil, fmt.Errorf("failed to setup L2 RPC: %w", err)
}
if cfg.InProcessSourcesEnabled() {
logger.Debug("Using in-process sources for preimage fetching.")
l1Cl = cfg.L1ProcessSource
l1BlobFetcher = cfg.L1BeaconProcessSource
l2DebugCl = cfg.L2ProcessSource
} else {
logger.Info("Connecting to L1 node", "l1", cfg.L1URL)
l1RPC, err := client.NewRPC(ctx, logger, cfg.L1URL, client.WithDialBackoff(10))
if err != nil {
return nil, fmt.Errorf("failed to setup L1 RPC: %w", err)
}
l1ClCfg := sources.L1ClientDefaultConfig(cfg.Rollup, cfg.L1TrustRPC, cfg.L1RPCKind)
l2ClCfg := sources.L2ClientDefaultConfig(cfg.Rollup, true)
l1Cl, err := sources.NewL1Client(l1RPC, logger, nil, l1ClCfg)
if err != nil {
return nil, fmt.Errorf("failed to create L1 client: %w", err)
}
l1Beacon := sources.NewBeaconHTTPClient(client.NewBasicHTTPClient(cfg.L1BeaconURL, logger))
l1BlobFetcher := sources.NewL1BeaconClient(l1Beacon, sources.L1BeaconClientConfig{FetchAllSidecars: false})
l2Cl, err := NewL2Client(l2RPC, logger, nil, &L2ClientConfig{L2ClientConfig: l2ClCfg, L2Head: cfg.L2Head})
if err != nil {
return nil, fmt.Errorf("failed to create L2 client: %w", err)
logger.Info("Connecting to L2 node", "l2", cfg.L2URL)
l2RPC, err := client.NewRPC(ctx, logger, cfg.L2URL, client.WithDialBackoff(10))
if err != nil {
return nil, fmt.Errorf("failed to setup L2 RPC: %w", err)
}
l1ClCfg := sources.L1ClientDefaultConfig(cfg.Rollup, cfg.L1TrustRPC, cfg.L1RPCKind)
l2ClCfg := sources.L2ClientDefaultConfig(cfg.Rollup, true)
l1Cl, err = sources.NewL1Client(l1RPC, logger, nil, l1ClCfg)
if err != nil {
return nil, fmt.Errorf("failed to create L1 client: %w", err)
}
l1Beacon := sources.NewBeaconHTTPClient(client.NewBasicHTTPClient(cfg.L1BeaconURL, logger))
l1BlobFetcher = sources.NewL1BeaconClient(l1Beacon, sources.L1BeaconClientConfig{FetchAllSidecars: false})
l2Cl, err := NewL2Client(l2RPC, logger, nil, &L2ClientConfig{L2ClientConfig: l2ClCfg, L2Head: cfg.L2Head})
if err != nil {
return nil, fmt.Errorf("failed to create L2 client: %w", err)
}
l2DebugCl = &L2Source{L2Client: l2Cl, DebugClient: sources.NewDebugClient(l2RPC.CallContext)}
}
l2DebugCl := &L2Source{L2Client: l2Cl, DebugClient: sources.NewDebugClient(l2RPC.CallContext)}
return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, l2DebugCl, kv), nil
}
......
......@@ -13,6 +13,7 @@ import (
"github.com/ethereum-optimism/optimism/op-program/client/l2"
"github.com/ethereum-optimism/optimism/op-program/client/mpt"
"github.com/ethereum-optimism/optimism/op-program/host/kvstore"
"github.com/ethereum-optimism/optimism/op-program/host/sources"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
......@@ -34,34 +35,16 @@ var acceleratedPrecompiles = []common.Address{
common.BytesToAddress([]byte{0x0a}), // KZG Point Evaluation
}
type L1Source interface {
InfoByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, error)
InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error)
FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error)
}
type L1BlobSource interface {
GetBlobSidecars(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.BlobSidecar, error)
GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error)
}
type L2Source interface {
InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error)
NodeByHash(ctx context.Context, hash common.Hash) ([]byte, error)
CodeByHash(ctx context.Context, hash common.Hash) ([]byte, error)
OutputByRoot(ctx context.Context, root common.Hash) (eth.Output, error)
}
type Prefetcher struct {
logger log.Logger
l1Fetcher L1Source
l1BlobFetcher L1BlobSource
l2Fetcher L2Source
l1Fetcher sources.L1Source
l1BlobFetcher sources.L1BlobSource
l2Fetcher sources.L2Source
lastHint string
kvStore kvstore.KV
}
func NewPrefetcher(logger log.Logger, l1Fetcher L1Source, l1BlobFetcher L1BlobSource, l2Fetcher L2Source, kvStore kvstore.KV) *Prefetcher {
func NewPrefetcher(logger log.Logger, l1Fetcher sources.L1Source, l1BlobFetcher sources.L1BlobSource, l2Fetcher sources.L2Source, kvStore kvstore.KV) *Prefetcher {
return &Prefetcher{
logger: logger,
l1Fetcher: NewRetryingL1Source(logger, l1Fetcher),
......
......@@ -4,6 +4,7 @@ import (
"context"
"math"
"github.com/ethereum-optimism/optimism/op-program/host/sources"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/ethereum/go-ethereum/common"
......@@ -15,11 +16,11 @@ const maxAttempts = math.MaxInt // Succeed or die trying
type RetryingL1Source struct {
logger log.Logger
source L1Source
source sources.L1Source
strategy retry.Strategy
}
func NewRetryingL1Source(logger log.Logger, source L1Source) *RetryingL1Source {
func NewRetryingL1Source(logger log.Logger, source sources.L1Source) *RetryingL1Source {
return &RetryingL1Source{
logger: logger,
source: source,
......@@ -57,15 +58,15 @@ func (s *RetryingL1Source) FetchReceipts(ctx context.Context, blockHash common.H
})
}
var _ L1Source = (*RetryingL1Source)(nil)
var _ sources.L1Source = (*RetryingL1Source)(nil)
type RetryingL1BlobSource struct {
logger log.Logger
source L1BlobSource
source sources.L1BlobSource
strategy retry.Strategy
}
func NewRetryingL1BlobSource(logger log.Logger, source L1BlobSource) *RetryingL1BlobSource {
func NewRetryingL1BlobSource(logger log.Logger, source sources.L1BlobSource) *RetryingL1BlobSource {
return &RetryingL1BlobSource{
logger: logger,
source: source,
......@@ -93,11 +94,11 @@ func (s *RetryingL1BlobSource) GetBlobs(ctx context.Context, ref eth.L1BlockRef,
})
}
var _ L1BlobSource = (*RetryingL1BlobSource)(nil)
var _ sources.L1BlobSource = (*RetryingL1BlobSource)(nil)
type RetryingL2Source struct {
logger log.Logger
source L2Source
source sources.L2Source
strategy retry.Strategy
}
......@@ -142,7 +143,7 @@ func (s *RetryingL2Source) OutputByRoot(ctx context.Context, root common.Hash) (
})
}
func NewRetryingL2Source(logger log.Logger, source L2Source) *RetryingL2Source {
func NewRetryingL2Source(logger log.Logger, source sources.L2Source) *RetryingL2Source {
return &RetryingL2Source{
logger: logger,
source: source,
......@@ -150,4 +151,4 @@ func NewRetryingL2Source(logger log.Logger, source L2Source) *RetryingL2Source {
}
}
var _ L2Source = (*RetryingL2Source)(nil)
var _ sources.L2Source = (*RetryingL2Source)(nil)
......@@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-program/host/sources"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/ethereum-optimism/optimism/op-service/testlog"
......@@ -374,4 +375,4 @@ func (m *MockL2Source) ExpectOutputByRoot(root common.Hash, output eth.Output, e
m.Mock.On("OutputByRoot", root).Once().Return(output, &err)
}
var _ L2Source = (*MockL2Source)(nil)
var _ sources.L2Source = (*MockL2Source)(nil)
package sources
import (
"context"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type L1Source interface {
InfoByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, error)
InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error)
FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error)
}
type L1BlobSource interface {
GetBlobSidecars(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.BlobSidecar, error)
GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error)
}
type L2Source interface {
InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error)
NodeByHash(ctx context.Context, hash common.Hash) ([]byte, error)
CodeByHash(ctx context.Context, hash common.Hash) ([]byte, error)
OutputByRoot(ctx context.Context, root common.Hash) (eth.Output, error)
}
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