Skip to content

Commit

Permalink
Add support for different finalities
Browse files Browse the repository at this point in the history
  • Loading branch information
arnaubennassar authored and Stefan-Ethernal committed Sep 17, 2024
1 parent 912b63e commit 93ba8aa
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 13 deletions.
39 changes: 39 additions & 0 deletions etherman/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package etherman

import (
"fmt"
"math/big"
"time"

"github.com/0xPolygon/cdk-contracts-tooling/contracts/elderberry/polygonvalidiumetrog"
Expand Down Expand Up @@ -89,3 +91,40 @@ type ForkID struct {
ForkID uint64
Version string
}

type BlockNumberFinality string

const (
FinalizedBlock = BlockNumberFinality("FinalizedBlock")
SafeBlock = BlockNumberFinality("SafeBlock")
PendingBlock = BlockNumberFinality("PendingBlock")
LatestBlock = BlockNumberFinality("LatestBlock")
EarliestBlock = BlockNumberFinality("EarliestBlock")
)

func (b *BlockNumberFinality) ToBlockNum() (*big.Int, error) {
switch *b {
case FinalizedBlock:
return big.NewInt(int64(Finalized)), nil
case SafeBlock:
return big.NewInt(int64(Safe)), nil
case PendingBlock:
return big.NewInt(int64(Pending)), nil
case LatestBlock:
return big.NewInt(int64(Latest)), nil
case EarliestBlock:
return big.NewInt(int64(Earliest)), nil
default:
return nil, fmt.Errorf("invalid finality keyword: %s", string(*b))
}
}

type BlockNumber int64

const (
Finalized = BlockNumber(-5)
Safe = BlockNumber(-4)
Pending = BlockNumber(-3)
Latest = BlockNumber(-2)
Earliest = BlockNumber(-1)
)
14 changes: 11 additions & 3 deletions localbridgesync/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonzkevmbridge"
"github.com/0xPolygon/cdk-contracts-tooling/contracts/etrog/polygonzkevmbridgev2"
"github.com/0xPolygon/cdk/etherman"
"github.com/0xPolygon/cdk/log"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
Expand Down Expand Up @@ -49,6 +50,7 @@ func newDownloader(
bridgeAddr common.Address,
ethClient EthClienter,
syncBlockChunkSize uint64,
blockFinalityType etherman.BlockNumberFinality,
) (*downloader, error) {
bridgeContractV1, err := polygonzkevmbridge.NewPolygonzkevmbridge(bridgeAddr, ethClient)
if err != nil {
Expand All @@ -58,13 +60,18 @@ func newDownloader(
if err != nil {
return nil, err
}
finality, err := blockFinalityType.ToBlockNum()
if err != nil {
return nil, err
}
return &downloader{
syncBlockChunkSize: syncBlockChunkSize,
downloaderInterface: &downloaderImplementation{
bridgeAddr: bridgeAddr,
bridgeContractV1: bridgeContractV1,
bridgeContractV2: bridgeContractV2,
ethClient: ethClient,
blockFinality: finality,
},
}, nil
}
Expand Down Expand Up @@ -110,20 +117,21 @@ type downloaderImplementation struct {
bridgeContractV1 *polygonzkevmbridge.Polygonzkevmbridge
bridgeContractV2 *polygonzkevmbridgev2.Polygonzkevmbridgev2
ethClient EthClienter
blockFinality *big.Int
}

func (d *downloaderImplementation) waitForNewBlocks(ctx context.Context, lastBlockSeen uint64) (newLastBlock uint64) {
attempts := 0
for {
lastBlock, err := d.ethClient.BlockNumber(ctx)
header, err := d.ethClient.HeaderByNumber(ctx, d.blockFinality)
if err != nil {
attempts++
log.Error("error geting last block num from eth client: ", err)
retryHandler("waitForNewBlocks", attempts)
continue
}
if lastBlock > lastBlockSeen {
return lastBlock
if header.Number.Uint64() > lastBlockSeen {
return header.Number.Uint64()
}
time.Sleep(waitForNewBlocksPeriod)
}
Expand Down
27 changes: 18 additions & 9 deletions localbridgesync/downloader_test.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"
"github.com/0xPolygon/cdk/etherman"
"github.com/0xPolygon/cdk/log"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
Expand Down Expand Up @@ -37,7 +38,7 @@ func TestGetEventsByBlockRange(t *testing.T) {
testCases := []testCase{}
clientMock := NewL2Mock(t)
ctx := context.Background()
d, err := newDownloader(contractAddr, clientMock, syncBlockChunck)
d, err := newDownloader(contractAddr, clientMock, syncBlockChunck, etherman.LatestBlock)
require.NoError(t, err)

// case 0: single block, no events
Expand Down Expand Up @@ -279,7 +280,7 @@ func TestDownload(t *testing.T) {
ctx1, cancel := context.WithCancel(ctx)
expectedBlocks := []block{}
clientMock := NewL2Mock(t)
dwnldr, err := newDownloader(contractAddr, clientMock, syncBlockChunck)
dwnldr, err := newDownloader(contractAddr, clientMock, syncBlockChunck, etherman.LatestBlock)
require.NoError(t, err)
dwnldr.downloaderInterface = d

Expand Down Expand Up @@ -404,25 +405,33 @@ func TestWaitForNewBlocks(t *testing.T) {
retryAfterErrorPeriod = time.Millisecond * 100
clientMock := NewL2Mock(t)
ctx := context.Background()
d, err := newDownloader(contractAddr, clientMock, syncBlockChunck)
d, err := newDownloader(contractAddr, clientMock, syncBlockChunck, etherman.LatestBlock)
require.NoError(t, err)

// at first attempt
currentBlock := uint64(5)
expectedBlock := uint64(6)
clientMock.On("BlockNumber", ctx).Return(expectedBlock, nil).Once()
clientMock.On("HeaderByNumber", ctx, mock.Anything).Return(&types.Header{
Number: big.NewInt(6),
}, nil).Once()
actualBlock := d.waitForNewBlocks(ctx, currentBlock)
assert.Equal(t, expectedBlock, actualBlock)

// 2 iterations
clientMock.On("BlockNumber", ctx).Return(currentBlock, nil).Once()
clientMock.On("BlockNumber", ctx).Return(expectedBlock, nil).Once()
clientMock.On("HeaderByNumber", ctx, mock.Anything).Return(&types.Header{
Number: big.NewInt(5),
}, nil).Once()
clientMock.On("HeaderByNumber", ctx, mock.Anything).Return(&types.Header{
Number: big.NewInt(6),
}, nil).Once()
actualBlock = d.waitForNewBlocks(ctx, currentBlock)
assert.Equal(t, expectedBlock, actualBlock)

// after error from client
clientMock.On("BlockNumber", ctx).Return(uint64(0), errors.New("foo")).Once()
clientMock.On("BlockNumber", ctx).Return(expectedBlock, nil).Once()
clientMock.On("HeaderByNumber", ctx, mock.Anything).Return(nil, errors.New("foo")).Once()
clientMock.On("HeaderByNumber", ctx, mock.Anything).Return(&types.Header{
Number: big.NewInt(6),
}, nil).Once()
actualBlock = d.waitForNewBlocks(ctx, currentBlock)
assert.Equal(t, expectedBlock, actualBlock)
}
Expand All @@ -431,7 +440,7 @@ func TestGetBlockHeader(t *testing.T) {
retryAfterErrorPeriod = time.Millisecond * 100
clientMock := NewL2Mock(t)
ctx := context.Background()
d, err := newDownloader(contractAddr, clientMock, syncBlockChunck)
d, err := newDownloader(contractAddr, clientMock, syncBlockChunck, etherman.LatestBlock)
require.NoError(t, err)

blockNum := uint64(5)
Expand Down
4 changes: 3 additions & 1 deletion localbridgesync/localbridgesync.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package localbridgesync
import (
"time"

"github.com/0xPolygon/cdk/etherman"
"github.com/0xPolygon/cdk/log"
"github.com/ethereum/go-ethereum/common"
)
Expand All @@ -21,14 +22,15 @@ func New(
dbPath string,
bridge common.Address,
syncBlockChunkSize uint64,
blockFinalityType etherman.BlockNumberFinality,
rd ReorgDetector,
l2Client EthClienter,
) (*LocalBridgeSync, error) {
p, err := newProcessor(dbPath)
if err != nil {
return nil, err
}
dwn, err := newDownloader(bridge, l2Client, syncBlockChunkSize)
dwn, err := newDownloader(bridge, l2Client, syncBlockChunkSize, blockFinalityType)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 93ba8aa

Please sign in to comment.