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() 可由以下步骤展开: