Beersy
BRC-107

Enhanced Mandala Token Protocol

A minimal token protocol leaves amounts as plain numbers, which anyone in the chain could quietly alter. This adds a cryptographic so tampering is detectable, without abandoning the minimal design.

Jake Jones5 min read
assetId+amountprevTxidcommitmenthash

Summary

Why
Lightweight wallets have no way to independently confirm that a token transfer preserves the correct total amount without trusting an .
What
BRC-107 is an extension to the Mandala Token Protocol (BRC-92) that adds a cryptographic commitment hash to each token output so its amount and history can be verified without a full node or overlay.
How
A wallet computes a SHA-256 hash of the asset ID, amount, previous transaction ID, and an optional nonce, embeds it in the output alongside the existing BRC-92 fields, and sends it with a (SPV) proof so the recipient can recompute the hash and check that input and output totals match.

What this lets you do

  • Verify a token amount hasn't been tampered with using only transaction data
  • Check that input and output token amounts still balance without an overlay network
  • Accept token payments in an SPV wallet with a sub-100ms local check
  • Add privacy to token transfers with an optional nonce to prevent amount linking
  • Keep old BRC-92 tokens working unchanged alongside commitment-enabled ones

Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.

Reference for an AI

Everything an assistant needs to answer questions about BRC-107 accurately, including what it depends on.

The specification

Abstract

This proposal extends BRC-92 (Mandala Token Protocol) with cryptographic to provide tamper-evident token amounts and SPV-friendly verification while maintaining the minimalist design philosophy. The enhancement adds a commitment hash to each token output that cryptographically binds the token amount to its transaction history, enabling lightweight clients to verify token integrity without accessing the full blockchain or trusting .

Motivation

The original BRC-92 Mandala Token Protocol provides a minimalist approach to tokenization on BSV, but relies entirely on overlay networks to validate token conservation rules. In real-world usage scenarios, particularly wallets and point-of-sale transactions, users need cryptographic assurance that token amounts haven't been tampered with. This enhancement addresses these limitations while preserving the simplicity that makes BRC-92 attractive.

Key problems this solves:

  • SPV wallets cannot verify token conservation without trusting overlays
  • No cryptographic proof linking token amounts to their history
  • Potential for amount tampering between transaction creation and overlay submission
  • Lack of standardized verification protocol for lightweight clients

Specification

Enhanced Token Output Format

Building upon BRC-92's structure, we add a cryptographic commitment field:

Fungible Token Output

21 <assetId> <amount> <commitment> OP_2DROP OP_2DROP OP_DROP ...

Where:

  • 21 (0x21): UTF-8 exclamation mark prefix (unchanged from BRC-92)
  • assetId: Genesis transaction (txid:vout) (unchanged)
  • amount: Token amount in Bitcoin number format (unchanged)
  • commitment: NEW - Cryptographic commitment hash
  • ...: Functional (e.g., ) (unchanged)

Commitment Construction

The commitment is calculated as:

commitment = H(assetId || amount || prevTxid || nonce)

Where:

  • H: SHA-256 hash function
  • ||: Concatenation operator
  • prevTxid: Transaction ID of the input being spent
  • nonce: Optional 32-byte random value for privacy

NFT Token Output

21 <assetId> <commitment> OP_2DROP OP_DROP ...

For NFTs, the commitment is:

commitment = H(assetId || prevTxid || metadata_hash)

SPV Verification Protocol

When transferring tokens in an SPV context, the sender provides:

{
  "transaction": "hex_encoded_transaction",
  "tokenProofs": {
    "inputs": [
      {
        "index": 0,
        "amount": 100,
        "commitment": "abc123...",
        "prevTx": "def456...",
        "merkleProof": "..."
      }
    ],
    "outputs": [
      {
        "index": 0,
        "amount": 60,
        "commitment": "ghi789..."
      },
      {
        "index": 1,
        "amount": 40,
        "commitment": "jkl012..."
      }
    ],
    "conservationProof": {
      "totalIn": 100,
      "totalOut": 100
    }
  }
}

Verification Steps

Recipients MUST perform the following verification:

  1. Commitment Verification: For each input and output, verify:

    commitment == H(assetId || amount || prevTxid || nonce)
    
  2. Conservation Check: Verify that:

    sum(input_amounts) == sum(output_amounts)
    
  3. Validation: Verify SPV proofs for recent transactions

  4. Accept/Reject: Transaction is valid if all checks pass

Backward Compatibility

This enhancement maintains full backward compatibility with BRC-92:

  • Existing BRC-92 tokens continue to function
  • Overlays that don't recognize commitments can ignore them (treated as extra data)
  • The drop pattern ensures scripts execute identically
  • Migration path: New tokens use commitments, old tokens grandfathered

Privacy Considerations

The commitment includes an optional nonce field to prevent amount analysis:

  • Without nonce: Same amounts produce same commitments (linkable)
  • With nonce: Same amounts produce different commitments (unlinkable)

Design Justification

Why Commitments Instead of Script Enforcement?

Bitcoin Script's execution model prevents cross-input/output verification within scripts. Cryptographic commitments provide the next best solution:

  • Tamper-evident: Can't change amounts without breaking commitments
  • SPV-compatible: Verifiable with just transaction data
  • Minimalist: Adds only one hash field
  • Overlay-independent: Cryptographic proof doesn't require trust

Why Include prevTxid?

Including the previous transaction ID in the commitment:

  • Creates an unforgeable chain of custody
  • Prevents replay attacks with old commitments
  • Links each token to its complete history
  • Enables proof of lineage back to genesis

Why Optional Nonce?

The nonce field balances transparency and privacy:

  • Public tokens (securities): No nonce for full transparency
  • Private tokens (cash-like): Nonce prevents amount correlation
  • User choice: Applications decide based on use case

Example Transactions

Token Transfer with Commitments

Input (100 tokens from previous tx):

Previous output:
21 <assetId> <100> <H(assetId||100||prev_prev_txid||nonce)> OP_2DROP OP_2DROP OP_DROP

Outputs:

Output 0 (60 tokens to Bob):
21 <assetId> <60> <H(assetId||60||current_input_txid||nonce1)> OP_2DROP OP_2DROP OP_DROP P2PKH(Bob)

Output 1 (40 tokens change to Alice):
21 <assetId> <40> <H(assetId||40||current_input_txid||nonce2)> OP_2DROP OP_2DROP OP_DROP P2PKH(Alice)

SPV Verification Example

Bob receives a payment at a coffee shop:

  1. Alice sends: Transaction + commitment proofs + merkle proof
  2. Bob's wallet verifies (< 100ms):
    • Commitment: H(assetId||30||prevTxid||nonce) == provided_commitment
    • Conservation: 50 in == 30 + 20 out
    • Merkle proof: Transaction exists in blockchain ✓
  3. Bob accepts: Payment verified without blockchain access

Implementation Considerations

Wallet Integration

Wallets implementing this standard should:

  1. Generate commitments when creating token transactions
  2. Store nonces for privacy-enabled tokens
  3. Verify commitments before accepting tokens
  4. Provide SPV proof packages to recipients

Overlay Network Integration

Overlay networks can:

  1. Reject transactions with invalid commitments
  2. Use commitments for faster validation
  3. Provide commitment verification as a service
  4. Index tokens by commitment for quick lookups

Performance Impact

  • Additional data: 32 bytes per output (commitment)
  • Computation: One SHA-256 hash per input/output
  • Verification time: < 1ms per token on modern devices
  • Storage: Negligible increase (< 5% for typical token transactions)

Security Considerations

Commitment Forgery

Forging a commitment requires finding a hash collision:

  • SHA-256 preimage resistance: 2^256 operations
  • Collision resistance: 2^128 operations
  • Practically impossible with current technology

Replay Attacks

Including prevTxid prevents replay:

  • Old commitments won't match new transactions
  • Each commitment is unique to its transaction chain

Amount Tampering

Changing amounts breaks commitments:

  • Detectable by any verifier
  • Rejected by overlays and recipients

Migration Path

  1. Phase 1: Wallets add commitment generation (optional)
  2. Phase 2: Overlays prefer commitment-enabled tokens
  3. Phase 3: Recipients require commitments for new tokens
  4. Phase 4: Full ecosystem adoption

References

  • BRC-92: Mandala Token Protocol
  • BRC-62: (BEEF) Transactions
  • BRC-67: Simplified Payment Verification

Test Vectors

Commitment Calculation

Input:

assetId = "abc...def:0"
amount = 100
prevTxid = "123...456"
nonce = "000...000"

Output:

commitment = SHA256("abc...def:0" || 100 || "123...456" || "000...000")
           = "a7b8c9d0e1f2..."

Conservation Verification

Valid (conserves tokens):

Inputs: [50, 30, 20] (sum = 100)
Outputs: [60, 40] (sum = 100)
Result: VALID ✓

Invalid (creates tokens):

Inputs: [50, 30] (sum = 80)
Outputs: [60, 40] (sum = 100)
Result: INVALID ✗

Implementations

Reference implementations available at:

  • TypeScript: Coming Soon
  • Go: Coming Soon
  • Python: Coming Soon
Was this helpful?

Search Beersy

Search standards by number, title, author or topic