以太坊源码学习(三)交易

internal/ethapi/api.go

// SendTransaction will create a transaction from the given arguments and
// tries to sign it with the key associated with args.To. If the given passwd isn't
// able to decrypt the key it fails.
func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) {
   if args.Nonce == nil {
      // Hold the addresse's mutex around signing to prevent concurrent assignment of
      // the same nonce to multiple accounts.
      s.nonceLock.LockAddr(args.From)
      defer s.nonceLock.UnlockAddr(args.From)
   }
   signed, err := s.signTransaction(ctx, &args, passwd) //签名交易
   if err != nil {
      log.Warn("Failed transaction send attempt", "from", args.From, "to", args.To, "value", args.Value.ToInt(), "err", err)
      return common.Hash{}, err
   }
   return submitTransaction(ctx, s.b, signed)  // 提交交易
}
// signTransaction sets defaults and signs the given transaction
// NOTE: the caller needs to ensure that the nonceLock is held, if applicable,
// and release it after the transaction has been submitted to the tx pool
func (s *PrivateAccountAPI) signTransaction(ctx context.Context, args *SendTxArgs /*交易参数,用于提交到交易池*/, passwd string) (*types.Transaction, error) {
   // Look up the wallet containing the requested signer
   account := accounts.Account{Address: args.From}
   wallet, err := s.am.Find(account)
   if err != nil {
      return nil, err
   }
   // Set some sanity defaults and terminate on failure
   if err := args.setDefaults(ctx, s.b); err != nil {
      return nil, err
   }
   // Assemble the transaction and sign with the wallet
   tx := args.toTransaction() // 创建交易

   var chainID *big.Int
   if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
      chainID = config.ChainID
   }
   return wallet.SignTxWithPassphrase(account, passwd, tx, chainID)//签名
}
创建交易
func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
   if len(data) > 0 {
      data = common.CopyBytes(data)
   }
   d := txdata{
      AccountNonce: nonce,
      Recipient:    to,
      Payload:      data,
      Amount:       new(big.Int),
      GasLimit:     gasLimit,
      Price:        new(big.Int),
      V:            new(big.Int),
      R:            new(big.Int),
      S:            new(big.Int),
   }
   if amount != nil {
      d.Amount.Set(amount)
   }
   if gasPrice != nil {
      d.Price.Set(gasPrice)
   }

   return &Transaction{data: d}
}

 

签名并把签名数据放入交易
// WithSignature returns a new transaction with the given signature.
// This signature needs to be in the [R || S || V] format where V is 0 or 1.
func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, error) {
   r, s, v, err := signer.SignatureValues(tx, sig)
   if err != nil {
      return nil, err
   }
   cpy := &Transaction{data: tx.data}
   cpy.data.R, cpy.data.S, cpy.data.V = r, s, v
   return cpy, nil
}

你可能感兴趣的:(区块链)