Skip to content
This repository has been archived by the owner on Feb 17, 2025. It is now read-only.

#3514 Fix l1 info root after reorg #3515

Merged
merged 8 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion aggregator/aggregator.go
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ func (a *Aggregator) buildInputProver(ctx context.Context, batchToVerify *state.
if err != nil {
return nil, err
}
leaves, err := a.State.GetLeafsByL1InfoRoot(ctx, *l1InfoRoot, nil)
leaves, err := a.State.GetLeavesByL1InfoRoot(ctx, *l1InfoRoot, nil)
if err != nil {
return nil, err
}
Expand Down
10 changes: 5 additions & 5 deletions aggregator/aggregator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@ func TestTryGenerateBatchProof(t *testing.T) {
}
m.etherman.On("GetLatestBlockHeader", mock.Anything).Return(&types.Header{Number: new(big.Int).SetUint64(1)}, nil).Once()
m.stateMock.On("GetVirtualBatch", mock.Anything, lastVerifiedBatchNum+1, nil).Return(&vb, nil).Twice()
m.stateMock.On("GetLeafsByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice()
m.stateMock.On("GetLeavesByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice()
expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve)
require.NoError(err)
m.proverMock.On("BatchProof", expectedInputProver).Return(nil, errBanana).Once()
Expand Down Expand Up @@ -844,7 +844,7 @@ func TestTryGenerateBatchProof(t *testing.T) {
}
m.etherman.On("GetLatestBlockHeader", mock.Anything).Return(&types.Header{Number: new(big.Int).SetUint64(1)}, nil).Once()
m.stateMock.On("GetVirtualBatch", mock.Anything, lastVerifiedBatchNum+1, nil).Return(&vb, nil).Twice()
m.stateMock.On("GetLeafsByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice()
m.stateMock.On("GetLeavesByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice()
expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve)
require.NoError(err)
m.proverMock.On("BatchProof", expectedInputProver).Return(&proofID, nil).Once()
Expand Down Expand Up @@ -888,7 +888,7 @@ func TestTryGenerateBatchProof(t *testing.T) {
}
m.etherman.On("GetLatestBlockHeader", mock.Anything).Return(&types.Header{Number: new(big.Int).SetUint64(1)}, nil).Once()
m.stateMock.On("GetVirtualBatch", mock.Anything, lastVerifiedBatchNum+1, nil).Return(&vb, nil).Twice()
m.stateMock.On("GetLeafsByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice()
m.stateMock.On("GetLeavesByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice()
expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve)
require.NoError(err)
m.proverMock.On("BatchProof", expectedInputProver).Return(&proofID, nil).Once()
Expand Down Expand Up @@ -932,7 +932,7 @@ func TestTryGenerateBatchProof(t *testing.T) {
}
m.etherman.On("GetLatestBlockHeader", mock.Anything).Return(&types.Header{Number: new(big.Int).SetUint64(1)}, nil).Once()
m.stateMock.On("GetVirtualBatch", mock.Anything, lastVerifiedBatchNum+1, nil).Return(&vb, nil).Twice()
m.stateMock.On("GetLeafsByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice()
m.stateMock.On("GetLeavesByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice()
expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve)
require.NoError(err)
m.proverMock.On("BatchProof", expectedInputProver).Return(&proofID, nil).Once()
Expand Down Expand Up @@ -989,7 +989,7 @@ func TestTryGenerateBatchProof(t *testing.T) {
TimestampBatchEtrog: &t,
}
m.stateMock.On("GetVirtualBatch", mock.Anything, lastVerifiedBatchNum+1, nil).Return(&vb, nil).Twice()
m.stateMock.On("GetLeafsByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice()
m.stateMock.On("GetLeavesByL1InfoRoot", mock.Anything, *vb.L1InfoRoot, nil).Return([]state.L1InfoTreeExitRootStorageEntry{}, nil).Twice()
expectedInputProver, err := a.buildInputProver(context.Background(), &batchToProve)
require.NoError(err)
m.proverMock.On("BatchProof", expectedInputProver).Return(&proofID, nil).Once()
Expand Down
2 changes: 1 addition & 1 deletion aggregator/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type stateInterface interface {
CleanupGeneratedProofs(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) error
CleanupLockedProofs(ctx context.Context, duration string, dbTx pgx.Tx) (int64, error)
GetL1InfoRootLeafByIndex(ctx context.Context, l1InfoTreeIndex uint32, dbTx pgx.Tx) (state.L1InfoTreeExitRootStorageEntry, error)
GetLeafsByL1InfoRoot(ctx context.Context, l1InfoRoot common.Hash, dbTx pgx.Tx) ([]state.L1InfoTreeExitRootStorageEntry, error)
GetLeavesByL1InfoRoot(ctx context.Context, l1InfoRoot common.Hash, dbTx pgx.Tx) ([]state.L1InfoTreeExitRootStorageEntry, error)
GetVirtualBatchParentHash(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (common.Hash, error)
GetForcedBatchParentHash(ctx context.Context, forcedBatchNumber uint64, dbTx pgx.Tx) (common.Hash, error)
GetVirtualBatch(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.VirtualBatch, error)
Expand Down
6 changes: 3 additions & 3 deletions aggregator/mocks/mock_state.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 19 additions & 1 deletion l1infotree/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,32 @@
var err error
mt.siblings, mt.currentRoot, err = mt.initSiblings(initialLeaves)
if err != nil {
log.Error("error initializing si siblings. Error: ", err)
log.Error("error initializing siblings. Error: ", err)
return nil, err
}
log.Debug("Initial count: ", mt.count)
log.Debug("Initial root: ", mt.currentRoot)
return mt, nil
}

func (mt *L1InfoTree) ResetL1InfoTree(initialLeaves [][32]byte) (*L1InfoTree, error) {

Check failure on line 37 in l1infotree/tree.go

View workflow job for this annotation

GitHub Actions / lint

exported: exported method L1InfoTree.ResetL1InfoTree should have comment or be unexported (revive)
newMT := &L1InfoTree{
zeroHashes: mt.zeroHashes,
height: mt.height,
count: uint32(len(initialLeaves)),
}
var err error
newMT.siblings, newMT.currentRoot, err = newMT.initSiblings(initialLeaves)
if err != nil {
log.Error("error initializing siblings. Error: ", err)
return nil, err
}
log.Debug("Reset initial count: ", newMT.count)
log.Debug("Reset initial root: ", newMT.currentRoot)
mt = newMT
return newMT, nil
}

func buildIntermediate(leaves [][32]byte) ([][][]byte, [][32]byte) {
var (
nodes [][][]byte
Expand Down
2 changes: 1 addition & 1 deletion state/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ type storage interface {
GetRawBatchTimestamps(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*time.Time, *time.Time, error)
GetL1InfoRootLeafByL1InfoRoot(ctx context.Context, l1InfoRoot common.Hash, dbTx pgx.Tx) (L1InfoTreeExitRootStorageEntry, error)
GetL1InfoRootLeafByIndex(ctx context.Context, l1InfoTreeIndex uint32, dbTx pgx.Tx) (L1InfoTreeExitRootStorageEntry, error)
GetLeafsByL1InfoRoot(ctx context.Context, l1InfoRoot common.Hash, dbTx pgx.Tx) ([]L1InfoTreeExitRootStorageEntry, error)
GetLeavesByL1InfoRoot(ctx context.Context, l1InfoRoot common.Hash, dbTx pgx.Tx) ([]L1InfoTreeExitRootStorageEntry, error)
GetBlockByNumber(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (*Block, error)
GetVirtualBatchParentHash(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (common.Hash, error)
GetForcedBatchParentHash(ctx context.Context, forcedBatchNumber uint64, dbTx pgx.Tx) (common.Hash, error)
Expand Down
18 changes: 18 additions & 0 deletions state/l1infotree.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,24 @@
return &entry, nil
}

func (s *State) ResetL1InfoTree(ctx context.Context, dbTx pgx.Tx) error {

Check failure on line 90 in state/l1infotree.go

View workflow job for this annotation

GitHub Actions / lint

exported: exported method State.ResetL1InfoTree should have comment or be unexported (revive)
allLeaves, err := s.GetAllL1InfoRootEntries(ctx, dbTx)
if err != nil {
log.Error("error getting all leaves to reset l1InfoTree. Error: ", err)
return err
}
var leaves [][32]byte
for _, leaf := range allLeaves {
leaves = append(leaves, leaf.Hash())
}
s.l1InfoTree, err = s.l1InfoTree.ResetL1InfoTree(leaves)
if err != nil {
log.Error("error resetting l1InfoTree. Error: ", err)
return err
}
return nil
}

// GetCurrentL1InfoRoot Return current L1InfoRoot
func (s *State) GetCurrentL1InfoRoot(ctx context.Context, dbTx pgx.Tx) (common.Hash, error) {
err := s.buildL1InfoTreeCacheIfNeed(ctx, dbTx)
Expand Down
22 changes: 11 additions & 11 deletions state/mocks/mock_storage.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion state/pgstatestorage/l1infotree.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (p *PostgresStorage) GetL1InfoRootLeafByIndex(ctx context.Context, l1InfoTr
return entry, nil
}

func (p *PostgresStorage) GetLeafsByL1InfoRoot(ctx context.Context, l1InfoRoot common.Hash, dbTx pgx.Tx) ([]state.L1InfoTreeExitRootStorageEntry, error) {
func (p *PostgresStorage) GetLeavesByL1InfoRoot(ctx context.Context, l1InfoRoot common.Hash, dbTx pgx.Tx) ([]state.L1InfoTreeExitRootStorageEntry, error) {
// TODO: Optimize this query
const getLeafsByL1InfoRootSQL = `SELECT block_num, timestamp, mainnet_exit_root, rollup_exit_root, global_exit_root, prev_block_hash, l1_info_root, l1_info_tree_index
FROM state.exit_root
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ func (p *ProcessorL1SequenceBatchesEtrog) checkTrustedState(ctx context.Context,
reason := reorgReasons.String()

if p.sync.IsTrustedSequencer() {
log.Errorf("TRUSTED REORG DETECTED! Batch: %d reson:%s", batch.BatchNumber, reason)
log.Errorf("TRUSTED REORG DETECTED! Batch: %d reason:%s", batch.BatchNumber, reason)
// Halt function never have to return! it must blocks the process
p.halt(ctx, fmt.Errorf("TRUSTED REORG DETECTED! Batch: %d", batch.BatchNumber))
log.Errorf("CRITICAL!!!: Never have to execute this code. Halt function never have to return! it must blocks the process")
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions synchronizer/common/syncinterfaces/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type StateFullInterface interface {
AddForcedBatch(ctx context.Context, forcedBatch *state.ForcedBatch, dbTx pgx.Tx) error
AddBlock(ctx context.Context, block *state.Block, dbTx pgx.Tx) error
Reset(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) error
ResetL1InfoTree(ctx context.Context, dbTx pgx.Tx) error
GetPreviousBlock(ctx context.Context, offset uint64, dbTx pgx.Tx) (*state.Block, error)
GetLastBatchNumber(ctx context.Context, dbTx pgx.Tx) (uint64, error)
GetBatchByNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*state.Batch, error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,13 @@ func (b *SyncTrustedBatchExecutorForEtrog) FullProcess(ctx context.Context, data
return nil, err
}

leafs, l1InfoRoot, _, err := b.state.GetL1InfoTreeDataFromBatchL2Data(ctx, data.TrustedBatch.BatchL2Data, dbTx)
leaves, l1InfoRoot, _, err := b.state.GetL1InfoTreeDataFromBatchL2Data(ctx, data.TrustedBatch.BatchL2Data, dbTx)
if err != nil {
log.Errorf("%s error getting GetL1InfoTreeDataFromBatchL2Data: %v. Error:%w", data.DebugPrefix, l1InfoRoot, err)
return nil, err
}
debugStr := data.DebugPrefix
processBatchResp, err := b.processAndStoreTxs(ctx, b.getProcessRequest(data, leafs, l1InfoRoot), dbTx, debugStr)
processBatchResp, err := b.processAndStoreTxs(ctx, b.getProcessRequest(data, leaves, l1InfoRoot), dbTx, debugStr)
if err != nil {
log.Error("%s error procesingAndStoringTxs. Error: ", debugStr, err)
return nil, err
Expand Down Expand Up @@ -197,15 +197,15 @@ func (b *SyncTrustedBatchExecutorForEtrog) IncrementalProcess(ctx context.Contex
return nil, err
}

leafs, l1InfoRoot, _, err := b.state.GetL1InfoTreeDataFromBatchL2Data(ctx, PartialBatchL2Data, dbTx)
leaves, l1InfoRoot, _, err := b.state.GetL1InfoTreeDataFromBatchL2Data(ctx, PartialBatchL2Data, dbTx)
if err != nil {
log.Errorf("%s error getting GetL1InfoTreeDataFromBatchL2Data: %v. Error:%w", data.DebugPrefix, l1InfoRoot, err)
// TODO: Need to refine, depending of the response of GetL1InfoTreeDataFromBatchL2Data
// if some leaf is missing, we need to resync from L1 to get the missing events and then process again
return nil, syncinterfaces.ErrMissingSyncFromL1
}
debugStr := fmt.Sprintf("%s: Batch %d:", data.Mode, uint64(data.TrustedBatch.Number))
processReq := b.getProcessRequest(data, leafs, l1InfoRoot)
processReq := b.getProcessRequest(data, leaves, l1InfoRoot)
processReq.Transactions = PartialBatchL2Data
processBatchResp, err := b.processAndStoreTxs(ctx, processReq, dbTx, debugStr)
if err != nil {
Expand Down
10 changes: 10 additions & 0 deletions synchronizer/synchronizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,16 @@ func (s *ClientSynchronizer) resetState(blockNumber uint64) error {
log.Error("error processing reorg on eth tx manager. Error: ", err)
return err
}
err = s.state.ResetL1InfoTree(s.ctx, dbTx)
if err != nil {
rollbackErr := dbTx.Rollback(s.ctx)
if rollbackErr != nil {
log.Errorf("error rolling back state when resetting l1InfoTree. BlockNumber: %d, rollbackErr: %s, error : %v", blockNumber, rollbackErr.Error(), err)
return rollbackErr
}
log.Error("error resetting the l1InfoTree. Error: ", err)
return err
}
err = dbTx.Commit(s.ctx)
if err != nil {
rollbackErr := dbTx.Rollback(s.ctx)
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/forced_batches_vector_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func LaunchTestForcedBatchesVectorFilesGroup(t *testing.T, vectorFilesDir string
}

log.Info("#######################")
log.Info("# Verifying new leafs #")
log.Info("# Verifying new leaves #")
log.Info("#######################")
merkleTree := opsman.State().GetTree()
for _, expectedNewLeaf := range testCase.ExpectedNewLeafs {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func TestStateTransition(t *testing.T) {

st := opsman.State()

// Check leafs
// Check leaves
l2Block, err := st.GetLastL2Block(ctx, nil)
require.NoError(t, err)
for addrStr, leaf := range testCase.ExpectedNewLeafs {
Expand Down
Loading
Loading