Skip to content

Commit

Permalink
op-program: encapsulate ValidateClaim (#10960)
Browse files Browse the repository at this point in the history
  • Loading branch information
protolambda committed Jun 19, 2024
1 parent ea4d1fd commit 258a480
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 82 deletions.
18 changes: 10 additions & 8 deletions op-e2e/system_fpp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@ import (
"testing"
"time"

"github.com/stretchr/testify/require"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"

"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
"github.com/ethereum-optimism/optimism/op-program/client/driver"
"github.com/ethereum-optimism/optimism/op-program/client/claim"
opp "github.com/ethereum-optimism/optimism/op-program/host"
oppconf "github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require"
)

func TestVerifyL2OutputRoot(t *testing.T) {
Expand Down Expand Up @@ -320,7 +322,7 @@ func testFaultProofProgramScenario(t *testing.T, ctx context.Context, sys *Syste
if s.Detached {
require.Error(t, err, "exit status 1")
} else {
require.ErrorIs(t, err, driver.ErrClaimNotValid)
require.ErrorIs(t, err, claim.ErrClaimNotValid)
}
}

Expand Down
34 changes: 34 additions & 0 deletions op-program/client/claim/validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package claim

import (
"context"
"errors"
"fmt"

"github.com/ethereum/go-ethereum/log"

"github.com/ethereum-optimism/optimism/op-service/eth"
)

var ErrClaimNotValid = errors.New("invalid claim")

type L2Source interface {
L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel) (eth.L2BlockRef, error)
L2OutputRoot(uint64) (eth.Bytes32, error)
}

func ValidateClaim(log log.Logger, l2ClaimBlockNum uint64, claimedOutputRoot eth.Bytes32, src L2Source) error {
l2Head, err := src.L2BlockRefByLabel(context.Background(), eth.Safe)
if err != nil {
return fmt.Errorf("cannot retrieve safe head: %w", err)
}
outputRoot, err := src.L2OutputRoot(min(l2ClaimBlockNum, l2Head.Number))
if err != nil {
return fmt.Errorf("calculate L2 output root: %w", err)
}
log.Info("Validating claim", "head", l2Head, "output", outputRoot, "claim", claimedOutputRoot)
if claimedOutputRoot != outputRoot {
return fmt.Errorf("%w: claim: %v actual: %v", ErrClaimNotValid, claimedOutputRoot, outputRoot)
}
return nil
}
113 changes: 113 additions & 0 deletions op-program/client/claim/validate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package claim

import (
"context"
"errors"
"testing"

"github.com/stretchr/testify/require"

"github.com/ethereum/go-ethereum/log"

"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/testlog"
)

type mockL2 struct {
safeL2 eth.L2BlockRef
safeL2Err error

outputRoot eth.Bytes32
outputRootErr error

requestedOutputRoot uint64
}

func (m *mockL2) L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel) (eth.L2BlockRef, error) {
if label != eth.Safe {
panic("unexpected usage")
}
if m.safeL2Err != nil {
return eth.L2BlockRef{}, m.safeL2Err
}
return m.safeL2, nil
}

func (m *mockL2) L2OutputRoot(u uint64) (eth.Bytes32, error) {
m.requestedOutputRoot = u
if m.outputRootErr != nil {
return eth.Bytes32{}, m.outputRootErr
}
return m.outputRoot, nil
}

var _ L2Source = (*mockL2)(nil)

func TestValidateClaim(t *testing.T) {
t.Run("Valid", func(t *testing.T) {
expected := eth.Bytes32{0x11}
l2 := &mockL2{
outputRoot: expected,
}
logger := testlog.Logger(t, log.LevelError)
err := ValidateClaim(logger, uint64(0), expected, l2)
require.NoError(t, err)
})

t.Run("Valid-PriorToSafeHead", func(t *testing.T) {
expected := eth.Bytes32{0x11}
l2 := &mockL2{
outputRoot: expected,
safeL2: eth.L2BlockRef{
Number: 10,
},
}
logger := testlog.Logger(t, log.LevelError)
err := ValidateClaim(logger, uint64(20), expected, l2)
require.NoError(t, err)
require.Equal(t, uint64(10), l2.requestedOutputRoot)
})

t.Run("Invalid", func(t *testing.T) {
l2 := &mockL2{
outputRoot: eth.Bytes32{0x22},
}
logger := testlog.Logger(t, log.LevelError)
err := ValidateClaim(logger, uint64(0), eth.Bytes32{0x11}, l2)
require.ErrorIs(t, err, ErrClaimNotValid)
})

t.Run("Invalid-PriorToSafeHead", func(t *testing.T) {
l2 := &mockL2{
outputRoot: eth.Bytes32{0x22},
safeL2: eth.L2BlockRef{Number: 10},
}
logger := testlog.Logger(t, log.LevelError)
err := ValidateClaim(logger, uint64(20), eth.Bytes32{0x55}, l2)
require.ErrorIs(t, err, ErrClaimNotValid)
require.Equal(t, uint64(10), l2.requestedOutputRoot)
})

t.Run("Error-safe-head", func(t *testing.T) {
expectedErr := errors.New("boom")
l2 := &mockL2{
outputRoot: eth.Bytes32{0x11},
safeL2: eth.L2BlockRef{Number: 10},
safeL2Err: expectedErr,
}
logger := testlog.Logger(t, log.LevelError)
err := ValidateClaim(logger, uint64(0), eth.Bytes32{0x11}, l2)
require.ErrorIs(t, err, expectedErr)
})
t.Run("Error-output-root", func(t *testing.T) {
expectedErr := errors.New("boom")
l2 := &mockL2{
outputRoot: eth.Bytes32{0x11},
outputRootErr: expectedErr,
safeL2: eth.L2BlockRef{Number: 10},
}
logger := testlog.Logger(t, log.LevelError)
err := ValidateClaim(logger, uint64(0), eth.Bytes32{0x11}, l2)
require.ErrorIs(t, err, expectedErr)
})
}
15 changes: 0 additions & 15 deletions op-program/client/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import (
"github.com/ethereum-optimism/optimism/op-service/eth"
)

var ErrClaimNotValid = errors.New("invalid claim")

type Derivation interface {
Step(ctx context.Context) error
}
Expand Down Expand Up @@ -154,16 +152,3 @@ func (d *Driver) Step(ctx context.Context) error {
func (d *Driver) SafeHead() eth.L2BlockRef {
return d.deriver.SafeL2Head()
}

func (d *Driver) ValidateClaim(l2ClaimBlockNum uint64, claimedOutputRoot eth.Bytes32) error {
l2Head := d.SafeHead()
outputRoot, err := d.l2OutputRoot(min(l2ClaimBlockNum, l2Head.Number))
if err != nil {
return fmt.Errorf("calculate L2 output root: %w", err)
}
d.logger.Info("Validating claim", "head", l2Head, "output", outputRoot, "claim", claimedOutputRoot)
if claimedOutputRoot != outputRoot {
return fmt.Errorf("%w: claim: %v actual: %v", ErrClaimNotValid, claimedOutputRoot, outputRoot)
}
return nil
}
57 changes: 0 additions & 57 deletions op-program/client/driver/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,63 +69,6 @@ func TestNoError(t *testing.T) {
require.NoError(t, err)
}

func TestValidateClaim(t *testing.T) {
t.Run("Valid", func(t *testing.T) {
driver := createDriver(t, io.EOF)
expected := eth.Bytes32{0x11}
driver.l2OutputRoot = func(_ uint64) (eth.Bytes32, error) {
return expected, nil
}
err := driver.ValidateClaim(uint64(0), expected)
require.NoError(t, err)
})

t.Run("Valid-PriorToSafeHead", func(t *testing.T) {
driver := createDriverWithNextBlock(t, io.EOF, 10)
expected := eth.Bytes32{0x11}
requestedOutputRoot := uint64(0)
driver.l2OutputRoot = func(blockNum uint64) (eth.Bytes32, error) {
requestedOutputRoot = blockNum
return expected, nil
}
err := driver.ValidateClaim(uint64(20), expected)
require.NoError(t, err)
require.Equal(t, uint64(10), requestedOutputRoot)
})

t.Run("Invalid", func(t *testing.T) {
driver := createDriver(t, io.EOF)
driver.l2OutputRoot = func(_ uint64) (eth.Bytes32, error) {
return eth.Bytes32{0x22}, nil
}
err := driver.ValidateClaim(uint64(0), eth.Bytes32{0x11})
require.ErrorIs(t, err, ErrClaimNotValid)
})

t.Run("Invalid-PriorToSafeHead", func(t *testing.T) {
driver := createDriverWithNextBlock(t, io.EOF, 10)
expected := eth.Bytes32{0x11}
requestedOutputRoot := uint64(0)
driver.l2OutputRoot = func(blockNum uint64) (eth.Bytes32, error) {
requestedOutputRoot = blockNum
return expected, nil
}
err := driver.ValidateClaim(uint64(20), eth.Bytes32{0x55})
require.ErrorIs(t, err, ErrClaimNotValid)
require.Equal(t, uint64(10), requestedOutputRoot)
})

t.Run("Error", func(t *testing.T) {
driver := createDriver(t, io.EOF)
expectedErr := errors.New("boom")
driver.l2OutputRoot = func(_ uint64) (eth.Bytes32, error) {
return eth.Bytes32{}, expectedErr
}
err := driver.ValidateClaim(uint64(0), eth.Bytes32{0x11})
require.ErrorIs(t, err, expectedErr)
})
}

func createDriver(t *testing.T, derivationResult error) *Driver {
return createDriverWithNextBlock(t, derivationResult, 0)
}
Expand Down
5 changes: 3 additions & 2 deletions op-program/client/program.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/ethereum-optimism/optimism/op-node/rollup"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client/claim"
cldr "github.com/ethereum-optimism/optimism/op-program/client/driver"
"github.com/ethereum-optimism/optimism/op-program/client/l1"
"github.com/ethereum-optimism/optimism/op-program/client/l2"
Expand All @@ -26,7 +27,7 @@ func Main(logger log.Logger) {
log.Info("Starting fault proof program client")
preimageOracle := CreatePreimageChannel()
preimageHinter := CreateHinterChannel()
if err := RunProgram(logger, preimageOracle, preimageHinter); errors.Is(err, cldr.ErrClaimNotValid) {
if err := RunProgram(logger, preimageOracle, preimageHinter); errors.Is(err, claim.ErrClaimNotValid) {
log.Error("Claim is invalid", "err", err)
os.Exit(1)
} else if err != nil {
Expand Down Expand Up @@ -79,7 +80,7 @@ func runDerivation(logger log.Logger, cfg *rollup.Config, l2Cfg *params.ChainCon
return err
}
}
return d.ValidateClaim(l2ClaimBlockNum, eth.Bytes32(l2Claim))
return claim.ValidateClaim(logger, l2ClaimBlockNum, eth.Bytes32(l2Claim), l2Source)
}

func CreateHinterChannel() oppio.FileChannel {
Expand Down

0 comments on commit 258a480

Please sign in to comment.