Skip to content

Commit

Permalink
feat(op-challenger): Large Preimage Uploader InitLPP Call Support (et…
Browse files Browse the repository at this point in the history
…hereum-optimism#9033)

* feat(op-challenger): Adds a helper to call the initLPP preimage oracle
contract call.

* fix(op-challenger): call init large preimage from the uploader

* fix(op-challenger): keep large preimage upload unsupported for the interim
  • Loading branch information
refcell authored Jan 18, 2024
1 parent 7b8b9a8 commit 989b640
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 9 deletions.
11 changes: 6 additions & 5 deletions op-challenger/game/fault/preimages/direct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
var (
mockUpdateOracleTxError = errors.New("mock update oracle tx error")
mockTxMgrSendError = errors.New("mock tx mgr send error")
mockInitLPPError = errors.New("mock init LPP error")
)

func TestDirectPreimageUploader_UploadPreimage(t *testing.T) {
Expand All @@ -25,7 +26,7 @@ func TestDirectPreimageUploader_UploadPreimage(t *testing.T) {
contract.updateFails = true
err := oracle.UploadPreimage(context.Background(), 0, &types.PreimageOracleData{})
require.ErrorIs(t, err, mockUpdateOracleTxError)
require.Equal(t, 1, contract.updates)
require.Equal(t, 1, contract.updateCalls)
require.Equal(t, 0, txMgr.sends) // verify that the tx was not sent
})

Expand All @@ -34,7 +35,7 @@ func TestDirectPreimageUploader_UploadPreimage(t *testing.T) {
txMgr.sendFails = true
err := oracle.UploadPreimage(context.Background(), 0, &types.PreimageOracleData{})
require.ErrorIs(t, err, mockTxMgrSendError)
require.Equal(t, 1, contract.updates)
require.Equal(t, 1, contract.updateCalls)
require.Equal(t, 1, txMgr.sends)
})

Expand All @@ -48,7 +49,7 @@ func TestDirectPreimageUploader_UploadPreimage(t *testing.T) {
oracle, _, contract := newTestDirectPreimageUploader(t)
err := oracle.UploadPreimage(context.Background(), 0, &types.PreimageOracleData{})
require.NoError(t, err)
require.Equal(t, 1, contract.updates)
require.Equal(t, 1, contract.updateCalls)
})
}

Expand Down Expand Up @@ -85,12 +86,12 @@ func newTestDirectPreimageUploader(t *testing.T) (*DirectPreimageUploader, *mock
}

type mockPreimageGameContract struct {
updates int
updateCalls int
updateFails bool
}

func (s *mockPreimageGameContract) UpdateOracleTx(_ context.Context, _ uint64, _ *types.PreimageOracleData) (txmgr.TxCandidate, error) {
s.updates++
s.updateCalls++
if s.updateFails {
return txmgr.TxCandidate{}, mockUpdateOracleTxError
}
Expand Down
54 changes: 52 additions & 2 deletions op-challenger/game/fault/preimages/large.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ package preimages

import (
"context"
"crypto/rand"
"errors"
"fmt"
"math/big"

"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
)

var _ PreimageUploader = (*LargePreimageUploader)(nil)

var errNotSupported = errors.New("not supported")

var _ PreimageUploader = (*LargePreimageUploader)(nil)

// LargePreimageUploader handles uploading large preimages by
// streaming the merkleized preimage to the PreimageOracle contract,
// tightly packed across multiple transactions.
Expand All @@ -34,7 +38,53 @@ func (p *LargePreimageUploader) UploadPreimage(ctx context.Context, parent uint6
// todo(proofs#467): split up the preimage into chunks and submit the preimages
// and state commitments to the preimage oracle contract using
// `PreimageOracle.addLeavesLPP` (`_finalize` = false).

// TODO(client-pod#473): The UUID must be deterministic so the challenger can resume uploads.
uuid, err := p.newUUID()
if err != nil {
return fmt.Errorf("failed to generate UUID: %w", err)
}
err = p.initLargePreimage(ctx, uuid, data.OracleOffset, uint32(len(data.OracleData)))
if err != nil {
return fmt.Errorf("failed to initialize large preimage with uuid: %s: %w", uuid, err)
}

// todo(proofs#467): track the challenge period starting once the full preimage is posted.
// todo(proofs#467): once the challenge period is over, call `squeezeLPP` on the preimage oracle contract.

return errNotSupported
}

func (p *LargePreimageUploader) newUUID() (*big.Int, error) {
max := new(big.Int)
max.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(max, big.NewInt(1))
return rand.Int(rand.Reader, max)
}

// initLargePreimage initializes the large preimage proposal.
// This method *must* be called before adding any leaves.
func (p *LargePreimageUploader) initLargePreimage(ctx context.Context, uuid *big.Int, partOffset uint32, claimedSize uint32) error {
candidate, err := p.contract.InitLargePreimage(uuid, partOffset, claimedSize)
if err != nil {
return fmt.Errorf("failed to create pre-image oracle tx: %w", err)
}
if err := p.sendTxAndWait(ctx, candidate); err != nil {
return fmt.Errorf("failed to populate pre-image oracle: %w", err)
}
return nil
}

// sendTxAndWait sends a transaction through the [txmgr] and waits for a receipt.
// This sets the tx GasLimit to 0, performing gas estimation online through the [txmgr].
func (p *LargePreimageUploader) sendTxAndWait(ctx context.Context, candidate txmgr.TxCandidate) error {
receipt, err := p.txMgr.Send(ctx, candidate)
if err != nil {
return err
}
if receipt.Status == ethtypes.ReceiptStatusFailed {
p.log.Error("LargePreimageUploader tx successfully published but reverted", "tx_hash", receipt.TxHash)
} else {
p.log.Debug("LargePreimageUploader tx successfully published", "tx_hash", receipt.TxHash)
}
return nil
}
20 changes: 18 additions & 2 deletions op-challenger/game/fault/preimages/large_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@ import (
)

func TestLargePreimageUploader_UploadPreimage(t *testing.T) {
t.Run("InitFails", func(t *testing.T) {
oracle, _, contract := newTestLargePreimageUploader(t)
contract.initFails = true
err := oracle.UploadPreimage(context.Background(), 0, &types.PreimageOracleData{})
require.ErrorIs(t, err, mockInitLPPError)
require.Equal(t, 1, contract.initCalls)
})

t.Run("Success", func(t *testing.T) {
oracle, _, _ := newTestLargePreimageUploader(t)
oracle, _, contract := newTestLargePreimageUploader(t)
err := oracle.UploadPreimage(context.Background(), 0, &types.PreimageOracleData{})
require.Equal(t, 1, contract.initCalls)
// TODO(proofs#467): fix this to not error. See LargePreimageUploader.UploadPreimage.
require.ErrorIs(t, err, errNotSupported)
})
Expand All @@ -31,9 +40,16 @@ func newTestLargePreimageUploader(t *testing.T) (*LargePreimageUploader, *mockTx
return NewLargePreimageUploader(logger, txMgr, contract), txMgr, contract
}

type mockPreimageOracleContract struct{}
type mockPreimageOracleContract struct {
initCalls int
initFails bool
}

func (s *mockPreimageOracleContract) InitLargePreimage(_ *big.Int, _ uint32, _ uint32) (txmgr.TxCandidate, error) {
s.initCalls++
if s.initFails {
return txmgr.TxCandidate{}, mockInitLPPError
}
return txmgr.TxCandidate{}, nil
}
func (s *mockPreimageOracleContract) AddLeaves(_ *big.Int, _ []contracts.Leaf, _ bool) ([]txmgr.TxCandidate, error) {
Expand Down

0 comments on commit 989b640

Please sign in to comment.