1. 链一财经首页
  2. 资讯

比特币扩容纷争:对隔离见证的思考

比特币的基础架构:区块链

科普一下比特币的区块链是什么,老手们可以直接跳过这一部分了。这里说的比特币,是2017年8月以前的比特币,后来分为了 有隔离见证的BTC 和没有隔离见证的 BCH 两条链。下面会有不少看起来很专业的东西,不过请放心,我不是专业的程序员,不会讲太深的。稍微理解一点比特币的架构和转账的方法,对理解隔离见证的骗局很有帮助。比特币链条大概是长这个样子:

比特币扩容纷争:对隔离见证的思考

上图我们可以看到几个区块(Block),可以看到每个区块都有两个部分:一部分是虚线画出来的 Prev.block 指向上一个区块,这部分我们叫它“区块头”,另外一部分是“区块主体” Transaction,即这个区块里交易的信息。由于每个区块头都指向上一个区块的头,所以这个系统我们叫他区块链。再详细点看这个区块头:

比特币扩容纷争:对隔离见证的思考

上图我们可以看到3个区块(Block),可以看到每个区块头里都有4个信息。其中 Nonce 就是矿机去搜寻的数,这个数很难找所以要用很快的矿机烧很多电费,谁先找来一个 Nonce,能让这4个信息合起来的 Hash 结果符合一定的条件,谁就可以发布这个区块,并拿区块奖励12.5个币。Prev-Hash 是上一个区块的这4个信息合起来的Hash 结果,Timestamp 是目前的时间,有这两个的限制,矿工至少要收到上一个区块的区块头,才能开始挖下一个区块。Tx_Root 是这个区块的主体里所有交易的Merkle Root,如果有任何一个交易被改变,这个 Tx_Root 就会有变化。 如此,比特币的区块形成了一条不能被更改的链:加入这个 Block11里面的 Tx1被改变了,那他上面的 Hash1就会变,Tx_Root 也就变了,这样 Block11的4个信息合起来的 Hash 结果会不一样,就和 Block12的 Prev_Hash 断开了,Block12就无效,以此类推。

支付脚本

区块链里的交易,大概可以理解为是 “A 地址转给 B 地址 xx 个币”,“B 地址转给 C 地址 xx 个币”这样的信息。如果 C地址收到了 xx 个币,但没有往外转,那这就会在 UTXO 数据库里记一条:“C 地址还有 xx 币没花掉”。假如 C 地址是普通的1打头的比特币地址,要花掉这笔钱,就需要用到一个脚本,这个脚本是“B 地址转给 C 地址 xx 个币”时规定的,定了这笔钱要怎么才能被C 地址花掉。一般这个脚本是这样的两部分

scriptPubKey部分: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

scriptSig部分: <sig> <pubKey>

不会编程的朋友请不要害怕,不难看懂的。scriptPubKey部分有几个“操作码”,是 OP 打头的,表示几种操作。<pubKeyHash>就是比特币地址的中间部分,不带开头的版本号1和末尾的几位校验码,这部分是对公钥进行 Hash 的结果。scriptSig部分要由想转账的这个人提供,公钥<pubKey>,和用私钥对这笔交易的签名<sig>。由私钥可以推导出公钥,公钥可以推导出比特币的地址,这两个步骤都不能反推(在当今科技下)。如果一个人可以展示私钥对这笔交易的签名,又可以提供这个地址的公钥,那我们就相信这笔转账是他授权的,别人伪造不了。矿池收到了提供的交易,和交易的签名,要怎么验证呢?就是运行一遍上面的脚本,看看结果是不是“True”。如果结果是 True 那就算通过了。首先要把scriptSig里的东西“堆”起来,形成一个“堆栈”:

<pubKey>

<sig>

然后,就一个一个地执行scriptPubKey部分。先是一个 OP_DUP,这个是复制操作,这些操作都是对着堆栈的顶部操作。所以复制操作后堆栈变成了:

<pubKey>

<pubKey>

<sig>

然后是一个 OP_HASH160,是 Hash160算法的操作,把堆栈顶部的<pubKey>变成了<pubKey Hash1>:

