From 5c4a0251b6a52300a460acd82bd98b23adaeefa5 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 10 May 2024 08:33:54 +0800 Subject: [PATCH] fix(taiko-client): fix an issue in `BlockProposed` event handler && remove some unused code (#17065) --- packages/taiko-client/pkg/rpc/utils.go | 107 ------------------ packages/taiko-client/pkg/rpc/utils_test.go | 41 ------- .../prover/event_handler/block_proposed.go | 24 ++-- packages/taiko-client/prover/prover.go | 8 ++ packages/taiko-client/prover/prover_test.go | 7 +- 5 files changed, 31 insertions(+), 156 deletions(-) diff --git a/packages/taiko-client/pkg/rpc/utils.go b/packages/taiko-client/pkg/rpc/utils.go index e4a25dd6cbb..04a06c5263a 100644 --- a/packages/taiko-client/pkg/rpc/utils.go +++ b/packages/taiko-client/pkg/rpc/utils.go @@ -3,13 +3,11 @@ package rpc import ( "context" "math/big" - "strconv" "strings" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -197,111 +195,6 @@ func GetBlockProofStatus( }, nil } -type AccountPoolContent map[string]map[string]map[string]*types.Transaction -type AccountPoolContentFrom map[string]map[string]*types.Transaction - -// Content GetPendingTxs fetches the pending transactions from tx pool. -func Content(ctx context.Context, client *EthClient) (AccountPoolContent, error) { - ctxWithTimeout, cancel := ctxWithTimeoutOrDefault(ctx, defaultTimeout) - defer cancel() - - var result AccountPoolContent - return result, client.CallContext(ctxWithTimeout, &result, "txpool_content") -} - -// ContentFrom fetches a given account's transactions list from a node's transactions pool. -func ContentFrom( - ctx context.Context, - rawRPC *EthClient, - address common.Address, -) (AccountPoolContentFrom, error) { - ctxWithTimeout, cancel := ctxWithTimeoutOrDefault(ctx, defaultTimeout) - defer cancel() - - var result AccountPoolContentFrom - return result, rawRPC.CallContext( - ctxWithTimeout, - &result, - "txpool_contentFrom", - address, - ) -} - -// IncreaseGasTipCap tries to increase the given transaction's gasTipCap. -func IncreaseGasTipCap( - ctx context.Context, - cli *Client, - opts *bind.TransactOpts, - address common.Address, - txReplacementTipMultiplier *big.Int, - maxGasTipCap *big.Int, -) (*bind.TransactOpts, error) { - ctxWithTimeout, cancel := ctxWithTimeoutOrDefault(ctx, defaultTimeout) - defer cancel() - - log.Info("Try replacing a transaction with same nonce", "sender", address, "nonce", opts.Nonce) - - originalTx, err := GetPendingTxByNonce(ctxWithTimeout, cli.L1, address, opts.Nonce.Uint64()) - if err != nil || originalTx == nil { - log.Warn( - "Original transaction not found", - "sender", address, - "nonce", opts.Nonce, - "error", err, - ) - - opts.GasTipCap = new(big.Int).Mul(opts.GasTipCap, txReplacementTipMultiplier) - } else { - log.Info( - "Original transaction to replace", - "sender", address, - "nonce", opts.Nonce, - "gasTipCap", originalTx.GasTipCap(), - "gasFeeCap", originalTx.GasFeeCap(), - ) - - opts.GasTipCap = new(big.Int).Mul(originalTx.GasTipCap(), txReplacementTipMultiplier) - } - - if maxGasTipCap != nil && opts.GasTipCap.Cmp(maxGasTipCap) > 0 { - log.Info( - "New gasTipCap exceeds limit, keep waiting", - "multiplier", txReplacementTipMultiplier, - "newGasTipCap", opts.GasTipCap, - "maxTipCap", maxGasTipCap, - ) - return nil, txpool.ErrReplaceUnderpriced - } - - return opts, nil -} - -// GetPendingTxByNonce tries to retrieve a pending transaction with a given nonce in a node's mempool. -func GetPendingTxByNonce( - ctx context.Context, - cli *EthClient, - address common.Address, - nonce uint64, -) (*types.Transaction, error) { - ctxWithTimeout, cancel := ctxWithTimeoutOrDefault(ctx, defaultTimeout) - defer cancel() - - content, err := ContentFrom(ctxWithTimeout, cli, address) - if err != nil { - return nil, err - } - - for _, txMap := range content { - for txNonce, tx := range txMap { - if txNonce == strconv.Itoa(int(nonce)) { - return tx, nil - } - } - } - - return nil, nil -} - // SetHead makes a `debug_setHead` RPC call to set the chain's head, should only be used // for testing purpose. func SetHead(ctx context.Context, client *EthClient, headNum *big.Int) error { diff --git a/packages/taiko-client/pkg/rpc/utils_test.go b/packages/taiko-client/pkg/rpc/utils_test.go index bc5d84245b1..90152b20729 100644 --- a/packages/taiko-client/pkg/rpc/utils_test.go +++ b/packages/taiko-client/pkg/rpc/utils_test.go @@ -2,15 +2,9 @@ package rpc import ( "context" - "math/big" - "os" - "strconv" "testing" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/require" ) @@ -22,38 +16,3 @@ func TestStringToBytes32(t *testing.T) { require.Equal(t, [32]byte{}, StringToBytes32("")) require.Equal(t, [32]byte{0x61, 0x62, 0x63}, StringToBytes32("abc")) } - -func TestL1ContentFrom(t *testing.T) { - client := newTestClient(t) - l2Head, err := client.L2.HeaderByNumber(context.Background(), nil) - require.Nil(t, err) - - baseFeeInfo, err := client.TaikoL2.GetBasefee(nil, 0, uint32(l2Head.GasUsed)) - require.Nil(t, err) - - testAddrPrivKey, err := crypto.ToECDSA(common.FromHex(os.Getenv("L1_PROPOSER_PRIVATE_KEY"))) - require.Nil(t, err) - - testAddr := crypto.PubkeyToAddress(testAddrPrivKey.PublicKey) - - nonce, err := client.L2.PendingNonceAt(context.Background(), testAddr) - require.Nil(t, err) - - tx := types.NewTransaction( - nonce, - testAddr, - common.Big1, - 100000, - new(big.Int).SetUint64(uint64(10*params.GWei)+baseFeeInfo.Basefee.Uint64()), - []byte{}, - ) - signedTx, err := types.SignTx(tx, types.LatestSignerForChainID(client.L2.ChainID), testAddrPrivKey) - require.Nil(t, err) - require.Nil(t, client.L2.SendTransaction(context.Background(), signedTx)) - - content, err := ContentFrom(context.Background(), client.L2, testAddr) - require.Nil(t, err) - - require.NotZero(t, len(content["pending"])) - require.Equal(t, signedTx.Nonce(), content["pending"][strconv.Itoa(int(signedTx.Nonce()))].Nonce()) -} diff --git a/packages/taiko-client/prover/event_handler/block_proposed.go b/packages/taiko-client/prover/event_handler/block_proposed.go index 6a0136585a0..3b7d616024d 100644 --- a/packages/taiko-client/prover/event_handler/block_proposed.go +++ b/packages/taiko-client/prover/event_handler/block_proposed.go @@ -295,14 +295,24 @@ func (h *BlockProposedEventHandler) checkExpirationAndSubmitProof( return nil } - // The proof submitted to protocol is invalid. - h.proofContestCh <- &proofProducer.ContestRequestBody{ - BlockID: e.BlockId, - ProposedIn: new(big.Int).SetUint64(e.Raw.BlockNumber), - ParentHash: proofStatus.ParentHeader.Hash(), - Meta: &e.Meta, - Tier: e.Meta.MinTier, + // If the current proof has not been contested, we should contest it at first. + if proofStatus.CurrentTransitionState.Contester == rpc.ZeroAddress { + h.proofContestCh <- &proofProducer.ContestRequestBody{ + BlockID: e.BlockId, + ProposedIn: new(big.Int).SetUint64(e.Raw.BlockNumber), + ParentHash: proofStatus.ParentHeader.Hash(), + Meta: &e.Meta, + Tier: e.Meta.MinTier, + } + } else { + // The invalid proof submitted to protocol is contested by another prover, + // we need to submit a proof with a higher tier. + h.proofSubmissionCh <- &proofProducer.ProofRequestBody{ + Tier: proofStatus.CurrentTransitionState.Tier + 1, + Event: e, + } } + return nil } diff --git a/packages/taiko-client/prover/prover.go b/packages/taiko-client/prover/prover.go index 9da418561d3..10e0bd5f3f8 100644 --- a/packages/taiko-client/prover/prover.go +++ b/packages/taiko-client/prover/prover.go @@ -446,6 +446,10 @@ func (p *Prover) Name() string { func (p *Prover) selectSubmitter(minTier uint16) proofSubmitter.Submitter { for _, s := range p.proofSubmitters { if s.Tier() >= minTier { + if !p.IsGuardianProver() && s.Tier() >= encoding.TierGuardianMinorityID { + continue + } + log.Debug("Proof submitter selected", "tier", s.Tier(), "minTier", minTier) return s } @@ -460,6 +464,10 @@ func (p *Prover) selectSubmitter(minTier uint16) proofSubmitter.Submitter { func (p *Prover) getSubmitterByTier(tier uint16) proofSubmitter.Submitter { for _, s := range p.proofSubmitters { if s.Tier() == tier { + if !p.IsGuardianProver() && s.Tier() >= encoding.TierGuardianMinorityID { + continue + } + return s } } diff --git a/packages/taiko-client/prover/prover_test.go b/packages/taiko-client/prover/prover_test.go index fa9858dd307..101c3607c5f 100644 --- a/packages/taiko-client/prover/prover_test.go +++ b/packages/taiko-client/prover/prover_test.go @@ -358,7 +358,9 @@ func (s *ProverTestSuite) TestProveExpiredUnassignedBlock() { } func (s *ProverTestSuite) TestSelectSubmitter() { - submitter := s.p.selectSubmitter(encoding.TierGuardianMajorityID - 1) + s.p.cfg.GuardianProverMajorityAddress = common.HexToAddress(os.Getenv("GUARDIAN_PROVER_CONTRACT_ADDRESS")) + s.True(s.p.IsGuardianProver()) + submitter := s.p.selectSubmitter(encoding.TierGuardianMinorityID + 1) s.NotNil(submitter) s.Equal(encoding.TierGuardianMajorityID, submitter.Tier()) } @@ -369,6 +371,9 @@ func (s *ProverTestSuite) TestSelectSubmitterNotFound() { } func (s *ProverTestSuite) TestGetSubmitterByTier() { + s.p.cfg.GuardianProverMajorityAddress = common.HexToAddress(os.Getenv("GUARDIAN_PROVER_CONTRACT_ADDRESS")) + s.True(s.p.IsGuardianProver()) + submitter := s.p.getSubmitterByTier(encoding.TierGuardianMajorityID) s.NotNil(submitter) s.Equal(encoding.TierGuardianMajorityID, submitter.Tier())