From 47053b95dfb3e9b516a177f70c91c5ccc176cef1 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Thu, 25 Jan 2024 13:08:33 -0700 Subject: [PATCH] In delayed sequencer, check accumulator against safe block hash --- arbnode/delayed.go | 41 +++++++++++++++++++++++++++++++----- arbnode/delayed_sequencer.go | 10 ++++++--- arbnode/inbox_reader.go | 3 ++- arbutil/wait_for_l1.go | 1 + 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/arbnode/delayed.go b/arbnode/delayed.go index 498aa0475f..2a1745c540 100644 --- a/arbnode/delayed.go +++ b/arbnode/delayed.go @@ -7,6 +7,7 @@ import ( "bytes" "context" "errors" + "fmt" "math/big" "sort" @@ -14,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" @@ -28,6 +30,7 @@ var messageDeliveredID common.Hash var inboxMessageDeliveredID common.Hash var inboxMessageFromOriginID common.Hash var l2MessageFromOriginCallABI abi.Method +var delayedInboxAccsCallABI abi.Method func init() { parsedIBridgeABI, err := bridgegen.IBridgeMetaData.GetAbi() @@ -35,6 +38,7 @@ func init() { panic(err) } messageDeliveredID = parsedIBridgeABI.Events["MessageDelivered"].ID + delayedInboxAccsCallABI = parsedIBridgeABI.Methods["delayedInboxAccs"] parsedIMessageProviderABI, err := bridgegen.IDelayedMessageProviderMetaData.GetAbi() if err != nil { @@ -95,12 +99,39 @@ func (b *DelayedBridge) GetMessageCount(ctx context.Context, blockNumber *big.In return bigRes.Uint64(), nil } -func (b *DelayedBridge) GetAccumulator(ctx context.Context, sequenceNumber uint64, blockNumber *big.Int) (common.Hash, error) { - opts := &bind.CallOpts{ - Context: ctx, - BlockNumber: blockNumber, +// Uses blockHash if nonzero, otherwise uses blockNumber +func (b *DelayedBridge) GetAccumulator(ctx context.Context, sequenceNumber uint64, blockNumber *big.Int, blockHash common.Hash) (common.Hash, error) { + calldata := append([]byte{}, delayedInboxAccsCallABI.ID...) + inputs, err := delayedInboxAccsCallABI.Inputs.Pack(arbmath.UintToBig(sequenceNumber)) + if err != nil { + return common.Hash{}, err + } + calldata = append(calldata, inputs...) + msg := ethereum.CallMsg{ + To: &b.address, + Data: calldata, + } + var result hexutil.Bytes + if blockHash != (common.Hash{}) { + result, err = b.client.CallContractAtHash(ctx, msg, blockHash) + } else { + result, err = b.client.CallContract(ctx, msg, blockNumber) + } + if err != nil { + return common.Hash{}, err + } + values, err := delayedInboxAccsCallABI.Outputs.Unpack(result) + if err != nil { + return common.Hash{}, err + } + if len(values) != 1 { + return common.Hash{}, fmt.Errorf("expected 1 return value from %v, got %v", delayedInboxAccsCallABI.Name, len(values)) + } + hash, ok := values[0].([32]byte) + if !ok { + return common.Hash{}, fmt.Errorf("expected [32]uint8 return value from %v, got %T", delayedInboxAccsCallABI.Name, values[0]) } - return b.con.DelayedInboxAccs(opts, new(big.Int).SetUint64(sequenceNumber)) + return hash, nil } type DelayedInboxMessage struct { diff --git a/arbnode/delayed_sequencer.go b/arbnode/delayed_sequencer.go index f1b912e0f7..8cbb094c16 100644 --- a/arbnode/delayed_sequencer.go +++ b/arbnode/delayed_sequencer.go @@ -100,16 +100,20 @@ func (d *DelayedSequencer) sequenceWithoutLockout(ctx context.Context, lastBlock } var finalized uint64 + var finalizedHash common.Hash if config.UseMergeFinality && headerreader.HeaderIndicatesFinalitySupport(lastBlockHeader) { + var header *types.Header var err error if config.RequireFullFinality { - finalized, err = d.l1Reader.LatestFinalizedBlockNr(ctx) + header, err = d.l1Reader.LatestFinalizedBlockHeader(ctx) } else { - finalized, err = d.l1Reader.LatestSafeBlockNr(ctx) + header, err = d.l1Reader.LatestSafeBlockHeader(ctx) } if err != nil { return err } + finalized = header.Number.Uint64() + finalizedHash = header.Hash() } else { currentNum := lastBlockHeader.Number.Int64() if currentNum < config.FinalizeDistance { @@ -167,7 +171,7 @@ func (d *DelayedSequencer) sequenceWithoutLockout(ctx context.Context, lastBlock // Sequence the delayed messages, if any if len(messages) > 0 { - delayedBridgeAcc, err := d.bridge.GetAccumulator(ctx, pos-1, new(big.Int).SetUint64(finalized)) + delayedBridgeAcc, err := d.bridge.GetAccumulator(ctx, pos-1, new(big.Int).SetUint64(finalized), finalizedHash) if err != nil { return err } diff --git a/arbnode/inbox_reader.go b/arbnode/inbox_reader.go index 9c830e3c89..7a2ffa505c 100644 --- a/arbnode/inbox_reader.go +++ b/arbnode/inbox_reader.go @@ -14,6 +14,7 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" flag "github.com/spf13/pflag" @@ -299,7 +300,7 @@ func (r *InboxReader) run(ctx context.Context, hadError bool) error { } if checkingDelayedCount > 0 { checkingDelayedSeqNum := checkingDelayedCount - 1 - l1DelayedAcc, err := r.delayedBridge.GetAccumulator(ctx, checkingDelayedSeqNum, currentHeight) + l1DelayedAcc, err := r.delayedBridge.GetAccumulator(ctx, checkingDelayedSeqNum, currentHeight, common.Hash{}) if err != nil { return err } diff --git a/arbutil/wait_for_l1.go b/arbutil/wait_for_l1.go index b66710dbf0..a80502610b 100644 --- a/arbutil/wait_for_l1.go +++ b/arbutil/wait_for_l1.go @@ -23,6 +23,7 @@ type L1Interface interface { ethereum.TransactionReader TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) BlockNumber(ctx context.Context) (uint64, error) + CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) ChainID(ctx context.Context) (*big.Int, error) }