Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/l1bridge2infoindexsync #31

Merged
merged 57 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
30880cd
implementation completed, missing tests
arnaubennassar Jul 23, 2024
73128ae
WIP
arnaubennassar Jul 24, 2024
c7d159a
WIP
arnaubennassar Jul 24, 2024
5cc0c6f
WIP
arnaubennassar Jul 25, 2024
fd0eb73
sync refactor
arnaubennassar Jul 25, 2024
4bd7ef1
decouple sync processors from EVM
arnaubennassar Jul 25, 2024
80157a4
Add CLI for aggOracle
arnaubennassar Jul 26, 2024
08bb5f2
WIP
arnaubennassar Jul 26, 2024
11ec3af
wip
arnaubennassar Jul 26, 2024
f6bf0ad
WIP
arnaubennassar Jul 26, 2024
26ce165
start reorg detector
arnaubennassar Jul 26, 2024
4354830
fix docker
arnaubennassar Jul 26, 2024
f66c337
pass test with docker
arnaubennassar Jul 26, 2024
698f2bd
add TODO
arnaubennassar Jul 26, 2024
d88238b
go mod tidy
Stefan-Ethernal Jul 29, 2024
fc3df5e
Implement base addLeaf
arnaubennassar Jul 29, 2024
abf8be8
pass test vectors
arnaubennassar Jul 30, 2024
bfdc806
fix UT
arnaubennassar Jul 30, 2024
69d9139
Add PR review suggestions from Stefan-Ethernal
arnaubennassar Jul 30, 2024
b90342f
Fix conflicts
arnaubennassar Jul 30, 2024
b1a399b
fix UTs
arnaubennassar Jul 30, 2024
78a5cc8
Add PR review suggestions from Stefan-Ethernal
arnaubennassar Jul 30, 2024
024a57f
fix datacommittee_test deploying proxy contract
joanestebanr Jul 29, 2024
9ffbd57
fix UTs
arnaubennassar Jul 30, 2024
d5f517f
WIP
arnaubennassar Jul 31, 2024
c90f2d0
WIP
arnaubennassar Jul 31, 2024
4869094
abstract tree
arnaubennassar Jul 31, 2024
e971132
Merge pull request #29 from 0xPolygon/feature/rollupExitTree
arnaubennassar Jul 31, 2024
cc03adc
FIx conflict
arnaubennassar Jul 31, 2024
99180de
Fix UTs
arnaubennassar Jul 31, 2024
5f2c29f
Add PR review suggestions from joanestebanr
arnaubennassar Aug 1, 2024
db681b2
bring changes
arnaubennassar Aug 1, 2024
5d0c94f
Fix evmdownloader problems
arnaubennassar Aug 1, 2024
7665527
refactor tree add and rollback to be atomic
arnaubennassar Aug 1, 2024
1453bce
simplify l1infotree
arnaubennassar Aug 1, 2024
5f0d15a
implementation done, test WIP
arnaubennassar Aug 1, 2024
acd372e
pass E2E test
arnaubennassar Aug 2, 2024
ed3f001
Merge develop
arnaubennassar Aug 2, 2024
64cd1d4
remove outdated coment
arnaubennassar Aug 2, 2024
f2f2fda
make test shorter
arnaubennassar Aug 2, 2024
da78344
Add coments
arnaubennassar Aug 2, 2024
4c17d6e
WIP
arnaubennassar Aug 2, 2024
1430a70
added E2E test
arnaubennassar Aug 5, 2024
27aa35c
fix duplicated key case
arnaubennassar Aug 6, 2024
bd0036f
Feature/lastgersync (#33)
arnaubennassar Aug 13, 2024
6823610
Feature/rpc (#40)
arnaubennassar Aug 13, 2024
bc0e663
Fix conflicts
arnaubennassar Aug 13, 2024
f637a8d
add l1Info as part of the claim response
arnaubennassar Aug 13, 2024
a620cd6
increase time.sleep to pass UT on GHA
arnaubennassar Aug 13, 2024
29c8b74
apply requests from ToniRamirezM
arnaubennassar Aug 13, 2024
9b2b245
fix block finality config
arnaubennassar Aug 14, 2024
766aa4f
apply PR requests by Stefan-Ethernal
arnaubennassar Aug 19, 2024
9121c28
apply PR requests by goran-ethernal
arnaubennassar Aug 19, 2024
200479d
fix conflicts
arnaubennassar Aug 19, 2024
e124a9f
Fixing warnings and go mod tidy
Stefan-Ethernal Aug 19, 2024
028f85d
fix conflicts
arnaubennassar Aug 21, 2024
84fd550
fix UTs
arnaubennassar Aug 21, 2024
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
4 changes: 2 additions & 2 deletions aggoracle/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ var (
type Config struct {
TargetChainType TargetChainType `mapstructure:"TargetChainType"`
URLRPCL1 string `mapstructure:"URLRPCL1"`
// TODO: BlockFinality doesnt work as per the jsonschema
BlockFinality string `jsonschema:"enum=latest,enum=safe, enum=pending, enum=finalized" mapstructure:"BlockFinality"`
// BlockFinality indicates the status of the blocks that will be queried in order to sync
BlockFinality string `jsonschema:"enum=LatestBlock, enum=SafeBlock, enum=PendingBlock, enum=FinalizedBlock, enum=EarliestBlock" mapstructure:"BlockFinality"`
WaitPeriodNextGER types.Duration `mapstructure:"WaitPeriodNextGER"`
EVMSender chaingersender.EVMConfig `mapstructure:"EVMSender"`
}
179 changes: 3 additions & 176 deletions aggoracle/e2e_test.go
Original file line number Diff line number Diff line change
@@ -1,196 +1,23 @@
package aggoracle_test

import (
"context"
"errors"
"fmt"
"math/big"
"strconv"
"testing"
"time"

gerContractL1 "github.com/0xPolygon/cdk-contracts-tooling/contracts/manual/globalexitrootnopush0"
gerContractEVMChain "github.com/0xPolygon/cdk-contracts-tooling/contracts/manual/pessimisticglobalexitrootnopush0"
"github.com/0xPolygon/cdk/aggoracle"
"github.com/0xPolygon/cdk/aggoracle/chaingersender"
"github.com/0xPolygon/cdk/etherman"
"github.com/0xPolygon/cdk/l1infotreesync"
"github.com/0xPolygon/cdk/log"
"github.com/0xPolygon/cdk/reorgdetector"
ethtxmanager "github.com/0xPolygonHermez/zkevm-ethtx-manager/ethtxmanager"
"github.com/ethereum/go-ethereum"
"github.com/0xPolygon/cdk/test/helpers"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient/simulated"
mock "github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)

func TestEVM(t *testing.T) {
ctx := context.Background()
l1Client, syncer, gerL1Contract, authL1 := commonSetup(t)
sender := evmSetup(t)
oracle, err := aggoracle.New(sender, l1Client.Client(), syncer, etherman.LatestBlock, time.Millisecond)
require.NoError(t, err)
go oracle.Start(ctx)

runTest(t, gerL1Contract, sender, l1Client, authL1)
}

func commonSetup(t *testing.T) (
*simulated.Backend,
*l1infotreesync.L1InfoTreeSync,
*gerContractL1.Globalexitrootnopush0,
*bind.TransactOpts,
) {
// Config and spin up
ctx := context.Background()
// Simulated L1
privateKeyL1, err := crypto.GenerateKey()
require.NoError(t, err)
authL1, err := bind.NewKeyedTransactorWithChainID(privateKeyL1, big.NewInt(1337))
require.NoError(t, err)
l1Client, gerL1Addr, gerL1Contract, err := newSimulatedL1(authL1)
require.NoError(t, err)
// Reorg detector
dbPathReorgDetector := t.TempDir()
reorg, err := reorgdetector.New(ctx, l1Client.Client(), dbPathReorgDetector)
require.NoError(t, err)
// Syncer
dbPathSyncer := t.TempDir()
syncer, err := l1infotreesync.New(ctx, dbPathSyncer, gerL1Addr, common.Address{}, 10, etherman.LatestBlock, reorg, l1Client.Client(), time.Millisecond, 0, 100*time.Millisecond, 3)
require.NoError(t, err)
go syncer.Start(ctx)

return l1Client, syncer, gerL1Contract, authL1
}

func evmSetup(t *testing.T) aggoracle.ChainSender {
privateKeyL2, err := crypto.GenerateKey()
require.NoError(t, err)
authL2, err := bind.NewKeyedTransactorWithChainID(privateKeyL2, big.NewInt(1337))
require.NoError(t, err)
l2Client, gerL2Addr, _, err := newSimulatedEVMAggSovereignChain(authL2)
require.NoError(t, err)
ethTxManMock := aggoracle.NewEthTxManagerMock(t)
// id, err := c.ethTxMan.Add(ctx, &c.gerAddr, nil, big.NewInt(0), tx.Data(), c.gasOffset, nil)
ethTxManMock.On("Add", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Run(func(args mock.Arguments) {
ctx := context.Background()
nonce, err := l2Client.Client().PendingNonceAt(ctx, authL2.From)
if err != nil {
log.Error(err)
return
}
gas, err := l2Client.Client().EstimateGas(ctx, ethereum.CallMsg{
From: authL2.From,
To: args.Get(1).(*common.Address),
Value: big.NewInt(0),
Data: args.Get(4).([]byte),
})
if err != nil {
log.Error(err)
res, err := l2Client.Client().CallContract(ctx, ethereum.CallMsg{
From: authL2.From,
To: args.Get(1).(*common.Address),
Value: big.NewInt(0),
Data: args.Get(4).([]byte),
}, nil)
log.Debugf("contract call: %s", res)
if err != nil {
log.Error(err)
}
return
}
price, err := l2Client.Client().SuggestGasPrice(ctx)
if err != nil {
log.Error(err)
}
tx := types.NewTx(&types.LegacyTx{
To: args.Get(1).(*common.Address),
Nonce: nonce,
Value: big.NewInt(0),
Data: args.Get(4).([]byte),
Gas: gas,
GasPrice: price,
})
tx.Gas()
signedTx, err := authL2.Signer(authL2.From, tx)
if err != nil {
log.Error(err)
return
}
err = l2Client.Client().SendTransaction(ctx, signedTx)
if err != nil {
log.Error(err)
return
}
l2Client.Commit()
}).
Return(common.Hash{}, nil)
// res, err := c.ethTxMan.Result(ctx, id)
ethTxManMock.On("Result", mock.Anything, mock.Anything).
Return(ethtxmanager.MonitoredTxResult{Status: ethtxmanager.MonitoredTxStatusMined}, nil)
sender, err := chaingersender.NewEVMChainGERSender(gerL2Addr, authL2.From, l2Client.Client(), ethTxManMock, 0, time.Millisecond*50)
require.NoError(t, err)

return sender
}

func newSimulatedL1(auth *bind.TransactOpts) (
client *simulated.Backend,
gerAddr common.Address,
gerContract *gerContractL1.Globalexitrootnopush0,
err error,
) {
balance, _ := new(big.Int).SetString("10000000000000000000000000", 10) //nolint:gomnd
address := auth.From
genesisAlloc := map[common.Address]types.Account{
address: {
Balance: balance,
},
}
blockGasLimit := uint64(999999999999999999) //nolint:gomnd
client = simulated.NewBackend(genesisAlloc, simulated.WithBlockGasLimit(blockGasLimit))

gerAddr, _, gerContract, err = gerContractL1.DeployGlobalexitrootnopush0(auth, client.Client(), auth.From, auth.From)

client.Commit()
return
}

func newSimulatedEVMAggSovereignChain(auth *bind.TransactOpts) (
client *simulated.Backend,
gerAddr common.Address,
gerContract *gerContractEVMChain.Pessimisticglobalexitrootnopush0,
err error,
) {
balance, _ := new(big.Int).SetString("10000000000000000000000000", 10) //nolint:gomnd
address := auth.From
genesisAlloc := map[common.Address]types.Account{
address: {
Balance: balance,
},
}
blockGasLimit := uint64(999999999999999999) //nolint:gomnd
client = simulated.NewBackend(genesisAlloc, simulated.WithBlockGasLimit(blockGasLimit))

gerAddr, _, gerContract, err = gerContractEVMChain.DeployPessimisticglobalexitrootnopush0(auth, client.Client(), auth.From)
if err != nil {
return
}
client.Commit()

_GLOBAL_EXIT_ROOT_SETTER_ROLE := common.HexToHash("0x7b95520991dfda409891be0afa2635b63540f92ee996fda0bf695a166e5c5176")
_, err = gerContract.GrantRole(auth, _GLOBAL_EXIT_ROOT_SETTER_ROLE, auth.From)
client.Commit()
hasRole, _ := gerContract.HasRole(&bind.CallOpts{Pending: false}, _GLOBAL_EXIT_ROOT_SETTER_ROLE, auth.From)
if !hasRole {
err = errors.New("failed to set role")
}
return
env := helpers.SetupAggoracleWithEVMChain(t)
runTest(t, env.GERL1Contract, env.AggOracleSender, env.L1Client, env.AuthL1)
}

func runTest(
Expand Down
55 changes: 41 additions & 14 deletions bridgesync/bridgesync.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@ const (
downloadBufferSize = 1000
)

var (
retryAfterErrorPeriod = time.Second * 10
maxRetryAttemptsAfterError = 5
)

type LocalBridgeSync struct {
type BridgeSync struct {
processor *processor
driver *sync.EVMDriver
}
Expand All @@ -35,8 +30,11 @@ func NewL1(
rd sync.ReorgDetector,
ethClient EthClienter,
initialBlock uint64,
) (*LocalBridgeSync, error) {
return new(
waitForNewBlocksPeriod time.Duration,
retryAfterErrorPeriod time.Duration,
maxRetryAttemptsAfterError int,
) (*BridgeSync, error) {
return newBridgeSync(
ctx,
dbPath,
bridge,
Expand All @@ -46,6 +44,9 @@ func NewL1(
ethClient,
initialBlock,
bridgeSyncL1,
waitForNewBlocksPeriod,
retryAfterErrorPeriod,
maxRetryAttemptsAfterError,
)
}

Expand All @@ -59,8 +60,11 @@ func NewL2(
rd sync.ReorgDetector,
ethClient EthClienter,
initialBlock uint64,
) (*LocalBridgeSync, error) {
return new(
waitForNewBlocksPeriod time.Duration,
retryAfterErrorPeriod time.Duration,
maxRetryAttemptsAfterError int,
) (*BridgeSync, error) {
return newBridgeSync(
ctx,
dbPath,
bridge,
Expand All @@ -70,10 +74,13 @@ func NewL2(
ethClient,
initialBlock,
bridgeSyncL2,
waitForNewBlocksPeriod,
retryAfterErrorPeriod,
maxRetryAttemptsAfterError,
)
}

func new(
func newBridgeSync(
ctx context.Context,
dbPath string,
bridge common.Address,
Expand All @@ -83,7 +90,10 @@ func new(
ethClient EthClienter,
initialBlock uint64,
l1OrL2ID string,
) (*LocalBridgeSync, error) {
waitForNewBlocksPeriod time.Duration,
retryAfterErrorPeriod time.Duration,
maxRetryAttemptsAfterError int,
) (*BridgeSync, error) {
processor, err := newProcessor(ctx, dbPath, l1OrL2ID)
if err != nil {
return nil, err
Expand All @@ -110,6 +120,7 @@ func new(
return nil, err
}
downloader, err := sync.NewEVMDownloader(
l1OrL2ID,
ethClient,
syncBlockChunkSize,
blockFinalityType,
Expand All @@ -126,13 +137,29 @@ func new(
if err != nil {
return nil, err
}
return &LocalBridgeSync{
return &BridgeSync{
processor: processor,
driver: driver,
}, nil
}

// Start starts the synchronization process
func (s *LocalBridgeSync) Start(ctx context.Context) {
func (s *BridgeSync) Start(ctx context.Context) {
s.driver.Sync(ctx)
}

func (s *BridgeSync) GetLastProcessedBlock(ctx context.Context) (uint64, error) {
return s.processor.GetLastProcessedBlock(ctx)
}

func (s *BridgeSync) GetBridgeIndexByRoot(ctx context.Context, root common.Hash) (uint32, error) {
return s.processor.exitTree.GetIndexByRoot(ctx, root)
}

func (s *BridgeSync) GetClaimsAndBridges(ctx context.Context, fromBlock, toBlock uint64) ([]Event, error) {
return s.processor.GetClaimsAndBridges(ctx, fromBlock, toBlock)
}

func (s *BridgeSync) GetProof(ctx context.Context, depositCount uint32, localExitRoot common.Hash) ([32]common.Hash, error) {
return s.processor.exitTree.GetProof(ctx, depositCount, localExitRoot)
}
27 changes: 27 additions & 0 deletions bridgesync/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package bridgesync

import (
"github.com/0xPolygon/cdk/config/types"
"github.com/ethereum/go-ethereum/common"
)

type Config struct {
// DBPath path of the DB
DBPath string `mapstructure:"DBPath"`
// BlockFinality indicates the status of the blocks that will be queried in order to sync
BlockFinality string `jsonschema:"enum=LatestBlock, enum=SafeBlock, enum=PendingBlock, enum=FinalizedBlock, enum=EarliestBlock" mapstructure:"BlockFinality"`
// InitialBlockNum is the first block that will be queried when starting the synchronization from scratch.
// It should be a number equal or bellow the creation of the bridge contract
InitialBlockNum uint64 `mapstructure:"InitialBlockNum"`
// BridgeAddr is the address of the bridge smart contract
BridgeAddr common.Address `mapstructure:"BridgeAddr"`
// SyncBlockChunkSize is the amount of blocks that will be queried to the client on each request
SyncBlockChunkSize uint64 `mapstructure:"SyncBlockChunkSize"`
// RetryAfterErrorPeriod is the time that will be waited when an unexpected error happens before retry
RetryAfterErrorPeriod types.Duration `mapstructure:"RetryAfterErrorPeriod"`
// MaxRetryAttemptsAfterError is the maximum number of consecutive attempts that will happen before panicing.
// Any number smaller than zero will be considered as unlimited retries
MaxRetryAttemptsAfterError int `mapstructure:"MaxRetryAttemptsAfterError"`
// WaitForNewBlocksPeriod time that will be waited when the synchronizer has reached the latest block
WaitForNewBlocksPeriod types.Duration `mapstructure:"WaitForNewBlocksPeriod"`
}
7 changes: 1 addition & 6 deletions bridgesync/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package bridgesync
import (
"fmt"
"math/big"
"time"

"github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonzkevmbridge"
"github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonzkevmbridgev2"
Expand All @@ -15,10 +14,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)

const (
waitForNewBlocksPeriod = time.Millisecond * 100
)

var (
bridgeEventSignature = crypto.Keccak256Hash([]byte("BridgeEvent(uint8,uint32,address,uint32,address,uint256,bytes,uint32)"))
claimEventSignature = crypto.Keccak256Hash([]byte("ClaimEvent(uint256,uint32,address,address,uint256)"))
Expand Down Expand Up @@ -82,7 +77,7 @@ func buildAppender(client EthClienter, bridge common.Address) (sync.LogAppenderM
return nil
}

appender[claimEventSignature] = func(b *sync.EVMBlock, l types.Log) error {
appender[claimEventSignaturePreEtrog] = func(b *sync.EVMBlock, l types.Log) error {
claim, err := bridgeContractV1.ParseClaimEvent(l)
if err != nil {
return fmt.Errorf(
Expand Down
Loading
Loading