Skip to content

Commit 4329432

Browse files
authored
Merge pull request #3471 from OffchainLabs/mel-uses-logs
Message extraction function works with logs instead of receipts
2 parents cd2cb43 + c100876 commit 4329432

22 files changed

+827
-585
lines changed

arbnode/db-schema/schema.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ var (
1515
SequencerBatchMetaPrefix []byte = []byte("s") // maps a batch sequence number to BatchMetadata
1616
DelayedSequencedPrefix []byte = []byte("a") // maps a delayed message count to the first sequencer batch sequence number with this delayed count
1717
MelStatePrefix []byte = []byte("l") // maps a parent chain block number to its computed MEL state
18-
MelDelayedMessagePrefix []byte = []byte("y") // maps a delayed sequence number to an accumulator and an RLP encoded message [Note: might need to replace or be replaced by RlpDelayedMessagePrefix]
18+
MelDelayedMessagePrefix []byte = []byte("y") // maps a delayed sequence number to an accumulator and an RLP encoded message [TODO: might need to replace or be replaced by RlpDelayedMessagePrefix]
19+
MelSequencerBatchMetaPrefix []byte = []byte("q") // maps a batch sequence number to BatchMetadata [TODO: might need to replace or be replaced by SequencerBatchMetaPrefix
1920

2021
MessageCountKey []byte = []byte("_messageCount") // contains the current message count
2122
LastPrunedMessageKey []byte = []byte("_lastPrunedMessageKey") // contains the last pruned message key

arbnode/mel/delayed_message_backlog.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type DelayedMessageBacklog struct {
2424
ctx context.Context
2525
capacity int
2626
entries []*DelayedMessageBacklogEntry
27+
dirtiesStartPos int // represents the starting point of dirties in the entries list, items added while processing a state
2728
initMessage *DelayedInboxMessage
2829
finalizedAndReadIndexFetcher func(context.Context) (uint64, error)
2930
}
@@ -80,7 +81,8 @@ func (d *DelayedMessageBacklog) Get(index uint64) (*DelayedMessageBacklogEntry,
8081
return entry, nil
8182
}
8283

83-
func (d *DelayedMessageBacklog) Len() int { return len(d.entries) } // Used for testing InitializeDelayedMessageBacklog function in melrunner
84+
func (d *DelayedMessageBacklog) CommitDirties() { d.dirtiesStartPos = len(d.entries) } // Add dirties to the entries by moving dirtiesStartPos to the end
85+
func (d *DelayedMessageBacklog) Len() int { return len(d.entries) } // Used for testing InitializeDelayedMessageBacklog function in melrunner
8486
func (d *DelayedMessageBacklog) GetInitMsg() *DelayedInboxMessage { return d.initMessage }
8587
func (d *DelayedMessageBacklog) setInitMsg(msg *DelayedInboxMessage) { d.initMessage = msg }
8688

@@ -89,22 +91,29 @@ func (d *DelayedMessageBacklog) clear() error {
8991
if len(d.entries) <= d.capacity {
9092
return nil
9193
}
92-
if d.finalizedAndReadIndexFetcher != nil {
94+
if d.finalizedAndReadIndexFetcher != nil && d.dirtiesStartPos > 0 { // if all entries are currently dirty we dont trim the finalized ones
9395
finalizedDelayedMessagesRead, err := d.finalizedAndReadIndexFetcher(d.ctx)
9496
if err != nil {
9597
log.Error("Unable to trim finalized and read delayed messages from DelayedMessageBacklog, will be retried later", "err", err)
9698
return nil // we should not interrupt delayed messages accumulation if we cannot trim the backlog, since its not high priority
9799
}
98100
if finalizedDelayedMessagesRead > d.entries[0].Index {
99101
leftTrimPos := min(finalizedDelayedMessagesRead-d.entries[0].Index, uint64(len(d.entries)))
102+
// #nosec G115
103+
leftTrimPos = min(leftTrimPos, uint64(d.dirtiesStartPos)) // cannot clear dirties yet, they will be cleared out in the next attempt
100104
d.entries = d.entries[leftTrimPos:]
105+
// #nosec G115
106+
d.dirtiesStartPos -= int(leftTrimPos) // adjust start position of dirties
101107
}
102108
}
103109
return nil
104110
}
105111

106112
// Reorg removes from backlog the entries that corresponded to the reorged out parent chain blocks
107113
func (d *DelayedMessageBacklog) reorg(newDelayedMessagedSeen uint64) error {
114+
if d.dirtiesStartPos != len(d.entries) {
115+
return fmt.Errorf("delayedMessageBacklog dirties is non-empty when reorg was called, size of dirties:%d", len(d.entries)-d.dirtiesStartPos)
116+
}
108117
if len(d.entries) == 0 {
109118
return nil
110119
}
@@ -117,19 +126,13 @@ func (d *DelayedMessageBacklog) reorg(newDelayedMessagedSeen uint64) error {
117126
} else {
118127
d.entries = make([]*DelayedMessageBacklogEntry, 0)
119128
}
129+
d.dirtiesStartPos = len(d.entries)
120130
return nil
121131
}
122132

133+
// clone is a shallow clone of DelayedMessageBacklog
123134
func (d *DelayedMessageBacklog) clone() *DelayedMessageBacklog {
124-
var deque []*DelayedMessageBacklogEntry
125-
for _, item := range d.entries {
126-
msgHash := common.Hash{}
127-
copy(msgHash[:], item.MsgHash[:])
128-
deque = append(deque, &DelayedMessageBacklogEntry{
129-
Index: item.Index,
130-
MsgHash: msgHash,
131-
MelStateParentChainBlockNum: item.MelStateParentChainBlockNum,
132-
})
133-
}
134-
return &DelayedMessageBacklog{d.ctx, d.capacity, deque, nil, d.finalizedAndReadIndexFetcher} // Init msg should only be read once, no need to persist it
135+
// Remove dirties from entries
136+
d.entries = d.entries[:d.dirtiesStartPos]
137+
return d
135138
}

arbnode/mel/delayed_message_backlog_test.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,26 @@ func TestDelayedMessageBacklog(t *testing.T) {
1515

1616
backlog, err := NewDelayedMessageBacklog(ctx, 1, func(ctx context.Context) (uint64, error) { return 0, nil }, WithUnboundedCapacity)
1717
require.NoError(t, err)
18+
19+
// Verify handling of dirties
20+
for i := uint64(0); i < 2; i++ {
21+
require.NoError(t, backlog.Add(&DelayedMessageBacklogEntry{Index: i}))
22+
}
23+
backlog.CommitDirties()
24+
require.True(t, backlog.dirtiesStartPos == 2)
25+
// Add dirties and verify that calling a clone would remove them
26+
for i := uint64(2); i < 5; i++ {
27+
require.NoError(t, backlog.Add(&DelayedMessageBacklogEntry{Index: i}))
28+
}
29+
backlog.clone() // should remove all the dirties from entries list
30+
require.True(t, len(backlog.entries) == 2)
1831
numEntries := uint64(25)
19-
for i := uint64(0); i < numEntries; i++ {
32+
for i := uint64(2); i < numEntries; i++ {
2033
require.NoError(t, backlog.Add(&DelayedMessageBacklogEntry{Index: i}))
2134
}
35+
backlog.CommitDirties()
36+
// #nosec G115
37+
require.True(t, uint64(backlog.dirtiesStartPos) == numEntries)
2238

2339
// Test that clone works
2440
cloned := backlog.clone()

arbnode/mel/extraction/abis.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ import (
77
"github.com/offchainlabs/nitro/solgen/go/bridgegen"
88
)
99

10-
var batchDeliveredID common.Hash
11-
var inboxMessageDeliveredID common.Hash
12-
var inboxMessageFromOriginID common.Hash
13-
var seqInboxABI *abi.ABI
14-
var iBridgeABI *abi.ABI
10+
var BatchDeliveredID common.Hash
11+
var InboxMessageDeliveredID common.Hash
12+
var InboxMessageFromOriginID common.Hash
13+
var SeqInboxABI *abi.ABI
14+
var IBridgeABI *abi.ABI
1515
var iInboxABI *abi.ABI
1616
var iDelayedMessageProviderABI *abi.ABI
1717

@@ -21,20 +21,20 @@ func init() {
2121
if err != nil {
2222
panic(err)
2323
}
24-
batchDeliveredID = sequencerBridgeABI.Events["SequencerBatchDelivered"].ID
24+
BatchDeliveredID = sequencerBridgeABI.Events["SequencerBatchDelivered"].ID
2525
parsedIBridgeABI, err := bridgegen.IBridgeMetaData.GetAbi()
2626
if err != nil {
2727
panic(err)
2828
}
29-
iBridgeABI = parsedIBridgeABI
29+
IBridgeABI = parsedIBridgeABI
3030
parsedIMessageProviderABI, err := bridgegen.IDelayedMessageProviderMetaData.GetAbi()
3131
if err != nil {
3232
panic(err)
3333
}
3434
iDelayedMessageProviderABI = parsedIMessageProviderABI
35-
inboxMessageDeliveredID = parsedIMessageProviderABI.Events["InboxMessageDelivered"].ID
36-
inboxMessageFromOriginID = parsedIMessageProviderABI.Events["InboxMessageDeliveredFromOrigin"].ID
37-
seqInboxABI, err = bridgegen.SequencerInboxMetaData.GetAbi()
35+
InboxMessageDeliveredID = parsedIMessageProviderABI.Events["InboxMessageDelivered"].ID
36+
InboxMessageFromOriginID = parsedIMessageProviderABI.Events["InboxMessageDeliveredFromOrigin"].ID
37+
SeqInboxABI, err = bridgegen.SequencerInboxMetaData.GetAbi()
3838
if err != nil {
3939
panic(err)
4040
}
@@ -43,5 +43,5 @@ func init() {
4343
panic(err)
4444
}
4545
iInboxABI = parsedIInboxABI
46-
batchDeliveredID = sequencerBridgeABI.Events["SequencerBatchDelivered"].ID
46+
BatchDeliveredID = sequencerBridgeABI.Events["SequencerBatchDelivered"].ID
4747
}

arbnode/mel/extraction/batch_lookup.go

Lines changed: 46 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -20,82 +20,60 @@ func parseBatchesFromBlock(
2020
ctx context.Context,
2121
melState *mel.State,
2222
parentChainHeader *types.Header,
23-
txsFetcher TransactionsFetcher,
24-
receiptFetcher ReceiptFetcher,
23+
txFetcher TransactionFetcher,
24+
logsFetcher LogsFetcher,
2525
eventUnpacker eventUnpacker,
26-
) ([]*mel.SequencerInboxBatch, []*types.Transaction, []uint, error) {
27-
allBatches := make([]*mel.SequencerInboxBatch, 0)
28-
allBatchTxs := make([]*types.Transaction, 0)
29-
allBatchTxIndices := make([]uint, 0)
30-
parentChainBlockTxs, err := txsFetcher.TransactionsByHeader(ctx, parentChainHeader.Hash())
26+
) ([]*mel.SequencerInboxBatch, []*types.Transaction, error) {
27+
batches := make([]*mel.SequencerInboxBatch, 0)
28+
batchTxs := make([]*types.Transaction, 0)
29+
logs, err := logsFetcher.LogsForBlockHash(ctx, parentChainHeader.Hash())
3130
if err != nil {
32-
return nil, nil, nil, fmt.Errorf("failed to fetch transactions for parent chain block %v: %w", parentChainHeader.Hash(), err)
31+
return nil, nil, fmt.Errorf("failed to fetch logs from parent chain block %v: %w", parentChainHeader.Hash(), err)
3332
}
34-
for i, tx := range parentChainBlockTxs {
35-
// TODO: remove this temporary work around for handling init message, i.e skipping the check when msgCount==0
36-
if melState.MsgCount != 0 {
37-
if tx.To() == nil {
38-
continue
39-
}
40-
if *tx.To() != melState.BatchPostingTargetAddress {
41-
continue
42-
}
33+
var lastSeqNum *uint64
34+
for _, log := range logs {
35+
if log == nil || log.Topics[0] != BatchDeliveredID {
36+
continue
4337
}
44-
// Fetch the receipts for the transaction to get the logs.
45-
txIndex := uint(i) // #nosec G115
46-
receipt, err := receiptFetcher.ReceiptForTransactionIndex(ctx, txIndex)
47-
if err != nil {
48-
return nil, nil, nil, err
38+
event := new(bridgegen.SequencerInboxSequencerBatchDelivered)
39+
if err := eventUnpacker.unpackLogTo(event, SeqInboxABI, "SequencerBatchDelivered", *log); err != nil {
40+
return nil, nil, err
4941
}
50-
if len(receipt.Logs) == 0 {
51-
continue
42+
if !event.BatchSequenceNumber.IsUint64() {
43+
return nil, nil, errors.New("sequencer inbox event has non-uint64 sequence number")
44+
}
45+
if !event.AfterDelayedMessagesRead.IsUint64() {
46+
return nil, nil, errors.New("sequencer inbox event has non-uint64 delayed messages read")
5247
}
53-
batches := make([]*mel.SequencerInboxBatch, 0, len(receipt.Logs))
54-
txs := make([]*types.Transaction, 0, len(receipt.Logs))
55-
txIndices := make([]uint, 0, len(receipt.Logs))
56-
var lastSeqNum *uint64
57-
for _, log := range receipt.Logs {
58-
if log == nil || log.Topics[0] != batchDeliveredID {
59-
continue
60-
}
61-
event := new(bridgegen.SequencerInboxSequencerBatchDelivered)
62-
if err := eventUnpacker.unpackLogTo(event, seqInboxABI, "SequencerBatchDelivered", *log); err != nil {
63-
return nil, nil, nil, err
64-
}
65-
if !event.BatchSequenceNumber.IsUint64() {
66-
return nil, nil, nil, errors.New("sequencer inbox event has non-uint64 sequence number")
67-
}
68-
if !event.AfterDelayedMessagesRead.IsUint64() {
69-
return nil, nil, nil, errors.New("sequencer inbox event has non-uint64 delayed messages read")
70-
}
7148

72-
seqNum := event.BatchSequenceNumber.Uint64()
73-
if lastSeqNum != nil {
74-
if seqNum != *lastSeqNum+1 {
75-
return nil, nil, nil, fmt.Errorf("sequencer batches out of order; after batch %v got batch %v", *lastSeqNum, seqNum)
76-
}
49+
seqNum := event.BatchSequenceNumber.Uint64()
50+
if lastSeqNum != nil {
51+
if seqNum != *lastSeqNum+1 {
52+
return nil, nil, fmt.Errorf("sequencer batches out of order; after batch %v got batch %v", *lastSeqNum, seqNum)
7753
}
78-
lastSeqNum = &seqNum
79-
batch := &mel.SequencerInboxBatch{
80-
BlockHash: log.BlockHash,
81-
ParentChainBlockNumber: log.BlockNumber,
82-
SequenceNumber: seqNum,
83-
BeforeInboxAcc: event.BeforeAcc,
84-
AfterInboxAcc: event.AfterAcc,
85-
AfterDelayedAcc: event.DelayedAcc,
86-
AfterDelayedCount: event.AfterDelayedMessagesRead.Uint64(),
87-
RawLog: *log,
88-
TimeBounds: event.TimeBounds,
89-
DataLocation: mel.BatchDataLocation(event.DataLocation),
90-
BridgeAddress: log.Address,
91-
}
92-
batches = append(batches, batch)
93-
txs = append(txs, tx)
94-
txIndices = append(txIndices, uint(i)) // #nosec G115
9554
}
96-
allBatches = append(allBatches, batches...)
97-
allBatchTxs = append(allBatchTxs, txs...)
98-
allBatchTxIndices = append(allBatchTxIndices, txIndices...)
55+
lastSeqNum = &seqNum
56+
57+
tx, err := txFetcher.TransactionByLog(ctx, log)
58+
if err != nil {
59+
return nil, nil, fmt.Errorf("error fetching tx by hash: %v in parseBatchesFromBlock: %w ", log.TxHash, err)
60+
}
61+
62+
batch := &mel.SequencerInboxBatch{
63+
BlockHash: log.BlockHash,
64+
ParentChainBlockNumber: log.BlockNumber,
65+
SequenceNumber: seqNum,
66+
BeforeInboxAcc: event.BeforeAcc,
67+
AfterInboxAcc: event.AfterAcc,
68+
AfterDelayedAcc: event.DelayedAcc,
69+
AfterDelayedCount: event.AfterDelayedMessagesRead.Uint64(),
70+
RawLog: *log,
71+
TimeBounds: event.TimeBounds,
72+
DataLocation: mel.BatchDataLocation(event.DataLocation),
73+
BridgeAddress: log.Address,
74+
}
75+
batches = append(batches, batch)
76+
batchTxs = append(batchTxs, tx)
9977
}
100-
return allBatches, allBatchTxs, allBatchTxIndices, nil
78+
return batches, batchTxs, nil
10179
}

0 commit comments

Comments
 (0)