Ethereum Blockchain Block Raw Data in brief
缘起
由于最近在看智能合约相关内容,但一个对区块链有一些隐约的困惑,没有一个感性的认识。于是有了想分析区块内容的想法,以便能更深刻的认识区块链。其次最近简单学习了以太坊区块数据的格式,做个简答小结。主要资料可参考 Ethereum Wiki
区块格式
以太坊区块格式
主要参考这里
一个完整的区块定义格式是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| [ block_header, transaction_list, uncle_list, stack_trace ] 其中: transaction_list = [ transaction 0, transaction 1, ... ] uncle list = [ uncle_block_header_1, uncle_block_header_2, ... ] block_header = [ parent hash, number, TRIEHASH(transaction_list), TRIEHASH(uncle_list), TRIEHASH(stack_trace), coinbase address, state_root, difficulty, timestamp, extra_data, nonce ] stack_trace = [ [ medhash 0, stkhash 0 ], [ medhash 1, stkhash 1 ], ... ]
|
比如一个私链上的创世块是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| rawData: f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0a4328ecabdd749f4e24d190cd2bd00f6609f3334bf94a55fc2ea3e4ede05a44ba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008240008084ffffffff808080a00000000000000000000000000000000000000000000000000000000000000000880000000000000042c0c0 解析各个部分并按rfc定义用RLP编码转16进制输出 BlockData [ truehash=55da6a62b7a8d0a438aa3934d3571b12269eb7c011a4e62df171de5c05fd2853 true hash=55da6a62b7a8d0a438aa3934d3571b12269eb7c011a4e62df171de5c05fd2853 true parentHash=0000000000000000000000000000000000000000000000000000000000000000 true unclesHash=1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 true coinbase=0000000000000000000000000000000000000000 true stateRoot=a4328ecabdd749f4e24d190cd2bd00f6609f3334bf94a55fc2ea3e4ede05a44b true txTrieHash=56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 true receiptsTrieHash=56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 true difficulty=4000 true number=0 gasLimit=ffffffff true gasUsed=0 timestamp=0 (1970.01.01 08:00:00) true extraData= true mixHash=0000000000000000000000000000000000000000000000000000000000000000 true nonce=0000000000000042 trueUncles [] trueTxs [] ]
|
每个transaction 和uncle_block_header 都是一张表。工作量证明数据是区块数据去除掉nonce(交易数)后的RLP编码。
uncle_list 和 transaction_list 分别是叔区块头和区块里的交易构成的表。nonce 和 extra_data 都被限制为最大32字节,除了在创世区块中参数extra_data会更大。
state_root 是一个包含所有地址的(key, value)对的默克尔-帕特里夏树(Merkle Patricia tree )的根, 其中每一个地址都由一个20字节二进制字符串表示。对于每个地址,储存在默克尔-帕特里夏树的 value 字段是一个对以下格式对象进行RLP串接编码形成的字符串:
[ balance, nonce, contract_root, storage_deposit ]
nonce 是该地址的交易数,每做一次交易都会增加1。其目的是(1)使每个交易只有一次合法的机会以防范重放攻击,(2)使得构建一个和已存合约有相同哈希的合约成为不可能(更准确地说,密码学意义上不可行)。balance 指的是合约或地址的平衡账目,以伟为单位。contract_root 是另一个帕特里夏树的根,在该地址被一个合约控制的情况下包含该合约的内存。如果一个地址没有被一个合约控制,contract_root 就会是一个空字符串。storage_deposit是一个计数器,储存花费的储存费用
注 RLP 递归长度前缀编码 (recursive length prefix encoding,RLP)
这种编码格式将任意长度和维度的字符串构成的数组串接成字符串。例如,[‘dog’, ‘cat’]被串接 (以字节数组格式) 为 [ 130, 67, 100, 111, 103, 67, 99, 97, 116];其基本的思想是把数据类型和长度编码成一个单独的字节放在实际数据的前面(例如‘dog’的字节数组编码为[ 100, 111, 103 ], 于是串接后就成了[ 67, 100, 111, 103 ].)注意RLP编码正如其名字表示的一样,是递归的;当RLP编码一个数组时,实际上是在对每一个元素的RLP编码级联成的字符串编码。需要进一步提请注意的是,以太坊中所有数据都是整数;所以,如果有任何的以一个或多个0字节开头的哈希或者地址,这些0字节应该在计算出现问题的时候去除。以太坊中没有串接数据结构包含任何以0开头的数值。整数以大端基础256格式存储(例如32767字节数组格式为[ 127, 255 ])。
详细代码可以参考ethereumj中Block的代码部分
bitcoin 区块格式
关于bitcoin的区块格式,已经有前人做了分析大致结构如下
比特币创世区块是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| { "txid" : "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", "version" : 1, "locktime" : 0, "vin" : [ { "coinbase" : "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73", "sequence" : 4294967295 } ], "vout" : [ { "value" : 50.00000000, "n" : 0, "scriptPubKey" : { "asm" : "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG", "hex" : "4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac", "reqSigs" : 1, "type" : "pubkey", "addresses" : [ "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa" ] } } ] }
|
关键代码在 bitcoinj 的Block的代码