Confidential Transactions

Thanks @Bastian for sharing this progress, which started as exploring Silent Reusable Payment Addresses (SRPA) and now it has evolved into a full ZKP privacy system on BCH, covering both stealth identity and confidential transactions. That’s a massive scope expansion. BCH gets Monero-level privacy, but with an auditable supply, all enforced natively via CashVM without compromising chain transparency :fire: @bitjson is also exploring​​​​​​​​​​​​​​​​ zk prover.


Source

It seems Triton VM would be the closest candidate to power the proof verification layer for confidential transactions on BCH .​​​​​​​​​​​​​​​​

2 Likes

stealth change looking good now

Legend
  Base P2PKH      = wallet’s long-lived transparent identity address
  RPA(paycode)    = paycode-derived one-time P2PKH (receiver one-time address)
  Change(Self)    = stealth change output derived from sender’s OWN paycode (also one-time)
  [txid:vout]     = output reference
  addr(...)       = cashaddr shown on-chain

──────────────────────────────────────────────────────────────────────────────
ACTORS (IDENTITIES)
──────────────────────────────────────────────────────────────────────────────

Alice
  Base identity (transparent, long-lived):
    addr(bchtest:qzfjtjffx5l0vaz063lrc3hqghrc06h6h5z8xmaysg)
  Paycode identity:
    PM8TJKNaaaF7Wkg6uXr412Pee7iGtJa22shUBAKSfo2hKtcmPpcC4j4euPaAJJoQzafiFZeD712FVXFWTVwFuxJYi7vZCobUDc38rhZ62F6WMR9PZe9K

Bob
  Base identity (transparent, long-lived):
    addr(bchtest:qr29cg3xsyq4fne2f6ahdkel9wj66xzzh56c4t8ntm)
  Paycode identity:
    PM8TJR5zAr6B67JpKfL7Z3o1PcsQaNJpZgaWUjENzEXKEUgoX5F4tFwwEXUksSRfuadTQ9cfbUiwa1r3ZiXnyk2YnhNJSk5FSKDxqkiep7n9iUDzBbR5

──────────────────────────────────────────────────────────────────────────────
FLOW MAP (Chipnet) — WITH BASE IDENTITIES INCLUDED
──────────────────────────────────────────────────────────────────────────────

Alice (Base P2PKH)                                               Bob (Base P2PKH)
┌───────────────────────────────────────────────┐                ┌───────────────────────────────────────────────┐
│ Base addr (stable):                           │                │ Base addr (stable):                           │
│   bchtest:qzfjtjffx5l0vaz063lrc3hqghrc06h6…   │                │   bchtest:qr29cg3xsyq4fne2f6ahdkel9wj66x…     │
│ Paycode (derives one-time RPAs):              │                │ Paycode (derives one-time RPAs):              │
│   PM8TJKNaaaF7Wkg6uXr412P…                    │                │   PM8TJR5zAr6B67JpKfL7Z3…                     │
└───────────────────────────────┬───────────────┘                └───────────────────────────────┬───────────────┘
                                │                                                       │
                                │ 1) Alice pays Bob via Bob PAYCODE (RPA destination)   │
                                │                                                       │
                                ▼                                                       ▼
TX d5af7f2a…66d8  https://chipnet.chaingraph.cash/tx/d5af7f2ad12fdd5a87e36e2ad0bccf1fbb3dbcafacf8bbd5506923b20a4a66d8
┌───────────────────────────────────────────────────────────────────────────────┐
│ Input anchor (spent): 171f8516…f1f4:1                                         │
│                                                                               │
│ Outputs                                                                       │
│  [d5af…:0] Payment → Bob  RPA(Bob paycode)                                    │
│            addr(bchtest:qquw3tr59mu3pl4ydq0mveuvyum50jfjyykpcrepdc)           │
│            hash160=38e8ac742ef910fea4681fb6678c273747c93221                   │
│                                                                               │
│  [d5af…:1] Change → Alice Change(Self)=RPA(Alice paycode)                     │
│            addr(bchtest:qqm79cqzvrux6npyz3lqw90ehh9g8ztxpcyf285l6n)           │
│            hash160=37e2e00260f86d4c24147e0715f9bdca8389660e                   │
└───────────────────────────────────────────────────────────────────────────────┘
                                │                                                       │
                                │ 2) Bob imports into pool (optional step in this map)  │
                                │                                                       ▼
TX 75fb04b3…9c45  https://chipnet.chaingraph.cash/tx/75fb04b38b15bce930e2eda41e8e7423913cc86e58657425e3f7605f6f099c45
┌───────────────────────────────────────────────────────────────────────────────┐
│ Pool import: converts RPA UTXO into pool state output(s) (cashTokens covenant) │
└───────────────────────────────────────────────────────────────────────────────┘
                                │                                                       │
                                │ 3) Bob withdraws from pool → pays Alice (RPA)         │
                                │    + stealth change back to Bob (RPA)                 │
                                ▼                                                       ▼
TX c102dd4a…8e66  https://chipnet.chaingraph.cash/tx/c102dd4acbfe4c439ffa8725374b891512cd21428c441a854acdf5d809308e66
┌───────────────────────────────────────────────────────────────────────────────┐
│ Outputs                                                                       │
│  [c102…:1] Payment → Alice  RPA(Alice paycode)                                │
│            addr(bchtest:qzlvttunuy8dmnq7yn5qwezyv29j664n5qq4gcf9gt)           │
│            hash160=bec5af93e10eddcc1e24e8076444628b2d6ab3a0                   │
│                                                                               │
│  [c102…:2] Change → Bob   Change(Self)=RPA(Bob paycode)                       │
│            addr(bchtest:qqeglnnz8246nem7x88n2pzfap8a7qv5hc9d23m7pl)           │
│            hash160=328fce623aaba9e77e31cf350449e84fdf0194be                   │
└───────────────────────────────────────────────────────────────────────────────┘

──────────────────────────────────────────────────────────────────────────────
NO-REUSE SUMMARY (BASE vs RPA vs CHANGE)
──────────────────────────────────────────────────────────────────────────────

Stable base identities (can be reused; that’s the point of “base”):
  Alice base: bchtest:qzfjtjffx5l0vaz063lrc3hqghrc06h6h5z8xmaysg
  Bob   base: bchtest:qr29cg3xsyq4fne2f6ahdkel9wj66xzzh56c4t8ntm

One-time addresses (must NOT be reused; and they aren’t here):
  Bob receive from Alice (RPA/Bob paycode):
    d5af…:0  bchtest:qquw3tr…   (h160 38e8ac…)
  Alice stealth change (Change(Self)=RPA/Alice paycode):
    d5af…:1  bchtest:qqm79cq…   (h160 37e2e0…)
  Alice receive from Bob (RPA/Alice paycode):
    c102…:1  bchtest:qzlvtt…    (h160 bec5af…)
  Bob stealth change (Change(Self)=RPA/Bob paycode):
    c102…:2  bchtest:qqegln…    (h160 328fce…)

Key point:
  • Base addresses are stable identifiers.
  • Every payment address and every change address in this flow is paycode-derived and unique.
  • So observers never see Bob’s base address receive the payment, and they never see Alice’s base address receive change.
4 Likes

initial wireframe coming along, working on multi profile and integrating cli commands with each send button

3 Likes

I’m excited to publicly release a demo cli and gui for rpa tx and the beginning foundation of a sharded state pool, that sets the stage for further privacy development with zkp in future phase

3 Likes

Cash-Like Privacy on Bitcoin Cash

Bitcoin Cash is good at moving value cheaply and directly, but ordinary BCH payments still reveal too much. In most cases, the chain can expose who paid, who received, and how much was sent. That is not how cash works.

The project I’m building is aimed at changing that.

The goal is not just to make BCH payments a little harder to follow. The goal is to build a private payment path that shields both identity and amount while keeping the system self-custodied, enforced by the chain, and usable without trusting a coordinator as part of the base model.

At a high level, the design works like this: the public BCH transaction does not reveal the real amount being transferred. The visible on-chain BCH amount is only the fee required to move the private payment system forward. The real private value is carried inside protected protocol state rather than exposed directly in the visible transaction amount.

That is the privacy model this work is building toward.

The challenge this work is answering

A useful way to understand this project is through a public challenge @bitjson raised late last year: if BCH privacy is going to matter, it should not settle for a privacy-themed wrapper. It should aim for a much harder combination instead — actually zero-knowledge, post-quantum in direction, and compact enough to matter in practice, ideally under 100KB for one-off proofs.

First challenge post:
https://x.com/bitjson/status/1995873869077332056

This project is best understood as one attempt to answer that public challenge on BCH: build a private payment path that is actually zero-knowledge in direction, compact enough to matter, enforced on-chain, and strong enough to support a later optional aggregation market rather than depending on one from the start.

That challenge also aligns with broader public BCH work around more compact covenants, reusable contract factoring, and support for non-trivial cryptographic systems, including zero-knowledge and post-quantum designs. In other words, this is not a random detour. It fits a broader BCH design conversation that is already happening in public.

What this project is building

The current direction is a privacy protocol for BCH where the base path is self-sovereign and direct.

That matters because I do not think BCH privacy should begin with an aggregator as the trust base. Aggregation can still be extremely valuable later. In fact, I think a competitive aggregation market is one of the most interesting future directions for BCH privacy. But the base path should work without making a batching service or coordinator part of the protocol’s core authority.

So the current design starts from the simpler question:

Can BCH support a private payment path where a user can create the private activity themselves, prove what needs to be proved off-chain, and rely on the chain itself to verify and enforce the important transition rules on-chain?

That is the role of the current direct-spend path. It is the base layer first. Aggregation is deferred and treated as an optional later service layer rather than part of the current trust base.

The technical direction in plain language

At a high level, this project is building toward five properties that rarely appear together.

First, actual zero-knowledge direction rather than a system that still leaks too much public meaning.

Second, succinct proofs, because a private system that only works with huge proofs or heavy wallet assumptions is much less useful in practice.

Third, off-chain proving. The expensive proving work should happen outside the chain, where wallets and services can choose how to generate it.

Fourth, on-chain verification. BCH itself should enforce the important rules rather than outsourcing trust to an off-chain party.

Fifth, a post-quantum direction. Ordinary blockchain payments depend heavily on exposed signing-key meaning. This project is moving the meaningful authorization and consistency checks toward a proof-based path that is better aligned with longer-term quantum resilience.

This is also why the compact commitment format matters. A major part of the work is moving the live payment path onto a compact 128-byte commitment carrier. In simple terms, that gives the chain a compact way to carry forward the protected payment state without using the visible BCH amount to reveal the real private transfer amount.

Why BCH is an interesting place to build this

This is not just a generic privacy idea looking for a home.

Bitcoin Cash is an especially interesting place to build this because public BCH design discussions are already moving in the same direction: smaller and more efficient covenants, reusable contract factoring, and better support for non-trivial cryptographic constructions like zero-knowledge and post-quantum systems.