<pubKeyHash1>

<pubKey>

<sig>

然后是<pubKeyHash>,把这个推进堆栈:

<pubKeyHash>

<pubKeyHash1>

<pubKey>

<sig>

然后是OP_EQUALVERIFY,是检查是否相等的操作,对着堆栈顶部的两个元素进行。如果提供的<pubKey>是没错的话,应该是一样的,操作后堆栈变成了:

<pubKey>

<sig>

最后一个操作码是OP_CHECKSIG,检查这个签名<sig>和公钥<pubKey>是不是对的上,如果没问题,堆栈就清空了。任何一步出问题都会造成脚本报错,如果没出错,那脚本结果是 True,表示通过。

脚本能用的操作码还有很多,可以进行 if,else,add,sub,drop,swap等等等等。比如,B 地址给 C 地址转账的时候,在刚才的脚本开头,加上一个<expiry time>和一个操作码 OP_CHECKLOCKTIMEVERIFY,就可以制造一笔冻结款,C 地址里的这笔钱要经过特定时间后才能花,在到期之前OP_CHECKLOCKTIMEVERIFY会让脚本验证失败。

据“2009年就开始参与比特币开发”的 Craig Wright 的说法,如果有足够的操作码,比特币系统也是图灵完备的,也可以运行ETH 那样的智能合约。但是,许多操作码在2013年被 Core 禁用了(因为 Core 开发者看不懂那些操作码有什么用),对脚本的限制也更多。BCH 在2018年的开发路线图里就包含了修复操作码设计的部分。

如果,B 地址给 C 地址转账的时候,把脚本搞成这样:

scriptPubKey部分: 留空

scriptSig部分: OP_TRUE

那这个脚本就是永远都可以通过的,不需要提供任何信息。这笔钱谁来转出,怎么转出都是有效的,我们称这钱现在是 anyone-can-spend。这笔钱等于就是给了矿池,因为矿池最终决定谁的交易可以被打包进块。如果有人把自己的钱转入这么一个 anyone-can-spend地址,矿池肯定会把这笔钱打给自己。

这个anyone-can-spend的脚本,就是隔离见证(Segwit)的基础。用这个脚本,转账的时候就不用在区块里提供签名了,签名被“隔离”到了区块链以外,故名“隔离见证”。虽然签名挪了地方,但是转账的话签名还是要给的,不然岂不是乱转账了。其实,用户该发送的信息没有少,矿池要验证的信息也没有少,区别只是在区块链里存的信息少了。由于区块被设置了1MB 上限,并且已经堵满了,如果交易在区块里占的空间小一点,就能多挤几个交易进这个1MB 块。隔离见证技术被吹嘘有1.7 x 的扩容效果,如果所有人的交易都用这种 anyone-can-spend的格式的话。现在问题来了,这样把签名信息挪出区块链,有什么好处?为什么不直接把1MB 上限放宽到2MB 呢?

软硬分叉之争

如上的疑问,就是扩容软硬分叉之争。因为 Segwit 是一个所谓的软分叉,而提高区块大小会是一个硬分叉。在之前的文章里已经说过,其实这里面软硬分叉之争是个表象,本质上是路线之争:普及后,比特币是流通的币,还是流通币的结算层;是流通的币更去中心,还是结算层更去中心。软硬分叉其实都只是技术手段而已,真正最后的结果还是被人所控制的。

涉及到“共识层”的修改,就会形成“分叉”。共识的运行其实是两个半层面,一层是在有算力的节点(矿池),第二层是没有算力的全节点,还有简单支付验证的轻钱包 SPV 我们算半层。软分叉的特点是“旧版软件还能认新共识”。硬分叉是“旧版软件不认可新版软件”。我们用下面一张图来看软硬分叉的情况。

比特币扩容纷争:对隔离见证的思考

在 Block8区块之后,系统从 V1软分叉升级到 V2,这时:

算力层:

运行 V2的矿工(大多数算力)认为最长的有效链是上面的这一条。

运行 V1的矿工(少量未升级算力)也认为最长的有效链是上面的这一条,会放弃掉自己的 Block9(V1)形成孤块,因为它不是最长了。而 V1矿工挖出的旧版本块不会被 V2矿工承认,这样,V1矿工不升级,就面临着不被承认的境况,矿机白白浪费电。

全节点层:

运行 V1和V2的全节点(无算力)都认为最长的有效链是上面的这一条。V1节点因为没有矿机而无经济损失。

SPV 层:

运行V1和V2的 SPV钱包都认为最长的有效链是上面的这一条。

总结来看,软分叉时,只要挖矿的节点需要升。如果不升级,会有经济损失。

对比一下,系统从 V1硬分叉升级到 V2,这时:

算力层:

运行 V2的矿工(大多数算力)认为最长的有效链是上面的这一条。

运行 V1的矿工(少量未升级算力)认为最长的有效链是下面的这一条,上面一条虽然长但是无效。这样,V1矿工不升级,就会和 V2形成两条并行的链。

全节点层:

运行 V2的节点(无算力)认为最长的有效链是上面的这一条。

运行 V1的节点(无算力)认为最长的有效链是下面的这一条,上面一条虽然长但是无效。

SPV 层:

如果这个硬分叉是扩容1M到2M 的话,由于 SPV 钱包不检查容量限制,所以不会因为容量而判某链无效。运行V1和V2的 SPV钱包都认为最长的有效链是上面的这一条。如果这个硬分叉修改了挖矿算法或者难度调节算法,那么 SPV 节点也会依新旧版本各自认各自的链。

总结来看,硬分叉时,不只要挖矿的节点需要升级,不挖矿的节点也要升级,SPV看情况, 可能可以不用升级。如果一部分算力不升级,会被拆成互相不能转账的两种币,像现在的 BTC 和 BCH 一样。

这么看,软分叉是不是比硬分叉来得安全呢?如果担心有人因为不知道大家升级,或忘记及时升级的话,看起来软分叉可以预防比特币被莫名其妙分为两个币。但这种情况是不存在的好么?现在算力都在几个矿池手里,只要提前几个星期通知一下大家做好准备,完全不会出现“忘记升级”这种事。能出现“忘记升级”的只能是普通用户,普通没有算力的用户,对系统的运行也没有影响。BCH 上的 DAA 硬分叉(把难度调节算法更改为逐块调整)已经非常好地展示了这样的硬分叉,对普通用户的使用并不构成障碍。我们平时使用其他软件,也经常面临着不升级一下登陆不进去这样的情况,并不是什么要命的事情。Core 开发组一直在妖魔化硬分叉,表示硬分叉会造成比特币分裂为两种币,影响市场稳定。其实有分歧造成的硬分叉拦不住(BCH 分离出来),没分歧的硬分叉升级没危险(BCH 难度算法调整),无视路线分歧硬说软分叉安全是没有理由的。

软硬分叉之争的结局:中间派的失败

在大家对硬分叉的安全性有质疑的时候,中间派试图用“合并分叉”这样的手段来调解。大致手法就是先用大家都认可安全的软分叉从 V1升级到 V1.5,然后在 V1.5里预埋硬分叉到 V2 的代码。这样,如果是有算力“忘记升级”,他的 V1会在升级到 V1.5的时候被孤立,但不会立刻形成2种币。等到 V1.5到 V2进行硬分叉升级的时候,由于是预埋的代码,自动运行的,不会“忘记”。没有鄙视程序员的意思,这是一种典型的“程序员思维”。软件是死的,人是活的。如果人要搞事情,用代码是限制不住的。

中间派的最后运行的方案是 Segwit2x 方案,合并分叉 Segwit 和2M 这两个升级,前一个是软分叉,后一个是硬分叉。这个方案在纽约得到了超过83%的算力的支持,纽约会议之后,中国矿业又内部约定:大家都运行 Segwit2x 的软件,这个软件预埋了代码,在 Segwit 激活后90天,自动激活2M 的升级。问题就来了,你如何知道别人运行的软件和你是一样的?除非是黑进矿池的服务器去,否则从外部完全不能判断别人会不会在3个月后进行2M 分叉。虽然代码是写了,但别人可以运行别的版本的软件,可以把那几行删掉,改掉,外人无从得知。反扩容派是倾向于要 Segwit而不要2M,中间派是为了要2M 愿意妥协 Segwit。当 Segwit 激活 以后,中间派没法靠这2行代码来逼反扩容派进行2M 升级,分裂成2种币的结局依然是难免的。最后结果大家也看到了,中间派认怂取消掉了2M 硬分叉的计划。

从2016以来,为了不让比特币分成两种币,大家花了那么多的时间在开会谈判上,现在才明白过来:如果路线有分歧,没有技术手段可以防止比特币分成两种币,也没有技术手段可以督促其他方面参与或不参与一个硬分叉。

隔离见证软分叉(Segwit)的危险

前面我们提到,隔离见证是一个软分叉,旧版依然可以兼容,在升级的时候可以预防“因为忘记升级而乱套”。这可以算一个非常模糊的优点,具体有没有用是很值得怀疑的。相比之下,这软分叉的缺点就要严重得多。还是画个图看一下:

比特币扩容纷争:对隔离见证的思考

从 Block7开始,系统加入了 Segwit 的功能。前面介绍脚本的段落里已经介绍过这种 anyone-can-spend 的地址,假如 Block7里一个 Segwit 交易,把币发到了一个任何人都可以花的地址 C 里面,签名放在了外面。假设 C 地址的拥有者,打算在 Block8把钱花出去,发送币给地址 D,诚实的矿工会验证C用户的签名,安全性基本和以前是一样的。这里,读者可以可以看到,“这笔钱是不是 C 的”这个问题,要靠 Block7下面挂着的那个小块 sig来回答。如果仅看Block7的信息,得出的结论会是“这笔钱是无主的随便捡”。

众所周知这个 Segwit 功能是一个软分叉,也就是说旧版软件依然会承认 Segwit 版发出来的块,不用升级。旧版的软件根本就看不到 这个小块 sig。旧版钱包软件(全节点或 SPV 钱包)看到这笔钱就是无主的,任何人都可以花的。好在算力一层是必须全部升级的,旧版钱包软件如果提出要转走这笔钱会被所有算力拒绝,只能眼睁睁地看着钱在那里无主地放着。旧版钱包不能正确地获得交易信息,仅仅是验证机制被绕过了,无法发现交易模型已经改变了。前面我们介绍过,区块链的一个特点就是,后一个区块依赖前一个区块的区块头里的信息,如果修改一笔交易,区块头会变化,会造成整个链条的失效。可是现在 Segwit 的“外挂见证块”并不在这个链条里面,修改 sig 里面的内容是不会使链条失效的。如果我有算力,但不是 C 地址的拥有者,我无法提供地址 C 的签名,但我把地址 C 的钱转给自己,这个块一定会被其他矿池拒绝掉,因为他们验证了 sig 发现我并没有资格动这笔钱。可是旧版钱包(全节点或 SPV 钱包),和新版的 SPV 钱包(不验证和自己不相关的交易,只接收区块头),都不会发现,他们只会跟随最长的块,sig 的内容不影响有效与否。

因此,Segwit 带来了一种新型的51%攻击。这种攻击我在之前的一篇回答里介绍过:

一般币的51%攻击:我在高度12345上发布一个交易,从 A 地址到 B 地址发送1000比特币。同时我用自己的压倒性的算力,重新挖出一条12344-12345-12346的链,不包含刚才的交易。这样 B 一开始以为我付款了,后来我付款的那个块被孤立了,最终成型的最长链里不包含我的支付。这也是为什么各大交易所都要求3个确认,6个确认,就是防止出现你发送币给交易所的交易被孤立。一般认为6个确认后就几乎不会出问题了。小额支付(几万美金以内)经常1确认甚至0确认(块不满的时候)也可以,因为对于小额交易你没有经济动力去攻击。小额没赚头,大额肯定会要求多个块的确认很难做到,也没赚头,并且攻击窗口就是交易发布后的那一两个小时,过去了就没法攻击了。所以至今比特币没有发生过真正意义上的 51%攻击。
SW 币的51%攻击:Segwit交易带来了“AnyOneCanSpend”地址,它实质上是一个空白的交易签名。这种交易的签名被挪移到了附加的见证块里,因此这个技术叫做“隔离见证”。当然,虽然这个交易的签名不在这里,矿池肯定还是会去附加的见证块里找出来核对验证。在大家都核对验证的情况下,安全性和以前是一样的。控制算力超过50%的矿霸矿池,可以直接放弃附加见证块的核对,并把AnyOneCanSpend地址里的钱转给自己,然后孤立那些去核对见证块的矿池。由于 Segwit 是软分叉升级,原来的那些没有 Segwit 功能的 SPV 钱包和全节点钱包还是可以用的,这些钱包也没有核对附加见证块的能力,这时候这些钱包都会认为矿霸的链是合法的最长链。和一般币的51%攻击巨大的区别就是:一般币的51%攻击只能退回自己的一笔支付,而SW 币的51%可以花掉别人账上的钱,而且这钱的数字是从 SW 激活起慢慢积累变多的。SW 运行的越久,SW 交易运用的越多,这笔钱的数量也就越大,有动力攻击的算力也就越容易找。参考资料:Risk of SegWit – Mining Cartels – nChain

软分叉可以在不惊动普通用户的情况下偷偷进行,上 Segwit 功能是软分叉,关闭 Segwit 功能也是软分叉,也可以偷偷地进行。一旦使用了 Segwit 功能,把币放在了AnyOneCanSpend地址里,就只能信任51%的算力不会去进行关闭 Segwit 功能的软分叉。如果不使用 Segwit 功能,把币放在“经典”的1字头地址里面,任何软分叉都不能让你失去这币,除非有绝大部分算力针对你的存币地址发动一个硬分叉,才能把这个地址里面的钱转给别的地址。显然这种硬分叉是无法成为主流的,估计中本聪也得不到这种待遇。放在1字头地址里的币就是你的币,只有你可以转走卖掉,别人都不行。放在 Segwit 地址里的币,就要看矿业有没有诚信了,如果超过51%的算力发动取消 Segwit 的软分叉,剩下的49%里必须有算力主动发起硬分叉才能甩脱51%算力的最长链,保住你的币。可是 目前 Segwit 链的座右铭就是“We don’t hard-fork”,是不是有点尴尬?

有人会说,51%算力发起关闭 Segwit 功能的软分叉是不可能做到的事情。这点我同意,但是也许你不需要51%算力来做到这事。如果我是捣乱矿池,占5%算力,我挖出一个块以后,签名 部分拖延1分钟再发出去,其他矿池敢不敢再这1分钟里以我这个块为基础挖下一个块?如果挖,一分钟以后收到 签名 的内容可能会发现这个块里有非法的交易,这一分钟就白挖了。如果不挖,一分钟以后 签名 内容是正常的,就浪费了一分钟。我只要用5%的算力捣乱,每天出几个块,就足以逼很多矿池修改自己的软件设定,在收到签名前就开始挖矿。捣乱矿池可以把 签名 渐渐拖更久,比如10分钟后才发,很少的算力就可以把严格验证 签名搞成成本挺高的事情。不验证签名的矿工收益更高,这在 Segwit 以前的比特币上是不可能发生的事情,如今可能了。如果有30%的算力不验证附加的签名块,那我只要21%的算力就可以发动上述的 Segwit 独有的51%攻击了。

隔离见证软分叉(Segwit)无法扩容

Core的开发者一直在宣传,说 Segwit 可以带来1.3x,后来又说1.7x,又四舍五入到2x 的扩容效果。从交易数来看,2017年8月中旬激活 Segwit 以来,每个块的交易数勉强突破了之前的高点2250,连1.1x 的扩容效果也没有。每个块2000+笔的交易能力是不够的,必须尽快改进,这一点上各派都没有异议。Core 的开发者现在已经不提“ Segwit 有立竿见影的扩容效果”这话了,着重宣传闪电网络。“小额交易走闪电几乎零手续费,大额结算上主链五十美金一笔”,这已经是 Core 支持者的信仰宣言。

第二层交易网络

我们来简单对比一下BCH 的“传统”单层模型,和闪电网络的第二层模型。

手续费方面:

以50美金一笔手续费的大额结算来计算(50美金就是今天的手续费水平),闪电网络开闭通道各需要一次交易,就是100美金的成本(闪电节点的成本没有计入)。如果平均每个通道结算时已经发生过1000笔交易,那每个交易的成本为10美分,勉强还属于比较低的手续费水平。要什么样的通道才能1000笔结算一次呢?以我的想象力,我只能想到这个是支付宝,银行或者地下钱庄的模型,把我的币充值锁进去慢慢花。交易所等机构之间大概更有用一些,对于普通用户其实是毫无作用。

按照每个块开闭2000次闪电网络通道(1M 的极限),每个通道1000笔交易来算,BCH 的模型里,1000000笔交易差不多也就是500MB 区块。nChain 已经和 BitcoinUnlimited 联合测试过1GB 区块,并没有很科幻。

安全方面:

Segwit 的安全性问题已经是一个很好的反例了。区块链,或者说a chain of digital signatures,是中本聪的杰作,也是比特币和支付宝,银行,信用卡的根本区别。在比特币,现在的 BCH 里,没有私钥谁也没法挪动你的钱,你必须有私钥才能把钱挪动到指定的地方。闪电网络虽然已经宣称进行过多轮测试,但“怎么保证通道内的交易公正不被修改”这个问题,依然没有清楚的回答。如果有哪位朋友有好的资料能够提供,不胜感激。从我目前的理解是,闪电通道内基本还是充值卡的模型,外加了通过多次交换签名来让双方对余额有共识,但如果双方有意或无意对余额有分歧,需要由 闪电节点来裁决。Segwit 的问题又出现了:有人可以在没有你的数字签名的情况下挪动你的钱。

安全方面,这一篇文章值得看看:https://news.bitcoin.com/lightning-network-centralization-leads-economic-censorship/

技术方面:

刚刚其实都是我瞎编的,目前闪电网络完全没有如此大流量的公开测试,考虑到闪电通道内多次反复交换签名的设计,同等硬件瓶颈下闪电网络的交易容量堪忧。

结语

我在敲这篇文章的时候,BTC 正在疯涨,BCH 和其他所有币都被“抽血”而下跌。同时,BTC 拥堵了17万笔交易没有确认,单笔手续费大约50美金。Steam 宣布放弃比特币支付渠道,因为手续费太贵了没法用了。Bitpay 宣布要投资支持比特币以外的各种币,也是因为手续费太高。

市场在短时间内是不理智的,这个混乱时间点上暴涨暴跌都不稀奇。如果说再过十年,市场上主流的是哪种币?一个挪动困难,安全性堪忧的 BTC 真能保值十年吗?如今 BTC 确实是有保值增值的功效,在过去几年里任何一个时间点,甚至过去几个月的任何一个时间点买入,到今天都是大赚。暴涨总是有头的,如果BTC 不再暴涨,失去了支付渠道和商家支持的 BTC 就没有上新闻的能力了,在投资者的圈子里,不再暴涨的BTC也失去了增值保值的能力。如今加密货币都是新事物,严格意义上来说BTC 也还没有进入公众视野,新闻里的 BTC 只有暴涨,没有应用。这两年新入场投资加密货币的,都很少有只买 BTC 的了,都是 ETH等币搭配着投资,在币圈 BTC 都不是那么大众化,终究是会淡出公众视野,变得越来越小众的。十年后能成为主流的币,一定是接下来几年能第一个真正进入公共视野的币,我猜这个币是BCH。

欢迎大家在评论里和我讨论!

根据国家《关于防范代币发行融资风险的公告》,大家应警惕代币发行融资与交易的风险隐患。

本文来自LIANYI转载,不代表链一财经立场,转载请联系原作者。

发表评论

登录后才能评论

联系我们

微信:kkyves

邮件:kefu@lianyi.com

时间:7x24,节假日bu休息

QR code