北京大学肖臻老师《区块链技术与应用》公开课笔记:BTC原理(三):分叉、匿名性

9、BTC-分叉

分叉指的是,原来的系统中是一条链,现在分成了两条链。分叉可能是多种原因造成的,例如:

  1. 挖矿时两个节点差不多同时挖出矿,都会发布区块,这种分叉称为state fork,由于对区块链当前的状态有意见分歧而产生的分叉
  2. 分叉攻击(forking attack)也属于state fork,只不过这种意见分歧是人为造成的,这种情况也称为deliberate fork
  3. 比特币协议改变,要修改比特币协议需要软件升级,在去中心化的系统中,没办法要求所有的节点都升级软件。假设大部分节点升级了软件,少部分节点没有升级(可能是没来得及升级,也可能是不同意协议的修改),这时候也会出现分叉,这种分叉称为protocol fork,即对比特币协议产生了分歧,使用不同版本的协议而产生的分叉

在protocol fork中,根据对协议修改的内容的不同,又可以分为硬分叉软分叉

1)、硬分叉(hard fork)

如果对比特币协议增加一些新的特性,扩展一些新的功能,这时候没有升级协议的那些节点是不认可这些特性的,认为它们是非法的

硬分叉的一个例子就是比特币中的区块大小限制,比特币规定每个区块不超过1M,可以包含的交易最大数量为4000笔左右。而平均10分钟产生一个区块,算下来大约平均每秒只能写入7个交易。所以有的人就认为区块太小了,限制了交易上链的速度

假设协议更新了,将区块大小的限制从1M提高到4M,同时假设大多数节点更新了软件以支持这个协议(节点的多数和少数不是按账户数目来算的,而是根据算力来算的,假设系统中拥有大多数哈希算力的节点都更新了软件)

这样会有什么后果?

在这里插入图片描述

上图1为当前区块链,此时软件更新,如上图2有一个新节点挖出了一个大区块(因为新的协议只要不小于4M)。但对于旧节点来说,该区块是一个非法区块,旧节点是不认可这个区块的,不会沿着这个区块继续往下挖,而是继续沿着之前的区块往下挖下一个区块,如上图3

需要注意的是,旧节点挖出的区块新节点是认可的(因为并未超过4M限制)。对旧节点来说,上图3中下面的链才是合法链,而对于新节点来说,这两条链都是合法的链。因为新节点算力强,所以出现上图4中情况可能性大。对于新节点来说,上面的链才是最长合法链,新节点都会沿着上面的链继续挖;对于旧节点来说,上面的链无论多么长,都是一条非法链,不会认可该链,所以旧节点就会沿着下面的链继续挖矿

此时就出现了新节点永远沿着上面的链挖矿,旧节点永远沿着下面的链挖矿,由于新节点算力足够强,所以形成两条永远都在延伸且平行的链。当然,上面的链也有可能会挖出大小在1M内的小区块,但对旧节点来说,该链上存在非法区块,不会认可该链。这种分叉是永久性的,只要这部分旧节点永远不更新软件,下面的链就永远不会消失

  1. 比特币社区中有些人很保守,不愿意加大区块大小
  2. 区块大小也不是越大越好,比特币网络传输是尽力而为的,区块加大会造成传输变慢等问题
  3. 单纯增加区块大小,对交易数量的增加远不能达到数量级的提升

出现硬分叉之后,就相当于社区分裂了,出现了两条平行运行的链,两条链上的比特币也是不相干的,各挖各的矿。在某条链上的出块奖励,对于认可这条链为最长合法链的节点而言是有效的,对认可另一条链的则是无效的,而分裂之前产生的比特币则是在两条链上都认可的。从这个意义上来看,硬分叉可以认为是产生了新的一种加密货币

硬分叉之后,如果不采取任何措施,两条链互相之间会产生一定影响。因为两条链上的账户的私钥、公钥等都是一样的,仅仅是运行的协议不同,按理来说两条链上的账户余额应该不一样才对

