Skip to content

Commit

Permalink
Merge branch 'master' into finalize-arbos-20
Browse files Browse the repository at this point in the history
  • Loading branch information
PlasmaPower authored Feb 20, 2024
2 parents cf2eadf + e62cc57 commit 59876e0
Show file tree
Hide file tree
Showing 66 changed files with 1,508 additions and 373 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,7 @@ jobs:
skip-pkg-cache: true
- name: Custom Lint
run: |
go run ./linter/koanf ./...
go run ./linter/pointercheck ./...
go run ./linters ./...
- name: Set environment variables
run: |
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/release-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Release CI
run-name: Release CI triggered from @${{ github.actor }} of ${{ github.head_ref }}

on:
workflow_dispatch:

jobs:
build_and_run:
runs-on: ubuntu-8

steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host

- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ hashFiles('Dockerfile') }}
restore-keys: ${{ runner.os }}-buildx-

- name: Startup Nitro testnode
run: ./scripts/startup-testnode.bash
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ RUN ./download-machine.sh consensus-v10.2 0x0754e09320c381566cc0449904c377a52bd3
RUN ./download-machine.sh consensus-v10.3 0xf559b6d4fa869472dabce70fe1c15221bdda837533dfd891916836975b434dec
RUN ./download-machine.sh consensus-v11 0xf4389b835497a910d7ba3ebfb77aa93da985634f3c052de1290360635be40c4a
RUN ./download-machine.sh consensus-v11.1 0x68e4fe5023f792d4ef584796c84d710303a5e12ea02d6e37e2b5e9c4332507c4
RUN ./download-machine.sh consensus-v20 0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4

