以太坊源码分析(37)eth以太坊协议分析


node中的服务的定义, eth其实就是实现了一个服务。

    type Service interface {
        // Protocols retrieves the P2P protocols the service wishes to start.
        Protocols() []p2p.Protocol
    
        // APIs retrieves the list of RPC descriptors the service provides
        APIs() []rpc.API
    
        // Start is called after all services have been constructed and the networking
        // layer was also initialized to spawn any goroutines required by the service.
        Start(server *p2p.Server) error
    
        // Stop terminates all goroutines belonging to the service, blocking until they
        // are all terminated.
        Stop() error
    }

go ethereum 的eth目录是以太坊服务的实现。 以太坊协议是通过node的Register方法注入的。


    // RegisterEthService adds an Ethereum client to the stack.
    func RegisterEthService(stack *node.Node, cfg *eth.Config) {
        var err error
        if cfg.SyncMode == downloader.LightSync {
            err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
                return les.New(ctx, cfg)
            })
        } else {
            err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
                fullNode, err := eth.New(ctx, cfg)
                if fullNode != nil && cfg.LightServ > 0 {
                    ls, _ := les.NewLesServer(fullNode, cfg)
                    fullNode.AddLesServer(ls)
                }
                return fullNode, err
            })
        }
        if err != nil {
            Fatalf("Failed to register the Ethereum service: %v", err)
        }
    }

以太坊协议的数据结构
    
    // Ethereum implements the Ethereum full node service.
    type Ethereum struct {
        config *Config                 配置
        chainConfig *params.ChainConfig     链配置
    
        // Channel for shutting down the service
        shutdownChan chan bool // Channel for shutting down the ethereum
        stopDbUpgrade func() error // stop chain db sequential key upgrade
    
        // Handlers
        txPool *core.TxPool            交易池
        blockchain *core.BlockChain        区块链
        protocolManager *ProtocolManager        协议管理
        lesServer LesServer               轻量级客户端服务器
    
        // DB interfaces
        chainDb ethdb.Database // Block chain database  区块链数据库
    
        eventMux *event.TypeMux
        engine consensus.Engine             一致性引擎。 应该是Pow部分
        accountManager *accounts.Manager            账号管理
    
        bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 接收bloom过滤器数据请求的通道
        bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports //在区块import的时候执行Bloom indexer操作 暂时不清楚是什么
    
        ApiBackend *EthApiBackend       //提供给RPC服务使用的API后端
    
        miner *miner.Miner          //矿工
        gasPrice *big.Int              //节点接收的gasPrice的最小值。 比这个值更小的交易会被本节点拒绝
        etherbase common.Address        //矿工地址
    
        networkId uint64            //网络ID testnet是0 mainnet是1
        netRPCService *ethapi.PublicNetAPI  //RPC的服务
    
        lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase)
    }

以太坊协议的创建New. 暂时先不涉及core的内容。 只是大概介绍一下。 core里面的内容后续会分析。

    // New creates a new Ethereum object (including the
    // initialisation of the common Ethereum object)
    func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
        if config.SyncMode == downloader.LightSync {
            return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum")
        }
        if !config.SyncMode.IsValid() {
            return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode)
        }
        // 创建leveldb。 打开或者新建 chaindata目录
        chainDb, err := CreateDB(ctx, config, "chaindata")
        if err != nil {
            return nil, err
        }
        // 数据库格式升级
        stopDbUpgrade := upgradeDeduplicateData(chainDb)
        // 设置创世区块。 如果数据库里面已经有创世区块那么从数据库里面取出(私链)。或者是从代码里面获取默认值。
        chainConfig, genesisHash, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis)
        if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
            return nil, genesisErr
        }
        log.Info("Initialised chain configuration", "config", chainConfig)
    
        eth := &Ethereum{
            config: config,
            chainDb: chainDb,
            chainConfig: chainConfig,
            eventMux: ctx.EventMux,
            accountManager: ctx.AccountManager,
            engine: CreateConsensusEngine(ctx, config, chainConfig, chainDb), // 一致性引擎。 这里我理解是Pow
            shutdownChan: make(chan bool),
            stopDbUpgrade: stopDbUpgrade,
            networkId: config.NetworkId, // 网络ID用来区别网路。 测试网络是0.主网是1
            gasPrice: config.GasPrice, // 可以通过配置 --gasprice 客户端接纳的交易的gasprice最小值。如果小于这个值那么会被节点丢弃。
            etherbase: config.Etherbase, //挖矿的受益者
            bloomRequests: make(chan chan *bloombits.Retrieval), //bloom的请求
            bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks),
        }
    
        log.Info("Initialising Ethereum protocol", "versions", ProtocolVersions, "network", config.NetworkId)
    
        if !config.SkipBcVersionCheck { // 检查数据库里面存储的BlockChainVersion和客户端的BlockChainVersion的版本是否一致
            bcVersion := core.GetBlockChainVersion(chainDb)
            if bcVersion != core.BlockChainVersion && bcVersion != 0 {
                return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run geth upgradedb.\n", bcVersion, core.BlockChainVersion)
            }
            core.WriteBlockChainVersion(chainDb, core.BlockChainVersion)
        }
    
        vmConfig := vm.Config{EnablePreimageRecording: config.EnablePreimageRecording}
        // 使用数据库创建了区块链
        eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.engine, vmConfig)
        if err != nil {
            return nil, err
        }
        // Rewind the chain in case of an incompatible config upgrade.
        if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
            log.Warn("Rewinding chain to upgrade configuration", "err", compat)
            eth.blockchain.SetHead(compat.RewindTo)
            core.WriteChainConfig(chainDb, genesisHash, chainConfig)
        }
        // bloomIndexer 暂时不知道是什么东西 这里面涉及得也不是很多。 暂时先不管了
        eth.bloomIndexer.Start(eth.blockchain.CurrentHeader(), eth.blockchain.SubscribeChainEvent)
    
        if config.TxPool.Journal != "" {
            config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal)
        }
        // 创建交易池。 用来存储本地或者在网络上接收到的交易。
        eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain)
        // 创建协议管理器
        if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb); err != nil {
            return nil, err
        }
        // 创建矿工
        eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine)
        eth.miner.SetExtra(makeExtraData(config.ExtraData))
        // ApiBackend 用于给RPC调用提供后端支持
        eth.ApiBackend = &EthApiBackend{eth, nil}
        // gpoParams GPO Gas Price Oracle 的缩写。 GasPrice预测。 通过最近的交易来预测当前的GasPrice的值。这个值可以作为之后发送交易的费用的参考。
        gpoParams := config.GPO
        if gpoParams.Default == nil {
            gpoParams.Default = config.GasPrice
        }
        eth.ApiBackend.gpo = gasprice.NewOracle(eth.ApiBackend, gpoParams)
    
        return eth, nil
    }

