From 78d2cdd012982f28548c5edd4ef9b9cfbd42c3ae Mon Sep 17 00:00:00 2001 From: Adrian Sutton Date: Fri, 19 Jan 2024 12:52:12 +1000 Subject: [PATCH] op-challenger: Trigger verification of completed preimages (#9097) --- op-challenger/game/keccak/scheduler.go | 31 ++++++++---- op-challenger/game/keccak/scheduler_test.go | 56 +++++++++++++++++++-- op-challenger/game/keccak/verifier.go | 22 ++++++++ op-challenger/game/service.go | 3 +- op-challenger/game/types/types.go | 6 +++ 5 files changed, 104 insertions(+), 14 deletions(-) create mode 100644 op-challenger/game/keccak/verifier.go diff --git a/op-challenger/game/keccak/scheduler.go b/op-challenger/game/keccak/scheduler.go index f25e198cbe3f..7a9b5a838cd3 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 cdbb0c385f0b..23d391200922 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 000000000000..08a21aef7c6b --- /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 626172483917..9dec7f841b5f 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 e3c03cf5bdcc..3d3b631978ca 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)