比特币挖矿算法

原文地址:https://blog.csdn.net/u013137970/article/details/79041038

基础数据

发行总量:2100万。 
新区块生成周期:约10分钟。 
挖矿难度调整周期:每2016个区块,大约2个星期。 
挖矿奖励:比特币的挖矿奖励来源于两部分:

  • 创世区块奖励50个比特币,以后每210000个区块减半,即约4年调整一次。目前已经经历了两次减半,当前的挖矿奖励为12.5个比特币。
  • 比特币的每个交易必须支付一定数额的手续费给矿工。这个设定是为了防止恶意节点发送大量的垃圾交易对比特币网络进行DOS攻击。

挖矿算法

挖矿参考算法:挖矿算法为SHA256。在挖矿过程中,矿工将比特币的80个字节长度的区块头数据进行两次SHA256运算,运算结果就是一个256位(32字节)长度的字符串。通过比较与当前难度值的大小判断当前区块是否合法。即满足下列条件: 
SHA256(SHA256(block_header))< difficulty 
如果不满足上面的条件,则需要在区块头中改变一下随机值,或者使用随机数据填充coinbase交易,这样就能改变区块头的数据,从而找到满足条件的区块。这就是PoW机制的精髓所在,使用单向函数,迫使矿工不断地尝试随机数找到符合条件的区块以完成一定的计算量,保障系统的安全稳定。

实例分析

为了更加深入理解比特币的挖矿算法,以一个实际的区块数据为例。

首先获取区块号为100000的区块原始数据,可以在https://webbtc.com/block/000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506.hex上获取:

0100000050120119172a610421a6c3011dd330d9df07b63616c2cc1f1cd00200000000006657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f337221b4d4c86041b0f2b57100401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08044c86041b020602ffffffff0100f2052a010000004341041b0e8c2567c12536aa13357b79a073dc4444acb83c4ec7a0e2f99dd7457516c5817242da796924ca4e99947d087fedf9ce467cb9f7c6287078f801df276fdf84ac000000000100000001032e38e9c0a84c6046d687d10556dcacc41d275ec55fc00779ac88fdf357a187000000008c493046022100c352d3dd993a981beba4a63ad15c209275ca9470abfcd57da93b58e4eb5dce82022100840792bc1f456062819f15d33ee7055cf7b5ee1af1ebcc6028d9cdb1c3af7748014104f46db5e9d61a9dc27b8d64ad23e7383a4e6ca164593c2527c038c0857eb67ee8e825dca65046b82c9331586c82e0fd1f633f25f87c161bc6f8a630121df2b3d3ffffffff0200e32321000000001976a914c398efa9c392ba6013c5e04ee729755ef7f58b3288ac000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac000000000100000001c33ebff2a709f13d9f9a7569ab16a32786af7d7e2de09265e41c61d078294ecf010000008a4730440220032d30df5ee6f57fa46cddb5eb8d0d9fe8de6b342d27942ae90a3231e0ba333e02203deee8060fdc70230a7f5b4ad7d7bc3e628cbe219a886b84269eaeb81e26b4fe014104ae31c31bf91278d99b8377a35bbce5b27d9fff15456839e919453fc7b3f721f0ba403ff96c9deeb680e5fd341c0fc3a7b90da4631ee39560639db462e9cb850fffffffff0240420f00000000001976a914b0dcbf97eabf4404e31d952477ce822dadbe7e1088acc060d211000000001976a9146b1281eec25ab4e1e0793ff4e08ab1abb3409cd988ac0000000001000000010b6072b386d4a773235237f64c1126ac3b240c84b917a3909ba1c43ded5f51f4000000008c493046022100bb1ad26df930a51cce110cf44f7a48c3c561fd977500b1ae5d6b6fd13d0b3f4a022100c5b42951acedff14abba2736fd574bdb465f3e6f8da12e2c5303954aca7f78f3014104a7135bfe824c97ecc01ec7d7e336185c81e2aa2c41ab175407c09484ce9694b44953fcb751206564a9c24dd094d42fdbfdd5aad3e063ce6af4cfaaea4ea14fbbffffffff0140420f00000000001976a91439aa3d569e06a1d7926dc4be1193c99bf2eb9ee088ac00000000
  • 1

