github.com/klaytn/klaytn@v1.12.1/node/sc/sub_bridge_handler.go (about)

     1  // Copyright 2019 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package sc
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"math/big"
    24  
    25  	"github.com/klaytn/klaytn/blockchain"
    26  	"github.com/klaytn/klaytn/blockchain/types"
    27  	"github.com/klaytn/klaytn/common"
    28  	"github.com/klaytn/klaytn/networks/p2p"
    29  	"github.com/klaytn/klaytn/params"
    30  	"github.com/klaytn/klaytn/rlp"
    31  )
    32  
    33  const (
    34  	SyncRequestInterval = 10
    35  )
    36  
    37  var (
    38  	ErrInvalidBlock              = errors.New("block is invalid")
    39  	ErrUnknownBridgeContractAddr = errors.New("The given address was not found in the bridge contract list")
    40  )
    41  
    42  // parentChainInfo handles the information of parent chain, which is needed from child chain.
    43  type parentChainInfo struct {
    44  	Nonce          uint64
    45  	GasPrice       uint64
    46  	KIP71Config    params.KIP71Config
    47  	IsMagmaEnabled bool
    48  }
    49  
    50  type InvalidParentChainTx struct {
    51  	TxHash common.Hash
    52  	ErrStr string
    53  }
    54  
    55  type SubBridgeHandler struct {
    56  	subbridge *SubBridge
    57  	// parentChainID is the first received chainID from parent chain peer.
    58  	// It will be reset to nil if there's no parent peer.
    59  	parentChainID *big.Int
    60  	// remoteGasPrice means gas price of parent chain, used to make a service chain transaction.
    61  	// Therefore, for now, it is only used by child chain side.
    62  	remoteGasPrice        uint64
    63  	mainChainAccountNonce uint64
    64  	nonceSynced           bool
    65  	chainTxPeriod         uint64
    66  
    67  	latestTxCountAddedBlockNumber uint64
    68  	txCountStartingBlockNumber    uint64
    69  	txCount                       uint64 // accumulated tx counts in blocks for each anchoring period.
    70  
    71  	// TODO-Klaytn-ServiceChain Need to limit the number independently? Or just managing the size of sentServiceChainTxs?
    72  	sentServiceChainTxsLimit uint64
    73  
    74  	skipSyncBlockCount int32
    75  }
    76  
    77  func NewSubBridgeHandler(main *SubBridge) (*SubBridgeHandler, error) {
    78  	return &SubBridgeHandler{
    79  		subbridge:                     main,
    80  		parentChainID:                 new(big.Int).SetUint64(main.config.ParentChainID),
    81  		remoteGasPrice:                uint64(0),
    82  		mainChainAccountNonce:         uint64(0),
    83  		nonceSynced:                   false,
    84  		chainTxPeriod:                 main.config.AnchoringPeriod,
    85  		latestTxCountAddedBlockNumber: uint64(0),
    86  		sentServiceChainTxsLimit:      main.config.SentChainTxsLimit,
    87  	}, nil
    88  }
    89  
    90  func (sbh *SubBridgeHandler) setParentChainID(chainId *big.Int) {
    91  	sbh.parentChainID = chainId
    92  	sbh.subbridge.bridgeAccounts.pAccount.SetChainID(chainId)
    93  }
    94  
    95  func (sbh *SubBridgeHandler) getParentChainID() *big.Int {
    96  	return sbh.parentChainID
    97  }
    98  
    99  func (sbh *SubBridgeHandler) LockParentOperator() {
   100  	sbh.subbridge.bridgeAccounts.pAccount.Lock()
   101  }
   102  
   103  func (sbh *SubBridgeHandler) UnLockParentOperator() {
   104  	sbh.subbridge.bridgeAccounts.pAccount.UnLock()
   105  }
   106  
   107  // getParentOperatorNonce returns the parent chain operator nonce of parent chain operator address.
   108  func (sbh *SubBridgeHandler) getParentOperatorNonce() uint64 {
   109  	return sbh.subbridge.bridgeAccounts.pAccount.GetNonce()
   110  }
   111  
   112  // setParentOperatorNonce sets the parent chain operator nonce of parent chain operator address.
   113  func (sbh *SubBridgeHandler) setParentOperatorNonce(newNonce uint64) {
   114  	sbh.subbridge.bridgeAccounts.pAccount.SetNonce(newNonce)
   115  }
   116  
   117  // addParentOperatorNonce increases nonce by number
   118  func (sbh *SubBridgeHandler) addParentOperatorNonce(number uint64) {
   119  	sbh.subbridge.bridgeAccounts.pAccount.IncNonce()
   120  }
   121  
   122  // getParentOperatorNonceSynced returns whether the parent chain operator account nonce is synced or not.
   123  func (sbh *SubBridgeHandler) getParentOperatorNonceSynced() bool {
   124  	return sbh.nonceSynced
   125  }
   126  
   127  // getParentOperatorBalance returns the parent chain operator balance.
   128  func (sbh *SubBridgeHandler) getParentOperatorBalance() (*big.Int, error) {
   129  	ctx, cancel := context.WithTimeout(context.Background(), timeout)
   130  	defer cancel()
   131  	return sbh.subbridge.remoteBackend.BalanceAt(ctx, sbh.subbridge.bridgeAccounts.pAccount.address, nil)
   132  }
   133  
   134  // getParentBridgeContractBalance returns the parent bridge contract's balance.
   135  func (sbh *SubBridgeHandler) getParentBridgeContractBalance(addr common.Address) (*big.Int, error) {
   136  	ctx, cancel := context.WithTimeout(context.Background(), timeout)
   137  	defer cancel()
   138  
   139  	if !sbh.subbridge.bridgeManager.IsInParentAddrs(addr) {
   140  		logger.Error(ErrUnknownBridgeContractAddr.Error(), "addr", addr)
   141  		return common.Big0, ErrUnknownBridgeContractAddr
   142  	}
   143  	return sbh.subbridge.remoteBackend.BalanceAt(ctx, addr, nil)
   144  }
   145  
   146  // setParentOperatorNonceSynced sets whether the parent chain operator account nonce is synced or not.
   147  func (sbh *SubBridgeHandler) setParentOperatorNonceSynced(synced bool) {
   148  	sbh.nonceSynced = synced
   149  }
   150  
   151  func (sbh *SubBridgeHandler) getChildOperatorNonce() uint64 {
   152  	return sbh.subbridge.txPool.GetPendingNonce(sbh.subbridge.bridgeAccounts.cAccount.address)
   153  }
   154  
   155  // getChildOperatorBalance returns the child chain operator balance.
   156  func (sbh *SubBridgeHandler) getChildOperatorBalance() (*big.Int, error) {
   157  	ctx, cancel := context.WithTimeout(context.Background(), timeout)
   158  	defer cancel()
   159  	return sbh.subbridge.localBackend.BalanceAt(ctx, sbh.subbridge.bridgeAccounts.cAccount.address, nil)
   160  }
   161  
   162  // getChildBridgeContractBalance returns the child bridge contract's balance.
   163  func (sbh *SubBridgeHandler) getChildBridgeContractBalance(addr common.Address) (*big.Int, error) {
   164  	ctx, cancel := context.WithTimeout(context.Background(), timeout)
   165  	defer cancel()
   166  
   167  	if !sbh.subbridge.bridgeManager.IsInChildAddrs(addr) {
   168  		logger.Error(ErrUnknownBridgeContractAddr.Error(), "addr", addr)
   169  		return common.Big0, ErrUnknownBridgeContractAddr
   170  	}
   171  	return sbh.subbridge.localBackend.BalanceAt(ctx, addr, nil)
   172  }
   173  
   174  func (sbh *SubBridgeHandler) getRemoteGasPrice() uint64 {
   175  	return sbh.remoteGasPrice
   176  }
   177  
   178  // setRemoteGasPrice sets parent chain's gasprice
   179  func (sbh *SubBridgeHandler) setRemoteGasPrice(gasPrice uint64) {
   180  	sbh.subbridge.bridgeAccounts.pAccount.SetGasPrice(big.NewInt(int64(gasPrice)))
   181  	sbh.remoteGasPrice = gasPrice
   182  }
   183  
   184  // setRemoteChainValues sets parent chain's configuration values
   185  func (sbh *SubBridgeHandler) setRemoteChainValues(pcInfo parentChainInfo) {
   186  	sbh.setRemoteGasPrice(pcInfo.GasPrice)
   187  	if pcInfo.IsMagmaEnabled {
   188  		// Set parent chain's gasprice with upperboundbasefee
   189  		sbh.remoteGasPrice = pcInfo.KIP71Config.UpperBoundBaseFee
   190  		sbh.subbridge.bridgeAccounts.SetParentKIP71Config(pcInfo.KIP71Config)
   191  		kip71Config := sbh.subbridge.bridgeAccounts.GetParentKIP71Config()
   192  
   193  		logger.Info("[SC][Sync] Updated parent chain values", "gasPrice", sbh.subbridge.bridgeAccounts.GetParentGasPrice(),
   194  			"LowerBoundBaseFee", kip71Config.LowerBoundBaseFee,
   195  			"UpperBoundBaseFee", kip71Config.UpperBoundBaseFee,
   196  			"GasTarget", kip71Config.GasTarget,
   197  			"MaxBlockGasUsedForBaseFee", kip71Config.MaxBlockGasUsedForBaseFee,
   198  			"BaseFeeDenominator", kip71Config.BaseFeeDenominator)
   199  	} else {
   200  		logger.Info("Updated parent chain's gas price", "gasPrice", sbh.subbridge.bridgeAccounts.GetParentGasPrice())
   201  	}
   202  }
   203  
   204  // GetParentOperatorAddr returns a pointer of a hex address of an account used for parent chain.
   205  // If given as a parameter, it will use it. If not given, it will use the address of the public key
   206  // derived from chainKey.
   207  func (sbh *SubBridgeHandler) GetParentOperatorAddr() *common.Address {
   208  	return &sbh.subbridge.bridgeAccounts.pAccount.address
   209  }
   210  
   211  // GetChildOperatorAddr returns a pointer of a hex address of an account used for child chain.
   212  // If given as a parameter, it will use it. If not given, it will use the address of the public key
   213  // derived from chainKey.
   214  func (sbh *SubBridgeHandler) GetChildOperatorAddr() *common.Address {
   215  	return &sbh.subbridge.bridgeAccounts.cAccount.address
   216  }
   217  
   218  // GetAnchoringPeriod returns the period to make and send a chain transaction to parent chain.
   219  func (sbh *SubBridgeHandler) GetAnchoringPeriod() uint64 {
   220  	return sbh.chainTxPeriod
   221  }
   222  
   223  // GetSentChainTxsLimit returns the maximum number of stored chain transactions for resending.
   224  func (sbh *SubBridgeHandler) GetSentChainTxsLimit() uint64 {
   225  	return sbh.sentServiceChainTxsLimit
   226  }
   227  
   228  func (sbh *SubBridgeHandler) HandleMainMsg(p BridgePeer, msg p2p.Msg) error {
   229  	// Handle the message depending on its contents
   230  	switch msg.Code {
   231  	case ServiceChainResponse:
   232  		logger.Trace("received rpc ServiceChainResponse")
   233  		data := make([]byte, msg.Size)
   234  		err := msg.Decode(&data)
   235  		if err != nil {
   236  			logger.Error("failed to decode the p2p ServiceChainResponse message", "err", err)
   237  			return nil
   238  		}
   239  		logger.Trace("send rpc response to the rpc client")
   240  		_, err = sbh.subbridge.rpcConn.Write(data)
   241  		if err != nil {
   242  			return err
   243  		}
   244  		return nil
   245  	case StatusMsg:
   246  		return nil
   247  	case ServiceChainParentChainInfoResponseMsg:
   248  		logger.Debug("received ServiceChainParentChainInfoResponseMsg")
   249  		if err := sbh.handleParentChainInfoResponseMsg(p, msg); err != nil {
   250  			return err
   251  		}
   252  
   253  	case ServiceChainReceiptResponseMsg:
   254  		logger.Debug("received ServiceChainReceiptResponseMsg")
   255  		if err := sbh.handleParentChainReceiptResponseMsg(p, msg); err != nil {
   256  			return err
   257  		}
   258  	case ServiceChainInvalidTxResponseMsg:
   259  		logger.Debug("received ServiceChainInvalidTxResponseMsg")
   260  		if err := sbh.handleParentChainInvalidTxResponseMsg(msg); err != nil {
   261  			return err
   262  		}
   263  	default:
   264  		return errResp(ErrInvalidMsgCode, "%v", msg.Code)
   265  	}
   266  	return nil
   267  }
   268  
   269  // handleParentChainInfoResponseMsg handles parent chain info response message from parent chain.
   270  // It will update the ParentOperatorNonce and remoteGasPrice of ServiceChainProtocolManager.
   271  func (sbh *SubBridgeHandler) handleParentChainInfoResponseMsg(p BridgePeer, msg p2p.Msg) error {
   272  	var pcInfo parentChainInfo
   273  	if err := msg.Decode(&pcInfo); err != nil {
   274  		logger.Error("failed to decode", "err", err)
   275  		return errResp(ErrDecode, "msg %v: %v", msg, err)
   276  	}
   277  	sbh.LockParentOperator()
   278  	defer sbh.UnLockParentOperator()
   279  
   280  	poolNonce := sbh.subbridge.bridgeTxPool.GetMaxTxNonce(sbh.GetParentOperatorAddr())
   281  	if poolNonce > 0 {
   282  		poolNonce += 1
   283  		// just check
   284  		if sbh.getParentOperatorNonce() > poolNonce {
   285  			logger.Error("parent chain operator nonce is bigger than the chain pool nonce.", "BridgeTxPoolNonce", poolNonce, "mainChainAccountNonce", sbh.getParentOperatorNonce())
   286  		}
   287  		if poolNonce < pcInfo.Nonce {
   288  			// BridgeTxPool journal miss txs which already sent to parent-chain
   289  			logger.Error("chain pool nonce is less than the parent chain nonce.", "chainPoolNonce", poolNonce, "receivedNonce", pcInfo.Nonce)
   290  			sbh.setParentOperatorNonce(pcInfo.Nonce)
   291  		} else {
   292  			// BridgeTxPool journal has txs which don't receive receipt from parent-chain
   293  			sbh.setParentOperatorNonce(poolNonce)
   294  		}
   295  	} else if sbh.getParentOperatorNonce() > pcInfo.Nonce {
   296  		logger.Error("parent chain operator nonce is bigger than the received nonce.", "mainChainAccountNonce", sbh.getParentOperatorNonce(), "receivedNonce", pcInfo.Nonce)
   297  		sbh.setParentOperatorNonce(pcInfo.Nonce)
   298  	} else {
   299  		// there is no tx in bridgetTxPool, so parent-chain's nonce is used
   300  		sbh.setParentOperatorNonce(pcInfo.Nonce)
   301  	}
   302  	sbh.setParentOperatorNonceSynced(true)
   303  	sbh.setRemoteChainValues(pcInfo)
   304  	logger.Info("ParentChainNonceResponse", "receivedNonce", pcInfo.Nonce, "gasPrice", pcInfo.GasPrice, "mainChainAccountNonce", sbh.getParentOperatorNonce())
   305  	return nil
   306  }
   307  
   308  // handleParentChainReceiptResponseMsg handles receipt response message from parent chain.
   309  // It will store the received receipts and remove corresponding transaction in the resending list.
   310  func (sbh *SubBridgeHandler) handleParentChainReceiptResponseMsg(p BridgePeer, msg p2p.Msg) error {
   311  	// TODO-Klaytn-ServiceChain Need to add an option, not to write receipts.
   312  	// Decode the retrieval message
   313  	var receipts []*types.ReceiptForStorage
   314  	if err := msg.Decode(&receipts); err != nil && err != rlp.EOL {
   315  		return errResp(ErrDecode, "msg %v: %v", msg, err)
   316  	}
   317  	// Stores receipt and remove tx from sentServiceChainTxs only if the tx is successfully executed.
   318  	sbh.writeServiceChainTxReceipts(sbh.subbridge.blockchain, receipts)
   319  	return nil
   320  }
   321  
   322  // genUnsignedChainDataAnchoringTx generates an unsigned transaction, which type is TxTypeChainDataAnchoring.
   323  // Nonce of account used for service chain transaction will be increased after the signing.
   324  func (sbh *SubBridgeHandler) genUnsignedChainDataAnchoringTx(block *types.Block) (*types.Transaction, error) {
   325  	anchoringData, err := types.NewAnchoringDataType0(block, block.NumberU64()-sbh.txCountStartingBlockNumber+1, sbh.txCount)
   326  	if err != nil {
   327  		return nil, err
   328  	}
   329  	encodedCCTxData, err := rlp.EncodeToBytes(anchoringData)
   330  	if err != nil {
   331  		return nil, err
   332  	}
   333  
   334  	values := map[types.TxValueKeyType]interface{}{
   335  		types.TxValueKeyNonce:        sbh.getParentOperatorNonce(), // parent chain operator nonce will be increased after signing a transaction.
   336  		types.TxValueKeyFrom:         *sbh.GetParentOperatorAddr(),
   337  		types.TxValueKeyGasLimit:     uint64(100000), // TODO-Klaytn-ServiceChain should define proper gas limit
   338  		types.TxValueKeyGasPrice:     new(big.Int).SetUint64(sbh.remoteGasPrice),
   339  		types.TxValueKeyAnchoredData: encodedCCTxData,
   340  	}
   341  
   342  	txType := types.TxTypeChainDataAnchoring
   343  
   344  	if feePayer := sbh.subbridge.bridgeAccounts.GetParentOperatorFeePayer(); feePayer != (common.Address{}) {
   345  		values[types.TxValueKeyFeePayer] = feePayer
   346  		txType = types.TxTypeFeeDelegatedChainDataAnchoring
   347  	}
   348  
   349  	if tx, err := types.NewTransactionWithMap(txType, values); err != nil {
   350  		return nil, err
   351  	} else {
   352  		return tx, nil
   353  	}
   354  }
   355  
   356  // LocalChainHeadEvent deals with servicechain feature to generate/broadcast service chain transactions and request receipts.
   357  func (sbh *SubBridgeHandler) LocalChainHeadEvent(block *types.Block) {
   358  	if sbh.getParentOperatorNonceSynced() {
   359  		// TODO-Klaytn if other feature use below chainTx, this condition should be refactored to use it for other feature.
   360  		if sbh.subbridge.GetAnchoringTx() {
   361  			sbh.blockAnchoringManager(block)
   362  		}
   363  		sbh.broadcastServiceChainTx()
   364  		sbh.broadcastServiceChainReceiptRequest()
   365  
   366  		sbh.skipSyncBlockCount = 0
   367  	} else {
   368  		sbh.txCountStartingBlockNumber = 0
   369  		if sbh.skipSyncBlockCount%SyncRequestInterval == 0 {
   370  			// TODO-Klaytn too many request while sync main-net
   371  			sbh.SyncNonceAndGasPrice()
   372  			// check tx's receipts which parent-chain already executed in BridgeTxPool
   373  			go sbh.broadcastServiceChainReceiptRequest()
   374  		}
   375  		sbh.skipSyncBlockCount++
   376  	}
   377  }
   378  
   379  // handleParentChainInvalidTxResponseMsg receives unexecuted txs which were not executed by some of the reasons (e.g., lower gas price)
   380  // and removes them from bridgeTxPool to prevent resending **as it is without necessary modification**
   381  func (sbh *SubBridgeHandler) handleParentChainInvalidTxResponseMsg(msg p2p.Msg) error {
   382  	var invalidTxs []InvalidParentChainTx
   383  	if err := msg.Decode(&invalidTxs); err != nil && err != rlp.EOL {
   384  		return errResp(ErrDecode, "msg %v: %v", msg, err)
   385  	}
   386  	txPool := sbh.subbridge.GetBridgeTxPool()
   387  	for _, invalidTx := range invalidTxs {
   388  		if tx := txPool.Get(invalidTx.TxHash); tx != nil {
   389  			logger.Error("A bridge tx was not executed", "err", invalidTx.ErrStr,
   390  				"txHash", invalidTx.TxHash.String(),
   391  				"txGasPrice", tx.GasPrice().Uint64())
   392  			if invalidTx.ErrStr == blockchain.ErrGasPriceBelowBaseFee.Error() {
   393  				logger.Info("[SC][HandleTxDropped] Request gasPrice and Magma values to parent chain")
   394  				sbh.SyncNonceAndGasPrice()
   395  
   396  				logger.Error("Bridge tx is removed which has lower gasPrice than UpperBoundBaseFee")
   397  				// Remove the tx and delegate re-execution of the tx by Value Transfer Recovery feature
   398  				if err := sbh.subbridge.GetBridgeTxPool().RemoveTx(tx); err != nil {
   399  					logger.Error("Failed to remove bridge tx",
   400  						"txType", tx.Type(), "txNonce", tx.Nonce(), "txHash", tx.Hash().String())
   401  				} else {
   402  					logger.Info("Removed bridge tx",
   403  						"txType", tx.Type(), "txNonce", tx.Nonce(), "txHash", tx.Hash().String())
   404  				}
   405  			} // TODO-ServiceChain: Consider other types of tx failures with else {}
   406  		}
   407  	}
   408  	return nil
   409  }
   410  
   411  // broadcastServiceChainTx broadcasts service chain transactions to parent chain peers.
   412  // It signs the given unsigned transaction with parent chain ID and then send it to its
   413  // parent chain peers.
   414  func (sbh *SubBridgeHandler) broadcastServiceChainTx() {
   415  	parentChainID := sbh.parentChainID
   416  	if parentChainID == nil {
   417  		logger.Error("unexpected nil parentChainID while broadcastServiceChainTx")
   418  	}
   419  	txs := sbh.subbridge.GetBridgeTxPool().PendingTxsByAddress(&sbh.subbridge.bridgeAccounts.pAccount.address, int(sbh.GetSentChainTxsLimit())) // TODO-Klaytn-Servicechain change GetSentChainTxsLimit type to int from uint64
   420  	peers := sbh.subbridge.BridgePeerSet().peers
   421  
   422  	for _, peer := range peers {
   423  		if peer.GetChainID().Cmp(parentChainID) != 0 {
   424  			logger.Error("parent peer with different parent chainID", "peerID", peer.GetID(), "peer chainID", peer.GetChainID(), "parent chainID", parentChainID)
   425  			continue
   426  		}
   427  		peer.SendServiceChainTxs(txs)
   428  		logger.Trace("sent ServiceChainTxData", "peerID", peer.GetID())
   429  	}
   430  	logger.Trace("broadcastServiceChainTx ServiceChainTxData", "len(txs)", len(txs), "len(peers)", len(peers))
   431  }
   432  
   433  // writeServiceChainTxReceipts writes the received receipts of service chain transactions.
   434  func (sbh *SubBridgeHandler) writeServiceChainTxReceipts(bc *blockchain.BlockChain, receipts []*types.ReceiptForStorage) {
   435  	for _, receipt := range receipts {
   436  		txHash := receipt.TxHash
   437  		if tx := sbh.subbridge.GetBridgeTxPool().Get(txHash); tx != nil {
   438  			if tx.Type().IsChainDataAnchoring() {
   439  				data, err := tx.AnchoredData()
   440  				if err != nil {
   441  					logger.Error("failed to get anchoring data", "txHash", txHash.String(), "err", err)
   442  					continue
   443  				}
   444  				decodedData, err := types.DecodeAnchoringData(data)
   445  				if err != nil {
   446  					logger.Warn("failed to decode anchoring tx", "txHash", txHash.String(), "err", err)
   447  					continue
   448  				}
   449  				sbh.WriteReceiptFromParentChain(decodedData.GetBlockHash(), (*types.Receipt)(receipt))
   450  				sbh.WriteAnchoredBlockNumber(decodedData.GetBlockNumber().Uint64())
   451  			}
   452  			// TODO-Klaytn-ServiceChain: support other tx types if needed.
   453  			sbh.subbridge.GetBridgeTxPool().RemoveTx(tx)
   454  		} else {
   455  			logger.Trace("received service chain transaction receipt does not exist in sentServiceChainTxs", "txHash", txHash.String())
   456  		}
   457  		logger.Trace("received service chain transaction receipt", "anchoring txHash", txHash.String())
   458  	}
   459  }
   460  
   461  func (sbh *SubBridgeHandler) RegisterNewPeer(p BridgePeer) error {
   462  	sbh.subbridge.addPeerCh <- struct{}{}
   463  
   464  	if sbh.getParentChainID().Cmp(p.GetChainID()) != 0 {
   465  		return fmt.Errorf("attempt to add a peer with different chainID failed! existing chainID: %v, new chainID: %v", sbh.getParentChainID(), p.GetChainID())
   466  	}
   467  	// sync nonce and gasprice with peer
   468  	sbh.SyncNonceAndGasPrice()
   469  
   470  	return nil
   471  }
   472  
   473  // broadcastServiceChainReceiptRequest broadcasts receipt requests for service chain transactions.
   474  func (sbh *SubBridgeHandler) broadcastServiceChainReceiptRequest() {
   475  	hashes := sbh.subbridge.GetBridgeTxPool().PendingTxHashesByAddress(sbh.GetParentOperatorAddr(), int(sbh.GetSentChainTxsLimit())) // TODO-Klaytn-Servicechain change GetSentChainTxsLimit type to int from uint64
   476  	for _, peer := range sbh.subbridge.BridgePeerSet().peers {
   477  		peer.SendServiceChainReceiptRequest(hashes)
   478  		logger.Debug("sent ServiceChainReceiptRequest", "peerID", peer.GetID(), "numReceiptsRequested", len(hashes))
   479  	}
   480  }
   481  
   482  // updateTxCount update txCount to insert into anchoring tx.
   483  func (sbh *SubBridgeHandler) updateTxCount(block *types.Block) error {
   484  	if block == nil {
   485  		return ErrInvalidBlock
   486  	}
   487  
   488  	if sbh.txCountStartingBlockNumber == 0 {
   489  		sbh.txCount = 0 // reset for the next anchoring period
   490  		sbh.txCountStartingBlockNumber = block.NumberU64()
   491  	}
   492  
   493  	var startBlkNum uint64
   494  	if sbh.latestTxCountAddedBlockNumber == 0 {
   495  		startBlkNum = block.NumberU64()
   496  	} else {
   497  		startBlkNum = sbh.latestTxCountAddedBlockNumber + 1
   498  	}
   499  
   500  	if startBlkNum < sbh.txCountStartingBlockNumber {
   501  		startBlkNum = sbh.txCountStartingBlockNumber
   502  	}
   503  
   504  	for i := startBlkNum; i <= block.NumberU64(); i++ {
   505  		b := sbh.subbridge.blockchain.GetBlockByNumber(i)
   506  		if b == nil {
   507  			logger.Error("blockAnchoringManager: break to generateAndAddAnchoringTxIntoTxPool by the missed block", "missedBlockNumber", i)
   508  			break
   509  		}
   510  		sbh.txCount += uint64(b.Transactions().Len())
   511  		sbh.UpdateLatestTxCountAddedBlockNumber(i)
   512  	}
   513  
   514  	return nil
   515  }
   516  
   517  // blockAnchoringManager generates anchoring transactions and updates transaction count.
   518  func (sbh *SubBridgeHandler) blockAnchoringManager(block *types.Block) error {
   519  	if err := sbh.updateTxCount(block); err != nil {
   520  		return err
   521  	}
   522  	return sbh.generateAndAddAnchoringTxIntoTxPool(block)
   523  }
   524  
   525  func (sbh *SubBridgeHandler) generateAndAddAnchoringTxIntoTxPool(block *types.Block) error {
   526  	if block == nil {
   527  		return ErrInvalidBlock
   528  	}
   529  
   530  	// Generating Anchoring Tx
   531  	if block.NumberU64()%sbh.chainTxPeriod != 0 {
   532  		return nil
   533  	}
   534  	sbh.LockParentOperator()
   535  	defer sbh.UnLockParentOperator()
   536  
   537  	unsignedTx, err := sbh.genUnsignedChainDataAnchoringTx(block)
   538  	if err != nil {
   539  		logger.Error("Failed to generate service chain transaction", "blockNum", block.NumberU64(), "err", err)
   540  		return err
   541  	}
   542  	txCount := sbh.txCount
   543  	// Reset for the next anchoring period.
   544  	sbh.txCount = 0
   545  	sbh.txCountStartingBlockNumber = block.NumberU64() + 1
   546  
   547  	signedTx, err := sbh.subbridge.bridgeAccounts.pAccount.SignTx(unsignedTx)
   548  	if err != nil {
   549  		logger.Error("failed signing tx", "err", err)
   550  		return err
   551  	}
   552  	if err := sbh.subbridge.GetBridgeTxPool().AddLocal(signedTx); err == nil {
   553  		sbh.addParentOperatorNonce(1)
   554  	} else {
   555  		logger.Debug("failed to add tx into bridge txpool", "err", err)
   556  		return err
   557  	}
   558  
   559  	logger.Info("Generate an anchoring tx", "blockNum", block.NumberU64(), "blockhash", block.Hash().String(), "txCount", txCount, "txHash", signedTx.Hash().String())
   560  
   561  	return nil
   562  }
   563  
   564  // SyncNonceAndGasPrice requests the nonce of address used for service chain tx to parent chain peers.
   565  func (scpm *SubBridgeHandler) SyncNonceAndGasPrice() {
   566  	addr := scpm.GetParentOperatorAddr()
   567  	for _, peer := range scpm.subbridge.BridgePeerSet().peers {
   568  		peer.SendServiceChainInfoRequest(addr)
   569  	}
   570  }
   571  
   572  // GetLatestAnchoredBlockNumber returns the latest block number whose data has been anchored to the parent chain.
   573  func (sbh *SubBridgeHandler) GetLatestAnchoredBlockNumber() uint64 {
   574  	return sbh.subbridge.ChainDB().ReadAnchoredBlockNumber()
   575  }
   576  
   577  // UpdateLatestTxCountAddedBlockNumber sets the latestTxCountAddedBlockNumber to the block number of the last anchoring tx which was added into bridge txPool.
   578  func (sbh *SubBridgeHandler) UpdateLatestTxCountAddedBlockNumber(newLatestAnchoredBN uint64) {
   579  	if sbh.latestTxCountAddedBlockNumber < newLatestAnchoredBN {
   580  		sbh.latestTxCountAddedBlockNumber = newLatestAnchoredBN
   581  	}
   582  }
   583  
   584  // WriteAnchoredBlockNumber writes the block number whose data has been anchored to the parent chain.
   585  func (sbh *SubBridgeHandler) WriteAnchoredBlockNumber(blockNum uint64) {
   586  	if sbh.GetLatestAnchoredBlockNumber() < blockNum {
   587  		sbh.subbridge.chainDB.WriteAnchoredBlockNumber(blockNum)
   588  		lastAnchoredBlockNumGauge.Update(int64(blockNum))
   589  	}
   590  }
   591  
   592  // WriteReceiptFromParentChain writes a receipt received from parent chain to child chain
   593  // with corresponding block hash. It assumes that a child chain has only one parent chain.
   594  func (sbh *SubBridgeHandler) WriteReceiptFromParentChain(blockHash common.Hash, receipt *types.Receipt) {
   595  	sbh.subbridge.chainDB.WriteReceiptFromParentChain(blockHash, receipt)
   596  }
   597  
   598  // GetReceiptFromParentChain returns a receipt received from parent chain to child chain
   599  // with corresponding block hash. It assumes that a child chain has only one parent chain.
   600  func (sbh *SubBridgeHandler) GetReceiptFromParentChain(blockHash common.Hash) *types.Receipt {
   601  	return sbh.subbridge.chainDB.ReadReceiptFromParentChain(blockHash)
   602  }