BRC20 铭文的构建原理与实现
概述
BRC20 铭文是基于比特币 Ordinals 协议的代币标准,它利用比特币的 Taproot 升级(P2TR 交易类型)在比特币区块链上存储数据。本文将详细介绍 BRC20 铭文的构建原理和实现流程。
一、技术基础:理解 P2TR 和 Taproot
1.1 什么是 P2TR
P2TR(Pay-to-Taproot) 是比特币的一种新交易类型,由 BIP341 提案引入。与传统交易不同:
- 传统交易:资金锁定到固定的地址
- P2TR 交易:资金锁定到一个 Taproot(Merkle 树根)
1.2 Taproot 的工作原理
Taproot 类似于 Merkle Root,是一棵 Merkle 树的根节点。树上的每个叶子节点都是一个 witness script(见证脚本)。
解锁机制:
要花费 P2TR 地址上的比特币,需要提供一份有效的 Merkle 证明,证明你使用的 witness script 是脚本树中的合法路径。如下图所示,要使用某个脚本(如 Banana),需要提供从该脚本到 Merkle Root 的完整路径证明,只要能计算出正确的 Merkle Root Hash,就能解锁资金。
二、铭文构建流程
BRC20 铭文的创建采用 Commit-Reveal 两阶段模式:
2.1 整体流程
- 生成密钥对:随机生成一个 BTC 私钥
- 转换为 P2TR 格式:将私钥转换为符合 P2TR 格式的公钥
- 构建铭文脚本:创建包含铭文数据的 witness script
- 生成 P2TR 地址:基于脚本树生成 P2TR 地址
- Commit 阶段:向该地址发送 BTC(创建 UTXO)
- Reveal 阶段:花费该 UTXO,将铭文数据写入区块链
2.2 核心概念:Witness Script
Witness Script 包含两部分:
- 签名验证:确保只有密钥持有者可以花费
- 铭文数据:使用 OP_FALSE + OP_IF 创建的数据信封(Envelope),存储 BRC20 JSON 数据
三、代码实现详解
3.1 步骤一:生成密钥和构建铭文脚本
// 1. 生成 P2TR 格式的公钥(32字节,去掉前缀)
const tweakedPublicKey = toXOnly(keypair.publicKey)
// 2. 定义 BRC20 铭文内容(JSON 格式)
const json = `{ "p": "brc-20", "op": "mint", "tick": "cccc", "amt": "100" }`;
// 3. 构建铭文的 witness script
const inscriptionWitnessScript = bitcoin.script.compile([
// 第一部分:签名验证(真正的解锁条件)
tweakedPublicKey,
opcodes.OP_CHECKSIG, // 验证签名是否与公钥匹配
// 第二部分:数据信封(Envelope),用于存储铭文数据
opcodes.OP_FALSE, // 标记开始,使内容可被剪枝(不影响脚本执行)
opcodes.OP_IF, // 条件语句(永远不会执行,因为前面是 OP_FALSE)
opPush("ord"), // 协议标识:ordinal inscription
1, // 字段分隔符
1, // 字段分隔符
opPush("text/plain;charset=utf-8"), // 内容类型
opcodes.OP_0, // 字段分隔符
opPush(json), // 实际的铭文内容(BRC20 JSON)
bitcoin.opcodes.OP_ENDIF // 结束数据信封
]);
// 4. 构建备用恢复脚本(可选)
const recover_witness_script = bitcoin.script.compile([
tweakedPublicKey,
bitcoin.opcodes.OP_CHECKSIG
]);
关键点说明:
- OP_CHECKSIG:这是真正的解锁条件,验证签名
- OP_FALSE + OP_IF:创建一个永远不会执行的代码块,用于存储数据
- 数据信封内容:包含协议标识(ord)、媒体类型、铭文数据
3.2 步骤二:构建 Taproot 脚本树和 P2TR 地址
// 5. 构建 Tap Tree(包含多个可选的花费路径)
const scriptTree: Taptree = [
{ output: inscriptionWitnessScript }, // 路径1:铭文脚本
{ output: recover_witness_script } // 路径2:恢复脚本(备用)
];
// 6. 配置赎回脚本
const redeemScript = {
output: inscriptionWitnessScript,
redeemVersion: 192 // Taproot 版本号
}
// 7. 生成 P2TR 支付对象(包含铭文的 P2TR 交易)
const inscriptionPayment = bitcoin.payments.p2tr({
internalPubkey: tweakedPublicKey, // 内部公钥
network: network, // 网络类型(主网/测试网)
scriptTree: scriptTree, // Taproot 脚本树
redeem: redeemScript, // 赎回脚本配置
});
// 8. 获取 Commit 地址(向此地址发送 BTC,完成 Commit 阶段)
const commitAndRevealAddress = inscriptionPayment.address;
console.log(`Commit 地址 = `, commitAndRevealAddress)
流程说明:
- 构建了一个包含两个路径的脚本树
- 生成 P2TR 地址
- 向该地址发送 BTC,创建包含铭文的 UTXO(Commit 阶段)
3.3 步骤三:Reveal 铭文(花费 P2TR UTXO)
// 9. 创建 PSBT(Partially Signed Bitcoin Transaction,部分签名交易)
const psbt = new Psbt({ network });
// 10. 配置 Tap Leaf Script(用于解锁 P2TR)
const tapLeafScript = {
leafVersion: 192, // Taproot 版本
script: inscriptionWitnessScript, // 使用的脚本
controlBlock: inscriptionPayment.witness![inscriptionPayment.witness!.length - 1] // 控制块(Merkle 证明)
};
// 11. 添加输入(花费 Commit 阶段创建的 UTXO)
psbt.addInput({
hash: utxos[utxos.length - 1].txid, // 交易哈希
index: utxos[utxos.length - 1].vout, // 输出索引
tapInternalKey: tweakedPublicKey, // Taproot 内部密钥
witnessUtxo: {
value: utxos[utxos.length - 1].value, // UTXO 金额
script: inscriptionPayment.output! // 锁定脚本
},
tapLeafScript: [tapLeafScript] // Taproot 叶子脚本
});
// 12. 添加输出(定义资金去向)
psbt.addOutputs([
{
// 输出1:铭文接收地址(将铭文 Reveal 到此地址)
address: "tb1plf84y3ak54k6m3kr9rzka9skynkn5mhfjmaenn70epdzamtgpadqu8uxx9",
value: 1000
},
{
// 输出2:找零地址
address: "tb1pjjq4snuntgja3ggyluncdlkvhxw26gm8pkfgjc8jvhh3asyaj6as4uctjg",
value: utxos[utxos.length - 1].value - 1000 - 1000 // 扣除铭文输出和矿工费
}
]);
// 13. 签名交易
psbt.signInput(0, keypair);
// 14. 最终化所有输入(完成签名验证)
psbt.finalizeAllInputs();
// 15. 提取交易数据(十六进制格式)
const tx = psbt.extractTransaction().toHex();
console.log(`广播交易 Hex: ${tx}`);
// 16. 广播交易到比特币网络
const txid = await broadcast(tx);
console.log(`成功!交易 ID: ${txid}`);
Reveal 阶段核心要点:
- tapLeafScript:包含脚本和 Merkle 证明(controlBlock)
- 签名验证:通过 OP_CHECKSIG 验证
- 数据上链:铭文数据通过 witness 数据写入区块链
- 输出分配:将铭文绑定到目标地址,并处理找零
四、实践案例
4.1 完整的铭文部署示例
以下是一个完整的 BRC20 铭文部署(Deploy)交易示例:
铭文详情页面:
testnet.unisat.io/brc20/coda
Commit 交易地址:
mempool.space/testnet/add…
交易结构:
一个 Deploy 铭文需要两笔交易才能完成:
- Commit 交易:向 P2TR 地址发送 BTC
- Reveal 交易:花费 UTXO,将铭文数据写入区块链
4.2 关键技术点总结
| 阶段 | 作用 | 关键操作 |
|---|---|---|
| Commit | 准备铭文 | 生成 P2TR 地址,发送 BTC 创建 UTXO |
| Reveal | 公开铭文 | 花费 UTXO,铭文数据通过 witness 上链 |
数据存储机制:
- 铭文数据存储在 witness script 中
- 利用 OP_FALSE + OP_IF 创建数据信封,确保数据不影响脚本执行
- 数据可被剪枝,但仍保留在区块链完整节点中
五、开发资源
5.1 代码仓库
项目地址: github.com/6gunner/ord…
快速开始:
# 运行 BRC20 完整示例
cd examples/unisat-web3-demo
npm install
npm run dev
配合 Unisat 钱包插件,可以完整体验 BRC20 铭文的 Deploy、Mint、Transfer 全流程。
5.2 参考资料
-
Taproot 技术详解: More on Taproot
-
实战指南: A Guide to creating TapRoot Scripts with bitcoinjs-lib
六、总结
BRC20 铭文的构建本质上是利用比特币的 Taproot 升级,通过巧妙的脚本设计将数据嵌入到 witness 中。核心要点包括:
- 技术基础:基于 P2TR 交易类型和 Taproot 脚本树
- 两阶段模型:Commit(准备)+ Reveal(公开)
- 数据信封:使用 OP_FALSE + OP_IF 创建不影响执行的数据块
- 安全机制:通过 OP_CHECKSIG 确保只有密钥持有者可以操作
理解这些原理后,你可以构建自己的铭文应用,或深入研究 Ordinals 协议的更多可能性。