This also aligns with an important practical part of the current work: moving the live payment path onto a compact 128-byte token commitment. In simple terms, that gives BCH a compact on-chain carrier for protected payment state, allowing the system to move private value forward without exposing the real payment amount in the visible BCH transaction amount.

What is already true, and what is not

This project is not yet claiming a finished privacy system.

The current work is best described as a real private-payment base path under active R&D. It is already being developed and validated on Chipnet, and the current effort is about carrying it forward into something that people can run, inspect, and continue advancing toward Mainnet. But this is not yet a broad final claim of a complete deployed privacy system, and it is not yet the later aggregation-market phase.

That truth boundary matters.

This is also why I’m focusing first on a reference wallet and CLI, clear receiver identity surfaces, transparent bootstrap funding only where necessary, and live on-chain validation of the intended path. The job right now is to make the base path real and auditable, not to pretend the full end state already exists.

Why this matters

If BCH privacy is ever going to become more than a niche demo, it needs a real protocol path underneath it.

That path should not just hide the social graph a little better. It should aim to hide both identity and amount. It should be practical enough to use, compact enough to fit BCH constraints, and honest enough to state what is already true versus what is still future work.

That is the direction here.

So this post is the first in a short series leading up to May 15. The goal is to explain, in public and in plain language, what is being built, why BCH is a serious place to build it, and how this work is answering a harder public challenge: bringing cash-like privacy to Bitcoin Cash without giving up self-custody, on-chain enforceability, or the possibility of a later open market for privacy services built on top of something real.

Next post: why this work starts with direct spend first, and treats aggregation as a later optional layer rather than the trust base.

3 Likes

Cash-Like Privacy on Bitcoin Cash: First Explicit Packet-Plane Milestone

TL;DR

A live Chipnet transaction has accepted the first on-chain private-payment packet layout for this BCH confidential transaction protocol.

Txid:

https://chipnet.chaingraph.cash/tx/1fb716d7640fe821589a12389ebf4e2f9ff3d507a0081524f929ea3549054950

The important part: the intended private payment amount was 9,987,000 sats, but the public chain does not show a visible 9,987,000 sat recipient payment. It also does not show an ordinary visible BCH change output.

Instead, the chain shows:

  • one Plane A private state continuation output
  • twelve Plane B recipient recovery packet outputs
  • sender change retained inside the Plane A private state continuation output
  • no ordinary visible BCH change output
  • no fallback to the earlier compact carrier path

This does not mean the full privacy system is finished. It does not yet claim full end-to-end post-quantum privacy, final wallet recovery, or proof-bearing covenant enforcement.

But it is a real on-chain milestone: the intended private-payment layout can now land on Chipnet without falling back to ordinary visible change or the earlier compact carrier path.


What happened

The accepted transaction has 13 outputs:

  • output 0: Plane A private state continuation output
  • outputs 1 through 12: Plane B recipient recovery packet outputs
  • recipient packet profile: ml-kem-768-12x128
  • sender change retained inside the Plane A private state continuation output
  • no ordinary visible BCH change output
  • no fallback to the earlier compact carrier path

The transaction was accepted on Chipnet with a size of 2400 bytes and a 10,000 sat fee.

That matters because the public transaction does not look like an ordinary payment where the recipient amount is visible as a normal BCH output.

What Plane A and Plane B mean

The easiest way to understand the transaction is to split it into two roles.

Plane A is the private state continuation output. In this milestone transaction, output 0 is Plane A. It carries the next private protocol state and retains sender change, avoiding an ordinary visible BCH change output. This is the part of the transaction that keeps the private payment system moving forward without exposing the sender’s remaining value as conventional public change.

Plane B is the recipient recovery packet set. In this milestone transaction, outputs 1 through 12 are Plane B. These outputs carry the fixed ML-KEM-era recovery packet material the recipient wallet will later use to discover and recover the private payment.

So the public transaction does not have the usual structure:

“recipient payment output plus sender change output.”

Instead, it has:

“one private state continuation output plus a fixed recipient recovery packet set.”

That distinction is important. Plane A keeps the state transition moving forward. Plane B gives the recipient a packet set to recover against with wallet secrets. Public observers can see the layout, token commitments, and BCH values, but they do not see a normal visible recipient payment output or an ordinary visible BCH change output.

The accepted transaction demonstrates the on-chain packet layout. Final receiver discovery, recovery, and wallet reconciliation remain next engineering work.

Public value vs private value

The public chain sees this arithmetic:

20,000,000 sats input = 19,978,000 sats Plane A + 12,000 sats recovery packet outputs + 10,000 sats fee

But the operator-intended private payment amount was:

9,987,000 sats

There is no visible 9,987,000 sat recipient output on-chain.

That is the important privacy milestone: the visible BCH values are not the same thing as the actual intended private payment amount. The public chain sees the private-payment packet layout and token commitments. The actual payment meaning is carried inside the protocol state transition rather than exposed as a normal visible recipient payment.

An important detail here is how change is handled.

In an ordinary BCH transaction, leftover value often appears as a separate visible change output. That can be a privacy leak, because observers can often distinguish payment output from change output and use that distinction to reconstruct user activity.

This transaction avoids that pattern.

There is no ordinary visible BCH change output. Instead, sender change is retained inside Plane A, the private state continuation output. Plane B remains the recipient recovery packet set: twelve uniform packet outputs carrying the ML-KEM-era recipient recovery material.

So the public transaction does not say:

“here is the recipient payment, and here is the sender change.”

It says something closer to:

“here is the next private state continuation, plus a fixed recipient recovery packet set.”

That is a key part of the privacy direction. Public observers can still see the transaction graph, the input, the output count, token commitments, and visible BCH amounts. But they do not get a conventional visible recipient output or a conventional visible change output that directly reveals the payment split.