如上图,在新链上有一笔B->C的交易,对旧链而言这笔交易也是完全合法的,旧节点挖矿时就会把这个交易回放了。这样就相当于B从一个钱包中拿出一定数量的币给C,导致B的另一个钱包中也转给了C同样数额(注意不是价值,如以太经典ETC和以太坊ETH)的币到相应的钱包中

为了解决这个问题,可以在硬分叉后设置chainId来标识这两条链为两条独立的链

2)、软分叉(soft fork)

如果对比特币协议加了一些限制,使得原本某些合法的交易或区块,在限制后的新协议中变得不合法,就会引起软分叉

假设协议更新将区块的限制大小变小了,从1M变成了0.5M(实际肯定不会这样做)

需要注意的是,区块链中区块大小调整并非简单修改一个参数,调改大小就很有可能会引发分叉,由于参数修改方式不同,有可能会是硬分叉,也有可能是软分叉

假设系统中大多数节点更新了软件,认为区块限制为0.5M;少部分节点是旧节点,仍然认为区块限制为1M

在这里插入图片描述

上图1为当前区块链,此时软件更新,如上图2有一个新节点挖出了一个小区块(因为新的协议不小于0.5M)。对于旧节点来说,该区块符合1M大小限制,旧节点认可这个区块,会沿着这个新的小区块开始挖矿,如上图3。但是新节点会认为旧节点挖出的区块超过0.5M限制,为一个非法区块,不会认可该区块,会从前一个小区块开始挖矿,如上图4。因为旧节点认可新区块,最终会造成如上图5中的效果,旧节点挖出的区块一直被抛弃,无法得到出块奖励(因为不在最长合法链上)。这就倒逼旧节点升级软件,最终会实现区块链上的所有矿工共同认可新协议,实现软件协议的升级

需要注意的是,旧节点如果不升级软件,挖出的区块可能就白挖了(大于0.5M),但对于系统来说,不会存在永久性分叉

实际当中可能出现软分叉的情况:

1)给某些目前协议中未规定的域赋予新的含义

最经典的就是,coinbase transaction(铸币交易)中CoinBase域。在CoinBase域中写入任何内容都可以,没有任何规定。挖矿本质是调整block header中的nonce,但其本身只有4个字节,搜索空间太小。所以实际使用中,将CoinBase域前8个字节作为extra nonce,此时搜索空间从原本 2 32 2^{32} 232增长到 2 96 2^{96} 296,对于目前挖矿难度来说已经足够

但CoinBase中并不是只有8个字节,还剩下很多空间。有人就提出将其作为UTXO(当前还没花掉的交易的输出)集合的根哈希值。目前UTXO是每个全节点自己在内存中维护的,主要是为了快速查找来判断交易是否是double spending,但UTXO内容并未写入区块链

由于UTXO存在本地,如果查询某账户余额,轻节点需要询问全节点,全节点根据UTXO中信息可以计算得到账户余额,如何证明全节点返回给轻节点的是正确的呢?轻节点自己没有维护一个UTXO集合,所以是证明不出来的

因此有人提出将UTXO中的交易也组织成一个Merkle Tree,将其根哈希值写在coinbase transaction的CoinBase域里面,而coinbase transaction中的此内容也会随着影响交易的Merkle Tree的根哈希值,这在轻节点里是保存了的。所以在这种方式下就可以像Merkle proof的方式一样证明账户里有多少钱(需要提供UTXO的Merkle Tree对应位置的哈希)

2)增加新的功能

P2SH(Pay to Script Hash)在最初的比特币系统中是没有的,是后来通过软分叉的方式加进去的

P2SH在支付时输出不是收款人公钥的哈希,而是一个赎回脚本(Redeem Script)的哈希

在赎回(把这些比特币花出去)时分为两阶段,第一阶段验证输入脚本中给出的赎回脚本,和前面交易的输出脚本中的赎回脚本的哈希对得上,第二阶段执行赎回脚本,验证输入脚本中给出的签名是合法的

对于旧节点而言,并不知道赎回脚本的这些特性,旧节点只会做第一阶段的验证,即验证赎回脚本是不是正确的(和哈希对得上)。只有新节点才会把两阶段的验证都做完

所以旧节点验证通过的交易,可能是第二阶段验证无法通过的P2SH形式的交易,在新节点上无法验证通过。而新节点验证通过的交易,旧节点也都验证通过

3)、小结

软分叉的特点:只要系统中拥有半数以上算力的节点更新了软件,就不会出现永久性的分叉

硬分叉的特点:必须系统中所有的节点都更新了软件,才不会出现永久性的分叉

10、BTC-问答

  1. 转账交易时候,如果接收者不在线(没有连在比特币网络上)怎么办?

    转账交易只需要在区块链上记录,将某账户比特币转到另一账户,而接收方是否在线并无影响

  2. 假设某全节点收到某个转账交易,会不会有可能转账交易中收款人地址该全节点从未听过?

    可能,因为比特币账户只需要本地产生即可。只有该账户第一次收到钱时,其他节点才能知道该节点的存在

  3. 如果账户私钥丢失怎么办?

    没有办法。因为比特币是去中心化货币,没有第三方中心机构可以重置密码,所以账户上的钱也就变成了死钱

    通过加密货币交易所(中心化机构),一般需要提供身份证明,如果忘记私钥可以找交易所申请追回私钥。但目前这类货币的交易所还处于缺少监管的状态,并不一定具有可信力

    在历史上,有很多次交易所被黑客攻击偷走大量加密货币的事情,其中最著名的为Mt.Gox(门头沟)事件。该交易所曾经为全球最大比特币交易所,交易量占到全球比特币交易量的70%左右,设于日本。后来由于被攻击丢失大量比特币,导致交易所破产,其CEO被判刑入狱

  4. 私钥泄露怎么办?

    尽快将剩余比特币转到其他安全账户上,没有第三方中心机构重置密码或冻结账户,只能自己对自己负责

    比特币系统中账户就是公私钥对,密码就是私钥,无法更改

  5. 转账写错地址怎么办?

    没有办法,无法取消已经发布的交易。如果转入不存在地址,则该部分比特币就成为了死钱。比特币系统中UTXO会永久保存该交易,记录该并不存在的地址。因此,对全节点来说,这是不友好的

  6. 比特币脚本中的OP_RETURN指令的执行结果是无条件返回错误,而交易返回错误,区块又怎么会包含它?区块链又如何会接收这个区块?

    OP_RETURN是写在当前交易的输出脚本中,而验证交易合法性时,使用的当前交易的输入脚本和前一个交易(币来源的交易)的输出脚本进行验证。也就是说,验证当前交易合法性时,并不会执行该语句。只有在有人想花这笔钱时候,才会执行该语句

  7. 比特币系统挖矿会不会有矿工偷答案?比如,某个矿工发现其他矿工发布了nonce,收到后验证该区块合法,将该nonce作为自己找到的nonce发布出去

    实际上这是不可能的。发布的区块中包含coinbase transaction(铸币交易),其收款人地址为挖到矿的矿工地址,如果要偷答案,需要修改该收款地址,而地址改变,coinbase transaction内容也发生改变,从而引发Merkle Tree根哈希值改变,从而导致原本的nonce作废。也就是说,不可能会偷答案

  8. 交易费是交易者为了自己交易可以上链而给出的小费,那么事先如何得知哪个矿工可以挖到矿?

    事先不需要知道谁会挖到矿,交易中总输入和总输出差额就是交易费。哪个矿工挖到矿,在打包交易时,可以将这些交易费收集起来作为自己获得的交易费

11、BTC-匿名性

匿名性(anonimity) 总是和隐私保护相关,即用户做的事情不想被别人知道。因为比特币系统中账户的产生不会暴露用户个人信息,用户可以产生很多对账户,然后用不同的账户做不同的事情。但这种不暴露个人信息的账户显然不是完全的匿名,可以称为假名(pseudonymity)。所以比特币系统中的匿名只是一种假的匿名,就像作家写作用笔名,网民上网交流用网名一样

1)、比特币的匿名性能提供什么程度的隐私保护

和现金相比:

和现金相比,比特币的匿名性没有现金好,现金上没有任何持有者的信息,所以很多非法交易用的都是大额现金。现金的劣势就是不便于保管和运输

和银行存款相比:

如果银行允许化名的话(以前国内银行不要求实名),比特币的匿名性没有银行好。因为比特币系统中所有有效的交易都写在区块链上,所有人都可以看到,而银行中的交易信息是受控制的,只有银行本身或者司法手段能获取到

2)、比特币系统中什么情况下可能破坏匿名性

1)地址账户之间产生关联

表面上看,每次交易可以更换公私钥对,从而每次都是新的账户,具有很强的匿名性。但实际上,这些账户在一定情况下是可以被关联起来的

例如出现下图这样的交易:

从这个交易中,可以推断地址1和地址2很可能是同一个人持有,因为买东西时候很可能一个比特币账户中的钱不是正好够用,就要用到多个账户的钱

而地址3和地址4很可能有其中之一还是这个人持有,因为一个地址是卖家的账户地址,另一个地址就是找零的地址

这些地址可能都是比特币钱包的软件自动生成的,在找零时自动生成一个新的地址,以更好的进行隐私保护

比特币生成交易的时候并没有规定找零的地址在输出中的位置,但可能可以分析出来,如下面是这几个输入输出中的比特币数量:

可以猜测地址4就是找零的地址,因为如果只要买价格是3个比特币的东西,不需要使用地址1和地址2这两个账户,只动用其中一个就可以了

现在常用的比特币钱包就那些种,搞清它们生成交易输入输出的方式,比特币系统中的大多交易匿名性也就低了很多

2)地址账户和现实身份产生关联

任何让虚拟货币和现实世界发生联系的时候都可能泄露身份,其中最明显的就是资金的转入和转出。比如很多人获得比特币的过程肯定不是挖矿挖出来的,而是买过来的,可以在交易所买(需要在交易所注册登记),也可以场外交易(两个人私下交易)

很多国家有反洗钱法,如何防范用比特币洗钱的行为?只要盯住大额度的转入和转出,即大量买入比特币和大量比特币转出为法币的情况

用比特币支付的时候也会引起隐私泄露,因为这时候也是将自己的比特币账户和自己身份关联起来了。不仅仅是向收款方泄露了自己的比特币账户,同时周围的人可以知道这个人在这个时间用比特币消费了这家店,然后知道了这家店的收款账户,再根据这个时间很容易就能在区块链上找到对应的交易记录,然后就知道这个人的比特币账户地址了

中本聪的比特币匿名性保持的最好,就是因为他一点比特币也没有花出去

3)、如何提高匿名性

比特币系统运行在应用层,其下层是P2P网络,所以可以在这两层考虑提高匿名性

网络层:

当本地节点将交易发布到比特币网络上时,其它节点如果发现一直收到此账户的交易都是来自这个或这几个ip地址,那么就可以根据ip地址来查验身份

好在虽然区块链是新生事物,但网络层的匿名性已经有了很好的解决方案,比如多路径转发

应用层:

破坏匿名性的一个原因就是同一个人的不同比特币账户会被关联起来,而在区块链上可以看到所有具体的交易及其来源,所以可以考虑将不同人的币混起来(coin mixing)

有一些专门的网站,收取一定的费用,将所有要做coin mixing的人给的币混合起来,然后经过coin mixing再取出来再做交易。在现在的比特币环境下,没有什么信誉度很高的coin mixing服务。因为做coin mixing服务的机构的账户本身也要保持匿名,如果他们卷款跑了也很难把钱追回来

没有必要特意去做coin mixing,有些应用本身带有coin mixing的性质,比如某些在线钱包以及交易所。交易所天然带有coin mixing的性质,比如将比特币存入到交易所,过一段时间卖出得到法币,然后又用法币买进比特币,那么买进的就不是当初存入的比特币了。但这样保持匿名性的前提是交易所不会泄露个人信息以及提币和买入币的信息

4)、零知识证明(zero-knowledge proof)

零知识证明是指一方(证明者)向另一方(验证者)证明一个陈述是正确的,而无需透露除该陈述是正确的之外的任何信息

例如:A想要向B证明某一账户属于A,这说明A知道该账户的私钥。但不可能通过A公布私钥的方法来证明,该账户确实属于A。因此,A可以产生一个用私钥进行的签名,B通过公钥验证签名的正确性(实际上该证明是否属于零知识证明存在争议,因为泄露了用私钥产生的签名)

同态隐藏:

零知识证明的数学基础就是同态隐藏,上图为同态隐藏的三个性质:

第一个性质说明加密函数E不会出现碰撞,反过来说明如果有E(x)=E(y),则必然有x=y

第二个性质说明加密函数不可逆,知道加密值无法反推出密码值

第三个性质最为重要,称为同态运算,说明对加密后的函数值进行某些代数运算,等价于对输入直接进行代数运算再加密

案例:Alice想要向Bob证明她知道一组数x和y使得x+y=7,同时不让Bob知道x和y的具体数值

其中证明者为Alice,验证者为Bob。最简单的证明版本如下:

  1. Alice把E(x)和E(y)的数值发给Bob(Bob知道E(x)和E(y)的数值无法反推出x和y的具体数值,利用了性质2)
  2. Bob通过收到的E(x)和E(y)计算出E(x+y)的值(利用了性质3)
  3. Bob同时计算E(7)的值,如果E(x+y)=E(7),那么验证通过,否则验证失败(如果有E(x)=E(y),则必然有x=y,利用了性质1)

缺陷:Bob可以用蛮力算法猜出x和y的值,Bob虽然通过E(x)无法知道x是多少,但是可以遍历x的各种取值,用蛮力算法一个个比较,看哪个恰好和E(x)相等

盲签:

央行发布虚拟货币:

方案一:发布的货币带有央行的签名,支付的时候把带签名的货币给出就可以了。这个方案是不行的,因为签名可以复制,无法防止双花攻击

方案二:每个数字货币需要有个编号,央行数据库中记录编号的钱有没有被花过,是在谁的手里,可以防止双花攻击。这个方案不利于匿名性,每一笔交易都必须通过央行,央行知道用户所有的交易信息。盲签可以解决这个问题

零币和零钞——专门为匿名性设计的货币:

比特币在一定程度上提供了匿名性,但无法完全消除关联性。零币和零钞就是为此问题设计的加密货币,运用密码学原理保证匿名性

这里基础币是既有的一种币,比如比特币,然后将其变成花不出去的状态换取零币。在花零币的时候,只要通过零知识证明证明花的是系统中的多少币,而不需要说明花的是哪些币

零币和零钞还不是很流行,原因是很多方面的:

  • 为了匿名性,损失了一些性能
  • 对初始化有比较严格的要求,初始化使用的随机源要能很好的销毁掉,否则会有安全漏洞
  • 需要强匿名性的用户不多(大多不做非法洗钱之类的事情)
  • 与现实世界发生交互时,仍然会破坏匿名性

12、BTC-思考

1)、哈希指针

比特币系统中很多地方使用到了哈希指针。指针保存的本地内存地址,只有在本地计算机上才有意义,如果发送给其他计算机就没有意义了。那么在区块发布的时候,哈希指针如何通过网络进行传输?

所谓的哈希指针只是一种形象的说法,实际系统中用的时候只有哈希没有指针

在这里插入图片描述

在block header中只有hash值,没有指针。那么如何查找到前一个区块的内容?

全节点一般将区块存储于一个key-value数据库中,key是区块的哈希,value是区块内容。常用的key-value数据库是LevelDB,只要掌握了最后一个区块的哈希值,就可根据哈希值一直往前找到区块链所有内容

有些节点只保存区块链部分信息,如果需要用到前面的区块,可以问其他节点要。哈希指针的性质保证了整个区块链内容是不可篡改的

2)、区块恋

有情侣一起买比特币,将私钥从中截断,每人保留其中一部分。如果未来两人依旧感情很好,就可以将钱取出;如果分手,这部分钱就会永久锁死,谁也无法取出,通过区块链的不可篡改性作为两人的爱情见证。这样做有什么问题?如此下来,N个人的账户该怎么办?

如果按照这种方法,将私钥分为N份。但这样会有一系列问题:

  1. 如果N个人中任意一个人忘记私钥,则无法将钱取出
  2. 截断私钥的做法会降低账户的安全性。比特币系统中每个账户的安全性跟所用的私钥的长度是相关的,256位的私钥用暴力破解的方法是不可行的,计算量太大。 2 256 2^{256} 2256远远大于 2 128 2^{128} 2128,之间难度差距远远不止一倍。对于多个人的共享账户,应该使用多重签名,而非截断私钥的方法
  3. 如果分手,该钱变成死钱,一直保存在UTXO集合中,对矿工不友好
3)、分布式共识

理论上来说,分布式系统中不可能达成共识。为什么比特币系统能够绕过分布式共识中的那些不可能结论?

严格来说,比特币系统并没有取得真正意义上的共识,因为取得的共识随时可能被推翻。比如出现了分叉攻击,本来以为已经达成了某个共识,分叉攻击后系统会回滚到前一个状态,从理论上说甚至可能一直回滚到创世纪块。按照分布式系统理论的要求,共识一旦达成之后就不应该再改了,从这个意义上来说比特币并没有绕过分布式共识中的那些不可能结论,因为并没有达到真正意义上的共识

理论和实际往往是有距离的。不可能结论只是针对某种特定模型的,实际中对模型稍微修改就可以将不可能变为可能

4)、比特币的稀缺性

为什么要挖矿?因为有收益,且收益大于开销。早期比特币难度低且出块奖励高,从而吸引矿工

比特币总量固定,有人认为其是一个精妙的设计。但实际上,总量固定的东西是不适合作为货币的,这也就决定了比特币并不能在未来完全颠覆现有货币体系。以太坊中就没有比特币中出块奖励定期减半的做法,此外,某些新型货币会自带通货膨胀的功能

对个人来说,通货膨胀并不是好事,因为钱不值钱了。但人类每年创造的价值,如果用总量固定的东西作为货币,则其只会越来越值钱,而这会导致拥有者不断看着其升值,其他没有的人无论如何奋斗都赶不上

5)、量子计算

会不会比特币这种建立在密码学上的加密货币,在量子计算出来后会不会变得不安全?

  1. 量子计算距离使用仍然有很长距离
  2. 量子计算若真正使用到破坏现有加密算法,对传统金融业的破坏是最大的
  3. 实际中使用的不是公钥,而是使用公钥的哈希。而哈希函数一般都是不可逆的,所以即使量子计算也无法反推私钥

比特币中用的SHA-256,无论输入多大,最终结果都为256位,必然会导致信息丢失,无法反推原本数据

加密和哈希的区别:加密可逆,哈希不可逆;加密不损失信息,哈希破坏信息

对应课程

北京大学肖臻老师《区块链技术与应用》公开课

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邋遢的流浪剑客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值