Commit 1e6a656f authored by Adrian Sutton's avatar Adrian Sutton

op-challenger: Create cannon trace providers for the bottom half of output cannon traces.

parent d2f2db1e
...@@ -65,7 +65,7 @@ func registerOutputCannon( ...@@ -65,7 +65,7 @@ func registerOutputCannon(
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
accessor, err := outputs.NewOutputCannonTraceAccessor(ctx, logger, m, cfg.RollupRpc, gameDepth, agreed.L2BlockNumber.Uint64(), disputed.L2BlockNumber.Uint64()) accessor, err := outputs.NewOutputCannonTraceAccessor(ctx, logger, m, cfg, contract, dir, gameDepth, agreed.L2BlockNumber.Uint64(), disputed.L2BlockNumber.Uint64())
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
......
...@@ -23,21 +23,29 @@ type L2DataSource interface { ...@@ -23,21 +23,29 @@ type L2DataSource interface {
HeaderByNumber(context.Context, *big.Int) (*ethtypes.Header, error) HeaderByNumber(context.Context, *big.Int) (*ethtypes.Header, error)
} }
type GameInputsSource interface { type L1HeadSource interface {
GetL1Head(ctx context.Context) (common.Hash, error) GetL1Head(ctx context.Context) (common.Hash, error)
}
type GameInputsSource interface {
L1HeadSource
GetProposals(ctx context.Context) (agreed contracts.Proposal, disputed contracts.Proposal, err error) GetProposals(ctx context.Context) (agreed contracts.Proposal, disputed contracts.Proposal, err error)
} }
func fetchLocalInputs(ctx context.Context, caller GameInputsSource, l2Client L2DataSource) (LocalGameInputs, error) { func fetchLocalInputs(ctx context.Context, caller GameInputsSource, l2Client L2DataSource) (LocalGameInputs, error) {
l1Head, err := caller.GetL1Head(ctx) agreedOutput, claimedOutput, err := caller.GetProposals(ctx)
if err != nil { if err != nil {
return LocalGameInputs{}, fmt.Errorf("fetch L1 head: %w", err) return LocalGameInputs{}, fmt.Errorf("fetch proposals: %w", err)
} }
return fetchLocalInputsFromProposals(ctx, caller, l2Client, agreedOutput, claimedOutput)
}
agreedOutput, claimedOutput, err := caller.GetProposals(ctx) func fetchLocalInputsFromProposals(ctx context.Context, caller GameInputsSource, l2Client L2DataSource, agreedOutput contracts.Proposal, claimedOutput contracts.Proposal) (LocalGameInputs, error) {
l1Head, err := caller.GetL1Head(ctx)
if err != nil { if err != nil {
return LocalGameInputs{}, fmt.Errorf("fetch proposals: %w", err) return LocalGameInputs{}, fmt.Errorf("fetch L1 head: %w", err)
} }
agreedHeader, err := l2Client.HeaderByNumber(ctx, agreedOutput.L2BlockNumber) agreedHeader, err := l2Client.HeaderByNumber(ctx, agreedOutput.L2BlockNumber)
if err != nil { if err != nil {
return LocalGameInputs{}, fmt.Errorf("fetch L2 block header %v: %w", agreedOutput.L2BlockNumber, err) return LocalGameInputs{}, fmt.Errorf("fetch L2 block header %v: %w", agreedOutput.L2BlockNumber, err)
......
...@@ -42,6 +42,36 @@ func TestFetchLocalInputs(t *testing.T) { ...@@ -42,6 +42,36 @@ func TestFetchLocalInputs(t *testing.T) {
require.Equal(t, contract.disputed.L2BlockNumber, inputs.L2BlockNumber) require.Equal(t, contract.disputed.L2BlockNumber, inputs.L2BlockNumber)
} }
func TestFetchLocalInputsFromProposals(t *testing.T) {
ctx := context.Background()
agreed := contracts.Proposal{
L2BlockNumber: big.NewInt(2222),
OutputRoot: common.Hash{0xdd},
}
claimed := contracts.Proposal{
L2BlockNumber: big.NewInt(3333),
OutputRoot: common.Hash{0xee},
}
contract := &mockGameInputsSource{
l1Head: common.Hash{0xcc},
}
l2Client := &mockL2DataSource{
chainID: big.NewInt(88422),
header: ethtypes.Header{
Number: agreed.L2BlockNumber,
},
}
inputs, err := fetchLocalInputsFromProposals(ctx, contract, l2Client, agreed, claimed)
require.NoError(t, err)
require.Equal(t, contract.l1Head, inputs.L1Head)
require.Equal(t, l2Client.header.Hash(), inputs.L2Head)
require.EqualValues(t, agreed.OutputRoot, inputs.L2OutputRoot)
require.EqualValues(t, claimed.OutputRoot, inputs.L2Claim)
require.Equal(t, claimed.L2BlockNumber, inputs.L2BlockNumber)
}
type mockGameInputsSource struct { type mockGameInputsSource struct {
l1Head common.Hash l1Head common.Hash
starting contracts.Proposal starting contracts.Proposal
......
...@@ -69,6 +69,30 @@ func NewTraceProvider(ctx context.Context, logger log.Logger, m CannonMetricer, ...@@ -69,6 +69,30 @@ func NewTraceProvider(ctx context.Context, logger log.Logger, m CannonMetricer,
return NewTraceProviderFromInputs(logger, m, cfg, localContext, localInputs, dir, gameDepth), nil return NewTraceProviderFromInputs(logger, m, cfg, localContext, localInputs, dir, gameDepth), nil
} }
func NewTraceProviderFromProposals(
ctx context.Context,
logger log.Logger,
m CannonMetricer,
cfg *config.Config,
gameContract *contracts.FaultDisputeGameContract,
localContext common.Hash,
agreed contracts.Proposal,
claimed contracts.Proposal,
dir string,
gameDepth uint64,
) (*CannonTraceProvider, error) {
l2Client, err := ethclient.DialContext(ctx, cfg.CannonL2)
if err != nil {
return nil, fmt.Errorf("dial l2 client %v: %w", cfg.CannonL2, err)
}
defer l2Client.Close() // Not needed after fetching the inputs
localInputs, err := fetchLocalInputsFromProposals(ctx, gameContract, l2Client, agreed, claimed)
if err != nil {
return nil, fmt.Errorf("fetch local game inputs: %w", err)
}
return NewTraceProviderFromInputs(logger, m, cfg, localContext, localInputs, dir, gameDepth), nil
}
func NewTraceProviderFromInputs(logger log.Logger, m CannonMetricer, cfg *config.Config, localContext common.Hash, localInputs LocalGameInputs, dir string, gameDepth uint64) *CannonTraceProvider { func NewTraceProviderFromInputs(logger log.Logger, m CannonMetricer, cfg *config.Config, localContext common.Hash, localInputs LocalGameInputs, dir string, gameDepth uint64) *CannonTraceProvider {
return &CannonTraceProvider{ return &CannonTraceProvider{
logger: logger, logger: logger,
......
...@@ -2,10 +2,13 @@ package outputs ...@@ -2,10 +2,13 @@ package outputs
import ( import (
"context" "context"
"errors" "fmt"
"path/filepath"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-challenger/metrics"
...@@ -17,20 +20,29 @@ func NewOutputCannonTraceAccessor( ...@@ -17,20 +20,29 @@ func NewOutputCannonTraceAccessor(
ctx context.Context, ctx context.Context,
logger log.Logger, logger log.Logger,
m metrics.Metricer, m metrics.Metricer,
rollupRpc string, cfg *config.Config,
contract *contracts.FaultDisputeGameContract,
dir string,
gameDepth uint64, gameDepth uint64,
prestateBlock uint64, prestateBlock uint64,
poststateBlock uint64, poststateBlock uint64,
) (*trace.Accessor, error) { ) (*trace.Accessor, error) {
topDepth := gameDepth / 2 // TODO(client-pod#43): Load this from the contract // TODO(client-pod#43): Load depths from the contract
outputProvider, err := NewTraceProvider(ctx, logger, rollupRpc, topDepth, prestateBlock, poststateBlock) topDepth := gameDepth / 2
bottomDepth := gameDepth - topDepth
outputProvider, err := NewTraceProvider(ctx, logger, cfg.RollupRpc, topDepth, prestateBlock, poststateBlock)
if err != nil { if err != nil {
return nil, err return nil, err
} }
cannonCreator := func(ctx context.Context, localContext common.Hash, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) { cannonCreator := func(ctx context.Context, localContext common.Hash, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) {
// TODO(client-pod#43): Actually create the cannon trace provider for the trace between the given claims. logger := logger.New("pre", agreed.OutputRoot, "post", claimed.OutputRoot, "localContext", localContext)
return nil, errors.New("not implemented") subdir := filepath.Join(dir, localContext.Hex())
provider, err := cannon.NewTraceProviderFromProposals(ctx, logger, m, cfg, contract, localContext, agreed, claimed, subdir, bottomDepth)
if err != nil {
return nil, fmt.Errorf("failed to create cannon trace provider: %w", err)
}
return provider, nil
} }
cache := NewProviderCache(m, "output_cannon_provider", cannonCreator) cache := NewProviderCache(m, "output_cannon_provider", cannonCreator)
......
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