Why this matters

This is the first accepted explicit packet-plane shell for the ML-KEM-era path.

It demonstrates that the transaction can be shaped as:

  • one Plane A private state continuation output
  • twelve Plane B recipient recovery packet outputs
  • no ordinary visible BCH change output
  • sender change retained inside Plane A
  • Plane B reserved for the twelve recipient recovery packet outputs
  • no fallback to the earlier compact carrier path

That is a major step toward the target architecture: private value moving through authenticated protocol state rather than through publicly meaningful BCH payment outputs.

What this does not claim yet

This is still R&D, and the truth boundary matters.

This milestone does not yet claim:

  • full end-to-end post-quantum privacy
  • production-ready confidential transactions
  • final wallet reconciliation or receiver recovery
  • final proof-bearing covenant enforcement on this path
  • aggregation or coordinator-based privacy

The transaction proves the explicit packet-plane on-chain layout. It does not by itself prove that the whole final privacy protocol is complete.

Why I’m excited

This is the first time the intended ML-KEM packet-plane layout has made it onto Chipnet in the form the current protocol direction requires.

This milestone shows the explicit packet-plane layout (13 outputs) can be accepted on-chain without falling back to ordinary visible change or the earlier compact carrier path.

That is real progress toward cash-like BCH privacy: hiding the actual intended private payment amount inside protected protocol state while keeping the transaction self-custodied and visible enough to be audited on-chain.

Appendix: evidence data

The accepted packet-plane attempt was recorded as:

{
  "version": 1,
  "generatedAt": "2026-04-27T19:00:51.406Z",
  "attemptKind": "explicit-packet-plane-path",
  "attemptStage": "broadcast-observed",
  "profileId": "bob",
  "stateFilePath": "/tmp/bcloak-live-profiles.json",
  "signedArtifactIdHex": "1fb716d7640fe821589a12389ebf4e2f9ff3d507a0081524f929ea3549054950",
  "selectedFundingOutpoint": {
    "txidHex": "676ed5dd9a72949a59cd7c523d8e50279dc13c5084f2f949bbba7d85a540db77",
    "vout": 0
  },
  "outputCount": 13,
  "outputLayoutSummary": "output0=PlaneA, outputs1..12=PlaneB packet outputs",
  "planeAIndex": 0,
  "planeBRange": {
    "start": 1,
    "end": 12
  },
  "recipientPacketCount": 12,
  "recipientPacketProfile": "ml-kem-768-12x128",
  "transparentChangeAbsent": true,
  "compactCarrierFallbackAbsent": true,
  "residueState": "privately-folded",
  "txidHex": "1fb716d7640fe821589a12389ebf4e2f9ff3d507a0081524f929ea3549054950"
}

The live transaction facts were:

{
  "network": "chipnet",
  "txid": "1fb716d7640fe821589a12389ebf4e2f9ff3d507a0081524f929ea3549054950",
  "version": 2,
  "sizeBytes": 2400,
  "feeSats": 10000,
  "input": {
    "outpoint": "676ed5dd9a72949a59cd7c523d8e50279dc13c5084f2f949bbba7d85a540db77:0",
    "valueSats": 20000000
  },
  "outputs": {
    "count": 13,
    "planeA": {
      "index": 0,
      "valueSats": 19978000,
      "scriptHex": "51",
      "tokenNftCapability": "mutable"
    },
    "planeB": {
      "range": "1..12",
      "count": 12,
      "valueSatsEach": 1000,
      "totalValueSats": 12000,
      "scriptHex": "51",
      "tokenNftCapability": "none",
      "recipientPacketProfile": "ml-kem-768-12x128"
    }
  },
  "planeModel": {
    "planeA": {
      "outputIndex": 0,
      "role": "private state continuation output",
      "currentMilestoneFunction": "carries the next private protocol state and retains sender change at the current shell level"
    },
    "planeB": {
      "outputRange": "1..12",
      "role": "recipient recovery packet set",
      "currentMilestoneFunction": "carries the fixed ML-KEM-era recipient recovery packet material",
      "packetProfile": "ml-kem-768-12x128"
    }
  },
  "changeHandling": {
    "ordinaryVisibleBchChangeOutputPresent": false,
    "senderChangeHandling": "retained-inside-plane-a-private-state-continuation-output",
    "publicChangeClassification": "no conventional visible BCH change output"
  },
  "publicArithmetic": {
    "inputSats": 20000000,
    "planeASats": 19978000,
    "planeBRecoveryPacketSats": 12000,
    "feeSats": 10000
  },
  "operatorIntendedPrivatePaymentSats": 9987000,
  "visibleRecipientOutputForIntendedAmount": false,
  "ordinaryVisibleBchChangeOutputAbsent": true,
  "fallbackToEarlierCompactCarrierPathAbsent": true
}

Next steps toward full confidentiality

The next work is to move from an accepted packet-plane layout toward the full confidential transaction architecture.

Near-term work:

  • receiver discovery and recovery from Plane B recipient recovery packet outputs
  • proof-bearing continuation spend validation
  • covenant/state-cell enforcement of the private transition rules
  • clearer evidence tooling for comparing public chain values against intended private payment semantics

The key point is that this milestone proves the explicit packet-plane layout can land on-chain. The next stage is making that layout fully recoverable, enforceable, and spendable as a complete confidential payment path.

3 Likes

Milestone: first live proof-bearing P2S/kernel continuation spend on Chipnet

Direct Confidential Spend on BCH: Packet-Plane Source + Proof-Bearing State-Cell Continuation

