以太坊ETH源码分析(2):交易执行过程

一、 交易大致流程

以太坊的交易大致分以下几步:
1、 发起交易:指定目标地址和交易金额以及相关的gas/gaslimit发起相关交易,如果目标地址为空,则表示其为一个智能合约的交易。
2、 交易签名:使用私钥对交易进行签名。这涉及到上一篇中帐户的私钥和公钥的产生机制。
3、 提交交易:把交易添加到交易池中,类似于比特币。签名验证后,通过一定的规则对池内的交易进行排序(如交易的gas)。
4、 广播交易:EVM执行交易,然后广播到其他节点。
5、 交易打包:POW工作量证明,然后形成新的区块打包交易。
6、 广播区块事件:即提交最终的区块。
通过以上六个步骤,把一个完整的交易过程展现出来,严格意义上来说,5和6要归到区块链的模块中去,但是一个完整的交易是需要有这个过程才能证明是完成的。所以在说明时,重点说明前四条。

二、交易的步骤

1、 发起交易

交易的发起一般通过调用RPC接口实现,ETH源码本身提供了相关api,位于源码的ethereum/go-ethereum的internal包中

(1) 交易入口源码位于ethereum/go-ethereum/internal/ethapi/api.go

// SendTransaction creates a transaction for the given argument, sign it and submit it to the
// transaction pool.
func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {

	// Look up the wallet containing the requested signer
	account := accounts.Account{Address: args.From}

	//a.根据发送者地址找出对应钱包用于签名
	wallet, err := s.b.AccountManager().Find(account)
	if err != nil {
		return common.Hash{}, err
	}

	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)
	}

	// Set some sanity defaults and terminate on failure
	if err := args.setDefaults(ctx, s.b); err != nil {
		return common.Hash{}, err
	}
	// Assemble the transaction and sign with the wallet
	//b.处理原生交易数据
	tx := args.toTransaction()

	var chainID *big.Int
	if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
		chainID = config.ChainID
	}
	//c.对交易进行签名
	signed, err := wallet.SignTx(account, tx, chainID)
	if err != nil {
		return common.Hash{}, err
	}

	//d.提交交易
	return submitTransaction(ctx, s.b, signed)
}

(2) 分析b处理原生交易数据 源码如下

func (args *SendTxArgs) toTransaction() *types.Transaction {
	var input []byte
	if args.Data != nil {
		input = *args.Data
	} else if args.Input != nil {
		input = *args.Input
	}
	// 接收者地址为空时,即为创建合约交易
	if args.To == nil {
		return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
	}
	// 此处为普通交易
	return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
}

(3)分析c对交易进行签名,源码:ethereum/go-ethereum/accounts/keystore/keystore.go

// SignTx signs the given transaction with the requested account.
func (ks *KeyStore) SignTx(a accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
	// Look up the key to sign with and abort if it cannot be found
	ks.mu.RLock()
	defer ks.mu.RUnlock()

	unlockedKey, found := ks.unlocked[a.Address]
	if !found {
		return nil, ErrLocked
	}
	// Depending on the presence of the chain ID, sign with EIP155 or homestead
	if chainID != nil {
		return types.SignTx(tx, types.NewEIP155Signer(chainID), unlockedKey.PrivateKey)
	}
	return types.SignTx(tx, types.HomesteadSigner{}, unlockedKey.PrivateKey)
}

(4) 分析d提交交易

…待续

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值