区块链技术与应用--比特币

15 min read

比特币的数据结构

哈希指针(hash pointers)

哈希指针(Hash Pointers)是一种数据结构,结合了哈希函数和指针的特性。它将数据块的内容通过哈希函数计算得到一个固定长度的哈希值,并将该哈希值与数据块的位置信息(指针)关联起来。
具体来说,哈希指针通常由两部分组成:
  • 哈希值(Hash Value):由哈希函数对数据块的内容计算得到的固定长度的哈希码。哈希值可以唯一地标识数据块的内容,即使数据块的内容发生了微小的改变,其哈希值也会发生较大的变化。
  • 指针(Pointer):指向存储数据块的位置信息,如存储器中的地址或者其他数据结构中的索引。
创世纪区块(genesis)
区块链中产生的第一个区块
最近区块(most recent block)
区块链中产生的最近的一个区块
画板 (点击查看大图)

默克尔树(Merkle tree)

画板 (点击查看大图)
其中每一个数据块就是一个交易tx,全节点包括block header和block body,而轻节点包括block header。block body包括交易的信息,如果我们在手机上交易,只有block header没有body信息,我们应该怎么做?这个时候就需要Merkle proof来找到从block header到tx的一条路径
如果我们想要查找一个交易是否不在Merkle tree中,我们应该怎么做呢?如果我们一个个查找时间复杂度是O(n)显然和查找在Merkle tree中的O(logn)比较慢?那么我们应该怎么查询呢?其实我们可以将最后的一层叶节点按哈希值进行排序,将我们查到的交易与叶节点的hash值进行比较。这种排好序的叫Sorted Merkle tree结构
但是比特币没有用的这种Sorted Merkle tree结构来做不存在证明,因为没有硬性需求,所以我们不需要这个结构,注意我们使用hash指针时要保证无环,如果链表中存在环,会导致块中哪个哈希值都无法确认的问题。

比特币协议

数字货币体系和传统的货币体系有什么区别吗?传统货币,如果你有100元,你想要和别人进行交易,你就损失了你的100元。但是数字货币,你有100元的数字货币,你可以复制1份,把它进行交换。这就是double spending attack双花攻击。那么我们应该怎么防范这个问题呢?我们可以在数字货币上加上一个代号用来防伪,保证一个编号对应一个人,当我们复制一个数字货币时,就会与央行的代号映射产生矛盾,这样就保证了数字货币的安全性。但这是一个中心化的方案,每次交易都必须通过央行来证明货币的合法性,因此我们能不能找到一个去中心化的方案使数字货币由广大群众承担。这也是比特币数字系统需要解决的原因。
为了解决这个问题,我们就需要用的区块链这个数据结构。
假如A拥有铸币权,铸了10个比特币。A将这10个比特币给B和C,每个人给5个比特币,这个交易需要A证明这是A同意的
我们上面说了我们要有一个hash pointer来保证信息不被篡改,但我们还需要一个指针用来溯源,来证明这个钱是有记录的,不是凭空捏造的,同时也防止了double spending attack,但是我们想要a给b转比特币,我们还需要知道b的地址,那么b的地址又是怎么来的呢?其实b的地址是由b的公钥通过hash加密等一系列操作得来的,也就是b的账户号,那么我们怎么证明转账的合法性呢?如果A向B进行转账,我们要先知道A的公钥也就是A的签名来保证这个转账是A转的,那么我们怎么保证所有人都知道A的公钥呢?因为这个交易是A和B之间的交易,如果我们直接将A的公钥直接发送给B那么就是不是完成这次验证呢?其实,这样做还是存在一个问题,如果有一个中间人,用自己的公钥冒充A的公钥给B发生信息那么该怎么办呢?其实我们可以进行溯源,如果中间人冒充A的公钥给b发送,由于铸币A这里公钥对应一个hash值,我们将这个篡改后的公钥重新带如到原来公钥加密的哈希函数就不一致了,这就证明了,这个公钥不是a发送给b的公钥,而是篡改后的。
交易其实都是自动化的,比如a和b进行交易,a的输入脚本和a前面的输出脚本合成一段程序,如果没有错误,那么证明交易通过。也叫BitCoin Script
而这一个交易流程就组成了上面的tx

block header

存储比特币的版本协议,以及回溯指针和Merkle tree的根hash值,挖矿的难度阈值target,随机数nonce
挖矿就是找到一个H(block header)<=target,就说明挖到了一个区块
target存的其实是目标阈值的一个编码nBits