I have live-validated a narrow but important milestone for a confidential transaction protocol on BCH:

  1. An explicit ML-KEM-768 packet-plane transaction was accepted on Chipnet.
  2. The recipient recovery path can use ML-KEM-era packet material rather than exposing a normal recipient payment output.
  3. A P2S/kernel state-cell continuation spend was accepted on Chipnet.
  4. That continuation spend carried compact proof material and advanced the protocol state cell.
  5. The public chain did not show a normal recipient output equal to the private transfer amount, and did not show ordinary transparent BCH change.

The next questions are:

  • Is the compact proof system used here properly classifiable as a STARK?
  • If so, is this STARK construction actually zero-knowledge for the defined public statement?
  • Does the full transaction transcript reveal only the intended public statement, or are there additional public-field, graph, timing, or metadata leaks?

That distinction matters because “proof-bearing,” “STARK-class,” and “actually zero-knowledge” are not the same claim.

The direct-path point

The most important architectural point is this:

This is still direct, self-sovereign spend. Aggregation is not required for correctness.

A confidential BCH protocol should not require users to depend on a coordinator, aggregator, server, or service market as part of the trust base. Those services may become useful later for batching, timing privacy, fee efficiency, and UX.

But the base path should work directly from wallet-controlled state, chain truth, and wallet secrets.

That is what this milestone demonstrates.

Source packet-plane tx:
76982788a0f653c31b42890ab1cd75a994af55b76c43d969f3da8a78b095cd99

Continuation tx:
4586ce7296dd456cd973610fc2f36362c324594682dbc91d03ef4acb4eaa49e9

Continuation input:
76982788a0f653c31b42890ab1cd75a994af55b76c43d969f3da8a78b095cd99:0

Continuation output:
index 0
value 29,978,000 sats
P2S script type: script
mutable NFT protocol state cell
token category: 6f2b7d8d0a509b6011aca9f08bf1786d3824027ed5ba939a00d6328cca9cb17e

Tx size:
1,589 bytes

Fee:
5,000 sats

Fee rate:
~3.147 sats/byte

Mempool:
accepted, 0 confirmations at observation

1 Like

Why I Think Privacy Doesn’t Just “Drop Into” BCH Wallets

BCH-CT has reached an important design checkpoint.

The early framing was:

How do we add confidential transactions to BCH wallets?

That is still the eventual integration question, but it skips over the deeper architecture question:

How do we build a BCH-native private payment mode when BCH does not have native shielded-pool consensus like Zcash or default privacy rules like Monero?

That distinction matters a lot.

It changes the work from “add a new address type” into a larger protocol/app-layer design problem: private notes, encrypted note delivery, proof-based authorization, wallet accounting, aggregation, and BCH settlement.


Why this is harder than “add a new address type”

A normal BCH wallet is built around:


keys -> addresses -> UTXOs -> signatures -> broadcast

That model works well for transparent payments.

But confidential payments move the problem into a different model:


private notes -> commitments -> nullifiers/spend markers -> proofs -> encrypted note delivery

In other words, the important shift is from key-based authorization to proof-based authorization.

On transparent BCH, the chain asks:

Did the spender satisfy this visible script/address condition?

In BCH-CT, the chain should eventually ask:

Does this proof show that a valid private note was spent, value was conserved, and new private notes were created correctly?

That is why trying to make an ML-KEM key, Nostr key, or Quantumroot vault behave like a normal BCH address does not really solve the core problem.

ML-KEM is useful for encrypted note delivery.

Nostr may be useful for message transport.

Quantumroot is useful for post-quantum custody.

But none of those are the same thing as a private-note authorization model.


What other privacy chains have that BCH does not

Zcash privacy is not just a wallet feature. Zcash made shielded transactions a first-class part of the protocol: shielded notes, note commitments, nullifiers, encrypted note data, and proof verification are all part of the native shielded transaction model.

Monero also does not bolt privacy onto ordinary visible addresses. Its privacy model combines stealth addresses, RingCT, and spend/view key separation so recipient identity and amounts are not represented like ordinary public UTXO payments.

Dash PrivateSend is closer to BCH’s existing CashFusion pattern: it uses non-custodial CoinJoin-style coordination to make transaction history harder to trace, but it is not a private-note protocol like Zcash or Monero.

That is the key difference:


Zcash:

native shielded-pool consensus

Monero:

native privacy transaction model

Dash / CashFusion:

non-custodial mixing of transparent coins

BCH-CT:

currently being explored as a BCH contract/app-layer protocol

So BCH-CT cannot just “copy Zcash” without consensus changes. It has to use BCH-native primitives: UTXOs, covenants, CashTokens, proof-bearing scripts, and optional coordination.


The SLP / CashTokens analogy

The closest BCH historical analogy may be SLP before CashTokens.

SLP filled the token gap before BCH had consensus-native tokens: wallets, indexers, and applications interpreted token rules on top of normal BCH transactions. Later, CashTokens made token functionality first-class at the BCH consensus/VM layer.

BCH-CT may be doing something similar for privacy. BCH does not currently have native shielded-pool consensus, so this work explores what can be done at the contract/app layer first. If the model proves useful, it may help clarify what a future native BCH privacy proposal would actually need.

The analogy is not perfect: privacy is harder than tokens. BCH-CT has to deal with private notes, nullifiers, proofs, encrypted note delivery, wallet recovery, metadata leakage, and post-quantum assumptions. But the pattern is familiar: explore at the application layer first, learn the real requirements, then decide whether any part belongs in consensus later.


Why not make privacy more chain-native?

The obvious question is:

If Zcash made privacy native, why not do the same thing on BCH?

