Skip to main content

Tapret

Applies to both RGB lines

Both lines use the same tapret construction, but with a different 29-byte script prefix, so a tapret commitment from one line does not verify under the other. See Two RGB lines.

Tapret hides the RGB commitment inside the script tree of a taproot (P2TR) output. On chain the output looks like any other taproot output, and no extra output is needed. It is one of the two deterministic Bitcoin commitment schemes. The other is opret.

The commitment only counts if the P2TR output is the first OP_RETURN-or-P2TR output of the witness transaction (first-output rule). A transaction carries at most one tapret commitment. Several contracts share it through MPC.

The leaf scriptโ€‹

The commitment is a tapscript leaf of exactly 64 bytes:

<29-byte prefix> OP_RETURN OP_PUSHBYTES_33 <mpc::Commitment> <nonce>
29 bytes 1 byte 1 byte (0x21) 32 bytes 1 byte

The prefix is the one byte that differs between the lines:

29 ร— OP_RESERVED (0x50), then 6a 21.

Source: rgb-consensus 0.11.1 src/dbc/tapret/tapscript.rs, TAPRET_SCRIPT_COMMITMENT_PREFIX. The docs.rgb.info tapret page shows the same layout.

Consensus difference

The prefix is part of the leaf hash, and so of the output key. A wallet or verifier from one line computes a different taproot key from the same commitment than the other line does. The two lines' tapret commitments are not interchangeable. Opret commitments and MPC trees are byte-identical in both lines.

The leaf is never meant to be spent: execution would reach OP_RETURN and fail. Its only job is to be hashed into the taproot tree.

Where the leaf goesโ€‹

Taproot (BIP 341) builds the output key Q from an internal key P and an optional script tree:

Q = P + tH_TapTweak(P || script_root) ยท G

tH_TapTweak is a BIP 340 tagged hash, and branch hashes (TapBranch) sort their two children lexicographically. RGB adds one rule on top: the tapret leaf sits at depth 1, as a direct child of the root. Any script tree the wallet already had becomes the other child.

CaseScript tree beforeTree afterWhat the proof must reveal
No script pathnonethe tapret leaf is the whole treeonly P
Commitment ends up on the rightroot RTapBranch(R, T) with R < TP and the hash of R
Commitment on the left, R is a leafleaf CTapBranch(T, C)P and the script of C
Commitment on the left, R is a branchbranch (X, Y)TapBranch(T, R)P and the hashes of X and Y

Revealing the right-hand partner shows that it can't hide a second commitment at depth 1. A leaf is shown as its script. A branch is shown as two child hashes, and branch and leaf hashes use different tags, so a branch can't pose as a 64-byte leaf.

The nonce. The last byte of the leaf can be changed freely. Wallets "mine" it so the commitment hash T sorts to the right of R. Then the proof needs only R's hash, and the scripts under R stay private.

This section follows the docs.rgb.info tapret page, which has full diagrams of each case.

The proofโ€‹

The same structure appears in both lines (bp-core 0.12.0 dbc/src/tapret/mod.rs; rgb-consensus 0.11.1 src/dbc/tapret/mod.rs):

pub struct TapretProof {
pub path_proof: TapretPathProof, // { partner_node: Option<TapretNodePartner>, nonce: u8 }
pub internal_pk: InternalPk,
}

pub enum TapretNodePartner {
LeftNode(TapNodeHash), // commitment is on the right
RightLeaf(LeafScript), // the old tree was a single leaf
RightBranch(TapretRightBranch), // the old tree was a branch
}

The verifier rebuilds the leaf from the MPC commitment and the nonce. It combines that leaf with the partner (if any), tweaks internal_pk, and checks that the result equals the output key of the first P2TR output. No output index is needed, because the first-output rule picks the output.

Spending a tapret outputโ€‹

Back up the tapret tweak

A tapret output's key is P tweaked by a script tree only your RGB wallet knows. To spend the bitcoin later, the signer needs that tweak: the commitment and nonce, or the full TapretProof. A generic taproot wallet, hardware wallet or Bitcoin Core descriptor wallet that has only your seed cannot produce the signature. If you lose the RGB wallet data, the BTC in that output is unspendable, and so are the RGB assets assigned to it.

  • Line B: rgb taprets lists the tweaks a wallet knows. Back up the RGB data directory, not just the seed.
  • Line A: wallets made with rgb create --tapret-key-only keep the tweaks in the RGB data directory. Back it up the same way.
# Line B (rgb-cmd 0.11.1): list known tapret tweaks for a wallet
rgb taprets --wallet <NAME>

See the CLI reference (v0.11) and the CLI reference (v0.12) for the wallet commands of each line.

Further readingโ€‹