Skip to content

Confidential Receive Descriptor and Invisible Protocol Entry Design v1

Status: design note for TKT-P4-03
Scope: recipient addressing and wallet UX on the frozen trustless fixed-statement path

This note does not change verifier semantics, artifact shape, or the frozen host/kernel split. It answers whether normal user-facing protocol entry can be hidden behind a confidential receive surface while preserving the merged trustless contract.

1. Executive recommendation

The best current model is:

  • canonical protocol object: a recipient descriptor
  • canonical user-shareable bundle: a descriptor bundle carrying the confidential descriptor plus an optional standard BCH fallback address
  • copy/paste / QR UX: an address-like encoding of that descriptor later if desired
  • session-based richer flows: a payment request that embeds the same descriptor plus amount/memo/expiry metadata

Why:

  • a plain BCH-style "address" implies "any wallet can pay this output format correctly"
  • that is not true for the current confidential protocol path
  • the sender must understand protocol entry, confidential transition planning, and receiver recovery bindings
  • the current frozen contract already has the right internal protocol objects for this, but it does not make the receive surface a generic BCH address

So the honest recommendation is:

  • descriptor now
  • descriptor bundle for real wallet UX
  • address-like encoding later
  • payment request wrapper where richer sender-side context is helpful

2. Frozen baseline

This design assumes all of the following stay unchanged:

  • backendId=2
  • trustless TRQ1
  • chunked proof transport as the BCH-scale rule
  • Stage-B structural/kernel-facing verifier lane only
  • Stage-A host duties unchanged
  • wallet artifact parity remains fail-closed
  • no ABI widening
  • no verifier-visible witness aliases
  • no host/public-shell drift

3. Product cases that must stay separate

3.1 Wallet-native confidential receive descriptor

The sender wallet understands the protocol and can:

  • parse the descriptor
  • derive receiver identity material
  • perform protocol entry if needed
  • construct the confidential transition
  • emit the existing frozen trustless artifacts
  • leave receiver recovery unchanged

This case is viable now on the frozen contract, with the caveat that "invisible entry" may still be an internally orchestrated multi-step wallet flow rather than a new single-transaction protocol shape.

3.2 Wallet-connect / handshake-based request flow

The sender and receiver exchange richer context through an app/session:

  • recipient descriptor
  • optional amount request
  • optional memo or merchant label
  • optional expiry / network / policy hints

This case is also viable now, and is a clean place to wrap the same descriptor in a richer request without redefining the protocol.

The important point is that the descriptor remains the protocol identity object. The payment request is only a transport/wrapper for richer UX.

3.3 Ordinary BCH wallet with no protocol support

This case is not viable for confidential receive on the frozen path.

An ordinary BCH wallet cannot:

  • construct protocol entry into covenant-controlled state cells
  • produce the trustless confidential transition artifacts
  • enforce the protocol’s receiver recovery bindings
  • reason about RRE1, PIv1, PBv1, or SCv2

So ordinary BCH wallet behavior must fail closed.

Acceptable fallback behavior is:

  • use a separate transparent BCH address or paycode surface
  • or route through a protocol-aware wallet/application

Current Phase-2 compatibility commands (pool, shard, stage, import) should remain legacy/dev tooling, not the ordinary-user receive model.

Define a reusable ConfidentialReceiveDescriptorV1 as the canonical recipient object.

It should contain:

  • protocol/version marker
  • network marker
  • receiver identity transport payload
  • either a protocol-tagged paycode / scan pubkey transport that yields (A, B)
  • or explicitly encoded receiver scan/spend public keys
  • profile lock for the frozen path
  • backendId=2
  • trustless TRQ1
  • optional user-facing label / capabilities metadata

It should not contain:

  • amount
  • tx hex
  • source note ids
  • proof bytes
  • witness material
  • current state cell pointers
  • verifier-only or host-side recomputation data

If a richer request is needed, wrap the descriptor in a payment request object rather than widening the descriptor itself.

The recommended wallet-facing receive object is:

  • ConfidentialReceiveBundleV1

It packages together:

  • confidentialDescriptor
  • the protocol-native recipient descriptor used by protocol-aware wallets
  • fallbackBchAddress
  • an optional standard BCH address for non-supporting wallets
  • preference
  • preferConfidential
  • optional display metadata
  • receiver label
  • network
  • explanatory text for fallback handling

This is the cleanest honest model because:

  • protocol-aware senders need more than a BCH address
  • non-supporting wallets need a real standard BCH destination
  • the bundle makes the capability split explicit instead of pretending one string can mean both paths

Recommended minimal shape:

type ConfidentialReceiveBundleV1 = {
  version: 1;
  network: 'chipnet' | 'mainnet';
  confidentialDescriptor: ConfidentialReceiveDescriptorV1;
  fallbackBchAddress?: string;
  preference: 'prefer-confidential';
  labels?: {
    confidential?: string;
    fallback?: string;
  };
};

4.2 Packaging recommendation

Recommendation across the three packaging candidates:

  • best canonical packaging: descriptor bundle
  • best richer transport: payment request wrapping the descriptor bundle
  • not recommended as the primary model yet: address-like encoding with fallback metadata

Why the descriptor bundle wins:

  • it cleanly carries both the protocol path and the fallback path
  • it matches the actual sender capability split
  • it avoids overloading the word "address" with semantics that ordinary BCH wallets cannot satisfy

Why a payment request is still useful:

  • it can wrap the same bundle for wallet-connect/session flows
  • it can add amount, memo, expiry, or merchant context without redefining the protocol object

Why an address-like encoding is not the primary answer yet:

  • a single address-like string suggests universal wallet compatibility
  • fallback metadata and capability routing are more naturally expressed as a structured bundle
  • address-like encoding can still be added later as a human-shareable representation of either the confidential descriptor or the whole bundle

5. Exact protocol object mapping

The correct mapping on the current frozen path is:

5.1 Receiver publishes descriptor

Receiver wallet exports:

  • ConfidentialReceiveDescriptorV1
  • whose identity payload yields receiver (A, B) or the public material needed to derive it

Current protocol anchors:

  • receiver identity (A, B) is the normative ownership model in spec/protocol-terminology.md
  • paycodes/RPA are optional identity-distribution transports, not protocol requirements

5.2 Sender wallet resolves receiver identity

Sender wallet parses the descriptor and resolves:

  • receiverScanPub33
  • receiverSpendPub33

This is exactly the public information the current planner uses.

Current code anchor:

5.2.1 Sender capability decision tree

The correct sender behavior for ConfidentialReceiveBundleV1 is:

  1. Parse bundle.
  2. If wallet supports the confidential protocol path and can consume confidentialDescriptor:
  3. default to Send Confidentially
  4. if sender already has confidential balance, run the existing confidential transition
  5. if sender only has transparent BCH, perform automatic protocol entry first, then run the confidential transition
  6. If wallet does not support the confidential protocol path:
  7. ignore confidentialDescriptor
  8. if fallbackBchAddress is present, offer only a standard BCH payment to that address
  9. do not claim or imply that the payment creates a confidential note
  10. If wallet does not support the protocol path and no fallback BCH address is present:
  11. fail closed and report that the receiver requires a protocol-aware wallet

This keeps the confidentiality claim aligned with actual sender capability.

5.3 Sender funding mode check

Sender wallet checks whether it already has at least one spendable confidential note:

  • inspect wallet notes first
  • treat protocol state cells only as the backing state for a wallet note

Current code anchor:

5.4 If sender already has confidential balance

Then the wallet runs the existing confidential transition path directly:

  • source WalletNoteRecordV1
  • backing SCv2 state cell
  • current deterministic planner
  • current PIv1 / PBv1 / RRE1 / EPv1

Objects produced:

  • stateIn32
  • stateOut32
  • outputFingerprint32
  • PIv1
  • PBv1(backendId=2, TRQ1, encrypted payload + hints)
  • RRE1
  • WNPay1 payload encrypted in EPv1

5.5 If sender only has transparent BCH

Then the wallet performs invisible protocol entry as an internal orchestration step:

  1. spend ordinary BCH into at least one protocol state cell
  2. materialize a sender-owned wallet note backed by that state cell
  3. immediately continue with the standard confidential transition path

This preserves the current protocol model:

  • entry remains entry
  • transition remains transition
  • the user simply does not see stage/import as a manual workflow

Important honesty rule:

under the current frozen contract, this is best modeled as wallet-orchestrated invisible entry, not as a new one-step protocol action.

5.6 Receiver recovery remains unchanged

