github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/internal/ethapi/api_sub.go (about)

     1  // Copyright 2020 The go-simplechain Authors
     2  // This file is part of the go-simplechain library.
     3  //
     4  // The go-simplechain 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 go-simplechain 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 go-simplechain library. If not, see <http://www.gnu.org/licenses/>.
    16  //go:build sub
    17  // +build sub
    18  
    19  package ethapi
    20  
    21  import (
    22  	"bytes"
    23  	"context"
    24  	"math/big"
    25  
    26  	"errors"
    27  	"github.com/bigzoro/my_simplechain/common"
    28  	"github.com/bigzoro/my_simplechain/common/hexutil"
    29  	"github.com/bigzoro/my_simplechain/core/types"
    30  	"github.com/bigzoro/my_simplechain/log"
    31  	"github.com/bigzoro/my_simplechain/rpc"
    32  )
    33  
    34  // SendTxArgs represents the arguments to sumbit a new transaction into the transaction pool.
    35  type SendTxArgs struct {
    36  	From       common.Address  `json:"from"`
    37  	To         *common.Address `json:"to"`
    38  	Gas        *hexutil.Uint64 `json:"gas"`
    39  	GasPrice   *hexutil.Big    `json:"gasPrice"`
    40  	Value      *hexutil.Big    `json:"value"`
    41  	Nonce      *hexutil.Uint64 `json:"nonce"`
    42  	BlockLimit *hexutil.Uint64 `json:"blockLimit"`
    43  
    44  	// We accept "data" and "input" for backwards-compatibility reasons. "input" is the
    45  	// newer name and should be preferred by clients.
    46  	Data  *hexutil.Bytes `json:"data"`
    47  	Input *hexutil.Bytes `json:"input"`
    48  }
    49  
    50  // setDefaults is a helper function that fills in default values for unspecified tx fields.
    51  func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
    52  	if args.GasPrice == nil {
    53  		price, err := b.SuggestPrice(ctx)
    54  		if err != nil {
    55  			return err
    56  		}
    57  		args.GasPrice = (*hexutil.Big)(price)
    58  	}
    59  	if args.Value == nil {
    60  		args.Value = new(hexutil.Big)
    61  	}
    62  	if args.Nonce == nil {
    63  		nonce, err := b.GetPoolNonce(ctx, args.From)
    64  		if err != nil {
    65  			return err
    66  		}
    67  		args.Nonce = (*hexutil.Uint64)(&nonce)
    68  	}
    69  	if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) {
    70  		return errors.New(`both "data" and "input" are set and not equal. Please use "input" to pass transaction call data`)
    71  	}
    72  	if args.To == nil {
    73  		// Contract creation
    74  		var input []byte
    75  		if args.Data != nil {
    76  			input = *args.Data
    77  		} else if args.Input != nil {
    78  			input = *args.Input
    79  		}
    80  		if len(input) == 0 {
    81  			return errors.New(`contract creation without any data provided`)
    82  		}
    83  	}
    84  	// Estimate the gas usage if necessary.
    85  	if args.Gas == nil {
    86  		// For backwards-compatibility reason, we try both input and data
    87  		// but input is preferred.
    88  		input := args.Input
    89  		if input == nil {
    90  			input = args.Data
    91  		}
    92  		callArgs := CallArgs{
    93  			From:     &args.From, // From shouldn't be nil
    94  			To:       args.To,
    95  			GasPrice: args.GasPrice,
    96  			Value:    args.Value,
    97  			Data:     input,
    98  		}
    99  		pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
   100  		estimated, err := DoEstimateGas(ctx, b, callArgs, pendingBlockNr, b.RPCGasCap())
   101  		if err != nil {
   102  			return err
   103  		}
   104  		args.Gas = &estimated
   105  		log.Trace("Estimate gas usage automatically", "gas", args.Gas)
   106  	}
   107  
   108  	if args.BlockLimit == nil {
   109  		block, err := b.BlockByNumberOrHash(ctx, rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber))
   110  		if err != nil {
   111  			return err
   112  		}
   113  		expiredNum := block.NumberU64() + 50
   114  		args.BlockLimit = (*hexutil.Uint64)(&expiredNum)
   115  	}
   116  
   117  	return nil
   118  }
   119  
   120  // SubmitTransaction is a helper function that submits tx to txPool and logs a message.
   121  func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
   122  	if err := b.SendTx(ctx, tx); err != nil {
   123  		return common.Hash{}, err
   124  	}
   125  	if tx.To() == nil {
   126  		//signer := types.MakeSigner(b.ChainConfig())
   127  		//from, err := types.Sender(signer, tx)
   128  		//if err != nil {
   129  		//	return common.Hash{}, err
   130  		//}
   131  		//addr := crypto.CreateAddress(from, tx.Nonce())
   132  		//log.Info("Submitted contract creation", "fullhash", tx.Hash().Hex(), "contract", addr.Hex())
   133  		log.Debug("Submitted contract creation", "fullhash", tx.Hash().Hex())
   134  	} else {
   135  		log.Debug("Submitted transaction", "fullhash", tx.Hash().Hex(), "recipient", tx.To())
   136  	}
   137  	return tx.Hash(), nil
   138  }
   139  
   140  func (args *SendTxArgs) toTransaction() *types.Transaction {
   141  	var (
   142  		input []byte
   143  		tx    *types.Transaction
   144  	)
   145  	if args.Input != nil {
   146  		input = *args.Input
   147  	} else if args.Data != nil {
   148  		input = *args.Data
   149  	}
   150  	if args.To == nil {
   151  		tx = types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
   152  	} else {
   153  		tx = types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), 0, (*big.Int)(args.GasPrice), input)
   154  	}
   155  	if args.BlockLimit != nil {
   156  		tx.SetBlockLimit(uint64(*args.BlockLimit))
   157  	}
   158  	return tx
   159  }