获取的数据是16进制的,其中前80个字节是区块头数据。对前80个字节数据进行双SHA256运算,得到当前区块的哈希值。Go语言代码如下:

package main

import (
    "crypto/sha256"
    "encoding/hex"
    "fmt"
)

const HashSize = 32
type Hash [32]byte

func (hash Hash) String() string {
    for i := 0; i < HashSize/2; i++ {
        hash[i], hash[HashSize-1-i] = hash[HashSize-1-i], hash[i]
    }
    return hex.EncodeToString(hash[:])
}

func main() {
    block, _ := hex.DecodeString("0100000050120119172a610421a6c3011dd330d9df07b63616c2cc1f1cd00200000000006657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f337221b4d4c86041b0f2b57100401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08044c86041b020602ffffffff0100f2052a010000004341041b0e8c2567c12536aa13357b79a073dc4444acb83c4ec7a0e2f99dd7457516c5817242da796924ca4e99947d087fedf9ce467cb9f7c6287078f801df276fdf84ac000000000100000001032e38e9c0a84c6046d687d10556dcacc41d275ec55fc00779ac88fdf357a187000000008c493046022100c352d3dd993a981beba4a63ad15c209275ca9470abfcd57da93b58e4eb5dce82022100840792bc1f456062819f15d33ee7055cf7b5ee1af1ebcc6028d9cdb1c3af7748014104f46db5e9d61a9dc27b8d64ad23e7383a4e6ca164593c2527c038c0857eb67ee8e825dca65046b82c9331586c82e0fd1f633f25f87c161bc6f8a630121df2b3d3ffffffff0200e32321000000001976a914c398efa9c392ba6013c5e04ee729755ef7f58b3288ac000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac000000000100000001c33ebff2a709f13d9f9a7569ab16a32786af7d7e2de09265e41c61d078294ecf010000008a4730440220032d30df5ee6f57fa46cddb5eb8d0d9fe8de6b342d27942ae90a3231e0ba333e02203deee8060fdc70230a7f5b4ad7d7bc3e628cbe219a886b84269eaeb81e26b4fe014104ae31c31bf91278d99b8377a35bbce5b27d9fff15456839e919453fc7b3f721f0ba403ff96c9deeb680e5fd341c0fc3a7b90da4631ee39560639db462e9cb850fffffffff0240420f00000000001976a914b0dcbf97eabf4404e31d952477ce822dadbe7e1088acc060d211000000001976a9146b1281eec25ab4e1e0793ff4e08ab1abb3409cd988ac0000000001000000010b6072b386d4a773235237f64c1126ac3b240c84b917a3909ba1c43ded5f51f4000000008c493046022100bb1ad26df930a51cce110cf44f7a48c3c561fd977500b1ae5d6b6fd13d0b3f4a022100c5b42951acedff14abba2736fd574bdb465f3e6f8da12e2c5303954aca7f78f3014104a7135bfe824c97ecc01ec7d7e336185c81e2aa2c41ab175407c09484ce9694b44953fcb751206564a9c24dd094d42fdbfdd5aad3e063ce6af4cfaaea4ea14fbbffffffff0140420f00000000001976a91439aa3d569e06a1d7926dc4be1193c99bf2eb9ee088ac00000000")
    first := sha256.Sum256(block[:80])  // 选择区块的前80个字节,即区块头数据,进行第一次哈希运算
    second := sha256.Sum256(first[:])   // 将第一次结果继续哈希,得到第二个结果,该结果为区块哈希值
    fmt.Printf("blockheader is: \n%x\n", block[:80])
    fmt.Printf("doublehash is:\n%v\n", Hash(second))
}
  • 运行结果为:
blockheader is:
0100000050120119172a610421a6c3011dd330d9df07b63616c2cc1f1cd00200000000006657a9252aacd5c0b2940996ecff952228c3067cc38d4885efb5a4ac4247e9f337221b4d4c86041b0f2b5710
doublehash is:
000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506

可以发现经过两次SHA256运算之后得到的结果就是区块哈希。


猜你喜欢

转载自blog.csdn.net/metal1/article/details/80152211