前言
我们知道区块链是由多个区块链接而成的一条链,每一个区块都包含着一些数据,我们通过比特币区块的解析来了解一下区块链。
区块结构
比特币大概每10分钟左右产生一个区块,每个区块的容量是中本聪设置的1M大小。我们可以在blockchain这个网站上看到最近产生的区块。
一个完整的区块包括以下5块内容:
名称 | 数据大小 | 说明 |
---|---|---|
魔数(Magic NO) | 4字节 | 总为常数0xD9B4BEF9,作为区块之间的分隔符 |
区块大小(Blocksize) | 4字节 | 用于记录当前区块的大小(即该字段之后的区块大小) |
区块头(Blockheader) | 80字节 | 记录当前区块头上的一些信息 |
交易计数(Transaction counter) | 1-9字节 | 该区块包含的交易数量,包含coinbase交易 |
交易详情(Transactions) | 不定 | 包含了当前区块保存的所有交易细节 |
区块内容解析
我们从webbtc里随便选一个区块,看到内容如下图所示:
这里是从区块里读出的一个数据的概要。具体的原始数据可以查看Formats那一行,一个是json数据,一个是十六进制的数据,还有一个是二进制的数据。我们这里直接查看json数据即可。下面我把整个json数据分成了三个部分便于查看。
当前区块Hasn、区块头、交易计数、区块大小
{
"hash": "000000000000000001806a922d4d35a37ad9324c690f72d556c6445cb7a9c214",
"ver": 536870914,
"prev_block": "000000000000000000f061205567dc79c4e718209a568879d66132e016968ac6",
"mrkl_root": "83f5fdf40b0b02c09ae669041df1bedfc635c45f696057a8c29e1bde1f4cbd24",
"time": 1482006384,
"bits": 402885509,
"nonce": 636041063,
"n_tx": 20,
"size": 6264
}
当前区块Hasn
我们看这段json数据,第一个是当前区块的Hash,但它并不保存在区块的数据结构里,不管是该区块在网络上传输时,抑或是它作为区块链的一部分被存储在某节点的永久性存储设备上时。相反,区块哈希值是当该区块从网络被接收时由每个节点计算出来的。区块的哈希值可能会作为区块元数据的一部分被存储在一个独立的数据库表中,以便于索引和更快地从磁盘检索区块。
简单的说就是这个值被算出来后在本地数据库或缓存中,然后供下个区块生成或者是到来较验用,然后在下一个区块生成时,在下一个区块的区块头中保存。
区块头
//bitcoin 区块头的代码
class CBlockHeader
{
public:
// header
int32_t nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
uint32_t nTime;
uint32_t nBits;
uint32_t nNonce;
CBlockHeader()
{
SetNull();
}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(this->nVersion);
READWRITE(hashPrevBlock);
READWRITE(hashMerkleRoot);
READWRITE(nTime);
READWRITE(nBits);
READWRITE(nNonce);
}
void SetNull()
{
nVersion = 0;
hashPrevBlock.SetNull();
hashMerkleRoot.SetNull();
nTime = 0;
nBits = 0;
nNonce = 0;
}
bool IsNull() const
{
return (nBits == 0);
}
uint256 GetHash() const;
int64_t GetBlockTime() const
{
return (int64_t)nTime;
}
};
区块头包含以下6个部分:版本、父区块头哈希值、Merkle根、时间戳、难度目标、随机数,总共80个字节。
名称 | 数据大小 | 说明 |
---|---|---|
版本(ver) | 4字节 | 数据区块的版本号 |
父区块头哈希值(prev_block) | 32字节 | 记录了前一个区块的哈希值,当前区块的哈希值一定比它小 |
Merkle根(mrkl_root) | 32字节 | 该区块中交易的Merkle树根的哈希,是根据当前区块所有交易的哈希值生成的 |
时间戳(time) | 4字节 | 该区块产生的近似时间,精确到秒的UNIX时间戳,必须严格大于前11个区块时间的中值,同时全节点也会拒绝那些超出自己2个小时时间戳的区块 |
难度目标(bits) | 4字节 | 该区块工作量证明算法的难度目标,已经使用特定算法编码 |
随机数(nonce) | 4字节 | 为了找到满足难度目标所设定的随机数,为了解决32位随机数在算力飞升的情况下不够用的问题,规定时间戳和coinbase交易信息均可更改,以此扩展nonce的位数 |
交易计数
n_tx即是当前区块的交易计数,我们能看到一共有20笔
区块大小
size即为当前区块的大小,这里看到的为6264字节
交易详情
以下数据即为交易详情,一共20笔,我这里只取了其中的两笔交易,其中第一笔为coinbase交易,即由挖矿产生的比特币奖励。
{ "tx": [
{
"hash": "f94528b2012446f4e367694871d07d5c726788e2f20d5553161a24debbec5118",
"ver": 1,
"vin_sz": 1,
"vout_sz": 1,
"lock_time": 0,
"size": 154,
"in": [
{
"prev_out": {
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
"n": 4294967295
},
"coinbase": "03efc506fabe6d6d3146d1ecf0c8b111d52ee100ef81dc1ab32ce28f4f6b677e9eb0f0a5032fa9270100000000000000016506008508ed705d0000ea6e1c2f736c7573682f",
"sequence": 0
}
],
"out": [
{
"value": "12.50503278",
"scriptPubKey": "OP_DUP OP_HASH160 7c154ed1dc59609e3d26abb2df2ea3d587cd8c41 OP_EQUALVERIFY OP_CHECKSIG",
"address": "1CK6KHY6MHgYvmRQ4PAafKYDrg1ejbH1cE"
}
],
"nid": "0f66ac12827c122c2df335ba8c4d89ca0d0b071cab39ab1e6b436ed3fb246d36"
},
{
"hash": "c8a340969b594332876f357207083a6a36b3269e37302315e8bef05032105346",
"ver": 1,
"vin_sz": 1,
"vout_sz": 2,
"lock_time": 0,
"size": 334,
"in": [
{
"prev_out": {
"hash": "8529367f8e6d3cf34fe702eb05a18e67e521385835e735e5c69184b14d19f688",
"n": 1
},
"scriptSig": "0 30450221009c1503bc1500b58aab48bfe62d40fb511a03193e8a7fbdefde4915949dc2ade902207920d7a86e819b568d34d931871d94824cec8dad63dc977d354b65264380907501 304502210095b2184dd3649e2a5025cd8e67a2c3aad6dc022848160f169006c322d77f67d302205ff0f8417126650c5b5e71abc64e37c1769a312d613602b96a944a8281f6c69c01 5221032284521d6790130f7043136a14b60119cea371c754cb3743b56c61b7d495d6e42103f15e3cdd49c26ea7b00c9b5ddeac06129033ac38e5a0b739883e0b302138ec3552ae"
}
],
"out": [
{
"value": "0.00149700",
"scriptPubKey": "OP_HASH160 88196be31c9252c3895e495bd657d7dd389ddd94 OP_EQUAL"
},
{
"value": "0.00824600",
"scriptPubKey": "OP_HASH160 d4dc84eedfec38bad0510d364b2c8fd4fce57151 OP_EQUAL"
}
],
"nid": "ccd4371ec31f533884416959ad1e5503c9be5fb3262d7a40fc6ec58f9cf54090"
}
·
·
·
·
]
}
我们能看到每一笔都有输入和输出,以及交易哈希、版本号等等。
默克树(Merkle Tree)
{
"mrkl_tree": [
"f94528b2012446f4e367694871d07d5c726788e2f20d5553161a24debbec5118",
"c8a340969b594332876f357207083a6a36b3269e37302315e8bef05032105346",
"460bf9d5db9f1df960c03b5225316ac77d1965b8f4ac429e0e66a6e097018a07",
"104bf4664aab45e8e20274fbed530eccf22af9565e10597bd63965f0bbbf11ff",
"9b49a5734b040cfcd370c0af924f590d79eceb1cfb77b655770713bff9e01281",
"8da9855406072b487dc14c05f9d1fb98eaea5cdf802aafe9a361fd23531db819",
"9430c839d5605f59ed7a47ed59d50c1cec2d62e771f7a02bfbb17d91416af4b9",
"ebe8e007b49aceef46e3971564802b049029a9bdc31d2ed1b0be23633b01236b",
"26ffe42a53c5caabd37ca0a260d3e6e15d0dbdb30cd641d8fa2690f065b5b712",
"358f05fb03bad69fb4ebcef9a74dea2a7fd4368e31e0ac7794a155f4930ba4e6",
"8d1ab4e9c5b788d97f126a7c22ab67b8326cbed2d1b992bbc8dcdbb74b13bf7d",
"4c2980e9bca8044f61db1e1422fb92aab50389517c8d8da8dca79ae2d73776c4",
"72fa5baf9250e5226afaaa1dd7194912027407111642f1e420e42f52023eba60",
"3facb7091d0c4330735b3d184662a52902c820e98de65ac692075abb2d917db7",
"46c33ae0d9f03cc97bcb94013f4c54640614db1768728c928d0ac7ebd9f8c1c9",
"6dcaec17dc034f242166c8e2161acbefcf3b30087a96ed621da7cdccc8ff3002",
"40edfee9764baab18bbe375fa5d15c26ecdf109f90fa27522809902c441e45ab",
"45b3093eb524baa5b078f73755b80789af733c78c16ec612ed435860c33020fa",
"2b05f2168afc22d73b929fbdcb8e38fea969fa1fbe7cb6e10efb37e876f5cfe2",
"323c7c81cff26c38171c4740d5163ff5ef0ab23de80a2a069f95405d0945b693",
"99deb2a2f7d199062e3a075e9bb0b58f7fb8498621e799e3365e1a3c4c255d8d",
"ecfc6aea54b4d7e517a3170d291bde5f9edb0119dedf8193b8ddf90e583c19cc",
"c549c24b1575ada64dd21a5b59f6018e44d9e4caec0a0505f034b7d4cb54c7d9",
"c9001c84acba3b2e5c2020344552d29a09460dd86906757394caa80c49b84c08",
"197eb574bcbf4b85c934bc985a15bfc6f2e5da513e5e8ccc9206a50edd66297f",
"4e92a4eb49c494146a5172b0dddb903013d478c82f7c9da81a675872468ac7d6",
"7849c98a4bd4af150eb9c954cda0734a9dbcf9e2f88e34480bc910544d3fdf4c",
"dfd05872158c2a78923159f1cb1182c89641398967c458d768bdb422c397fa57",
"9b27fb4636d299311abb6015ca27760e408fce7802d196fa14a0a9470e219bbb",
"da9b1c4deda656cc215646f204700b7829fd72a2e2ebd967e1fa01e1811c7ec1",
"b81ab1b0c6cc42fdb56176ede115bee5b66a571ebbf8053f6510fdd3a9927501",
"7ca0e3b3e7cc193fbc1f6553cfca35b3358727b3107c0d5914311685bdf761a8",
"5ce961502e61d22b77860d478dfb0b4073ba5249b11aaba32e2c13db4b4356c7",
"c1a84c7a58fdf92834b05aadffaaaeef4745ea60a8914a250b010e581839221a",
"f1e7cbe4a5f916c87fab0049eaccd6dc825ca7ac495575c01a3fc9b358d2c377",
"bebd7be3317d84cce8c2674d39c883a4218d218294f7154c33359c34b7437fbb",
"91f5ea3df74833e2dd94ecc2b8360a8a764a01c5c006baab88556b923434706a",
"2298fca6dc939e048c79721afeaadfa6f8056eb8006b1f1e2d1d653e6baa438f",
"bf57c77219a6d905440368629f593c4fb4c23cc35d68b7305cc8506bbdb4e452",
"513be8c874a6bba6259e0a44a709e5a58c1cb0f610612c35b9725227b7c2bd78",
"83f5fdf40b0b02c09ae669041df1bedfc635c45f696057a8c29e1bde1f4cbd24"
]
}
上面为默克树(Merkle Tree)的整个树节点的信息。保存在区块头中的mrkl_root
就是由这个默克树生成的,我们能看到以上数组的最后一个Hash值跟区块头中的mrkl_root
相同,这个数据就是默克树最后生成的默克根。所以我们一共20笔交易,那么加上mrkl_root
一共就是20+10+5+3+2+1=41
个Hash值。下图是一个简单的默克树生成过程:
比特币使用默克树的方式对交易进行验证,相对于哈希列表,默克树是一种哈希二叉树,它的明显的一个好处是可以单独拿出一个分支来对部分数据进行校验,更加高效。