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

EigenDA Proxy + Historical Nitro Changes #11

Closed
wants to merge 18 commits into from
Closed
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
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "go-ethereum"]
path = go-ethereum
url = https://github.com/OffchainLabs/go-ethereum.git
url = git@github.com:Layr-Labs/nitro-go-ethereum-private.git
[submodule "fastcache"]
path = fastcache
url = https://github.com/OffchainLabs/fastcache.git
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ COPY ./blsSignatures ./blsSignatures
COPY ./cmd/chaininfo ./cmd/chaininfo
COPY ./cmd/replay ./cmd/replay
COPY ./das/dastree ./das/dastree
COPY ./das/eigenda ./das/eigenda
COPY ./eigenda ./eigenda
COPY ./precompiles ./precompiles
COPY ./statetransfer ./statetransfer
COPY ./util ./util
Expand Down
81 changes: 66 additions & 15 deletions arbnode/batch_poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import (
"github.com/offchainlabs/nitro/cmd/chaininfo"
"github.com/offchainlabs/nitro/cmd/genericconf"
"github.com/offchainlabs/nitro/das"
"github.com/offchainlabs/nitro/das/eigenda"
"github.com/offchainlabs/nitro/eigenda"
"github.com/offchainlabs/nitro/execution"
"github.com/offchainlabs/nitro/solgen/go/bridgegen"
"github.com/offchainlabs/nitro/util"
Expand All @@ -64,8 +64,9 @@ var (
const (
batchPosterSimpleRedisLockKey = "node.batch-poster.redis-lock.simple-lock-key"

sequencerBatchPostMethodName = "addSequencerL2BatchFromOrigin0"
sequencerBatchPostWithBlobsMethodName = "addSequencerL2BatchFromBlobs"
sequencerBatchPostMethodName = "addSequencerL2BatchFromOrigin0"
sequencerBatchPostWithBlobsMethodName = "addSequencerL2BatchFromBlobs"
sequencerBatchPostWithEigendaMethodName = "addSequencerL2BatchFromEigenDA"
)

type batchPosterPosition struct {
Expand Down Expand Up @@ -143,6 +144,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"`
PostEigenDA bool `koanf:"post-eigen-da" 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"`
Expand Down Expand Up @@ -194,6 +196,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+".post-eigen-da", DefaultBatchPosterConfig.PostEigenDA, "Post data to EigenDA")
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)")
Expand Down Expand Up @@ -221,6 +224,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{
GasRefunderAddress: "",
ExtraBatchGas: 50_000,
Post4844Blobs: false,
PostEigenDA: false,
IgnoreBlobPrice: false,
DataPoster: dataposter.DefaultDataPosterConfig,
ParentChainWallet: DefaultBatchPosterL1WalletConfig,
Expand Down Expand Up @@ -252,6 +256,30 @@ var TestBatchPosterConfig = BatchPosterConfig{
GasRefunderAddress: "",
ExtraBatchGas: 10_000,
Post4844Blobs: true,
PostEigenDA: false,
IgnoreBlobPrice: false,
DataPoster: dataposter.TestDataPosterConfig,
ParentChainWallet: DefaultBatchPosterL1WalletConfig,
L1BlockBound: "",
L1BlockBoundBypass: time.Hour,
UseAccessLists: true,
GasEstimateBaseFeeMultipleBips: arbmath.OneInBips * 3 / 2,
}

var EigenDABatchPosterConfig = BatchPosterConfig{
Enable: true,
MaxSize: 100000,
Max4844BatchSize: DefaultBatchPosterConfig.Max4844BatchSize,
PollInterval: time.Millisecond * 10,
ErrorDelay: time.Millisecond * 10,
MaxDelay: 0,
WaitForMaxDelay: false,
CompressionLevel: 2,
DASRetentionPeriod: time.Hour * 24 * 15,
GasRefunderAddress: "",
ExtraBatchGas: 10_000,
Post4844Blobs: false,
PostEigenDA: true,
IgnoreBlobPrice: false,
DataPoster: dataposter.TestDataPosterConfig,
ParentChainWallet: DefaultBatchPosterL1WalletConfig,
Expand Down Expand Up @@ -611,6 +639,7 @@ type buildingBatch struct {
msgCount arbutil.MessageIndex
haveUsefulMessage bool
use4844 bool
useEigenDA bool
}

func newBatchSegments(firstDelayed uint64, config *BatchPosterConfig, backlog uint64, use4844 bool) *batchSegments {
Expand Down Expand Up @@ -847,11 +876,16 @@ func (b *BatchPoster) encodeAddBatch(
l2MessageData []byte,
delayedMsg uint64,
use4844 bool,
useEigenDA bool,
eigenDaBlobInfo *eigenda.EigenDABlobInfo,
) ([]byte, []kzg4844.Blob, error) {
methodName := sequencerBatchPostMethodName
if use4844 {
methodName = sequencerBatchPostWithBlobsMethodName
}
if useEigenDA {
methodName = sequencerBatchPostWithEigendaMethodName
}
Comment on lines 883 to +888
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

knit - could be useful enforce that use488 and useEigenDA are never both true

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are cases where we would want both flags to be true to be able to specify between using 4844 as fallback or calldata imo

method, ok := b.seqInboxABI.Methods[methodName]
if !ok {
return nil, nil, errors.New("failed to find add batch method")
Expand All @@ -872,6 +906,17 @@ func (b *BatchPoster) encodeAddBatch(
new(big.Int).SetUint64(uint64(prevMsgNum)),
new(big.Int).SetUint64(uint64(newMsgNum)),
)
} else if useEigenDA {
calldata, err = method.Inputs.Pack(
seqNum,
eigenDaBlobInfo.BlobVerificationProof,
eigenDaBlobInfo.BlobHeader,
new(big.Int).SetUint64(delayedMsg),
b.config().gasRefunder,
new(big.Int).SetUint64(uint64(prevMsgNum)),
new(big.Int).SetUint64(uint64(newMsgNum)),
)

} else {
calldata, err = method.Inputs.Pack(
seqNum,
Expand Down Expand Up @@ -907,7 +952,7 @@ func estimateGas(client rpc.ClientInterface, ctx context.Context, params estimat
return uint64(gas), err
}

func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, delayedMessages uint64, realData []byte, realBlobs []kzg4844.Blob, realNonce uint64, realAccessList types.AccessList) (uint64, error) {
func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte, delayedMessages uint64, realData []byte, realBlobs []kzg4844.Blob, realNonce uint64, realAccessList types.AccessList, eigenDaBlobInfo *eigenda.EigenDABlobInfo) (uint64, error) {
config := b.config()
rpcClient := b.l1Reader.Client()
rawRpcClient := rpcClient.Client()
Expand Down Expand Up @@ -949,7 +994,7 @@ func (b *BatchPoster) estimateGas(ctx context.Context, sequencerMessage []byte,
// However, we set nextMsgNum to 1 because it is necessary for a correct estimation for the final to be non-zero.
// Because we're likely estimating against older state, this might not be the actual next message,
// but the gas used should be the same.
data, kzgBlobs, err := b.encodeAddBatch(abi.MaxUint256, 0, 1, sequencerMessage, delayedMessages, len(realBlobs) > 0)
data, kzgBlobs, err := b.encodeAddBatch(abi.MaxUint256, 0, 1, sequencerMessage, delayedMessages, len(realBlobs) > 0, eigenDaBlobInfo != nil, eigenDaBlobInfo)
if err != nil {
return 0, err
}
Expand Down Expand Up @@ -1044,11 +1089,17 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error)
}
}

var useEigenDA bool
if b.eigenDAWriter != nil {
useEigenDA = true
}

b.building = &buildingBatch{
segments: newBatchSegments(batchPosition.DelayedMessageCount, b.config(), b.GetBacklogEstimate(), use4844),
msgCount: batchPosition.MessageCount,
startMsgCount: batchPosition.MessageCount,
use4844: use4844,
useEigenDA: useEigenDA,
}
}
msgCount, err := b.streamer.GetMessageCount()
Expand Down Expand Up @@ -1224,26 +1275,25 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error)
}
}

var blobInfo *eigenda.EigenDABlobInfo
if b.daWriter == nil && b.eigenDAWriter != nil {
log.Info("Start to write data to eigenda: ", "data", hex.EncodeToString(sequencerMsg))
daRef, err := b.eigenDAWriter.Store(ctx, sequencerMsg)
blobInfo, err = b.eigenDAWriter.Store(ctx, sequencerMsg)
if err != nil {
if config.DisableEigenDAFallbackStoreDataOnChain {
log.Warn("Falling back to storing data on chain", "err", err)
return false, errors.New("unable to post batch to EigenDA and fallback storing data on chain is disabled")
}
}

pointer, err := b.eigenDAWriter.Serialize(daRef)
if err != nil {
log.Warn("DaRef serialization failed", "err", err)
return false, errors.New("DaRef serialization failed")
}
log.Info("EigenDA transaction receipt(data pointer): ", "hash", hex.EncodeToString(daRef.BatchHeaderHash), "index", daRef.BlobIndex)
sequencerMsg = pointer
// sequencerMsg, err = b.eigenDAWriter.Serialize(blobInfo)
// if err != nil {
// log.Warn("DaRef serialization failed", "err", err)
// return false, errors.New("DaRef serialization failed")
// }
}

data, kzgBlobs, err := b.encodeAddBatch(new(big.Int).SetUint64(batchPosition.NextSeqNum), batchPosition.MessageCount, b.building.msgCount, sequencerMsg, b.building.segments.delayedMsg, b.building.use4844)
data, kzgBlobs, err := b.encodeAddBatch(new(big.Int).SetUint64(batchPosition.NextSeqNum), batchPosition.MessageCount, b.building.msgCount, sequencerMsg, b.building.segments.delayedMsg, b.building.use4844, b.building.useEigenDA, blobInfo)
if err != nil {
return false, err
}
Expand All @@ -1258,7 +1308,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error)
// In theory, this might reduce gas usage, but only by a factor that's already
// accounted for in `config.ExtraBatchGas`, as that same factor can appear if a user
// posts a new delayed message that we didn't see while gas estimating.
gasLimit, err := b.estimateGas(ctx, sequencerMsg, lastPotentialMsg.DelayedMessagesRead, data, kzgBlobs, nonce, accessList)
gasLimit, err := b.estimateGas(ctx, sequencerMsg, lastPotentialMsg.DelayedMessagesRead, data, kzgBlobs, nonce, accessList, blobInfo)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -1286,6 +1336,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error)
}
log.Info(
"BatchPoster: batch sent",
"eigenDA", b.building.useEigenDA,
"sequenceNumber", batchPosition.NextSeqNum,
"from", batchPosition.MessageCount,
"to", b.building.msgCount,
Expand Down
8 changes: 6 additions & 2 deletions arbnode/inbox_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"github.com/offchainlabs/nitro/arbutil"
"github.com/offchainlabs/nitro/broadcaster"
m "github.com/offchainlabs/nitro/broadcaster/message"
"github.com/offchainlabs/nitro/das/eigenda"
"github.com/offchainlabs/nitro/eigenda"
"github.com/offchainlabs/nitro/staker"
"github.com/offchainlabs/nitro/util/containers"
)
Expand Down Expand Up @@ -616,8 +616,12 @@ func (t *InboxTracker) AddSequencerBatches(ctx context.Context, client arbutil.L
if t.blobReader != nil {
daProviders = append(daProviders, arbstate.NewDAProviderBlobReader(t.blobReader))
}
multiplexer := arbstate.NewInboxMultiplexer(backend, prevbatchmeta.DelayedMessageCount, daProviders, t.eigenDA, arbstate.KeysetValidate)
if t.eigenDA != nil {
daProviders = append(daProviders, arbstate.NewDAProviderEigenDA(t.eigenDA))
}
multiplexer := arbstate.NewInboxMultiplexer(backend, prevbatchmeta.DelayedMessageCount, daProviders, arbstate.KeysetValidate)
batchMessageCounts := make(map[uint64]arbutil.MessageIndex)

currentpos := prevbatchmeta.MessageCount + 1
for {
if len(backend.batches) == 0 {
Expand Down
4 changes: 3 additions & 1 deletion arbnode/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
"github.com/offchainlabs/nitro/broadcaster"
"github.com/offchainlabs/nitro/cmd/chaininfo"
"github.com/offchainlabs/nitro/das"
"github.com/offchainlabs/nitro/das/eigenda"
"github.com/offchainlabs/nitro/eigenda"
"github.com/offchainlabs/nitro/execution"
"github.com/offchainlabs/nitro/execution/gethexec"
"github.com/offchainlabs/nitro/solgen/go/bridgegen"
Expand Down Expand Up @@ -546,6 +546,8 @@ func createNodeImpl(
eigenDAWriter = eigenDAService
}

log.Info("EigenDA reader", "reader", eigenDAReader)

inboxTracker, err := NewInboxTracker(arbDb, txStreamer, daReader, blobReader, eigenDAReader)
if err != nil {
return nil, err
Expand Down
59 changes: 36 additions & 23 deletions arbstate/inbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"github.com/offchainlabs/nitro/arbos/l1pricing"
"github.com/offchainlabs/nitro/arbutil"
"github.com/offchainlabs/nitro/das/dastree"
"github.com/offchainlabs/nitro/das/eigenda"
"github.com/offchainlabs/nitro/eigenda"
"github.com/offchainlabs/nitro/util/blobs"
"github.com/offchainlabs/nitro/zeroheavy"
)
Expand Down Expand Up @@ -70,7 +70,7 @@ var (
ErrInvalidBlobDataFormat = errors.New("blob batch data is not a list of hashes as expected")
)

func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash common.Hash, data []byte, daProviders []DataAvailabilityProvider, eigenDAReader eigenda.EigenDAReader, keysetValidationMode KeysetValidationMode) (*sequencerMessage, error) {
func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash common.Hash, data []byte, daProviders []DataAvailabilityProvider, keysetValidationMode KeysetValidationMode) (*sequencerMessage, error) {
if len(data) < 40 {
return nil, errors.New("sequencer message missing L1 header")
}
Expand All @@ -84,6 +84,7 @@ func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash
}
payload := data[40:]
log.Info("Inbox parse sequencer message: ", "payload", hex.EncodeToString(payload))
log.Info("Inbox parse header message: ", "header", hex.EncodeToString(data[:40]))

// Stage 0: Check if our node is out of date and we don't understand this batch type
// If the parent chain sequencer inbox smart contract authenticated this batch,
Expand All @@ -101,23 +102,6 @@ func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash
foundDA := false
var err error

// detect eigenda message from byte
if eigenda.IsEigenDAMessageHeaderByte(payload[0]) {
if eigenDAReader == nil {
log.Error("No EigenDA Reader configured, but sequencer message found with EigenDA header")
} else {
var err error
payload, err = eigenda.RecoverPayloadFromEigenDABatch(ctx, payload[1:], eigenDAReader, nil)
if err != nil {
return nil, err
}
if payload == nil {
return parsedMsg, nil
}
foundDA = true
}
}

for _, provider := range daProviders {
if provider != nil && provider.IsValidHeaderByte(payload[0]) {
payload, err = provider.RecoverPayloadFromBatch(ctx, batchNum, batchBlockHash, data, nil, keysetValidationMode)
Expand All @@ -137,6 +121,8 @@ func parseSequencerMessage(ctx context.Context, batchNum uint64, batchBlockHash
log.Error("No DAS Reader configured, but sequencer message found with DAS header")
} else if IsBlobHashesHeaderByte(payload[0]) {
return nil, ErrNoBlobReader
} else if eigenda.IsEigenDAMessageHeaderByte(payload[0]) {
log.Error("eigenDA versioned batch payload was encountered but no instance of EigenDA was configured")
}
}
}
Expand Down Expand Up @@ -385,6 +371,35 @@ func (b *dAProviderForBlobReader) RecoverPayloadFromBatch(
return payload, nil
}

// NewDAProviderEigenDA is generally meant to be only used by nitro.
// DA Providers should implement methods in the DataAvailabilityProvider interface independently
func NewDAProviderEigenDA(eigenDAReader eigenda.EigenDAReader) *daProviderForEigenDA {
return &daProviderForEigenDA{
eigenDAReader: eigenDAReader,
}
}

type daProviderForEigenDA struct {
eigenDAReader eigenda.EigenDAReader
}

func (e *daProviderForEigenDA) IsValidHeaderByte(headerByte byte) bool {
return eigenda.IsEigenDAMessageHeaderByte(headerByte)
}

func (e *daProviderForEigenDA) RecoverPayloadFromBatch(
ctx context.Context,
batchNum uint64,
batchBlockHash common.Hash,
sequencerMsg []byte,
preimages map[arbutil.PreimageType]map[common.Hash][]byte,
keysetValidationMode KeysetValidationMode,
) ([]byte, error) {
// we start from the 41st byte of sequencerMsg because bytes 0 - 40 are the header, and 40 - 41 is the eigenDA header flag
// we use the binary domain here because this is what we use in the derivation pipeline
return eigenda.RecoverPayloadFromEigenDABatch(ctx, sequencerMsg[41:], e.eigenDAReader, preimages, "binary")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Knit - domain could be enum

}

type KeysetValidationMode uint8

const KeysetValidate KeysetValidationMode = 0
Expand All @@ -395,7 +410,6 @@ type inboxMultiplexer struct {
backend InboxBackend
delayedMessagesRead uint64
daProviders []DataAvailabilityProvider
eigenDAReader eigenda.EigenDAReader
cachedSequencerMessage *sequencerMessage
cachedSequencerMessageNum uint64
cachedSegmentNum uint64
Expand All @@ -405,12 +419,11 @@ type inboxMultiplexer struct {
keysetValidationMode KeysetValidationMode
}

func NewInboxMultiplexer(backend InboxBackend, delayedMessagesRead uint64, daProviders []DataAvailabilityProvider, eigenDAReader eigenda.EigenDAReader, keysetValidationMode KeysetValidationMode) arbostypes.InboxMultiplexer {
func NewInboxMultiplexer(backend InboxBackend, delayedMessagesRead uint64, daProviders []DataAvailabilityProvider, keysetValidationMode KeysetValidationMode) arbostypes.InboxMultiplexer {
return &inboxMultiplexer{
backend: backend,
delayedMessagesRead: delayedMessagesRead,
daProviders: daProviders,
eigenDAReader: eigenDAReader,
keysetValidationMode: keysetValidationMode,
}
}
Expand All @@ -432,7 +445,7 @@ func (r *inboxMultiplexer) Pop(ctx context.Context) (*arbostypes.MessageWithMeta
}
r.cachedSequencerMessageNum = r.backend.GetSequencerInboxPosition()
var err error
r.cachedSequencerMessage, err = parseSequencerMessage(ctx, r.cachedSequencerMessageNum, batchBlockHash, bytes, r.daProviders, r.eigenDAReader, r.keysetValidationMode)
r.cachedSequencerMessage, err = parseSequencerMessage(ctx, r.cachedSequencerMessageNum, batchBlockHash, bytes, r.daProviders, r.keysetValidationMode)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion arbstate/inbox_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func FuzzInboxMultiplexer(f *testing.F) {
delayedMessage: delayedMsg,
positionWithinMessage: 0,
}
multiplexer := NewInboxMultiplexer(backend, 0, nil, nil, KeysetValidate)
multiplexer := NewInboxMultiplexer(backend, 0, nil, KeysetValidate)
_, err := multiplexer.Pop(context.TODO())
if err != nil {
panic(err)
Expand Down
Loading
Loading