Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

Commit

Permalink
test(driver): add more unit tests (#328)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidtaikocha authored Jul 25, 2023
1 parent a95380f commit 295f0ab
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
- name: Install protocol dependencies
working-directory: ${{ env.TAIKO_MONO_DIR }}
run: cd ./packages/protocol && pnpm install && ./script/download_solc.sh && forge install
run: cd ./packages/protocol && pnpm install --no-frozen-lockfile && ./script/download_solc.sh && forge install

- name: Build
working-directory: ${{ env.CLIENT_DIR }}
Expand Down
11 changes: 6 additions & 5 deletions driver/chain_syncer/calldata/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func NewSyncer(
progressTracker *beaconsync.SyncProgressTracker,
signalServiceAddress common.Address,
) (*Syncer, error) {
configs, err := rpc.TaikoL1.GetConfig(nil)
configs, err := rpc.TaikoL1.GetConfig(&bind.CallOpts{Context: ctx})
if err != nil {
return nil, fmt.Errorf("failed to get protocol configs: %w", err)
}
Expand Down Expand Up @@ -88,15 +88,16 @@ func (s *Syncer) ProcessL1Blocks(ctx context.Context, l1End *types.Header) error
if err != nil {
return err
}
s.state.SetL1Current(newL1Current)
s.lastInsertedBlockID = nil

log.Info(
"Reorg detected",
"oldL1Current", s.state.GetL1Current().Number,
"newL1Current", startHeight,
"l1Head", l1End.Number,
)

s.state.SetL1Current(newL1Current)
s.lastInsertedBlockID = nil
}

iter, err := eventIterator.NewBlockProposedIterator(ctx, &eventIterator.BlockProposedIteratorConfig{
Expand Down Expand Up @@ -324,14 +325,14 @@ func (s *Syncer) insertNewHead(
}
}

parentTimestamp, err := s.rpc.TaikoL2.ParentTimestamp(&bind.CallOpts{BlockNumber: parent.Number})
parentTimestamp, err := s.rpc.TaikoL2.ParentTimestamp(&bind.CallOpts{BlockNumber: parent.Number, Context: ctx})
if err != nil {
return nil, err
}

// Get L2 baseFee
baseFee, err := s.rpc.TaikoL2.GetBasefee(
&bind.CallOpts{BlockNumber: parent.Number},
&bind.CallOpts{BlockNumber: parent.Number, Context: ctx},
uint32(event.Meta.Timestamp-parentTimestamp),
event.Meta.GasLimit+uint32(s.anchorConstructor.GasLimit()),
uint32(parent.GasUsed),
Expand Down
14 changes: 11 additions & 3 deletions driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

"github.com/cenkalti/backoff/v4"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
Expand Down Expand Up @@ -84,7 +85,11 @@ func InitFromConfig(ctx context.Context, d *Driver, cfg *Config) (err error) {
log.Warn("P2P syncing verified blocks enabled, but no connected peer found in L2 execution engine")
}

signalServiceAddress, err := d.rpc.TaikoL1.Resolve0(nil, rpc.StringToBytes32("signal_service"), false)
signalServiceAddress, err := d.rpc.TaikoL1.Resolve0(
&bind.CallOpts{Context: ctx},
rpc.StringToBytes32("signal_service"),
false,
)
if err != nil {
return err
}
Expand Down Expand Up @@ -192,7 +197,10 @@ func (d *Driver) reportProtocolStatus() {
var maxNumBlocks uint64
if err := backoff.Retry(
func() error {
configs, err := d.rpc.TaikoL1.GetConfig(nil)
if d.ctx.Err() != nil {
return nil
}
configs, err := d.rpc.TaikoL1.GetConfig(&bind.CallOpts{Context: d.ctx})
if err != nil {
return err
}
Expand All @@ -211,7 +219,7 @@ func (d *Driver) reportProtocolStatus() {
case <-d.ctx.Done():
return
case <-ticker.C:
vars, err := d.rpc.GetProtocolStateVariables(nil)
vars, err := d.rpc.GetProtocolStateVariables(&bind.CallOpts{Context: d.ctx})
if err != nil {
log.Error("Failed to get protocol state variables", "error", err)
continue
Expand Down
124 changes: 122 additions & 2 deletions driver/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (s *DriverTestSuite) TestProcessL1Blocks() {
}
}

func (s *DriverTestSuite) TestCheckL1Reorg() {
func (s *DriverTestSuite) TestCheckL1ReorgToHigherFork() {
var testnetL1SnapshotID string
s.Nil(s.RpcClient.L1RawRPC.CallContext(context.Background(), &testnetL1SnapshotID, "evm_snapshot"))
s.NotEmpty(testnetL1SnapshotID)
Expand Down Expand Up @@ -146,13 +146,132 @@ func (s *DriverTestSuite) TestCheckL1Reorg() {
s.Equal(l1Head3.Number.Uint64(), l1Head1.Number.Uint64())
s.Equal(l1Head3.Hash(), l1Head1.Hash())

// Propose two blocks in another fork
// Propose ten blocks on another fork
for i := 0; i < 10; i++ {
testutils.ProposeInvalidTxListBytes(&s.ClientTestSuite, s.p)
}

l1Head4, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)

s.Greater(l1Head4.Number.Uint64(), l1Head2.Number.Uint64())

s.Nil(s.d.ChainSyncer().CalldataSyncer().ProcessL1Blocks(context.Background(), l1Head4))

l2Head3, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
s.Nil(err)

s.Equal(l2Head1.Number.Uint64()+10, l2Head3.Number.Uint64())

parent, err := s.d.rpc.L2.HeaderByNumber(context.Background(), new(big.Int).SetUint64(l2Head1.Number.Uint64()+1))
s.Nil(err)
s.Equal(parent.ParentHash, l2Head1.Hash())
s.NotEqual(parent.Hash(), l2Head2.ParentHash)
}

func (s *DriverTestSuite) TestCheckL1ReorgToLowerFork() {
var testnetL1SnapshotID string
s.Nil(s.RpcClient.L1RawRPC.CallContext(context.Background(), &testnetL1SnapshotID, "evm_snapshot"))
s.NotEmpty(testnetL1SnapshotID)

l1Head1, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
l2Head1, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
s.Nil(err)

// Propose two L2 blocks
testutils.ProposeAndInsertValidBlock(&s.ClientTestSuite, s.p, s.d.ChainSyncer().CalldataSyncer())
time.Sleep(3 * time.Second)
testutils.ProposeAndInsertValidBlock(&s.ClientTestSuite, s.p, s.d.ChainSyncer().CalldataSyncer())

l1Head2, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
l2Head2, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
s.Nil(err)
s.Greater(l2Head2.Number.Uint64(), l2Head1.Number.Uint64())
s.Greater(l1Head2.Number.Uint64(), l1Head1.Number.Uint64())

reorged, _, _, err := s.RpcClient.CheckL1ReorgFromL2EE(context.Background(), l2Head2.Number)
s.Nil(err)
s.False(reorged)

// Reorg back to l2Head1
var revertRes bool
s.Nil(s.RpcClient.L1RawRPC.CallContext(context.Background(), &revertRes, "evm_revert", testnetL1SnapshotID))
s.True(revertRes)

l1Head3, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
s.Equal(l1Head3.Number.Uint64(), l1Head1.Number.Uint64())
s.Equal(l1Head3.Hash(), l1Head1.Hash())

// Propose one blocks on another fork
testutils.ProposeInvalidTxListBytes(&s.ClientTestSuite, s.p)

l1Head4, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)

s.Greater(l1Head4.Number.Uint64(), l1Head3.Number.Uint64())
s.Less(l1Head4.Number.Uint64(), l1Head2.Number.Uint64())

s.Nil(s.d.ChainSyncer().CalldataSyncer().ProcessL1Blocks(context.Background(), l1Head4))

l2Head3, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
s.Nil(err)

parent, err := s.d.rpc.L2.HeaderByHash(context.Background(), l2Head3.ParentHash)
s.Nil(err)
s.Equal(l2Head3.Number.Uint64(), l2Head2.Number.Uint64()-1)
s.Equal(parent.Hash(), l2Head1.Hash())
}

func (s *DriverTestSuite) TestCheckL1ReorgToSameHeightFork() {
var testnetL1SnapshotID string
s.Nil(s.RpcClient.L1RawRPC.CallContext(context.Background(), &testnetL1SnapshotID, "evm_snapshot"))
s.NotEmpty(testnetL1SnapshotID)

l1Head1, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
l2Head1, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
s.Nil(err)

// Propose two L2 blocks
testutils.ProposeAndInsertValidBlock(&s.ClientTestSuite, s.p, s.d.ChainSyncer().CalldataSyncer())
time.Sleep(3 * time.Second)
testutils.ProposeAndInsertValidBlock(&s.ClientTestSuite, s.p, s.d.ChainSyncer().CalldataSyncer())

l1Head2, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
l2Head2, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
s.Nil(err)
s.Greater(l2Head2.Number.Uint64(), l2Head1.Number.Uint64())
s.Greater(l1Head2.Number.Uint64(), l1Head1.Number.Uint64())

reorged, _, _, err := s.RpcClient.CheckL1ReorgFromL2EE(context.Background(), l2Head2.Number)
s.Nil(err)
s.False(reorged)

// Reorg back to l2Head1
var revertRes bool
s.Nil(s.RpcClient.L1RawRPC.CallContext(context.Background(), &revertRes, "evm_revert", testnetL1SnapshotID))
s.True(revertRes)

l1Head3, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
s.Equal(l1Head3.Number.Uint64(), l1Head1.Number.Uint64())
s.Equal(l1Head3.Hash(), l1Head1.Hash())

// Propose two blocks on another fork
testutils.ProposeInvalidTxListBytes(&s.ClientTestSuite, s.p)
time.Sleep(3 * time.Second)
testutils.ProposeInvalidTxListBytes(&s.ClientTestSuite, s.p)

l1Head4, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)

s.Greater(l1Head4.Number.Uint64(), l1Head3.Number.Uint64())
s.Equal(l1Head4.Number.Uint64(), l1Head2.Number.Uint64())

s.Nil(s.d.ChainSyncer().CalldataSyncer().ProcessL1Blocks(context.Background(), l1Head4))

l2Head3, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
Expand All @@ -161,6 +280,7 @@ func (s *DriverTestSuite) TestCheckL1Reorg() {
parent, err := s.d.rpc.L2.HeaderByHash(context.Background(), l2Head3.ParentHash)
s.Nil(err)
s.Equal(l2Head3.Number.Uint64(), l2Head2.Number.Uint64())
s.NotEqual(l2Head3.Hash(), l2Head2.Hash())
s.Equal(parent.ParentHash, l2Head1.Hash())
}

Expand Down
13 changes: 7 additions & 6 deletions driver/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (s *State) Close() {

// init fetches the latest status and initializes the state instance.
func (s *State) init(ctx context.Context) error {
stateVars, err := s.rpc.GetProtocolStateVariables(nil)
stateVars, err := s.rpc.GetProtocolStateVariables(&bind.CallOpts{Context: ctx})
if err != nil {
return err
}
Expand Down Expand Up @@ -134,7 +134,7 @@ func (s *State) init(ctx context.Context) error {
s.setL2Head(l2Head)

latestVerifiedBlockHash, err := s.rpc.TaikoL1.GetCrossChainBlockHash(
nil,
&bind.CallOpts{Context: ctx},
new(big.Int).SetUint64(stateVars.LastVerifiedBlockId),
)
if err != nil {
Expand Down Expand Up @@ -182,7 +182,7 @@ func (s *State) startSubscriptions(ctx context.Context) {
continue
}
}
id, err := s.getSyncedHeaderID(e.Raw.BlockNumber, e.BlockHash)
id, err := s.getSyncedHeaderID(ctx, e.Raw.BlockNumber, e.BlockHash)
if err != nil {
log.Error("Get synced header block ID error", "error", err)
continue
Expand Down Expand Up @@ -289,10 +289,11 @@ func (s *State) VerifyL2Block(ctx context.Context, height *big.Int, hash common.
}

// getSyncedHeaderID fetches the block ID of the synced L2 header.
func (s *State) getSyncedHeaderID(l1Height uint64, hash common.Hash) (*big.Int, error) {
func (s *State) getSyncedHeaderID(ctx context.Context, l1Height uint64, hash common.Hash) (*big.Int, error) {
iter, err := s.rpc.TaikoL1.FilterBlockVerified(&bind.FilterOpts{
Start: l1Height,
End: &l1Height,
Start: l1Height,
End: &l1Height,
Context: ctx,
}, nil)
if err != nil {
return nil, fmt.Errorf("failed to filter BlockVerified event: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion driver/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (s *DriverStateTestSuite) TestGetSyncedHeaderID() {
l2Genesis, err := s.RpcClient.L2.BlockByNumber(context.Background(), common.Big0)
s.Nil(err)

id, err := s.s.getSyncedHeaderID(s.s.GenesisL1Height.Uint64(), l2Genesis.Hash())
id, err := s.s.getSyncedHeaderID(context.Background(), s.s.GenesisL1Height.Uint64(), l2Genesis.Hash())
s.Nil(err)
s.Zero(id.Uint64())
}
Expand Down
28 changes: 22 additions & 6 deletions pkg/rpc/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ var (
// ensureGenesisMatched fetches the L2 genesis block from TaikoL1 contract,
// and checks whether the fetched genesis is same to the node local genesis.
func (c *Client) ensureGenesisMatched(ctx context.Context) error {
stateVars, err := c.GetProtocolStateVariables(nil)
stateVars, err := c.GetProtocolStateVariables(&bind.CallOpts{Context: ctx})
if err != nil {
return err
}

// Fetch the genesis `BlockVerified` event.
iter, err := c.TaikoL1.FilterBlockVerified(
&bind.FilterOpts{Start: stateVars.GenesisHeight, End: &stateVars.GenesisHeight},
&bind.FilterOpts{Start: stateVars.GenesisHeight, End: &stateVars.GenesisHeight, Context: ctx},
[]*big.Int{common.Big0},
)
if err != nil {
Expand Down Expand Up @@ -99,7 +99,7 @@ func (c *Client) WaitTillL2ExecutionEngineSynced(ctx context.Context) error {

return nil
},
backoff.NewConstantBackOff(syncProgressRecheckDelay),
backoff.WithMaxRetries(backoff.NewConstantBackOff(syncProgressRecheckDelay), 10),
)
}

Expand Down Expand Up @@ -138,7 +138,7 @@ func (c *Client) LatestL2KnownL1Header(ctx context.Context) (*types.Header, erro

// GetGenesisL1Header fetches the L1 header that including L2 genesis block.
func (c *Client) GetGenesisL1Header(ctx context.Context) (*types.Header, error) {
stateVars, err := c.GetProtocolStateVariables(nil)
stateVars, err := c.GetProtocolStateVariables(&bind.CallOpts{Context: ctx})
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -271,7 +271,7 @@ func (c *Client) L2ExecutionEngineSyncProgress(ctx context.Context) (*L2SyncProg
})

g.Go(func() error {
stateVars, err := c.GetProtocolStateVariables(nil)
stateVars, err := c.GetProtocolStateVariables(&bind.CallOpts{Context: ctx})
if err != nil {
return err
}
Expand Down Expand Up @@ -305,6 +305,22 @@ func (c *Client) L2ExecutionEngineSyncProgress(ctx context.Context) (*L2SyncProg

// GetProtocolStateVariables gets the protocol states from TaikoL1 contract.
func (c *Client) GetProtocolStateVariables(opts *bind.CallOpts) (*bindings.TaikoDataStateVariables, error) {
var (
ctxWithTimeout context.Context
cancel context.CancelFunc
)
if opts != nil && opts.Context != nil {
if _, ok := opts.Context.Deadline(); !ok {
ctxWithTimeout, cancel = context.WithTimeout(opts.Context, defaultWaitReceiptTimeout)
defer cancel()
opts.Context = ctxWithTimeout
}
} else {
ctxWithTimeout, cancel = context.WithTimeout(context.Background(), defaultWaitReceiptTimeout)
defer cancel()
opts = &bind.CallOpts{Context: ctxWithTimeout}
}

return GetProtocolStateVariables(c.TaikoL1, opts)
}

Expand Down Expand Up @@ -338,7 +354,7 @@ func (c *Client) CheckL1ReorgFromL2EE(ctx context.Context, blockID *big.Int) (bo
)
for {
if blockID.Cmp(common.Big0) == 0 {
stateVars, err := c.TaikoL1.GetStateVariables(nil)
stateVars, err := c.TaikoL1.GetStateVariables(&bind.CallOpts{Context: ctx})
if err != nil {
return false, nil, nil, err
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/rpc/methods_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,9 @@ func TestCheckL1ReorgFromL1Cursor(t *testing.T) {
require.True(t, reorged)
require.Equal(t, l1Head.ParentHash, newL1Current.Hash())
}

func TestIsJustSyncedByP2P(t *testing.T) {
client := newTestClient(t)
_, err := client.IsJustSyncedByP2P(context.Background())
require.Nil(t, err)
}
2 changes: 1 addition & 1 deletion pkg/rpc/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func NeedNewProof(
}
}

fc, err := cli.TaikoL1.GetForkChoice(nil, id, parent.Hash(), uint32(parent.GasUsed))
fc, err := cli.TaikoL1.GetForkChoice(&bind.CallOpts{Context: ctx}, id, parent.Hash(), uint32(parent.GasUsed))
if err != nil {
if !strings.Contains(encoding.TryParsingCustomError(err).Error(), "L1_FORK_CHOICE_NOT_FOUND") {
return false, encoding.TryParsingCustomError(err)
Expand Down
Loading

0 comments on commit 295f0ab

Please sign in to comment.