That may be a valid long-term direction. BCH could eventually consider a consensus-level privacy proposal with native note commitments, nullifier sets, proof verification, encrypted note fields, and pool accounting.

That would be the closest BCH equivalent to Zcash.

But it is also the largest path. It would require a serious CHIP process, broad ecosystem review, wallet changes, node implementation work, long-term maintenance, and agreement that private notes should become a first-class BCH consensus feature.

That is not the smallest next step.

The more immediate question is:

What can BCH do with the primitives it already has or is already gaining?

That led to direct state cells first.

A direct state cell is very BCH-native:


state cell UTXO exists

wallet spends it with valid covenant/proof data

new state cell UTXO is created

BCH consensus enforces single-spend

That path is decentralized, self-sovereign, and fits the UTXO model.

The problem is privacy.

If Alice’s private activity visibly advances like this:


Alice state cell -> Alice next state cell -> Alice next state cell

then the state-cell lineage can become Alice’s activity graph.

So the current design keeps direct state cells as the base/fallback primitive, but no longer treats visible one-user state-cell advancement as the final privacy boundary.


Where Quantumroot fits

Quantumroot is extremely important, but it solves a different layer.

Quantumroot is a post-quantum vault/custody design for BCH. It protects visible BCH UTXOs with hash-based post-quantum authorization paths and aggregation techniques.

That is not the same thing as confidential transactions.

Quantumroot answers:


How do I hold and later spend BCH safely in a quantum-threat model?

BCH-CT is trying to answer:


How does Alice privately pay Bob without the chain showing Bob’s normal recipient output,

the private amount, or Alice’s ordinary transparent change?

So the practical stack may become:


CashFusion:

improve transparent input provenance

Quantumroot:

PQ-safe custody before/after private mode

BCH-CT:

private note transfers inside private mode


Why CashFusion + Quantumroot may be enough for some users

This is worth saying plainly.

For many users, CashFusion + Quantumroot may be the right near-term privacy/security stack.

It gives:


better transparent coin history

+

post-quantum custody

That is valuable.

But it does not give:


hidden payment amounts

hidden sender residue/change

private note transfer

proof-based private spends

the ability to stay inside a private payment mode across multiple hops

That is the reason BCH-CT still exists as a separate research path.

If BCH-CT cannot deliver private notes, hidden amounts, hidden residue, and proof-based private transfer, then it is probably not worth the complexity.


Why this MVP design was chosen

The current MVP direction is:


direct state cells as the base/fallback path

+

CashFusion-like aggregation as the privacy boundary

+

private notes as the internal payment object

Instead of Alice directly advancing her own visible state cell, Alice creates a spend intent.

That intent says:


I authorize my current BCH-CT state cell to be consumed

only if this batch creates the private note commitments I committed to.

Alice submits that intent to one or more aggregators.

The aggregator is not a validator.

It is not a shard manager.

It is not a sequencer.

It does not custody funds.

It does not decide protocol truth.

It is just a batch assembler, similar in spirit to CashFusion coordination.

The aggregator collects many intents:


Alice intent

Bob intent

Carol intent

Dave intent

...

Then builds one BCH transaction:


many BCH-CT state cells in

many unordered private note commitments out

no ordinary transparent change

no public recipient marker

no obvious input -> output mapping

BCH validates the transaction. If the aggregator lies, redirects value, omits required commitments, or builds an invalid transition, the transaction fails.

That is why this design was chosen: it is more BCH-native than a managed pool or sequencer, avoids the single-UTXO bottleneck, avoids visible per-user lineage, and does not require immediate native shielded-pool consensus changes.

It is not “privacy off-chain.”

It is:


BCH validates settlement.

Users own their state.

Aggregators assemble batches.

Encrypted note delivery happens off-chain.

Recipients verify notes against BCH commitments.

Direct spend remains the fallback.


Where Nostr fits

Nostr should not be the protocol trust base.

But it can be useful as a message transport.

In the MVP, Nostr can carry:


aggregation intents

encrypted note envelopes

batch status messages

contact/discovery messages

It should not carry protocol truth.

The chain remains the settlement and validation layer.

The important line is:


Nostr routes encrypted note material.

BCH anchors settlement.

Proofs authorize private state transitions.


Alice to Bob in the updated model


1. Alice has BCH-CT private state from a prior import.

2. Alice wants to pay Bob.

3. Alice obtains Bob-compatible receive material off-chain.

This might use Nostr, QR, direct contact exchange, or another transport.

4. Alice creates Bob’s private note:

- private amount

- note randomness/opening

- commitment

- recovery material

5. Alice encrypts Bob’s note envelope, likely using ML-KEM-derived shared secret material.

6. Alice creates a spend intent:

- consume Alice’s current BCH-CT state cell

- create Bob note commitment

- create Alice residue note commitment

- pay fee/postage

- expire after height H

- no transparent change

7. Alice submits the intent to one or more aggregators.

8. Aggregator combines many intents into one BCH batch transaction.

9. BCH validates the batch.

10. Bob receives the encrypted note envelope.

11. Bob decrypts it, verifies that the note commitment appears in the accepted BCH batch, and imports the private note.

12. Bob later spends by submitting his own direct spend or aggregation intent.


What this borrows from other systems

From Zcash, BCH-CT borrows the note/nullifier/proof model.

From Monero, BCH-CT borrows the lesson that recipient identity should not become a public chain object.

From Dash/CashFusion, BCH-CT borrows the coordination pattern: non-custodial batch construction where the coordinator cannot steal funds.

From Quantumroot, BCH-CT can borrow BCH-native continuation, token authority, and post-quantum custody lessons.

