Enhanced Mandala Token Protocol

Jake Jones ([email protected])

Abstract

This proposal extends BRC-92 (Mandala Token Protocol) with cryptographic commitments 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 overlay networks.

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 SPV 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 outpoint (txid:vout) (unchanged)

  • amount: Token amount in Bitcoin number format (unchanged)

  • commitment: NEW - Cryptographic commitment hash

  • ...: Functional locking script (e.g., P2PKH) (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. Merkle Proof 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: Background Evaluation Extended Format (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

Last updated

Was this helpful?