diff --git a/driver/anchor_tx_constructor/anchor_tx_constructor_test.go b/driver/anchor_tx_constructor/anchor_tx_constructor_test.go index b808d6ea5..b6dff0e08 100644 --- a/driver/anchor_tx_constructor/anchor_tx_constructor_test.go +++ b/driver/anchor_tx_constructor/anchor_tx_constructor_test.go @@ -63,6 +63,14 @@ func (s *AnchorTxConstructorTestSuite) TestNewAnchorTransactor() { s.Equal(common.Big0, opts.GasTipCap) } +func (s *AnchorTxConstructorTestSuite) TestCancelCtxTransactOpts() { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + opts, err := s.c.transactOpts(ctx, common.Big1, common.Big256) + s.Nil(opts) + s.ErrorContains(err, "context canceled") +} + func (s *AnchorTxConstructorTestSuite) TestSign() { // Payload 1 hash := hexutil.MustDecode("0x44943399d1507f3ce7525e9be2f987c3db9136dc759cb7f92f742154196868b9") @@ -95,6 +103,13 @@ func (s *AnchorTxConstructorTestSuite) TestSign() { s.Equal(signatureBytes, signed) } +func (s *AnchorTxConstructorTestSuite) TestSignShortHash() { + rand := testutils.RandomHash().Bytes() + hash := rand[:len(rand)-2] + _, err := s.c.signTxPayload(hash) + s.ErrorContains(err, "hash is required to be exactly 32 bytes") +} + func TestAnchorTxConstructorTestSuite(t *testing.T) { suite.Run(t, new(AnchorTxConstructorTestSuite)) } diff --git a/driver/chain_syncer/calldata/syncer_test.go b/driver/chain_syncer/calldata/syncer_test.go index 3f4c5031d..cc16c9e14 100644 --- a/driver/chain_syncer/calldata/syncer_test.go +++ b/driver/chain_syncer/calldata/syncer_test.go @@ -59,6 +59,19 @@ func (s *CalldataSyncerTestSuite) SetupTest() { s.p = prop } +func (s *CalldataSyncerTestSuite) TestNewSyncer() { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + syncer, err := NewSyncer( + ctx, + s.RpcClient, + s.s.state, + s.s.progressTracker, + common.HexToAddress(os.Getenv("L1_SIGNAL_SERVICE_CONTRACT_ADDRESS")), + ) + s.Nil(syncer) + s.NotNil(err) +} func (s *CalldataSyncerTestSuite) TestProcessL1Blocks() { head, err := s.s.rpc.L1.HeaderByNumber(context.Background(), nil) @@ -66,6 +79,13 @@ func (s *CalldataSyncerTestSuite) TestProcessL1Blocks() { s.Nil(s.s.ProcessL1Blocks(context.Background(), head)) } +func (s *CalldataSyncerTestSuite) TestProcessL1BlocksReorg() { + head, err := s.s.rpc.L1.HeaderByNumber(context.Background(), nil) + testutils.ProposeAndInsertEmptyBlocks(&s.ClientTestSuite, s.p, s.s) + s.Nil(err) + s.Nil(s.s.ProcessL1Blocks(context.Background(), head)) +} + func (s *CalldataSyncerTestSuite) TestOnBlockProposed() { s.Nil(s.s.onBlockProposed( context.Background(), diff --git a/driver/chain_syncer/chain_syncer_test.go b/driver/chain_syncer/chain_syncer_test.go index e58f5c4f6..91c083581 100644 --- a/driver/chain_syncer/chain_syncer_test.go +++ b/driver/chain_syncer/chain_syncer_test.go @@ -46,6 +46,11 @@ func (s *ChainSyncerTestSuite) TestSync() { s.Nil(s.s.Sync(head)) } +// func (s *ChainSyncerTestSuite) TestSyncTriggerBeaconSync() { +// s.s.p2pSyncVerifiedBlocks = true +// s.s.state.setLatestVerifiedBlockHash(common.Hash{}) +// } + func TestChainSyncerTestSuite(t *testing.T) { suite.Run(t, new(ChainSyncerTestSuite)) } diff --git a/driver/driver_test.go b/driver/driver_test.go index 399056462..536b8580d 100644 --- a/driver/driver_test.go +++ b/driver/driver_test.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/suite" "github.com/taikoxyz/taiko-client/bindings/encoding" + "github.com/taikoxyz/taiko-client/driver/state" "github.com/taikoxyz/taiko-client/pkg/jwt" "github.com/taikoxyz/taiko-client/proposer" "github.com/taikoxyz/taiko-client/testutils" @@ -295,6 +296,15 @@ func (s *DriverTestSuite) TestStartClose() { s.d.Close() } +func (s *DriverTestSuite) TestL1Current() { + // propose and insert a block + testutils.ProposeAndInsertEmptyBlocks(&s.ClientTestSuite, s.p, s.d.ChainSyncer().CalldataSyncer()) + // reset L1 current with increased height + _, id, err := s.d.state.ResetL1Current(s.d.ctx, &state.HeightOrID{ID: common.Big1}) + s.Equal(common.Big1, id) + s.Nil(err) +} + func TestDriverTestSuite(t *testing.T) { suite.Run(t, new(DriverTestSuite)) } diff --git a/driver/state/l1_current_test.go b/driver/state/l1_current_test.go index 86b26b60d..b55f52e4a 100644 --- a/driver/state/l1_current_test.go +++ b/driver/state/l1_current_test.go @@ -16,6 +16,11 @@ func (s *DriverStateTestSuite) TestSetL1Current() { h := &types.Header{ParentHash: testutils.RandomHash()} s.s.SetL1Current(h) s.Equal(h.Hash(), s.s.GetL1Current().Hash()) + + // should warn, but not panic + s.NotPanics(func() { + s.s.SetL1Current(nil) + }) } func (s *DriverStateTestSuite) TestResetL1CurrentEmptyHeight() { @@ -29,5 +34,17 @@ func (s *DriverStateTestSuite) TestResetL1CurrentEmptyHeight() { func (s *DriverStateTestSuite) TestResetL1CurrentEmptyID() { _, _, err := s.s.ResetL1Current(context.Background(), &HeightOrID{Height: common.Big1}) - s.NotNil(err) + s.ErrorContains(err, "not found") +} + +func (s *DriverStateTestSuite) TestResetL1CurrentEmptyHeightAndID() { + _, _, err := s.s.ResetL1Current(context.Background(), &HeightOrID{}) + s.ErrorContains(err, "empty input") +} + +func (s *DriverStateTestSuite) TestResetL1CurrentCtxErr() { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + _, _, err := s.s.ResetL1Current(ctx, &HeightOrID{Height: common.Big0}) + s.ErrorContains(err, "context canceled") } diff --git a/driver/state/state_test.go b/driver/state/state_test.go index 58c560254..de7987e98 100644 --- a/driver/state/state_test.go +++ b/driver/state/state_test.go @@ -77,6 +77,21 @@ func (s *DriverStateTestSuite) TestGetSyncedHeaderID() { s.Zero(id.Uint64()) } +func (s *DriverStateTestSuite) TestNewDriverContextErr() { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + state, err := New(ctx, s.RpcClient) + s.Nil(state) + s.ErrorContains(err, "context canceled") +} + +func (s *DriverStateTestSuite) TestDriverInitContextErr() { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + err := s.s.init(ctx) + s.ErrorContains(err, "context canceled") +} + func TestDriverStateTestSuite(t *testing.T) { suite.Run(t, new(DriverStateTestSuite)) } diff --git a/pkg/rpc/client_test.go b/pkg/rpc/client_test.go index 7fc0b9971..6ab63bd14 100644 --- a/pkg/rpc/client_test.go +++ b/pkg/rpc/client_test.go @@ -4,6 +4,7 @@ import ( "context" "os" "testing" + "time" "github.com/cenkalti/backoff/v4" "github.com/ethereum/go-ethereum/common" @@ -27,3 +28,23 @@ func newTestClient(t *testing.T) *Client { return client } + +func newTestClientWithTimeout(t *testing.T) *Client { + timeout := 5 * time.Second + client, err := NewClient(context.Background(), &ClientConfig{ + L1Endpoint: os.Getenv("L1_NODE_WS_ENDPOINT"), + L2Endpoint: os.Getenv("L2_EXECUTION_ENGINE_WS_ENDPOINT"), + TaikoL1Address: common.HexToAddress(os.Getenv("TAIKO_L1_ADDRESS")), + TaikoL2Address: common.HexToAddress(os.Getenv("TAIKO_L2_ADDRESS")), + TaikoProverPoolL1Address: common.HexToAddress(os.Getenv("TAIKO_PROVER_POOL_L1_ADDRESS")), + L2EngineEndpoint: os.Getenv("L2_EXECUTION_ENGINE_AUTH_ENDPOINT"), + JwtSecret: os.Getenv("JWT_SECRET"), + RetryInterval: backoff.DefaultMaxInterval, + Timeout: &timeout, + }) + + require.Nil(t, err) + require.NotNil(t, client) + + return client +} diff --git a/pkg/rpc/dial_test.go b/pkg/rpc/dial_test.go index 7f1f627a6..e37609197 100644 --- a/pkg/rpc/dial_test.go +++ b/pkg/rpc/dial_test.go @@ -46,3 +46,17 @@ func TestDialClientWithBackoff(t *testing.T) { require.Equal(t, common.Big0.Uint64(), genesis.Number.Uint64()) } + +// NOTE: current constant backoff will only stop if passed -1 (backoff.Stop), +// and error does not match +// error comes back as "dial unix: ...." instead + +// func TestDialClientWithBackoff_CtxError(t *testing.T) { +// ctx, _ := context.WithCancel(context.Background()) +// _, err := DialClientWithBackoff( +// ctx, +// "", +// -1, +// ) +// require.ErrorContains(t, err, "Dial engine client error") +// } diff --git a/pkg/rpc/methods_test.go b/pkg/rpc/methods_test.go index 030152bea..4467741be 100644 --- a/pkg/rpc/methods_test.go +++ b/pkg/rpc/methods_test.go @@ -14,7 +14,7 @@ var ( ) func TestL2AccountNonce(t *testing.T) { - client := newTestClient(t) + client := newTestClientWithTimeout(t) nonce, err := client.L2AccountNonce(context.Background(), testAddress, common.Big0) diff --git a/proposer/config_test.go b/proposer/config_test.go index 318932c32..b401a3200 100644 --- a/proposer/config_test.go +++ b/proposer/config_test.go @@ -11,34 +11,24 @@ import ( "github.com/urfave/cli/v2" ) -func (s *ProposerTestSuite) TestNewConfigFromCliContext() { - l1Endpoint := os.Getenv("L1_NODE_WS_ENDPOINT") - l2Endpoint := os.Getenv("L2_EXECUTION_ENGINE_HTTP_ENDPOINT") - taikoL1 := os.Getenv("TAIKO_L1_ADDRESS") - taikoL2 := os.Getenv("TAIKO_L2_ADDRESS") - proposeInterval := "10s" - rpcTimeout := 5 * time.Second +var ( + l1Endpoint = os.Getenv("L1_NODE_WS_ENDPOINT") + l2Endpoint = os.Getenv("L2_EXECUTION_ENGINE_HTTP_ENDPOINT") + taikoL1 = os.Getenv("TAIKO_L1_ADDRESS") + taikoL2 = os.Getenv("TAIKO_L2_ADDRESS") + proposeInterval = "10s" + rpcTimeout = 5 * time.Second +) +func (s *ProposerTestSuite) TestNewConfigFromCliContext() { goldenTouchAddress, err := s.RpcClient.TaikoL2.GOLDENTOUCHADDRESS(nil) s.Nil(err) goldenTouchPrivKey, err := s.RpcClient.TaikoL2.GOLDENTOUCHPRIVATEKEY(nil) s.Nil(err) - app := cli.NewApp() - app.Flags = []cli.Flag{ - &cli.StringFlag{Name: flags.L1WSEndpoint.Name}, - &cli.StringFlag{Name: flags.L2HTTPEndpoint.Name}, - &cli.StringFlag{Name: flags.TaikoL1Address.Name}, - &cli.StringFlag{Name: flags.TaikoL2Address.Name}, - &cli.StringFlag{Name: flags.L1ProposerPrivKey.Name}, - &cli.StringFlag{Name: flags.L2SuggestedFeeRecipient.Name}, - &cli.StringFlag{Name: flags.ProposeInterval.Name}, - &cli.StringFlag{Name: flags.TxPoolLocals.Name}, - &cli.Uint64Flag{Name: flags.ProposeBlockTxReplacementMultiplier.Name}, - &cli.Uint64Flag{Name: flags.RPCTimeout.Name}, - &cli.Uint64Flag{Name: flags.WaitReceiptTimeout.Name}, - } + app := s.SetupApp() + app.Action = func(ctx *cli.Context) error { c, err := NewConfigFromCliContext(ctx) s.Nil(err) @@ -72,5 +62,120 @@ func (s *ProposerTestSuite) TestNewConfigFromCliContext() { "-" + flags.ProposeBlockTxReplacementMultiplier.Name, "5", "-" + flags.RPCTimeout.Name, "5", "-" + flags.WaitReceiptTimeout.Name, "10", + "-" + flags.ProposeBlockTxGasLimit.Name, "100000", })) } + +func (s *ProposerTestSuite) TestNewConfigFromCliContextPrivKeyErr() { + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContextPrivKeyErr", + "-" + flags.L1ProposerPrivKey.Name, string(common.FromHex("0x")), + }), "invalid L1 proposer private key") +} + +func (s *ProposerTestSuite) TestNewConfigFromCliContextPropIntervalErr() { + goldenTouchPrivKey, err := s.RpcClient.TaikoL2.GOLDENTOUCHPRIVATEKEY(nil) + s.Nil(err) + + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContextProposeIntervalErr", + "-" + flags.L1ProposerPrivKey.Name, common.Bytes2Hex(goldenTouchPrivKey.Bytes()), + "-" + flags.ProposeInterval.Name, "", + }), "invalid proposing interval") +} + +func (s *ProposerTestSuite) TestNewConfigFromCliContextEmptyPropoIntervalErr() { + goldenTouchPrivKey, err := s.RpcClient.TaikoL2.GOLDENTOUCHPRIVATEKEY(nil) + s.Nil(err) + + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContextEmptyProposalIntervalErr", + "-" + flags.L1ProposerPrivKey.Name, common.Bytes2Hex(goldenTouchPrivKey.Bytes()), + "-" + flags.ProposeInterval.Name, proposeInterval, + "-" + flags.ProposeEmptyBlocksInterval.Name, "", + }), "invalid proposing empty blocks interval") +} + +func (s *ProposerTestSuite) TestNewConfigFromCliContextL2RecipErr() { + goldenTouchPrivKey, err := s.RpcClient.TaikoL2.GOLDENTOUCHPRIVATEKEY(nil) + s.Nil(err) + + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContextL2RecipErr", + "-" + flags.L1ProposerPrivKey.Name, common.Bytes2Hex(goldenTouchPrivKey.Bytes()), + "-" + flags.ProposeInterval.Name, proposeInterval, + "-" + flags.ProposeEmptyBlocksInterval.Name, proposeInterval, + "-" + flags.L2SuggestedFeeRecipient.Name, "notAnAddress", + }), "invalid L2 suggested fee recipient address") +} + +func (s *ProposerTestSuite) TestNewConfigFromCliContextTxPoolLocalsErr() { + goldenTouchAddress, err := s.RpcClient.TaikoL2.GOLDENTOUCHADDRESS(nil) + s.Nil(err) + + goldenTouchPrivKey, err := s.RpcClient.TaikoL2.GOLDENTOUCHPRIVATEKEY(nil) + s.Nil(err) + + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContextTxPoolLocalsErr", + "-" + flags.L1ProposerPrivKey.Name, common.Bytes2Hex(goldenTouchPrivKey.Bytes()), + "-" + flags.ProposeInterval.Name, proposeInterval, + "-" + flags.ProposeEmptyBlocksInterval.Name, proposeInterval, + "-" + flags.L2SuggestedFeeRecipient.Name, goldenTouchAddress.Hex(), + "-" + flags.TxPoolLocals.Name, "notAnAddress", + }), "invalid account in --txpool.locals") +} + +func (s *ProposerTestSuite) TestNewConfigFromCliContextReplMultErr() { + goldenTouchAddress, err := s.RpcClient.TaikoL2.GOLDENTOUCHADDRESS(nil) + s.Nil(err) + + goldenTouchPrivKey, err := s.RpcClient.TaikoL2.GOLDENTOUCHPRIVATEKEY(nil) + s.Nil(err) + + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContextReplMultErr", + "-" + flags.L1ProposerPrivKey.Name, common.Bytes2Hex(goldenTouchPrivKey.Bytes()), + "-" + flags.ProposeInterval.Name, proposeInterval, + "-" + flags.ProposeEmptyBlocksInterval.Name, proposeInterval, + "-" + flags.L2SuggestedFeeRecipient.Name, goldenTouchAddress.Hex(), + "-" + flags.TxPoolLocals.Name, goldenTouchAddress.Hex(), + "-" + flags.ProposeBlockTxReplacementMultiplier.Name, "0", + }), "invalid --proposeBlockTxReplacementMultiplier value") +} + +func (s *ProposerTestSuite) SetupApp() *cli.App { + app := cli.NewApp() + app.Flags = []cli.Flag{ + &cli.StringFlag{Name: flags.L1WSEndpoint.Name}, + &cli.StringFlag{Name: flags.L2HTTPEndpoint.Name}, + &cli.StringFlag{Name: flags.TaikoL1Address.Name}, + &cli.StringFlag{Name: flags.TaikoL2Address.Name}, + &cli.StringFlag{Name: flags.L1ProposerPrivKey.Name}, + &cli.StringFlag{Name: flags.L2SuggestedFeeRecipient.Name}, + &cli.StringFlag{Name: flags.ProposeEmptyBlocksInterval.Name}, + &cli.StringFlag{Name: flags.ProposeInterval.Name}, + &cli.StringFlag{Name: flags.TxPoolLocals.Name}, + &cli.Uint64Flag{Name: flags.ProposeBlockTxReplacementMultiplier.Name}, + &cli.Uint64Flag{Name: flags.RPCTimeout.Name}, + &cli.Uint64Flag{Name: flags.WaitReceiptTimeout.Name}, + &cli.Uint64Flag{Name: flags.ProposeBlockTxGasLimit.Name}, + } + app.Action = func(ctx *cli.Context) error { + _, err := NewConfigFromCliContext(ctx) + return err + } + return app +} diff --git a/proposer/proposer.go b/proposer/proposer.go index 4dc698bf2..729b93cad 100644 --- a/proposer/proposer.go +++ b/proposer/proposer.go @@ -136,15 +136,16 @@ func (p *Proposer) eventLoop() { select { case <-p.ctx.Done(): return + // proposing interval timer has been reached case <-p.proposingTimer.C: metrics.ProposerProposeEpochCounter.Inc(1) - + // attempt propose operation if err := p.ProposeOp(p.ctx); err != nil { if !errors.Is(err, errNoNewTxs) { log.Error("Proposing operation error", "error", err) continue } - + // if no new transactions and empty block interval has passed, propose an empty block if p.proposeEmptyBlocksInterval != nil { if time.Now().Before(lastNonEmptyBlockProposedAt.Add(*p.proposeEmptyBlocksInterval)) { continue diff --git a/proposer/proposer_test.go b/proposer/proposer_test.go index 380c5e5f0..294e19a51 100644 --- a/proposer/proposer_test.go +++ b/proposer/proposer_test.go @@ -187,6 +187,22 @@ func (s *ProposerTestSuite) TestStartClose() { s.NotPanics(s.p.Close) } +// TODO: not working +// func (s *ProposerTestSuite) TestEventLoopEmptyBlock() { +// fiveSecs := 5 * time.Second +// s.p.proposingInterval = &fiveSecs +// s.p.proposeEmptyBlocksInterval = &fiveSecs +// s.p.Start() +// time.Sleep(30 * time.Second) +// s.cancel() +// s.p.Close() +// // check if empty blocks have been proposed? query TaikoL1 contract? +// block, err := s.p.rpc.L2.BlockByNumber(context.Background(), nil) +// s.Nil(err) +// s.Equal(uint64(block.GasLimit()), uint64(21000)) +// s.Equal(block.TxHash(), common.Hash(crypto.Keccak256Hash([]byte{}))) +// } + func TestProposerTestSuite(t *testing.T) { suite.Run(t, new(ProposerTestSuite)) } diff --git a/prover/config_test.go b/prover/config_test.go index 386987730..422daed4f 100644 --- a/prover/config_test.go +++ b/prover/config_test.go @@ -10,36 +10,19 @@ import ( "github.com/urfave/cli/v2" ) -var testFlags = []cli.Flag{ - &cli.StringFlag{Name: flags.L1WSEndpoint.Name}, - &cli.StringFlag{Name: flags.L1HTTPEndpoint.Name}, - &cli.StringFlag{Name: flags.L2WSEndpoint.Name}, - &cli.StringFlag{Name: flags.L2HTTPEndpoint.Name}, - &cli.StringFlag{Name: flags.TaikoL1Address.Name}, - &cli.StringFlag{Name: flags.TaikoL2Address.Name}, - &cli.StringFlag{Name: flags.L1ProverPrivKey.Name}, - &cli.BoolFlag{Name: flags.Dummy.Name}, - &cli.StringFlag{Name: flags.RandomDummyProofDelay.Name}, - &cli.BoolFlag{Name: flags.OracleProver.Name}, - &cli.StringFlag{Name: flags.OracleProverPrivateKey.Name}, - &cli.StringFlag{Name: flags.Graffiti.Name}, - &cli.StringFlag{Name: flags.TaikoProverPoolL1Address.Name}, - &cli.Uint64Flag{Name: flags.CheckProofWindowExpiredInterval.Name}, - &cli.BoolFlag{Name: flags.ProveUnassignedBlocks.Name}, - &cli.Uint64Flag{Name: flags.RPCTimeout.Name}, -} +var ( + l1WsEndpoint = os.Getenv("L1_NODE_WS_ENDPOINT") + l1HttpEndpoint = os.Getenv("L1_NODE_HTTP_ENDPOINT") + l2WsEndpoint = os.Getenv("L2_EXECUTION_ENGINE_WS_ENDPOINT") + l2HttpEndpoint = os.Getenv("L2_EXECUTION_ENGINE_HTTP_ENDPOINT") + taikoL1 = os.Getenv("TAIKO_L1_ADDRESS") + taikoL2 = os.Getenv("TAIKO_L2_ADDRESS") + taikoProverPoolL1 = os.Getenv("TAIKO_PROVER_POOL_L1_ADDRESS") + rpcTimeout = 5 * time.Second +) func (s *ProverTestSuite) TestNewConfigFromCliContext_OracleProver() { - l1WsEndpoint := os.Getenv("L1_NODE_WS_ENDPOINT") - l1HttpEndpoint := os.Getenv("L1_NODE_HTTP_ENDPOINT") - l2WsEndpoint := os.Getenv("L2_EXECUTION_ENGINE_WS_ENDPOINT") - l2HttpEndpoint := os.Getenv("L2_EXECUTION_ENGINE_HTTP_ENDPOINT") - taikoL1 := os.Getenv("TAIKO_L1_ADDRESS") - taikoL2 := os.Getenv("TAIKO_L2_ADDRESS") - taikoProverPoolL1 := os.Getenv("TAIKO_PROVER_POOL_L1_ADDRESS") - - app := cli.NewApp() - app.Flags = testFlags + app := s.SetupApp() app.Action = func(ctx *cli.Context) error { c, err := NewConfigFromCliContext(ctx) s.Nil(err) @@ -65,7 +48,7 @@ func (s *ProverTestSuite) TestNewConfigFromCliContext_OracleProver() { s.Equal("", c.Graffiti) s.Equal(30*time.Second, c.CheckProofWindowExpiredInterval) s.Equal(true, c.ProveUnassignedBlocks) - s.Nil(c.RPCTimeout) + s.Equal(rpcTimeout, *c.RPCTimeout) s.Nil(new(Prover).InitFromCli(context.Background(), ctx)) return err @@ -81,6 +64,8 @@ func (s *ProverTestSuite) TestNewConfigFromCliContext_OracleProver() { "-" + flags.TaikoL2Address.Name, taikoL2, "-" + flags.TaikoProverPoolL1Address.Name, taikoProverPoolL1, "-" + flags.L1ProverPrivKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), + "-" + flags.StartingBlockID.Name, "0", + "-" + flags.RPCTimeout.Name, "5", "-" + flags.Dummy.Name, "-" + flags.RandomDummyProofDelay.Name, "30m-1h", "-" + flags.OracleProver.Name, @@ -92,21 +77,7 @@ func (s *ProverTestSuite) TestNewConfigFromCliContext_OracleProver() { } func (s *ProverTestSuite) TestNewConfigFromCliContext_OracleProverError() { - l1WsEndpoint := os.Getenv("L1_NODE_WS_ENDPOINT") - l1HttpEndpoint := os.Getenv("L1_NODE_HTTP_ENDPOINT") - l2WsEndpoint := os.Getenv("L2_EXECUTION_ENGINE_WS_ENDPOINT") - l2HttpEndpoint := os.Getenv("L2_EXECUTION_ENGINE_HTTP_ENDPOINT") - taikoL1 := os.Getenv("TAIKO_L1_ADDRESS") - taikoL2 := os.Getenv("TAIKO_L2_ADDRESS") - taikoProverPoolL1 := os.Getenv("TAIKO_PROVER_POOL_L1_ADDRESS") - - app := cli.NewApp() - app.Flags = testFlags - app.Action = func(ctx *cli.Context) error { - _, err := NewConfigFromCliContext(ctx) - s.NotNil(err) - return err - } + app := s.SetupApp() s.ErrorContains(app.Run([]string{ "TestNewConfigFromCliContext", @@ -125,3 +96,96 @@ func (s *ProverTestSuite) TestNewConfigFromCliContext_OracleProverError() { "-" + flags.RPCTimeout.Name, "5", }), "oracleProver flag set without oracleProverPrivateKey set") } + +func (s *ProverTestSuite) TestNewConfigFromCliContext_ProverKeyError() { + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContext", + "-" + flags.L1ProverPrivKey.Name, "0x", + }), "invalid L1 prover private key") +} + +// TODO: find case for ToECDSA failing +// func (s *ProverTestSuite) TestNewConfigFromCliContext_OracleProverKeyError() { +// app := s.SetupApp() + +// s.ErrorContains(app.Run([]string{ +// "TestNewConfigFromCliContext", +// "-" + flags.L1ProverPrivKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), +// "-" + flags.OracleProverPrivateKey.Name, "0x", +// }), "invalid oracle private key") +// } + +func (s *ProverTestSuite) TestNewConfigFromCliContext_RandomDelayError() { + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContext", + "-" + flags.L1ProverPrivKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), + "-" + flags.OracleProverPrivateKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), + "-" + flags.RandomDummyProofDelay.Name, "130m", + }), "invalid random dummy proof delay value") +} + +func (s *ProverTestSuite) TestNewConfigFromCliContext_RandomDelayErrorLower() { + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContext", + "-" + flags.L1ProverPrivKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), + "-" + flags.OracleProverPrivateKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), + "-" + flags.RandomDummyProofDelay.Name, "30x-1h", + }), "invalid random dummy proof delay value") +} + +func (s *ProverTestSuite) TestNewConfigFromCliContext_RandomDelayErrorUpper() { + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContext", + "-" + flags.L1ProverPrivKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), + "-" + flags.OracleProverPrivateKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), + "-" + flags.RandomDummyProofDelay.Name, "30m-1x", + }), "invalid random dummy proof delay value") +} + +func (s *ProverTestSuite) TestNewConfigFromCliContext_RandomDelayErrorOrder() { + app := s.SetupApp() + + s.ErrorContains(app.Run([]string{ + "TestNewConfigFromCliContext", + "-" + flags.L1ProverPrivKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), + "-" + flags.OracleProverPrivateKey.Name, os.Getenv("L1_PROVER_PRIVATE_KEY"), + "-" + flags.RandomDummyProofDelay.Name, "1h-30m", + }), "invalid random dummy proof delay value (lower > upper)") +} + +func (s *ProverTestSuite) SetupApp() *cli.App { + app := cli.NewApp() + app.Flags = []cli.Flag{ + &cli.StringFlag{Name: flags.L1WSEndpoint.Name}, + &cli.StringFlag{Name: flags.L1HTTPEndpoint.Name}, + &cli.StringFlag{Name: flags.L2WSEndpoint.Name}, + &cli.StringFlag{Name: flags.L2HTTPEndpoint.Name}, + &cli.StringFlag{Name: flags.TaikoL1Address.Name}, + &cli.StringFlag{Name: flags.TaikoL2Address.Name}, + &cli.StringFlag{Name: flags.L1ProverPrivKey.Name}, + &cli.Uint64Flag{Name: flags.StartingBlockID.Name}, + &cli.BoolFlag{Name: flags.Dummy.Name}, + &cli.StringFlag{Name: flags.RandomDummyProofDelay.Name}, + &cli.BoolFlag{Name: flags.OracleProver.Name}, + &cli.StringFlag{Name: flags.OracleProverPrivateKey.Name}, + &cli.StringFlag{Name: flags.Graffiti.Name}, + &cli.StringFlag{Name: flags.TaikoProverPoolL1Address.Name}, + &cli.Uint64Flag{Name: flags.CheckProofWindowExpiredInterval.Name}, + &cli.BoolFlag{Name: flags.ProveUnassignedBlocks.Name}, + &cli.Uint64Flag{Name: flags.RPCTimeout.Name}, + } + app.Action = func(ctx *cli.Context) error { + _, err := NewConfigFromCliContext(ctx) + s.NotNil(err) + return err + } + return app +} diff --git a/prover/proof_producer/dummy_producer_test.go b/prover/proof_producer/dummy_producer_test.go index 9eb3e1214..27dfb7bf0 100644 --- a/prover/proof_producer/dummy_producer_test.go +++ b/prover/proof_producer/dummy_producer_test.go @@ -85,6 +85,41 @@ func TestProofDelay(t *testing.T) { require.False(t, allSame(delays)) } +func TestProofCancel(t *testing.T) { + dummyProofProducer := &DummyProofProducer{} + + resCh := make(chan *ProofWithHeader, 1) + + blockID := common.Big32 + header := &types.Header{ + ParentHash: randHash(), + UncleHash: randHash(), + Coinbase: common.HexToAddress("0x0000777735367b36bC9B61C50022d9D0700dB4Ec"), + Root: randHash(), + TxHash: randHash(), + ReceiptHash: randHash(), + Difficulty: common.Big0, + Number: common.Big256, + GasLimit: 1024, + GasUsed: 1024, + Time: uint64(time.Now().Unix()), + Extra: randHash().Bytes(), + MixDigest: randHash(), + Nonce: types.BlockNonce{}, + } + require.Nil(t, dummyProofProducer.RequestProof( + context.Background(), + &ProofRequestOptions{}, + blockID, + &bindings.TaikoDataBlockMetadata{}, + header, + resCh, + )) + + // Cancel the proof request, should return nil + require.Nil(t, dummyProofProducer.Cancel(context.Background(), blockID)) +} + func randHash() common.Hash { b := make([]byte, 32) if _, err := rand.Read(b); err != nil {