From Cardano/eUTXO lessons, BCH-CT should avoid one global mutable UTXO or managed sharded state.

From SLP/CashTokens, BCH-CT borrows the historical pattern of exploring a missing feature at the application layer first, before deciding whether any part belongs in consensus later.


What BCH-CT is not claiming yet

This is not production Zcash-level privacy.

This is not a native shielded pool.

This is not complete post-quantum private money.

This is not solved wallet UX.

This is not a replacement for CashFusion or Quantumroot.

The honest current target is narrower:

Can BCH support an aggregated, proof-bearing private note transfer flow where users retain direct fallback, aggregators cannot steal or validate by authority, and visible state-cell lineage is broken by batch construction?

That is the MVP I think is worth building next.


Why this path may work on BCH

The reason I still think BCH is a good place to explore this is that BCH can validate rich covenant/script behavior directly on L1, while still preserving the UTXO model.

That means the design does not need to become an Ethereum-style rollup with a sequencer as the trust base.

The architecture I now see is:


BCH L1:

settlement, covenant/proof validation, fees, finality

BCH-CT app:

private notes, encrypted note delivery, wallet accounting, proof witnesses

Aggregation:

optional CashFusion-like batch assembly

Quantumroot:

PQ-safe custody at the transparent edges

Nostr:

optional message transport, not protocol truth

The goal is not to make privacy magically “drop into” existing BCH wallets.

The goal is to define a BCH-native private payment mode that wallets can eventually integrate once the protocol boundary is clear.

That is the next milestone.


References

1 Like

The confidential concept only works if you have mixers, as you correctly point out here. Because a single user obscuring 10 bch for n transactions and then taking the 10 bch out on the other side is not obscuring much. You need multiple people to mix.

A mixer can be called fusion or aggregator, it’s basically the same thing.

It is relevant to point out that if you start moving mixing transactions away from fusion, you make fusion less powerful because the measure of anonimity is the size of the pool.
And if you require fusion AS WELL AS your confidential script, you likely don’t need your confidential scripts at all.

Let’s work on finding solutions for whatever problem you are trying to solve using p2pkh UTXOs.

Some quick examples you give as being impossible in Fusion:

Both are actually directly available with very little work or complexity based on cash fusion.

BIP69 provides a lot of this already and is operational in various wallets today. You can take it further and spread your payment and / or change over a series of already fused transactions to pay to a dozen (or a hundred) different addresses that are all owned by the recipient.

You can make it as private as you want if you keep one simple rule: don’t reuse addresses.

The goal may be simply to have fun with zcash or similar algorithms, which is fun and naturally more than fine to play with.
If, on the other hand you are trying to solve actual real life privacy problems then I think we can work on a simple solution that reaches that without a new couple of layers.

1 Like

Thanks for bringing the conversation here. I like the forum posts more than TG because it slows things down and inspires thought.

The criticism is fair, and I agree with the main constraints.

Aggregation is mixer-like. Any design that needs multiple participants competes for anonymity-set attention. CashFusion is already BCH-native, non-custodial, and broadly useful. BCH-CT should not claim value if improved P2PKH/CF wallet behavior solves the same problem more simply. And BCH-CT should not weaken CF’s anonymity set unless it provides a privacy property CF cannot provide.

One clarification: BCH-CT is not trying to replace CF as a mixer.

The base BCH-CT result already demonstrated a different transaction shape: the public transaction does not show a normal recipient output equal to the private amount, and it does not show ordinary transparent BCH change. Instead, the actual value movement is represented through proof-bound private state, with only a public carrier/postage amount visible.

So I think the real question is:

Does moving from improved P2PKH/CF wallet behavior to P2S/proof-bound private state provide enough additional privacy, PQ-readiness, and practical value to justify the added complexity?

If the answer is no, then BCH-CT should shrink or stop.

If the answer is yes, then BCH-CT is not competing with CF as “another mixer.” It is a private-note/payment-state experiment that should use CF for clean imports and only use aggregation as an optional privacy improvement inside the private mode.

The strongest value I currently see is hiding the actual value being transferred behind a simple public postage amount while also avoiding ordinary transparent recipient/change outputs. That is the specific property I want to test against what can be done with P2PKH + CF + Quantumroot alone.

In the beautiful world of permissionless innovation nobody will (or can) tell you to stop. My goal is also not in that direction.
My goal is to make sure you’re working under the best knowledge to decide what you want to spent your time on.

The most used protocol today; cash fusion, does this as well. A single wallet (or identity) can have one or 50 inputs in any specific fusion transaction. Similar with outputs. From 1 to a large number. Nobody can tell what combination. Next to that, there is no reuse of addresses so there is simply no such concept as an identity.
Every single fusion makes any sort of tracability insanely improbable. Which means that an IDENTITY can mix funds that are spending just a token amount of fees (typically less than 2000 sats) and send an anonymous amount.
What that identity puts in and gets out is completely invisible. Hiding in plain sight.

More: https://x.com/i/grok/share/rlUL1TJY3gRbfwu4E9A8hTVi0

In other words, your goal of hiding amount and hiding identity is something that already is possible with cash fusion today, which is deployed and operational.

In my wallet there is special care taken to make this anonymous. The lack of address reuse helps because it means you don’t even know which of the outputs is the change and which is the payment. You also don’t know who it comes from and with fusion you don’t know who it went to.

All your requirements are fulfulled.

Quantumroot needs a single line. If at any time p2pkh is not enough and we need to move to any new crypto primitives then we’ll see that supported widely. So if there is a real need for fusion based on some new crypto signing primitive (quantum or otherwise), then the fusion server will be supporting. There is no technical reason stopping anyone from running one modified for any specific p2sh / p2s today. It is merely a matter of how big the anonimity pool is.

