签名能看见什么
一笔比特币支付的条件是怎么定义的
A book in the spirit of Feynman's QED.
v0.1 · 一本费曼式的薄思想书 · 配套可交互 playground
与可运行代码(见本仓 sighash-playground/)
前言 · 一个承诺
这不是一本教你写代码的书。
读完它,你不会多记住一个字节偏移,也不会多背一条 BIP 编号。但你会彻底看懂一句话——一句短到可以写在餐巾纸上、却撑着整个比特币合约世界的话:
一笔比特币支付的条件,就是每个签名能看见、能承诺的东西之和。
费曼写过一本薄薄的小书,叫《QED:光和物质的奇异理论》。他用四场讲座、几乎一个公式都不写,讲清了光怎么和物质打交道——靠的是一个反复出现的场景(光打在一片玻璃上)和一个你能拿铅笔亲手玩的小玩具(一根会转的小指针)。读完那本书,你不会算量子电动力学,但你懂了。
我想用同样的方式,带你从一顿饭走到一堵墙。
中间会出现一些名字——sighash、covenant、CSFS、CAT、CTV、APO。别紧张。我保证:在你需要它们之前,我不会让它们出现;在它们出现的时候,我会先用饭桌上的话把它们讲清楚。所有真正硌牙的东西——字节偏移、tagged hash、preimage 字段表——我都流放到了书末的附录里。正文只用人话。
我们开始吧。先坐下来吃顿饭。
第一章 · 一顿饭
小王和小李一起吃了顿饭。
吃完,该买单了。一共三百块。怎么付?也许小王出两百、小李出一百;也许各付一半;也许小王今天发了工资,全包了。不管怎么分,有一件事是确定的:这顿饭的"支付条件"——谁出多少、钱去哪——是被某种东西定下来的。
是被什么定下来的?
你可能会说:被规则定的,被账单定的。但你仔细想想,账单只写了"一共三百",它没规定谁掏钱。真正让这笔钱动起来的,是小王和小李各自点头的那一刻——小王说"这两百我认",小李说"这一百我认"。两个人都点头,钱才付得出去。少一个人点头,这顿饭就买不成单。
比特币里的一笔交易,几乎一模一样。
一笔交易可以有好几个输入(input)——你可以把每个输入想成饭桌上的一个人,他带来一笔钱。交易要成立,每一个输入都得"签字点头"。不是某个中心规则规定这笔钱怎么花,不是矿工说了算,也不是谁的服务器说了算——是所有签名共同同意的那个东西,定义了这笔支付的条件。一个输入拒绝签字,整笔交易就作废,就像饭桌上有人不肯掏钱,这单就买不成。
你再低头看那张账单。账单上写的,是一道一道菜——什么菜、多少钱、钱进谁口袋。它写的是"🍜 这道,八块,给餐厅"。
可你发现没有:账单上没有哪一行写"这八块里,小王出了五块、小李出了三块"。 餐厅不关心这个,也看不见这个。对餐厅来说,账单的粒度就到"这道菜八块"为止;再往细——谁在这道菜里掏了多少——那是你们俩桌子底下的事,账单上没这一栏。
比特币的交易,分毫不差。账单上那些"菜",叫输出,每条只写"多少钱、给谁"。每个人带来的钱,叫输入;链上会记得小王那枚币是五块、小李那枚是三块(每人带了多少,是记下来的)——但它永远不记"小王这五块里,几块去了🍜、几块找零回了自己口袋"。钱一进这笔交易,就像倒进同一个碗:进来的总数等于出去的总数(减掉一点小费),可碗里这块钱原来是谁的、流去了哪道菜——这笔账,链上压根没有。
把这件事记住。这是全书里你第一次撞见一样东西,链根本看不见——不是它不想看,是它的账细不到那个地步。这条看不见的边际,后面还会回来两次:一次变成第八章那堵墙;还有一次……是另一个故事了——去问问研究隐私的人,为什么钱能在碗里藏住自己的来路。
这件事听起来简单,但它把一个很深的问题摆到了桌面上:
如果"支付的条件"是由签名共同同意的,那每个签名到底同意了什么?
它同意了"我出两百"吗?它同意了"这顿饭一共三百"吗?它同意了"小李必须也掏钱"吗?它在签字的那一刻,到底看见了多少?
这就是整本书要回答的问题。我们不会去问"协议规定了什么",我们要问的是一件更朴素、也更深的事:每一个签名,看见了什么;它能替你承诺什么;它看不见的,又是什么。
把这个问题记在心里。下一章,我们就坐下来,看看小王在签字之前,到底低头看了账单的哪几行。
第二章 · 账单看得多清
签字之前,你会多仔细地看账单?
我见过三种人。
第一种人,通读全单才肯签。每一道菜、每一个数字、总额是多少、钱最后进谁的口袋,他全看一遍,看准了才签字。他的态度是:"这单子我从头到尾认下来了,改动任何一处,我这一签就作废。"
第二种人,只看自己那一行。"我点的这道菜多少钱?行,这部分我认,别的我不管。"
第三种人最潇洒:他签字的时候根本不在乎别人。"我出我这份,至于待会儿谁又凑过来加了个菜、单子上多了一个人——跟我无关,我那份照付。"
比特币给每个签名都准备了这样一个"看多仔细"的旋钮。它的名字叫 sighash——sig 是签名,hash 是它实际签下去的那串摘要。这个旋钮决定了:你这一签,到底覆盖了账单的哪些部分。 旋钮主要有这么几档:
- 看全单(叫
SIGHASH_ALL):所有的去向(输出)都被你这一签钉死。改一个数字,签名就废。第一种人。 - 不看去向(叫
SIGHASH_NONE):你签了,但钱去哪你没管,别人可以随便改。 - 只看自己那行(叫
SIGHASH_SINGLE):你只对自己对应的那一笔去向负责。第二种人。 - 不管别人上不上桌(叫
ANYONECANPAY):别人往这笔交易里加不加输入,跟你的签名无关。第三种人。
到这里,我想给你一个玩具——这本书里你能一直拿在手上玩的那个东西。
想象一张长纸条。纸条上从左到右印着一格一格的标签:版本号、有哪些输入、钱去哪些输出、锁定时间……这张纸条,就是你签字时真正按手印的那个东西(它有个学名叫 sighash preimage,但我们就叫它"纸带")。
而那个"看多仔细"的旋钮,干的事情特别直观:它决定你按手印的时候,盖住纸带的哪几格、露出哪几格。
- 看全单,就是整条纸带都露着,你的手印盖满全程。
- 只看自己那行,就是只露出"你那一笔去向"那一格,其余盖住。
- 不管别人上桌,就是把"有哪些输入"那几格盖住——所以别人后加输入,你的手印照样有效。
这就是 sighash 的全部秘密:签名不是签在整笔交易上的,是签在你选择露出来的那几格纸带上的。 你露出多少,你就承诺多少;你盖住的,你就管不着。
现在,讲一个真实的代价。
比特币历史上,"只看自己那行"这一档出过一个有名的 bug。如果你选了这一档,却没有和你对应的那一笔去向(你那一格是空的),早期的实现不会报错,而是默默地让你在一串固定的、人人都知道的常数上按了手印。一个人人都知道的手印,意味着什么?意味着任何人都能复制它。少露出一格、少看清一处,攻击面就开了一道缝。
把这件事记牢,因为它是这本书第一次、也不会是最后一次让你摸到那条主线:
看得见,你才管得着;看不见的地方,就是风险和约束的来处。
下一章,我们要往饭桌上请来第三个角色——它不是小王,不是小李,而是给钱的那个人,和他附在钱上的一张纸条。
第三章 · 爸爸的纸条
小王桌上的那两百块,是从哪来的?
不是凭空变出来的。是他爸前几天给的。而他爸给钱的时候,附了一句话——甚至是附了一张纸条:"这钱,只能花在吃饭上,不许拿去打游戏。"
于是小王手里这笔钱,从一进口袋起,就背着一个约束。他签字付饭钱没问题(符合纸条),但他要是想拿这两百去干别的,纸条不答应。
比特币里有一个一模一样的东西,名字叫 covenant——盟约,或者你就理解成"钱背着的那张纸条"。
要看懂它,得先知道比特币的钱长什么样。你钱包里的"余额",其实是一笔一笔还没花掉的钱(每一笔叫一个 UTXO)。而每一笔这样的钱,都不是光秃秃的数字——它附着一段小小的规矩,规定"想花我,你得满足什么条件"。最常见的规矩是"你得证明你有那把私钥"。但规矩可以写得更细。
细到什么程度?细到可以规定这笔钱下一步只能怎么花。
这就是关键的转折。一张普通的纸条只说"你得有钥匙才能花";而一张 covenant 纸条说的是:"你可以花,但你花出去的钱,必须去某个指定的地方。" 注意,这个约束不是签字的人临时定的——是钱本身背着来的,是上一手给钱的人写死的。小王没法撕掉他爸的纸条,正如这笔比特币没法摆脱上一手刻在它身上的规矩。
到这一章,桌上其实已经有了两种不同的力量,它们合起来定义了一笔支付的条件:
- 一种是sighash——上一章讲的,签名看清账单到什么程度。这是"看"的力量。
- 一种是covenant——这一章讲的,钱背着什么前置约束。这是"绑"的力量。
一笔支付到底能不能成、长什么样,就是这两种力量合成出来的结果。一个管你看见多少,一个管你被绑多死。
这本书剩下的篇幅,几乎都在做一件事:把这两种力量推到极限,看它们能合成出多复杂的约束——以及,它们合不出来的,是什么。
下一章,我们先把"绑"的力量推一把。因为爸爸的纸条,其实比你想的还要狠——它不止管这一顿饭。
第四章 · 纸条管到下一手
上一章那张纸条,还是太温柔了。它只管到小王这一顿饭。
真正狠的爸爸是这么写的:"这钱给餐厅可以——但餐厅老板收了之后,也只能拿去买食材,不许挪作他用。" 你看出区别了吗?这张纸条不止约束小王,它跟着钱一路传下去,约束下一手、下下一手。钱流到哪,纸条的规矩就贴到哪。
这个叫递归 covenant(recursive covenant)——约束会自我复制,沿着钱一手一手传递。比特币里很多最有意思的构造,比如金库(vault,一种"就算私钥被偷也偷不走钱"的保险柜结构),靠的就是这个。
那么,技术上怎么让一张纸条"管到下一手"?
这里要请出一个新角色,叫 CTV(全名 OP_CHECKTEMPLATEVERIFY,但记名字没用,记它干什么的)。CTV 干的事情,用饭桌话说就是:它把"这笔钱下一步必须长成什么样"事先拍下一张照片,钉死在纸条上。 谁来花这笔钱,都得让交易长得和照片一模一样——同样的去向、同样的结构——否则花不动。
要做成递归,只要在那张照片里再要求下一手也戴上同样的纸条就行。于是约束就自己复制下去了:餐厅老板那笔钱的照片里,又写着"你的下一手也只能买食材"……一环扣一环。
现在,把你手上那根纸带拿出来玩一下。
CTV 是怎么"拍照片"的?它不是真去拍照,它做的事,是把纸带上"钱去哪些输出"那几格单独拓印下来,揉成一个独一无二的手印(一段 hash),然后把这个手印钉死在花钱的规矩里。以后谁想花这笔钱,必须当场拿出"钱去哪"那几格,拓印一遍,比对手印——对得上才放行,对不上免谈。
请你特别记住一件小事,因为下一章它会回来:在这整个过程里,我们只用到了"拓印 + 比对手印",一次签名都没动。 CTV 强制钱的去向,靠的是 hash 对不对得上,不是靠谁签了字。
这一章,"绑"的力量已经推到了相当狠的地步——钱可以被规定下一步去哪,甚至能把这个规定一路传下去。
但是。
我们到现在为止,所有的力量都用在一个人自己身上:小王看自己的账单(sighash),小王背自己爸的纸条(covenant),小王的钱去哪被钉死(CTV)。
桌上还坐着小李呢。
小王,能看见小李的那张纸条吗?
这一问,是整本书的转折。下一章见。
第五章 · 你看得见邻座的纸条吗
小王心里其实有个嘀咕。
小李掏出来凑份子的那一百块——它干净吗? 是小李他爸正经给的、也好好背着一张纸条的钱,还是小李从哪儿顺来的、来路不明的黑钱?
在真实的饭桌上,这事好办。小王扭头问一句:"哎,你这钱哪来的,给我看看你那张纸条?" 小李把纸条递过来,小王看一眼,心里就有数了。两个人当面,能互相看见对方的约束。
可是在比特币里——小王看不见。
这是这本书里你必须停下来、盯着看三秒钟的一句话。比特币那套执行规矩有一个深深的、几乎反直觉的限制:
一个输入,看不见同一笔交易里别的输入。
小王这个输入,在签字、在验证自己那套规矩的时候,没有任何办法去读小李那个输入花的是哪一笔钱、背着什么纸条、受什么规矩管。每个人只能低头看自己爸的纸条,抬起头来,只看得见桌子中央那张共同的账单(所有的输出,钱总共去了哪)——但他看不见邻座手里攥着的那张纸条。
这个能力——"一个输入能不能看见、能不能查验另一个输入"——有个名字,叫跨输入内省(cross-input introspection)。而比特币,原生就没有这个能力。
请你体会一下这个裂缝有多大。
前面四章,我们把"看"和"绑"的力量推得挺远了:账单看得清(sighash),钱背着纸条(covenant),去向被钉死、还能一路传下去(CTV)。但你回头看会发现,这些力量全都用在"输出侧"和"自己身上"——管的是"钱往哪去"、"我自己背什么约束"。一旦问题变成"我能不能查验坐我旁边那个输入",比特币就两手一摊:做不到。
所以,桌上的局面其实是这样的:
- 协作,在输出侧已经解决了。"我俩的钱合起来必须 ≥ 这顿饭、必须只付给这家餐厅"——这种共同的去向约束,前面那些力量锁得住。
- 互相查验,在输入侧还是个敞着的口子。"我想确认小李也受他爸管、不是拿黑钱来凑"——这种邻座之间的核对,比特币原生做不到。
这个敞着的口子,就是接下来三章的全部战场。
下一章,我们想个歪招:既然小王不能直接偷看小李的纸条,那能不能……让小李自己把纸条念出来,小王亲手抄一遍、亲自核对?
第六章 · 手抄纸条
小王不能直接看小李的纸条。好。那我们换个法子。
让小李把纸条上的每一个字,一字一句念出来,摊在桌面上。然后小王自己拿张纸,照着抄一遍,再亲手核对:这张纸条上的签名,对不对得上?
绕是绕了点。但你品一品——这一招居然真的能核。小王没有"看见"小李纸条的超能力,可只要小李肯把内容摆出来,小王就能自己重建一遍,自己验。
这一章,就是讲怎么在比特币里使出这一招。它需要两件工具。
第一件叫 CAT——它的本事简单到好笑:把两截字节拼成一截。 给你两块东西,它给你粘成一块。听起来无聊,但"把小李念出来的字一截一截拼回成完整的纸条",靠的就是它。
第二件叫 CSFS(OP_CHECKSIGFROMSTACK)。要讲清它,得先说它的老前辈 OP_CHECKSIG。平时验签名,用的是 OP_CHECKSIG,它是个黑箱:你把签名递进去,它自己在内部按规矩拼出那张该签的纸带、自己验,你插不上手,也看不见它拼了什么。而 CSFS 是个玻璃箱:它说,"你想验什么签名?你自己把要签的那张纸条递给我,我就验它。" 它把"该签的内容"这件事的决定权,从协议手里,交到了你手里。
把这两件工具一搭,刚才那个歪招就成立了:
让小李把字段当作证据一一摆上桌(压进见证),小王用 CAT 把这些字段重新拼成一张完整的纸带,再用 CSFS 验这张自己亲手拼出来的纸带上的签名对不对。手抄内省,大功告成。
这个歪招的厉害之处,是它能手搓出前面那些"原生能力"的效果。我给你看两个:
- 想模仿那个"签名不绑定具体来源"的特殊能力(它的学名叫 APO / ANYPREVOUT)?简单:拼纸带的时候,故意把"这笔钱具体是哪来的"那一格留空不拼。一张缺了那格的纸带,签出来的名,自然就不绑定来源了。说穿了,APO 不过是"标准纸带剪掉一格",而手抄这一招,本来就能想拼哪几格就拼哪几格。
- 想模仿 CTV 那个"钉死去向"的本事?也简单:把"钱去哪"那几格拼出来、拓个手印、和钉死的值比一比。——其实你发现没有,这一下连 CSFS 都不太用得上,光靠 CAT 拼一拼、拓个印、比一比就够了。CTV 那半边,纯粹是"拼字节 + 比手印"。
这件事有个正经名字,叫能力对等(capability parity):手抄这一招(CAT+CSFS),能模拟出 APO 和 CTV 所施加的那些约束。 这是小王这条线最硬的成果——不靠协议给的现成能力,纯靠把字段摆出来、亲手重拼、亲手验,就逼近了它们。
现在把纸带玩具开到满功率。这一招的全部精髓,就是沿着字段把纸带剪开、重组:抽掉"来源"那一格,你得到 APO;只保留"去向"那几格再拓印,你得到 CTV;想拼哪几格就拼哪几格,你就得到一张为所欲为的自定义纸带。手抄,让"内省"从一个你没有的超能力,变成了一桩手工活。
但我得对你诚实——这是这本书的规矩——说清楚这一招不是什么。
它是"模拟那个约束的效果",不是工程意义上的"替代"。小李把整张纸条都念出来摆上桌,这事本身是有代价的:纸条越长,桌上越挤(见证数据更大、更贵),而且这终究是"让花钱的人主动把字段摆出来再核",不是凭空长出了一双能直接读取的眼睛。所以你可以说小王"手抄出了同样的效果",但别以为这和原生能力在工程上一模一样。效果逼近了,成本和手段不一样。 记住这条分寸,下一章和最后一章都要用到。
这一章,链上是有真凭实据的:小王真的用 CAT+CSFS 手搓出了"钉死去向"的那张纸带,那笔交易就躺在链上,字节级的拆解我放进了附录¹。
下一章轻松一点。我们已经会手抄了,来看一个好玩的事实:同一个目标,常常有好几条路都能走到。
第七章 · 殊途同归
桌上有一种玩法,特别能体现比特币合约的精巧,它叫 Eltoo(也叫 Lightning Symmetry)。
它解决的问题是这样的:小王和小李想开一个长期的"共同账本",两人之间反复转账、随时更新余额,而且——关键来了——任何时候,都能用一个更新的状态去覆盖一个旧状态。 谁要是想耍赖、拿一个对自己有利的旧账本来结算,对方总能甩出一个更新的账本把它盖掉。这是闪电网络这类二层网络的命根子。
有意思的地方在于:要把这套"随时可翻新"的玩法摆上桌,有不止一种摆法。
- 第一种摆法,靠的是上一章提过的那个"签名不绑定来源"的能力(APO)。因为后续状态可以重绑到任意前序状态,所以更新起来很灵活。这条路,小王真的在链上跑通了,一共六笔交易、三个状态,完整的一条状态链²。
- 第二种摆法,一个 APO 都不用,改用"手抄"那条线里的 CSFS + CTV 组合。它玩的是一个很妙的互锁:让某个签名去签一张 CTV 的手印,而那张手印又在见证里出现第二次,两处一咬合,状态就锁死了。这条路更省,两笔交易、三个状态就够³。
你看,同一个目的地,两条完全不同的路。 一条六笔,一条两笔;一条用 APO,一条用 CSFS+CTV。终点一模一样——都是一个能随时翻新的共同账本——但走法南辕北辙。
这里有一个常被人搞混、值得你记一辈子的道理:
协议,不是操作码的阵营。
外面常有人吵"该上 APO 还是该上 CTV",吵得跟站队打仗似的,好像选了一个就背叛了另一个。但 Eltoo 这个例子明明白白告诉你:Eltoo 是一个目标,不是某一个操作码的私产。能走到这个目标的路有好几条,操作码只是不同的走法。你真正该关心的,从来不是"哪个操作码赢",而是"我想要的那个约束,能不能被够到;如果能,有几条路;每条路的代价是什么。"
这正是这本书想交到你手里的那把尺子——不站队,量能力。
(这一章得谢一个人:Christian Decker,他在那条公开讨论串里回了小王一手,那条回复本身就是这套东西成立的一个旁证。)
我们已经爬得很高了。手也会抄了,路也看清了不止一条。
那么,是时候去撞那堵墙了。下一章,我们要去找一件无论怎么手抄、都抄不出来的事。
第八章 · 墙
小王手抄上了瘾。他开始觉得,只要肯让对方把字段摆上桌,自己重拼重验,就没有什么约束是搓不出来的。
这一章,我要让他撞墙。而且我要让你亲眼看见这堵墙为什么在这儿、为什么绕不过去——这是这本书的智识高潮,请你慢一点读。
小王想要的,是这么两件事,听上去都不过分:
- 一件叫共同买单(行话叫 co-spend):"我这份钱要花,桌上就必须同时有小李那份也在花。" 而且他要的是规矩自己强制,不是靠小李配合签字——是哪怕小李不情愿,规矩也逼着这笔交易必须带上小李那份。
- 另一件叫金额守恒:"花出去的总额,必须正好等于收进来的总额,减掉一笔固定的小费。" 一分不多,一分不少,由规矩钉死。
小王挽起袖子,准备老办法:让对方把字段摆上桌,我重拼重验呗。
他失败了。无论怎么试,都搓不出来。
为什么?这就是我要你慢下来的地方。答案不在"他还不够聪明",答案在一个结构性的、数学性的死结:
回想小王手抄的整个动作——他能验的那张纸条,是他自己拼出来的。而他拿什么拼?他只能拿摆到桌面上、他看得见的字段来拼。换句话说,小王手里那张纸条,是"他看得见的东西"的一个函数。
那么,对于他看不见的东西呢?——比如,小李那份钱具体是从哪个来源来的、那份钱到底有多少。这些字段,没有被摆上桌,小王压根碰不到。 既然碰不到,它们就根本不会进入小王拼的那张纸条。
死结就在这里:
假设有两笔交易,唯一的区别就是"小李那份钱在不在场"。 因为小王拼纸条用的全是他看得见的字段,而"小李在不在场"这件事他看不见—— 所以这两笔交易,小王拼出来的纸条一模一样。 纸条一样,签名验起来就一样。小王永远分不出这两笔交易谁是谁。
既然他分不出来,他就没法只放行其中一笔、拦住另一笔。而"共同买单"要的恰恰就是这个:放行"小李在场"的,拦住"小李不在场"的。小王分不出,规矩就强制不了。
这就是墙。 它不是一道你再使把劲就能翻过去的栅栏,它是一条逻辑上的死线:一个函数,永远没法依赖一个它读不到的输入。你看不见的东西,你拼的纸条就对它无动于衷;纸条对它无动于衷,你就永远拿它没办法。金额守恒栽在同一个死结上——那个"有多少钱"的数,被摆不上桌、读不出明文,于是它也进不了纸条,于是你也守不住它。
还记得第一章那个碗吗?那是同一堵墙、更早的一块砖。钱倒进碗,"哪块是谁的、流去了哪道菜"这笔账,链从一开始就没记——它细不到那个边际。所以你今天就算想立"这道菜必须是小李出的钱",也无从立起:那个事实从来就不存在,链上没有哪一格写着它,你拼的纸条自然碰不到它。有时候你管不着一样东西,是因为它压根不在账上。
这件事,是可以被严格证明的——不是"我试了半天没成功",而是"我能证明谁都不可能成功"。它的形状是:
你能验的约束,全都是"可摆上桌的字段"的函数; 凡是摆不上桌的字段,约束对它必然无动于衷; 所以,凡是只在这种字段上有区别的两笔交易,必然无法被区分、无法被分别对待。
前面第六章我们证过手抄"够强"——强到能模拟 APO 和 CTV。这一章我们证的是另一半,而且是更值钱的一半:手抄"恰好够强"——它的能力边界,精确地停在这堵墙上。(这堵墙的半形式版本,我放进了附录⁴,那也正是小王那篇形式化论文的核心。)
现在,请你跟我一起,用费曼最爱的那种心情,来看这堵墙——带着高兴,而不是沮丧。
因为这堵墙,根本不是 CAT+CSFS 的缺陷。它是 sighash 这门语言本身的语法边界。它在说一件很深的事:在比特币里,你能承诺的,恰好就是你能看见的;你看不见你邻座手里的那张纸条,所以有些约束,永远手搓不出来。
而且——这是最妙的一点——那个"钉死去向"的 CTV,自己也翻不过这堵墙。 共同买单、金额守恒,CTV 一样做不到。所以这堵墙不是"谁比谁强"的问题,它不在小王和别人之间,它在所有人脚下。它划出的,是"签名能看见什么"这件事的天涯海角。
到这儿,开篇那句餐巾纸上的话,你应该真的看懂了:
一笔比特币支付的条件,就是每个签名能看见、能承诺的字段之和。
这句话的两头,你现在都摸到了。一头是第六章——凡是看得见、摆得上桌的,手抄就能承诺。 另一头是这一章——凡是看不见的,谁都承诺不了。 中间这条线,就是这堵墙。
最后一章,我们走出餐厅,去听听门外那群大人在吵什么。你会发现,他们吵了好多年的那件事,其实就是这堵墙该不该开一扇窗。
第九章 · 大人们在吵纸条该写多细
走出餐厅,门外站着一群大人,吵得不可开交。
你凑近一听,发现他们吵的,居然就是你刚刚在饭桌上想明白的那件事——纸条,到底该允许写多细?
有人说,纸条该能写"必须有人陪你一起付"(这不就是小王想要的共同买单吗)。有人说,该能写"这钱不能超过这个数"(这不就是金额守恒吗)。还有人说,别开这么细,纸条写太细了,会出乱子。
你现在听得懂这场架了。他们吵的,根本不是哪个操作码的名字。他们吵的是一件更根本的事:
我们到底要不要,让签名多看见一点?
因为第八章那堵墙你已经懂了:小王搓不出共同买单、搓不出金额守恒,不是手艺不行,是他看不见邻座的纸条。 想翻过那堵墙,只有一条路——给比特币装上一双新眼睛,让一个输入能直接读到另一个输入的来源、金额。这种"新眼睛",就是外面那些提案在争的东西(它们有一堆名字,OP_VAULT、CCV、INSPECTINPUT 之类,记不记得住都无所谓)。它们要给的,恰恰就是 CAT+CSFS 给不了的那个能力——看见邻座的纸条。
所以你可以把所有这些争论,整整齐齐地摆进一个框里。每一个 covenant 提案,本质上都是在三个旋钮上选一个位置:
- 看见多少(能内省到哪些字段)?
- 绑死多少(能钉死哪些约束)?
- 能不能转手(能不能把权限委托出去)?
每一个提案,都是在这三个旋钮组成的空间里,挑了一个角落站。 吵架,吵的就是该站哪个角。没有哪个角是天生正确的——每个角都有它的代价:开的窗越大,能写的纸条越细,但要操心的乱子也越多。
现在,我把开篇那句话,还给你。它不再是我写在餐巾纸上、要你先记下的一句口号了——它是你亲手一章一章挣来的一句真话:
一笔比特币支付的条件,就是每个签名能看见、能承诺的字段之和。 而那场吵了很多年的 covenant 之争,归根结底只是一个问题: 我们,要不要让签名,多看见一点?
这本书到这里就该合上了。但我不想给你一个句号,我想给你一把尺子。
往后,比特币会冒出新的提案、新的操作码、新的吵架。你不必去站任何一队。你只要把这把尺子掏出来,问三个问题:这个新东西,让签名多看见了什么?因此能多绑死什么?它在那个三旋钮的空间里,站到了哪个角?
能答上这三个问题,你就比绝大多数吵架的人,看得更清。
而"看得更清",从第一页那顿饭到现在,一直就是这本书唯一在讲的事。
附录
附录 A · 可以剪下来的 sighash 纸带
把 BIP-143 / BIP-341 的 sighash preimage 字段,画成一张一页纸的实体纸带,沿字段印好剪裁线。读者可以真的剪下来,在第二、四、六章动手玩:盖住几格(sighash flag)、抽掉来源那格(APO)、只拓印去向那几格(CTV)。正文里一直躲着的那张偏移表,在这里变成一件手工玩具。
完整的动手版游戏(七关,从 sighash 玩到墙,孩子能玩明白)见
APPENDIX_A_strip_game_CN.md —— 核心动作"按手印 =
抄下你看得见的格子",把全书每个例子都做成了纸条游戏。验收线:孩子玩明白
= 这本书写成了。 (成书时把纸条 / 硬币 / 手印卡画成可打印剪裁的一页
PDF。)
附录 B · 全部链上 TxID 与区块浏览器链接
书里引用的交易都在 Bitcoin Inquisition signet 上(那些尚未在主网激活的操作码在这里可以运行)。完整 hash 与逐步讲解,见作者对应的公开文章:
- 第六章 · CSFS+CAT 手搓输出绑定(txid
2f3451…)→ OP_CAT + OP_CHECKSIGFROMSTACK on Signet - 第七章 · APO 路 Eltoo 六笔状态链(
386dbb6a…等)→ SIGHASH_ANYPREVOUT on Signet - 第七章 · CSFS+CTV 路
Eltoo(
92efc475…、b96324da…)→ OP_CHECKTEMPLATEVERIFY on Signet - 第八章 · sha_prevouts 输入侧绑定(
7311da…)→ 见附录 D 的 signet 实证代码
Inquisition 是自定义 signet,没有通用区块浏览器;上述公开文章即这些交易的权威记录。
附录 C · 给好奇者:真实的字节偏移
正文被流放到这里的硬东西:BIP-143 preimage 的字段顺序与偏移、Taproot(BIP-341)的 tagged hash 构造、sha_outputs / sha_prevouts / sha_amounts 各自的字节区间、midstate 细节。
但最快的路子是直接打开配套的交互
playground(sighash-playground/index.html):它在浏览器里把这些字段一格一格实时拼给你看,拨一下旋钮就看见哪些被
SEE、哪些被蒙,digest 现算——而且逐字节对着 bitcoinutils
验证过。规范原文见 BIP-341、BIP-342、BIP-143。
附录 D · 延伸阅读(全是公开资料)
这本书只讲一个想法、不堆细节。想深入每个操作码,作者有一整套公开的 signet 实证系列,逐章对应:
- 第 2 章 · sighash 与脚本骨架 → The Anatomy of Bitcoin Scripts: From P2PKH to Taproot
- 第 3 / 4 章 · covenant、递归(CTV)→ OP_CHECKTEMPLATEVERIFY on Signet
- 第 6 章 · 手抄纸条(CSFS + CAT)→ OP_CAT on Signet · OP_CHECKSIGFROMSTACK on Signet · OP_CAT + OP_CHECKSIGFROMSTACK on Signet
- 第 7 章 · Eltoo / 签名不绑来源(APO)→ SIGHASH_ANYPREVOUT on Signet
- 全书“commit-reveal”背景 → Commit-Reveal vs Dual-Layer Scripts
作者全部公开写作:https://medium.com/@aaron.recompile
规范原文(BIP): Taproot sighash BIP-341 · Tapscript BIP-342 · 旧版 sighash BIP-143 · CTV BIP-119 · APO BIP-118 · OP_CAT BIP-347 · OP_CHECKSIGFROMSTACK BIP-348
试验场: Bitcoin Inquisition —— 一个公开 signet,上面这些还未在主网激活的操作码都能跑。
交互 + 代码: 本书配套的 sighash
playground(浏览器里拨旋钮看 SEE / 蒙、亲手 tamper
验证),以及单→多输入的字段打印器,都在本仓
sighash-playground/。
v0.1 完。中文版;英文版见 MANUSCRIPT_EN.md。配套交互
playground 与代码见 sighash-playground/。
正文零代码、零内部引用;所有延伸资料(操作码深潜、BIP、链上交易)都是公开链接,见附录
B / C / D。
¹ 见附录 B。完整逐步讲解见公开文章 OP_CAT + OP_CHECKSIGFROMSTACK on Signet,以及配套 playground(在浏览器里看 sha_outputs 怎么被拼出来)。 ² 见附录 B(APO 路 Eltoo 六笔)。 ³ 见附录 B(CSFS+CTV 路 Eltoo 两笔)。 ⁴ 见附录 C 与配套 playground;这堵墙(separation)可以进一步写成机械化可验证的定理。