Miner模块:
类结构如下:
主要结构体
Miner、Worker、Work、CpuAgent、Result、unconfiredBlocks
Miner为挖矿的核心对象(矿工),核心成员包括注册处理事件(mux)、工人(worker)、coinbase(默认账户地址hash)、后台处理对象(eth)、共识处理引擎(engine)、判定能否挖矿的对象(canstart)、判定是否同步挖矿(shouldstart)
方法:
| 方法名 |
参数 |
主要描述 |
| update |
空 |
防止DOS攻击 |
| Start |
coinbase |
关闭同步,启动挖矿 |
| Stop |
空 |
停止挖矿 |
| Register |
空 |
注册代理 |
| Unregister |
空 |
解除代理 |
| Mining |
空 |
是否挖矿 |
| HashRate |
空 |
返回Pow当前挖矿的哈希率 |
| SetExtra |
空 |
设置worker的extra值(byte数组) |
| Pending |
空 |
挂起返回当前挂起的块和关联的状态。 |
| PendingBlock |
空 |
挂起返回当前挂起的块 |
| SetEtherbase |
空 |
设置coinbase |
Worker为挖矿管理的核心对象,主要的属性包括区块配置项(BlockConfig)、共识引擎(consensus.Engine)、交易事件处理通道或生产订阅处理(txsch、chainHead、chainSide Ch or Sub)、代理对象集、
属性:
| 属性名 |
类型 |
主要描述 |
| config |
*params.ChainConfig |
区块链config配置 |
| engine |
consensus.Engine |
共识引擎 |
| mu |
sync.Mutex |
互斥锁 |
| mux |
*event.TypeMux |
Type MeXUX将事件发送到已注册的接收方。接收机可以注册处理某些类型的事件。任何操作MUX停止后调用将返回ErrMxxOutlook零值已经准备好使用了。弃用:使用饲料 |
| txsCh
|
chan core.NewTxsEvent |
|
| txsSub |
event.Subscription |
|
| chainHeadCh |
chan core.ChainHeadEvent |
|
| chainHeadSub |
event.Subscription |
|
| …… |
…… |
…… |
| agents |
agents map[Agent]struct{} |
挖矿代理通道 |
| recv |
chan *Result |
结果通道 |
| eth |
Backend |
后台处理对象(账号管理、链、交易池以及链存储管理) |
| chain |
*core.BlockChain |
链对象 |
| proc |
core.Validator |
区块核查对象,核查区块儿内容 |
| chainDb |
ethdb.Database |
数据库封装所有数据库操作。所有的方法都是安全的并发使用。 |
| coinbase |
common.Address |
Coinbase |
| extra |
[]byte |
区块的extraData |
| currentMu |
sync.Mutex |
当前互斥锁 |
| current |
*Work |
当前执行的工作work |
| snapshotMu |
sync.RWMutex |
读写锁快照 |
| snapshotBlock |
*types.Block |
区块快照 |
| snapshotState |
*state.StateDB |
状态快照 |
| uncleMu |
sync.Mutex |
数块互斥锁 |
| possibleUncles |
map[common.Hash]*types.Block |
数块哈希映射 |
| unconfirmed |
*unconfirmedBlocks |
未确认区块 |
| atWork |
int32 |
运行中的引擎数量 |
| running |
int32 |
状态判定字段 |
方法:
| 方法名 |
参数 |
描述 |
| newWorker |
Config,engine,eth,mux返回*worker |
初始化Worker函数 |
| setEtherbase |
addr (common.Address) |
设置coinbase |
| setExtra |
extra ([]byte) |
设置extra |
| pending |
返回(*types.Block, *state.StateDB) |
返回快照防止房钱互斥锁征用 |
| pendingBlock |
返回 *types.Block |
返回区块快照 |
| start |
空 |
启动所有agent挖矿工作 |
| stop |
空 |
停止所有agent挖矿工作 |
| isRunning |
空 |
返回是否运行bool值 |
| register |
agent |
注册新代理,若worker运行则启动代理挖矿 |
| unregister |
Agent |
解除已存在的agent,并停止挖矿 |
| update |
空 |
处理交易、区块头等事件,更新区块、叔块和交易信息 |
| wait |
空 |
更新所有日志中的块散列,从它现在可用时,而不是在创建单个事务的收据/日志时,广播pending的区块等待确认 |
| push |
Work |
创建一个新的work 任务给当前活动的矿工代理 |
| makeCurrent |
parent *types.Block, header *types.Header |
为当前循环,创建一个新的环境 |
| commitNewWork |
空 |
提交新的work |
| commitUncle |
Work,uncle |
在新的work中添加叔块hash |
| updateSnapshot |
空 |
更新快照 |
| commitTransactions |
Mux、 txs、bc、coinbase |
提交交易 |
| commitTransaction |
Tx,bc、coinbase、gp |
|
Work是矿工的执行环境,掌握所有当前状态信息
属性:
| 属性名 |
类型 |
主要描述 |
| config |
*params.ChainConfig |
区块链config配置 |
| signer |
types.Signer |
签名器封装事务签名处理 |
| state |
*state.StateDB |
网络状态存储 |
| ancestors |
mapset.Set |
祖先 用于检查叔块父块是否合法 |
| family |
mapset.Set |
用于检查叔块合法 |
| uncles |
mapset.Set |
叔块集合 |
| gasPool |
*core.GasPool |
Gas池 用于打包交易的可用gas值 |
| Block |
*types.Block |
新块儿 |
| header |
*types.Header |
…… |
| txs |
[]*types.Transaction |
…… |
| receipts |
[]*types.Receipt |
…… |
| createdAt |
time.Time |
…… |
Agent:挖矿代理
属性:
| 属性名 |
类型 |
主要描述 |
| mu |
sync.Mutex |
互斥锁 |
| workCh |
chan *Work |
Work 通道 |
| quitCurrentOp |
chan struct{} |
取消当前操作 |
| returnCh |
chan<- *Result |
返回执行结果(work 和区块) |
| chain |
consensus.ChainReader |
Uncle核查时提供查询区块链的对象 |
| Engine |
consensus.Engine |
共识处理引擎 |
| Started |
Int32 |
指定agent当前是否启动 |
方法:
| 方法名 |
参数 |
描述 |
| Work |
无 返回chan<-*Work |
返回工作通道 |
| SetReturnCh |
ch |
设置Work 通道 |
| Start |
空 |
调用update,启动挖矿 |
| Stop |
空 |
清空work |
| Update |
consensus.ChainReader |
Uncle核查时提供查询区块链的对象 |
| Mine |
work. stop |
调用engine.Seal封装交易,打包新块儿 |
Miner 中Gas及gasPrice相关重点分析:( blockheader 的gaslimit来源commitNewWork)
1)从miner、worker、work、agent的相关接口可知并无直接修改或者接受gas、gasprice、gaslimit的直接设定和修改,miner对gas、gasPrice不具有大的自主性修改权限和接收权限
2)挖矿打包的过程由eth.backend.go实现,其中对象Ethereum处理交易池、区块链存储、共识引擎、矿工、RPC服务等关键操作,值得注意的是ethereum对象包含gasprice对象,但该值初始化配置源于config的默认设置为big.NewInt(18 * params.Shannon),见eth.config.go文件中的DefaultConfig;
3)从commitTransactions函数分析,若新的work 的可用gas值gasPool为nil则默认将work正在处理的区块儿的区块头中的Gaslimit作为该work的gaspool,作为当前工作的可用gas。而当前work.header.Gaslimit来源于work. commitNewWork()中core.CalcGasLimit(parent),计算机制如下:
// contrib = (parentGasUsed * 3 / 2) / 1024,当父区块Gas使用量>2/3的时候,会较上次加大gaslimit,反之减小;
计算新区块gaslimit的贡献度值contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor(1024)
计算衰减量:decay = parentGasLimit / 1024 -1
此处work在打包时要进行gas判断:env.gasPool.Gas() < params.TxGas(21000),每个work的gas值(也就是说交易发送者提供的每笔交易gas)不能低于21000;
commitTransaction调用了core.ApplyTransaction函数,该函数的具体实现Gas的消耗和奖励机制,过程如下图:
TransitioinDb()的执行过程(/core/state_transition.go)。假设有StateTransition对象st, 其成员变量initialGas表示初始可用Gas数量,gas表示即时可用Gas数量,初始值均为0,于是st.TransitionDb() 可由以下步骤展开: