diff --git a/.github/workflows/publish-crates.yml b/.github/workflows/publish-crates.yml index 1bd33dd28..037b52c42 100644 --- a/.github/workflows/publish-crates.yml +++ b/.github/workflows/publish-crates.yml @@ -55,7 +55,7 @@ jobs: # Skipped: stellar-fee-abstraction (dev-deps on stellar-tokens, stellar-macros) # Skipped: stellar-tokens (depends on stellar-contract-utils, stellar-governance) - # Skipped: stellar-confidential (not published to crates.io yet) + # Skipped: stellar-confidential (depends on stellar-contract-utils) # Skipped: stellar-zk-email (not published to crates.io yet) publish: @@ -106,3 +106,7 @@ jobs: # stellar-fee-abstraction dev-depends on stellar-tokens, stellar-macros - name: Publish stellar-fee-abstraction run: cargo publish -p stellar-fee-abstraction --no-verify + + # stellar-confidential depends on stellar-contract-utils + - name: Publish stellar-confidential + run: cargo publish -p stellar-confidential --no-verify diff --git a/CLAUDE.md b/CLAUDE.md index e26b20a4f..8a8567632 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -160,8 +160,6 @@ Reversing the two is a common mistake. - All packages have `[package.metadata.stellar] cargo_inherit = true`. - Workspace fields use `field.workspace = true` shorthand; library crates set `crate-type = ["lib", "cdylib"]`, examples set `["cdylib"]` only. - `stellar-confidential` is the exception (`["lib"]`, unpublished, no - `alloc` feature); see `packages/confidential/README.md#packaging`. - Two-step transfer pattern (initiate + accept with `live_until_ledger`) for any owner/admin handover. Reuse `role_transfer` rather than rolling a new one. diff --git a/Cargo.lock b/Cargo.lock index 23248d36c..cbc62153a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2948,7 +2948,8 @@ checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "ultrahonk_soroban_verifier" version = "0.1.0" -source = "git+https://github.com/NethermindEth/rs-soroban-ultrahonk?rev=097da17df8b0b971d71885566034958a8caebab4#097da17df8b0b971d71885566034958a8caebab4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63ad166fd0d4fcecdddd094a92e496eb2d815bc1694d5f22a7aac63fc5de95d8" dependencies = [ "soroban-sdk 28.0.0", ] diff --git a/Cargo.toml b/Cargo.toml index a19371b5a..9d5ea9390 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,10 +68,9 @@ p256 = "0.13.2" serde = { version = "1", default-features = false } serde-json-core = { version = "0.6.0", default-features = false } -# UltraHonk proof-verification backend for the confidential token. Pinned to a -# specific commit because the upstream crate has no tagged release. The pinned -# commit carries the remediation of the OpenZeppelin audit performed at 661db07. -ultrahonk-soroban-verifier = { git = "https://github.com/NethermindEth/rs-soroban-ultrahonk", rev = "097da17df8b0b971d71885566034958a8caebab4", package = "ultrahonk_soroban_verifier", default-features = false } +# UltraHonk proof-verification backend for the confidential token. 0.1.0 carries +# the remediation of the OpenZeppelin audit performed at 661db07. +ultrahonk-soroban-verifier = { version = "0.1.0", package = "ultrahonk_soroban_verifier" } # members stellar-access = { path = "packages/access", version = "0.7.1" } diff --git a/examples/confidential/allowlist-policy/Cargo.toml b/examples/confidential/allowlist-policy/Cargo.toml index c8f4551ca..41180ad87 100644 --- a/examples/confidential/allowlist-policy/Cargo.toml +++ b/examples/confidential/allowlist-policy/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { workspace = true, features = ["alloc"] } +soroban-sdk = { workspace = true } stellar-access = { workspace = true } stellar-confidential = { workspace = true } stellar-macros = { workspace = true } diff --git a/examples/confidential/auditor/Cargo.toml b/examples/confidential/auditor/Cargo.toml index 6d5eeabf8..ff8ec5ebb 100644 --- a/examples/confidential/auditor/Cargo.toml +++ b/examples/confidential/auditor/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { workspace = true, features = ["alloc"] } +soroban-sdk = { workspace = true } stellar-access = { workspace = true } stellar-confidential = { workspace = true } stellar-macros = { workspace = true } diff --git a/examples/confidential/compliant-token/Cargo.toml b/examples/confidential/compliant-token/Cargo.toml index e955cbeee..ae5641a85 100644 --- a/examples/confidential/compliant-token/Cargo.toml +++ b/examples/confidential/compliant-token/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { workspace = true, features = ["alloc"] } +soroban-sdk = { workspace = true } stellar-access = { workspace = true } stellar-confidential = { workspace = true } stellar-macros = { workspace = true } diff --git a/examples/confidential/factory/Cargo.toml b/examples/confidential/factory/Cargo.toml index 5efe2830d..d8cdb4c10 100644 --- a/examples/confidential/factory/Cargo.toml +++ b/examples/confidential/factory/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { workspace = true, features = ["alloc"] } +soroban-sdk = { workspace = true } stellar-confidential = { workspace = true } [dev-dependencies] diff --git a/examples/confidential/factory/testdata/confidential_allowlist_policy_example.wasm b/examples/confidential/factory/testdata/confidential_allowlist_policy_example.wasm index 52fab1eb4..b71c174e9 100644 Binary files a/examples/confidential/factory/testdata/confidential_allowlist_policy_example.wasm and b/examples/confidential/factory/testdata/confidential_allowlist_policy_example.wasm differ diff --git a/examples/confidential/factory/testdata/confidential_compliant_token_example.wasm b/examples/confidential/factory/testdata/confidential_compliant_token_example.wasm index fa617f87b..fb40b2987 100644 Binary files a/examples/confidential/factory/testdata/confidential_compliant_token_example.wasm and b/examples/confidential/factory/testdata/confidential_compliant_token_example.wasm differ diff --git a/examples/confidential/verifier/Cargo.toml b/examples/confidential/verifier/Cargo.toml index 029e33ccb..74ff8d052 100644 --- a/examples/confidential/verifier/Cargo.toml +++ b/examples/confidential/verifier/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { workspace = true, features = ["alloc"] } +soroban-sdk = { workspace = true } stellar-access = { workspace = true } stellar-confidential = { workspace = true } stellar-macros = { workspace = true } diff --git a/packages/confidential/CLAUDE.md b/packages/confidential/CLAUDE.md index 8ca22252a..7172e6467 100644 --- a/packages/confidential/CLAUDE.md +++ b/packages/confidential/CLAUDE.md @@ -17,10 +17,6 @@ The crate ships one token contract at its root (`src/lib.rs` / `src/storage.rs` Balances are Pedersen commitments on Grumpkin. Every operation that opens or re-randomizes a commitment carries a proof the contract forwards to the verifier contract; `deposit`, `merge`, and `revoke_spender` are proofless homomorphic folds. -## Packaging - -The crate is `lib` only, `publish = false`, and depends on `soroban-sdk` without its `alloc` feature, so contracts built on it supply the global allocator. These depart from the root guide's library conventions for reasons recorded in `README.md#packaging`; keep all three when editing `Cargo.toml`. - ## Errors `ConfidentialTokenError` occupies **3500–3510**. The root guide's range list predates this module and omits it. Stay in the 3500s; do not open a new range for the satellites. diff --git a/packages/confidential/Cargo.toml b/packages/confidential/Cargo.toml index 855752950..9e01b9279 100644 --- a/packages/confidential/Cargo.toml +++ b/packages/confidential/Cargo.toml @@ -3,17 +3,15 @@ name = "stellar-confidential" edition.workspace = true license.workspace = true repository.workspace = true -publish = false +publish = true version.workspace = true description = "Confidential token with encrypted balances and zero-knowledge proofs for the Stellar contracts." [package.metadata.stellar] cargo_inherit = true -# `lib` only, `publish = false`, and no `alloc` feature on `soroban-sdk`: see -# README.md#packaging. [lib] -crate-type = ["lib"] +crate-type = ["lib", "cdylib"] doctest = false [dependencies] diff --git a/packages/confidential/README.md b/packages/confidential/README.md index 5676a6252..d52fa0005 100644 --- a/packages/confidential/README.md +++ b/packages/confidential/README.md @@ -84,14 +84,3 @@ The circuits close one known leak. When a base point is a constant equal to one This removes the plookup channel only and does not make proofs private. Whether other parts of a non-zk proof, such as the wire commitments or the opened evaluations, leak private values has not been established, beyond one known case: the commitment to the lookup inverses and its opened evaluation determine two BN254 points whose discrete logarithm is the prover's long-term key. Recovering the key from them is a discrete-logarithm problem in BN254, estimated at about 100 bits of security, the level the proof system's soundness already relies on. Zero knowledge requires the zk flavour of the verifier. Nethermind has [zk verification in progress](https://github.com/NethermindEth/rs-soroban-ultrahonk/pull/38); adopting it changes the proving recipe and the verifier dependency, not the circuits or the verification keys. - -## Packaging - -The crate's packaging follows from its UltraHonk verifier backend -(`ultrahonk-soroban-verifier`), which links Rust's `alloc` crate and has no -crates.io release. - -- **Separate from `stellar-tokens`.** As a module of `stellar-tokens`, the verifier would put `alloc` in the dependency graph of every contract that uses a fungible, non-fungible, RWA, or vault token, and each of them would need a global allocator it never uses. A `confidential` cargo feature on `stellar-tokens` would remove that coupling but would leave `stellar-tokens` unpublishable, because `cargo publish` rejects git dependencies even when they are optional. -- **Contracts provide the allocator.** A wasm binary whose dependency graph includes `alloc` needs exactly one `#[global_allocator]`. Enabling the `alloc` feature of `soroban-sdk` registers the SDK's bump allocator as that allocator, and Cargo features are additive, so a library that enables it prevents every dependent contract from registering its own (`the #[global_allocator] in this crate conflicts with global allocator in: soroban_sdk`). This crate leaves the feature off, and each contract either enables it or registers its own allocator. The verifier's repository splits its library and contracts the same way. -- **`lib` only.** Without an allocator, a standalone `cdylib` build of this crate fails with `no global memory allocator found but one is required`. The crate is compiled to wasm as a dependency of the contracts under `examples/confidential/`, which provide one. -- **`publish = false`.** The verifier is a git dependency, which `cargo publish` rejects. The crate can be published once the verifier has a crates.io release. diff --git a/packages/confidential/src/lib.rs b/packages/confidential/src/lib.rs index 8f6a7ccd3..42b8b367a 100644 --- a/packages/confidential/src/lib.rs +++ b/packages/confidential/src/lib.rs @@ -21,15 +21,6 @@ //! none. //! - Storage helpers and operation-level orchestration under [`storage`]. //! -//! ## Global Allocator -//! -//! The UltraHonk verifier backend links Rust's `alloc` crate, so every -//! contract that depends on this crate must provide a global allocator, -//! either by enabling the `alloc` feature of `soroban-sdk` or by registering -//! its own `#[global_allocator]`. This crate enables neither and leaves the -//! choice to the contract; the "Packaging" section of `README.md` gives the -//! reasons. -//! //! ## Public-Input Encoding //! //! The contract assembles the public-input blob handed to the verifier by diff --git a/packages/confidential/src/verifier/mod.rs b/packages/confidential/src/verifier/mod.rs index bef637b27..9b7b9424e 100644 --- a/packages/confidential/src/verifier/mod.rs +++ b/packages/confidential/src/verifier/mod.rs @@ -13,8 +13,7 @@ //! //! [`ConfidentialVerifier::verify_proof`] is backed by the UltraHonk verifier //! from -//! [`NethermindEth/rs-soroban-ultrahonk`](https://github.com/NethermindEth/rs-soroban-ultrahonk), -//! pinned to a specific commit in the workspace `Cargo.toml`. +//! [`NethermindEth/rs-soroban-ultrahonk`](https://github.com/NethermindEth/rs-soroban-ultrahonk). //! //! ## Why a Separate Contract //!