mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
fix(worker): short-circuit l1 message iteration (#525)
* fix(worker): short-circuit l1 message iteration * Update core/rawdb/accessors_l1_message_test.go Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com> --------- Co-authored-by: colin <102356659+colinlyguo@users.noreply.github.com>
This commit is contained in:
parent
abcf48f20c
commit
fe8232a40f
4 changed files with 80 additions and 7 deletions
|
|
@ -43,7 +43,38 @@ func ReadSyncedL1BlockNumber(db ethdb.Reader) *uint64 {
|
||||||
return &value
|
return &value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteHighestSyncedQueueIndex writes the highest synced L1 message queue index to the database.
|
||||||
|
func WriteHighestSyncedQueueIndex(db ethdb.KeyValueWriter, queueIndex uint64) {
|
||||||
|
value := big.NewInt(0).SetUint64(queueIndex).Bytes()
|
||||||
|
|
||||||
|
if err := db.Put(highestSyncedQueueIndexKey, value); err != nil {
|
||||||
|
log.Crit("Failed to update highest synced L1 message queue index", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadHighestSyncedQueueIndex retrieves the highest synced L1 message queue index.
|
||||||
|
func ReadHighestSyncedQueueIndex(db ethdb.Reader) uint64 {
|
||||||
|
data, err := db.Get(highestSyncedQueueIndexKey)
|
||||||
|
if err != nil && isNotFoundErr(err) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("Failed to read highest synced L1 message queue index from database", "err", err)
|
||||||
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
number := new(big.Int).SetBytes(data)
|
||||||
|
if !number.IsUint64() {
|
||||||
|
log.Crit("Unexpected highest synced L1 block number in database", "number", number)
|
||||||
|
}
|
||||||
|
|
||||||
|
return number.Uint64()
|
||||||
|
}
|
||||||
|
|
||||||
// WriteL1Message writes an L1 message to the database.
|
// WriteL1Message writes an L1 message to the database.
|
||||||
|
// We assume that L1 messages are written to DB following their queue index order.
|
||||||
func WriteL1Message(db ethdb.KeyValueWriter, l1Msg types.L1MessageTx) {
|
func WriteL1Message(db ethdb.KeyValueWriter, l1Msg types.L1MessageTx) {
|
||||||
bytes, err := rlp.EncodeToBytes(l1Msg)
|
bytes, err := rlp.EncodeToBytes(l1Msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -52,6 +83,8 @@ func WriteL1Message(db ethdb.KeyValueWriter, l1Msg types.L1MessageTx) {
|
||||||
if err := db.Put(L1MessageKey(l1Msg.QueueIndex), bytes); err != nil {
|
if err := db.Put(L1MessageKey(l1Msg.QueueIndex), bytes); err != nil {
|
||||||
log.Crit("Failed to store L1 message", "err", err)
|
log.Crit("Failed to store L1 message", "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WriteHighestSyncedQueueIndex(db, l1Msg.QueueIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteL1Messages writes an array of L1 messages to the database.
|
// WriteL1Messages writes an array of L1 messages to the database.
|
||||||
|
|
@ -91,20 +124,23 @@ func ReadL1Message(db ethdb.Reader, queueIndex uint64) *types.L1MessageTx {
|
||||||
// allows us to iterate over L1 messages in the database. It
|
// allows us to iterate over L1 messages in the database. It
|
||||||
// implements an interface similar to ethdb.Iterator.
|
// implements an interface similar to ethdb.Iterator.
|
||||||
type L1MessageIterator struct {
|
type L1MessageIterator struct {
|
||||||
inner ethdb.Iterator
|
inner ethdb.Iterator
|
||||||
keyLength int
|
keyLength int
|
||||||
|
maxQueueIndex uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// IterateL1MessagesFrom creates an L1MessageIterator that iterates over
|
// IterateL1MessagesFrom creates an L1MessageIterator that iterates over
|
||||||
// all L1 message in the database starting at the provided enqueue index.
|
// all L1 message in the database starting at the provided enqueue index.
|
||||||
func IterateL1MessagesFrom(db ethdb.Iteratee, fromQueueIndex uint64) L1MessageIterator {
|
func IterateL1MessagesFrom(db ethdb.Database, fromQueueIndex uint64) L1MessageIterator {
|
||||||
start := encodeBigEndian(fromQueueIndex)
|
start := encodeBigEndian(fromQueueIndex)
|
||||||
it := db.NewIterator(l1MessagePrefix, start)
|
it := db.NewIterator(l1MessagePrefix, start)
|
||||||
keyLength := len(l1MessagePrefix) + 8
|
keyLength := len(l1MessagePrefix) + 8
|
||||||
|
maxQueueIndex := ReadHighestSyncedQueueIndex(db)
|
||||||
|
|
||||||
return L1MessageIterator{
|
return L1MessageIterator{
|
||||||
inner: it,
|
inner: it,
|
||||||
keyLength: keyLength,
|
keyLength: keyLength,
|
||||||
|
maxQueueIndex: maxQueueIndex,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,7 +181,7 @@ func (it *L1MessageIterator) Release() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadL1MessagesFrom retrieves up to `maxCount` L1 messages starting at `startIndex`.
|
// ReadL1MessagesFrom retrieves up to `maxCount` L1 messages starting at `startIndex`.
|
||||||
func ReadL1MessagesFrom(db ethdb.Iteratee, startIndex, maxCount uint64) []types.L1MessageTx {
|
func ReadL1MessagesFrom(db ethdb.Database, startIndex, maxCount uint64) []types.L1MessageTx {
|
||||||
msgs := make([]types.L1MessageTx, 0, maxCount)
|
msgs := make([]types.L1MessageTx, 0, maxCount)
|
||||||
it := IterateL1MessagesFrom(db, startIndex)
|
it := IterateL1MessagesFrom(db, startIndex)
|
||||||
defer it.Release()
|
defer it.Release()
|
||||||
|
|
@ -170,6 +206,10 @@ func ReadL1MessagesFrom(db ethdb.Iteratee, startIndex, maxCount uint64) []types.
|
||||||
msgs = append(msgs, msg)
|
msgs = append(msgs, msg)
|
||||||
index += 1
|
index += 1
|
||||||
count -= 1
|
count -= 1
|
||||||
|
|
||||||
|
if msg.QueueIndex == it.maxQueueIndex {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return msgs
|
return msgs
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,11 @@ func TestReadWriteL1Message(t *testing.T) {
|
||||||
if got == nil || got.QueueIndex != queueIndex {
|
if got == nil || got.QueueIndex != queueIndex {
|
||||||
t.Fatal("L1 message mismatch", "expected", queueIndex, "got", got)
|
t.Fatal("L1 message mismatch", "expected", queueIndex, "got", got)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
max := ReadHighestSyncedQueueIndex(db)
|
||||||
|
if max != 123 {
|
||||||
|
t.Fatal("max index mismatch", "expected", 123, "got", max)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIterateL1Message(t *testing.T) {
|
func TestIterateL1Message(t *testing.T) {
|
||||||
|
|
@ -62,6 +67,11 @@ func TestIterateL1Message(t *testing.T) {
|
||||||
db := NewMemoryDatabase()
|
db := NewMemoryDatabase()
|
||||||
WriteL1Messages(db, msgs)
|
WriteL1Messages(db, msgs)
|
||||||
|
|
||||||
|
max := ReadHighestSyncedQueueIndex(db)
|
||||||
|
if max != 1000 {
|
||||||
|
t.Fatal("max index mismatch", "expected", 1000, "got", max)
|
||||||
|
}
|
||||||
|
|
||||||
it := IterateL1MessagesFrom(db, 103)
|
it := IterateL1MessagesFrom(db, 103)
|
||||||
defer it.Release()
|
defer it.Release()
|
||||||
|
|
||||||
|
|
@ -125,3 +135,25 @@ func TestReadWriteLastL1MessageInL2Block(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIterationStopsAtMaxQueueIndex(t *testing.T) {
|
||||||
|
msgs := []types.L1MessageTx{
|
||||||
|
newL1MessageTx(100),
|
||||||
|
newL1MessageTx(101),
|
||||||
|
newL1MessageTx(102),
|
||||||
|
newL1MessageTx(103),
|
||||||
|
}
|
||||||
|
|
||||||
|
db := NewMemoryDatabase()
|
||||||
|
WriteL1Messages(db, msgs)
|
||||||
|
|
||||||
|
// artificially change max index from 103 to 102
|
||||||
|
WriteHighestSyncedQueueIndex(db, 102)
|
||||||
|
|
||||||
|
// iteration should terminate at 102 and not read 103
|
||||||
|
got := ReadL1MessagesFrom(db, 100, 10)
|
||||||
|
|
||||||
|
if len(got) != 3 {
|
||||||
|
t.Fatal("Invalid length", "expected", 3, "got", len(got))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ var (
|
||||||
syncedL1BlockNumberKey = []byte("LastSyncedL1BlockNumber")
|
syncedL1BlockNumberKey = []byte("LastSyncedL1BlockNumber")
|
||||||
l1MessagePrefix = []byte("l1") // l1MessagePrefix + queueIndex (uint64 big endian) -> L1MessageTx
|
l1MessagePrefix = []byte("l1") // l1MessagePrefix + queueIndex (uint64 big endian) -> L1MessageTx
|
||||||
firstQueueIndexNotInL2BlockPrefix = []byte("q") // firstQueueIndexNotInL2BlockPrefix + L2 block hash -> enqueue index
|
firstQueueIndexNotInL2BlockPrefix = []byte("q") // firstQueueIndexNotInL2BlockPrefix + L2 block hash -> enqueue index
|
||||||
|
highestSyncedQueueIndexKey = []byte("HighestSyncedQueueIndex")
|
||||||
|
|
||||||
// Row consumption
|
// Row consumption
|
||||||
rowConsumptionPrefix = []byte("rc") // rowConsumptionPrefix + hash -> row consumption by block
|
rowConsumptionPrefix = []byte("rc") // rowConsumptionPrefix + hash -> row consumption by block
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import (
|
||||||
const (
|
const (
|
||||||
VersionMajor = 4 // Major version component of the current release
|
VersionMajor = 4 // Major version component of the current release
|
||||||
VersionMinor = 4 // Minor version component of the current release
|
VersionMinor = 4 // Minor version component of the current release
|
||||||
VersionPatch = 13 // Patch version component of the current release
|
VersionPatch = 14 // Patch version component of the current release
|
||||||
VersionMeta = "sepolia" // Version metadata to append to the version string
|
VersionMeta = "sepolia" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue