feat: NUT-CTF conditional tokens for prediction markets#1666
Draft
joemphilips wants to merge 11 commits intocashubtc:mainfrom
Draft
feat: NUT-CTF conditional tokens for prediction markets#1666joemphilips wants to merge 11 commits intocashubtc:mainfrom
joemphilips wants to merge 11 commits intocashubtc:mainfrom
Conversation
175bfa9 to
f713358
Compare
Implements the NUT-CTF specification for conditional tokens using DLC oracles. - Condition registration with NIP-88 tags metadata - Conditional keyset derivation per outcome - CTF split/merge operations - Outcome redemption with oracle attestation verification - Numeric outcome markets with boundary keysets - Multi-oracle threshold attestation support - SQL migrations for conditions, partitions, and attestation storage - Conditional-tokens feature flag gating all CTF code
Cargo.toml lists bindings/{dart,swift,kotlin}/rust as workspace members but the Dockerfile never copied the bindings directory, causing the Docker build to fail.
Required for docker-compose healthcheck (curl -f http://localhost:8085/v1/info).
Conditional keysets were being stored in the shared `keyset` table, which caused `reload_keys_from_db`'s `HashMap<CurrencyUnit, Id>` collapse to randomly mark a conditional keyset as the 'primary active sat', breaking wallet keychain binding over `/v1/keys`.
- Move conditional keysets to a new `conditional_keyset` table with a 'one active per outcome_collection_id' unique partial index. The primary `keyset` table keeps its 'one active per unit' invariant.
- Hide conditional keysets from the public NUT-01/NUT-02 list endpoints (`/v1/keys`, `/v1/keysets`). Per-ID lookups (`/v1/keys/{id}`) stay open so wallets holding a conditional token can still fetch its keys.
- Replace `SignatoryKeySet::is_conditional` with `condition_id: Option<String>` propagated from `MintKeySetInfo`, so the filter uses the DLC binding directly.
- Insert new conditional keysets directly into the in-memory signing map instead of full-DB reloads, removing O(N\xc2\xb2) behavior in `register_partition`.
- Share SQL row parsing and cursor-pagination helpers between the public NUT-CTF listing endpoint and the internal reload path, fix `>=` vs `>` on the `since` cursor, and add a `created_at` index on `conditional_keyset`.
The original 20260216 migration was modified in-place (4d95858) to rename conditional_keysets -> conditional_keyset with a new schema. Existing deployments that ran the old version skip the migration by name, leaving the new table missing. This adds a separate migration that drops the old table and creates the correct one.
The original 20260216 migration created a description column but the current code expects tags_json. Add column, migrate existing data into NIP-88 tag arrays, and keep description for safe rollback.
The tags_json ALTER TABLE was included in 20260420000000 which had already been applied. Split into a separate 20260420010000 migration so it runs on existing deployments.
The CDK SQL parser treats : as placeholder prefix, so :: in Postgres type cast syntax triggers InvalidPlaceholder error.
Fresh DBs already have tags_json from the base migration. Guard the ALTER TABLE with IF NOT EXISTS (postgres) and make SQLite a no-op.
The DLC spec signs over raw Writeable::write() bytes, not TLV-wrapped bytes. verify_announcement_signature() was hashing full write_as_tlv() output (including BigSize type+length prefix), causing verification to fail for real oracle announcements. Tests passed because both signing and verifying used the same wrong bytes. Fix: delegate to announcement.validate(&secp) which uses correct serialization. Update test_helpers to strip TLV prefix before signing so test announcements produce spec-compliant signatures.
Add Conditional Tokens, CTF Split/Merge, and CTF Numeric to the supported features section on the mint HTML index page when the conditional-tokens feature flag is enabled.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reference implementation of NUT-CTF: Conditional Tokens for Prediction Markets.
This is a work-in-progress draft. More details to follow as the spec stabilizes.