isn’t the time now? this is the thing I’m most curious about. does p2pkh survive in PQ with privacy like CF and protection with QR?

In other words, can you demonstrate the CF works well with QR easily?

1 Like

I think the question is to migration cost later if BCH support quantum route today then any new product should consider that today so it can become future proof.

1 Like

this may now actually be more possible then originally thought, thanks to tools like WizardConnect. A privacy wallet dapp is currently under development without needing to build an entirely new wallet layer.

the dapp uses keys and signatures from electron cash and uses the utxos in the EC wallet to populate the privacy protocol or private notes.

wallets may optionally integrate with the dapp via open access template versions, but it’s not a requirement. or, non electron cash wallets can simply add wizardconnect support.

then, as the privacy protocol matures, wallets may develop and integrate as needed, but the dapp will bridge transparent and private transactions regardless

1 Like

This all sounds good, but it’s also very long and very generic.

Where/when is the actual proposal? Here’s a (draft) script transaction that allows someone to move BCH between parties with some amount of increased privacy over the transparent default?

CashTokens, Velma and Layla are all live. The VM cannot be a limiting factor.

Feels like months and months of these generic statements and no actual “Here’s the work on a privacy solution”.

Compare with e.g. the work by BCHAutist (who also tackles very big scale problems that might not be apparent in the importance of the ground work at first). Pretty quickly things start to go from a generic discussion, to key details and decisions emerging on real points.

I’ll be short and direct.

Each phase of funding met and delivered as specified in campaign:

Phase 1
https://fundme.cash/campaign/79

Phase 2
https://fundme.cash/campaign/94

Phase 3 has yet to be funded, but this thread keeps the conversation going around proof based utxo spends that with proper hardening may become STARK / ZKP.

Milestone plan here

Milestone are very fluid as MVP being built

Summary of work completed and what this project is building towards https://gist.github.com/bastiancarmy/e64d49e937d2bf7567173e34eeb46b6f

The current most direct alice to bob type script is in this demo https://github.com/bastiancarmy/bitcoin-cash-stealth-demo/tree/main

From there, however, RPA was abandoned to focus on a more PQ ready solution, which is the ml-kem examples posted in this thread. Looking forward to discussing in deeper detail with whoever is interested.

2 Likes

Great summary, I’ll find some time to play around with the released files thanks.

Didn’t have anywhere I could see it all in one place like this before. Maybe worth pinning it to the thread or having some other place where this kind of “summary” explanation is posted and updated?

I’m sure other people will be looking for the same thing if they get interested in this project, but it’s hard to find if the information is all scattered about or buried in a thread.

1 Like

Great! glad it helps summarize.

I’m excited to keep building towards a wallet integration. I’m seeing two options:

  1. Wallet adds wizardconnect support
  2. Wallet adds first class support for the privacy protocol, using the open access covenant templates

#2 is most exciting, because it’s most similar to a service to service API call. The template exposes the required details to build the bytecode and an SDK can be published to build the commitment values:

type ApntImportTemplateInput = {
  valueSats: bigint;

  claimCommitment32: Bytes32;
  privateNoteCommitment32: Bytes32;
  selfRecoveryPacketHash32: Bytes32;
  refundKeyCommitment32: Bytes32;

  laneRoutingConfigHash32: Bytes32;
  laneId: number;

  batchPolicy: "aggregator-batch-v0";
  feePolicy: "exact-output-no-transparent-change-v0";

  expiryHeight: bigint;
};

This is very interesting. What do you need to get this finished?

1 Like

I noticed that with these EC primitives we could have a few lines of commitment script that enable Bulletproofs confidential transactions so they are essential and the backbone of any confidential transactions if we ever wanted one as close to drop-in. What’s being done on confidential transactions for BCH right now?

Honestly, I used to think we couldn’t have Monero-like confidential amounts without giving up auditability of the supply this is why there is workaround on non privacy chains like how eth had tornado cash. Turns out i was wrong and had it backwards… actually with @lightswarm proposal it could be very much possible to have the best from both world thanks to CashVM. The model is a transparent-backed shielded pool where BCH is locked transparently into a pool covenant, so the backing stays fully auditable and keeps cash-like properties, and inside the pool value moves as confidential notes (Pedersen commitments plus balance and range proofs, so amounts are hidden but conservation is enforced). A note transfers between users privately, or redeems back to transparent BCH by whoever holds the matching NFT commitment, with the NFT state cell tracking the pool root and nullifiers. The covenant can never release more than was locked, so even a bug is bounded to theft inside the pool; it can’t inflate the 21M. That’s the part Monero can’t give you, the tradeoff being privacy at the boundary since deposits and withdrawals are visible. Which is totally acceptable given that BCH is not a privacy chain like XMR.

From what i understand the aggregated private-note path here (ML-KEM encrypted note delivery, state-cell continuation) is a shielded-pool style design, and it covers the anonymity-set side, breaking linkage with ZKP STARKs, which is valuable. But hiding the link is a different property than hiding the amount. Pedersen commitments + Bulletproofs would give the confidential-amount piece directly: the commitment is only a few lines, and the range-proof verify reduces to one multi-scalar mult, with no trusted setup.

So on the “privacy doesn’t just drop into BCH wallets” point, I’d say the amount-hiding part actually can if we could add the EC primitives mentioned from @lightswarm proposal, with these opcodes. The two look complementary: EC/Bulletproofs for confidential amounts, mixing/aggregation for the anonymity set. Together that’s a real full Monero system.

  • Reference: