Skip to content

feat(token): add confidential note delivery extension - #1183

Draft
0xisk wants to merge 7 commits into
feat/math-uintnfrom
feat/confidential-note-token-delivery
Draft

0xisk wants to merge 7 commits into
feat/math-uintnfrom
feat/confidential-note-token-delivery

Conversation

@0xisk

@0xisk 0xisk commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Depends on #1189, merge after.

Types of changes

What types of changes does your code introduce to OpenZeppelin Midnight Contracts?
Put an x in the boxes that apply

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation Update (if none of the other choices apply)

Fixes #727

Draft until the test suites land. The extension, both mocks, the witness and the simulators are in.

Not visible in the diff:

  • The pads are added modulo 2^248 and the ciphertext fields are Uint<248>, where the issue's draft added in Field. A Field sum of a full-width nonce and the pad reaches 2^248 half the time, and an entry holding a 32-byte field atom makes the generated _deliveries.head() / popFront accessor throw exceeded structure bounds: compactc sizes the Maybe<T> concat two bytes short of maxAlignedSize(Maybe<T>), and 0.35.0 emits the same line. The modular pad keeps every atom at 31 bytes and is a perfect one-time pad, so the width margin leaves the hiding argument. About 1200 rows on _deliver.
  • The composed mock's constructor runs _mint + _deliver, both witnesses at deploy: the path that lets a constructor-time mint reach its owner without the deployer keeping the note.

PR Checklist

Further comments

Rows under compactc 0.34.0: _deliver k=15, 26723 (annotated); composed mint 43533, transfer 107408, burn 64111.

@coderabbitai

coderabbitai Bot commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@0xisk 0xisk mentioned this pull request Oct 21, 2026
3 of 8 tasks
0xisk added 7 commits October 21, 2026 13:31
Publishes every output note of a ConfidentialNoteFungibleToken
encrypted to its owner's Jubjub key, so a wallet discovers its notes
from chain data alone instead of over an out-of-band channel.

* extensions/ConfidentialNoteFungibleTokenDelivery: one ECDH per
  output under an ephemeral that binds the note's nonce, two
  EcdhMask.kdf masks, one append-only List. The masks are added
  modulo 2^248 rather than in Field: each ciphertext is then a
  perfect one-time pad, and no ledger atom reaches 32 bytes, which
  the generated List head() / popFront accessors cannot read under
  compactc 0.34.0.
* test/mocks: a standalone mock, and a core<32> + delivery mock whose
  constructor mints and delivers so the deployer keeps nothing.
* test/witnesses, test/simulators: the delivery witness with an
  optional planted seed, and one simulator per mock.

Refs: #727
`slot` is a compile-time constant of the composer, so it is public from
the source. The Privacy notice now says it is hashed into `e` and never
written instead of counting it among the private values.
The core header says notes reach recipients out of band and that a
chain rescan finds nothing. Neither holds once a contract composes the
delivery extension. The core file stays untouched, so the extension's
Composition notice carries the correction for integrators who read the
core alone.
Unit, privacy, compatibility, concurrency and witness specs for the
ConfidentialNoteFungibleTokenDelivery extension, mirroring the core's
files. The privacy probe drives the composed mock so the differential
layer can pin which atoms of an entry move: the pads with the plaintext
or the key, the ephemeral only with the nonce. The compatibility suite
records the golden entry under compactc 0.34.0.

The contract-info reader gains the `JubjubPoint` and `JubjubScalar`
type names, which the delivery mocks are the first artifacts to emit.
The modular pad is also what keeps every `Delivery` atom below 32
bytes. The generated `head()` / `popFront()` queries bound their
`Maybe<T>` concat by `2 + maxAlignedSize(T)`, and the runtime's
`maxAlignedSize` budgets 34 bytes for a field atom whose serialized
form is 35 when the value needs all 32 bytes (the length prefix grows
to two bytes past 31). An entry with enough full-width atoms makes the
VM throw `exceeded structure bounds` while iteration still works. A
maintainer reverting to Field addition would see every suite pass and
break the typed accessors.

Upstream: the shortfall is in midnight-ledger's
`transient-crypto/src/fab.rs`; LFDT-Minokawa/compact#297 reports the
same symptom from a `List<Vector<2, ContractAddress>>`.
The swap is byte- and row-identical: the golden vector passes and
_deliver stays at k=15, rows=26723. compile:token depends on
compile:math for the new import.

Refs: #727
@0xisk
0xisk force-pushed the feat/confidential-note-token-delivery branch from 69a3ebe to b1944ae Compare October 21, 2026 14:28
@0xisk
0xisk changed the base branch from main to feat/math-uintn October 21, 2026 14:28
@0xisk
0xisk added this pull request to stack #1190 October 21, 2026 14:29

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Confidential Note Fungible Token Delivery extension

1 participant