github.com/klaytn/klaytn@v1.12.1/api/api_public_transaction_pool.go (about)

     1  // Modifications Copyright 2019 The klaytn Authors
     2  // Copyright 2015 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from internal/ethapi/api.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package api
    22  
    23  import (
    24  	"context"
    25  	"encoding/json"
    26  	"errors"
    27  	"fmt"
    28  	"math/big"
    29  
    30  	"github.com/klaytn/klaytn/accounts"
    31  	"github.com/klaytn/klaytn/blockchain/types"
    32  	"github.com/klaytn/klaytn/common"
    33  	"github.com/klaytn/klaytn/common/hexutil"
    34  	"github.com/klaytn/klaytn/crypto"
    35  	"github.com/klaytn/klaytn/networks/rpc"
    36  	"github.com/klaytn/klaytn/rlp"
    37  )
    38  
    39  // PublicTransactionPoolAPI exposes methods for the RPC interface
    40  type PublicTransactionPoolAPI struct {
    41  	b         Backend
    42  	nonceLock *AddrLocker
    43  }
    44  
    45  // NewPublicTransactionPoolAPI creates a new RPC service with methods specific for the transaction pool.
    46  func NewPublicTransactionPoolAPI(b Backend, nonceLock *AddrLocker) *PublicTransactionPoolAPI {
    47  	return &PublicTransactionPoolAPI{b, nonceLock}
    48  }
    49  
    50  // GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
    51  func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*hexutil.Uint, error) {
    52  	block, err := s.b.BlockByNumber(ctx, blockNr)
    53  	if block != nil && err == nil {
    54  		n := hexutil.Uint(len(block.Transactions()))
    55  		return &n, err
    56  	}
    57  	return nil, err
    58  }
    59  
    60  // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash.
    61  func (s *PublicTransactionPoolAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) (*hexutil.Uint, error) {
    62  	block, err := s.b.BlockByHash(ctx, blockHash)
    63  	if block != nil && err == nil {
    64  		n := hexutil.Uint(len(block.Transactions()))
    65  		return &n, err
    66  	}
    67  	return nil, err
    68  }
    69  
    70  // GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
    71  func (s *PublicTransactionPoolAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
    72  	block, err := s.b.BlockByNumber(ctx, blockNr)
    73  	if block != nil && err == nil {
    74  		return newRPCTransactionFromBlockIndex(block, uint64(index)), nil
    75  	}
    76  	return nil, err
    77  }
    78  
    79  // GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
    80  func (s *PublicTransactionPoolAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) {
    81  	block, err := s.b.BlockByHash(ctx, blockHash)
    82  	if block != nil && err == nil {
    83  		return newRPCTransactionFromBlockIndex(block, uint64(index)), nil
    84  	}
    85  	return nil, err
    86  }
    87  
    88  // GetRawTransactionByBlockNumberAndIndex returns the bytes of the transaction for the given block number and index.
    89  func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (hexutil.Bytes, error) {
    90  	block, err := s.b.BlockByNumber(ctx, blockNr)
    91  	if block != nil && err == nil {
    92  		return newRPCRawTransactionFromBlockIndex(block, uint64(index)), nil
    93  	}
    94  	return nil, err
    95  }
    96  
    97  // GetRawTransactionByBlockHashAndIndex returns the bytes of the transaction for the given block hash and index.
    98  func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (hexutil.Bytes, error) {
    99  	block, err := s.b.BlockByHash(ctx, blockHash)
   100  	if block != nil && err == nil {
   101  		return newRPCRawTransactionFromBlockIndex(block, uint64(index)), nil
   102  	}
   103  	return nil, err
   104  }
   105  
   106  // GetTransactionCount returns the number of transactions the given address has sent for the given block number or hash
   107  func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error) {
   108  	// Ask transaction pool for the nonce which includes pending transactions
   109  	if blockNr, ok := blockNrOrHash.Number(); ok && blockNr == rpc.PendingBlockNumber {
   110  		nonce := s.b.GetPoolNonce(ctx, address)
   111  		return (*hexutil.Uint64)(&nonce), nil
   112  	}
   113  
   114  	// Resolve block number and use its state to ask for the nonce
   115  	state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	nonce := state.GetNonce(address)
   120  	return (*hexutil.Uint64)(&nonce), state.Error()
   121  }
   122  
   123  func (s *PublicTransactionPoolAPI) GetTransactionBySenderTxHash(ctx context.Context, senderTxHash common.Hash) map[string]interface{} {
   124  	txhash := s.b.ChainDB().ReadTxHashFromSenderTxHash(senderTxHash)
   125  	if common.EmptyHash(txhash) {
   126  		txhash = senderTxHash
   127  	}
   128  	return s.GetTransactionByHash(ctx, txhash)
   129  }
   130  
   131  // GetTransactionByHash returns the transaction for the given hash
   132  func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) map[string]interface{} {
   133  	// Try to return an already finalized transaction
   134  	if tx, blockHash, blockNumber, index := s.b.ChainDB().ReadTxAndLookupInfo(hash); tx != nil {
   135  		return newRPCTransaction(nil, tx, blockHash, blockNumber, index)
   136  	}
   137  	// No finalized transaction, try to retrieve it from the pool
   138  	if tx := s.b.GetPoolTransaction(hash); tx != nil {
   139  		return newRPCPendingTransaction(tx)
   140  	}
   141  	// Transaction unknown, return as such
   142  	return nil
   143  }
   144  
   145  // GetDecodedAnchoringTransactionByHash returns the decoded anchoring data of anchoring transaction for the given hash
   146  func (s *PublicTransactionPoolAPI) GetDecodedAnchoringTransactionByHash(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
   147  	var tx *types.Transaction
   148  
   149  	// Try to return an already finalized transaction
   150  	if tx, _, _, _ = s.b.ChainDB().ReadTxAndLookupInfo(hash); tx != nil {
   151  		goto decode
   152  	}
   153  
   154  	// No finalized transaction, try to retrieve it from the pool
   155  	if tx = s.b.GetPoolTransaction(hash); tx != nil {
   156  		goto decode
   157  	}
   158  	return nil, errors.New("can't find the transaction")
   159  
   160  decode:
   161  
   162  	if !tx.Type().IsChainDataAnchoring() {
   163  		return nil, errors.New("invalid transaction type")
   164  	}
   165  
   166  	data, err := tx.AnchoredData()
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  
   171  	anchoringDataInternal, err := types.DecodeAnchoringData(data)
   172  	if err != nil {
   173  		return nil, err
   174  	}
   175  
   176  	str, err := json.Marshal(anchoringDataInternal)
   177  	if err != nil {
   178  		return nil, err
   179  	}
   180  
   181  	var result map[string]interface{}
   182  	json.Unmarshal(str, &result)
   183  
   184  	return result, nil
   185  }
   186  
   187  // GetRawTransactionByHash returns the bytes of the transaction for the given hash.
   188  func (s *PublicTransactionPoolAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
   189  	var tx *types.Transaction
   190  
   191  	// Retrieve a finalized transaction, or a pooled otherwise
   192  	if tx, _, _, _ = s.b.ChainDB().ReadTxAndLookupInfo(hash); tx == nil {
   193  		if tx = s.b.GetPoolTransaction(hash); tx == nil {
   194  			// Transaction not found anywhere, abort
   195  			return nil, nil
   196  		}
   197  	}
   198  
   199  	// Serialize to RLP and return
   200  	return rlp.EncodeToBytes(tx)
   201  }
   202  
   203  // RpcOutputReceipt converts a receipt to the RPC output with the associated information regarding to the
   204  // block in which the receipt is included, the transaction that outputs the receipt, and the receipt itself.
   205  func RpcOutputReceipt(header *types.Header, tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64, receipt *types.Receipt) map[string]interface{} {
   206  	if tx == nil || receipt == nil {
   207  		return nil
   208  	}
   209  
   210  	fields := newRPCTransaction(nil, tx, blockHash, blockNumber, index)
   211  
   212  	if receipt.Status != types.ReceiptStatusSuccessful {
   213  		fields["status"] = hexutil.Uint(types.ReceiptStatusFailed)
   214  		fields["txError"] = hexutil.Uint(receipt.Status)
   215  	} else {
   216  		fields["status"] = hexutil.Uint(receipt.Status)
   217  	}
   218  
   219  	fields["logsBloom"] = receipt.Bloom
   220  	fields["gasUsed"] = hexutil.Uint64(receipt.GasUsed)
   221  
   222  	fields["effectiveGasPrice"] = hexutil.Uint64(tx.EffectiveGasPrice(header).Uint64())
   223  
   224  	if receipt.Logs == nil {
   225  		fields["logs"] = [][]*types.Log{}
   226  	} else {
   227  		fields["logs"] = receipt.Logs
   228  	}
   229  	// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
   230  	if receipt.ContractAddress != (common.Address{}) {
   231  		fields["contractAddress"] = receipt.ContractAddress
   232  	} else {
   233  		fields["contractAddress"] = nil
   234  	}
   235  
   236  	// Rename field name `hash` to `transactionHash` since this function returns a JSON object of a receipt.
   237  	fields["transactionHash"] = fields["hash"]
   238  	delete(fields, "hash")
   239  
   240  	return fields
   241  }
   242  
   243  func (s *PublicTransactionPoolAPI) GetTransactionReceiptBySenderTxHash(ctx context.Context, senderTxHash common.Hash) (map[string]interface{}, error) {
   244  	txhash := s.b.ChainDB().ReadTxHashFromSenderTxHash(senderTxHash)
   245  	if common.EmptyHash(txhash) {
   246  		txhash = senderTxHash
   247  	}
   248  	return s.GetTransactionReceipt(ctx, txhash)
   249  }
   250  
   251  // GetTransactionReceipt returns the transaction receipt for the given transaction hash.
   252  func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
   253  	tx, blockHash, blockNumber, index, receipt := s.b.GetTxLookupInfoAndReceipt(ctx, hash)
   254  	return s.getTransactionReceipt(ctx, tx, blockHash, blockNumber, index, receipt)
   255  }
   256  
   257  // GetTransactionReceiptInCache returns the transaction receipt for the given transaction hash.
   258  func (s *PublicTransactionPoolAPI) GetTransactionReceiptInCache(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
   259  	tx, blockHash, blockNumber, index, receipt := s.b.GetTxLookupInfoAndReceiptInCache(hash)
   260  	return s.getTransactionReceipt(ctx, tx, blockHash, blockNumber, index, receipt)
   261  }
   262  
   263  // getTransactionReceipt returns the transaction receipt for the given transaction hash.
   264  func (s *PublicTransactionPoolAPI) getTransactionReceipt(ctx context.Context, tx *types.Transaction, blockHash common.Hash,
   265  	blockNumber uint64, index uint64, receipt *types.Receipt,
   266  ) (map[string]interface{}, error) {
   267  	// No error handling is required here.
   268  	// Header is checked in the following RpcOutputReceipt function
   269  	header, _ := s.b.HeaderByHash(ctx, blockHash)
   270  	return RpcOutputReceipt(header, tx, blockHash, blockNumber, index, receipt), nil
   271  }
   272  
   273  // sign is a helper function that signs a transaction with the private key of the given address.
   274  func (s *PublicTransactionPoolAPI) sign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
   275  	// Look up the wallet containing the requested signer
   276  	account := accounts.Account{Address: addr}
   277  
   278  	wallet, err := s.b.AccountManager().Find(account)
   279  	if err != nil {
   280  		return nil, err
   281  	}
   282  	// Request the wallet to sign the transaction
   283  	return wallet.SignTx(account, tx, s.b.ChainConfig().ChainID)
   284  }
   285  
   286  // signAsFeePayer is a helper function that signs a transaction as a fee payer with the private key of the given address.
   287  func (s *PublicTransactionPoolAPI) signAsFeePayer(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
   288  	// Look up the wallet containing the requested signer
   289  	account := accounts.Account{Address: addr}
   290  
   291  	wallet, err := s.b.AccountManager().Find(account)
   292  	if err != nil {
   293  		return nil, err
   294  	}
   295  	// Request the wallet to sign the transaction
   296  	return wallet.SignTxAsFeePayer(account, tx, s.b.ChainConfig().ChainID)
   297  }
   298  
   299  var submitTxCount = 0
   300  
   301  // submitTransaction is a helper function that submits tx to txPool and logs a message.
   302  func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
   303  	// submitTxCount++
   304  	// log.Error("### submitTransaction","tx",submitTxCount)
   305  
   306  	if err := b.SendTx(ctx, tx); err != nil {
   307  		return common.Hash{}, err
   308  	}
   309  	// TODO-Klaytn only enable on logging
   310  	//if tx.To() == nil {
   311  	//	signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number())
   312  	//	from, err := types.Sender(signer, tx)
   313  	//	if err != nil {
   314  	//		logger.Error("api.submitTransaction make from","err",err)
   315  	//		return common.Hash{}, err
   316  	//	}
   317  	//	addr := crypto.CreateAddress(from, tx.Nonce())
   318  	//	logger.Info("Submitted contract creation", "fullhash", tx.Hash().Hex(), "contract", addr.Hex())
   319  	//} else {
   320  	//	logger.Info("Submitted transaction", "fullhash", tx.Hash().Hex(), "recipient", tx.To())
   321  	//}
   322  	return tx.Hash(), nil
   323  }
   324  
   325  // SendTransaction creates a transaction for the given argument, sign it and submit it to the
   326  // transaction pool.
   327  func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {
   328  	if args.AccountNonce == nil {
   329  		// Hold the addresse's mutex around signing to prevent concurrent assignment of
   330  		// the same nonce to multiple accounts.
   331  		s.nonceLock.LockAddr(args.From)
   332  		defer s.nonceLock.UnlockAddr(args.From)
   333  	}
   334  
   335  	signedTx, err := s.SignTransaction(ctx, args)
   336  	if err != nil {
   337  		return common.Hash{}, err
   338  	}
   339  
   340  	return submitTransaction(ctx, s.b, signedTx.Tx)
   341  }
   342  
   343  // SendTransactionAsFeePayer creates a transaction for the given argument, sign it as a fee payer
   344  // and submit it to the transaction pool.
   345  func (s *PublicTransactionPoolAPI) SendTransactionAsFeePayer(ctx context.Context, args SendTxArgs) (common.Hash, error) {
   346  	// Don't allow dynamic assign of values from the setDefaults function since the sender already signed on specific values.
   347  	if args.TypeInt == nil {
   348  		return common.Hash{}, errTxArgNilTxType
   349  	}
   350  	if args.AccountNonce == nil {
   351  		return common.Hash{}, errTxArgNilNonce
   352  	}
   353  	if args.GasLimit == nil {
   354  		return common.Hash{}, errTxArgNilGas
   355  	}
   356  	if args.Price == nil {
   357  		return common.Hash{}, errTxArgNilGasPrice
   358  	}
   359  
   360  	if args.TxSignatures == nil {
   361  		return common.Hash{}, errTxArgNilSenderSig
   362  	}
   363  
   364  	feePayerSignedTx, err := s.SignTransactionAsFeePayer(ctx, args)
   365  	if err != nil {
   366  		return common.Hash{}, err
   367  	}
   368  
   369  	return submitTransaction(ctx, s.b, feePayerSignedTx.Tx)
   370  }
   371  
   372  // SendRawTransaction will add the signed transaction to the transaction pool.
   373  // The sender is responsible for signing the transaction and using the correct nonce.
   374  func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) {
   375  	tx := new(types.Transaction)
   376  	if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
   377  		return common.Hash{}, err
   378  	}
   379  	return submitTransaction(ctx, s.b, tx)
   380  }
   381  
   382  // Sign calculates an ECDSA signature for:
   383  // keccack256("\x19Klaytn Signed Message:\n" + len(message) + message).
   384  //
   385  // Note, the produced signature conforms to the secp256k1 curve R, S and V values,
   386  // where the V value will be 27 or 28 for legacy reasons.
   387  //
   388  // The account associated with addr must be unlocked.
   389  //
   390  // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
   391  func (s *PublicTransactionPoolAPI) Sign(addr common.Address, data hexutil.Bytes) (hexutil.Bytes, error) {
   392  	// Look up the wallet containing the requested signer
   393  	account := accounts.Account{Address: addr}
   394  
   395  	wallet, err := s.b.AccountManager().Find(account)
   396  	if err != nil {
   397  		return nil, err
   398  	}
   399  	// Sign the requested hash with the wallet
   400  	signature, err := wallet.SignHash(account, signHash(data))
   401  	if err == nil {
   402  		signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
   403  	}
   404  	return signature, err
   405  }
   406  
   407  // SignTransactionResult represents a RLP encoded signed transaction.
   408  type SignTransactionResult struct {
   409  	Raw hexutil.Bytes      `json:"raw"`
   410  	Tx  *types.Transaction `json:"tx"`
   411  }
   412  
   413  // SignTransaction will sign the given transaction with the from account.
   414  // The node needs to have the private key of the account corresponding with
   415  // the given from address and it needs to be unlocked.
   416  func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args SendTxArgs) (*SignTransactionResult, error) {
   417  	if args.TypeInt != nil && args.TypeInt.IsEthTypedTransaction() {
   418  		if args.Price == nil && (args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil) {
   419  			return nil, fmt.Errorf("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas")
   420  		}
   421  	}
   422  
   423  	// No need to obtain the noncelock mutex, since we won't be sending this
   424  	// tx into the transaction pool, but right back to the user
   425  	if err := args.setDefaults(ctx, s.b); err != nil {
   426  		return nil, err
   427  	}
   428  	tx, err := args.toTransaction()
   429  	if err != nil {
   430  		return nil, err
   431  	}
   432  	signedTx, err := s.sign(args.From, tx)
   433  	if err != nil {
   434  		return nil, err
   435  	}
   436  	data, err := rlp.EncodeToBytes(signedTx)
   437  	if err != nil {
   438  		return nil, err
   439  	}
   440  	return &SignTransactionResult{data, signedTx}, nil
   441  }
   442  
   443  // SignTransactionAsFeePayer will sign the given transaction as a fee payer
   444  // with the from account. The node needs to have the private key of the account
   445  // corresponding with the given from address and it needs to be unlocked.
   446  func (s *PublicTransactionPoolAPI) SignTransactionAsFeePayer(ctx context.Context, args SendTxArgs) (*SignTransactionResult, error) {
   447  	// Allows setting a default nonce value of the sender just for the case the fee payer tries to sign a tx earlier than the sender.
   448  	if err := args.setDefaults(ctx, s.b); err != nil {
   449  		return nil, err
   450  	}
   451  	tx, err := args.toTransaction()
   452  	if err != nil {
   453  		return nil, err
   454  	}
   455  	// Don't return errors for nil signature allowing the fee payer to sign a tx earlier than the sender.
   456  	if args.TxSignatures != nil {
   457  		tx.SetSignature(args.TxSignatures.ToTxSignatures())
   458  	}
   459  	feePayer, err := tx.FeePayer()
   460  	if err != nil {
   461  		return nil, errTxArgInvalidFeePayer
   462  	}
   463  	feePayerSignedTx, err := s.signAsFeePayer(feePayer, tx)
   464  	if err != nil {
   465  		return nil, err
   466  	}
   467  	data, err := rlp.EncodeToBytes(feePayerSignedTx)
   468  	if err != nil {
   469  		return nil, err
   470  	}
   471  	return &SignTransactionResult{data, feePayerSignedTx}, nil
   472  }
   473  
   474  func getAccountsFromWallets(wallets []accounts.Wallet) map[common.Address]struct{} {
   475  	accounts := make(map[common.Address]struct{})
   476  	for _, wallet := range wallets {
   477  		for _, account := range wallet.Accounts() {
   478  			accounts[account.Address] = struct{}{}
   479  		}
   480  	}
   481  	return accounts
   482  }
   483  
   484  // PendingTransactions returns the transactions that are in the transaction pool
   485  // and have a from address that is one of the accounts this node manages.
   486  func (s *PublicTransactionPoolAPI) PendingTransactions() ([]map[string]interface{}, error) {
   487  	pending, err := s.b.GetPoolTransactions()
   488  	if err != nil {
   489  		return nil, err
   490  	}
   491  	accounts := getAccountsFromWallets(s.b.AccountManager().Wallets())
   492  	transactions := make([]map[string]interface{}, 0, len(pending))
   493  	for _, tx := range pending {
   494  		from := getFrom(tx)
   495  		if _, exists := accounts[from]; exists {
   496  			transactions = append(transactions, newRPCPendingTransaction(tx))
   497  		}
   498  	}
   499  	return transactions, nil
   500  }
   501  
   502  // Resend accepts an existing transaction and a new gas price and limit. It will remove
   503  // the given transaction from the pool and reinsert it with the new gas price and limit.
   504  func (s *PublicTransactionPoolAPI) Resend(ctx context.Context, sendArgs SendTxArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
   505  	return resend(s, ctx, &sendArgs, gasPrice, gasLimit)
   506  }
   507  
   508  // Resend accepts an existing transaction and a new gas price and limit. It will remove
   509  // the given transaction from the pool and reinsert it with the new gas price and limit.
   510  func resend(s *PublicTransactionPoolAPI, ctx context.Context, sendArgs NewTxArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
   511  	if sendArgs.nonce() == nil {
   512  		return common.Hash{}, fmt.Errorf("missing transaction nonce in transaction spec")
   513  	}
   514  	if err := sendArgs.setDefaults(ctx, s.b); err != nil {
   515  		return common.Hash{}, err
   516  	}
   517  	matchTx, err := sendArgs.toTransaction()
   518  	if err != nil {
   519  		return common.Hash{}, err
   520  	}
   521  	pending, err := s.b.GetPoolTransactions()
   522  	if err != nil {
   523  		return common.Hash{}, err
   524  	}
   525  
   526  	for _, p := range pending {
   527  		signer := types.LatestSignerForChainID(p.ChainId())
   528  		wantSigHash := signer.Hash(matchTx)
   529  
   530  		if pFrom, err := types.Sender(signer, p); err == nil && pFrom == sendArgs.from() && signer.Hash(p) == wantSigHash {
   531  			// Match. Re-sign and send the transaction.
   532  			if gasPrice != nil && (*big.Int)(gasPrice).Sign() != 0 {
   533  				sendArgs.setGasPrice(gasPrice)
   534  			}
   535  			if gasLimit != nil && *gasLimit != 0 {
   536  				sendArgs.setGas(gasLimit)
   537  			}
   538  			tx, err := sendArgs.toTransaction()
   539  			if err != nil {
   540  				return common.Hash{}, err
   541  			}
   542  			signedTx, err := s.sign(sendArgs.from(), tx)
   543  			if err != nil {
   544  				return common.Hash{}, err
   545  			}
   546  			if err = s.b.SendTx(ctx, signedTx); err != nil {
   547  				return common.Hash{}, err
   548  			}
   549  			return signedTx.Hash(), nil
   550  		}
   551  	}
   552  
   553  	return common.Hash{}, fmt.Errorf("Transaction %#x not found", matchTx.Hash())
   554  }
   555  
   556  // RecoverFromTransaction recovers the sender address from a signed raw transaction.
   557  // The signature is validated against the sender account's key configuration at the given block number.
   558  func (s *PublicTransactionPoolAPI) RecoverFromTransaction(ctx context.Context, encodedTx hexutil.Bytes, blockNumber rpc.BlockNumber) (common.Address, error) {
   559  	if len(encodedTx) == 0 {
   560  		return common.Address{}, fmt.Errorf("Empty input")
   561  	}
   562  	if 0 < encodedTx[0] && encodedTx[0] < 0x8 { // TODO: Add helper to distinguish eth vs klay txtypes
   563  		ethEnvelope := []byte{byte(types.EthereumTxTypeEnvelope)}
   564  		encodedTx = append(ethEnvelope, encodedTx...)
   565  	}
   566  
   567  	tx := new(types.Transaction)
   568  	if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
   569  		return common.Address{}, err
   570  	}
   571  
   572  	var bn uint64
   573  	if blockNumber == rpc.LatestBlockNumber || blockNumber == rpc.PendingBlockNumber {
   574  		bn = s.b.CurrentBlock().NumberU64()
   575  	} else {
   576  		bn = blockNumber.Uint64()
   577  	}
   578  
   579  	signer := types.MakeSigner(s.b.ChainConfig(), new(big.Int).SetUint64(bn))
   580  	state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNumber)
   581  	if err != nil {
   582  		return common.Address{}, err
   583  	}
   584  	_, err = tx.ValidateSender(signer, state, bn)
   585  	if err != nil {
   586  		return common.Address{}, err
   587  	}
   588  	return tx.From()
   589  }
   590  
   591  // RecoverFromMessage validates that the message is signed by one of the keys in the given account.
   592  // Returns the recovered signer address, which may be different from the account address.
   593  func (s *PublicTransactionPoolAPI) RecoverFromMessage(
   594  	ctx context.Context, address common.Address, data, sig hexutil.Bytes, blockNumber rpc.BlockNumber,
   595  ) (common.Address, error) {
   596  	if len(sig) != crypto.SignatureLength {
   597  		return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
   598  	}
   599  	if sig[crypto.RecoveryIDOffset] != 27 && sig[crypto.RecoveryIDOffset] != 28 {
   600  		return common.Address{}, fmt.Errorf("invalid Klaytn signature (V is not 27 or 28)")
   601  	}
   602  
   603  	// Transform yellow paper V from 27/28 to 0/1
   604  	sig[crypto.RecoveryIDOffset] -= 27
   605  
   606  	state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNumber)
   607  	if err != nil {
   608  		return common.Address{}, err
   609  	}
   610  	key := state.GetKey(address)
   611  
   612  	// We cannot identify if the signature has signed with klay or eth prefix without the signer's address.
   613  	// Even though a user signed message with eth prefix, it will return invalid something in klayEcRecover.
   614  	// We should call each rcrecover function separately and the actual result will be checked in ValidateMember.
   615  	var recoverErr error
   616  	if pubkey, err := klayEcRecover(data, sig); err == nil {
   617  		if key.ValidateMember(pubkey, address) {
   618  			return crypto.PubkeyToAddress(*pubkey), nil
   619  		}
   620  	} else {
   621  		recoverErr = err
   622  	}
   623  	if pubkey, err := ethEcRecover(data, sig); err == nil {
   624  		if key.ValidateMember(pubkey, address) {
   625  			return crypto.PubkeyToAddress(*pubkey), nil
   626  		}
   627  	} else {
   628  		recoverErr = err
   629  	}
   630  	if recoverErr != nil {
   631  		return common.Address{}, recoverErr
   632  	} else {
   633  		return common.Address{}, errors.New("Invalid signature")
   634  	}
   635  }