Skip to content

Commit

Permalink
Merge pull request #2164 from OffchainLabs/data-poster-blob-rbf
Browse files Browse the repository at this point in the history
Properly support replace by fee for blob txs
  • Loading branch information
PlasmaPower authored Mar 1, 2024
2 parents 7bc9a6e + 1891599 commit f10123b
Show file tree
Hide file tree
Showing 9 changed files with 382 additions and 145 deletions.
2 changes: 1 addition & 1 deletion arbnode/batch_poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{
// This default is overridden for L3 chains in applyChainParameters in cmd/nitro/nitro.go
MaxSize: 100000,
// TODO: is 1000 bytes an appropriate margin for error vs blob space efficiency?
Max4844BatchSize: (254 * params.BlobTxFieldElementsPerBlob / 8 * (params.MaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob)) - 1000,
Max4844BatchSize: blobs.BlobEncodableData*(params.MaxBlobGasPerBlock/params.BlobTxBlobGasPerBlob) - 1000,
PollInterval: time.Second * 10,
ErrorDelay: time.Second * 10,
MaxDelay: time.Hour,
Expand Down
430 changes: 304 additions & 126 deletions arbnode/dataposter/data_poster.go

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions arbnode/dataposter/dbstorage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ func (s *Storage) FetchContents(_ context.Context, startingIndex uint64, maxResu
return res, it.Error()
}

func (s *Storage) Get(_ context.Context, index uint64) (*storage.QueuedTransaction, error) {
key := idxToKey(index)
value, err := s.db.Get(key)
if err != nil {
if errors.Is(err, leveldb.ErrNotFound) {
return nil, nil
}
return nil, err
}
return s.encDec().Decode(value)
}

func (s *Storage) lastItemIdx(context.Context) ([]byte, error) {
return s.db.Get(lastItemIdxKey)
}
Expand Down
4 changes: 4 additions & 0 deletions arbnode/dataposter/noop/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ func (s *Storage) FetchContents(_ context.Context, _, _ uint64) ([]*storage.Queu
return nil, nil
}

func (s *Storage) Get(_ context.Context, _ uint64) (*storage.QueuedTransaction, error) {
return nil, nil
}

func (s *Storage) FetchLast(ctx context.Context) (*storage.QueuedTransaction, error) {
return nil, nil
}
Expand Down
14 changes: 14 additions & 0 deletions arbnode/dataposter/redis/redisstorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,20 @@ func (s *Storage) FetchContents(ctx context.Context, startingIndex uint64, maxRe
return items, nil
}

func (s *Storage) Get(ctx context.Context, index uint64) (*storage.QueuedTransaction, error) {
contents, err := s.FetchContents(ctx, index, 1)
if err != nil {
return nil, err
}
if len(contents) == 0 {
return nil, nil
} else if len(contents) == 1 {
return contents[0], nil
} else {
return nil, fmt.Errorf("expected only one return value for Get but got %v", len(contents))
}
}

func (s *Storage) FetchLast(ctx context.Context) (*storage.QueuedTransaction, error) {
query := redis.ZRangeArgs{
Key: s.key,
Expand Down
7 changes: 7 additions & 0 deletions arbnode/dataposter/slice/slicestorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ func (s *Storage) FetchContents(_ context.Context, startingIndex uint64, maxResu
return res, nil
}

func (s *Storage) Get(_ context.Context, index uint64) (*storage.QueuedTransaction, error) {
if index >= s.firstNonce+uint64(len(s.queue)) || index < s.firstNonce {
return nil, nil
}
return s.encDec().Decode(s.queue[index-s.firstNonce])
}

func (s *Storage) FetchLast(context.Context) (*storage.QueuedTransaction, error) {
if len(s.queue) == 0 {
return nil, nil
Expand Down
48 changes: 30 additions & 18 deletions arbnode/dataposter/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,42 @@ var (
)

type QueuedTransaction struct {
FullTx *types.Transaction
DeprecatedData types.DynamicFeeTx // FullTx should be used instead
Meta []byte
Sent bool
Created time.Time // may be earlier than the tx was given to the tx poster
NextReplacement time.Time
FullTx *types.Transaction
DeprecatedData types.DynamicFeeTx // FullTx should be used instead
Meta []byte
Sent bool
Created time.Time // may be earlier than the tx was given to the tx poster
NextReplacement time.Time
StoredCumulativeWeight *uint64
}

// CumulativeWeight returns a rough estimate of the total number of batches submitted at this point, not guaranteed to be exact
func (t *QueuedTransaction) CumulativeWeight() uint64 {
if t.StoredCumulativeWeight != nil {
return *t.StoredCumulativeWeight
}
return t.FullTx.Nonce()
}

type queuedTransactionForEncoding struct {
FullTx *types.Transaction
Data types.DynamicFeeTx
Meta []byte
Sent bool
Created RlpTime
NextReplacement RlpTime
FullTx *types.Transaction
Data types.DynamicFeeTx
Meta []byte
Sent bool
Created RlpTime
NextReplacement RlpTime
StoredCumulativeWeight *uint64 `rlp:"optional"`
}

func (qt *QueuedTransaction) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, queuedTransactionForEncoding{
FullTx: qt.FullTx,
Data: qt.DeprecatedData,
Meta: qt.Meta,
Sent: qt.Sent,
Created: (RlpTime)(qt.Created),
NextReplacement: (RlpTime)(qt.NextReplacement),
FullTx: qt.FullTx,
Data: qt.DeprecatedData,
Meta: qt.Meta,
Sent: qt.Sent,
Created: (RlpTime)(qt.Created),
NextReplacement: (RlpTime)(qt.NextReplacement),
StoredCumulativeWeight: qt.StoredCumulativeWeight,
})
}

Expand All @@ -65,6 +76,7 @@ func (qt *QueuedTransaction) DecodeRLP(s *rlp.Stream) error {
qt.Sent = qtEnc.Sent
qt.Created = time.Time(qtEnc.Created)
qt.NextReplacement = time.Time(qtEnc.NextReplacement)
qt.StoredCumulativeWeight = qtEnc.StoredCumulativeWeight
return nil
}

Expand Down
7 changes: 7 additions & 0 deletions util/arbmath/bips.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,10 @@ func UintMulByBips(value uint64, bips Bips) uint64 {
func SaturatingCastToBips(value uint64) Bips {
return Bips(SaturatingCast(value))
}

// BigDivToBips returns dividend/divisor as bips, saturating if out of bounds
func BigDivToBips(dividend, divisor *big.Int) Bips {
value := BigMulByInt(dividend, int64(OneInBips))
value.Div(value, divisor)
return Bips(BigToUintSaturating(value))
}
3 changes: 3 additions & 0 deletions util/blobs/blobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ func fillBlobBytes(blob []byte, data []byte) []byte {
// The number of bits in a BLS scalar that aren't part of a whole byte.
const spareBlobBits = 6 // = math.floor(math.log2(BLS_MODULUS)) % 8

// The number of bytes encodable in a blob with the current encoding scheme.
const BlobEncodableData = 254 * params.BlobTxFieldElementsPerBlob / 8

func fillBlobBits(blob []byte, data []byte) ([]byte, error) {
var acc uint16
accBits := 0
Expand Down

0 comments on commit f10123b

Please sign in to comment.