Replies: 2 comments 4 replies
-
Based on above approach, adding tentative tasks to the issue:
|
Beta Was this translation helpful? Give feedback.
-
I favor option 2 for retrieving this data back. Even if we could use async/await with option 1, we still need to handle failures (temporary read fail for whatever reason), and we're also blocking the processing pipeline for new blocks on each monitor if we choose to As for the issue with |
Beta Was this translation helpful? Give feedback.
-
Issue: #3049
Problem
After every commitment is signed,
counterparty_claimable_outpoints
keeps on growing without bounds within a channel_monitor, with a new hashmap entry for each commitment_tx.It poses two problems mainly:
We don’t want to keep storing outpoints that will only be used for revoked_tx/funding_spend, instead we would like to store them in cold storage and read them only when required.
Ideal outcome: After doing this, Ldk's memory footprint should be drastically decreased owing to removed in-memory hashmap entries of
counterparty_claimable_outpoints
Solution
Right now,
counterparty_claimable_outpoints: HashMap<Txid, Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>
stores two things mainly,
PaymentId
that can be used to track pending/inflight payments.HTLC Sources are also used to reconstruct pending_outbound_payments in channel_manager.
For commitment_tx’s htlc_outputs:
Most of the times, it is being used either for
current_counterparty_commitment_txid
orprev_counterparty_commitment_txid
for which we need to keep it in-memory because it is not just for revoked_tx/funding_spend, those are for current ongoing commitment_signed exchanges.Otherwise, it is used for revoked_tx/funding_spend.
So, for older commitment_tx outpoints, which are only useful for revoked_tx/funding_spend, we will persist them separately out of channel_monitor by using a trigger [here](
rust-lightning/lightning/src/chain/channelmonitor.rs
Lines 2545 to 2547 in d1ac071
ClaimInfo
against acommitment_tx
which can be retrieved later.Both read and write of
ClaimInfo
should be done in an async fashion, as we don’t need to block everything to handle this.Motivation: This is inline with us providing a async interface for channel_monitor persistence. If we don’t do async then we will be blocked on persistence for every commitment_signed which is sub-optimal.
Async Interface options
As mentioned earlier, both read and write of
ClaimInfo
should be done using in an async fashion. And currently we don’t have a Rust-async KVStore interface, which, as I understand, we avoid due to bindings support in LDK.So there are couple of options for Async interface:
Public trait, similar to
Persist
traitSimilar to how we handle async channel_monitor persistence for both new/updated channel_monitors, we could define a new interface for ClaimInfo or re-use existing Persist interface for it. Client will need to return something like
InProgress
and notify us via a function call just the current channel_monitor flow.Reading/writing ClaimInfo in Persist interface doesn’t fit very well within its scope, so we will have to create a new trait/interface.
Cons: ChannelMonitor interface /
InProgress
handling and its custom async implementation is already a complex interface to understand for our users and introducing yet another similar interface can cause unnecessary pain with one more custom async interface. An events based interface seems more intuitive, re-uses existing events interface that clients are familiar with and can be handled out-of-band, slightly delayed arbitrarily.Events based approach:
Publish
PersistClaimInfo
event which can be handled async by clients, whenever they handle the event, we(chain_monitor) are notified via a function call and we remove in-memory entry for the claim from channel_monitor.Whenever we suspect a revoked_tx/funding_spend after seeing a matching tx in transactions_confirmed, we request ClaimInfo using
RequestClaimInfo
, and once we have it, we do rest of the handling forcheck_spend_counterparty_transaction
orcancel_prev_commitment_claims
Cons: These events are time sensitive, if
RequestClaimInfo
is not handled in time we will fail to broadcast justice_tx.Preferred approach: Events, we can document that these events are time-sensitive, and the same applies for trait approach as well.
Caveats
In
get_claimable_balances
, if funding_spend is confirmed/pending, we readcounterparty_claimable_outpoints
forfunding_tx
on every call to this function.This is slightly concerning for two reasons:
As a workaround, once we have funding_spend_seen and
ClaimInfo
provided by user, we store it back again in hashmap. This solves it for times once we haveClaimInfo
.But, we can't provide reliable
get_claimable_balances
in the time betweenfunding_spend_seen
and user providing us withClaimInfo
.get_claimable_balances
would be slightly out-of-date until we haveClaimInfo
provided to us, and that should be fine for now.Beta Was this translation helpful? Give feedback.
All reactions