github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/cmd/evm/internal/t8ntool/tx_iterator.go (about)

     1  // Copyright 2023 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU 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  // go-ethereum 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 General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package t8ntool
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/ecdsa"
    22  	"encoding/json"
    23  	"fmt"
    24  	"io"
    25  	"os"
    26  	"strings"
    27  
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/common/hexutil"
    30  	"github.com/ethereum/go-ethereum/core/types"
    31  	"github.com/ethereum/go-ethereum/crypto"
    32  	"github.com/ethereum/go-ethereum/params"
    33  	"github.com/ethereum/go-ethereum/rlp"
    34  )
    35  
    36  // txWithKey is a helper-struct, to allow us to use the types.Transaction along with
    37  // a `secretKey`-field, for input
    38  type txWithKey struct {
    39  	key       *ecdsa.PrivateKey
    40  	tx        *types.Transaction
    41  	protected bool
    42  }
    43  
    44  func (t *txWithKey) UnmarshalJSON(input []byte) error {
    45  	// Read the metadata, if present
    46  	type txMetadata struct {
    47  		Key       *common.Hash `json:"secretKey"`
    48  		Protected *bool        `json:"protected"`
    49  	}
    50  	var data txMetadata
    51  	if err := json.Unmarshal(input, &data); err != nil {
    52  		return err
    53  	}
    54  	if data.Key != nil {
    55  		k := data.Key.Hex()[2:]
    56  		if ecdsaKey, err := crypto.HexToECDSA(k); err != nil {
    57  			return err
    58  		} else {
    59  			t.key = ecdsaKey
    60  		}
    61  	}
    62  	if data.Protected != nil {
    63  		t.protected = *data.Protected
    64  	} else {
    65  		t.protected = true
    66  	}
    67  	// Now, read the transaction itself
    68  	var tx types.Transaction
    69  	if err := json.Unmarshal(input, &tx); err != nil {
    70  		return err
    71  	}
    72  	t.tx = &tx
    73  	return nil
    74  }
    75  
    76  // signUnsignedTransactions converts the input txs to canonical transactions.
    77  //
    78  // The transactions can have two forms, either
    79  //  1. unsigned or
    80  //  2. signed
    81  //
    82  // For (1), r, s, v, need so be zero, and the `secretKey` needs to be set.
    83  // If so, we sign it here and now, with the given `secretKey`
    84  // If the condition above is not met, then it's considered a signed transaction.
    85  //
    86  // To manage this, we read the transactions twice, first trying to read the secretKeys,
    87  // and secondly to read them with the standard tx json format
    88  func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) {
    89  	var signedTxs []*types.Transaction
    90  	for i, tx := range txs {
    91  		var (
    92  			v, r, s = tx.tx.RawSignatureValues()
    93  			signed  *types.Transaction
    94  			err     error
    95  		)
    96  		if tx.key == nil || v.BitLen()+r.BitLen()+s.BitLen() != 0 {
    97  			// Already signed
    98  			signedTxs = append(signedTxs, tx.tx)
    99  			continue
   100  		}
   101  		// This transaction needs to be signed
   102  		if tx.protected {
   103  			signed, err = types.SignTx(tx.tx, signer, tx.key)
   104  		} else {
   105  			signed, err = types.SignTx(tx.tx, types.FrontierSigner{}, tx.key)
   106  		}
   107  		if err != nil {
   108  			return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
   109  		}
   110  		signedTxs = append(signedTxs, signed)
   111  	}
   112  	return signedTxs, nil
   113  }
   114  
   115  func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (txIterator, error) {
   116  	var txsWithKeys []*txWithKey
   117  	if txStr != stdinSelector {
   118  		data, err := os.ReadFile(txStr)
   119  		if err != nil {
   120  			return nil, NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
   121  		}
   122  		if strings.HasSuffix(txStr, ".rlp") { // A file containing an rlp list
   123  			var body hexutil.Bytes
   124  			if err := json.Unmarshal(data, &body); err != nil {
   125  				return nil, err
   126  			}
   127  			return newRlpTxIterator(body), nil
   128  		}
   129  		if err := json.Unmarshal(data, &txsWithKeys); err != nil {
   130  			return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshalling txs-file: %v", err))
   131  		}
   132  	} else {
   133  		if len(inputData.TxRlp) > 0 {
   134  			// Decode the body of already signed transactions
   135  			return newRlpTxIterator(common.FromHex(inputData.TxRlp)), nil
   136  		}
   137  		// JSON encoded transactions
   138  		txsWithKeys = inputData.Txs
   139  	}
   140  	// We may have to sign the transactions.
   141  	signer := types.LatestSignerForChainID(chainConfig.ChainID)
   142  	txs, err := signUnsignedTransactions(txsWithKeys, signer)
   143  	return newSliceTxIterator(txs), err
   144  }
   145  
   146  type txIterator interface {
   147  	// Next returns true until EOF
   148  	Next() bool
   149  	// Tx returns the next transaction, OR an error.
   150  	Tx() (*types.Transaction, error)
   151  }
   152  
   153  type sliceTxIterator struct {
   154  	idx int
   155  	txs []*types.Transaction
   156  }
   157  
   158  func newSliceTxIterator(transactions types.Transactions) txIterator {
   159  	return &sliceTxIterator{0, transactions}
   160  }
   161  
   162  func (ait *sliceTxIterator) Next() bool {
   163  	return ait.idx < len(ait.txs)
   164  }
   165  
   166  func (ait *sliceTxIterator) Tx() (*types.Transaction, error) {
   167  	if ait.idx < len(ait.txs) {
   168  		ait.idx++
   169  		return ait.txs[ait.idx-1], nil
   170  	}
   171  	return nil, io.EOF
   172  }
   173  
   174  type rlpTxIterator struct {
   175  	in *rlp.Stream
   176  }
   177  
   178  func newRlpTxIterator(rlpData []byte) txIterator {
   179  	in := rlp.NewStream(bytes.NewBuffer(rlpData), 1024*1024)
   180  	in.List()
   181  	return &rlpTxIterator{in}
   182  }
   183  
   184  func (it *rlpTxIterator) Next() bool {
   185  	return it.in.MoreDataInList()
   186  }
   187  
   188  func (it *rlpTxIterator) Tx() (*types.Transaction, error) {
   189  	var a types.Transaction
   190  	if err := it.in.Decode(&a); err != nil {
   191  		return nil, err
   192  	}
   193  	return &a, nil
   194  }