Commit cabb24d7 authored by Adrian Sutton's avatar Adrian Sutton Committed by GitHub

op-e2e: Add e2e test for validating preimages. (#9251)

Actually start the preimage scheduler.
parent 0196cf74
...@@ -71,6 +71,7 @@ func (c *PreimageChallenger) Challenge(ctx context.Context, blockHash common.Has ...@@ -71,6 +71,7 @@ func (c *PreimageChallenger) Challenge(ctx context.Context, blockHash common.Has
}() }()
} }
wg.Wait() wg.Wait()
c.log.Debug("Created preimage challenge transactions", "count", len(txs))
if len(txs) > 0 { if len(txs) > 0 {
_, err := c.sender.SendAndWait("challenge preimages", txs...) _, err := c.sender.SendAndWait("challenge preimages", txs...)
if err != nil { if err != nil {
......
...@@ -62,6 +62,7 @@ func (s *LargePreimageScheduler) Schedule(blockHash common.Hash, _ uint64) error ...@@ -62,6 +62,7 @@ func (s *LargePreimageScheduler) Schedule(blockHash common.Hash, _ uint64) error
select { select {
case s.ch <- blockHash: case s.ch <- blockHash:
default: default:
s.log.Trace("Skipping preimage check while already processing")
// Already busy processing, skip this update // Already busy processing, skip this update
} }
return nil return nil
......
...@@ -246,6 +246,7 @@ func (s *Service) initMonitor(cfg *config.Config) { ...@@ -246,6 +246,7 @@ func (s *Service) initMonitor(cfg *config.Config) {
func (s *Service) Start(ctx context.Context) error { func (s *Service) Start(ctx context.Context) error {
s.logger.Info("starting scheduler") s.logger.Info("starting scheduler")
s.sched.Start(ctx) s.sched.Start(ctx)
s.preimages.Start(ctx)
s.logger.Info("starting monitoring") s.logger.Info("starting monitoring")
s.monitor.StartMonitoring() s.monitor.StartMonitoring()
s.logger.Info("challenger game service start completed") s.logger.Info("challenger game service start completed")
......
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/outputs" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/outputs"
faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame/preimage"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
...@@ -101,6 +102,21 @@ func NewFactoryHelper(t *testing.T, ctx context.Context, system DisputeSystem) * ...@@ -101,6 +102,21 @@ func NewFactoryHelper(t *testing.T, ctx context.Context, system DisputeSystem) *
} }
} }
func (h *FactoryHelper) PreimageHelper(ctx context.Context) *preimage.Helper {
opts := &bind.CallOpts{Context: ctx}
gameAddr, err := h.factory.GameImpls(opts, alphabetGameType)
h.require.NoError(err)
game, err := bindings.NewFaultDisputeGameCaller(gameAddr, h.client)
h.require.NoError(err)
vmAddr, err := game.Vm(opts)
h.require.NoError(err)
vm, err := bindings.NewMIPSCaller(vmAddr, h.client)
h.require.NoError(err)
oracleAddr, err := vm.Oracle(opts)
h.require.NoError(err)
return preimage.NewHelper(h.t, h.opts, h.client, oracleAddr)
}
func (h *FactoryHelper) StartOutputCannonGameWithCorrectRoot(ctx context.Context, l2Node string, l2BlockNumber uint64) *OutputCannonGameHelper { func (h *FactoryHelper) StartOutputCannonGameWithCorrectRoot(ctx context.Context, l2Node string, l2BlockNumber uint64) *OutputCannonGameHelper {
h.waitForBlockToBeSafe(l2Node, l2BlockNumber) h.waitForBlockToBeSafe(l2Node, l2BlockNumber)
output, err := h.system.RollupClient(l2Node).OutputAtBlock(ctx, l2BlockNumber) output, err := h.system.RollupClient(l2Node).OutputAtBlock(ctx, l2BlockNumber)
......
package preimage
import (
"bytes"
"context"
"errors"
"io"
"math/big"
"math/rand"
"sync/atomic"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/preimages"
"github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix"
"github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/testutils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
)
const MinPreimageSize = 18000
type Helper struct {
t *testing.T
require *require.Assertions
client *ethclient.Client
opts *bind.TransactOpts
oracleBindings *bindings.PreimageOracle
oracle *contracts.PreimageOracleContract
uuidProvider atomic.Int64
}
func NewHelper(t *testing.T, opts *bind.TransactOpts, client *ethclient.Client, addr common.Address) *Helper {
require := require.New(t)
oracleBindings, err := bindings.NewPreimageOracle(addr, client)
require.NoError(err)
oracle, err := contracts.NewPreimageOracleContract(addr, batching.NewMultiCaller(client.Client(), batching.DefaultBatchSize))
require.NoError(err)
return &Helper{
t: t,
require: require,
client: client,
opts: opts,
oracleBindings: oracleBindings,
oracle: oracle,
}
}
type InputModifier func(startBlock uint64, input *types.InputData)
func WithReplacedCommitment(idx uint64, value common.Hash) InputModifier {
return func(startBlock uint64, input *types.InputData) {
if startBlock > idx {
return
}
if startBlock+uint64(len(input.Commitments)) < idx {
return
}
input.Commitments[idx-startBlock] = value
}
}
// UploadLargePreimage inits the preimage upload and uploads the leaves, starting the challenge period.
// Squeeze is not called by this method as the challenge period has not yet elapsed.
func (h *Helper) UploadLargePreimage(ctx context.Context, dataSize int, modifiers ...InputModifier) types.LargePreimageIdent {
data := testutils.RandomData(rand.New(rand.NewSource(1234)), dataSize)
s := matrix.NewStateMatrix()
uuid := big.NewInt(h.uuidProvider.Add(1))
tx, err := h.oracleBindings.InitLPP(h.opts, uuid, 32, uint32(len(data)))
h.require.NoError(err)
_, err = wait.ForReceiptOK(ctx, h.client, tx.Hash())
h.require.NoError(err)
startBlock := big.NewInt(0)
totalBlocks := len(data) / types.BlockSize
in := bytes.NewReader(data)
for {
inputData, err := s.AbsorbUpTo(in, preimages.MaxChunkSize)
if !errors.Is(err, io.EOF) {
h.require.NoError(err)
}
for _, modifier := range modifiers {
modifier(startBlock.Uint64(), &inputData)
}
commitments := make([][32]byte, len(inputData.Commitments))
for i, commitment := range inputData.Commitments {
commitments[i] = commitment
}
h.t.Logf("Uploading %v parts of preimage %v starting at block %v of about %v Finalize: %v", len(commitments), uuid.Uint64(), startBlock.Uint64(), totalBlocks, inputData.Finalize)
tx, err := h.oracleBindings.AddLeavesLPP(h.opts, uuid, startBlock, inputData.Input, commitments, inputData.Finalize)
h.require.NoError(err)
_, err = wait.ForReceiptOK(ctx, h.client, tx.Hash())
h.require.NoError(err)
startBlock = new(big.Int).Add(startBlock, big.NewInt(int64(len(inputData.Commitments))))
if inputData.Finalize {
break
}
}
return types.LargePreimageIdent{
Claimant: h.opts.From,
UUID: uuid,
}
}
func (h *Helper) WaitForChallenged(ctx context.Context, ident types.LargePreimageIdent) {
timedCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
err := wait.For(timedCtx, time.Second, func() (bool, error) {
metadata, err := h.oracle.GetProposalMetadata(ctx, batching.BlockLatest, ident)
if err != nil {
return false, err
}
h.require.Len(metadata, 1)
return metadata[0].Countered, nil
})
h.require.NoError(err, "Preimage was not challenged")
}
package faultproofs
import (
"context"
"testing"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame/preimage"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func TestChallengeLargePreimages_ChallengeFirst(t *testing.T) {
// TODO(client-pod#480: Fix padding and make this pass
t.Skip("Padding not implemented properly yet")
op_e2e.InitParallel(t)
ctx := context.Background()
sys, _ := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys)
disputeGameFactory.StartChallenger(ctx, "Challenger",
challenger.WithAlphabet(sys.RollupEndpoint("sequencer")),
challenger.WithPrivKey(sys.Cfg.Secrets.Alice))
preimageHelper := disputeGameFactory.PreimageHelper(ctx)
ident := preimageHelper.UploadLargePreimage(ctx, preimage.MinPreimageSize,
preimage.WithReplacedCommitment(0, common.Hash{0xaa}))
require.NotEqual(t, ident.Claimant, common.Address{})
preimageHelper.WaitForChallenged(ctx, ident)
}
func TestChallengeLargePreimages_ChallengeMiddle(t *testing.T) {
// TODO(client-pod#480: Fix padding and make this pass
t.Skip("Padding not implemented properly yet")
op_e2e.InitParallel(t)
ctx := context.Background()
sys, _ := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys)
disputeGameFactory.StartChallenger(ctx, "Challenger",
challenger.WithAlphabet(sys.RollupEndpoint("sequencer")),
challenger.WithPrivKey(sys.Cfg.Secrets.Mallory))
preimageHelper := disputeGameFactory.PreimageHelper(ctx)
ident := preimageHelper.UploadLargePreimage(ctx, preimage.MinPreimageSize,
preimage.WithReplacedCommitment(10, common.Hash{0xaa}))
require.NotEqual(t, ident.Claimant, common.Address{})
preimageHelper.WaitForChallenged(ctx, ident)
}
...@@ -55,6 +55,6 @@ ...@@ -55,6 +55,6 @@
"faultGameGenesisBlock": 0, "faultGameGenesisBlock": 0,
"faultGameGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "faultGameGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
"faultGameSplitDepth": 14, "faultGameSplitDepth": 14,
"preimageOracleMinProposalSize": 1800000, "preimageOracleMinProposalSize": 18000,
"preimageOracleChallengePeriod": 86400 "preimageOracleChallengePeriod": 86400
} }
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