Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] Don't let the sequencer include deposits that aren't part of L1 #57

Merged
merged 1 commit into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions op-enclave/enclave/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ func (c *Client) SetSignerKey(ctx context.Context, encrypted hexutil.Bytes) erro
return c.callContext(ctx, nil, "setSignerKey", encrypted)
}

func (c *Client) ExecuteStateless(ctx context.Context, config *PerChainConfig, l1Origin *types.Header, l1Receipts types.Receipts, previousBlockTxs []hexutil.Bytes, blockHeader *types.Header, blockTxs []hexutil.Bytes, witness *stateless.ExecutionWitness, messageAccount *eth.AccountResult, prevMessageAccountHash common.Hash) (*Proposal, error) {
func (c *Client) ExecuteStateless(ctx context.Context, config *PerChainConfig, l1Origin *types.Header, l1Receipts types.Receipts, previousBlockTxs []hexutil.Bytes, blockHeader *types.Header, sequencedTxs []hexutil.Bytes, witness *stateless.ExecutionWitness, messageAccount *eth.AccountResult, prevMessageAccountHash common.Hash) (*Proposal, error) {
var result Proposal
return &result, c.callContext(ctx, &result, "executeStateless", config, l1Origin, l1Receipts, previousBlockTxs, blockHeader, blockTxs, witness, messageAccount, prevMessageAccountHash)
return &result, c.callContext(ctx, &result, "executeStateless", config, l1Origin, l1Receipts, previousBlockTxs, blockHeader, sequencedTxs, witness, messageAccount, prevMessageAccountHash)
}

func (c *Client) Aggregate(ctx context.Context, configHash common.Hash, prevOutputRoot common.Hash, proposals []*Proposal) (*Proposal, error) {
Expand Down
2 changes: 1 addition & 1 deletion op-enclave/enclave/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type RPC interface {
l1Receipts types.Receipts,
previousBlockTxs []hexutil.Bytes,
blockHeader *types.Header,
blockTxs []hexutil.Bytes,
sequencedTxs []hexutil.Bytes,
witness *stateless.ExecutionWitness,
messageAccount *eth.AccountResult,
prevMessageAccountHash common.Hash,
Expand Down
4 changes: 2 additions & 2 deletions op-enclave/enclave/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ func (s *Server) ExecuteStateless(
l1Receipts types.Receipts,
previousBlockTxs []hexutil.Bytes,
blockHeader *types.Header,
blockTxs []hexutil.Bytes,
sequencedTxs []hexutil.Bytes,
witness *stateless.ExecutionWitness,
messageAccount *eth.AccountResult,
prevMessageAccountHash common.Hash,
Expand All @@ -267,7 +267,7 @@ func (s *Server) ExecuteStateless(
previousBlockHeader := w.Headers[0]

err = ExecuteStateless(ctx, config.ChainConfig, config.ToRollupConfig(),
l1Origin, l1Receipts, previousBlockTxs, blockHeader, blockTxs, w, messageAccount)
l1Origin, l1Receipts, previousBlockTxs, blockHeader, sequencedTxs, w, messageAccount)
if err != nil {
return nil, err
}
Expand Down
38 changes: 18 additions & 20 deletions op-enclave/enclave/stateless.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package enclave

import (
"bytes"
"context"
"errors"
"fmt"
Expand All @@ -26,7 +25,7 @@ func ExecuteStateless(
l1Receipts types.Receipts,
previousBlockTxs []hexutil.Bytes,
blockHeader *types.Header,
blockTxs []hexutil.Bytes,
sequencedTxs []hexutil.Bytes,
witness *stateless.Witness,
messageAccount *eth.AccountResult,
) error {
Expand All @@ -42,6 +41,11 @@ func ExecuteStateless(
return errors.New("invalid parent hash")
}

// block must only contain deposit transactions if it is outside the sequencer drift
if len(sequencedTxs) > 0 && blockHeader.Time > l1Origin.Time+maxSequencerDriftFjord {
return errors.New("l1 origin is too old")
}

unmarshalTxs := func(rlp []hexutil.Bytes) (types.Transactions, error) {
txs := make(types.Transactions, len(rlp))
for i, tx := range rlp {
Expand All @@ -56,10 +60,6 @@ func ExecuteStateless(
if err != nil {
return err
}
txs, err := unmarshalTxs(blockTxs)
if err != nil {
return err
}

previousTxHash := types.DeriveSha(previousTxs, trie.NewStackTrie(nil))
if previousTxHash != previousBlockHeader.TxHash {
Expand Down Expand Up @@ -90,25 +90,23 @@ func ExecuteStateless(
return fmt.Errorf("failed to prepare payload attributes: %w", err)
}

if txs.Len() < len(payload.Transactions) {
return errors.New("invalid transaction count")
// sequencer cannot include manual deposit transactions; otherwise it could mint funds arbitrarily
txs, err := unmarshalTxs(sequencedTxs)
if err != nil {
return err
}

for i, payloadTx := range payload.Transactions {
tx := txs[i]
if !tx.IsDepositTx() {
return errors.New("invalid transaction type")
}
if !bytes.Equal(blockTxs[i], payloadTx) {
return errors.New("invalid deposit transaction")
for _, tx := range txs {
if tx.IsDepositTx() {
return errors.New("sequenced txs cannot include deposits")
}
}

// block must only contain deposit transactions if it is outside the sequencer drift
if txs.Len() > len(payload.Transactions) &&
blockHeader.Time > l1Origin.Time+maxSequencerDriftFjord {
return errors.New("L1 origin is too old")
// now add the deposits from L1 (and any from fork upgrades)
payloadTxs, err := unmarshalTxs(payload.Transactions)
if err != nil {
return fmt.Errorf("failed to parse payload transactions: %w", err)
}
txs = append(payloadTxs, txs...)

expectedRoot := blockHeader.Root
expectedReceiptHash := blockHeader.ReceiptHash
Expand Down
22 changes: 13 additions & 9 deletions op-proposer/proposer/prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,21 +118,25 @@ func (o *Prover) Generate(ctx context.Context, block *types.Block) (*Proposal, e
return nil, &multierror.Error{Errors: errors}
}

marshalTxs := func(txs types.Transactions) ([]hexutil.Bytes, error) {
rlp := make([]hexutil.Bytes, len(txs))
var err error
for i, tx := range txs {
if rlp[i], err = tx.MarshalBinary(); err != nil {
marshalTxs := func(txs types.Transactions, includeDeposits bool) ([]hexutil.Bytes, error) {
var rlps []hexutil.Bytes
for _, tx := range txs {
if !includeDeposits && tx.IsDepositTx() {
continue
}
rlp, err := tx.MarshalBinary()
if err != nil {
return nil, fmt.Errorf("failed to marshal transaction: %w", err)
}
rlps = append(rlps, rlp)
}
return rlp, nil
return rlps, nil
}
previousTxs, err := marshalTxs(previousBlock.value.Transactions())
previousTxs, err := marshalTxs(previousBlock.value.Transactions(), true)
if err != nil {
return nil, err
}
txs, err := marshalTxs(block.Transactions())
sequencedTxs, err := marshalTxs(block.Transactions(), false)
if err != nil {
return nil, err
}
Expand All @@ -144,7 +148,7 @@ func (o *Prover) Generate(ctx context.Context, block *types.Block) (*Proposal, e
l1Receipts.value,
previousTxs,
block.Header(),
txs,
sequencedTxs,
witness.value,
messageAccount.value,
prevMessageAccount.value.StorageHash,
Expand Down
Loading