示例工程区块链【免费下载链接】Dapp-LearningDapp learning project for developers at all stages. Becoming and cultivating sovereign individuals. Nonprofit organization.项目地址https://gitcode.com/gh_mirrors/da/Dapp-Learning点击查看免费下载导读多签名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是提供的公钥数量。背景与 BIPOP_CHECKMULTISIG的多签标准化历史与两份 BIP 密切相关BIP 11M-of-N Standard Transactions由 Gavin Andresen 于 2012 年 3 月提出描述了多重签名交易的标准格式即 N 个公钥中需有 M 个签名验证通过方可执行交易。BIP 16Pay 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 16P2SH密切相关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 340Schnorr Signatures for secp256k1Pieter Wuille、Jonas Nick、Tim Ruffing 于 2020 年 1 月提出为比特币引入 Schnorr 签名算法带来更简洁的签名与更高的验证效率。BIP 341Taproot: SegWit version 1 spending rulesPieter Wuille、Jonas Nick、Anthony Towns 于 2020 年 1 月提出定义 Taproot 新输出类型使复杂交易更高效、更具隐私性。BIP 342Validation of Taproot ScriptsPieter 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 的详细对比特性ECDSASchnorr安全性随机数重用或泄露会暴露私钥对随机数选择不敏感相对更安全效率签名和验证相对复杂、计算量大签名和验证更高效支持批量验证可组合性无签名可组合性支持签名聚合可将多个签名合并为一个签名大小包含两个等长的整数(r, s)同样为(r, s)对但因可组合性可存储更少数据实际应用比特币早期广泛使用比特币 BIP 340 提案采用Schnorr 的线性特性使多方签名可以聚合成单一签名配合 Taproot 将多签交易伪装成普通单签交易兼顾效率与隐私。仓库中还提供了 schnorr.js 可运行示例通过ECPair.makeRandom()生成密钥对、keyPair.signSchnorr(txHash)生成 Schnorr 签名、keyPair.verifySchnorr(txHash, signature)验证签名可作为理解 Schnorr 签名流程的入门代码。三、多签脚本实战P2SH 与 TaprootP2SHPay-to-Script-Hash多签名交易P2SH 是最经典的多签承载方式其核心思想是链上只存放赎回脚本的哈希解锁时提供完整脚本。完整流程如下创建赎回脚本Redeem Script2 PubKey A PubKey B PubKey C 3 OP_CHECKMULTISIG其中2表示至少需要两个签名三个公钥为PubKey A PubKey B PubKey C3表示共有三个公钥。生成 P2SH 地址将上述赎回脚本的哈希值编码为 P2SH 地址将比特币发送到该地址。花费 P2SH 多签交易解锁脚本Unlocking Script为0 Sig1 Sig2 Redeem Script0应对OP_CHECKMULTISIG的 off-by-one 历史漏洞所需的额外空值。Sig1 Sig2两份有效签名。Redeem Script完整赎回脚本向节点证明满足解锁条件。Taproot 多签名脚本Script PathTaproot 将多签实现为 MASTMerkelized 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要求有效签名数恰好为 6OP_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, P2WSHBIP 11, BIP 162 PubKey A PubKey B PubKey C 3 OP_CHECKMULTISIGOP_CHECKMULTISIGVERIFY验证多签并返回错误与 OP_CHECKMULTISIG 类似但验证失败时立即终止执行并返回错误简化了错误处理逻辑同样存在 off-by-one 漏洞需要额外空值P2SH, P2WSHBIP 11, BIP 162 PubKey A PubKey B PubKey C 3 OP_CHECKMULTISIGVERIFYOP_CHECKSIGADD高效验证多签从堆栈中取出一个公钥和一个签名验证签名有效性并将结果累加到计数器更高效简化多签脚本减少交易大小与费用仅在 Taproot 与 Schnorr 签名方案中可用TaprootBIP 340, BIP 341, BIP 342PubKey A Sig A OP_CHECKSIGADDbrPubKey B Sig B OP_CHECKSIGADDbrPubKey C Sig C OP_CHECKSIGADDbr2 OP_EQUAL选型建议传统兼容场景P2SH / P2WSH选择OP_CHECKMULTISIG/OP_CHECKMULTISIGVERIFY。它们被所有钱包与节点广泛支持适合需要最大兼容性的企业共管钱包、继承方案等代价是脚本体积较大且必须处理OP_0占位符。Taproot 场景优先使用OP_CHECKSIGADD。它不仅脚本更简洁、交易体积更小还能借助 MAST 只暴露实际执行的分支配合 Schnorr 的签名聚合获得更好的隐私性。仓库的 Taproot 文档 指出SegWit v0P2WPKH/P2WSHbc1q开头使用 ECDSA而 SegWit v1Taprootbc1p开头使用 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-LearningDapp learning project for developers at all stages. Becoming and cultivating sovereign individuals. Nonprofit organization.项目地址https://gitcode.com/gh_mirrors/da/Dapp-Learning点击查看免费下载相关推荐比特币多签技术全指南从 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),仅供参考