diff --git a/op-challenger/game/keccak/scheduler.go b/op-challenger/game/keccak/scheduler.go index f25e198cbe3fd20258987a71b2b8b949ee0cf3f7..7a9b5a838cd30567db2af7a048f70cea29ed86cc 100644 --- a/op-challenger/game/keccak/scheduler.go +++ b/op-challenger/game/keccak/scheduler.go @@ -9,19 +9,25 @@ import ( "github.com/ethereum/go-ethereum/log" ) +type Verifier interface { + Verify(ctx context.Context, oracle types.LargePreimageOracle, preimage types.LargePreimageMetaData) +} + type LargePreimageScheduler struct { - log log.Logger - ch chan common.Hash - oracles []types.LargePreimageOracle - cancel func() - wg sync.WaitGroup + log log.Logger + ch chan common.Hash + oracles []types.LargePreimageOracle + verifier Verifier + cancel func() + wg sync.WaitGroup } -func NewLargePreimageScheduler(logger log.Logger, oracles []types.LargePreimageOracle) *LargePreimageScheduler { +func NewLargePreimageScheduler(logger log.Logger, oracles []types.LargePreimageOracle, verifier Verifier) *LargePreimageScheduler { return &LargePreimageScheduler{ - log: logger, - ch: make(chan common.Hash, 1), - oracles: oracles, + log: logger, + ch: make(chan common.Hash, 1), + oracles: oracles, + verifier: verifier, } } @@ -71,6 +77,11 @@ func (s *LargePreimageScheduler) verifyPreimages(ctx context.Context, blockHash } func (s *LargePreimageScheduler) verifyOraclePreimages(ctx context.Context, oracle types.LargePreimageOracle, blockHash common.Hash) error { - _, err := oracle.GetActivePreimages(ctx, blockHash) + preimages, err := oracle.GetActivePreimages(ctx, blockHash) + for _, preimage := range preimages { + if preimage.ShouldVerify() { + s.verifier.Verify(ctx, oracle, preimage) + } + } return err } diff --git a/op-challenger/game/keccak/scheduler_test.go b/op-challenger/game/keccak/scheduler_test.go index cdbb0c385f0b30cb55c7d60fcba53e8bdba2cfc2..23d39120092282359c238e469b422fccabd0dc13 100644 --- a/op-challenger/game/keccak/scheduler_test.go +++ b/op-challenger/game/keccak/scheduler_test.go @@ -2,6 +2,7 @@ package keccak import ( "context" + "math/big" "sync" "testing" "time" @@ -16,8 +17,32 @@ import ( func TestScheduleNextCheck(t *testing.T) { ctx := context.Background() logger := testlog.Logger(t, log.LvlInfo) - oracle := &stubOracle{} - scheduler := NewLargePreimageScheduler(logger, []types.LargePreimageOracle{oracle}) + preimage1 := types.LargePreimageMetaData{ // Incomplete so won't be verified + LargePreimageIdent: types.LargePreimageIdent{ + Claimant: common.Address{0xab}, + UUID: big.NewInt(111), + }, + } + preimage2 := types.LargePreimageMetaData{ // Already countered so won't be verified + LargePreimageIdent: types.LargePreimageIdent{ + Claimant: common.Address{0xab}, + UUID: big.NewInt(222), + }, + Timestamp: 1234, + Countered: true, + } + preimage3 := types.LargePreimageMetaData{ + LargePreimageIdent: types.LargePreimageIdent{ + Claimant: common.Address{0xdd}, + UUID: big.NewInt(333), + }, + Timestamp: 1234, + } + oracle := &stubOracle{ + images: []types.LargePreimageMetaData{preimage1, preimage2, preimage3}, + } + verifier := &stubVerifier{} + scheduler := NewLargePreimageScheduler(logger, []types.LargePreimageOracle{oracle}, verifier) scheduler.Start(ctx) defer scheduler.Close() err := scheduler.Schedule(common.Hash{0xaa}, 3) @@ -25,12 +50,18 @@ func TestScheduleNextCheck(t *testing.T) { require.Eventually(t, func() bool { return oracle.GetPreimagesCount() == 1 }, 10*time.Second, 10*time.Millisecond) + require.Eventually(t, func() bool { + verified := verifier.Verified() + t.Logf("Verified preimages: %v", verified) + return len(verified) == 1 && verified[0] == preimage3 + }, 10*time.Second, 10*time.Millisecond, "Did not verify preimage") } type stubOracle struct { m sync.Mutex addr common.Address getPreimagesCount int + images []types.LargePreimageMetaData } func (s *stubOracle) Addr() common.Address { @@ -41,7 +72,7 @@ func (s *stubOracle) GetActivePreimages(_ context.Context, _ common.Hash) ([]typ s.m.Lock() defer s.m.Unlock() s.getPreimagesCount++ - return nil, nil + return s.images, nil } func (s *stubOracle) GetPreimagesCount() int { @@ -49,3 +80,22 @@ func (s *stubOracle) GetPreimagesCount() int { defer s.m.Unlock() return s.getPreimagesCount } + +type stubVerifier struct { + m sync.Mutex + verified []types.LargePreimageMetaData +} + +func (s *stubVerifier) Verify(_ context.Context, _ types.LargePreimageOracle, image types.LargePreimageMetaData) { + s.m.Lock() + defer s.m.Unlock() + s.verified = append(s.verified, image) +} + +func (s *stubVerifier) Verified() []types.LargePreimageMetaData { + s.m.Lock() + defer s.m.Unlock() + v := make([]types.LargePreimageMetaData, len(s.verified)) + copy(v, s.verified) + return v +} diff --git a/op-challenger/game/keccak/verifier.go b/op-challenger/game/keccak/verifier.go new file mode 100644 index 0000000000000000000000000000000000000000..08a21aef7c6b9fdb3434dbc02125e9ae55217a85 --- /dev/null +++ b/op-challenger/game/keccak/verifier.go @@ -0,0 +1,22 @@ +package keccak + +import ( + "context" + + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum/go-ethereum/log" +) + +type PreimageVerifier struct { + log log.Logger +} + +func NewPreimageVerifier(logger log.Logger) *PreimageVerifier { + return &PreimageVerifier{ + log: logger, + } +} + +func (v *PreimageVerifier) Verify(ctx context.Context, oracle types.LargePreimageOracle, preimage types.LargePreimageMetaData) { + // No verification currently performed. +} diff --git a/op-challenger/game/service.go b/op-challenger/game/service.go index 62617248391740e6dbf0a6ed5b46abf3fb2ca690..9dec7f841b5fe67f10d21631e5fa59db0b33d53f 100644 --- a/op-challenger/game/service.go +++ b/op-challenger/game/service.go @@ -225,7 +225,8 @@ func (s *Service) initScheduler(cfg *config.Config) error { } func (s *Service) initLargePreimages() error { - s.preimages = keccak.NewLargePreimageScheduler(s.logger, s.registry.Oracles()) + verifier := keccak.NewPreimageVerifier(s.logger) + s.preimages = keccak.NewLargePreimageScheduler(s.logger, s.registry.Oracles(), verifier) return nil } diff --git a/op-challenger/game/types/types.go b/op-challenger/game/types/types.go index e3c03cf5bdccad45ce58eb4d2d224b31b445de21..3d3b631978caf38f9dba430f08b05f9b70216463 100644 --- a/op-challenger/game/types/types.go +++ b/op-challenger/game/types/types.go @@ -62,6 +62,12 @@ type LargePreimageMetaData struct { Countered bool } +// ShouldVerify returns true if the preimage upload is complete and has not yet been countered. +// Note that the challenge period for the preimage may have expired but the image not yet been finalized. +func (m LargePreimageMetaData) ShouldVerify() bool { + return m.Timestamp > 0 && !m.Countered +} + type LargePreimageOracle interface { Addr() common.Address GetActivePreimages(ctx context.Context, blockHash common.Hash) ([]LargePreimageMetaData, error)