主页 > imtoken钱包app官方下载 > 比特币探索之一:区块链

比特币探索之一:区块链

imtoken钱包app官方下载 2023-03-26 07:16:43

再闲也不能睡懒觉,再忙也不能停止学习。

说起肥兔兔,我其实已经停止写技术博客十几年了。 当然原因有很多,不完全是偷懒,我一开始也不是很好,但是我还是觉得写技术博客确实是一个很好的学习方式。 把一些心得写出来,既愉快,又能巩固和交流,利人利己。

少八卦。 2017年异常火热的比特币暴涨,再加上背后的区块链技术,吸引了无数眼球,自然少不了热衷于投资的中国大妈们。 本来肥兔兔还不懂区块链,被几位阿姨的质疑和鄙视之后,变得不那么淡定了。 于是我下定决心,抽空好好研究一下,这就是本系列文章的由来,顺便也算是重开技术博客的敲门砖。

当前区块链领域的几大支柱,第一是比特币,无可争议的鼻祖比特币每个区块包含多少交易,代表着区块链1.0时代,创始人是名不见经传的中本聪。 二是以太坊,引入了智能合约,开创了区块链2.0时代。 创始人Vitalik Buterin被国人称为V神,标准的90后小伙子,19岁就写出了以太坊白皮书。第三个是号称要迎来区块链3.0时代的EOS。 其主网于 6 月刚刚上线。 目前各方意见仍不一,但不可否认的是,EOS已经并将继续推动区块链技术的深入发展。

既然要学,从易到难,就从比特币开始。 肥兔兔一直信奉 Linus Torvalds 的名言:Talk is cheap, show me the code。 翻译成中文就是:别说那些没用的,给我看代码。 这几乎是一个有图有真相的真相。 在撰写本文时,比特币源代码版本为 0.16.1,基于 C++11。 好在肥兔兔的C++功力还在,OK,我们就从这里开始吧。

什么是区块链? 其实就是把一堆区块串在一起形成的链。 像下图这样:

比特币区块和比特币的区别_比特币莱特币量子链等交易_比特币每个区块包含多少交易

图 1-1 区块链示意图

每个区块都包含一个区块头和一堆交易数据。 区块链的伟大之处在于,首先,所有串在一起的区块都是相关的。 换言之,并不是只有单个区块才能上链,而是要经过复杂的计算和验证。 那就是传说中的采矿; 第二,整个区块链网络每个节点上的链都是一模一样的,不管你在中国还是南美,甚至全世界,你看到的链都是一模一样的,这是传说中的共识,你想偷偷换一个? 不好意思,其他所有节点都会告诉你,兄弟,你别耍花样了,老老实实一起玩吧!

让我们看看比特币源代码。 相关的数据结构是如何定义的? 先看一下肥兔兔简单画的UML类图:

比特币区块和比特币的区别_比特币莱特币量子链等交易_比特币每个区块包含多少交易

图 1-2 区块链的基本类

CBlockHeader 是区块头,CBlock 是区块。 这两个类在 primitives/block.h 中定义。

CBlockHeader 区块头

区块头包含的主要信息是版本号nVersion,方便软件升级。 只要区块的数据结构发生变化,版本号就必须随之改变,否则会出现不兼容的情况。 在比特币诞生之初,这个版本号一直是1。直到2012年,有人提出了比特币改进计划BIP-34,要求在区块中加入区块高度信息(即区块总数)。 最终,方案被讨论通过,并将这个高度信息添加到Coinbase解锁脚本中(这个脚本在区块头后面的交易数据中,我们以后会解释),区块头的结构有实际上并没有改变,只是版本号已经变成了2。这个改变发生在2013年3月24日下午15:49。在第227835个区块之后,所有区块的nVersion都变成了2。截至本文发表时,版本号还是2。

hashPrevBlock,指的是前一个区块头的hash。 什么是哈希? 它是一段数据的加密结果。 它的一大特点是只要对原始数据稍作改动,哪怕只是一个Bit,整个加密结果都会发生翻天覆地的变化。 每个区块都指向其前一个区块的哈希值,形成一条连续的链,这实际上就是“区块链”的由来。 为什么区块链是不可变的? 因为每一个区块一旦产生,它的哈希值就确定了。 如果你想改变一点点,对不起,后续链上的所有区块都必须重新生成,这将付出巨大的代价,我们将在未来详细说明。 请注意,它的类型是 uint256,因为它是使用 SHA256 加密算法生成的。

hashMerkleRoot 指的是交易树的根。 每个区块包含大量交易信息,以默克尔(Merkel)树的形式存储,效率很高,有助于节省硬盘空间。 区块头中只需要存储树的根,即可有效验证所有交易信息的真实性,防止非法篡改。 如果有人修改了某个交易信息,对应的哈希值就会发生变化,这个变化会依次上传到Merkle树的根部。 一旦root发生变化,hashPrevBlock也会随之变化,最终会导致整个block,以及后面的所有block的All changes。

nTime是一个时间戳,表示这个区块产生的时间。 它的格式是一个 32 位无符号整数,表示自 1970 年以来的所有秒数。

nBits 代表生成难度。 nNonce是一个随机数,两者都是用来挖矿的,以后再说。

CBlock块

CBlock继承自CBlockHeader,除了区块头数据外,还增加了两个:

vtx 代表这个区块中所有交易的集合。 它是一个vector,每个元素的类型都是CTransactionRef,是一个指向CTransaction的交易信息的指针。 交易详情将在文章后面介绍。

fChecked表示区块是否通过了合法性检查,包括工作量检查和交易信息检查。 每个区块在上链之前都必须经过校验,校验通过后才能上链。

CBlockIndex 块索引

CBlockIndex 和后面的 CChain 在 chain.h 中声明。

CBlockIndex 是块索引。 事实上,当区块链建立在内存中时,并不需要知道完整的区块内容,只要知道区块头即可。 CBlockIndex 区块索引已经包含了区块头的必要内容,足以构建一个完整的区块链。 另一方面,区块链节点分为全节点和轻节点。 全节点完整的保存了区块链的所有数据,包括所有的CBlockIndex和所有的CBlock,而轻节点只保存了CBlockIndex(包括所有的Block header信息),以及与本节点相关的交易信息,可以节省大量的硬盘空间(一个区块可能有几百K到1M,一个区块头只有80字节)。 如果轻节点需要查询其他交易信息,可以查询其他全节点。

CBlockIndex 中包含的数据是:

phashBlock 是这个区块的哈希值。

pprev是前一个CBlockIndex指针,pskip是更远的一个CBlockIndex指针。

nHeight为当前区块的高度,即整个区块链上当前区块的总数。 对于创世块,它的值为 0。

nFile 是当前块在磁盘上的存储编号。 对应的文件名为blk??????.dat。

nDataPos 是这个块在存储文件中的偏移量。 一个文件可以存储多个块,因此每个块都需要知道它在文件中的具体位置。 nUndoPos是这个block在rev??????.dat中的偏移量,存放的是每个block的undo数据。

nChainWork 是指包括本区块在内的所有区块的工作量之和。 此数据仅在内存中生成,不会写入磁盘。

nTx 是存储在该块中的所有交易的数量。 nChainTx 是所有区块中的交易总数。 这笔款项只有在本区块和所有父区块的交易数据都可用时才会产生,不会存储在磁盘上。 nChainTx目前还是32位数据,近期可能需要改为64位,但预计至少2030年之后。

nStatus 为该区块的验证状态。 稍后我会详细解释。

接下来,nVersion、hashMerkleRoot、nTime、nBits、nNonce是区块头对应的数据。 在生成CBlockIndex的时候,已经检查了hashPrevBlock,可以通过pprev->phashBlock获取,所以这里不需要额外存储。

nSequenceId是block的序号,只在内存中用来标识当前接收到的数据是哪一个block。

nTimeMax 是迄今为止所有区块的最大时间戳,仅在内存中使用。

CChain区块链

CChain 是存储在内存中的整个区块链。 它实际上只有一个数据成员vChain。

vChain的类型是vector,它是由所有的block index组成的vector,每个block index都可以很方便的访问。

OK,至此,我们基本了解了最基本的区块链数据结构。 那么区块中存储的主要是什么东西呢? 当然是交易信息啦! 可以说它是整个比特币的核心比特币每个区块包含多少交易,一切都围绕着交易展开。 我们将在下一篇文章中详细探讨。