如果你对比特币交易等数据感兴趣的话,可以自己部署一个BitcoinCore的全节点来同步数据
推荐京东的bds-btc,它已经修改了源码可以将区块的raw_data 发送到kafka中,然后能够从kafka中取消费它
https://github.com/jdcloud-bds/bds-btc
这里我主要解析下比特币的区块数据是怎么样的
区块整体结构
一个完整的区块结构主要由以下几部分构成:
字节 | 字段 | 说明 |
---|---|---|
4 | 区块大小 | 用字节表示的该字段之后的区块大小 |
80 | 区块头 | 组成区块头的几个字段 |
1-9 | 交易计数器 | 该区块包含的交易数量,包含coinbase交易 |
不定 | 交易 | 记录在区块里的交易信息,使用原生的交易信息格式,并且交易在数据流中的位置必须与Merkle树的叶子节点顺序一致 |
区块头结构
字节 | 字段 | 说明 |
---|---|---|
4 | 版本 | 区块版本号,表示本区块遵守的验证规则 |
32 | 父区块头哈希值 | 前一区块的哈希值,使用SHA256(SHA256(父区块头))计算 |
32 | Merkle根 | 该区块中交易的Merkle树根的哈希值,同样采用SHA256(SHA256())计算 |
4 | 时间戳 | 该区块产生的近似时间,精确到秒的UNIX时间戳,必须严格大于前11个区块时间的中值,同时全节点也会拒绝那些超出自己2个小时时间戳的区块 |
4 | 难度目标 | 该区块工作量证明算法的难度目标,已经使用特定算法编码 |
4 | Nonce | 为了找到满足难度目标所设定的随机数,为了解决32位随机数在算力飞升的情况下不够用的问题,规定时间戳和coinbase交易信息均可更改,以此扩展nonce的位数 |
区块头(80字节):
0100000055bd840a78798ad0da853f68974f3d183e2bd1db6a842c1feecf222a00000000ff104ccb05421ab93e63f8c3ce5c2c2e9dbb37de2764b3a3175c8166562cac7d51b96a49ffff001d283e9e70
版本号(4字节):01000000
父区块头hash值(32字节):55bd840a78798ad0da853f68974f3d183e2bd1db6a842c1feecf222a00000000
merkle根(32字节):ff104ccb05421ab93e63f8c3ce5c2c2e9dbb37de2764b3a3175c8166562cac7d
时间戳(4字节):51b96a49
难度(4字节):ffff001d
Nonce(4字节):283e9e70
代码实现:
class block():
def __init__(self, handle):
if type(handle)==str: handle=fstring(handle)
self.magic = handle.read(4)
self.size = sum([ord(handle.read(1))*(256**x) for x in range(4)])
startingpos = handle.tell()
self.version = sum([ord(handle.read(1))*(256**x) for x in range(4)])
self.prevblock = handle.read(32)[::-1].encode('hex')
self.merkleroot = handle.read(32)[::-1].encode('hex')
self.timestamp = time.gmtime(sum([ord(handle.read(1))*(256**x) for x in range(4)]))
self.bits = handle.read(4)
self.nonce = sum([ord(handle.read(1))*(256**x) for x in range(4)])
handle.seek(startingpos)
self.header = handle.read(80)
self.hash = hash256(self.header)[::-1].encode('hex')
self.txcount = ord(handle.read(1))
if self.txcount>=253: self.txcount = sum([ord(handle.read(1))*(256**x) for x in range(2*(self.txcount-252))])
self.tx = [transaction(handle) for txn in range(self.txcount)]
self.size = handle.tell() - startingpos; handle.seek(startingpos)
self.raw = handle.read(self.size)
#self.merkletree
#self.isvalid() to verify merkle tree, hash, and difficulty
交易同理,只要掌握了它的数据结构解析出来就很简单了,只是表示形式不同而已,这里可以参考:
https://www.jianshu.com/p/8289df50112f
解析交易代码实现:
class transaction():
def __init__(self, handle):
if type(handle)==str: handle=fstring(handle)
startingpos = handle.tell()
self.version = sum([ord(handle.read(1))*(256**x) for x in range(4)])
self.numinputs = ord(handle.read(1))
if self.numinputs>=253: self.numinputs = sum([ord(handle.read(1))*(256**x) for x in range(2*(self.numinputs-252))])
self.inputs = [txinput(handle) for inputnum in range(self.numinputs)]
self.numoutputs = ord(handle.read(1))
if self.numoutputs>=253: self.numoutputs = sum([ord(handle.read(1))*(256**x) for x in range(2*(self.numoutputs-252))])
self.outputs = [txoutput(handle) for outputnum in range(self.numoutputs)]
self.locktime = sum([ord(handle.read(1))*(256**x) for x in range(4)])
self.size = handle.tell() - startingpos; handle.seek(startingpos)
self.raw = handle.read(self.size)
self.hash = hash256(self.raw)[::-1].encode('hex')
以上是比较原始的方法,你可以借助其他工具,我这里总结了一些,希望对你有用;
(1)本地rpc的方法:
https://www.jianshu.com/p/514512224e68
bitcoind -damon
bitcoin-cli -rpcconnect=127.0.0.1 -rpcuser=rpc -rpcpassword=123 getblock 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
(2) 直接读取
了解区块数据结构即可,参考 https://github.com/rigmarole/blk-reader
(3) 借用工具
https://github.com/alecalve/python-bitcoin-blockchain-parser
(4) 借助API
https://github.com/blockchain/api-v1-client-python
(5) 其他
一个好用的工具bitiodine:
https://github.com/mikispag/bitiodine
bitcoin数据分析:
https://github.com/citp/BlockSci
因为数据量比较大,可以结合一些spark等工具来进行解析和分析,如果要用于交易溯源等可以参考一些论文。如果你对比特币或者其他区块链数据分析感兴趣可以私信可以进行一起研究,谢谢,鸣谢此前作出解读比特币数据结构的同学。