Skip to content

feat(core): support externally owned NUT-20 BOLT11 quote locks #405

Description

@igbopharaoh

Context

Follow-up to #365 and #400.

Source TODO:
https://github.com/cashubtc/coco/pull/400/changes#diff-0103091746c9015f4fece02e671808fd1f9b50c0981611512e59e7f2289d9949R51

The current BOLT11 handler supports:

  1. ordinary unlocked quotes;
  2. locked quotes using a newly generated Coco-owned key; and
  3. locked quotes using an existing Coco-owned public key.

An explicitly supplied ownedPubkey is verified against Coco's key ring because
the existing quote flow assumes Coco will later redeem every quote it creates.

Problem

There is no distinct flow for creating a NUT-20 quote locked to a public key
owned by another party.

Simply removing the local-key check would be unsafe: the quote could enter
Coco's normal prepare, execution, or recovery paths even though Coco cannot
produce the required NUT-20 signature.

The API must represent external ownership explicitly and keep externally owned
quotes separate from wallet-owned redemption.

Scope

  • Introduce an explicit quote-creation flow or discriminated input for an
    externally owned NUT-20 lock.
  • Keep the external-lock API distinct from locked: true and the internal
    Coco-owned ownedPubkey path.
  • Validate the supplied compressed public key.
  • Require NUT-20 support before requesting the quote.
  • Verify that the mint returns the requested public key.
  • Represent external ownership clearly in the returned quote or associated
    metadata.
  • Prevent externally owned quotes from accidentally entering Coco-owned
    prepare, execution, signing, or recovery paths.
  • Document the intended caller and ownership model.

Acceptance criteria

  • Callers can explicitly request a BOLT11 quote locked to an externally owned public key.
  • Quote creation does not require the corresponding private key to exist in Coco's key ring.
  • Invalid public keys are rejected before the remote request.
  • A response that omits or changes the requested public key is rejected.
  • Coco does not attempt to sign or redeem an externally owned quote through its wallet-owned mint flow.
  • An attempted wallet-owned redemption fails with a clear structured ownership error.
  • Existing unlocked and Coco-owned locked quote behavior remains unchanged.
  • Tests cover creation, response validation, and prevention of accidental local redemption.

Out of scope

  • Importing or storing another party's private key.
  • Automatically redeeming an externally owned quote.
  • Changing the existing Coco-owned NUT-20 recovery policy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions