validate_test.go 2.83 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 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)
	})
}