Receiver later scans the transition transaction and recovers the note using the same current rules:

  • parse host unlock carrier
  • parse PIv1 / PBv1
  • verify output fingerprint binding
  • parse RRE1
  • derive shared secret from scan key and txEphemeralPubkeyR33
  • decrypt EPv1
  • decode WNPay1
  • validate note root / null root / witness / note commitment
  • persist WalletNoteRecordV1

Current code anchor:

6. Why this is compatible with the frozen trustless contract

This addressing layer is compatible with the merged path because it only changes how the sender obtains receiver identity and entry intent.

It does not change:

  • the proof artifact
  • the public input boundary
  • the host/kernel split
  • the recovery payload format
  • the receiver scan rules

The descriptor feeds the existing planner boundary.

That planner boundary is already defined as:

  • source wallet note
  • source protocol state cell
  • sender wallet context
  • receiver wallet context (A, B)

See spec/confidential-transfer-planner-v1.md.

7. What is viable now vs later

7.1 Viable now

Invisible protocol entry is viable now if the sender wallet is protocol-aware and the product requirement is:

  • one recipient descriptor
  • one "Send Confidentially" action in the wallet
  • internal orchestration that may perform entry first if needed
  • no manual stage/import UX

This can be done without contract drift.

7.2 Viable later

An address-like encoding for copy/paste or QR is viable later as a transport wrapper for the same descriptor.

That is a wallet UX/encoding problem, not a verifier problem.

7.3 Not viable now under the current boundary

The following stronger claims are not viable now without future work:

  • "any ordinary BCH wallet can pay this and produce a confidential receive"
  • "transparent BCH can become a receiver note in one new universal address payment without protocol-aware sender support"
  • "protocol entry and confidential transition collapse into one new universal receive semantic under the current fixed planner without additional planning work"

8. Exact blocker for the stronger version

If the desired product is:

  • a single universal address
  • payable by non-protocol BCH wallets
  • or a one-step transparent-BCH-to-recipient-note flow with no sender-side protocol orchestration

then the blocker is:

  • the current frozen path assumes protocol-aware sender planning
  • the current confidential transition planner starts from an existing sender wallet note + backing state cell
  • the current protocol entry path is still distinct from the transition path

That is a wallet/planner/orchestration blocker, not a verifier blocker.

Recommended ordinary-user language:

  • Confidential Balance
  • Receive Confidentially
  • Send Confidentially
  • Scan
  • Move to Standard BCH

What becomes invisible:

  • pool
  • shard
  • stage
  • import
  • manual state-cell selection

What remains advanced/dev-only:

  • compatibility entry commands
  • direct state-cell inspection
  • manual import/stage overrides
  • debug selectors such as shardIndex

9.1 Receiver UX flow

Recommended receiver-facing flow:

Confidential receive

Primary action:

  • Receive Confidentially

Display:

  • a shareable confidential receive bundle
  • explanatory text such as:
  • For wallets that support Confidential BCH, use this to send directly into my confidential balance.

Fallback BCH receive

Secondary action:

  • Fallback BCH Address

Display:

  • a standard BCH address
  • explicit warning text such as:
  • For wallets that do not support Confidential BCH. Payments here are standard BCH only and are not confidential notes.

Later move-to-confidential flow

If fallback BCH is used:

  • wallet shows the received funds under standard BCH balance
  • wallet offers a follow-up action such as:
  • Move to Confidential Balance

That follow-up flow is an explicit wallet-side protocol entry from transparent BCH into confidential balance.

Important honesty rule:

  • fallback BCH receive is transparent BCH, full stop
  • it is not a confidential receive
  • it only becomes confidential after a later protocol entry step

10. Recommendation summary

10.1 Address vs descriptor vs payment request

Recommendation:

  • best canonical protocol identity model now: descriptor
  • best receiver-facing packaging now: descriptor bundle
  • best wallet-connect/session wrapper: payment request carrying the descriptor bundle
  • best future human-shareable encoding: address-like string for the confidential descriptor or bundle

10.2 Viability

Invisible protocol entry is viable now on the frozen contract for protocol-aware sender wallets.

It is not currently a generic BCH address capability.

10.3 Optional spike need

No spike is required to answer the design question honestly.

The current planner, receive scan, and note-first preflight seams already show that:

  • receiver identity transport is separable from verifier mechanics
  • sender-side descriptor interpretation can feed the current planner boundary
  • invisible entry is primarily an orchestration/UX problem under the existing contract