-
Notifications
You must be signed in to change notification settings - Fork 267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extended API for fine-grained payment tracking #867
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An advantage of using for
-sequences here:
- if either
success
ordelayed
fails then no tx is published as opposed to current approach wheresuccess
may be published butdelayed
won't be (because applying on-chain fees would make it dusty for example). - if either
success
ordelayed
fails then noPaymentSettlingOnChain
will be sent, butPaymentLostOnChain
will 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
/claimRemoteCommitTxOutputs
doesn'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.
@@ -202,7 +204,7 @@ object NodeParams { | |||
NodeParams( | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above. For this particular change it hurts readibility more than anything, as previous code was more consistent.
@@ -179,7 +181,7 @@ object NodeParams { | |||
val p = PublicKey(e.getString("nodeid")) | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The json serialization should probably be part of the flow instead of duplicating Serialization.write(...)
|
||
val forwarder = context.actorOf(Props(new Forwarder(nodeParams)), "forwarder") | ||
|
||
// 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
@@ -50,15 +50,15 @@ class LocalPaymentHandler(nodeParams: NodeParams) extends Actor with ActorLoggin | |||
case PurgeExpiredRequests => | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Options should be suffixed with _opt
by convention
@@ -230,10 +230,10 @@ object PaymentRequest { | |||
f.version match { | |||
case 17 if prefix == "lnbc" => Base58Check.encode(Base58.Prefix.PubkeyAddress, data) | |||
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch
# 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:
send
method 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:
send
becomes a fire-and-forget method.Payment
events are added:PaymentSettlingOnChain
andPaymentLostOnChain
.PaymentSent
|PaymentLostOnChain
|PaymentSettlingOnChain(isDone = true)
, alternatively user may callsentinfo
API endpoint which would return the same objects.PaymentReceived
|PaymentLostOnChain
|PaymentSettlingOnChain(isDone = true)
, alternatively user may callreceivedinfo
API endpoint which would return the same objects.One serious change this requires is https://github.com/btcontract/eclair/commit/a76ec92e3c1d09608c3db37f819de416fc0cbbc1#diff-aeb98076f262543b70a86753bd3719adR53 which adds
paymentHash
toHtlcTimeoutTx
. This is needed forPaymentSettlingOnChain
event which haspaymentHash
andtxid
fields.txid
there belongs to a final CSV-delayed refunding transaction and allows API user to link off-chain failed payment to on-chain refunding transaction.