Skip to content
Draft
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
23 changes: 13 additions & 10 deletions arbnode/db/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@ var (
SequencerBatchMetaPrefix []byte = []byte("s") // maps a batch sequence number to BatchMetadata
DelayedSequencedPrefix []byte = []byte("a") // maps a delayed message count to the first sequencer batch sequence number with this delayed count
MelStatePrefix []byte = []byte("l") // maps a parent chain block number to its computed MEL state
MelDelayedMessagePrefix []byte = []byte("y") // maps a delayed sequence number to an accumulator and an RLP encoded message [TODO(NIT-4209): might need to replace or be replaced by RlpDelayedMessagePrefix]
MelSequencerBatchMetaPrefix []byte = []byte("q") // maps a batch sequence number to BatchMetadata [TODO(NIT-4209): might need to replace or be replaced by SequencerBatchMetaPrefix]
MelDelayedMessagePrefix []byte = []byte("y") // maps a delayed sequence number to an RLP-encoded DelayedInboxMessage (coexists with RlpDelayedMessagePrefix for legacy data below the initial MEL boundary)
MelSequencerBatchMetaPrefix []byte = []byte("q") // maps a batch sequence number to BatchMetadata (coexists with SequencerBatchMetaPrefix for legacy data below the initial MEL boundary)

MessageCountKey []byte = []byte("_messageCount") // contains the current message count
LastPrunedMessageKey []byte = []byte("_lastPrunedMessageKey") // contains the last pruned message key
LastPrunedDelayedMessageKey []byte = []byte("_lastPrunedDelayedMessageKey") // contains the last pruned RLP delayed message key
DelayedMessageCountKey []byte = []byte("_delayedMessageCount") // contains the current delayed message count
SequencerBatchCountKey []byte = []byte("_sequencerBatchCount") // contains the current sequencer message count
DbSchemaVersion []byte = []byte("_schemaVersion") // contains a uint64 representing the database schema version
HeadMelStateBlockNumKey []byte = []byte("_headMelStateBlockNum") // contains the latest computed MEL state's parent chain block number
InitialMelStateBlockNumKey []byte = []byte("_initialMelStateBlockNum") // contains the initial MEL state's parent chain block number (legacy/MEL boundary)
MessageCountKey []byte = []byte("_messageCount") // contains the current message count
LastPrunedMessageKey []byte = []byte("_lastPrunedMessageKey") // contains the last pruned message key
LastPrunedDelayedMessageKey []byte = []byte("_lastPrunedDelayedMessageKey") // contains the last pruned RLP delayed message key
LastPrunedLegacyDelayedMessageKey []byte = []byte("_lastPrunedLegacyDelayedMessageKey") // contains the last pruned legacy delayed message key
LastPrunedMelDelayedMessageKey []byte = []byte("_lastPrunedMelDelayedMessageKey") // contains the last pruned MEL delayed message key
LastPrunedParentChainBlockNumberKey []byte = []byte("_lastPrunedParentChainBlockNumberKey") // contains the last pruned parent chain block number key
DelayedMessageCountKey []byte = []byte("_delayedMessageCount") // contains the current delayed message count
SequencerBatchCountKey []byte = []byte("_sequencerBatchCount") // contains the current sequencer message count
DbSchemaVersion []byte = []byte("_schemaVersion") // contains a uint64 representing the database schema version
HeadMelStateBlockNumKey []byte = []byte("_headMelStateBlockNum") // contains the latest computed MEL state's parent chain block number
InitialMelStateBlockNumKey []byte = []byte("_initialMelStateBlockNum") // contains the initial MEL state's parent chain block number (legacy/MEL boundary)
)

const CurrentDbSchemaVersion uint64 = 2
62 changes: 62 additions & 0 deletions arbnode/db/schema/schema_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2026, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE.md
package schema

import (
"testing"
)

func TestPrefixUniqueness(t *testing.T) {
// All single-byte DB key prefixes must be unique to prevent data corruption.
prefixes := []struct {
name string
value []byte
}{
{"MessagePrefix", MessagePrefix},
{"BlockHashInputFeedPrefix", BlockHashInputFeedPrefix},
{"BlockMetadataInputFeedPrefix", BlockMetadataInputFeedPrefix},
{"MissingBlockMetadataInputFeedPrefix", MissingBlockMetadataInputFeedPrefix},
{"MessageResultPrefix", MessageResultPrefix},
{"LegacyDelayedMessagePrefix", LegacyDelayedMessagePrefix},
{"RlpDelayedMessagePrefix", RlpDelayedMessagePrefix},
{"ParentChainBlockNumberPrefix", ParentChainBlockNumberPrefix},
{"SequencerBatchMetaPrefix", SequencerBatchMetaPrefix},
{"DelayedSequencedPrefix", DelayedSequencedPrefix},
{"MelStatePrefix", MelStatePrefix},
{"MelDelayedMessagePrefix", MelDelayedMessagePrefix},
{"MelSequencerBatchMetaPrefix", MelSequencerBatchMetaPrefix},
}
seen := make(map[string]string) // prefix string → variable name
for _, p := range prefixes {
key := string(p.value)
if existing, ok := seen[key]; ok {
t.Fatalf("prefix collision: %s and %s both use %q", existing, p.name, key)
}
seen[key] = p.name
}

keys := []struct {
name string
value []byte
}{
{"MessageCountKey", MessageCountKey},
{"LastPrunedMessageKey", LastPrunedMessageKey},
{"LastPrunedDelayedMessageKey", LastPrunedDelayedMessageKey},
{"LastPrunedLegacyDelayedMessageKey", LastPrunedLegacyDelayedMessageKey},
{"LastPrunedMelDelayedMessageKey", LastPrunedMelDelayedMessageKey},
{"LastPrunedParentChainBlockNumberKey", LastPrunedParentChainBlockNumberKey},
{"DelayedMessageCountKey", DelayedMessageCountKey},
{"SequencerBatchCountKey", SequencerBatchCountKey},
{"DbSchemaVersion", DbSchemaVersion},
{"HeadMelStateBlockNumKey", HeadMelStateBlockNumKey},
{"InitialMelStateBlockNumKey", InitialMelStateBlockNumKey},
}
seenKeys := make(map[string]string)
for _, k := range keys {
key := string(k.value)
if existing, ok := seenKeys[key]; ok {
t.Fatalf("key collision: %s and %s both use %q", existing, k.name, key)
}
seenKeys[key] = k.name
}
}
Loading
Loading