Extended API for fine-grained payment tracking#867
Extended API for fine-grained payment tracking#867akumaigorodski wants to merge 9 commits intoACINQ:masterfrom akumaigorodski:extended-api-2
Conversation
Also send `PaymentSettlingOnChan` and `PaymentLostOnChain` when uncooperative closing happens.
| val inFlightHtlcs = commitments.localCommit.spec.htlcs.map(htlc => htlc.add.paymentHash -> htlc.add.amountMsat).toMap | ||
| var onChainHashes = Set.empty[BinaryData] // this is needed to collect hashes of payments which can be resolved on-chain | ||
|
|
||
| val successAndDelayedTxs = for { |
There was a problem hiding this comment.
An advantage of using for-sequences here:
- if either
successordelayedfails then no tx is published as opposed to current approach wheresuccessmay be published butdelayedwon't be (because applying on-chain fees would make it dusty for example). - if either
successordelayedfails then noPaymentSettlingOnChainwill be sent, butPaymentLostOnChainwill be sent for this payment instead.
Further, if LocalCommitPublished can be modified to store (success, delayed) and (timeout, delayed) tuples directly then UI and API may inform how much blocks is left for each delayed payment: CLTV(timeout) + CSV(delayed) as well as total on-chain fees paid: timeout.input.amount - delayed.output.amount.
|
|
Looks like integration-test ecalir nodes couldn't find a config key, maybe because of this addition? https://github.com/ACINQ/eclair/pull/867/files#diff-8f6c9262b4235c9580874fdd69f54b7cR234 Notice that config key has been moved in the router block, and has become |
pm47
left a comment
There was a problem hiding this comment.
Concept OK, but I have several problems with the implementation:
-
Please submit a separate PR for the formatting changes. I'm not convinced by most of them to be honest, and they make the review more difficult;
-
The audit db isn't supposed to be used as a random access db but more like an append-only log for audit purpose. I know that there is a demand for a real payment database and I think we should probably add one;
-
I understand the need to index payments by
payment_hash(although it is not a real index!) but this could be inferred from the local commitment. -
Just because we call
claimCurrentLocalCommitTxOutputs/claimRemoteCommitTxOutputsdoesn't mean that this will be confirmed. If an htlc is fulfilled in the local tx, and if local commit wins the race despite remote publishing its local commit, then the code will produce an invalid event AFAICT.
Let me think about this a bit more and I may come up with an alternate proposal.
| keyManager = keyManager, | ||
| alias = nodeAlias, | ||
| color = Color(color.data(0), color.data(1), color.data(2)), | ||
| color = Color(color.data.head, color.data(1), color.data(2)), |
There was a problem hiding this comment.
Same comment as above. For this particular change it hurts readibility more than anything, as previous code was more consistent.
| val gf = BinaryData(e.getString("global-features")) | ||
| val lf = BinaryData(e.getString("local-features")) | ||
| (p -> (gf, lf)) | ||
| (p, (gf, lf)) |
There was a problem hiding this comment.
Are you following intellij recommendations or some automated code modification suggestions? This makes review more difficult are there are lot of unrelated changes.
Can you revert and submit a separate PR for those?
Also by convention I Iike using -> for defining tuples in the context of a Map.
| } | ||
|
|
||
| def receive: Receive = { | ||
| case message: PaymentFailed => flowInput.offer(Serialization write message) |
There was a problem hiding this comment.
The json serialization should probably be part of the flow instead of duplicating Serialization.write(...)
|
|
||
| // this will be used to detect htlc timeouts | ||
| context.system.eventStream.subscribe(self, classOf[CurrentBlockCount]) | ||
| implicitStream.subscribe(self, classOf[CurrentBlockCount]) |
There was a problem hiding this comment.
I don't think we should refer to the implicit variable here. Same for logging: we use an implicit that is passed to the Helper functions for context, but we call directly log from within the actor. Does that make sense?
| context.become(run(hash2preimage.filterNot { case (_, pr) => hasExpired(pr) })) | ||
|
|
||
| case ReceivePayment(amount_opt, desc, expirySeconds_opt, extraHops) => | ||
| case ReceivePayment(amount_opt, desc, expirySeconds_opt, extraHops, fallbackAddressOpt) => |
There was a problem hiding this comment.
Options should be suffixed with _opt by convention
| case 18 if prefix == "lnbc" => Base58Check.encode(Base58.Prefix.ScriptAddress, data) | ||
| case 17 if prefix == "lntb" => Base58Check.encode(Base58.Prefix.PubkeyAddressTestnet, data) | ||
| case 18 if prefix == "lntb" => Base58Check.encode(Base58.Prefix.ScriptAddressTestnet, data) | ||
| case 17 if prefix == "lntb" || prefix == "lnbcrt" => Base58Check.encode(Base58.Prefix.PubkeyAddressTestnet, data) |
# Conflicts: # eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala # eclair-core/src/test/scala/fr/acinq/eclair/wire/ChannelCodecsSpec.scala
This is a simpler alternative to #867, with the following limitations: - no `OnChainRefundsDb` and associated API calls - `PaymentSettlingOnChain` event will be sent exactly once per payment and have less information - we don't touch `HtlcTimeoutTx` - use json4s type hints instead of manual attributes to case classes
This is (yet another) attempt to sneak in an extended API which tries to improve on current limitations:
sendmethod has a hard timeout so can't be relied upon when payment takes a long time.Above limitations are tolerable when Eclair is run by user directly, but are problematic when API is used by a service which sends/receives payments on behalf of it's users since a service has to be able to tell users what is going on with their payments as well as reliably track these payments at all times.
New API strategy is this:
sendbecomes a fire-and-forget method.Paymentevents are added:PaymentSettlingOnChainandPaymentLostOnChain.PaymentSent|PaymentLostOnChain|PaymentSettlingOnChain(isDone = true), alternatively user may callsentinfoAPI endpoint which would return the same objects.PaymentReceived|PaymentLostOnChain|PaymentSettlingOnChain(isDone = true), alternatively user may callreceivedinfoAPI endpoint which would return the same objects.One serious change this requires is https://github.com/btcontract/eclair/commit/a76ec92e3c1d09608c3db37f819de416fc0cbbc1#diff-aeb98076f262543b70a86753bd3719adR53 which adds
paymentHashtoHtlcTimeoutTx. This is needed forPaymentSettlingOnChainevent which haspaymentHashandtxidfields.txidthere belongs to a final CSV-delayed refunding transaction and allows API user to link off-chain failed payment to on-chain refunding transaction.