Review of Spark's trust model

Privacy, control, and safety

Every Spark Operator receives the full Lightning invoice tied to the wallet identity

Spark distributes the complete Lightning invoice, payment hash, amount, fee, direction, and wallet identities to every Operator while dividing only the cryptographic shares. Each Operator stores the original invoice beside the affected Spark identity. 123456

6 sourcesEvidence reviewed through July 14, 2026

What the evidence shows

Technical and product details

  1. Documented behavior

    When creating a Lightning invoice, the SDK sends the coordinator the payment hash, complete BOLT11 invoice string, affected user's Spark identity, threshold, and one encrypted preimage share for every Operator. 1

    Supporting material shown on this page

    wallet preimage-share requestPinned source code · github.com · checked 2026-07-14
    Relevant lines from the pinned source · open raw file
    173      await sparkClient.store_preimage_share_v2({
    174        paymentHash,
    175        encryptedPreimageShares: encryptedShares,
    176        threshold,
    177        invoiceString,
    178        userIdentityPublicKey,
    179      });
  2. Documented behavior

    The coordinator fans that original request to all Operators. Each Operator decrypts its own share and stores the full invoice string, payment hash, threshold, and user identity in its own database. 23

    Supporting material shown on this page

    all-Operator preimage-share fan-outPinned source code · github.com · checked 2026-07-14
    Relevant lines from the pinned source · open raw file
    152// StorePreimageShareV2 stores preimage shares for all SOs via a single coordinator call.
    153// The coordinator decrypts and stores its own share, then fans out to other SOs via internal RPC.
    154func (h *LightningHandler) StorePreimageShareV2(ctx context.Context, req *pbspark.StorePreimageShareV2Request) (retErr error) {
    155	if req == nil {
    156		return sparkerrors.InvalidArgumentMissingField(fmt.Errorf("request is required"))
    stored invoice and wallet identityPinned source code · github.com · checked 2026-07-14
    Relevant lines from the pinned source · open raw file
    52			Comment("The identity public key of the operator that owns this preimage share.").
    53			Annotations(entexample.Default("02112b5bc18676433c593f8b02127354b9db8de6070088c1646a3cd58a60b90be3")),
    54		field.String("invoice_string").
    55			NotEmpty().
    56			Immutable().
    57			Comment("The original Lightning invoice string associated with the payment.").
    58			Annotations(entexample.Default("lnbc150n1p500ftzpp5v5kf3whqmujlh4wceer2jdfz0w074vjfs92myzsr8vcuclj7msvssp57pfy9xhj7ma00tzwwptwxse4wtn7yqffyy85t6tnwtf282px8w3sxqyz5vqnp4q0p92sfan5vj2a4f8q3gsfsy8qp60maeuxz858c5x0hvt5u0p0h9jrzjqtqd37k2ya0pv8pqeyjs4lklcexjyw600g9qqp62r4j0ph8fcmlfwqqqqzfv7u6g85qqqqqqq
  3. Documented behavior

    The outgoing Lightning preimage-swap protocol likewise wraps the public request verbatim for all Operators. That request carries the BOLT11 invoice, exact sats, fee, payment hash, direction, receiver identity, and Spark transfer package. 456

    Supporting material shown on this page

    all-Operator outgoing Lightning requestPinned source code · github.com · checked 2026-07-14
    Relevant lines from the pinned source · open raw file
    544// InitiatePreimageSwapPrepareRequest is the Prepare payload for the
    545// CONSENSUS_OPERATION_TYPE_INITIATE_PREIMAGE_SWAP 2PC flow. It wraps the public
    546// InitiatePreimageSwapRequest verbatim. Every SO runs the full preimage-swap
    547// validation (ValidateGetPreimageRequest, ValidateTransferPackage,
    548// buildHTLCRefundMaps), persists the transfer + preimage_request +
    outgoing request fieldsPinned source code · github.com · checked 2026-07-14
    Relevant lines from the pinned source · open raw file
    202    paymentHash,
    203    invoiceString,
    204    isInboundPayment,
    205    feeSats = 0,
    206    amountSatsToSend,
    207    startTransferRequest,
    208    idempotencyKey,
    BOLT 11 invoice fieldsPinned source code · github.com · checked 2026-07-14
    Relevant lines from the pinned source · open raw file
    145* `p` (1): `data_length` 52. 256-bit SHA256 payment_hash. Preimage of this provides proof of payment.
    146* `s` (16): `data_length` 52. This 256-bit secret prevents forwarding nodes from probing the payment recipient.
    147* `d` (13): `data_length` variable. Short description of purpose of payment (UTF-8), e.g. '1 cup of coffee' or 'ナンセンス 1杯'
    148* `m` (27): `data_length` variable. Additional metadata to attach to the
    149  payment. Note that the size of this field is limited by the maximum hop payload size. Long metadata fields reduce the maximum route length.
    150* `n` (19): `data_length` 53. 33-byte public key of the payee node
    151* `h` (23): `data_length` 52. 256-bit description of purpose of payment (SHA256). This is used to commit to an associated description that is over 639 bytes, but the transport mechanism for the description in that case is transport specific and not defined here.

Interpretation

Why this matters for Spark's trust model

The Lightning destination and invoice metadata are not visible only to the Lightning service that must route the payment. Spark deliberately replicates the full invoice beside the durable wallet identity across every Operator, allowing each Operator to link a Spark user to invoice amount, payment hash, memo or description hash, expiry, and Lightning payee. 123456

This section states the trust-model consequence of the cited evidence. Conditional or inferred claims remain bounded by the next section.

Scope control

What this does not establish

  • Each Operator normally decrypts only its own preimage or key-tweak share; this does not prove that one Operator holds every secret share. An inbound Lightning invoice does not automatically reveal the original payer's real identity, and the sources do not establish Operator retention periods or staff access policy. 234

Sources and excerpts

Primary sources

The relevant details and available source-code excerpts appear alongside the claims above. This list preserves the complete original-source trail for independent verification.

1

wallet preimage-share request

Pinned source code · github.com · Pinned or archival · checked 2026-07-14

Open original source
2

all-Operator preimage-share fan-out

Pinned source code · github.com · Pinned or archival · checked 2026-07-14

Open original source
3

stored invoice and wallet identity

Pinned source code · github.com · Pinned or archival · checked 2026-07-14

Open original source
4

all-Operator outgoing Lightning request

Pinned source code · github.com · Pinned or archival · checked 2026-07-14

Open original source
5

outgoing request fields

Pinned source code · github.com · Pinned or archival · checked 2026-07-14

Open original source
6

BOLT 11 invoice fields

Pinned source code · github.com · Pinned or archival · checked 2026-07-14

Open original source

How sources, absence findings, and limitations were evaluated