Confidential Assets: On-Chain Production Readiness - #299
Conversation
musitdev
left a comment
There was a problem hiding this comment.
About the events, we should do the same as Aptos V1.1. We emit an event for each operation that change the balance (need to add rotate, rollover, normalize) and we put the new changed balances in the event.
We need to put event for each admin operation so we can track them of chain to trigger alerts.
added:
|
…st (#305) # Formal: Move bytecode model, refinement proofs, Move VM ↔ Lean difftest ## Summary Adds a **Lean 4 bytecode interpreter** (`AptosFormal.Move.*`), **refinement proofs** (including a kernel-checked `vector::contains` theorem in `Refinement/Vector.lean`), a **Rust ↔ Lean differential harness** (`move-lean-difftest`) comparing the real Move VM to the Lean evaluator on shared oracles, and supporting **stdlib vector specs** plus **`AptosStd`** layout for crypto/hash modules. Workspace `Cargo.toml` registers the difftest crate. --- ## What changed (concise) | Area | Notes | | ---- | ----- | | **Move semantics** | `Value`, `Instr`, `State`, `Step`, `Native`, `Programs` (Core + Vector bytecode, including real disassembly-backed programs). | | **Refinement** | `Refinement/Core.lean` (`rfl` programs); `Refinement/Vector.lean` — `vector::contains` vs `Std.Vector.contains`. | | **Specs / tests** | `Std/Vector/Operations.lean`; `Tests/Defs`, `Tests/Vector`. | | **Difftest** | Crate `move-lean-difftest` (suites: vector, BCS, hash), JSON oracle, Lean `DiffTest` runner; [`difftest/README.md`](https://github.com/movementlabsxyz/aptos-core/blob/move-lean/aptos-move/framework/formal/difftest/README.md). | | **Layout** | `AptosStd` for Ristretto / SHA3-512; ConfidentialAsset imports updated. | | **Docs** | [`formal/README.md`](https://github.com/movementlabsxyz/aptos-core/blob/move-lean/aptos-move/framework/formal/README.md) (entry), [`lean/README.md`](https://github.com/movementlabsxyz/aptos-core/blob/move-lean/aptos-move/framework/formal/lean/README.md) (full runbook), [`Move/README.md`](https://github.com/movementlabsxyz/aptos-core/blob/move-lean/aptos-move/framework/formal/lean/AptosFormal/Move/README.md) (bytecode model + roadmap). | --- ## How to run — Lean proofs Prerequisites: [elan](https://github.com/leanprover/elan) (Lean 4.24.0 + Mathlib are pinned; see [`lean/README.md`](https://github.com/movementlabsxyz/aptos-core/blob/move-lean/aptos-move/framework/formal/lean/README.md)). ```bash cd aptos-move/framework/formal/lean lake build ``` Optional: confirm no proof holes: ```bash cd aptos-move/framework/formal/lean grep -r "sorry" AptosFormal/ --include="*.lean" ``` (Axiom inventory and registration proofs: still in [`lean/README.md`](https://github.com/movementlabsxyz/aptos-core/blob/move-lean/aptos-move/framework/formal/lean/README.md).) --- ## How to run — differential tests (VM vs Lean) **All suites** (from repo root): ```bash ./aptos-move/framework/formal/difftest.sh ``` Per-suite runs, oracle paths, and flags: **[`difftest/README.md`](https://github.com/movementlabsxyz/aptos-core/blob/move-lean/aptos-move/framework/formal/difftest/README.md)**. --- ## How to run — Move golden tests & byte consistency Companion Move tests and golden-byte drift check (optional for this PR, but part of the formal workflow). Commands use the **Movement** CLI (`movement`), not `aptos`: ```bash movement move test --package-dir aptos-move/framework/move-stdlib --filter formal_goldens movement move test --package-dir aptos-move/framework/aptos-experimental --filter formal_goldens bash aptos-move/framework/formal/check_golden_consistency.sh ``` Details: [`lean/README.md`](https://github.com/movementlabsxyz/aptos-core/blob/move-lean/aptos-move/framework/formal/lean/README.md) (sections *Companion Move golden tests* and *Checking Move / Lean golden consistency*). --- ## Editor Open the Lake project at **`aptos-move/framework/formal/lean`** for Lean 4 tooling — see [`lean/README.md`](https://github.com/movementlabsxyz/aptos-core/blob/move-lean/aptos-move/framework/formal/lean/README.md) (*Editor setup*).
## Summary Extend the Move stdlib formal verification in Lean 4: add a complete `vector::index_of` bytecode refinement proof, and add new specification modules for `error`, `option`, `signer`, `fixed_point32`, and `bit_vector` with bytecode programs, native models, and refinement proofs connecting them to the existing Move bytecode interpreter. ## Changes **`Refinement/Vector.lean` — add `index_of` refinement proof (+927 lines)** Building on the existing `vector::contains` refinement, adds a full correctness proof for `vector::index_of` (bytecode index 19 in `stdModuleEnv`), covering: - Loop setup (7 steps from `evalProg` to loop header) - Found path (element match → return `(true, k)`) - Iteration path (no match → advance to `k+1`) - Top-level theorems: `vectorIndexOf_returnValues_found` and `vectorIndexOf_returnValues_notFound` - Partial `vector::reverse` proof sketch (`sorry`) Key proof techniques: - `indexOfLoopFrame` uses `(List.map MoveValue.u64 xs).length.toUInt64` to match the VM's `step` computation, enabling `rfl` proofs (mirrors the `contains` pattern) - `hfail` / `hio` inductive proofs use `suffices` to generalize over the `indexOf.go` offset parameter, since naive list induction doesn't track offsets correctly - `iterN13` outputs `k.toUInt64 + 1` (what the kernel computes) with a `contains_uint64_succ` conversion in the run chain **New stdlib specification modules** - `Std/Error.lean` — canonical error codes and abort-code arithmetic - `Std/Option.lean` — `option::swap_or_fill` specification and properties - `Std/Signer.lean` — signer address extraction - `Std/FixedPoint32.lean` — fixed-point arithmetic (`create_from_rational`, `floor`, `ceil`, `round`, `min`, `max`) - `Std/BitVector.lean` — bit-vector operations (`new`, `set`, `shift_left`, `is_index_set`) **Bytecode & native plumbing** - `Move/Programs/StdPrimitives.lean` — bytecode arrays for `std::error::canonical` + 13 wrappers and `std::bit_vector::length`, using the existing instruction set from `Move/Instr.lean` - `Move/Native/StdPrimitives.lean` — native function models for `signer`, `fixed_point32`, `option`, and `bit_vector` operations - `Refinement/StdPrimitives.lean` — refinement proofs connecting bytecode/natives to specs (proved via `rfl` — the Lean kernel fully reduces `eval` for concrete non-looping programs) - `Tests/StdPrimitives.lean` — `native_decide` smoke tests for stdlib operations ## File changes summary | File | Description | |------|-------------| | `Refinement/Vector.lean` | Add `vector::index_of` refinement proof | | `Std/Error.lean` | New: error code specs | | `Std/Option.lean` | New: option swap/fill specs | | `Std/Signer.lean` | New: signer specs | | `Std/FixedPoint32.lean` | New: fixed-point arithmetic specs | | `Std/BitVector.lean` | New: bit-vector operation specs | | `Move/Programs/StdPrimitives.lean` | New: stdlib bytecode programs | | `Move/Native/StdPrimitives.lean` | New: stdlib native function models | | `Refinement/StdPrimitives.lean` | New: stdlib refinement proofs | | `Tests/StdPrimitives.lean` | New: stdlib smoke tests | | `README.md` | Document new modules | | `lakefile.lean` | Register new modules | ## Testing - **`lake build`** — passes (exit code 0). Only pre-existing `sorry` warnings in unrelated files (plus tracked `sorry` in new `FixedPoint32.lean`, `BitVector.lean`, and the `reverse` sketch). - **`lake build difftest`** — Lean difftest executable compiles successfully (2172/2172 jobs). - **`difftest.sh`** — full differential test pipeline: **227 passed, 0 failed, 0 skipped**. - Step 0: Rust corpus verification ✅ - Step 1: Move VM oracle generation ✅ - Step 2: Lean evaluator vs oracle ✅ ## Key Areas to Review - **`Refinement/Vector.lean`** lines 814–824 (`indexOfLoopFrame`): uses `(List.map MoveValue.u64 xs).length.toUInt64` to match the `contains` pattern, enabling ~20 downstream `rfl` proofs. - **`hfail` / `hio` proofs** in `vectorIndexOf_returnValues_notFound` / `_found`: use `suffices` to generalize over the `indexOf.go` offset parameter. - **`sorry` declarations** in `Std/FixedPoint32.lean` (2), `Std/BitVector.lean` (1), and `Refinement/Vector.lean` (`reverse` sketch) are tracked for future work. ## Type of Change - [x] New feature (non-breaking change which adds functionality) --------- Co-authored-by: andygolay <andygolay@users.noreply.github.com>
## Description ### Background: how batch verification works A confidential transfer proof contains multiple algebraic equations that the on-chain verifier must check (e.g. "sender's new balance is correct", "recipient's amount is correct", "each auditor's ciphertext is correct"). Checking them one by one is expensive. **Multi-scalar multiplication (MSM)** batching is an optimization: the verifier combines all equations into a single equation by multiplying each one by a different random weight. If the combined equation holds, all individual ones hold — with overwhelming probability. These random weights are called **gammas**. Each gamma is derived as `SHA2-512(rho || i || j)` where **rho** is a fresh random scalar and **(i, j)** is a unique index pair. The uniqueness of `(i, j)` is what guarantees every gamma is distinct. If two different proof relations accidentally receive the same `(i, j)` — and therefore the same gamma — an attacker could craft values where errors in one relation cancel out errors in the other, bypassing the batch check. ### The bug The function [`msm_transfer_gammas`](aptos-move/framework/aptos-experimental/sources/confidential_asset/confidential_proof.move) assigns gamma index groups as follows: | Group | Count | `i` index | What it checks | |-------|-------|-----------|----------------| | g1 | 1 | 1 | Overall balance consistency | | g2s | 8 | 2 | Sender's new balance (8 chunks of 16 bits each) | | g3s | 4 | 3 | Recipient's amount (4 chunks) | | g4s | 4 | 4 | Transfer amount range proof binding | | g5 | 1 | 5 | Sender encryption key consistency | | g6s | 8 | 6 | Current balance (8 chunks) | | g7s | 4 per auditor | 7+k | Auditor `k`'s ciphertext correctness | | g8s | 4 | **was 8** | Sender's copy of the transfer amount | With 2+ auditors, `g7s` for auditor `k=1` uses index `7+1 = 8` — the same `i` as `g8s`. Two different proof relations get identical gammas, weakening batch soundness. With 0 or 1 auditors there is no collision (g7s uses only index 7, g8s uses 8). ### The fix `g8s` now uses `i = auditors_count + 7` instead of the hardcoded `8`, so it is always one past the last `g7s` entry: - `g7s[k]`: index `(7+k, j)` for `k ∈ [0, n)` - `g8s`: index `(7+n, j)` This is a verifier-only change. Gammas are not part of the proof — they are computed on-chain after the proof is submitted. **No change to proof generation, no client SDK impact.** Whitepaper §9 updated with a new "Batch Soundness" subsection documenting the gamma layout. ## How Has This Been Tested? - 78 Move unit tests pass (`move_experimental_unit_tests`), including multi-auditor transfer tests and a new regression test (`test_g8s_gamma_no_collision_with_g7s`) - 143 Rust e2e tests pass (`e2e-move-tests -- confidential_asset`), including `confidential_transfer_with_voluntary_auditors_only` (1-3 auditors) and `confidential_transfer_asset_auditor_plus_voluntary_auditors` (asset auditor + 0-3 voluntary) - The regression test proves the collision was real (`msm_gamma_2(rho, 8, 0) == msm_gamma_2(rho, 1+7, 0)`) and that the fix eliminates it for all sub-indices ## Key Areas to Review - [`confidential_proof.move:1605-1609`](aptos-move/framework/aptos-experimental/sources/confidential_asset/confidential_proof.move#L1605-L1609) — the one-line fix in `msm_transfer_gammas` - [`confidential_proof.move:2453-2493`](aptos-move/framework/aptos-experimental/sources/confidential_asset/confidential_proof.move#L2453-L2493) — regression test proving the collision existed and the fix works - [`whitepaper.md` §9 Batch Soundness](aptos-move/framework/aptos-experimental/whitepaper.md) — new subsection documenting gamma index layout ## Type of Change - [ ] New feature - [x] Bug fix - [ ] Breaking change - [ ] Performance improvement - [ ] Refactoring - [ ] Dependency update - [x] Documentation update - [x] Tests ## Which Components or Systems Does This Change Impact? - [ ] Validator Node - [ ] Full Node (API, Indexer, etc.) - [ ] Move/Aptos Virtual Machine - [x] Aptos Framework - [ ] Aptos CLI/SDK - [ ] Developer Infrastructure - [ ] Move Compiler - [ ] Other (specify) ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I tested both happy and unhappy path of the functionality - [x] I have made corresponding changes to the documentation
…ty-point pubkeys (#330) # confidential_asset: fix `sub_balances_mut` and reject identity-point pubkeys Two hardening fixes in `aptos_experimental::confidential_asset`. ## Fix 1 — `confidential_balance::sub_balances_mut` was performing addition The body called `twisted_elgamal::ciphertext_add_assign` instead of `ciphertext_sub_assign`, so `sub_balances_mut` behaved identically to `add_balances_mut`. No in-tree caller today, but the function is `public` and exported; any future caller debiting via `sub_balances_mut` would silently credit instead. Deleted `sub_balances_mut` function as it is not used. ## Fix 2 — `ristretto255_twisted_elgamal::new_pubkey_from_bytes` accepted the identity point There is no scalar `dk` such that `dk⁻¹ · H = identity`, so an identity public key does not correspond to any keypair. Accepting it admits two degenerate states: - **Registration sigma is forgeable.** The proof `s·H + e·ek == R` collapses to `s·H == R` when `ek = identity`, so a registrant can pass `register` without holding any `dk`. The resulting account is unspendable — anything transferred to it is permanently locked. - **Auditor channel can be silently disabled.** If `set_asset_auditor` or `set_chain_auditor` (gated by `system_addresses::assert_aptos_framework`) is given an identity key, every subsequent transfer's auditor ciphertext is undecryptable and the auditor-binding term in the transfer proof becomes degenerate, letting senders submit auditor amounts unrelated to the actual transfer. All `CompressedPubkey` values flow through `new_pubkey_from_bytes` (`register`, `set_asset_auditor`, `set_chain_auditor`, `deserialize_auditor_eks`), so a single check at the deserializer covers every entry path. Changes in `ristretto255_twisted_elgamal.move`: - `new_pubkey_from_bytes` returns `None` for the identity point in addition to the existing `None` for non-canonical encodings. The check is a byte equality against `point_identity_compressed()` (the canonical encoding of identity is uniquely 32 zero bytes). - New public helper `is_identity_pubkey(&CompressedPubkey): bool` for callers that obtain a `CompressedPubkey` through other means and want to re-validate. ## Tests New module `tests/confidential_asset/audit_regression_tests.move` — 6 tests: - `sub_balances_mut_self_yields_zero` — subtracting a balance from itself decrypts to 0. - `sub_balances_mut_zero_is_identity` — subtracting an encryption of zero preserves the amount. - `new_pubkey_from_bytes_rejects_identity` — 32 zero bytes ⇒ `None`. - `new_pubkey_from_bytes_accepts_real_key` — generated keypair round-trips; `is_identity_pubkey` returns `false`. - `new_pubkey_from_bytes_rejects_non_canonical` — pre-existing rejection preserved. - `identity_rejection_composes_with_is_some` — callers using `assert!(... .is_some())` now reject identity with no caller-side change. ## Testing: ``` cd aptos-move/framework/aptos-experimental aptos move test --skip-fetch-latest-git-deps \ --named-addresses aptos_experimental=0x7 \ --filter confidential ``` Expected: 64 tests pass (58 existing + 6 new). ## Notes - No state schema or proof-format changes. Existing accounts and ciphertexts continue to verify. - The only other `CompressedPubkey` constructor is `pubkey_from_secret_key`, which is `#[test_only]`.
## Description View function added in `fungible_asset.move` (see diff). Required for the changes in #299 Confidential Assets, so would be good to include for testing against testnet. ## How Has This Been Tested? Two unit tests: - test_is_asset_type_dispatchable_false_for_plain_fa - test_is_asset_type_dispatchable_true_with_derived_supply
# Two-tier auditor model + epoch tracking for confidential assets ## Summary The Confidential Asset module previously supported a single optional per-asset auditor. This PR introduces a **chain-level auditor** (always required, governed at the framework address) layered alongside the existing per-asset auditor, plus **monotonic epoch tracking and append-only history** for both layers. Every confidential transfer now stamps the active chain and asset auditor epochs onto its `Transferred` event, enabling reconstruction of which historical key covered which transfer years after a rotation. ## Behavior changes ### Auditor slot layout `auditor_eks` (and the matching `auditor_amounts`) now have a fixed prefix: ``` [0] chain-level auditor (always required) [1] asset-specific auditor (required iff get_asset_auditor(token).is_some()) [2..] voluntary auditors (sender's choice; ordered) ``` Slot identity is bound into the transfer's Fiat–Shamir transcript via the order of `auditor_eks` (existing mechanism in `confidential_proof::fiat_shamir_transfer_sigma_proof_challenge`), so a sender cannot substitute one slot for another. ### Validation `validate_auditors` now: - Aborts with new error `ECHAIN_AUDITOR_NOT_SET` if no chain auditor is configured. - Rejects the transfer if `auditor_eks[0]` ≠ active chain auditor. - Rejects the transfer if an asset auditor is set and `auditor_eks[1]` ≠ it. - Otherwise behaves as before (length checks, ciphertext consistency). ### Epoch + history `FAController` and `FAConfig` each gain: - `*_auditor_epoch: u64` — bumped on every set/rotate/clear (including clears). - `*_auditor_history: vector<AuditorEntry>` — append-only; each entry carries `[activated_at_epoch, deactivated_at_epoch)` (`0` while still active). `Transferred` event gains `chain_auditor_epoch` and `asset_auditor_epoch` (`0` when the asset has no auditor). ### Renamed / new module API | Before | After | | ----------------------------------- | ------------------------------------------- | | `set_auditor` | `set_asset_auditor` | | `get_auditor` | `get_asset_auditor` | | `AuditorChanged` | `AssetAuditorChanged` (+`new_epoch` field) | | `FAConfig.auditor_ek` | `FAConfig.asset_auditor_ek` | | — | `set_chain_auditor` | | — | `get_chain_auditor` / `*_epoch` / `*_history` | | — | `get_asset_auditor_epoch` / `*_history` | | — | `ChainAuditorChanged` | | — | `AuditorEntry` struct | | — | `ECHAIN_AUDITOR_NOT_SET` | ### In-flight proof invalidation on rotation Auditor identity is bound into the proof's Fiat–Shamir transcript, so rotating either layer invalidates any user transactions signed against the old key but not yet executed. Documented inline on `set_chain_auditor` / `set_asset_auditor`. ## Tests ### Move unit tests (`confidential_asset_tests.move`) — 64/64 passing New coverage: - `fail_transfer_if_chain_auditor_unset` — abort when chain auditor missing. - `fail_transfer_if_slot0_not_chain_auditor` — slot 0 mismatch rejected. - `fail_transfer_if_asset_auditor_required_but_missing` — slot 1 absent when required. - `success_voluntary_auditors_without_asset_auditor` — slot 2+ accepted with no asset auditor. - `fail_transfer_after_chain_auditor_rotation` — pre-rotation old-key proof rejected. - `success_chain_auditor_rotation_tracks_history` — rotations bump epochs, history records prior keys, `Transferred` stamps current epoch. Existing transfer tests updated for the new slot layout (chain auditor auto-prepended via `get_chain_auditor()` in shared helpers). ### Rust e2e tests (`confidential_asset_e2e.rs`) — 7/7 passing New coverage: - `confidential_transfer_rejects_when_chain_auditor_unset` - `confidential_transfer_rejects_when_slot0_not_chain_auditor` - `confidential_transfer_rejects_after_chain_auditor_rotation` `fresh_harness` now installs a default chain auditor; existing tests pass through unchanged because the test-only `pack_confidential_transfer_proof_*` helpers auto-prepend the chain auditor. A `fresh_harness_no_chain_auditor` variant and `pack_transfer_audited_verbatim` helper support the rejection-path tests. > Note: `cargo test -p e2e-move-tests confidential_asset` requires `RUST_MIN_STACK=33554432` (or higher) — pre-existing requirement, documented in this module's file header. ## Follow-ups / out of scope - **Chain-level key custody.** The contract enforces that the chain-level auditor *exists* and is bound into every transfer, but it can't enforce *who* holds the private key or *how*. A separate decision is needed before launch on whether the key sits with a qualified third-party custodian and whether custody is single-party or threshold/MPC. Strictly an off-chain operational call. - **History sizing.** `chain_auditor_history` and `asset_auditor_history` are unbounded `vector<AuditorEntry>` on `FAController` / `FAConfig`. Fine pre-launch; if rotation cadence ends up high in production, follow up with a paginated view or periodic archival. Not a correctness or compliance gap — just a storage-growth concern. - **Per-user auditor epoch tracking on `ConfidentialAssetStore`.** Not needed in this codebase — auditors only receive ciphertexts at transfer time, not on the balance, so rollover-staleness (the issue addressed in zkSecurity finding #1 upstream) does not apply here. - **Documentation regeneration.** `aptos-experimental/doc/confidential_asset.md` is left untouched in this PR; regenerate via `movement move document` against a locally-built `movement` binary so the markup style stays consistent. ## Files changed - `aptos-move/framework/aptos-experimental/sources/confidential_asset/confidential_asset.move` - `aptos-move/framework/aptos-experimental/sources/confidential_asset/confidential_gas_e2e_helpers.move` - `aptos-move/framework/aptos-experimental/tests/confidential_asset/confidential_asset_tests.move` - `aptos-move/e2e-move-tests/src/tests/confidential_asset_e2e.rs`
…rimental` to `aptos-framework` (#366) # Move confidential asset code from `aptos-experimental` to `aptos-framework` ## Summary Promotes the Confidential Asset Standard from `aptos-experimental` (`0x7`) to `aptos-framework` (`0x1`). The module family is no longer experimental — it now lives alongside the rest of the framework and is published at the framework address. ## What moved Source modules (all `0x7::*` → `0x1::*`): - `confidential_asset` + `.spec.move` - `confidential_balance` + `.spec.move` - `confidential_proof` + `.spec.move` - `ristretto255_twisted_elgamal` + `.spec.move` - `confidential_gas_e2e_helpers` Unit tests: - `confidential_asset_tests.move` - `confidential_proof_tests.move` - `ristretto255_twisted_elgamal_tests.move` Everything under `aptos-experimental/sources/confidential_asset/` and `aptos-experimental/tests/confidential_asset/` is gone; the equivalents now live under `aptos-framework/sources/confidential_asset/` and `aptos-framework/tests/confidential_asset/`. ## Code changes - Module declarations re-addressed: `module aptos_experimental::*` → `module aptos_framework::*`. - All `use aptos_experimental::*` imports inside the module family rewritten to `use aptos_framework::*`. - Re-rendered framework reference docs: removed the four `0x7::*` entries from `aptos-experimental/doc/overview.md` and added the corresponding `0x1::*` entries to `aptos-framework/doc/overview.md`. The generated per-module docs (`confidential_asset.md`, `confidential_balance.md`, `confidential_proof.md`, `ristretto255_twisted_elgamal.md`) now live under `aptos-framework/doc/`. - `aptos_framework_sdk_builder.rs` regenerated with entries for the new framework entry functions. ## Downstream call-site updates - `aptos-move/move-examples/confidential_asset/Move.toml` — drop the `aptos-experimental` dep; all examples already use `aptos_framework::confidential_asset`. - `aptos-move/move-examples/confidential_asset/tests/*.move` — rewrite `use aptos_experimental::*` → `use aptos_framework::*` across the seven example tests (deposit, normalize, register, rollover, rotate, transfer, withdraw). - `scripts/chain-auditor-bootstrap/Move.toml` + `sources/set_chain_auditor_admin.move` — repoint at the framework module. ## Rust e2e test update `aptos-move/e2e-move-tests/src/tests/confidential_asset_e2e.rs` → `confidential_asset.rs` (registered as `mod confidential_asset;` in `tests/mod.rs`). The module-injection harness was retooled to match the new layout: - Stops compiling `aptos-experimental` and looking for `0x7::*` modules. - Test-compiles `aptos-framework` and overlays only the confidential-asset module family (`confidential_asset`, `confidential_balance`, `confidential_proof`, `confidential_gas_e2e_helpers`, `ristretto255_twisted_elgamal`) plus `event`. It deliberately does **not** replace other `0x1` framework modules — doing so would invalidate state that genesis already published (account/fungible-store/transaction-validation layouts) and break the gas-fee prologue. - `assert_kept_failure` tightened to require `Keep`-with-non-success instead of "anything that isn't Success" — a fee-discard was previously masquerading as a kept failure and hiding real bugs. - Dropped 13 unused helper functions that were carryovers from the experimental harness. ## Verification All 14 confidential-asset e2e tests pass against the new layout: ``` RUST_MIN_STACK=67108864 cargo test --release -p e2e-move-tests confidential_asset ... test result: ok. 14 passed; 0 failed; 0 ignored; 0 measured; 249 filtered out ``` ## Breaking changes Any off-chain caller or downstream Move package referencing the previous `0x7::confidential_asset` (and friends) must be updated to `0x1::confidential_asset`. The module functions, struct shapes, and entry signatures are unchanged. ## Test plan - [x] `cargo test --release -p e2e-move-tests confidential_asset` — 14/14 pass - [ ] Re-run framework Move unit tests for the relocated modules - [ ] Spot-check the move-examples build against the framework dep - [ ] Verify generated docs render correctly under `aptos-framework/doc/`
|
Just flagging - I think → If we want to clean up those dependent on move 2.2 maybe we drop |
There was a problem hiding this comment.
Is this intentional here? It is relevant to fun get_asset_auditor, see below
There was a problem hiding this comment.
no i think it's from aptos, updated
| { | ||
| let fa_config_address = get_fa_config_address(token); | ||
|
|
||
| if (!is_allow_list_enabled() && !exists<FAConfig>(fa_config_address)) { |
There was a problem hiding this comment.
allow_list_enabled: chain_id::get() == MAINNET_CHAIN_ID, therefore if MAINNET_CHAIN_ID is set to 126, the first gate !is_allow_list_enabled() will always be false leading to this branch unreachable
…or unreachable branch
|
Several docs under |
| @@ -0,0 +1,17 @@ | |||
| // Enables on-chain feature flag 87 (BULLETPROOFS_BATCH_NATIVES) and reconfigures. | |||
| // Sender must be the core resources account (localnet: key in <test-dir>/mint.key). | |||
| script { | |||
There was a problem hiding this comment.
This file can be removed from here to make the worktree cleaner. This script is in the governance proposal repo already
removed |
…_experimental compiles
thanks, pushed commit dropping it |
| const FIAT_SHAMIR_NORMALIZATION_SIGMA_DST: vector<u8> = b"MovementConfidentialAsset/Normalization"; | ||
| const FIAT_SHAMIR_REGISTRATION_SIGMA_DST: vector<u8> = b"MovementConfidentialAsset/Registration"; | ||
|
|
||
| const BULLETPROOFS_DST: vector<u8> = b"AptosConfidentialAsset/BulletproofRangeProof"; |
There was a problem hiding this comment.
Should be changed to MovementConfidentialAsset/BulletproofRangeProof ?
…tart-localnet-confidential-assets.sh
|
Found 1 test failure on Blacksmith runners: Failure
|
|
Found 1 test failure on Blacksmith runners: Failure
|
Confidential Assets: On-Chain Production Readiness
Summary
Upgrades Movement's confidential asset modules toward production readiness. Key changes vs
m1:prepend_domain_context, withMovementConfidentialAsset/...DST prefixesregistersender_auditor_hintbound into the transfer sigma transcript and emitted onTransferred, alongsideek_volun_audsvector::contains,vector::index_of,std::error, andbit_vector::length, plus registration L0 crypto proofs and L2 bytecode refinement#[test_only]pack helpersaptos-experimentaltrading subtree (Move 2.2 dependent) for clean CI243 files changed, +40648 / −5345
What changed
Fiat–Shamir & crypto
All sigma challenges use
ristretto255::new_scalar_from_sha2_512(DST || domain_context || public_inputs).prepend_domain_context()prependschain_id(1 byte),sender(BCS address), andcontract_address(BCS address) so proofs are bound to the deployed module, not just the user and chain. MSM gamma scalars use the same SHA2-512 derivation.Registration proof
verify_registration_proof()performs a standard Schnorr check (s * H + e * ek == R) with the challenge derived from the domain-prefixed transcript.registernow requiresregistration_proof_commitmentandregistration_proof_responsearguments.Transfer events
confidential_transferaccepts asender_auditor_hint: vector<u8>that gets hashed into the transfer sigma transcript. TheTransferredevent now includes bothsender_auditor_hintandek_volun_auds(serialized voluntary-auditor sigma commitments).API changes
All proof verification and
#[test_only]prove_*helpers takechain_id,sender, andcontract_address.registergains registration proof vectors. These are breaking changes vsm1.Package layout
Trading / order-book sources removed from
aptos-experimental(Move 2.2 dependencies). Onlyconfidential_*modules remain.Scripts & localnet
scripts/start-localnet-confidential-assets.sh— starts localnet with Docker, enables feature flag 87, optionally publishesaptos-experimentalscripts/enable-confidential-assets-feature-87.move— enablesBULLETPROOFS_BATCH_NATIVESDocumentation
whitepaper.md— Movement confidential-assets designREGISTRATION_VERIFY_REVIEW.md— auditor-facing review ofverify_registration_proofCONFIDENTIAL_ASSETS_FORMAL_VERIFICATION_PLAN.md— L0–L5 formal verification roadmapCONFIDENTIAL_ASSETS_DIFFERENTIAL_TESTING_PLAN.md— difftest tiers and coverage planHow this differs from Aptos
We do not use Aptos's generic sigma-protocol framework (
sigma_protocol*.movefrom their v1.1). We keep per-proof verification inconfidential_proof.move, use SHA2-512 withMovementConfidentialAsset/...DSTs andprepend_domain_contextfor domain separation, and implement registration as inline Schnorr.Cryptographic primitives
Test plan
Move unit tests
Covers registration / withdraw / transfer / normalize / rotate happy paths and wrong-input failures (wrong chain, sender, contract, balances, EKs, auditor lists,
sender_auditor_hint).Rust VM e2e
RUST_MIN_STACK=8388608 cargo test -p e2e-move-tests confidential_asset_e2e -- --nocaptureFull entrypoint tests: register, deposit, rollovers, confidential_transfer, withdraw_to, rotate_encryption_key, set_auditor, voluntary auditors, negatives, gas spot-checks.
TS SDK (cross-repo)
Companion SDK work lives in MoveIndustries/ts-sdk. To test end-to-end on localnet:
Checklist
confidential_asset_e2epasseslake buildpasses (exit code 0)difftest.shpasses (227 passed, 0 failed)