<div>Good morning c-lightningers,<br></div><div><br></div><div>I would like to propose a JSON-RPC interface for low-level atomic multipath payments.<br></div><div><br></div><div>Currently exists, the `sendpay`/`waitsendpay`/`listpayments`.<br></div><div>`sendpay` and `waitsendpay` are low-level interfaces for making a single payment attempt.<br></div><div>`listpayments` indicates status of payments.<br></div><div><br></div><div>These interfaces manage a table of payment attempts.<br></div><div>`sendpay` will create one, or reuse a payment attempt if it is marked as failing.<br></div><div>`waitsendpay` waits for a specific payment attempt to change its status to either completed or failing.<br></div><div><br></div><div>This table of payment attempts is used also to provide the high-level `pay` interface.<br></div><div>The `pay` interface leaves the payment attempt on the table if it succeeds, and just reuses the same entry (from the lower-level `sendpay` behavior) to keep retrying.<br></div><div>Thus `listpayments` serves as both a high-level and low-level interface.<br></div><div><br></div><div>Currently those interfaces are keyed to the `payment_hash`.<br></div><div>Each payment attempt has a unique `payment_hash`.<br></div><div><br></div><div>For simplicity to JSON-RPC users, I want to keep the existing `sendpay`/`waitsendpay` interfaces as-is without adding special multipath options to them.<br></div><div>However, atomic multipath means making separate attempts simultaneously with the same `payment_hash`, and the `sendpay`/`waitsendpay` are keyed according to `payment_hash`.<br></div><div>Further, the `listpayments` table also serves as a high-level interface, and I think atomic multipath should be low-level and not be exposed on `listpayments`.<br></div><div><br></div><div>So I want to propose a separate interface:<br></div><div><br></div><div>`sendpartialpay` `route` `payment_hash` `intended_msatoshi` [`description`]<br></div><div>=><br></div><div>{ "id" : 42, ... }<br></div><div><br></div><div>`waitpartialpay` `id`<br></div><div><br></div><div>`listpartialpayments` [`id`]<br></div><div><br></div><div>This handles a separate table for partial payments.<br></div><div>There is a many-to-one mapping from partial payments in `listpartialpayments` to payments in `listpayments`.<br></div><div><br></div><div>Then, `sendpartialpay` does:<br></div><div><br></div><div>1.  Check if there already exists a payment attempt with same `payment_hash` in `listpayments` table.<br></div><div>1.1.  If there is not, create it, with the `msatoshi` equal to the `intended_msatoshi` for this `sendpartialpay` call.<br></div><div>1.2.  Otherwise:<br></div><div>1.2.1.  If the `intended_msatoshi` does not match the `msatoshi` in the `listpayments` table, fail immediately and do nothing.<br></div><div>1.2.2.  If the existing `listpayments` entry is completed, return immediately with success and do nothing.<br></div><div>1.2.3.  If the existing `listpayments` entry is failed, change it to pending and continue.<br></div><div>2.  Create a payment attempt in `listpartialpayments` table, trigger the payment, and return the ID for the payment attempt.<br></div><div><br></div><div>When a partial payment returns either `update_fulfill_htlc` or `update_fail_htlc`:<br></div><div><br></div><div>1.  Change the state of the `listpartialpayments` entry to completed/failed.<br></div><div>2.  If completed, also set the `listpayments` entry to completed and trigger any `waitsendpay` waiters.<br></div><div>3.  If failed, and all other partial payments to the same `payment_hash` failed, set the `listpayments` entry to failed and trigger any `waitsendpay` waiters.<br></div><div>4.  Trigger any `waitpartialpay` waiters.<br></div><div><br></div><div>Regards,<br></div><div>ZmnSCPxj<br></div>