-
Notifications
You must be signed in to change notification settings - Fork 411
Define chain::Confirm trait for use by Electrum clients #889
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
Define chain::Confirm trait for use by Electrum clients #889
Conversation
Codecov Report
@@ Coverage Diff @@
## main #889 +/- ##
==========================================
+ Coverage 90.26% 90.33% +0.07%
==========================================
Files 55 58 +3
Lines 29088 29936 +848
==========================================
+ Hits 26255 27042 +787
- Misses 2833 2894 +61
Continue to review full report at Codecov.
|
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.
Trait name seems fine to me, but some comments on the docs.
lightning/src/chain/mod.rs
Outdated
/// The `Confirm` trait is used to notify when transactions have been confirmed on chain or | ||
/// unconfirmed during a chain reorganization. | ||
/// | ||
/// Clients should use this interface instead of [`Listen`] if they receive transaction data only |
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 think the distinction as to when to use this API vs Listen is more about if you get chain data in a transaction-oriented API vs a blockchain-oriented API - ie do you receive notifications of each new header with relevant transaction data, or do you receive simply notifications of transaction-level state changes, with header data separated out.
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.
Reworded. Though note that while header transaction is separated out, in practice it still needs to be fetched (either explicitly or cached from a notification) in order to pass it along to transactions_confirmed
calls.
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.
Right. I do kinda agree with you that "transaction-oriented" isn't really clear for a user, but I'm not sure what is better, and I do think it captures exactly what we mean. I wonder if adding more words to describe it would help or if that just makes it more confusing. Maybe it can be resolved by just mentioning "Clients which fetch the full header chain" in the docs for Listen
?
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 idea -- expanded Listen
docs to mention the full header chain. That said, it seems the only difference between the two APIs in this regard is that Listen
requires the full header chain whereas Confirm
is simply ok with skipping headers . Unless we want to further relax how Confirm
docs describe when to call best_block_updated
. Currently, it just says "whenever a new chain tip becomes available".
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.
As long as we don't expand the docs around best_block_updated
to include the reorg case, the reorg handling is a pretty big difference, too, I think. #889 (comment)
/// [`Filter`] by subscribing to activity related to registered transactions and outputs. Upon | ||
/// notification, it would pass along the relevant transactions using this interface. | ||
/// | ||
/// The intended use is as follows: |
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.
This is a bit confusing as it encompasses both actions thee implementor of this trait is taking, as well as actions the user of it is taking. Maybe the tense can be rejiggered to better describe who is doing what.
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.
Dropped the line about get_relevant_txids
since it is covered later and its implementation details are covered in its own docs.
lightning/src/chain/mod.rs
Outdated
/// Should be called for any transactions registered by [`Filter::register_tx`] or any | ||
/// transactions spending an output registered by [`Filter::register_output`]. Such transactions | ||
/// appearing in the same block do not need to be included in the same call; instead, multiple | ||
/// calls with additional transactions may be made. |
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.
However, the calls MUST be in chain order, or at least in dependency order.
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.
Done and linked to pertinent section on ordering in the trait docs.
lightning/src/chain/mod.rs
Outdated
/// calls with additional transactions may be made. | ||
/// | ||
/// May be called before or after [`best_block_updated`] for the corresponding block. However, | ||
/// it must not be called after [`best_block_updated`] if `header` corresponds to a block that |
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.
This is confusing - it only needs to be ordered with respect to a best_block_updated
call with a new header - ie we cannot be called with a header which is no longer in the main chain if we already called transactions_confirmed
or best_block_updated
with a later header.
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.
Re-worded. Let me know if that captures the reorg case. I also linked earlier to trait-level documentation on ordering.
lightning/src/chain/mod.rs
Outdated
/// Should be called when a new header is available but may be skipped for intermediary blocks | ||
/// if they become available at the same time. | ||
/// | ||
/// Implementations are not required to handle chain reorganizations unless `height` is not |
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.
Hmm, I'm not really sure what the point of this comment is - I can't really figure out what this should mean to me as a user who wishes to call this method on an implementation of this trait?
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.
This paragraph is meant for the implementer not the caller. But I can't exactly recall where we landed on this. Definitely needs to rewritten regardless.
IIRC, this is an implementation detail that may be leaking into the interface. Question is should I just drop this? Or is there something we need to convey about how implementations handle <=
heights.
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.
Right, I guess its a question of if we want to support both modes - I think right now you can call either transaction_unconfirmed
or you can skip it as long as you call best_block_updated
with reorg info. I don't think it really makes sense for clients to do that (if they're fetching the full header chain they should be using Listen
, eventually), but technically we could support it. If we don't want to support it, I dunno if its worth mentioning in the docs here, but if you have any other reasoning based on your electrum exploration we can.
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.
Dropped the paragraph.
/// has been reorganized out of the chain. | ||
/// - Call [`best_block_updated`] whenever a new chain tip becomes available. | ||
/// | ||
/// See individual method documentation for further details. |
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 feel like we need a general "things have to be called in chain order" call-out. I don't think we can or should reasonably handle things out-of-order, and callers of these interface methods need to take special care that they don't call things out of order.
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.
Added the requirements as discussed. Let me know if they are too strict.
lightning/src/chain/mod.rs
Outdated
/// - Call [`transactions_confirmed`] for any on-chain activity of interest. | ||
/// - Return such transactions from [`get_relevant_txids`] until they have enough confirmations to | ||
/// no longer be in danger of chain reorganization. | ||
/// - Call [`transaction_unconfirmed`] for any transaction returned by [`get_relevant_txids`] that |
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.
If a transaction was confirmed, but was later reorged into a different/later block height, should transaction_confirmed be called again, or should transaction_unconfirmed be called first?
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.
Here, transaction_unconfirmed
would need to be called first. I think this is addressed in the new "Order" section. Let me know if it doesn't clear things up, though, or if you have recommendations on how to better word it.
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.
Overall, I think it's moving in the good direction
lightning/src/chain/mod.rs
Outdated
/// Clients should use this interface instead of [`Listen`] if they receive transaction data only | ||
/// relevant to that identified by [`Filter`]. For instance, an Electrum client may implement | ||
/// [`Filter`] by subscribing to activity related to registered transactions and outputs. Upon | ||
/// notification, it would pass along the relevant transactions using this interface. |
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 think it would be a slight improvement here to dub "Client" as "LDK Client" or "Monitor Client" as a stark difference from Electrum client. In the last sentence, I would replace it by Electrum client.
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.
Both occurrences are meant to refer to the same entity. The unqualified one refers to a client that may be an Electrum client whereas the qualified one is an example of the first. Re-worded to make it clear that it is a client of a chain source.
/// handled by [`transaction_unconfirmed`]. | ||
/// | ||
/// [`transaction_unconfirmed`]: Self::transaction_unconfirmed | ||
fn best_block_updated(&self, header: &BlockHeader, height: u32); |
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.
Is a user require to call best_block_updated
if any transaction has been transaction_confirmed
for the associated height and hash ? I believe If it's a MUST just say it.
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 believe it is necessary as they are allowed to skip intermediary headers even for those where transaction_confirmed
is called, IIUC.
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.
If it's not necessary can you say it explicitly in either transaction_confirmed
or best_block_updated
? It wasn't obvious to me :)
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.
Added here.
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.
Hmm, its easy to confuse the new wording for "if you passed a header in via transactions_confirmed
, don't bother passing it in here, too" which I don't think is what we want. Instead we just mean "if you pass a header in via transactions_confirmed
but by the time you go to call best_block_updated
the best block is different, just call this with the latest one", which is pretty different.
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.
Alright, I'm just going to drop it to avoid confusion. Let me know if the docs around use of best_block_updated
can be clarified in any other way. It's currently mentioned in transactions_confirmed
and in the trait-level docs.
/// Returns transactions that should be monitored for reorganization out of the chain. | ||
/// | ||
/// Should include any transactions passed to [`transactions_confirmed`] that have insufficient | ||
/// confirmations to be safe from a chain reorganization. Should not include any transactions |
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.
Should it precise that "insufficient confirmations" is a matter of user client's policy ? Though ANTI_REORG_DELAY
isn't configurable for now. A user might be willingly to increase is more funds are at stake or lower it if less funds are at stake.
Lowering increase off-chain liquidity velocity as a node can immediately cancel back HTLC, thus freeing a HTLC slot.
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.
Right, not yet configurable. Also, it's general because it's talking about how this may be implemented. For example, ChannelManager
always returns the funding transactions no matter how many confirmations.
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.
Please take a look at the "Use" and "Order" sections added to the docs. Any feedback on how to better arrange this would be more than welcome.
lightning/src/chain/mod.rs
Outdated
/// The `Confirm` trait is used to notify when transactions have been confirmed on chain or | ||
/// unconfirmed during a chain reorganization. | ||
/// | ||
/// Clients should use this interface instead of [`Listen`] if they receive transaction data only |
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.
Reworded. Though note that while header transaction is separated out, in practice it still needs to be fetched (either explicitly or cached from a notification) in order to pass it along to transactions_confirmed
calls.
lightning/src/chain/mod.rs
Outdated
/// Clients should use this interface instead of [`Listen`] if they receive transaction data only | ||
/// relevant to that identified by [`Filter`]. For instance, an Electrum client may implement | ||
/// [`Filter`] by subscribing to activity related to registered transactions and outputs. Upon | ||
/// notification, it would pass along the relevant transactions using this interface. |
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.
Both occurrences are meant to refer to the same entity. The unqualified one refers to a client that may be an Electrum client whereas the qualified one is an example of the first. Re-worded to make it clear that it is a client of a chain source.
/// [`Filter`] by subscribing to activity related to registered transactions and outputs. Upon | ||
/// notification, it would pass along the relevant transactions using this interface. | ||
/// | ||
/// The intended use is as follows: |
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.
Dropped the line about get_relevant_txids
since it is covered later and its implementation details are covered in its own docs.
/// has been reorganized out of the chain. | ||
/// - Call [`best_block_updated`] whenever a new chain tip becomes available. | ||
/// | ||
/// See individual method documentation for further details. |
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.
Added the requirements as discussed. Let me know if they are too strict.
lightning/src/chain/mod.rs
Outdated
/// Should be called for any transactions registered by [`Filter::register_tx`] or any | ||
/// transactions spending an output registered by [`Filter::register_output`]. Such transactions | ||
/// appearing in the same block do not need to be included in the same call; instead, multiple | ||
/// calls with additional transactions may be made. |
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.
Done and linked to pertinent section on ordering in the trait docs.
lightning/src/chain/mod.rs
Outdated
/// calls with additional transactions may be made. | ||
/// | ||
/// May be called before or after [`best_block_updated`] for the corresponding block. However, | ||
/// it must not be called after [`best_block_updated`] if `header` corresponds to a block that |
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.
Re-worded. Let me know if that captures the reorg case. I also linked earlier to trait-level documentation on ordering.
/// handled by [`transaction_unconfirmed`]. | ||
/// | ||
/// [`transaction_unconfirmed`]: Self::transaction_unconfirmed | ||
fn best_block_updated(&self, header: &BlockHeader, height: u32); |
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 believe it is necessary as they are allowed to skip intermediary headers even for those where transaction_confirmed
is called, IIUC.
lightning/src/chain/mod.rs
Outdated
/// Should be called when a new header is available but may be skipped for intermediary blocks | ||
/// if they become available at the same time. | ||
/// | ||
/// Implementations are not required to handle chain reorganizations unless `height` is not |
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.
This paragraph is meant for the implementer not the caller. But I can't exactly recall where we landed on this. Definitely needs to rewritten regardless.
IIRC, this is an implementation detail that may be leaking into the interface. Question is should I just drop this? Or is there something we need to convey about how implementations handle <=
heights.
/// Returns transactions that should be monitored for reorganization out of the chain. | ||
/// | ||
/// Should include any transactions passed to [`transactions_confirmed`] that have insufficient | ||
/// confirmations to be safe from a chain reorganization. Should not include any transactions |
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.
Right, not yet configurable. Also, it's general because it's talking about how this may be implemented. For example, ChannelManager
always returns the funding transactions no matter how many confirmations.
lightning/src/chain/mod.rs
Outdated
/// - Call [`transactions_confirmed`] for any on-chain activity of interest. | ||
/// - Return such transactions from [`get_relevant_txids`] until they have enough confirmations to | ||
/// no longer be in danger of chain reorganization. | ||
/// - Call [`transaction_unconfirmed`] for any transaction returned by [`get_relevant_txids`] that |
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.
Here, transaction_unconfirmed
would need to be called first. I think this is addressed in the new "Order" section. Let me know if it doesn't clear things up, though, or if you have recommendations on how to better word it.
c0fc420
to
81f093f
Compare
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.
Looks good mod one question.
lightning/src/chain/chainmonitor.rs
Outdated
/// | ||
/// [`block_connected`]: Self::block_connected | ||
/// [`update_best_block`]: Self::update_best_block | ||
/// [`best_block_updated`]: Self::best_block_updated |
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.
Should we convert these into an impl chain::Confirm for ChainMonitor
?
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.
Yeah, this likely would be needed when implementing a sync utility. Added a separate block with Send
and Sync
restrictions akin to Listen
. Let me know if I'm misunderstanding when this is needed.
Could also move the implementations directly into the added definitions if you'd like. It's unclear to me why they are split for Listen
.
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.
Added a separate block with Send and Sync restrictions akin to Listen. Let me know if I'm misunderstanding when this is needed.
Hmm, frankly not sure why those are there, I assume we used to need them for something, but now don't? Either way, it seems to compile without them, so no reason to have extra bounds on it - same goes for the chain::Listen
impl as well now.
Also, I think if the traits are implemented we should drop the public functions which are duplicative. block_connected
is only there because its slightly different from the chain::Listen
block_connected
, IIRC.
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.
Yeah, sounds good. Note that this requires having full_stack
uses chain::Confirm
for ChainMonitor
otherwise it would be a much larger change. FWIW, it is already doing so for ChannelManager
.
3f1d727
to
7f35903
Compare
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.
Looks good to me, too!
Define a separate trait akin to chain::Listen for notifying when transactions have been confirmed on chain or unconfirmed during a chain reorganization. Whereas chain::Listen is used for block-oriented chain sources, chain::Confirm is used for chain sources supplying data for activity related to transactions and outputs registered via chain::Filter.
7f35903
to
99e2283
Compare
Squashed fixup commits |
Define a separate trait akin to
chain::Listen
for notifying when transactions have been confirmed on chain or unconfirmed during a chain reorganization. Whereaschain::Listen
is used for block-oriented chain sources,chain::Confirm
is used for chain sources supplying data for activity related to transactions and outputs registered viachain::Filter
.