ApiBackend 定义在 api_backend.go文件中。 封装了一些函数。

    // EthApiBackend implements ethapi.Backend for full nodes
    type EthApiBackend struct {
        eth *Ethereum
        gpo *gasprice.Oracle
    }
    func (b *EthApiBackend) SetHead(number uint64) {
        b.eth.protocolManager.downloader.Cancel()
        b.eth.blockchain.SetHead(number)
    }

New方法中除了core中的一些方法, 有一个ProtocolManager的对象在以太坊协议中比较重要, 以太坊本来是一个协议。ProtocolManager中又可以管理多个以太坊的子协议。

    
    // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
    // with the ethereum network.
    func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, networkId uint64, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) {
        // Create the protocol manager with the base fields
        manager := &ProtocolManager{
            networkId: networkId,
            eventMux: mux,
            txpool: txpool,
            blockchain: blockchain,
            chaindb: chaindb,
            chainconfig: config,
            peers: newPeerSet(),
            newPeerCh: make(chan *peer),
            noMorePeers: make(chan struct{}),
            txsyncCh: make(chan *txsync),
            quitSync: make(chan struct{}),
        }
        // Figure out whether to allow fast sync or not
        if mode == downloader.FastSync && blockchain.CurrentBlock().NumberU64() > 0 {
            log.Warn("Blockchain not empty, fast sync disabled")
            mode = downloader.FullSync
        }
        if mode == downloader.FastSync {
            manager.fastSync = uint32(1)
        }
        // Initiate a sub-protocol for every implemented version we can handle
        manager.SubProtocols = make([]p2p.Protocol, 0, len(ProtocolVersions))
        for i, version := range ProtocolVersions {
            // Skip protocol version if incompatible with the mode of operation
            if mode == downloader.FastSync && version < eth63 {
                continue
            }
            // Compatible; initialise the sub-protocol
            version := version // Closure for the run
            manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{
                Name: ProtocolName,
                Version: version,
                Length: ProtocolLengths[i],
                // 还记得p2p里面的Protocol么。 p2p的peer连接成功之后会调用Run方法
                Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
                    peer := manager.newPeer(int(version), p, rw)
                    select {
                    case manager.newPeerCh <- peer:
                        manager.wg.Add(1)
                        defer manager.wg.Done()
                        return manager.handle(peer)
                    case <-manager.quitSync:
                        return p2p.DiscQuitting
                    }
                },
                NodeInfo: func() interface{} {
                    return manager.NodeInfo()
                },
                PeerInfo: func(id discover.NodeID) interface{} {
                    if p := manager.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil {
        
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python以太坊交易是指使用Python编程语言进行以太坊区块链上的交易操作。以太坊是一种基于区块链技术的智能合约平台,它允许开发者构建和部署去中心化应用程序(DApps)。 在Python中,可以使用以太坊的官方库web3.py来进行以太坊交易的编程操作。web3.py提供了一系列的API,可以与以太坊节点进行通信,并执行各种操作,包括创建账户、发送交易、查询余额等。 以下是一个简单的Python代码示例,展示了如何使用web3.py库发送以太坊交易: ```python from web3 import Web3 # 连接到以太坊节点 w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/your_infura_project_id')) # 设置发送方账户私钥和接收方地址 private_key = 'your_private_key' receiver_address = '0x1234567890abcdef1234567890abcdef12345678' # 构建交易参数 transaction = { 'to': receiver_address, 'value': w3.toWei(1, 'ether'), 'gas': 21000, 'gasPrice': w3.toWei('50', 'gwei'), 'nonce': w3.eth.getTransactionCount(w3.eth.accounts), } # 签名交易 signed_transaction = w3.eth.account.signTransaction(transaction, private_key) # 发送交易 transaction_hash = w3.eth.sendRawTransaction(signed_transaction.rawTransaction) # 等待交易确认 transaction_receipt = w3.eth.waitForTransactionReceipt(transaction_hash) # 打印交易结果 print('交易成功,交易哈希:', transaction_receipt.transactionHash.hex()) ``` 上述代码中,首先使用`Web3`类连接到以太坊节点。然后设置发送方账户的私钥和接收方地址。接下来,构建交易参数,包括接收方地址、转账金额、燃气限制、燃气价格和交易序号。然后使用发送方账户的私钥对交易进行签名,并发送签名后的交易到以太坊网络。最后,等待交易被确认,并打印交易结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尹成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值