mining-getwork

getwork

2012年末 废弃
Getwork
getwork is a JSON-RPC method sent over a HTTP transport.
getwork 比较方便也非常好理解,直接连接到矿池挖矿。只需要填入矿池地址、端口、用户名、密码就可以了
端口 8332
getwork has been removed in v0.10.0

because it does not easily support mining at hash rates above 4 GH/s.
superceded by the newer getblocktemplate mining protocol

POW 的计算就是算区块头的 hash 值,使其小于目标值。

int32_t nVersion;       //版本号,4字节
uint256 hashPrevBlock; //前一个区块的区块头hash值,32字节
uint256 hashMerkleRoot; //包含进本区块的所有交易构造的Merkle树根,32字节
uint32_t nTime; //Unix时间戳,4字节
uint32_t nBits; //记录本区块难度,4字节
uint32_t nNonce; //随机数,4字节

nVersion,区块版本号,只有在升级时候才会改变。
hashPrevBlock,由前一个区块决定。
nBits,由全网决定,每2016个区块重新调整,调整算法固定。
因此以上3个字段可以理解为是固定的,对于每个矿工来说都一样。

矿工可以自由调整的地方是剩下的3个字段。
nNonce,提供2^32种可能取值。
nTime,其实本字段能提供的值空间非常有限,因为合理的区块时间有一个范围,这个范围是根据前一个区块时间来定,比前一个区块时间太早或者太超前都会被其他节点拒绝。值得一提的是,后一个区块的区块时间略早于前一个区块时间,这是允许的。一般来说,矿工会直接使用机器当前时间戳。
hashMerkleRoot,理论上提供2^256种可能,本字段的变化来自于对包含进区块的交易进行增删,或改变顺序,或者修改Coinbase交易的输入字段。

矿池通过修改 coinbase 交易里面的 extraNonce,让每个矿工计算不同的header

比特币挖矿的逻辑过程如下:

  1. 打包交易,检索待确认交易内存池,选择包含进区块的交易。矿工可以任意选择,甚至可以不选择(挖空块),
    因为每一个区块有容量限制(当前是1M),所以矿工也不能无限选择。对于矿工来说,最合理的策略是首先根据手续费对待确认交易集进行排序,然后由高到低尽量纳入最多的交易。
  2. 构造 Coinbase ,确定了包含进区块的交易集后,就可以统计本区块手续费总额,结合产出规则,矿工可以计算自己本区块的收益。
  3. 构造hashMerkleRoot,对所有交易构造Merkle树。
  4. 填充其他字段,获得完整区块头。
  5. Hash运算,对区块头进行SHA256D运算。
  6. 验证结果,如果符合难度,则广播到全网,挖下一个块;不符合难度则根据一定策略改变以上某个字段后再进行Hash运算并验证。

此外难度有最低限制,也就是说 有个最大值,比特币最低难度取值nBits=0x1d00ffff,
对应的最大目标值为:0x00000000FFFF0000000000000000000000000000000000000000000000000000

rpc request

{"method":"getwork","params":[],"id":1}

不带参数调用getwork,返回数据如下:

{
"midstate" : "9226a024e0b77f61d49fd5ffdf828c6b5c4330c61ea2778c606a8e49d4ad8bd6",
"data" :"00000002e9337bac28ee28a949d2140f9fb0a0ab740acfd739d7bcf67ca31c2301db858ad2ca54d92c8c1cded715922c4df2b07d9f10fa1a6cf3db7e949b320615761ed4581c76f21b12d87500000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000",
"hash1" :"00000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000010000",
"target" : "00000000000000000000000000000000000000000000000075d8120000000000"
}

Data字段

共128字节(80区块头字节 + 48补全字节),因为SHA256将输入数据切分成固定长度的分片处理,每个切片64字节,
输入总长度必须是64字节的整数倍,输入长度一般不符合要求,则根据一定规则在元数据末端补全数据。
其实对于挖矿来说,补全数据是固定不变的,这里没必要提供,外部挖矿软件可以自行补齐。
甚至连nNonce字段都不需要提供,data最少只需要提供前面的76字节就够了。nTime字段也是必不可少的,外部挖矿程序需要参照节点提供的区块时间来调节nTime。