block body

block body存在交易列表transaction list,block body中的节点存在两种:一种是full node(fully validating node),一种是light node
比如有一个节点收到很多交易请求,我判断一下哪些交易是合法的,然后我将它打包写入到下一个区块中,从而构造出一个本地的区块链,每个节点独立决定,是否可行?这样就会存在一点问题,就是每一个本地区块链都不一致,应该怎么解决?或者说是这个账本不一致的问题应该怎么去解决?
这个问题也叫做:账本的内容要取得分布式的共识。

分布式共识(distributed consensus)

分布式的哈希表distributed hash table

比如我在这个分布式哈希表中插入一个key-value-pair。其中有很多不可能结论impossibility result,如FLP impossibility result,就是如果一个系统中网络传输是异步的,网络时延没有上限,哪怕系统中有一个内容是faulty,那么我们也不能达成共识。

CAP Theorem

C指的是Consistency,A指的是Availability,P指的是Partition tolerance
也就是说在这个分布式哈希表中,这三个性质最多满足两个,不可能三个性质都满足,也就是一致性,容忍性,区分可用性不能同时满足。

Paxos协议

用来保证一致性

比特币中的共识协议

比特币共识协议需要解决的问题是有些节点是由恶意的。我们假设这些节点中仅有一部分是坏的,大部分都是好的,那么我们应该怎么设置比特币的共识协议呢?
一种方式是采取投票的方法,我们可以选择一些交易排序之后放到区块中作为我们的候选区块,然后大家再对这个候选区块进行投票,如果这些交易都是有效的就投赞成票,否则就投反对票,这样可以吗?这样就存在一个问题,就是谁投票的问题,谁能进行投票,比如联盟链hyperledger fabric ,如果有一台超级计算机,可以不断的产生账户,当我们的账户产生到一定数量,到全部的一半时,就掌握了控制权,这个方式叫做女巫攻击sybil attack。
其实比特币也是使用投票的这种方式进行,只不过是通过计算力进行投票。每一个节点都可以在本地组装成一个候选区块,把认为合法的交易放到这个区块中,然后挖矿尝试各种nonce随机数值,使得H(block header)<=target,nonce大小是4byte,如果某个节点找到了符合条件的nonce,那么我们就可以说它获得了记账权(在去中心化账本写入下一个区块的权利),找到这个区块之后,我们要验证这个区块的合法性,验证一下block header中的nBits(目标阈值的编码)是否正确,然后再看一下block body的交易列表,看一下每个交易是否是合法的(是否有合法的签名,以前没有被花过),如果不符合要求,说明这个区块不符合要求,就要放弃掉。
如果这些条件都满足的话,我们是否能够接受它呢?
同样我们还有一个问题,就是这个区块应该插在哪里呢?hash of prev block ,可以根据前面的hash pointer来确定具体插在那个地方。
这样就存在一个问题,其中一个区块是a->b,另一个区块是a->a'那么这个交易合法吗?我们可能认为它违反了上面的双花原则,a把钱转给了a'其实不然。假如b的来源是c->a,那么这个来源并没有对b产生影响,所以是合法的
但是这个a->a'这个结果显然是不能接受的,它把a->b这个交易进行了回滚。我们可以说虽然这个a->a'这个链是合法的,但不是最长的。我们把这个最长的合法链叫做longest valid chain,这个例子就是分叉攻击的例子forking attack。但是在正常情况下也存在分叉的情况,就是如果有两个节点同时找到合法的区块
那么我们应该接受哪一个呢?其实如果有两个等长的合法链,那么区块会优先进行寻找下一个区块,哪个先找到下一个区块,那么这个先找到的就是最长的合法链。另一个叫做orphan block被丢弃
那么我们为什么要耗费这么大的力去争取记账权,有什么好处?争取到拥有记账权的那个节点就会有很大的权利,可以选取哪些交易被写进区块,那么我们应该怎么解决这个问题呢?

block reward

我们如果想要获取比特币,应该怎么做呢?其实获取比特币的方式只有一个就是比特币交易,你把的美元与别人账户里的比特币进行交换,这样你就拥有了比特币,但是这样的比特币是凭空产生的,一开始比特币刚发布的时候,一个区块可以产生50个比特币,但是协议规定,210000个区块之后比特币就要减半,变成25个比特币

评论

区块链技术与应用--比特币 | Niutr's Blog | Niutr's Blog