From ef7f8da2438091ff3e18449362665e9c6437f600 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Wed, 19 Jun 2024 14:22:37 -0300 Subject: [PATCH 01/13] Moves L1PriceData, L1PriceDataOfMsg, BacklogCallDataUnits, BacklogL1GasCharged, and CacheL1PriceDataOfMsg from TransactionStreamer to ExecutionEngine --- arbnode/node.go | 11 --- arbnode/transaction_streamer.go | 120 +----------------------- execution/gethexec/executionengine.go | 126 ++++++++++++++++++++++++-- execution/gethexec/node.go | 6 +- execution/gethexec/sequencer.go | 4 +- execution/interface.go | 6 +- 6 files changed, 128 insertions(+), 145 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 5592574823..1fae09c108 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -792,17 +792,6 @@ func CreateNode( return currentNode, nil } -func (n *Node) CacheL1PriceDataOfMsg(pos arbutil.MessageIndex, callDataUnits uint64, l1GasCharged uint64) { - n.TxStreamer.CacheL1PriceDataOfMsg(pos, callDataUnits, l1GasCharged) -} - -func (n *Node) BacklogL1GasCharged() uint64 { - return n.TxStreamer.BacklogL1GasCharged() -} -func (n *Node) BacklogCallDataUnits() uint64 { - return n.TxStreamer.BacklogCallDataUnits() -} - func (n *Node) Start(ctx context.Context) error { execClient, ok := n.Execution.(*gethexec.ExecutionNode) if !ok { diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index c948bd8169..f2c19fe9ce 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -69,9 +69,6 @@ type TransactionStreamer struct { broadcastServer *broadcaster.Broadcaster inboxReader *InboxReader delayedBridge *DelayedBridge - - cachedL1PriceDataMutex sync.RWMutex - cachedL1PriceData *L1PriceData } type TransactionStreamerConfig struct { @@ -118,9 +115,6 @@ func NewTransactionStreamer( fatalErrChan: fatalErrChan, config: config, snapSyncConfig: snapSyncConfig, - cachedL1PriceData: &L1PriceData{ - msgToL1PriceData: []L1PriceDataOfMsg{}, - }, } err := streamer.cleanupInconsistentState() if err != nil { @@ -129,20 +123,6 @@ func NewTransactionStreamer( return streamer, nil } -type L1PriceDataOfMsg struct { - callDataUnits uint64 - cummulativeCallDataUnits uint64 - l1GasCharged uint64 - cummulativeL1GasCharged uint64 -} - -type L1PriceData struct { - startOfL1PriceDataCache arbutil.MessageIndex - endOfL1PriceDataCache arbutil.MessageIndex - msgToL1PriceData []L1PriceDataOfMsg - currentEstimateOfL1GasPrice uint64 -} - // Represents a block's hash in the database. // Necessary because RLP decoder doesn't produce nil values by default. type blockHashDBValue struct { @@ -154,103 +134,7 @@ const ( ) func (s *TransactionStreamer) CurrentEstimateOfL1GasPrice() uint64 { - s.cachedL1PriceDataMutex.Lock() - defer s.cachedL1PriceDataMutex.Unlock() - - currentEstimate, err := s.exec.GetL1GasPriceEstimate() - if err != nil { - log.Error("error fetching current L2 estimate of L1 gas price hence reusing cached estimate", "err", err) - } else { - s.cachedL1PriceData.currentEstimateOfL1GasPrice = currentEstimate - } - return s.cachedL1PriceData.currentEstimateOfL1GasPrice -} - -func (s *TransactionStreamer) BacklogCallDataUnits() uint64 { - s.cachedL1PriceDataMutex.RLock() - defer s.cachedL1PriceDataMutex.RUnlock() - - size := len(s.cachedL1PriceData.msgToL1PriceData) - if size == 0 { - return 0 - } - return (s.cachedL1PriceData.msgToL1PriceData[size-1].cummulativeCallDataUnits - - s.cachedL1PriceData.msgToL1PriceData[0].cummulativeCallDataUnits + - s.cachedL1PriceData.msgToL1PriceData[0].callDataUnits) -} - -func (s *TransactionStreamer) BacklogL1GasCharged() uint64 { - s.cachedL1PriceDataMutex.RLock() - defer s.cachedL1PriceDataMutex.RUnlock() - - size := len(s.cachedL1PriceData.msgToL1PriceData) - if size == 0 { - return 0 - } - return (s.cachedL1PriceData.msgToL1PriceData[size-1].cummulativeL1GasCharged - - s.cachedL1PriceData.msgToL1PriceData[0].cummulativeL1GasCharged + - s.cachedL1PriceData.msgToL1PriceData[0].l1GasCharged) -} - -func (s *TransactionStreamer) TrimCache(to arbutil.MessageIndex) { - s.cachedL1PriceDataMutex.Lock() - defer s.cachedL1PriceDataMutex.Unlock() - - if to < s.cachedL1PriceData.startOfL1PriceDataCache { - log.Info("trying to trim older cache which doesnt exist anymore") - } else if to >= s.cachedL1PriceData.endOfL1PriceDataCache { - s.cachedL1PriceData.startOfL1PriceDataCache = 0 - s.cachedL1PriceData.endOfL1PriceDataCache = 0 - s.cachedL1PriceData.msgToL1PriceData = []L1PriceDataOfMsg{} - } else { - newStart := to - s.cachedL1PriceData.startOfL1PriceDataCache + 1 - s.cachedL1PriceData.msgToL1PriceData = s.cachedL1PriceData.msgToL1PriceData[newStart:] - s.cachedL1PriceData.startOfL1PriceDataCache = to + 1 - } -} - -func (s *TransactionStreamer) CacheL1PriceDataOfMsg(seqNum arbutil.MessageIndex, callDataUnits uint64, l1GasCharged uint64) { - s.cachedL1PriceDataMutex.Lock() - defer s.cachedL1PriceDataMutex.Unlock() - - resetCache := func() { - s.cachedL1PriceData.startOfL1PriceDataCache = seqNum - s.cachedL1PriceData.endOfL1PriceDataCache = seqNum - s.cachedL1PriceData.msgToL1PriceData = []L1PriceDataOfMsg{{ - callDataUnits: callDataUnits, - cummulativeCallDataUnits: callDataUnits, - l1GasCharged: l1GasCharged, - cummulativeL1GasCharged: l1GasCharged, - }} - } - size := len(s.cachedL1PriceData.msgToL1PriceData) - if size == 0 || - s.cachedL1PriceData.startOfL1PriceDataCache == 0 || - s.cachedL1PriceData.endOfL1PriceDataCache == 0 || - arbutil.MessageIndex(size) != s.cachedL1PriceData.endOfL1PriceDataCache-s.cachedL1PriceData.startOfL1PriceDataCache+1 { - resetCache() - return - } - if seqNum != s.cachedL1PriceData.endOfL1PriceDataCache+1 { - if seqNum > s.cachedL1PriceData.endOfL1PriceDataCache+1 { - log.Info("message position higher then current end of l1 price data cache, resetting cache to this message") - resetCache() - } else if seqNum < s.cachedL1PriceData.startOfL1PriceDataCache { - log.Info("message position lower than start of l1 price data cache, ignoring") - } else { - log.Info("message position already seen in l1 price data cache, ignoring") - } - } else { - cummulativeCallDataUnits := s.cachedL1PriceData.msgToL1PriceData[size-1].cummulativeCallDataUnits - cummulativeL1GasCharged := s.cachedL1PriceData.msgToL1PriceData[size-1].cummulativeL1GasCharged - s.cachedL1PriceData.msgToL1PriceData = append(s.cachedL1PriceData.msgToL1PriceData, L1PriceDataOfMsg{ - callDataUnits: callDataUnits, - cummulativeCallDataUnits: cummulativeCallDataUnits + callDataUnits, - l1GasCharged: l1GasCharged, - cummulativeL1GasCharged: cummulativeL1GasCharged + l1GasCharged, - }) - s.cachedL1PriceData.endOfL1PriceDataCache = seqNum - } + return s.exec.GetL1GasPriceEstimate() } // Encodes a uint64 as bytes in a lexically sortable manner for database iteration. @@ -773,7 +657,7 @@ func (s *TransactionStreamer) AddMessagesAndEndBatch(pos arbutil.MessageIndex, m if messagesAreConfirmed { // Trim confirmed messages from l1pricedataCache - s.TrimCache(pos + arbutil.MessageIndex(len(messages))) + s.exec.TrimCache(pos + arbutil.MessageIndex(len(messages))) s.reorgMutex.RLock() dups, _, _, err := s.countDuplicateMessages(pos, messagesWithBlockHash, nil) s.reorgMutex.RUnlock() diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 083f59dfab..5e4d45b72f 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -53,6 +53,20 @@ var ( gasUsedSinceStartupCounter = metrics.NewRegisteredCounter("arb/gas_used", nil) ) +type L1PriceDataOfMsg struct { + callDataUnits uint64 + cummulativeCallDataUnits uint64 + l1GasCharged uint64 + cummulativeL1GasCharged uint64 +} + +type L1PriceData struct { + startOfL1PriceDataCache arbutil.MessageIndex + endOfL1PriceDataCache arbutil.MessageIndex + msgToL1PriceData []L1PriceDataOfMsg + currentEstimateOfL1GasPrice uint64 +} + type ExecutionEngine struct { stopwaiter.StopWaiter @@ -72,6 +86,9 @@ type ExecutionEngine struct { reorgSequencing bool prefetchBlock bool + + cachedL1PriceDataMutex sync.RWMutex + cachedL1PriceData *L1PriceData } func NewExecutionEngine(bc *core.BlockChain) (*ExecutionEngine, error) { @@ -79,10 +96,56 @@ func NewExecutionEngine(bc *core.BlockChain) (*ExecutionEngine, error) { bc: bc, resequenceChan: make(chan []*arbostypes.MessageWithMetadata), newBlockNotifier: make(chan struct{}, 1), + cachedL1PriceData: &L1PriceData{ + msgToL1PriceData: []L1PriceDataOfMsg{}, + }, }, nil } -func (n *ExecutionEngine) Initialize(rustCacheSize uint32) { +func (s *ExecutionEngine) backlogCallDataUnits() uint64 { + s.cachedL1PriceDataMutex.RLock() + defer s.cachedL1PriceDataMutex.RUnlock() + + size := len(s.cachedL1PriceData.msgToL1PriceData) + if size == 0 { + return 0 + } + return (s.cachedL1PriceData.msgToL1PriceData[size-1].cummulativeCallDataUnits - + s.cachedL1PriceData.msgToL1PriceData[0].cummulativeCallDataUnits + + s.cachedL1PriceData.msgToL1PriceData[0].callDataUnits) +} + +func (s *ExecutionEngine) backlogL1GasCharged() uint64 { + s.cachedL1PriceDataMutex.RLock() + defer s.cachedL1PriceDataMutex.RUnlock() + + size := len(s.cachedL1PriceData.msgToL1PriceData) + if size == 0 { + return 0 + } + return (s.cachedL1PriceData.msgToL1PriceData[size-1].cummulativeL1GasCharged - + s.cachedL1PriceData.msgToL1PriceData[0].cummulativeL1GasCharged + + s.cachedL1PriceData.msgToL1PriceData[0].l1GasCharged) +} + +func (s *ExecutionEngine) TrimCache(to arbutil.MessageIndex) { + s.cachedL1PriceDataMutex.Lock() + defer s.cachedL1PriceDataMutex.Unlock() + + if to < s.cachedL1PriceData.startOfL1PriceDataCache { + log.Info("trying to trim older cache which doesnt exist anymore") + } else if to >= s.cachedL1PriceData.endOfL1PriceDataCache { + s.cachedL1PriceData.startOfL1PriceDataCache = 0 + s.cachedL1PriceData.endOfL1PriceDataCache = 0 + s.cachedL1PriceData.msgToL1PriceData = []L1PriceDataOfMsg{} + } else { + newStart := to - s.cachedL1PriceData.startOfL1PriceDataCache + 1 + s.cachedL1PriceData.msgToL1PriceData = s.cachedL1PriceData.msgToL1PriceData[newStart:] + s.cachedL1PriceData.startOfL1PriceDataCache = to + 1 + } +} + +func (s *ExecutionEngine) Initialize(rustCacheSize uint32) { if rustCacheSize != 0 { programs.ResizeWasmLruCache(rustCacheSize) } @@ -618,22 +681,26 @@ func (s *ExecutionEngine) ResultAtPos(pos arbutil.MessageIndex) (*execution.Mess return s.resultFromHeader(s.bc.GetHeaderByNumber(s.MessageIndexToBlockNumber(pos))) } -func (s *ExecutionEngine) GetL1GasPriceEstimate() (uint64, error) { +func (s *ExecutionEngine) GetL1GasPriceEstimate() uint64 { bc := s.bc latestHeader := bc.CurrentBlock() latestState, err := bc.StateAt(latestHeader.Root) if err != nil { - return 0, errors.New("error getting latest statedb while fetching l2 Estimate of L1 GasPrice") + log.Error("error getting latest statedb while fetching l2 Estimate of L1 GasPrice") + return s.cachedL1PriceData.currentEstimateOfL1GasPrice } arbState, err := arbosState.OpenSystemArbosState(latestState, nil, true) if err != nil { - return 0, errors.New("error opening system arbos state while fetching l2 Estimate of L1 GasPrice") + log.Error("error opening system arbos state while fetching l2 Estimate of L1 GasPrice") + return s.cachedL1PriceData.currentEstimateOfL1GasPrice } l2EstimateL1GasPrice, err := arbState.L1PricingState().PricePerUnit() if err != nil { - return 0, errors.New("error fetching l2 Estimate of L1 GasPrice") + log.Error("error fetching l2 Estimate of L1 GasPrice") + return s.cachedL1PriceData.currentEstimateOfL1GasPrice } - return l2EstimateL1GasPrice.Uint64(), nil + s.cachedL1PriceData.currentEstimateOfL1GasPrice = l2EstimateL1GasPrice.Uint64() + return s.cachedL1PriceData.currentEstimateOfL1GasPrice } func (s *ExecutionEngine) getL1PricingSurplus() (int64, error) { @@ -654,17 +721,58 @@ func (s *ExecutionEngine) getL1PricingSurplus() (int64, error) { return surplus.Int64(), nil } -func (s *ExecutionEngine) cacheL1PriceDataOfMsg(num arbutil.MessageIndex, receipts types.Receipts, block *types.Block) { +func (s *ExecutionEngine) cacheL1PriceDataOfMsg(seqNum arbutil.MessageIndex, receipts types.Receipts, block *types.Block) { var gasUsedForL1 uint64 for i := 1; i < len(receipts); i++ { gasUsedForL1 += receipts[i].GasUsedForL1 } - gasChargedForL1 := gasUsedForL1 * block.BaseFee().Uint64() + l1GasCharged := gasUsedForL1 * block.BaseFee().Uint64() var callDataUnits uint64 for _, tx := range block.Transactions() { callDataUnits += tx.CalldataUnits } - s.consensus.CacheL1PriceDataOfMsg(num, callDataUnits, gasChargedForL1) + + s.cachedL1PriceDataMutex.Lock() + defer s.cachedL1PriceDataMutex.Unlock() + + resetCache := func() { + s.cachedL1PriceData.startOfL1PriceDataCache = seqNum + s.cachedL1PriceData.endOfL1PriceDataCache = seqNum + s.cachedL1PriceData.msgToL1PriceData = []L1PriceDataOfMsg{{ + callDataUnits: callDataUnits, + cummulativeCallDataUnits: callDataUnits, + l1GasCharged: l1GasCharged, + cummulativeL1GasCharged: l1GasCharged, + }} + } + size := len(s.cachedL1PriceData.msgToL1PriceData) + if size == 0 || + s.cachedL1PriceData.startOfL1PriceDataCache == 0 || + s.cachedL1PriceData.endOfL1PriceDataCache == 0 || + arbutil.MessageIndex(size) != s.cachedL1PriceData.endOfL1PriceDataCache-s.cachedL1PriceData.startOfL1PriceDataCache+1 { + resetCache() + return + } + if seqNum != s.cachedL1PriceData.endOfL1PriceDataCache+1 { + if seqNum > s.cachedL1PriceData.endOfL1PriceDataCache+1 { + log.Info("message position higher then current end of l1 price data cache, resetting cache to this message") + resetCache() + } else if seqNum < s.cachedL1PriceData.startOfL1PriceDataCache { + log.Info("message position lower than start of l1 price data cache, ignoring") + } else { + log.Info("message position already seen in l1 price data cache, ignoring") + } + } else { + cummulativeCallDataUnits := s.cachedL1PriceData.msgToL1PriceData[size-1].cummulativeCallDataUnits + cummulativeL1GasCharged := s.cachedL1PriceData.msgToL1PriceData[size-1].cummulativeL1GasCharged + s.cachedL1PriceData.msgToL1PriceData = append(s.cachedL1PriceData.msgToL1PriceData, L1PriceDataOfMsg{ + callDataUnits: callDataUnits, + cummulativeCallDataUnits: cummulativeCallDataUnits + callDataUnits, + l1GasCharged: l1GasCharged, + cummulativeL1GasCharged: cummulativeL1GasCharged + l1GasCharged, + }) + s.cachedL1PriceData.endOfL1PriceDataCache = seqNum + } } // DigestMessage is used to create a block by executing msg against the latest state and storing it. diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index eb0d39d253..ba1359a343 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -277,10 +277,14 @@ func CreateExecutionNode( } -func (n *ExecutionNode) GetL1GasPriceEstimate() (uint64, error) { +func (n *ExecutionNode) GetL1GasPriceEstimate() uint64 { return n.ExecEngine.GetL1GasPriceEstimate() } +func (n *ExecutionNode) TrimCache(to arbutil.MessageIndex) { + n.ExecEngine.TrimCache(to) +} + func (n *ExecutionNode) Initialize(ctx context.Context) error { n.ExecEngine.Initialize(n.ConfigFetcher().Caching.StylusLRUCache) n.ArbInterface.Initialize(n) diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 189261b95b..2bace9b677 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -1058,8 +1058,8 @@ func (s *Sequencer) updateExpectedSurplus(ctx context.Context) (int64, error) { if err != nil { return 0, fmt.Errorf("error encountered getting l1 pricing surplus while updating expectedSurplus: %w", err) } - backlogL1GasCharged := int64(s.execEngine.consensus.BacklogL1GasCharged()) - backlogCallDataUnits := int64(s.execEngine.consensus.BacklogCallDataUnits()) + backlogL1GasCharged := int64(s.execEngine.backlogL1GasCharged()) + backlogCallDataUnits := int64(s.execEngine.backlogCallDataUnits()) expectedSurplus := int64(surplus) + backlogL1GasCharged - backlogCallDataUnits*int64(l1GasPrice) // update metrics l1GasPriceGauge.Update(int64(l1GasPrice)) diff --git a/execution/interface.go b/execution/interface.go index 66aefe9a5e..d767dbe93c 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -56,7 +56,8 @@ type ExecutionSequencer interface { ForwardTo(url string) error SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error NextDelayedMessageNumber() (uint64, error) - GetL1GasPriceEstimate() (uint64, error) + GetL1GasPriceEstimate() uint64 + TrimCache(to arbutil.MessageIndex) } type FullExecutionClient interface { @@ -94,9 +95,6 @@ type ConsensusInfo interface { type ConsensusSequencer interface { WriteMessageFromSequencer(pos arbutil.MessageIndex, msgWithMeta arbostypes.MessageWithMetadata, msgResult MessageResult) error ExpectChosenSequencer() error - CacheL1PriceDataOfMsg(pos arbutil.MessageIndex, callDataUnits uint64, l1GasCharged uint64) - BacklogL1GasCharged() uint64 - BacklogCallDataUnits() uint64 } type FullConsensusClient interface { From a4ab1f59ba2def61284eae53630ce2a9af654803 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Wed, 19 Jun 2024 16:31:06 -0300 Subject: [PATCH 02/13] Moves l1GasPriceEstimateGauge from BatchPoster to ExecutionEngine. Removes latestBatchSurplusGauge. --- arbnode/batch_poster.go | 13 ++----------- arbnode/transaction_streamer.go | 4 ---- execution/gethexec/executionengine.go | 2 +- execution/gethexec/node.go | 4 ---- execution/gethexec/sequencer.go | 3 +++ execution/interface.go | 1 - 6 files changed, 6 insertions(+), 21 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 60693689fe..03f87f225f 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -58,8 +58,7 @@ var ( baseFeeGauge = metrics.NewRegisteredGauge("arb/batchposter/basefee", nil) blobFeeGauge = metrics.NewRegisteredGauge("arb/batchposter/blobfee", nil) l1GasPriceGauge = metrics.NewRegisteredGauge("arb/batchposter/l1gasprice", nil) - l1GasPriceEstimateGauge = metrics.NewRegisteredGauge("arb/batchposter/l1gasprice/estimate", nil) - latestBatchSurplusGauge = metrics.NewRegisteredGauge("arb/batchposter/latestbatchsurplus", nil) + messageLengthGauge = metrics.NewRegisteredGauge("arb/batchposter/messagelength", nil) blockGasUsedGauge = metrics.NewRegisteredGauge("arb/batchposter/blockgas/used", nil) blockGasLimitGauge = metrics.NewRegisteredGauge("arb/batchposter/blockgas/limit", nil) blobGasUsedGauge = metrics.NewRegisteredGauge("arb/batchposter/blobgas/used", nil) @@ -560,9 +559,7 @@ func (b *BatchPoster) pollForL1PriceData(ctx context.Context) { } else { suggestedTipCapGauge.Update(suggestedTipCap.Int64()) } - l1GasPriceEstimate := b.streamer.CurrentEstimateOfL1GasPrice() l1GasPriceGauge.Update(int64(l1GasPrice)) - l1GasPriceEstimateGauge.Update(int64(l1GasPriceEstimate)) case <-ctx.Done(): return } @@ -1354,13 +1351,7 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) "numBlobs", len(kzgBlobs), ) - surplus := arbmath.SaturatingMul( - arbmath.SaturatingSub( - l1GasPriceGauge.Snapshot().Value(), - l1GasPriceEstimateGauge.Snapshot().Value()), - int64(len(sequencerMsg)*16), - ) - latestBatchSurplusGauge.Update(surplus) + messageLengthGauge.Update(int64(len(sequencerMsg))) recentlyHitL1Bounds := time.Since(b.lastHitL1Bounds) < config.PollInterval*3 postedMessages := b.building.msgCount - batchPosition.MessageCount diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index f2c19fe9ce..0f91808b36 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -133,10 +133,6 @@ const ( BlockHashMismatchLogMsg = "BlockHash from feed doesn't match locally computed hash. Check feed source." ) -func (s *TransactionStreamer) CurrentEstimateOfL1GasPrice() uint64 { - return s.exec.GetL1GasPriceEstimate() -} - // Encodes a uint64 as bytes in a lexically sortable manner for database iteration. // Generally this is only used for database keys, which need sorted. // A shorter RLP encoding is usually used for database values. diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 5e4d45b72f..c5b3ec1e46 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -681,7 +681,7 @@ func (s *ExecutionEngine) ResultAtPos(pos arbutil.MessageIndex) (*execution.Mess return s.resultFromHeader(s.bc.GetHeaderByNumber(s.MessageIndexToBlockNumber(pos))) } -func (s *ExecutionEngine) GetL1GasPriceEstimate() uint64 { +func (s *ExecutionEngine) getL1GasPriceEstimate() uint64 { bc := s.bc latestHeader := bc.CurrentBlock() latestState, err := bc.StateAt(latestHeader.Root) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index ba1359a343..bcc0390e99 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -277,10 +277,6 @@ func CreateExecutionNode( } -func (n *ExecutionNode) GetL1GasPriceEstimate() uint64 { - return n.ExecEngine.GetL1GasPriceEstimate() -} - func (n *ExecutionNode) TrimCache(to arbutil.MessageIndex) { n.ExecEngine.TrimCache(to) } diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 2bace9b677..f14d70d292 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -54,6 +54,7 @@ var ( successfulBlocksCounter = metrics.NewRegisteredCounter("arb/sequencer/block/successful", nil) conditionalTxRejectedBySequencerCounter = metrics.NewRegisteredCounter("arb/sequencer/condtionaltx/rejected", nil) conditionalTxAcceptedBySequencerCounter = metrics.NewRegisteredCounter("arb/sequencer/condtionaltx/accepted", nil) + l1GasPriceEstimateGauge = metrics.NewRegisteredGauge("arb/sequencer/l1gasprice/estimate", nil) l1GasPriceGauge = metrics.NewRegisteredGauge("arb/sequencer/l1gasprice", nil) callDataUnitsBacklogGauge = metrics.NewRegisteredGauge("arb/sequencer/calldataunitsbacklog", nil) unusedL1GasChargeGauge = metrics.NewRegisteredGauge("arb/sequencer/unusedl1gascharge", nil) @@ -1061,8 +1062,10 @@ func (s *Sequencer) updateExpectedSurplus(ctx context.Context) (int64, error) { backlogL1GasCharged := int64(s.execEngine.backlogL1GasCharged()) backlogCallDataUnits := int64(s.execEngine.backlogCallDataUnits()) expectedSurplus := int64(surplus) + backlogL1GasCharged - backlogCallDataUnits*int64(l1GasPrice) + l1GasPriceEstimate := int64(s.execEngine.getL1GasPriceEstimate()) // update metrics l1GasPriceGauge.Update(int64(l1GasPrice)) + l1GasPriceEstimateGauge.Update(l1GasPriceEstimate) callDataUnitsBacklogGauge.Update(backlogCallDataUnits) unusedL1GasChargeGauge.Update(backlogL1GasCharged) currentSurplusGauge.Update(surplus) diff --git a/execution/interface.go b/execution/interface.go index d767dbe93c..c200d7dcd4 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -56,7 +56,6 @@ type ExecutionSequencer interface { ForwardTo(url string) error SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error NextDelayedMessageNumber() (uint64, error) - GetL1GasPriceEstimate() uint64 TrimCache(to arbutil.MessageIndex) } From 96c206215946902cd13868d2af4c25f807f4ad84 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 24 Jun 2024 16:03:28 -0300 Subject: [PATCH 03/13] Moves cacheL1PriceDataMutex to L1PriceData --- execution/gethexec/executionengine.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index c5b3ec1e46..5e65ea792e 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -61,6 +61,7 @@ type L1PriceDataOfMsg struct { } type L1PriceData struct { + mutex sync.RWMutex startOfL1PriceDataCache arbutil.MessageIndex endOfL1PriceDataCache arbutil.MessageIndex msgToL1PriceData []L1PriceDataOfMsg @@ -87,8 +88,7 @@ type ExecutionEngine struct { prefetchBlock bool - cachedL1PriceDataMutex sync.RWMutex - cachedL1PriceData *L1PriceData + cachedL1PriceData *L1PriceData } func NewExecutionEngine(bc *core.BlockChain) (*ExecutionEngine, error) { @@ -103,8 +103,8 @@ func NewExecutionEngine(bc *core.BlockChain) (*ExecutionEngine, error) { } func (s *ExecutionEngine) backlogCallDataUnits() uint64 { - s.cachedL1PriceDataMutex.RLock() - defer s.cachedL1PriceDataMutex.RUnlock() + s.cachedL1PriceData.mutex.RLock() + defer s.cachedL1PriceData.mutex.RUnlock() size := len(s.cachedL1PriceData.msgToL1PriceData) if size == 0 { @@ -116,8 +116,8 @@ func (s *ExecutionEngine) backlogCallDataUnits() uint64 { } func (s *ExecutionEngine) backlogL1GasCharged() uint64 { - s.cachedL1PriceDataMutex.RLock() - defer s.cachedL1PriceDataMutex.RUnlock() + s.cachedL1PriceData.mutex.RLock() + defer s.cachedL1PriceData.mutex.RUnlock() size := len(s.cachedL1PriceData.msgToL1PriceData) if size == 0 { @@ -129,8 +129,8 @@ func (s *ExecutionEngine) backlogL1GasCharged() uint64 { } func (s *ExecutionEngine) TrimCache(to arbutil.MessageIndex) { - s.cachedL1PriceDataMutex.Lock() - defer s.cachedL1PriceDataMutex.Unlock() + s.cachedL1PriceData.mutex.Lock() + defer s.cachedL1PriceData.mutex.Unlock() if to < s.cachedL1PriceData.startOfL1PriceDataCache { log.Info("trying to trim older cache which doesnt exist anymore") @@ -732,8 +732,8 @@ func (s *ExecutionEngine) cacheL1PriceDataOfMsg(seqNum arbutil.MessageIndex, rec callDataUnits += tx.CalldataUnits } - s.cachedL1PriceDataMutex.Lock() - defer s.cachedL1PriceDataMutex.Unlock() + s.cachedL1PriceData.mutex.Lock() + defer s.cachedL1PriceData.mutex.Unlock() resetCache := func() { s.cachedL1PriceData.startOfL1PriceDataCache = seqNum From 2bf5f5a4daeeb5d3a466cc4acea472211cf403df Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 24 Jun 2024 16:04:38 -0300 Subject: [PATCH 04/13] NewL1PriceData --- execution/gethexec/executionengine.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 5e65ea792e..ddab64c7df 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -91,14 +91,18 @@ type ExecutionEngine struct { cachedL1PriceData *L1PriceData } +func NewL1PriceData() *L1PriceData { + return &L1PriceData{ + msgToL1PriceData: []L1PriceDataOfMsg{}, + } +} + func NewExecutionEngine(bc *core.BlockChain) (*ExecutionEngine, error) { return &ExecutionEngine{ - bc: bc, - resequenceChan: make(chan []*arbostypes.MessageWithMetadata), - newBlockNotifier: make(chan struct{}, 1), - cachedL1PriceData: &L1PriceData{ - msgToL1PriceData: []L1PriceDataOfMsg{}, - }, + bc: bc, + resequenceChan: make(chan []*arbostypes.MessageWithMetadata), + newBlockNotifier: make(chan struct{}, 1), + cachedL1PriceData: NewL1PriceData(), }, nil } From 3802ac58e52738ce8a8f6c1a7ccf1a860ea1d2bb Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 24 Jun 2024 16:07:55 -0300 Subject: [PATCH 05/13] Removes arb/batchposter/messagelength --- arbnode/batch_poster.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 03f87f225f..57b43f26ea 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -58,7 +58,6 @@ var ( baseFeeGauge = metrics.NewRegisteredGauge("arb/batchposter/basefee", nil) blobFeeGauge = metrics.NewRegisteredGauge("arb/batchposter/blobfee", nil) l1GasPriceGauge = metrics.NewRegisteredGauge("arb/batchposter/l1gasprice", nil) - messageLengthGauge = metrics.NewRegisteredGauge("arb/batchposter/messagelength", nil) blockGasUsedGauge = metrics.NewRegisteredGauge("arb/batchposter/blockgas/used", nil) blockGasLimitGauge = metrics.NewRegisteredGauge("arb/batchposter/blockgas/limit", nil) blobGasUsedGauge = metrics.NewRegisteredGauge("arb/batchposter/blobgas/used", nil) @@ -1351,8 +1350,6 @@ func (b *BatchPoster) maybePostSequencerBatch(ctx context.Context) (bool, error) "numBlobs", len(kzgBlobs), ) - messageLengthGauge.Update(int64(len(sequencerMsg))) - recentlyHitL1Bounds := time.Since(b.lastHitL1Bounds) < config.PollInterval*3 postedMessages := b.building.msgCount - batchPosition.MessageCount b.messagesPerBatch.Update(uint64(postedMessages)) From d19e3036d9ccd7e5c811747d7e9271f4e2d98879 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 24 Jun 2024 16:33:55 -0300 Subject: [PATCH 06/13] Also caches L1 price data when digesting message. Useful to keep L1 price data with more precision when using multiple sequencers with a sequencer coordinator pattern. --- execution/gethexec/executionengine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index ddab64c7df..49ba9e3342 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -523,7 +523,6 @@ func (s *ExecutionEngine) sequenceTransactionsWithBlockMutex(header *arbostypes. if err != nil { return nil, err } - s.cacheL1PriceDataOfMsg(pos, receipts, block) return block, nil @@ -824,6 +823,7 @@ func (s *ExecutionEngine) digestMessageWithBlockMutex(num arbutil.MessageIndex, if err != nil { return nil, err } + s.cacheL1PriceDataOfMsg(num, receipts, block) if time.Now().After(s.nextScheduledVersionCheck) { s.nextScheduledVersionCheck = time.Now().Add(time.Minute) From 69821aacb876904b363cc06fe3b1a2ee82d92dfc Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 24 Jun 2024 17:51:55 -0300 Subject: [PATCH 07/13] Removes L1PriceData.currentEstimateOfL1GasPrice --- execution/gethexec/executionengine.go | 23 +++++++++-------------- execution/gethexec/sequencer.go | 7 +++++-- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 49ba9e3342..186ebb827f 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -61,11 +61,10 @@ type L1PriceDataOfMsg struct { } type L1PriceData struct { - mutex sync.RWMutex - startOfL1PriceDataCache arbutil.MessageIndex - endOfL1PriceDataCache arbutil.MessageIndex - msgToL1PriceData []L1PriceDataOfMsg - currentEstimateOfL1GasPrice uint64 + mutex sync.RWMutex + startOfL1PriceDataCache arbutil.MessageIndex + endOfL1PriceDataCache arbutil.MessageIndex + msgToL1PriceData []L1PriceDataOfMsg } type ExecutionEngine struct { @@ -684,26 +683,22 @@ func (s *ExecutionEngine) ResultAtPos(pos arbutil.MessageIndex) (*execution.Mess return s.resultFromHeader(s.bc.GetHeaderByNumber(s.MessageIndexToBlockNumber(pos))) } -func (s *ExecutionEngine) getL1GasPriceEstimate() uint64 { +func (s *ExecutionEngine) getL1GasPriceEstimate() (uint64, error) { bc := s.bc latestHeader := bc.CurrentBlock() latestState, err := bc.StateAt(latestHeader.Root) if err != nil { - log.Error("error getting latest statedb while fetching l2 Estimate of L1 GasPrice") - return s.cachedL1PriceData.currentEstimateOfL1GasPrice + return 0, errors.New("error getting latest statedb while fetching l2 Estimate of L1 GasPrice") } arbState, err := arbosState.OpenSystemArbosState(latestState, nil, true) if err != nil { - log.Error("error opening system arbos state while fetching l2 Estimate of L1 GasPrice") - return s.cachedL1PriceData.currentEstimateOfL1GasPrice + return 0, errors.New("error opening system arbos state while fetching l2 Estimate of L1 GasPrice") } l2EstimateL1GasPrice, err := arbState.L1PricingState().PricePerUnit() if err != nil { - log.Error("error fetching l2 Estimate of L1 GasPrice") - return s.cachedL1PriceData.currentEstimateOfL1GasPrice + return 0, errors.New("error fetching l2 Estimate of L1 GasPrice") } - s.cachedL1PriceData.currentEstimateOfL1GasPrice = l2EstimateL1GasPrice.Uint64() - return s.cachedL1PriceData.currentEstimateOfL1GasPrice + return l2EstimateL1GasPrice.Uint64(), nil } func (s *ExecutionEngine) getL1PricingSurplus() (int64, error) { diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index f14d70d292..15413fe1e5 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -1059,13 +1059,16 @@ func (s *Sequencer) updateExpectedSurplus(ctx context.Context) (int64, error) { if err != nil { return 0, fmt.Errorf("error encountered getting l1 pricing surplus while updating expectedSurplus: %w", err) } + l1GasPriceEstimate, err := s.execEngine.getL1GasPriceEstimate() + if err != nil { + return 0, fmt.Errorf("error encountered getting l1 gas price estimate while updating expectedSurplus: %w", err) + } backlogL1GasCharged := int64(s.execEngine.backlogL1GasCharged()) backlogCallDataUnits := int64(s.execEngine.backlogCallDataUnits()) expectedSurplus := int64(surplus) + backlogL1GasCharged - backlogCallDataUnits*int64(l1GasPrice) - l1GasPriceEstimate := int64(s.execEngine.getL1GasPriceEstimate()) // update metrics l1GasPriceGauge.Update(int64(l1GasPrice)) - l1GasPriceEstimateGauge.Update(l1GasPriceEstimate) + l1GasPriceEstimateGauge.Update(int64(l1GasPriceEstimate)) callDataUnitsBacklogGauge.Update(backlogCallDataUnits) unusedL1GasChargeGauge.Update(backlogL1GasCharged) currentSurplusGauge.Update(surplus) From cedb482b4c0d32a05ad1522548122373989ab921 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 24 Jun 2024 19:14:18 -0300 Subject: [PATCH 08/13] Moves l1GasPriceEstimateGauge to executionengine --- execution/gethexec/executionengine.go | 14 +++++++++----- execution/gethexec/sequencer.go | 6 ------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 186ebb827f..e27eddefab 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -46,6 +46,7 @@ import ( ) var ( + l1GasPriceEstimateGauge = metrics.NewRegisteredGauge("arb/l1gasprice/estimate", nil) baseFeeGauge = metrics.NewRegisteredGauge("arb/block/basefee", nil) blockGasUsedHistogram = metrics.NewRegisteredHistogram("arb/block/gasused", nil, metrics.NewBoundedHistogramSample()) txCountHistogram = metrics.NewRegisteredHistogram("arb/block/transactions/count", nil, metrics.NewBoundedHistogramSample()) @@ -665,6 +666,7 @@ func (s *ExecutionEngine) appendBlock(block *types.Block, statedb *state.StateDB } blockGasUsedHistogram.Update(int64(blockGasused)) gasUsedSinceStartupCounter.Inc(int64(blockGasused)) + s.updateL1GasPriceEstimateMetric() return nil } @@ -683,22 +685,24 @@ func (s *ExecutionEngine) ResultAtPos(pos arbutil.MessageIndex) (*execution.Mess return s.resultFromHeader(s.bc.GetHeaderByNumber(s.MessageIndexToBlockNumber(pos))) } -func (s *ExecutionEngine) getL1GasPriceEstimate() (uint64, error) { +func (s *ExecutionEngine) updateL1GasPriceEstimateMetric() { bc := s.bc latestHeader := bc.CurrentBlock() latestState, err := bc.StateAt(latestHeader.Root) if err != nil { - return 0, errors.New("error getting latest statedb while fetching l2 Estimate of L1 GasPrice") + log.Error("error getting latest statedb while fetching l2 Estimate of L1 GasPrice") + return } arbState, err := arbosState.OpenSystemArbosState(latestState, nil, true) if err != nil { - return 0, errors.New("error opening system arbos state while fetching l2 Estimate of L1 GasPrice") + log.Error("error opening system arbos state while fetching l2 Estimate of L1 GasPrice") + return } l2EstimateL1GasPrice, err := arbState.L1PricingState().PricePerUnit() if err != nil { - return 0, errors.New("error fetching l2 Estimate of L1 GasPrice") + log.Error("error fetching l2 Estimate of L1 GasPrice") } - return l2EstimateL1GasPrice.Uint64(), nil + l1GasPriceEstimateGauge.Update(l2EstimateL1GasPrice.Int64()) } func (s *ExecutionEngine) getL1PricingSurplus() (int64, error) { diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 15413fe1e5..2bace9b677 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -54,7 +54,6 @@ var ( successfulBlocksCounter = metrics.NewRegisteredCounter("arb/sequencer/block/successful", nil) conditionalTxRejectedBySequencerCounter = metrics.NewRegisteredCounter("arb/sequencer/condtionaltx/rejected", nil) conditionalTxAcceptedBySequencerCounter = metrics.NewRegisteredCounter("arb/sequencer/condtionaltx/accepted", nil) - l1GasPriceEstimateGauge = metrics.NewRegisteredGauge("arb/sequencer/l1gasprice/estimate", nil) l1GasPriceGauge = metrics.NewRegisteredGauge("arb/sequencer/l1gasprice", nil) callDataUnitsBacklogGauge = metrics.NewRegisteredGauge("arb/sequencer/calldataunitsbacklog", nil) unusedL1GasChargeGauge = metrics.NewRegisteredGauge("arb/sequencer/unusedl1gascharge", nil) @@ -1059,16 +1058,11 @@ func (s *Sequencer) updateExpectedSurplus(ctx context.Context) (int64, error) { if err != nil { return 0, fmt.Errorf("error encountered getting l1 pricing surplus while updating expectedSurplus: %w", err) } - l1GasPriceEstimate, err := s.execEngine.getL1GasPriceEstimate() - if err != nil { - return 0, fmt.Errorf("error encountered getting l1 gas price estimate while updating expectedSurplus: %w", err) - } backlogL1GasCharged := int64(s.execEngine.backlogL1GasCharged()) backlogCallDataUnits := int64(s.execEngine.backlogCallDataUnits()) expectedSurplus := int64(surplus) + backlogL1GasCharged - backlogCallDataUnits*int64(l1GasPrice) // update metrics l1GasPriceGauge.Update(int64(l1GasPrice)) - l1GasPriceEstimateGauge.Update(int64(l1GasPriceEstimate)) callDataUnitsBacklogGauge.Update(backlogCallDataUnits) unusedL1GasChargeGauge.Update(backlogL1GasCharged) currentSurplusGauge.Update(surplus) From f0f26c42d8ae88e784b86e53f4d7c6f86ae9342b Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 24 Jun 2024 19:32:48 -0300 Subject: [PATCH 09/13] Adds missing return --- execution/gethexec/executionengine.go | 1 + 1 file changed, 1 insertion(+) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index e27eddefab..fbd11dd112 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -701,6 +701,7 @@ func (s *ExecutionEngine) updateL1GasPriceEstimateMetric() { l2EstimateL1GasPrice, err := arbState.L1PricingState().PricePerUnit() if err != nil { log.Error("error fetching l2 Estimate of L1 GasPrice") + return } l1GasPriceEstimateGauge.Update(l2EstimateL1GasPrice.Int64()) } From bf48d44846d07122936da81fe4b8eee77f7017cf Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Wed, 26 Jun 2024 09:52:19 -0300 Subject: [PATCH 10/13] Renames TrimCache to MarkFeedStart --- arbnode/transaction_streamer.go | 2 +- execution/gethexec/executionengine.go | 2 +- execution/gethexec/node.go | 4 ++-- execution/interface.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 0f91808b36..5c02129ee6 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -653,7 +653,7 @@ func (s *TransactionStreamer) AddMessagesAndEndBatch(pos arbutil.MessageIndex, m if messagesAreConfirmed { // Trim confirmed messages from l1pricedataCache - s.exec.TrimCache(pos + arbutil.MessageIndex(len(messages))) + s.exec.MarkFeedStart(pos + arbutil.MessageIndex(len(messages))) s.reorgMutex.RLock() dups, _, _, err := s.countDuplicateMessages(pos, messagesWithBlockHash, nil) s.reorgMutex.RUnlock() diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index fbd11dd112..d7dcc8f584 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -132,7 +132,7 @@ func (s *ExecutionEngine) backlogL1GasCharged() uint64 { s.cachedL1PriceData.msgToL1PriceData[0].l1GasCharged) } -func (s *ExecutionEngine) TrimCache(to arbutil.MessageIndex) { +func (s *ExecutionEngine) MarkFeedStart(to arbutil.MessageIndex) { s.cachedL1PriceData.mutex.Lock() defer s.cachedL1PriceData.mutex.Unlock() diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index bcc0390e99..cb2bfe12e8 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -277,8 +277,8 @@ func CreateExecutionNode( } -func (n *ExecutionNode) TrimCache(to arbutil.MessageIndex) { - n.ExecEngine.TrimCache(to) +func (n *ExecutionNode) MarkFeedStart(to arbutil.MessageIndex) { + n.ExecEngine.MarkFeedStart(to) } func (n *ExecutionNode) Initialize(ctx context.Context) error { diff --git a/execution/interface.go b/execution/interface.go index c200d7dcd4..32ec7dd0f7 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -56,7 +56,7 @@ type ExecutionSequencer interface { ForwardTo(url string) error SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error NextDelayedMessageNumber() (uint64, error) - TrimCache(to arbutil.MessageIndex) + MarkFeedStart(to arbutil.MessageIndex) } type FullExecutionClient interface { From bf23a686408bc650ee32473212a33937967f527f Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Wed, 26 Jun 2024 11:06:02 -0300 Subject: [PATCH 11/13] Calls cachedL1PriceData when sequencing delayed messages. --- execution/gethexec/executionengine.go | 29 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index d7dcc8f584..355e33ca11 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -523,7 +523,7 @@ func (s *ExecutionEngine) sequenceTransactionsWithBlockMutex(header *arbostypes. if err != nil { return nil, err } - s.cacheL1PriceDataOfMsg(pos, receipts, block) + s.cacheL1PriceDataOfMsg(pos, receipts, block, false) return block, nil } @@ -543,7 +543,7 @@ func (s *ExecutionEngine) sequenceDelayedMessageWithBlockMutex(message *arbostyp expectedDelayed := currentHeader.Nonce.Uint64() - lastMsg, err := s.BlockNumberToMessageIndex(currentHeader.Number.Uint64()) + pos, err := s.BlockNumberToMessageIndex(currentHeader.Number.Uint64() + 1) if err != nil { return nil, err } @@ -569,7 +569,7 @@ func (s *ExecutionEngine) sequenceDelayedMessageWithBlockMutex(message *arbostyp return nil, err } - err = s.consensus.WriteMessageFromSequencer(lastMsg+1, messageWithMeta, *msgResult) + err = s.consensus.WriteMessageFromSequencer(pos, messageWithMeta, *msgResult) if err != nil { return nil, err } @@ -578,8 +578,9 @@ func (s *ExecutionEngine) sequenceDelayedMessageWithBlockMutex(message *arbostyp if err != nil { return nil, err } + s.cacheL1PriceDataOfMsg(pos, receipts, block, true) - log.Info("ExecutionEngine: Added DelayedMessages", "pos", lastMsg+1, "delayed", delayedSeqNum, "block-header", block.Header()) + log.Info("ExecutionEngine: Added DelayedMessages", "pos", pos, "delayed", delayedSeqNum, "block-header", block.Header()) return block, nil } @@ -724,16 +725,20 @@ func (s *ExecutionEngine) getL1PricingSurplus() (int64, error) { return surplus.Int64(), nil } -func (s *ExecutionEngine) cacheL1PriceDataOfMsg(seqNum arbutil.MessageIndex, receipts types.Receipts, block *types.Block) { +func (s *ExecutionEngine) cacheL1PriceDataOfMsg(seqNum arbutil.MessageIndex, receipts types.Receipts, block *types.Block, blockBuiltUsingDelayedMessage bool) { var gasUsedForL1 uint64 - for i := 1; i < len(receipts); i++ { - gasUsedForL1 += receipts[i].GasUsedForL1 - } - l1GasCharged := gasUsedForL1 * block.BaseFee().Uint64() var callDataUnits uint64 - for _, tx := range block.Transactions() { - callDataUnits += tx.CalldataUnits + if !blockBuiltUsingDelayedMessage { + // s.cachedL1PriceData tracks L1 price data for messages posted by Nitro, + // so delayed messages should not update cummulative values kept on it. + for i := 1; i < len(receipts); i++ { + gasUsedForL1 += receipts[i].GasUsedForL1 + } + for _, tx := range block.Transactions() { + callDataUnits += tx.CalldataUnits + } } + l1GasCharged := gasUsedForL1 * block.BaseFee().Uint64() s.cachedL1PriceData.mutex.Lock() defer s.cachedL1PriceData.mutex.Unlock() @@ -823,7 +828,7 @@ func (s *ExecutionEngine) digestMessageWithBlockMutex(num arbutil.MessageIndex, if err != nil { return nil, err } - s.cacheL1PriceDataOfMsg(num, receipts, block) + s.cacheL1PriceDataOfMsg(num, receipts, block, false) if time.Now().After(s.nextScheduledVersionCheck) { s.nextScheduledVersionCheck = time.Now().Add(time.Minute) From 628cdb893cc3dd17465fe6c00059630e9944ec1f Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Wed, 26 Jun 2024 11:10:30 -0300 Subject: [PATCH 12/13] Fixes not considering first receipt when computing gasUsedForL1 --- execution/gethexec/executionengine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index 355e33ca11..e9742a293c 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -731,7 +731,7 @@ func (s *ExecutionEngine) cacheL1PriceDataOfMsg(seqNum arbutil.MessageIndex, rec if !blockBuiltUsingDelayedMessage { // s.cachedL1PriceData tracks L1 price data for messages posted by Nitro, // so delayed messages should not update cummulative values kept on it. - for i := 1; i < len(receipts); i++ { + for i := 0; i < len(receipts); i++ { gasUsedForL1 += receipts[i].GasUsedForL1 } for _, tx := range block.Transactions() { From 060da16062c91fb34be51fe805d3d1e7b88d069c Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Wed, 26 Jun 2024 12:13:40 -0300 Subject: [PATCH 13/13] Excludes arbitrum internal transaction when computing gasUsedForL1 --- execution/gethexec/executionengine.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/execution/gethexec/executionengine.go b/execution/gethexec/executionengine.go index e9742a293c..95b865df5a 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -731,7 +731,10 @@ func (s *ExecutionEngine) cacheL1PriceDataOfMsg(seqNum arbutil.MessageIndex, rec if !blockBuiltUsingDelayedMessage { // s.cachedL1PriceData tracks L1 price data for messages posted by Nitro, // so delayed messages should not update cummulative values kept on it. - for i := 0; i < len(receipts); i++ { + + // First transaction in every block is an Arbitrum internal transaction, + // so we skip it here. + for i := 1; i < len(receipts); i++ { gasUsedForL1 += receipts[i].GasUsedForL1 } for _, tx := range block.Transactions() {