-
Notifications
You must be signed in to change notification settings - Fork 365
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
Batching of HTLC transactions for anchor output channels #3064
Comments
While we can definitely aggregate more aggressively, we may want to split up packages as HTLCs get close (e.g., 6-12 blocks left) to their deadline and the package they were in remains unconfirmed. |
Would we want to split up packages due to any transaction pinning concerns or to choose a higher fee rate for those HTLCs? If the latter, there could also be a trade-off to fee bump the entire package with the higher fee rate. |
For received HTLCs that haven't expired, the counterparty can't claim them so there's not much to talk about there (but indeed if they're getting close to expiry it may make sense to split them off and start giving them higher fee, though you can of course just assign higher fee to the whole package). For sent HTLCs (or received HTLCs once they expire or revoked outputs if our counterparty broadcasts a stale state), the counterparty could be able to spend the same output, which introduces pinning questions. However, its not clear to me that its worth trying to materially change the claiming logic for them - if a counterparty is trying to exploit you by pinning, they're going to just push the maximum possible amount as pending HTLC(s) and then try to pin them. If we assume pinning is 100% reliable at delaying an HTLC claim until it has expired then they will just always succeed and we should address pinning with mempool monitoring and human intervention (eg transaction accelerator services) instead. If, on the other hand, we assign some probability of succeeding at pinning, and we assume trials are uncorrelated (they almost certainly are not), then we should not combine claims too much to at least force the counterparty to do a handful of trials so that we get some successes. Of course none of that means we should aggregate spends of outputs that we believe are not pin-able (unexpired received HTLCs and revoked counterparty balance, basically, see lightning/bolts#803) with ones that we believe may be pin-able, but it seems like a reasonable policy might be to just claim everything in two buckets - pin-able and not-pin-able outputs. |
When we first added batch claiming, we only did so for claims which we thought were not pinnable, i.e. those for which only we can claim the output. This was the conservative choice - any outputs which we think are potentially pinnable might be pinned, leaving our entire batch unable to confirm on chain. However, if we assume that pinnable outputs are, indeed pinnable, and attempts to pin a transaction and keep it from confirming have highly correlated success rates, there's no reason we shouldn't also batch claims of pinnable outputs separately. Here we do so, grouping batch-claimable outputs into pinnable and unpinnable `AggregationCluster`s. We aggregate all outputs (which have some time left before expiry) in each cluster jointly. Fixes lightningdevkit#3064
When we first added batch claiming, we only did so for claims which we thought were not pinnable, i.e. those for which only we can claim the output. This was the conservative choice - any outputs which we think are potentially pinnable might be pinned, leaving our entire batch unable to confirm on chain. However, if we assume that pinnable outputs are, indeed pinnable, and attempts to pin a transaction and keep it from confirming have highly correlated success rates, there's no reason we shouldn't also batch claims of pinnable outputs separately. Sadly, aggregating other types of inputs is rather nontrivial, as evidenced by the size of this commit - HTLC-Timeout claims have locktimes fixed by our counterparty's signature and thus can only be aggregated with other HTLCs of the same CLTV, which we have to check for. Further, our concept of "pinnable" is deliberately somewhat fuzzy - outputs which we believe are not pinnable will eventually become pinnable at the height where our counterparty can spend them. Thus, we treat outputs as pinnable if they're over that height, and if they're within `COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE` of that height we treat them as neither pinnable nor not-pinnable, aggregating such claims only with other claims which will become pinnable at the same height. However, the complexity required is worth it - aggregation can save our users a lot of money in the case of a force-close, and directly impacts the amount of UTXOs they need as reserve for anchors, so we want to aggregate as much as possible. Fixes lightningdevkit#3064
When we first added batch claiming, we only did so for claims which we thought were not pinnable, i.e. those for which only we can claim the output. This was the conservative choice - any outputs which we think are potentially pinnable might be pinned, leaving our entire batch unable to confirm on chain. However, if we assume that pinnable outputs are, indeed pinnable, and attempts to pin a transaction and keep it from confirming have highly correlated success rates, there's no reason we shouldn't also batch claims of pinnable outputs separately. Sadly, aggregating other types of inputs is rather nontrivial, as evidenced by the size of this commit - HTLC-Timeout claims have locktimes fixed by our counterparty's signature and thus can only be aggregated with other HTLCs of the same CLTV, which we have to check for. Further, our concept of "pinnable" is deliberately somewhat fuzzy - outputs which we believe are not pinnable will eventually become pinnable at the height where our counterparty can spend them. Thus, we treat outputs as pinnable if they're over that height, and if they're within `COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE` of that height we treat them as neither pinnable nor not-pinnable, aggregating such claims only with other claims which will become pinnable at the same height. However, the complexity required is worth it - aggregation can save our users a lot of money in the case of a force-close, and directly impacts the amount of UTXOs they need as reserve for anchors, so we want to aggregate as much as possible. Fixes lightningdevkit#3064
When we first added batch claiming, we only did so for claims which we thought were not pinnable, i.e. those for which only we can claim the output. This was the conservative choice - any outputs which we think are potentially pinnable might be pinned, leaving our entire batch unable to confirm on chain. However, if we assume that pinnable outputs are, indeed pinnable, and attempts to pin a transaction and keep it from confirming have highly correlated success rates, there's no reason we shouldn't also batch claims of pinnable outputs separately. Sadly, aggregating other types of inputs is rather nontrivial, as evidenced by the size of this commit - HTLC-Timeout claims have locktimes fixed by our counterparty's signature and thus can only be aggregated with other HTLCs of the same CLTV, which we have to check for. Further, our concept of "pinnable" is deliberately somewhat fuzzy - outputs which we believe are not pinnable will eventually become pinnable at the height where our counterparty can spend them. Thus, we treat outputs as pinnable if they're over that height, and if they're within `COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE` of that height we treat them as neither pinnable nor not-pinnable, aggregating such claims only with other claims which will become pinnable at the same height. However, the complexity required is worth it - aggregation can save our users a lot of money in the case of a force-close, and directly impacts the amount of UTXOs they need as reserve for anchors, so we want to aggregate as much as possible. Fixes lightningdevkit#3064
When we first added batch claiming, we only did so for claims which we thought were not pinnable, i.e. those for which only we can claim the output. This was the conservative choice - any outputs which we think are potentially pinnable might be pinned, leaving our entire batch unable to confirm on chain. However, if we assume that pinnable outputs are, indeed pinnable, and attempts to pin a transaction and keep it from confirming have highly correlated success rates, there's no reason we shouldn't also batch claims of pinnable outputs separately. Sadly, aggregating other types of inputs is rather nontrivial, as evidenced by the size of this commit - HTLC-Timeout claims have locktimes fixed by our counterparty's signature and thus can only be aggregated with other HTLCs of the same CLTV, which we have to check for. Further, our concept of "pinnable" is deliberately somewhat fuzzy - outputs which we believe are not pinnable will eventually become pinnable at the height where our counterparty can spend them. Thus, we treat outputs as pinnable if they're over that height, and if they're within `COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE` of that height we treat them as neither pinnable nor not-pinnable, aggregating such claims only with other claims which will become pinnable at the same height. However, the complexity required is worth it - aggregation can save our users a lot of money in the case of a force-close, and directly impacts the amount of UTXOs they need as reserve for anchors, so we want to aggregate as much as possible. Fixes lightningdevkit#3064
When we first added batch claiming, we only did so for claims which we thought were not pinnable, i.e. those for which only we can claim the output. This was the conservative choice - any outputs which we think are potentially pinnable might be pinned, leaving our entire batch unable to confirm on chain. However, if we assume that pinnable outputs are, indeed pinnable, and attempts to pin a transaction and keep it from confirming have highly correlated success rates, there's no reason we shouldn't also batch claims of pinnable outputs separately. Sadly, aggregating other types of inputs is rather nontrivial, as evidenced by the size of this commit. HTLC-Timeout claims have locktimes fixed by our counterparty's signature and thus can only be aggregated with other HTLCs of the same CLTV, which we have to check for. Further, our concept of "pinnable" is deliberately somewhat fuzzy - outputs which we believe are not pinnable will eventually become pinnable at the height where our counterparty can spend them. Thus, we treat outputs as pinnable if they're over that height, and if they're within `COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE` of that height we treat them as neither pinnable nor not-pinnable, aggregating such claims only with other claims which will become pinnable at the same height. However, the complexity required is worth it - aggregation can save our users a lot of money in the case of a force-close, and directly impacts the amount of UTXOs they need as reserve for anchors, so we want to aggregate as much as possible. Fixes lightningdevkit#3064 Co-authored-by: Matt Corallo <git@bluematt.me>
When we first added batch claiming, we only did so for claims which we thought were not pinnable, i.e. those for which only we can claim the output. This was the conservative choice - any outputs which we think are potentially pinnable might be pinned, leaving our entire batch unable to confirm on chain. However, if we assume that pinnable outputs are, indeed pinnable, and attempts to pin a transaction and keep it from confirming have highly correlated success rates, there's no reason we shouldn't also batch claims of pinnable outputs separately. Sadly, aggregating other types of inputs is rather nontrivial, as evidenced by the size of this commit. HTLC-Timeout claims have locktimes fixed by our counterparty's signature and thus can only be aggregated with other HTLCs of the same CLTV, which we have to check for. Further, our concept of "pinnable" is deliberately somewhat fuzzy - outputs which we believe are not pinnable will eventually become pinnable at the height where our counterparty can spend them. Thus, we treat outputs as pinnable if they're over that height, and if they're within `COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE` of that height we treat them as neither pinnable nor not-pinnable, aggregating such claims only with other claims which will become pinnable at the same height. However, the complexity required is worth it - aggregation can save our users a lot of money in the case of a force-close, and directly impacts the amount of UTXOs they need as reserve for anchors, so we want to aggregate as much as possible. Fixes lightningdevkit#3064 Co-authored-by: Matt Corallo <git@bluematt.me>
HTLC transactions for anchor output channels can be aggregated with
SIGHASH_SINGLE|SIGHASH_ANYONECANPAY
. However, if I understand correctly, LDK currently performs only limited aggregation: only for HTLC success transactions, and only for preimages provided before force-closure, not afterwards.In the ideal case, all HTLC transactions can be aggregated per block, and a change output from one block can be used for the next block. This could significantly reduce the number of UTXOs (as opposed to the amount) that need to be reserved for anchor output channels.
Happy to take a look as well!
cc @wpaulino
The text was updated successfully, but these errors were encountered: