- 示例工程
- 区块链
【免费下载链接】Dapp-Learning
Dapp learning project for developers at all stages. Becoming and cultivating sovereign individuals. Nonprofit organization.
导读
多签名(Multi-Signature,简称 Multi-Sig)是比特币网络中最重要的安全性增强技术之一:它要求多个密钥共同签名才能执行一笔交易,从而将"单点私钥泄露即资金丢失"的风险转化为"必须同时攻破多个私钥"的高门槛。本文以 Dapp-Learning 仓库中 BTC/Advanced/Multisign/README-EN.md 为核心骨架,系统讲解多签的运作原理、典型应用场景,并深入剖析实现多签的三个核心操作码——传统时代的OP_CHECKMULTISIG/OP_CHECKMULTISIGVERIFY与 Taproot 时代的OP_CHECKSIGADD。读完本文,你将掌握:如何构建 2-of-3 多签地址、如何读懂 P2SH / P2WSH / Taproot 三类多签脚本、三个操作码的差异与选型依据,以及基于 bitcoinjs-lib 的完整代码级实现流程。
一、多签名技术概述
在比特币网络中,多签名是一种安全性增强技术,它要求多个密钥签名才能执行一笔交易。具体来说,多签机制允许用户创建一个钱包地址,只有在满足一定数量的签名条件时,才能动用钱包中的资金。多签名技术可以用于提高安全性、实现分布式控制以及管理资金等多种用途。
多签的"阈值"概念通常表示为m-of-n:地址由 n 个参与者的公钥共同生成,任何花费操作至少需要其中 m 个私钥对应的签名才能通过验证。例如 2-of-3 表示需要三个公钥,且至少其中两个对应的私钥参与签名。
多签名的工作原理
多签的完整生命周期可以分为三个步骤:
创建多签地址
- 多签地址通常由多个参与者的公钥共同生成。
- 以 2-of-3 为例:收集三份公钥,编写一个"至少两个签名有效"的赎回脚本(Redeem Script),再将该脚本的哈希编码为可接收比特币的地址。
构造交易
- 当需要花费多签地址中的比特币时,必须构造一个包含所有必要签名的交易。
- 仍以 2-of-3 为例:交易需要至少两个参与者(任意两人)提供有效签名后才能合法花费。
广播交易
- 完整签名后的交易可广播到比特币网络,由矿工验证签名与脚本逻辑后打包上链。
多签名的应用场景
多签之所以被广泛采用,是因为它能在三个维度上带来根本性的改变:
- 提高安全性:单一私钥被盗无法转移资金,攻击者必须同时窃取多个私钥才能构造恶意交易,显著提高资金失窃门槛。
- 分布式控制:适用于多方共同控制资金的场景,例如公司资金的多方共管,防止单人滥用职权挪用资产。
- 智能合约与去中心化应用(DApp):多签可作为简单的智能合约机制,配合时间锁、阈值条件等脚本元素,支撑更复杂的交易条件和业务逻辑。
一个完整的 2-of-3 多签流程示例
假设 Alice、Bob、Charlie 三人共同管理一笔资金,任何花费必须至少两人同意:
- 生成三份公私钥对(用户 A、用户 B、用户 C)。
- 使用三个公钥生成一个 2-of-3 多签地址。
- 将比特币转入该多签地址。
- 需要转出比特币时,由用户 A 和 B(或 A 和 C,或 B 和 C)中的任意两人共同签名交易。
- 将交易广播到网络并等待确认。
二、多签名验证的核心 OPCode
多签名技术在比特币脚本(Bitcoin Script)层面由一组关键操作码(OPCode)支撑。比特币脚本是一种基于堆栈的、非图灵完备的脚本语言,多签验证正是通过堆栈操作完成的。以下是三个与多签直接相关的操作码。
1. OP_CHECKMULTISIG——传统多签验证
- 功能:验证多签名交易。
- 描述:从堆栈中弹出 n 个公钥和 m 个签名,检查其中是否至少有 m 个签名有效。有效则返回 true,否则返回 false。
- 示例:
<m> <PubKey A> <PubKey B> <PubKey C> <n> OP_CHECKMULTISIG其中<m>是所需的最小签名数,<n>是提供的公钥数量。
背景与 BIP
OP_CHECKMULTISIG的多签标准化历史与两份 BIP 密切相关:
- BIP 11(M-of-N Standard Transactions):由 Gavin Andresen 于 2012 年 3 月提出,描述了多重签名交易的标准格式,即 N 个公钥中需有 M 个签名验证通过方可执行交易。
- BIP 16(Pay to Script Hash):由 Gavin Andresen 于 2012 年 1 月提出,定义了 P2SH 机制,使复杂脚本可以在链上以简洁的哈希形式表示,极大增强了多签的可用性。2012 年 5 月,Bitcoin Core 集成 P2SH 与多签功能,
OP_CHECKMULTISIG开始正式投入使用。
堆栈执行细节
从 BTC/Advanced/Multisign/OP_CHECKMULTISIG/README.md 的拆解看,其执行过程为:
- 堆栈输入依次为:签名数量(N)、N 个签名、公钥数量(M)、M 个公钥。
- 从堆栈中弹出签名数量 N,弹出 N 个签名并存储。
- 弹出公钥数量 M,弹出 M 个公钥并存储。
- 逐一验证签名与公钥的匹配关系,确认至少有 M 个签名有效。
- 验证成功则脚本继续执行,否则脚本失败。
著名的 off-by-one 漏洞
早期版本的OP_CHECKMULTISIG存在一个历史遗留的off-by-one 漏洞:它的实现会从堆栈中多弹出一个元素,因此要求在签名序列之前额外放置一个空操作数OP_0(即 0x00)。这一"多出来的空值"至今仍体现在所有传统多签的解锁脚本中,是阅读链上多签交易时必须了解的知识点。
链上真实交易拆解
在 OP_CHECKMULTISIG 子文档 中记录了真实的链上多签交易脚本,下面是一笔 P2SH 多签交易的完整脚本结构:
// ScriptSig(解锁脚本) <empty> OP_0 OP_PUSHBYTES_71 3044022018a750079fc75b68f5208f86b146821d5f3acb41f68195f8b4cbf1012cba2cbb02200c3ddd0dc271342f62222603356dd7c713cf387718e57ec2644f7811295d03ea01 OP_PUSHBYTES_72 30450221009a5914969675238ddfb9c1475d2888b3a5a507c6d13c35ac13a6f97a5c3dec97022055587f56408ba7abdc48d637d3eb03a3c29f05d7c22df9a20fd4bea739a00b2601 OP_PUSHDATA1 52210231d0ed51696dff4a25015f2a8330d07b81761eda22cae558da1086b5d084e1922102e142c9123d48ce4c0b32403b19403e41129f1d37de852d9bbc95165af6960e3b2102207620c770dc24eb02edc6fba51b70fd0c04a2772842d808188b835a8f73832853ae // P2SH redeem script(赎回脚本) OP_PUSHNUM_2 OP_PUSHBYTES_33 0231d0ed51696dff4a25015f2a8330d07b81761eda22cae558da1086b5d084e192 OP_PUSHBYTES_33 02e142c9123d48ce4c0b32403b19403e41129f1d37de852d9bbc95165af6960e3b OP_PUSHBYTES_33 02207620c770dc24eb02edc6fba51b70fd0c04a2772842d808188b835a8f738328 OP_PUSHNUM_3 OP_CHECKMULTISIG解读:OP_PUSHDATA1 52...ae中的52(即 0x52 = 十进制 82,代表OP_2)和末尾的ae(即OP_CHECKMULTISIG)共同构成2 <pk1> <pk2> <pk3> 3 OP_CHECKMULTISIG的 2-of-3 赎回脚本;解锁侧则携带了OP_0(应对 off-by-one 漏洞)、两份 DER 编码的 ECDSA 签名以及完整赎回脚本。
基于 bitcoinjs-lib 的代码级实现
子文档还给出了基于 bitcoinjs-lib 的分步实现思路(原示例来源于其测试套件),核心流程如下:
第一步,构建锁定脚本:
2 <AlicePubKey> <BobPubKey> <CharliePubKey> 3 OP_CHECKMULTISIG const output = bscript.compile( ([] as Stack).concat( OP_INT_BASE + a.m, // m = 2,最小签名数 a.pubkeys, // 三个公钥 OP_INT_BASE + o.n, // n = 3,公钥总数 OPS.OP_CHECKMULTISIG, ) );第二步,通过 PSBT 签名:
const psbt = new bitcoin.Psbt({ network: regtest }) .addInput(inputData1) .addOutput({ address: regtestUtils.RANDOM_ADDRESS, value: 1e4 }) .signInput(0, multisig.keys[0]) // Alice 签名 .signInput(0, multisig.keys[2]); // Charlie 签名签名后得到包含多份签名的数组:
const partialSig = [ { pubkey: AlicePubKey, signature: bscript.signature.encode(Alice.sign(hash), sighashType) }, { pubkey: BobPubKey, signature: bscript.signature.encode(Bob.sign(hash), sighashType) }, ];第三步,按脚本中公钥顺序排序签名:多签脚本要求签名按照赎回脚本中公钥的排列顺序摆放,因此需要通过payments.p2ms({ output: script })解析脚本并按公钥顺序过滤匹配的签名。
第四步,构建解锁脚本:
bscript.compile(([OPS.OP_0] as Stack).concat(a.signatures))注意开头的OPS.OP_0正是上文提到的 off-by-one 漏洞补偿空值。
2. OP_CHECKMULTISIGVERIFY——验证失败立即终止
- 功能:与
OP_CHECKMULTISIG类似,但在验证失败时终止脚本执行并返回错误。 - 描述:工作原理与
OP_CHECKMULTISIG完全相同,区别在于检查失败时脚本立即失败,而不是将 false 留在堆栈上继续执行。 - 示例:
<m> <PubKey A> <PubKey B> <PubKey C> <n> OP_CHECKMULTISIGVERIFY与 BIP 16 的关系
OP_CHECKMULTISIGVERIFY并未通过单独的 BIP 提出,其背景与 BIP 16(P2SH)密切相关:P2SH 使复杂脚本可以在链上以哈希形式简洁表示,而OP_CHECKMULTISIGVERIFY作为OP_CHECKMULTISIG与OP_VERIFY的组合被自然引入,用于简化多签验证的脚本编写与执行流程——验证通过则继续,失败则整个脚本立即失败,免去了手动判断返回值的逻辑。脚本构建与签名过程与OP_CHECKMULTISIG一致,可参考 OP_CHECKMULTISIG 子文档。
实战案例:Babylon 质押协议的多签验证
在 OP_CHECKMULTISIGVERIFY 子文档 中记录了一个真实应用:Babylon 业务将用户资产质押到 Taproot 地址中,其官方披露的三条解锁路径都使用OP_CHECKSIGVERIFY验证签名后再执行后续逻辑:
- 时间锁路径(质押者到期赎回):
<Staker_PK> OP_CHECKSIGVERIFY <Timelock_Blocks> OP_CHECKSEQUENCEVERIFY- 解绑路径(质押者提前赎回,需要 Covenant 多方达到阈值):
<StakerPk> OP_CHECKSIGVERIFY <CovenantPk1> OP_CHECKSIG <CovenantPk1> OP_CHECKSIGADD ... <CovenantPkN> OP_CHECKSIGADD <CovenantThreshold> OP_GREATERTHANOREQUAL- 惩罚路径(质押者作恶时,Finality Provider 与 Covenant 联合触发):
<StakerPk> OP_CHECKSIGVERIFY <FinalityProviderPk> OP_CHECKSIGVERIFY <CovenantPk1> OP_CHECKSIG <CovenantPk1> OP_CHECKSIGADD ... <CovenantPkN> OP_CHECKSIGADD <CovenantThreshold> OP_GREATERTHANOREQUAL这个案例展示了"验证 + 继续"的编程范式:先通过OP_CHECKSIGVERIFY强制验证某个签名(失败即终止),再进入多签阈值累加逻辑,是VERIFY系列操作码在真实协议中的典型应用。
3. OP_CHECKSIGADD——Taproot 时代的高效多签
- 功能:在 Taproot 与 Schnorr 签名方案中实现高效的多签名验证。
- 描述:从堆栈中取出一个公钥和一个签名,验证该签名是否有效,并将结果(0 或 1)累加到一个计数器上,计数器表示当前有效签名的总数。
- 示例:
<PubKey A> <Sig A> OP_CHECKSIGADD <PubKey B> <Sig B> OP_CHECKSIGADD <PubKey C> <Sig C> OP_CHECKSIGADD <2> OP_EQUAL逐行解读:
<PubKey A> <Sig A> OP_CHECKSIGADD:验证签名 A 是否匹配公钥 A,将结果加入计数器。<PubKey B> <Sig B> OP_CHECKSIGADD:同上累加 B 的结果。<PubKey C> <Sig C> OP_CHECKSIGADD:同上累加 C 的结果。<2> OP_EQUAL:检查计数器是否等于 2,即确认恰好有两个有效签名。
BIP 背景与激活历程
OP_CHECKSIGADD的引入与 Schnorr 签名、Taproot 升级捆绑推出(详见 OP_CHECKSIGADD 子文档):
- BIP 340(Schnorr Signatures for secp256k1):Pieter Wuille、Jonas Nick、Tim Ruffing 于 2020 年 1 月提出,为比特币引入 Schnorr 签名算法,带来更简洁的签名与更高的验证效率。
- BIP 341(Taproot: SegWit version 1 spending rules):Pieter Wuille、Jonas Nick、Anthony Towns 于 2020 年 1 月提出,定义 Taproot 新输出类型,使复杂交易更高效、更具隐私性。
- BIP 342(Validation of Taproot Scripts):Pieter Wuille 于 2020 年 1 月提出,正式引入
OP_CHECKSIGADD操作码用于 Taproot 中的高效多签验证。
Taproot 采用Speedy Trial激活机制:矿工通过区块中的 version bits 信号位表达支持;在一个难度调整周期(2016 个区块)内,至少 90% 的区块(1815 个)设置信号位即达到激活门槛,随后进入锁定期,再经一个难度调整周期后正式生效。Taproot 于 2021 年 6 月达到激活门槛,2021 年 11 月 14 日正式在主网激活,此后OP_CHECKSIGADD等新功能正式生效。
与 Schnorr 签名技术栈的关联
OP_CHECKSIGADD之所以高效,根源在于 Schnorr 签名本身的特性。在仓库的 BTC/Basic/signature/README.md 中可以看到 ECDSA 与 Schnorr 的详细对比:
| 特性 | ECDSA | Schnorr |
|---|---|---|
| 安全性 | 随机数重用或泄露会暴露私钥 | 对随机数选择不敏感,相对更安全 |
| 效率 | 签名和验证相对复杂、计算量大 | 签名和验证更高效,支持批量验证 |
| 可组合性 | 无签名可组合性 | 支持签名聚合,可将多个签名合并为一个 |
| 签名大小 | 包含两个等长的整数(r, s) | 同样为(r, s)对,但因可组合性可存储更少数据 |
| 实际应用 | 比特币早期广泛使用 | 比特币 BIP 340 提案采用 |
Schnorr 的线性特性使多方签名可以聚合成单一签名,配合 Taproot 将多签交易伪装成普通单签交易,兼顾效率与隐私。仓库中还提供了 schnorr.js 可运行示例:通过ECPair.makeRandom()生成密钥对、keyPair.signSchnorr(txHash)生成 Schnorr 签名、keyPair.verifySchnorr(txHash, signature)验证签名,可作为理解 Schnorr 签名流程的入门代码。
三、多签脚本实战:P2SH 与 Taproot
P2SH(Pay-to-Script-Hash)多签名交易
P2SH 是最经典的多签承载方式,其核心思想是链上只存放赎回脚本的哈希,解锁时提供完整脚本。完整流程如下:
- 创建赎回脚本(Redeem Script):
<2> <PubKey A> <PubKey B> <PubKey C> <3> OP_CHECKMULTISIG其中<2>表示至少需要两个签名,三个公钥为<PubKey A> <PubKey B> <PubKey C>,<3>表示共有三个公钥。
生成 P2SH 地址:将上述赎回脚本的哈希值编码为 P2SH 地址,将比特币发送到该地址。
花费 P2SH 多签交易:解锁脚本(Unlocking Script)为:
<0> <Sig1> <Sig2> <Redeem Script><0>:应对OP_CHECKMULTISIG的 off-by-one 历史漏洞所需的额外空值。<Sig1> <Sig2>:两份有效签名。<Redeem Script>:完整赎回脚本,向节点证明满足解锁条件。
Taproot 多签名脚本(Script Path)
Taproot 将多签实现为 MAST(Merkelized Abstract Syntax Tree)中的一个脚本叶子(leaf),花费时只需公开被执行的脚本分支与 Merkle 路径,其余条件保持隐藏:
<PubKey A> <Sig A> OP_CHECKSIGADD <PubKey B> <Sig B> OP_CHECKSIGADD <PubKey C> <Sig C> OP_CHECKSIGADD <2> OP_EQUALTaproot 多签的完整代码实践
OP_CHECKSIGADD 子文档 给出了基于 bitcoinjs-lib 的 Taproot script-path 2-of-3 多签完整示例,这里按步骤拆解:
1. 生成 internal public key 与三份多签用户密钥:
const internalKey = bip32.fromSeed(rng(64), regtest); const leafKeys = []; const leafPubkeys = []; for (let i = 0; i < 3; i++) { const leafKey = bip32.fromSeed(rng(64), regtest); leafKeys.push(leafKey); leafPubkeys.push(toXOnly(leafKey.publicKey).toString('hex')); }其中toXOnly将完整公钥截取为 32 字节的 x-only 公钥——这是 Taproot/Schnorr 体系的要求(仓库中 Taproot 示例 的实现为Buffer.from(pubKey).slice(1, 33))。
2. 构造锁定脚本(叶子脚本):
const leafScriptAsm = `${leafPubkeys[2]} OP_CHECKSIG ${leafPubkeys[1]} OP_CHECKSIGADD ${leafPubkeys[0]} OP_CHECKSIGADD OP_3 OP_NUMEQUAL`;注意这里把 2-of-3 阈值表达为"3 个公钥逐一OP_CHECKSIGADD累加,再OP_3 OP_NUMEQUAL要求恰好 3 个都有效"——在 Taproot 脚本路径中,签名者集合是确定的,未签名者需要以占位符补齐(详见第 5 步),因此"至少 2 个"的语义被等价实现为"全部 3 个槽位必须填满、其中至少 2 个是真实有效签名"。
3. 构造 MAST 脚本树并生成 P2TR 地址:
const leafScript = bitcoin.script.fromASM(leafScriptAsm); const scriptTree: Taptree = [ { output: bitcoin.script.fromASM('50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 OP_CHECKSIG') }, [ { output: bitcoin.script.fromASM('50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0 OP_CHECKSIG') }, { output: leafScript }, ], ]; const { output, address, witness } = bitcoin.payments.p2tr({ internalPubkey: toXOnly(internalKey.publicKey), scriptTree, redeem: { output: leafScript, redeemVersion: LEAF_VERSION_TAPSCRIPT }, network: regtest, });4. 构造 PSBT 交易:
const psbt = new bitcoin.Psbt({ network: regtest }); wallet.addInput(psbt, unspent.txId, unspent.vout, unspent.value); psbt.addOutput({ value: sendAmount, address: wallet.address });PSBT(部分签名比特币交易,BIP 174)正是为这种"多方离线协作签名"设计的格式,其标准流程包含创建者(Creator)、更新者(Updater)、签名者(Signer)、合并者(Combiner)、最终化者(Finalizer)与广播者(Broadcaster)等角色,详见仓库 BTC/Advanced/Psbt/README.md。
5. 三方中任意两方签名,并对未签名者补占位签名:
wallet3.verifyInputScript(psbt, 0); wallet2.verifyInputScript(psbt, 0); psbt.signInput(0, wallet3); psbt.signInput(0, wallet2); wallet.addDummySigs(psbt); // 为所有未签名公钥补充空签名占位addDummySigs的核心逻辑是:遍历 PSBT 输入,找出该叶子脚本哈希下尚未签名的公钥,为其写入signature: Buffer.from([])的空 Buffer 占位。关键要点:由于OP_CHECKSIGADD需要完整的三个签名槽位,对未签名的公钥必须补一个无效签名(一个字节的0x00),否则脚本验证会因为堆栈元素不足而失败。
6. 最终化、提取并广播交易:
psbt.finalizeAllInputs(); const tx = psbt.extractTransaction(); const hex = tx.toBuffer().toString('hex'); await regtestUtils.broadcast(hex);OP_CHECKSIGADD真实链上交易的 witness 脚本还经常与其他操作码混用,例如下面的真实脚本片段就同时包含了OP_CHECKSIGVERIFY、OP_CHECKSIG与连续多次OP_CHECKSIGADD,最后以OP_PUSHNUM_6 OP_NUMEQUAL要求有效签名数恰好为 6:
OP_PUSHBYTES_32 9d65bad2d86e26bf1a907077312b849f89e5109a8574087a34953252af63940c OP_CHECKSIGVERIFY OP_PUSHBYTES_32 113c3a32a9d320b72190a04a020a0db3976ef36972673258e9a38a364f3dc3b0 OP_CHECKSIG OP_PUSHBYTES_32 17921cf156ccb4e73d428f996ed11b245313e37e27c978ac4d2cc21eca4672e4 OP_CHECKSIGADD ...(后续多个 OP_PUSHBYTES_32 + OP_CHECKSIGADD 组合) OP_PUSHNUM_6 OP_NUMEQUAL这种"VERIFY 前置校验 + CHECKSIGADD 阈值累加 + NUMEQUAL 收尾"的写法,正是现代比特币复杂多签/质押协议的通用范式。
四、操作码横向对比
以下对比表完整覆盖三个多签操作码的功能、优缺点、适用脚本类型与 BIP 编号:
| OPCode | 功能 | 描述 | 优点 | 缺点 | 使用的脚本类型 | 推出的 BIP 编号 | 示例 |
|---|---|---|---|---|---|---|---|
| OP_CHECKMULTISIG | 验证多签名交易 | 从堆栈中弹出 n 个公钥和 m 个签名,检查是否有至少 m 个签名有效,有效返回 true,否则返回 false | 适用于传统多签交易,广泛支持 | 脚本较大;存在历史遗留 off-by-one 漏洞,需要额外空值 | P2SH, P2WSH | BIP 11, BIP 16 | <2> <PubKey A> <PubKey B> <PubKey C> <3> OP_CHECKMULTISIG |
| OP_CHECKMULTISIGVERIFY | 验证多签并返回错误 | 与 OP_CHECKMULTISIG 类似,但验证失败时立即终止执行并返回错误 | 简化了错误处理逻辑 | 同样存在 off-by-one 漏洞,需要额外空值 | P2SH, P2WSH | BIP 11, BIP 16 | <2> <PubKey A> <PubKey B> <PubKey C> <3> OP_CHECKMULTISIGVERIFY |
| OP_CHECKSIGADD | 高效验证多签 | 从堆栈中取出一个公钥和一个签名,验证签名有效性并将结果累加到计数器 | 更高效,简化多签脚本,减少交易大小与费用 | 仅在 Taproot 与 Schnorr 签名方案中可用 | Taproot | BIP 340, BIP 341, BIP 342 | <PubKey A> <Sig A> OP_CHECKSIGADD<br><PubKey B> <Sig B> OP_CHECKSIGADD<br><PubKey C> <Sig C> OP_CHECKSIGADD<br><2> OP_EQUAL |
选型建议
- 传统兼容场景(P2SH / P2WSH):选择
OP_CHECKMULTISIG/OP_CHECKMULTISIGVERIFY。它们被所有钱包与节点广泛支持,适合需要最大兼容性的企业共管钱包、继承方案等;代价是脚本体积较大,且必须处理OP_0占位符。 - Taproot 场景:优先使用
OP_CHECKSIGADD。它不仅脚本更简洁、交易体积更小,还能借助 MAST 只暴露实际执行的分支,配合 Schnorr 的签名聚合获得更好的隐私性。仓库的 Taproot 文档 指出:SegWit v0(P2WPKH/P2WSH,bc1q开头)使用 ECDSA,而 SegWit v1(Taproot,bc1p开头)使用 Schnorr 并支持 MAST 与批量验证,二者在地址格式、签名算法、隐私效率与智能合约能力上存在系统性差异。
五、总结
比特币网络通过一组操作码提供了多种实现多签的方式,可归纳为两个时代:
- 传统时代:
OP_CHECKMULTISIG与OP_CHECKMULTISIGVERIFY配合 P2SH/P2WSH 承载 m-of-n 多签,由 BIP 11 与 BIP 16 标准化,至今仍是兼容性最强的多签方案,但其 off-by-one 历史漏洞要求额外的OP_0占位,脚本体积也偏大。 - Taproot 时代:
OP_CHECKSIGADD随 BIP 340/341/342 与 Schnorr 签名一同登场,以"逐签验证、累加计数、阈值比较"的方式高效实现多签,配合 MAST 树隐藏未执行分支,兼顾效率、灵活性与隐私。
从 Dapp-Learning 仓库的多签专题可以看到,完整理解多签需要打通"协议层(BIP)→ 脚本层(OPCode 与堆栈)→ 应用层(PSBT 多方签名协作)→ 代码层(bitcoinjs-lib 实现)"的完整链路。无论是构建企业级共管钱包,还是开发 Babylon 式质押协议这类复杂条件支付,多签操作码的选择与脚本组织方式都直接决定了交易的安全性、体积与隐私表现——这正是本文希望通过源码级拆解帮你建立的核心能力。
延伸阅读
- 多签专题中文版:本文对应的中文原版文档。
- OP_CHECKMULTISIG 详解:BIP 11/16 历史、链上交易脚本与 bitcoinjs-lib 完整代码。
- OP_CHECKMULTISIGVERIFY 详解:含 Babylon 质押协议实战案例。
- OP_CHECKSIGADD 详解:Taproot 激活历程与 Taproot 多签完整代码。
- Taproot 技术文档:SegWit v0/v1 对比、锁脚本/解锁脚本对照。
- MAST 文档:Merkle 树结构、叶子/内部/根节点与验证路径。
- PSBT 文档:多方签名协作格式与六种参与角色。
- 比特币签名体系:ECDSA 与 Schnorr 的数学原理与对比。
- Schnorr 签名代码示例:可直接运行的 Schnorr 签名/验证演示。
- Taproot 可运行示例:地址生成、Schnorr 签名与交易构建的完整实现。
- 示例工程
- 区块链
【免费下载链接】Dapp-Learning
Dapp learning project for developers at all stages. Becoming and cultivating sovereign individuals. Nonprofit organization.
相关推荐
比特币多签技术全指南:从 OP_CHECKMULTISIG 到 Taproot OP_CHECKSIGADD
比特币多签技术全指南:从 OP_CHECKMULTISIG 到 Taproot OP_CHECKSIGADD 本指南基于 Dapp Learning 仓库 BT
示例工程区块链比特币 Taproot 实战指南:Dapp-Learning 示例中的 P2TR 地址生成与 Schnorr 签名交易
比特币 Taproot 实战指南:Dapp Learning 示例中的 P2TR 地址生成与 Schnorr 签名交易 本文以开源仓库 Dapp Learnin
示例工程区块链Dapp-Learning 深度解析:比特币 Taproot 与 MAST 技术全指南
Dapp Learning 深度解析:比特币 Taproot 与 MAST 技术全指南 导读 本文是 Dapp Learning 开源仓库中比特币 Taproo
示例工程区块链
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考