如何进行brc20铭文的创建

2,698 阅读6分钟

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(见证脚本)。

img

解锁机制:
要花费 P2TR 地址上的比特币,需要提供一份有效的 Merkle 证明,证明你使用的 witness script 是脚本树中的合法路径。如下图所示,要使用某个脚本(如 Banana),需要提供从该脚本到 Merkle Root 的完整路径证明,只要能计算出正确的 Merkle Root Hash,就能解锁资金。

img

二、铭文构建流程

BRC20 铭文的创建采用 Commit-Reveal 两阶段模式:

image-20240106205811015

2.1 整体流程

  1. 生成密钥对:随机生成一个 BTC 私钥
  2. 转换为 P2TR 格式:将私钥转换为符合 P2TR 格式的公钥
  3. 构建铭文脚本:创建包含铭文数据的 witness script
  4. 生成 P2TR 地址:基于脚本树生成 P2TR 地址
  5. Commit 阶段:向该地址发送 BTC(创建 UTXO)
  6. 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)

流程说明:

  1. 构建了一个包含两个路径的脚本树
  2. 生成 P2TR 地址
  3. 向该地址发送 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 阶段核心要点:

  1. tapLeafScript:包含脚本和 Merkle 证明(controlBlock)
  2. 签名验证:通过 OP_CHECKSIG 验证
  3. 数据上链:铭文数据通过 witness 数据写入区块链
  4. 输出分配:将铭文绑定到目标地址,并处理找零

四、实践案例

4.1 完整的铭文部署示例

以下是一个完整的 BRC20 铭文部署(Deploy)交易示例:

铭文详情页面:
testnet.unisat.io/brc20/coda

Commit 交易地址:
mempool.space/testnet/add…

交易结构:
一个 Deploy 铭文需要两笔交易才能完成:

  1. Commit 交易:向 P2TR 地址发送 BTC
  2. Reveal 交易:花费 UTXO,将铭文数据写入区块链

image-20240102113604625

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 铭文的 DeployMintTransfer 全流程。

5.2 参考资料

  1. 深度解析: 看完這篇,你對於 Ordinals 銘文的了解將超過 99% 的人

  2. Taproot 技术详解: More on Taproot

  3. 实战指南: A Guide to creating TapRoot Scripts with bitcoinjs-lib

六、总结

BRC20 铭文的构建本质上是利用比特币的 Taproot 升级,通过巧妙的脚本设计将数据嵌入到 witness 中。核心要点包括:

  1. 技术基础:基于 P2TR 交易类型和 Taproot 脚本树
  2. 两阶段模型:Commit(准备)+ Reveal(公开)
  3. 数据信封:使用 OP_FALSE + OP_IF 创建不影响执行的数据块
  4. 安全机制:通过 OP_CHECKSIG 确保只有密钥持有者可以操作

理解这些原理后,你可以构建自己的铭文应用,或深入研究 Ordinals 协议的更多可能性。