FROM golang:1.20-bookworm as node-builder
WORKDIR /workspace
Expand Down Expand Up @@ -200,7 +201,7 @@ FROM debian:bookworm-slim as nitro-fuzzer
COPY --from=fuzz-builder /workspace/fuzzers/*.fuzz /usr/local/bin/
COPY ./scripts/fuzz.bash /usr/local/bin
RUN mkdir /fuzzcache
ENTRYPOINT [ "/usr/local/bin/fuzz.bash", "--binary-path", "/usr/local/bin/", "--fuzzcache-path", "/fuzzcache" ]
ENTRYPOINT [ "/usr/local/bin/fuzz.bash", "FuzzStateTransition", "--binary-path", "/usr/local/bin/", "--fuzzcache-path", "/fuzzcache" ]

FROM debian:bookworm-slim as nitro-node-slim
WORKDIR /home/user
Expand Down
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,7 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro
# strategic rules to minimize dependency building

.make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make
go run ./linter/koanf ./...
go run ./linter/pointercheck ./...
go run ./linters ./...
golangci-lint run --fix
yarn --cwd contracts solhint
@touch $@
Expand Down
96 changes: 53 additions & 43 deletions arbnode/batch_poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"github.com/offchainlabs/nitro/cmd/chaininfo"
"github.com/offchainlabs/nitro/cmd/genericconf"
"github.com/offchainlabs/nitro/das"
"github.com/offchainlabs/nitro/execution"
"github.com/offchainlabs/nitro/solgen/go/bridgegen"
"github.com/offchainlabs/nitro/util"
"github.com/offchainlabs/nitro/util/arbmath"
Expand Down Expand Up @@ -73,22 +74,23 @@ type batchPosterPosition struct {

type BatchPoster struct {
stopwaiter.StopWaiter
l1Reader *headerreader.HeaderReader
inbox *InboxTracker
streamer *TransactionStreamer
config BatchPosterConfigFetcher
seqInbox *bridgegen.SequencerInbox
bridge *bridgegen.Bridge
syncMonitor *SyncMonitor
seqInboxABI *abi.ABI
seqInboxAddr common.Address
bridgeAddr common.Address
gasRefunderAddr common.Address
building *buildingBatch
daWriter das.DataAvailabilityServiceWriter
dataPoster *dataposter.DataPoster
redisLock *redislock.Simple
messagesPerBatch *arbmath.MovingAverage[uint64]
l1Reader *headerreader.HeaderReader
inbox *InboxTracker
streamer *TransactionStreamer
arbOSVersionGetter execution.FullExecutionClient
config BatchPosterConfigFetcher
seqInbox *bridgegen.SequencerInbox
bridge *bridgegen.Bridge
syncMonitor *SyncMonitor
seqInboxABI *abi.ABI
seqInboxAddr common.Address
bridgeAddr common.Address
gasRefunderAddr common.Address
building *buildingBatch
daWriter das.DataAvailabilityServiceWriter
dataPoster *dataposter.DataPoster
redisLock *redislock.Simple
messagesPerBatch *arbmath.MovingAverage[uint64]
// This is an atomic variable that should only be accessed atomically.
// An estimate of the number of batches we want to post but haven't yet.
// This doesn't include batches which we don't want to post yet due to the L1 bounds.
Expand Down Expand Up @@ -136,7 +138,7 @@ type BatchPosterConfig struct {
RedisLock redislock.SimpleCfg `koanf:"redis-lock" reload:"hot"`
ExtraBatchGas uint64 `koanf:"extra-batch-gas" reload:"hot"`
Post4844Blobs bool `koanf:"post-4844-blobs" reload:"hot"`
ForcePost4844Blobs bool `koanf:"force-post-4844-blobs" reload:"hot"`
IgnoreBlobPrice bool `koanf:"ignore-blob-price" reload:"hot"`
ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"`
L1BlockBound string `koanf:"l1-block-bound" reload:"hot"`
L1BlockBoundBypass time.Duration `koanf:"l1-block-bound-bypass" reload:"hot"`
Expand Down Expand Up @@ -186,7 +188,7 @@ func BatchPosterConfigAddOptions(prefix string, f *pflag.FlagSet) {
f.String(prefix+".gas-refunder-address", DefaultBatchPosterConfig.GasRefunderAddress, "The gas refunder contract address (optional)")
f.Uint64(prefix+".extra-batch-gas", DefaultBatchPosterConfig.ExtraBatchGas, "use this much more gas than estimation says is necessary to post batches")
f.Bool(prefix+".post-4844-blobs", DefaultBatchPosterConfig.Post4844Blobs, "if the parent chain supports 4844 blobs and they're well priced, post EIP-4844 blobs")
f.Bool(prefix+".force-post-4844-blobs", DefaultBatchPosterConfig.ForcePost4844Blobs, "if the parent chain supports 4844 blobs and post-4844-blobs is true, post 4844 blobs even if it's not price efficient")
f.Bool(prefix+".ignore-blob-price", DefaultBatchPosterConfig.IgnoreBlobPrice, "if the parent chain supports 4844 blobs and ignore-blob-price is true, post 4844 blobs even if it's not price efficient")
f.String(prefix+".redis-url", DefaultBatchPosterConfig.RedisUrl, "if non-empty, the Redis URL to store queued transactions in")
f.String(prefix+".l1-block-bound", DefaultBatchPosterConfig.L1BlockBound, "only post messages to batches when they're within the max future block/timestamp as of this L1 block tag (\"safe\", \"finalized\", \"latest\", or \"ignore\" to ignore this check)")
f.Duration(prefix+".l1-block-bound-bypass", DefaultBatchPosterConfig.L1BlockBoundBypass, "post batches even if not within the layer 1 future bounds if we're within this margin of the max delay")
Expand All @@ -212,7 +214,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{
GasRefunderAddress: "",
ExtraBatchGas: 50_000,
Post4844Blobs: false,
ForcePost4844Blobs: false,
IgnoreBlobPrice: false,
DataPoster: dataposter.DefaultDataPosterConfig,
ParentChainWallet: DefaultBatchPosterL1WalletConfig,
L1BlockBound: "",
Expand Down Expand Up @@ -242,7 +244,7 @@ var TestBatchPosterConfig = BatchPosterConfig{
GasRefunderAddress: "",
ExtraBatchGas: 10_000,
Post4844Blobs: true,
ForcePost4844Blobs: false,
IgnoreBlobPrice: false,
DataPoster: dataposter.TestDataPosterConfig,
ParentChainWallet: DefaultBatchPosterL1WalletConfig,
L1BlockBound: "",
Expand All @@ -255,6 +257,7 @@ type BatchPosterOpts struct {
L1Reader *headerreader.HeaderReader
Inbox *InboxTracker
Streamer *TransactionStreamer
VersionGetter execution.FullExecutionClient
SyncMonitor *SyncMonitor
Config BatchPosterConfigFetcher
DeployInfo *chaininfo.RollupAddresses
Expand Down Expand Up @@ -293,19 +296,20 @@ func NewBatchPoster(ctx context.Context, opts *BatchPosterOpts) (*BatchPoster, e
return nil, err
}
b := &BatchPoster{
l1Reader: opts.L1Reader,
inbox: opts.Inbox,
streamer: opts.Streamer,
syncMonitor: opts.SyncMonitor,
config: opts.Config,
bridge: bridge,
seqInbox: seqInbox,
seqInboxABI: seqInboxABI,
seqInboxAddr: opts.DeployInfo.SequencerInbox,
gasRefunderAddr: opts.Config().gasRefunder,
bridgeAddr: opts.DeployInfo.Bridge,
daWriter: opts.DAWriter,
redisLock: redisLock,
l1Reader: opts.L1Reader,
inbox: opts.Inbox,
streamer: opts.Streamer,
arbOSVersionGetter: opts.VersionGetter,
syncMonitor: opts.SyncMonitor,
config: opts.Config,
bridge: bridge,
seqInbox: seqInbox,
seqInboxABI: seqInboxABI,
seqInboxAddr: opts.DeployInfo.SequencerInbox,
gasRefunderAddr: opts.Config().gasRefunder,
bridgeAddr: opts.DeployInfo.Bridge,
daWriter: opts.DAWriter,
redisLock: redisLock,
}
b.messagesPerBatch, err = arbmath.NewMovingAverage[uint64](20)
if err != nil {
Expand Down Expand Up @@ -947,7 +951,6 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error)
if dbBatchCount > batchPosition.NextSeqNum {
return false, fmt.Errorf("attempting to post batch %v, but the local inbox tracker database already has %v batches", batchPosition.NextSeqNum, dbBatchCount)
}

if b.building == nil || b.building.startMsgCount != batchPosition.MessageCount {
latestHeader, err := b.l1Reader.LastHeader(ctx)
if err != nil {
Expand All @@ -956,17 +959,24 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error)
var use4844 bool
config := b.config()
if config.Post4844Blobs && latestHeader.ExcessBlobGas != nil && latestHeader.BlobGasUsed != nil {
if config.ForcePost4844Blobs {
use4844 = true
} else {
blobFeePerByte := eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed))
blobFeePerByte.Mul(blobFeePerByte, blobTxBlobGasPerBlob)
blobFeePerByte.Div(blobFeePerByte, usableBytesInBlob)

calldataFeePerByte := arbmath.BigMulByUint(latestHeader.BaseFee, 16)
use4844 = arbmath.BigLessThan(blobFeePerByte, calldataFeePerByte)
arbOSVersion, err := b.arbOSVersionGetter.ArbOSVersionForMessageNumber(arbutil.MessageIndex(arbmath.SaturatingUSub(uint64(batchPosition.MessageCount), 1)))
if err != nil {
return false, err
}
if arbOSVersion >= 20 {
if config.IgnoreBlobPrice {
use4844 = true
} else {
blobFeePerByte := eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*latestHeader.ExcessBlobGas, *latestHeader.BlobGasUsed))
blobFeePerByte.Mul(blobFeePerByte, blobTxBlobGasPerBlob)
blobFeePerByte.Div(blobFeePerByte, usableBytesInBlob)

calldataFeePerByte := arbmath.BigMulByUint(latestHeader.BaseFee, 16)
use4844 = arbmath.BigLessThan(blobFeePerByte, calldataFeePerByte)
}
}
}

b.building = &buildingBatch{
segments: newBatchSegments(batchPosition.DelayedMessageCount, b.config(), b.GetBacklogEstimate(), use4844),
msgCount: batchPosition.MessageCount,
Expand Down
45 changes: 38 additions & 7 deletions arbnode/delayed.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import (
"bytes"
"context"
"errors"
"fmt"
"math/big"
"sort"

"github.com/ethereum/go-ethereum"
"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"
Expand All @@ -28,13 +30,15 @@ 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()
if err != nil {
panic(err)
}
messageDeliveredID = parsedIBridgeABI.Events["MessageDelivered"].ID
delayedInboxAccsCallABI = parsedIBridgeABI.Methods["delayedInboxAccs"]

parsedIMessageProviderABI, err := bridgegen.IDelayedMessageProviderMetaData.GetAbi()
if err != nil {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -190,10 +221,10 @@ func (b *DelayedBridge) logsToDeliveredMessages(ctx context.Context, logs []type
msgKey := common.BigToHash(parsedLog.MessageIndex)
data, ok := messageData[msgKey]
if !ok {
return nil, errors.New("message not found")
return nil, fmt.Errorf("message %v data not found", parsedLog.MessageIndex)
}
if crypto.Keccak256Hash(data) != parsedLog.MessageDataHash {
return nil, errors.New("found message data with mismatched hash")
return nil, fmt.Errorf("found message %v data with mismatched hash", parsedLog.MessageIndex)
}

requestId := common.BigToHash(parsedLog.MessageIndex)
Expand Down
10 changes: 7 additions & 3 deletions arbnode/delayed_sequencer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
Expand Down
Loading

0 comments on commit 59876e0

Please sign in to comment.