Skip to content

Commit

Permalink
feat: sync UpdateL1InfoTreeV2 (#145)
Browse files Browse the repository at this point in the history
* feat: sync UpdateL1InfoTreeV2

* fix linter

* use common hash instead of bytes 32

* imporve

* imporve

* imporve

* cover verify trusted aggregator event

* cover halted queries

* rm coverage file

* increase coverage

* moar coverage

* remove files that shouldnt be there

* do not cover smart contracts (generated bindings)

* feat: increase coverage (#159)

* apply pr suggestions

* add context done in handle newblock

* add context done in handle newblock

* add context done in handle newblock

* add context done in handle newblock

---------

Co-authored-by: Joan Esteban <[email protected]>
  • Loading branch information
arnaubennassar and joanestebanr authored Nov 8, 2024
1 parent 242f2f3 commit 67c37e4
Show file tree
Hide file tree
Showing 21 changed files with 650 additions and 50 deletions.
5 changes: 3 additions & 2 deletions bridgesync/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ func (p *processor) ProcessBlock(ctx context.Context, block sync.Block) error {
if err != nil {
return err
}
shouldRollback := true
defer func() {
if err != nil {
if shouldRollback {
if errRllbck := tx.Rollback(); errRllbck != nil {
log.Errorf("error while rolling back tx %v", errRllbck)
}
Expand Down Expand Up @@ -306,9 +307,9 @@ func (p *processor) ProcessBlock(ctx context.Context, block sync.Block) error {
if err := tx.Commit(); err != nil {
return err
}
shouldRollback = false

p.log.Debugf("processed %d events until block %d", len(block.Events), block.Num)

return nil
}

Expand Down
Binary file added bridgesync/test_db_path
Binary file not shown.
Binary file added bridgesync/test_db_path-shm
Binary file not shown.
Binary file added bridgesync/test_db_path-wal
Binary file not shown.
13 changes: 8 additions & 5 deletions l1infotreesync/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,20 @@ func buildAppender(client EthClienter, globalExitRoot,
return nil
}

// TODO: integrate this event to perform sanity checks
appender[updateL1InfoTreeSignatureV2] = func(b *sync.EVMBlock, l types.Log) error { //nolint:unparam
l1InfoTreeUpdate, err := ger.ParseUpdateL1InfoTreeV2(l)
appender[updateL1InfoTreeSignatureV2] = func(b *sync.EVMBlock, l types.Log) error {
l1InfoTreeUpdateV2, err := ger.ParseUpdateL1InfoTreeV2(l)
if err != nil {
return fmt.Errorf(
"error parsing log %+v using ger.ParseUpdateL1InfoTreeV2: %w",
l, err,
)
}
log.Infof("updateL1InfoTreeSignatureV2: expected root: %s",
common.BytesToHash(l1InfoTreeUpdate.CurrentL1InfoRoot[:]))
b.Events = append(b.Events, Event{UpdateL1InfoTreeV2: &UpdateL1InfoTreeV2{
CurrentL1InfoRoot: l1InfoTreeUpdateV2.CurrentL1InfoRoot,
LeafCount: l1InfoTreeUpdateV2.LeafCount,
Blockhash: common.BytesToHash(l1InfoTreeUpdateV2.Blockhash.Bytes()),
MinTimestamp: l1InfoTreeUpdateV2.MinTimestamp,
}})

return nil
}
Expand Down
9 changes: 6 additions & 3 deletions l1infotreesync/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
cdktypes "github.com/0xPolygon/cdk/config/types"
"github.com/0xPolygon/cdk/etherman"
"github.com/0xPolygon/cdk/l1infotreesync"
mocks_l1infotreesync "github.com/0xPolygon/cdk/l1infotreesync/mocks"
"github.com/0xPolygon/cdk/log"
"github.com/0xPolygon/cdk/reorgdetector"
"github.com/0xPolygon/cdk/test/contracts/verifybatchesmock"
"github.com/0xPolygon/cdk/test/helpers"
Expand Down Expand Up @@ -59,7 +61,7 @@ func TestE2E(t *testing.T) {
ctx, cancelCtx := context.WithCancel(context.Background())
dbPath := path.Join(t.TempDir(), "file::memory:?cache=shared")

rdm := l1infotreesync.NewReorgDetectorMock(t)
rdm := mocks_l1infotreesync.NewReorgDetectorMock(t)
rdm.On("Subscribe", mock.Anything).Return(&reorgdetector.Subscription{}, nil)
rdm.On("AddBlockToTrack", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)

Expand Down Expand Up @@ -180,12 +182,12 @@ func TestWithReorgs(t *testing.T) {

// Update L1 Info Tree + Rollup Exit Tree
newLocalExitRoot := common.HexToHash(strconv.Itoa(i) + "ffff" + strconv.Itoa(1))
_, err = verifySC.VerifyBatches(auth, rollupID, 0, newLocalExitRoot, common.Hash{}, true)
_, err = verifySC.VerifyBatchesTrustedAggregator(auth, rollupID, 0, newLocalExitRoot, common.Hash{}, true)
require.NoError(t, err)

// Update Rollup Exit Tree
newLocalExitRoot = common.HexToHash(strconv.Itoa(i) + "ffff" + strconv.Itoa(2))
_, err = verifySC.VerifyBatches(auth, rollupID, 0, newLocalExitRoot, common.Hash{}, false)
_, err = verifySC.VerifyBatchesTrustedAggregator(auth, rollupID, 0, newLocalExitRoot, common.Hash{}, false)
require.NoError(t, err)
}

Expand Down Expand Up @@ -310,6 +312,7 @@ func TestStressAndReorgs(t *testing.T) {
require.NoError(t, err)

block, err := client.Client().BlockByNumber(ctx, big.NewInt(int64(currentBlockNum-reorgSizeInBlocks)))
log.Debugf("reorging until block %d. Current block %d (before reorg)", block.NumberU64(), currentBlockNum)
require.NoError(t, err)
reorgFrom := block.Hash()
err = client.Fork(reorgFrom)
Expand Down
57 changes: 57 additions & 0 deletions l1infotreesync/l1infotreesync.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ func (s *L1InfoTreeSync) Start(ctx context.Context) {

// GetL1InfoTreeMerkleProof creates a merkle proof for the L1 Info tree
func (s *L1InfoTreeSync) GetL1InfoTreeMerkleProof(ctx context.Context, index uint32) (types.Proof, types.Root, error) {
if s.processor.halted {
return types.Proof{}, types.Root{}, sync.ErrInconsistentState
}
return s.processor.GetL1InfoTreeMerkleProof(ctx, index)
}

Expand All @@ -115,6 +118,9 @@ func (s *L1InfoTreeSync) GetRollupExitTreeMerkleProof(
networkID uint32,
root common.Hash,
) (types.Proof, error) {
if s.processor.halted {
return types.Proof{}, sync.ErrInconsistentState
}
if networkID == 0 {
return tree.EmptyProof, nil
}
Expand All @@ -135,38 +141,59 @@ func translateError(err error) error {
// - ErrBlockNotProcessed,
// - ErrNotFound
func (s *L1InfoTreeSync) GetLatestInfoUntilBlock(ctx context.Context, blockNum uint64) (*L1InfoTreeLeaf, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
leaf, err := s.processor.GetLatestInfoUntilBlock(ctx, blockNum)
return leaf, translateError(err)
}

// GetInfoByIndex returns the value of a leaf (not the hash) of the L1 info tree
func (s *L1InfoTreeSync) GetInfoByIndex(ctx context.Context, index uint32) (*L1InfoTreeLeaf, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
return s.processor.GetInfoByIndex(ctx, index)
}

// GetL1InfoTreeRootByIndex returns the root of the L1 info tree at the moment the leaf with the given index was added
func (s *L1InfoTreeSync) GetL1InfoTreeRootByIndex(ctx context.Context, index uint32) (types.Root, error) {
if s.processor.halted {
return types.Root{}, sync.ErrInconsistentState
}
return s.processor.l1InfoTree.GetRootByIndex(ctx, index)
}

// GetLastRollupExitRoot return the last rollup exit root processed
func (s *L1InfoTreeSync) GetLastRollupExitRoot(ctx context.Context) (types.Root, error) {
if s.processor.halted {
return types.Root{}, sync.ErrInconsistentState
}
return s.processor.rollupExitTree.GetLastRoot(nil)
}

// GetLastL1InfoTreeRoot return the last root and index processed from the L1 Info tree
func (s *L1InfoTreeSync) GetLastL1InfoTreeRoot(ctx context.Context) (types.Root, error) {
if s.processor.halted {
return types.Root{}, sync.ErrInconsistentState
}
return s.processor.l1InfoTree.GetLastRoot(nil)
}

// GetLastProcessedBlock return the last processed block
func (s *L1InfoTreeSync) GetLastProcessedBlock(ctx context.Context) (uint64, error) {
if s.processor.halted {
return 0, sync.ErrInconsistentState
}
return s.processor.GetLastProcessedBlock(ctx)
}

func (s *L1InfoTreeSync) GetLocalExitRoot(
ctx context.Context, networkID uint32, rollupExitRoot common.Hash,
) (common.Hash, error) {
if s.processor.halted {
return common.Hash{}, sync.ErrInconsistentState
}
if networkID == 0 {
return common.Hash{}, errors.New("network 0 is not a rollup, and it's not part of the rollup exit tree")
}
Expand All @@ -175,45 +202,75 @@ func (s *L1InfoTreeSync) GetLocalExitRoot(
}

func (s *L1InfoTreeSync) GetLastVerifiedBatches(rollupID uint32) (*VerifyBatches, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
return s.processor.GetLastVerifiedBatches(rollupID)
}

func (s *L1InfoTreeSync) GetFirstVerifiedBatches(rollupID uint32) (*VerifyBatches, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
return s.processor.GetFirstVerifiedBatches(rollupID)
}

func (s *L1InfoTreeSync) GetFirstVerifiedBatchesAfterBlock(rollupID uint32, blockNum uint64) (*VerifyBatches, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
return s.processor.GetFirstVerifiedBatchesAfterBlock(rollupID, blockNum)
}

func (s *L1InfoTreeSync) GetFirstL1InfoWithRollupExitRoot(rollupExitRoot common.Hash) (*L1InfoTreeLeaf, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
return s.processor.GetFirstL1InfoWithRollupExitRoot(rollupExitRoot)
}

func (s *L1InfoTreeSync) GetLastInfo() (*L1InfoTreeLeaf, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
return s.processor.GetLastInfo()
}

func (s *L1InfoTreeSync) GetFirstInfo() (*L1InfoTreeLeaf, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
return s.processor.GetFirstInfo()
}

func (s *L1InfoTreeSync) GetFirstInfoAfterBlock(blockNum uint64) (*L1InfoTreeLeaf, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
return s.processor.GetFirstInfoAfterBlock(blockNum)
}

func (s *L1InfoTreeSync) GetInfoByGlobalExitRoot(ger common.Hash) (*L1InfoTreeLeaf, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
return s.processor.GetInfoByGlobalExitRoot(ger)
}

// GetL1InfoTreeMerkleProofFromIndexToRoot creates a merkle proof for the L1 Info tree
func (s *L1InfoTreeSync) GetL1InfoTreeMerkleProofFromIndexToRoot(
ctx context.Context, index uint32, root common.Hash,
) (types.Proof, error) {
if s.processor.halted {
return types.Proof{}, sync.ErrInconsistentState
}
return s.processor.l1InfoTree.GetProof(ctx, index, root)
}

// GetInitL1InfoRootMap returns the initial L1 info root map, nil if no root map has been set
func (s *L1InfoTreeSync) GetInitL1InfoRootMap(ctx context.Context) (*L1InfoTreeInitial, error) {
if s.processor.halted {
return nil, sync.ErrInconsistentState
}
return s.processor.GetInitL1InfoRootMap(nil)
}
Loading

0 comments on commit 67c37e4

Please sign in to comment.