Skip to content

Commit 5a8c06a

Browse files
author
ian
committed
docs(cch): clarify SwapProposal btc_amount_msat and add ReceiveBTC fee example
Cross-review against the implementation surfaced two documentation gaps in the multi-asset swap spec. * Section 5.6 implied the SwapProposal's btc_amount_msat for SendBTC was the raw Bolt11 amount, but the actor sends the total payout (Bolt11 amount + configured fee). Clarify the field semantics and note that the raw Bolt11 amount can be recovered as btc_amount_msat - fee_on_btc_side_msat. * Section 6.2 left ReceiveBTC proposal-path operators to infer how to combine the configured fee with their chosen rate. Add a worked formula and numeric example matching the fast-path computation, so operators have a reference implementation for the BTC-leg amount they submit.
1 parent 481f378 commit 5a8c06a

1 file changed

Lines changed: 26 additions & 2 deletions

File tree

docs/specs/cch-multi-asset-swap.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,11 @@ A `SwapProposalResponse` carries either a rejection or an acceptance that includ
180180

181181
- `proposal_id` (must match a pending proposal previously notified to this client),
182182
- `accept` (boolean),
183-
- `counterparty_leg_amount` (REQUIRED when `accept` is true; smallest-unit integer in the counterparty leg’s asset),
183+
- `counterparty_leg_amount` (REQUIRED and **must be > 0** when `accept` is true; smallest-unit integer in the counterparty leg’s asset),
184184
- `reject_reason` (optional string; logged by the hub and returned to the swap client as the failure reason when `accept` is false).
185185

186+
A response is **valid** when it parses, references a pending `proposal_id`, and \u2014 if `accept` is true \u2014 carries a positive `counterparty_leg_amount`. The first valid response resolves the proposal; later responses for the same `proposal_id` return `SwapProposalUnknown`. A malformed accept (missing or zero `counterparty_leg_amount`) is rejected with `SwapProposalResponseMissingAmount` / `SwapProposalResponseInvalidAmount` but **leaves the proposal pending** so the operator may correct and resubmit before the timeout elapses.
187+
186188
### 5.4 Timeout
187189

188190
- If no operator submits a valid `SwapProposalResponse` for a given `proposal_id` within `swap_proposal_timeout_seconds` (CCH config), the proposal is treated as **rejected** (same outcome as `accept: false`) with reason `acceptor_timeout`.
@@ -227,7 +229,7 @@ Fields delivered to subscribers (see `SwapProposal` in `fiber-types`):
227229
| `payment_hash` | Links both legs (derived from the client-submitted invoice). |
228230
| `fiber_asset` | UDT type script when the Fiber leg is a UDT; absent (or null) when the Fiber leg is native CKB. |
229231
| `fiber_amount_smallest_unit` | Fiber-leg amount in smallest units when known up-front (parsed from the submitted invoice on `ReceiveBTC`); absent on `SendBTC` because the operator supplies it in their response. |
230-
| `btc_amount_msat` | Lightning amount in millisatoshis when known up-front (parsed from the submitted Bolt11 on `SendBTC`); absent on `ReceiveBTC` because the operator supplies it in their response. |
232+
| `btc_amount_msat` | **Total** Lightning amount in millisatoshis the hub will pay out, **inclusive of `fee_on_btc_side_msat`** (i.e. submitted-Bolt11 amount + configured fee), when known up-front on `SendBTC`; absent on `ReceiveBTC` because the operator supplies it in their response. The raw Bolt11 amount can be recovered as `btc_amount_msat - fee_on_btc_side_msat`. |
231233
| `configured_fee_rate_per_million_sats` | Hub-configured proportional fee in effect for this swap. |
232234
| `configured_base_fee_sats` | Hub-configured flat base fee in effect for this swap. |
233235
| `fee_on_btc_side_msat` | Fee attributed to the BTC leg derived from the configured rate, in millisatoshi. For `SendBTC` this is computed from the submitted Bolt11; for `ReceiveBTC` it is reported as `0` because it depends on the operator-set BTC-leg amount — the operator is responsible for accounting for the configured rate/base when choosing the counterparty amount. |
@@ -269,6 +271,28 @@ The swap client submits the **Fiber invoice** they want the hub to pay on the Fi
269271
5. Continue with the existing order machinery.
270272
6. Return the order with the Lightning hold invoice attached; the swap client (if the amount is acceptable) forwards it to the user-side payer.
271273

274+
#### Worked example: ReceiveBTC proposal-path operator math
275+
276+
For a `ReceiveBTC` proposal the hub reports `fee_on_btc_side_msat = 0` because it cannot compute the fee until the operator picks a BTC-leg amount. The operator’s `counterparty_leg_amount` is taken as the **final** BTC-leg amount in millisatoshi (fee included). A reference computation that mirrors the fast path is:
277+
278+
1. Choose an effective BTC/asset rate $r$ in **fiber smallest units per satoshi** (the operator’s FX/inventory decision).
279+
2. Convert the submitted Fiber-leg amount to a fee-exclusive BTC amount:
280+
$$\text{btc\_msat\_pre\_fee} = \frac{\text{fiber\_amount\_smallest\_unit} \times 1000}{r}$$
281+
3. Apply the hub’s configured fee:
282+
$$\text{fee\_msat} = \Big\lfloor \frac{\text{btc\_msat\_pre\_fee} \times \text{configured\_fee\_rate\_per\_million\_sats}}{1\,000\,000} \Big\rfloor + \text{configured\_base\_fee\_sats} \times 1000$$
283+
4. Submit:
284+
$$\text{counterparty\_leg\_amount} = \text{btc\_msat\_pre\_fee} + \text{fee\_msat}$$
285+
286+
Concretely, given `fiber_amount_smallest_unit = 1_000_000` shannons, $r = 1$ shannon/sat, `configured_fee_rate_per_million_sats = 1000` (0.1 %), and `configured_base_fee_sats = 10`:
287+
288+
- `btc_msat_pre_fee = 1_000_000 * 1000 / 1 = 1_000_000_000` msat
289+
- `fee_msat = 1_000_000_000 * 1000 / 1_000_000 + 10 * 1000 = 1_000_000 + 10_000 = 1_010_000` msat
290+
- `counterparty_leg_amount = 1_001_010_000` msat
291+
292+
Operators MAY price more aggressively (larger `r`, larger fee) to cover FX/inventory risk. The hub does not validate the chosen rate — the swap client is the final gate by accepting or refusing to forward the minted Lightning hold invoice.
293+
294+
The symmetric `SendBTC` proposal already includes `btc_amount_msat` (Bolt11 amount + configured fee) and `fee_on_btc_side_msat`, so the operator’s task there is purely the BTC→asset conversion at their chosen rate.
295+
272296
## 7. Security and operations
273297

274298
- **Preimage release**: Preserve ordering guarantees so the hub does not strand funds (same class of concerns as current CCH).

0 commit comments

Comments
 (0)