You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Address review on static deposit security caveats:
- Flag the static-deposit key-export exception in the top-of-page caveat and link to the security section
- Wrap the EXPORT_WALLET_ACCOUNT note in a callout box
- Add reassurance that the exported key is irrelevant after claiming (links SPARK_CLAIM_TRANSFER + SDK example)
- Outline the SSP + Spark Operator collusion risk window and link Spark's sovereignty docs
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: features/networks/spark.mdx
+13-4Lines changed: 13 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@ title: "Spark support on Turnkey"
3
3
sidebarTitle: "Spark"
4
4
---
5
5
6
-
[Spark](https://www.spark.money/) is a Bitcoin Layer 2 that uses FROST threshold signing across a collective of operators to enable fast, low-fee transfers and Lightning payments without giving up self-custody of the underlying BTC. Turnkey provides enclave-based key management for Spark: your identity key, leaf keys, deposit keys, and Lightning preimages are generated and used inside the Turnkey enclave, and never leave it.
6
+
[Spark](https://www.spark.money/) is a Bitcoin Layer 2 that uses FROST threshold signing across a collective of operators to enable fast, low-fee transfers and Lightning payments without giving up self-custody of the underlying BTC. Turnkey provides enclave-based key management for Spark: your identity key, leaf keys, deposit keys, and Lightning preimages are generated and used inside the Turnkey enclave. With a single exception, none of this key material ever leaves it — the [static deposit flow](#static-deposits-export-a-key-from-the-enclave) exports one deposit key so a Spark Service Provider can process deposits while your wallet is offline, and that key stops mattering once you claim the deposit.
7
7
8
8
If you don't know the protocol, read [Spark core concepts](https://docs.spark.money/learn/core-concepts) and [Sovereignty](https://docs.spark.money/learn/sovereignty) first. This page covers what Turnkey adds to a Spark integration.
9
9
@@ -119,14 +119,23 @@ This is the property that makes Spark Operator unavailability a _liveness_ conce
119
119
120
120
### Static deposits export a key from the enclave
121
121
122
-
Static deposit addresses are reusable: one address can receive many deposits, each creating a separate Spark leaf. To make that work, the SSP needs to process deposits while your wallet is offline, which means it needs co-signing capability on the static deposit key. This is the **only** Spark flow that uses [`EXPORT_WALLET_ACCOUNT`](/api-reference/activities/export-wallet-account) to take a raw private key out of the Turnkey enclave.
122
+
Static deposit addresses are reusable: one address can receive many deposits, each creating a separate Spark leaf. To make that work, the SSP needs to process deposits while your wallet is offline, which means it needs co-signing capability on the static deposit key.
123
123
124
-
From the moment the static deposit key is shared with the SSP until you claim any deposits made to that address, the SSP holds co-signing capability. This is the intentional custodial tradeoff of static deposits. To minimize exposure:
124
+
<Warning>
125
+
Static deposits are the **only** Spark flow that takes a raw private key out of the Turnkey enclave. The flow uses [`EXPORT_WALLET_ACCOUNT`](/api-reference/activities/export-wallet-account) to export the static deposit key so it can be shared with the SSP. Every other Spark flow keeps all key material inside the enclave.
126
+
</Warning>
127
+
128
+
This is the intentional custodial tradeoff of static deposits — expected behavior, not a leak. The exported key controls only the **static deposit address**; it cannot move existing leaves or touch your identity key. To minimize exposure while the key is in transit:
125
129
126
130
- Use a fresh ephemeral P-256 keypair for each export and zero it immediately after decrypting.
127
131
- Transmit the key to the SSP only over an encrypted channel.
128
132
- Zero the key in your local memory immediately after transmission.
129
-
- Only use SSPs you trust: a compromised SSP holding this key can co-sign spends from the static deposit address.
133
+
134
+
<Note>
135
+
**The exported key stops mattering once you claim the deposit.** Claiming runs through [`SPARK_CLAIM_TRANSFER`](/api-reference/activities/claim-spark-transfer), which rotates the leaf to a fresh key derived inside your enclave; after that, the exported static deposit key has no authority over the funds. See the static deposit scripts in the [SDK example](#sdk-example) for the full claim flow.
136
+
</Note>
137
+
138
+
**The risk window.** A static deposit address is an aggregate of your static deposit key and the Spark Operators' key, so moving funds out of it requires a signature from both. Between the moment funds arrive at the address and the moment you claim them, the SSP holds your half of that key. During this window — and only this window — an SSP that **colludes with the Spark Operators** could co-sign a spend of the unclaimed deposit. This is the same operator-trust boundary described in Spark's [sovereignty model](https://docs.spark.money/learn/sovereignty); use only SSPs you trust, and claim deposits promptly to keep the window short.
130
139
131
140
If you don't need a reusable receiving address, prefer single-use deposits. They keep key material inside the enclave throughout.
0 commit comments