Skip to content

Commit

Permalink
First L1 Info tree in which bridge is included (#70)
Browse files Browse the repository at this point in the history
* wip

* wip

* WIP

* decoding direct and indeirecr assets and messages works

* connect everything

* fix building contract scripts

* fix building contract scripts

* wip

* WIP

* tree migrated to SQLite

* wip

* wip

* bridgesync working with sqlite

* pass tests

* minor cleaning

* add GetBlockByLER func

* handle err not found

* merge develop

* use memory for sqlite on the tests

* increase timestamp to pass UT

* review

* finished implementation

* replace l1bridge2infosync for rpc logic

* ut wip

* unit tests for new rpc funcs

* add UTs for new methods in the l1infotreesync processor

* fix UTs

* pass linter

* add PR requests

* add missing processor calls

* fixx linter

* rephrase binnary search formula

* rephrase binnary search formula
  • Loading branch information
arnaubennassar authored Sep 18, 2024
1 parent faf88bb commit f477aca
Show file tree
Hide file tree
Showing 42 changed files with 2,849 additions and 995 deletions.
3 changes: 2 additions & 1 deletion aggoracle/oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"math/big"
"time"

"github.com/0xPolygon/cdk/db"
"github.com/0xPolygon/cdk/etherman"
"github.com/0xPolygon/cdk/l1infotreesync"
"github.com/0xPolygon/cdk/log"
Expand Down Expand Up @@ -70,7 +71,7 @@ func (a *AggOracle) Start(ctx context.Context) {
case errors.Is(err, l1infotreesync.ErrBlockNotProcessed):
a.logger.Debugf("syncer is not ready for the block %d", blockNumToFetch)

case errors.Is(err, l1infotreesync.ErrNotFound):
case errors.Is(err, db.ErrNotFound):
blockNumToFetch = 0
a.logger.Debugf("syncer has not found any GER until block %d", blockNumToFetch)

Expand Down
15 changes: 10 additions & 5 deletions bridgesync/bridgesync.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func (s *BridgeSync) GetLastProcessedBlock(ctx context.Context) (uint64, error)
return s.processor.GetLastProcessedBlock(ctx)
}

func (s *BridgeSync) GetBridgeRootByHash(ctx context.Context, root common.Hash) (tree.Root, error) {
func (s *BridgeSync) GetBridgeRootByHash(ctx context.Context, root common.Hash) (*tree.Root, error) {
return s.processor.exitTree.GetRootByHash(ctx, root)
}

Expand All @@ -172,10 +172,7 @@ func (s *BridgeSync) GetBridges(ctx context.Context, fromBlock, toBlock uint64)
return s.processor.GetBridges(ctx, fromBlock, toBlock)
}

// GetProof retrieves the Merkle proof for the given deposit count and exit root.
func (s *BridgeSync) GetProof(
ctx context.Context, depositCount uint32, localExitRoot common.Hash,
) ([32]common.Hash, error) {
func (s *BridgeSync) GetProof(ctx context.Context, depositCount uint32, localExitRoot common.Hash) (tree.Proof, error) {
return s.processor.exitTree.GetProof(ctx, depositCount, localExitRoot)
}

Expand All @@ -186,3 +183,11 @@ func (p *processor) GetBlockByLER(ctx context.Context, ler common.Hash) (uint64,
}
return root.BlockNum, nil
}

func (s *BridgeSync) GetRootByLER(ctx context.Context, ler common.Hash) (*tree.Root, error) {
root, err := s.processor.exitTree.GetRootByHash(ctx, ler)
if err != nil {
return root, err
}
return root, nil
}
5 changes: 3 additions & 2 deletions bridgesync/claimcalldata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/0xPolygon/cdk/log"
"github.com/0xPolygon/cdk/test/contracts/claimmock"
"github.com/0xPolygon/cdk/test/contracts/claimmockcaller"
tree "github.com/0xPolygon/cdk/tree/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -52,11 +53,11 @@ func TestClaimCalldata(t *testing.T) {
require.NoError(t, err)

proofLocal := [32][32]byte{}
proofLocalH := [32]common.Hash{}
proofLocalH := tree.Proof{}
proofLocal[5] = common.HexToHash("beef")
proofLocalH[5] = common.HexToHash("beef")
proofRollup := [32][32]byte{}
proofRollupH := [32]common.Hash{}
proofRollupH := tree.Proof{}
proofRollup[4] = common.HexToHash("a1fa")
proofRollupH[4] = common.HexToHash("a1fa")
expectedClaim := Claim{
Expand Down
3 changes: 2 additions & 1 deletion bridgesync/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonzkevmbridge"
"github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonzkevmbridgev2"
rpcTypes "github.com/0xPolygon/cdk-rpc/types"
"github.com/0xPolygon/cdk/db"
"github.com/0xPolygon/cdk/sync"
tree "github.com/0xPolygon/cdk/tree/types"
"github.com/ethereum/go-ethereum"
Expand Down Expand Up @@ -181,7 +182,7 @@ func setClaimCalldata(client EthClienter, bridge common.Address, txHash common.H
callStack.Push(c)
}
}
return ErrNotFound
return db.ErrNotFound
}

func setClaimIfFoundOnInput(input []byte, claim *Claim) (bool, error) {
Expand Down
3 changes: 1 addition & 2 deletions bridgesync/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
var (
// ErrBlockNotProcessed indicates that the given block(s) have not been processed yet.
ErrBlockNotProcessed = errors.New("given block(s) have not been processed yet")
ErrNotFound = errors.New("not found")
)

// Bridge is the representation of a bridge event
Expand Down Expand Up @@ -184,7 +183,7 @@ func (p *processor) queryBlockRange(tx db.Querier, fromBlock, toBlock uint64, ta
`, table), fromBlock, toBlock)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNotFound
return nil, db.ErrNotFound
}
return nil, err
}
Expand Down
19 changes: 10 additions & 9 deletions claimsponsor/claimsponsor.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (
"time"

dbCommon "github.com/0xPolygon/cdk/common"
"github.com/0xPolygon/cdk/db"
"github.com/0xPolygon/cdk/log"
"github.com/0xPolygon/cdk/sync"
tree "github.com/0xPolygon/cdk/tree/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon-lib/kv/iter"
Expand All @@ -31,14 +33,13 @@ const (

var (
ErrInvalidClaim = errors.New("invalid claim")
ErrNotFound = errors.New("not found")
)

// Claim representation of a claim event
type Claim struct {
LeafType uint8
ProofLocalExitRoot [32]common.Hash
ProofRollupExitRoot [32]common.Hash
ProofLocalExitRoot tree.Proof
ProofRollupExitRoot tree.Proof
GlobalIndex *big.Int
MainnetExitRoot common.Hash
RollupExitRoot common.Hash
Expand Down Expand Up @@ -131,7 +132,7 @@ func (c *ClaimSponsor) Start(ctx context.Context) {
if err2 != nil {
err = err2
tx.Rollback()
if errors.Is(err, ErrNotFound) {
if errors.Is(err, db.ErrNotFound) {
c.logger.Debugf("queue is empty")
err = nil
time.Sleep(c.waitOnEmptyQueue)
Expand Down Expand Up @@ -242,7 +243,7 @@ func (c *ClaimSponsor) AddClaimToQueue(ctx context.Context, claim *Claim) error
}

_, err = getClaim(tx, claim.GlobalIndex)
if !errors.Is(err, ErrNotFound) {
if !errors.Is(err, db.ErrNotFound) {
if err != nil {
tx.Rollback()

Expand All @@ -264,7 +265,7 @@ func (c *ClaimSponsor) AddClaimToQueue(ctx context.Context, claim *Claim) error
var queuePosition uint64
lastQueuePosition, _, err := getLastQueueIndex(tx)
switch {
case errors.Is(err, ErrNotFound):
case errors.Is(err, db.ErrNotFound):
queuePosition = 0

case err != nil:
Expand Down Expand Up @@ -307,7 +308,7 @@ func (c *ClaimSponsor) getClaimByQueueIndex(ctx context.Context, queueIndex uint
return nil, err
}
if globalIndexBytes == nil {
return nil, ErrNotFound
return nil, db.ErrNotFound
}

return getClaim(tx, new(big.Int).SetBytes(globalIndexBytes))
Expand Down Expand Up @@ -345,7 +346,7 @@ func getIndex(iter iter.KV) (uint64, *big.Int, error) {
return 0, nil, err
}
if k == nil {
return 0, nil, ErrNotFound
return 0, nil, db.ErrNotFound
}
globalIndex := new(big.Int).SetBytes(v)

Expand All @@ -368,7 +369,7 @@ func getClaim(tx kv.Tx, globalIndex *big.Int) (*Claim, error) {
return nil, err
}
if claimBytes == nil {
return nil, ErrNotFound
return nil, db.ErrNotFound
}
claim := &Claim{}
err = json.Unmarshal(claimBytes, claim)
Expand Down
36 changes: 0 additions & 36 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/0xPolygon/cdk/etherman"
ethermanconfig "github.com/0xPolygon/cdk/etherman/config"
"github.com/0xPolygon/cdk/etherman/contracts"
"github.com/0xPolygon/cdk/l1bridge2infoindexsync"
"github.com/0xPolygon/cdk/l1infotreesync"
"github.com/0xPolygon/cdk/lastgersync"
"github.com/0xPolygon/cdk/log"
Expand Down Expand Up @@ -81,10 +80,6 @@ func start(cliCtx *cli.Context) error {
claimSponsor := runClaimSponsorIfNeeded(cliCtx.Context, components, l2Client, c.ClaimSponsor)
l1BridgeSync := runBridgeSyncL1IfNeeded(cliCtx.Context, components, c.BridgeL1Sync, reorgDetectorL1, l1Client)
l2BridgeSync := runBridgeSyncL2IfNeeded(cliCtx.Context, components, c.BridgeL2Sync, reorgDetectorL2, l2Client)
l1Bridge2InfoIndexSync := runL1Bridge2InfoIndexSyncIfNeeded(
cliCtx.Context, components, c.L1Bridge2InfoIndexSync,
l1BridgeSync, l1InfoTreeSync, l1Client,
)
lastGERSync := runLastGERSyncIfNeeded(
cliCtx.Context, components, c.LastGERSync, reorgDetectorL2, l2Client, l1InfoTreeSync,
)
Expand Down Expand Up @@ -115,7 +110,6 @@ func start(cliCtx *cli.Context) error {
c.Common.NetworkID,
claimSponsor,
l1InfoTreeSync,
l1Bridge2InfoIndexSync,
lastGERSync,
l1BridgeSync,
l2BridgeSync,
Expand Down Expand Up @@ -623,34 +617,6 @@ func runClaimSponsorIfNeeded(
return cs
}

func runL1Bridge2InfoIndexSyncIfNeeded(
ctx context.Context,
components []string,
cfg l1bridge2infoindexsync.Config,
l1BridgeSync *bridgesync.BridgeSync,
l1InfoTreeSync *l1infotreesync.L1InfoTreeSync,
l1Client *ethclient.Client,
) *l1bridge2infoindexsync.L1Bridge2InfoIndexSync {
if !isNeeded([]string{cdkcommon.RPC}, components) {
return nil
}
l1Bridge2InfoIndexSync, err := l1bridge2infoindexsync.New(
cfg.DBPath,
l1BridgeSync,
l1InfoTreeSync,
l1Client,
cfg.RetryAfterErrorPeriod.Duration,
cfg.MaxRetryAttemptsAfterError,
cfg.WaitForSyncersPeriod.Duration,
)
if err != nil {
log.Fatalf("error creating l1Bridge2InfoIndexSync: %s", err)
}
go l1Bridge2InfoIndexSync.Start(ctx)

return l1Bridge2InfoIndexSync
}

func runLastGERSyncIfNeeded(
ctx context.Context,
components []string,
Expand Down Expand Up @@ -751,7 +717,6 @@ func createRPC(
cdkNetworkID uint32,
sponsor *claimsponsor.ClaimSponsor,
l1InfoTree *l1infotreesync.L1InfoTreeSync,
l1Bridge2Index *l1bridge2infoindexsync.L1Bridge2InfoIndexSync,
injectedGERs *lastgersync.LastGERSync,
bridgeL1 *bridgesync.BridgeSync,
bridgeL2 *bridgesync.BridgeSync,
Expand All @@ -767,7 +732,6 @@ func createRPC(
cdkNetworkID,
sponsor,
l1InfoTree,
l1Bridge2Index,
injectedGERs,
bridgeL1,
bridgeL2,
Expand Down
5 changes: 0 additions & 5 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/0xPolygon/cdk/claimsponsor"
"github.com/0xPolygon/cdk/common"
ethermanconfig "github.com/0xPolygon/cdk/etherman/config"
"github.com/0xPolygon/cdk/l1bridge2infoindexsync"
"github.com/0xPolygon/cdk/l1infotreesync"
"github.com/0xPolygon/cdk/lastgersync"
"github.com/0xPolygon/cdk/log"
Expand Down Expand Up @@ -111,10 +110,6 @@ type Config struct {
// ClaimSponsor is the config for the claim sponsor
ClaimSponsor claimsponsor.EVMClaimSponsorConfig

// L1Bridge2InfoIndexSync is the config for the synchronizers that maintains the relation of
// bridge from L1 --> L1 Info tree index. Needed for the bridge service (RPC)
L1Bridge2InfoIndexSync l1bridge2infoindexsync.Config

// BridgeL1Sync is the configuration for the synchronizer of the bridge of the L1
BridgeL1Sync bridgesync.Config

Expand Down
6 changes: 0 additions & 6 deletions config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,6 @@ GasOffset = 0
L1ChainID = 1337
HTTPHeaders = []
[L1Bridge2InfoIndexSync]
DBPath = "/tmp/l1bridge2infoindexsync"
RetryAfterErrorPeriod = "1s"
MaxRetryAttemptsAfterError = -1
WaitForSyncersPeriod = "3s"
[BridgeL1Sync]
DBPath = "/tmp/bridgel1sync"
BlockFinality = "LatestBlock"
Expand Down
36 changes: 36 additions & 0 deletions db/meddler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func initMeddler() {
meddler.Register("bigint", BigIntMeddler{})
meddler.Register("merkleproof", MerkleProofMeddler{})
meddler.Register("hash", HashMeddler{})
meddler.Register("address", AddressMeddler{})
}

func SQLiteErr(err error) (*sqlite.Error, bool) {
Expand Down Expand Up @@ -176,3 +177,38 @@ func (b HashMeddler) PreWrite(fieldPtr interface{}) (saveValue interface{}, err
}
return field.Hex(), nil
}

// AddressMeddler encodes or decodes the field value to or from JSON
type AddressMeddler struct{}

// PreRead is called before a Scan operation for fields that have the ProofMeddler
func (b AddressMeddler) PreRead(fieldAddr interface{}) (scanTarget interface{}, err error) {
// give a pointer to a byte buffer to grab the raw data
return new(string), nil
}

// PostRead is called after a Scan operation for fields that have the ProofMeddler
func (b AddressMeddler) PostRead(fieldPtr, scanTarget interface{}) error {
ptr, ok := scanTarget.(*string)
if !ok {
return errors.New("scanTarget is not *string")
}
if ptr == nil {
return errors.New("AddressMeddler.PostRead: nil pointer")
}
field, ok := fieldPtr.(*common.Address)
if !ok {
return errors.New("fieldPtr is not common.Address")
}
*field = common.HexToAddress(*ptr)
return nil
}

// PreWrite is called before an Insert or Update operation for fields that have the ProofMeddler
func (b AddressMeddler) PreWrite(fieldPtr interface{}) (saveValue interface{}, err error) {
field, ok := fieldPtr.(common.Address)
if !ok {
return nil, errors.New("fieldPtr is not common.Address")
}
return field.Hex(), nil
}
12 changes: 12 additions & 0 deletions db/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package db

import (
"database/sql"
"errors"

_ "github.com/mattn/go-sqlite3"
)
Expand All @@ -10,6 +11,10 @@ const (
UniqueConstrain = 1555
)

var (
ErrNotFound = errors.New("not found")
)

// NewSQLiteDB creates a new SQLite DB
func NewSQLiteDB(dbPath string) (*sql.DB, error) {
initMeddler()
Expand All @@ -25,3 +30,10 @@ func NewSQLiteDB(dbPath string) (*sql.DB, error) {
`)
return db, err
}

func ReturnErrNotFound(err error) error {
if errors.Is(err, sql.ErrNoRows) {
return ErrNotFound
}
return err
}
15 changes: 0 additions & 15 deletions l1bridge2infoindexsync/config.go

This file was deleted.

Loading

0 comments on commit f477aca

Please sign in to comment.