Open matthewjablack opened 3 years ago
I think this is covered by
if funding_security_point is reached:
MUST spend a funding input with a higher-fee-rate transaction/absolute fee than any previously propagated package fee-rate
MUST start a fee-bumping timer of length security_bump_frequency
MUST disable congestion_bump_frequency timer
Though the wording could maybe be made more explicit.
This should be specified in the spec, and there should probably also be a timeout value in the offer message / accept message to specify how long a party will wait for a transaction to be broadcast.
I'm not sure about having it as a parameter in the protocol. I think it makes more sense to carefully check that the fee rate is adequate with respect to current mempool conditions and then have a global timeout. Open for discussions though.
I think this is covered by ...
So a security_point
is a time/block-stamp after which the confirmation of a corresponding transaction is a matter of contract safety
. So it has to do specifically with confirmation of the funding tx.
My understanding for funding_security_point
was that it referred to the safety of the contracts once it had been broadcast. I.e. if not confirmed within 24 hours. Whereas this issue refers to the situation where it has not been broadcast to the mempool at all, since the user would obviously not be able to fee bump in that scenario.
I'm not sure about having it as a parameter in the protocol. I think it makes more sense to carefully check that the fee rate is adequate with respect to current mempool conditions and then have a global timeout. Open for discussions though.
Perhaps there needs to be a finalize_security_point
which refers to the point at which the funding transaction not being present in the mempool is considered a matter of contract security.
My understanding for funding_security_point was that it referred to the safety of the contracts once it had been broadcast. I.e. if not confirmed within 24 hours. Whereas this issue refers to the situation where it has not been broadcast to the mempool at all, since the user would obviously not be able to fee bump in that scenario.
My understanding was that it referred to both situations. But if we are having this discussion and both of us aren't sure, it probably means that it's not clear enough.
@ariard can you confirm which one it is?
Currently, funding transactions signatures are only known by the DLC initiator, which as you described
open 2 issues :
a) it offers to the initiator a call option in function of mempool feerate fluctuation
b) it puts at risk the acceptor if funding transaction isn't confirmed before the security_point
is reached
W.r.t to a), the spec currently suggests both DLC counterparties to fee-bump the funding transaction in case it doesn't confirm. To remove the option we might either restrain the fee-bumping burden on the initiator only or send back the initiator funding transaction signatures to the acceptor ?
W.r.t to b) the current spec says
"if a funding signature has been sent or a funding transaction broadcast and there is no confirmation: MUST spend a funding input with a higher-fee-rate transaction/absolute fee than any previously propagated package fee-rate"
The first part of the sentence ("if a funding signature has been sent") targets the acceptor, but I confess the second sentence isn't really clear. The acceptor might not be able to observe the propagated package fee-rate in case of a malicious counterparty and left with a scortched earth approach of slowly burning its collateral input value as a fee. If a package fee-rate can be observed the starter feerate for such collateral input should be the funding transaction one. I should modify the spec saying this.
A 3rd issue raised in this issue is when it's lawful for both counterparties to try a double-spend and not be reputation-penalized in consequence. Likely we need a global timeout announced in some message.
W.r.t a) I think suggesting that both DLC counterparties fee-bump the funding tx in case it doesn't confirm is reasonable.
I have concerns around making fee-bumping one-sided since this puts the DLC Initiator in an awkward position where their only recourse in the case of a low-fee funding tx that isn't getting confirmed is to wait until refund_security_point
. It also gives the Acceptor
the ability to just not fee bump if market conditions aren't favorable.
W.r.t b) Isn't it the DLC Acceptor
that is the only one who knows the funding transaction signatures? https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#contract-negotiation
Once the accepter receives the sign_dlc message, it must broadcast the funding transaction to the Bitcoin network.
So in this case:
The first part of the sentence ("if a funding signature has been sent") targets the acceptor, but I confess the second sentence isn't really clear. The acceptor might not be able to observe the propagated package fee-rate in case of a malicious counterparty
I guess acceptor
should be changed to initiator
. If the initiator
isn't able to observe the propagated package fee-rate in case of a malicious counterparty, their only recourse is to move their funding inputs using this scorched earth
approach as you mentioned.
A 3rd issue raised in this issue is when it's lawful for both counterparties to try a double-spend and not be reputation-penalized in consequence. Likely we need a global timeout announced in some message.
Agreed. Are you thinking of a security_point
for this global timeout as well as a TLV? In practical terms, this should probably be a very short global timeout for UX purposes.
Agreed. Are you thinking of a security_point for this global timeout as well as a TLV? In practical terms, this should probably be a very short global timeout for UX purposes.
I think it will be difficult to have a "very short" timeout as it is difficult to rely on transaction propagation. Maybe a solution would be to add a step to the protocol where the acceptor also shares his signatures for the fund tx, in which case it would be possible and meaningful to have a short timeout on this message which would make the UX smooth.
Maybe a solution would be to add a step to the protocol where the acceptor also shares his signatures for the fund tx, in which case it would be possible and meaningful to have a short timeout on this message which would make the UX smooth.
I think this is a great idea! In that case, the full set of messages could be something like Offer
, Accept
, Sign
, Finalize
, with specification for timeout between each of these messages.
Thoughts @nkohen @ariard?
I think it will be difficult to have a "very short" timeout as it is difficult to rely on transaction propagation. Maybe a solution would be to add a step to the protocol where the acceptor also shares his signatures for the fund tx, in which case it would be possible and meaningful to have a short timeout on this message which would make the UX smooth.
The only problem here is that the Accepter doesn't need to ever send that final message
The only problem here is that the Accepter doesn't need to ever send that final message
Right, and I guess the assumption is if Finalize
isn't received by the Initiator, and the Initiator also doesn't detect anything in mempool, then Initiator assumes malicious intent and starts moving funding UTXOs.
Just read the whole thread, here are my thoughts:
funding_security_point + x
should be used as a time to double-spend funding inputs in the case that you are an offerer who has not received confirmation of the funding transaction on-chain. I don't think there's any issue with this as the offerer should be black-listing the accepter in this case so what should they care if the accepter is black-listing them in return?Finalize
message so long as if it is added it is explicitly marked as optional (likely with a description of how it leads to better UX and allows one's counter-party to participate in fee-bumping without worrying about whether the funding tx has been broadcast, which is good for the sender of this optional message).dlc_cancel
message to make cooperative-case double-spending of a single funding input by one party not result in black-listing.EDIT: To be clear, the dlc_cancel
requires an ACK response
On further discussion in slack with Tibo, I've decided that I don't actually have any opinions on the optional vs. mandatory nature of points 4 and 5
W.r.t b) Isn't it the DLC Acceptor that is the only one who knows the funding transaction signatures? https://github.com/discreetlogcontracts/dlcspecs/blob/master/Protocol.md#contract-negotiation
You're right, the initiator doesn't learn the acceptor signature. I guess I've been confused with the dual-funding_tx proposal where the initiator is the one collecting all the signatures and responsible of the fee-bumping.
Right, and I guess the assumption is if Finalize isn't received by the Initiator, and the Initiator also doesn't detect anything in mempool, then Initiator assumes malicious intent and starts moving funding UTXOs.
I would rather shun away from any mempool-detection as lightclient don't have a mempool and it's gameable by broadcasting the funding_tx in your local mempool and a double-spend/pinning tx to the rest of the network.
Let's consider the following framework of actions and see the margin of actions we have to solve the call_option. Those are the actions counterparties can take with the current transactions/signatures exchanged, not exactly what the spec is requiring to do.
An Acceptor:
An Initiator:
As you can observe by running the optional paths, in case of malicious counterparties, we have the choice between overpaying bumping feerate OR infinite timevalue DoS. The current spec is recommending the first option as it forces the attacker to engage in a scorched earth game and to bid competing fees in the mempool to maintain the pin. Note, this last point benefits the Acceptor only if it does engage in funding input double-spend once reaching its funding_security_point
. Otherwise a malicious Initiator has a free pinning trick by stucking a rbf-disabled doube-spend of its input in network mempools.
With this context in mind, I think solving the call_option by either two-sided fee-bumping or complete signatures exchange will only complexify further this part of the spec. And introduce new issues like asynchronous fee-bumping overshooting the package feerate far above what is required for block inclusion.
What we might consider in the feature would be a premium fee paid by the initiator to the acceptor to cover mempool spikes. Such fee could be zero or even negative if the mempool might dry-up in near-feature. It could be added on any change output.
I would shun away from black-listing from now, failing to confirm the funding_tx might have a lot of acceptable reasons like a network outage or black mempool spikes. We might introduce service-level-agreement negotiation feature in the future.
Lastly, I think a timeout
announced by the Initiator to the Acceptor is pretty nice, at it lets the Acceptor stops fee-bumping and frees out any bumping utxo especially locked by the operation. You might a small-value change output and uses a 2 input CPFP.
I'm pretty sure I need to correct the current spec to make it clearer, but for v0 I'm of the opinion we shouldn't increase its scope. Note also, we won't reuse most of the work here once we piggyback on payment channels and if get package-relay, a lot of those issues should be flattened.
I think solving the call_option by either two-sided fee-bumping or complete signatures exchange will only complexify further this part of the spec.
The main goal of complete signature exchange (or Finalize
message) would be to prevent the acceptor from not broadcasting the fund_tx for the purpose of getting a free option, or at least for the offerer to see that the acceptor might not be cooperating. The way I see it from the acceptor POV is:
An Initiator:
Finalize
:
Finalize
message:
Tbh I'm not trying to convince anybody that Finalize
is something we should have, I agree it might make thing a bit more complicated.
The more I think about this the more it seems to me that messages such as Finalize
and Cancel
should not be included in the protocol specification but rather should be viewed as second layer "features" which parties can opt-in to using. I think we should keep a clean separation between the information needed to facilitate the construction of a DLC and additional messages which make mitigation of problems like these and UX easier/nicer. Users can of course choose not to interact with other users who do not support these additional messages but I don't think this warrants complicating the core protocol when it can instead be added as a second layer interaction.
I do think Finalize
and Cancel
should be laid out somewhere in the specification for clients to opt-in implementing, but agree with @nkohen that it doesn't make as much sense to be included in the core protocol specification. A second layer interaction section makes sense to me, and there are additional "features" that I think would be useful to have laid out as well (such as #161).
ACK adding second layer interaction section
During the Funding Phase, the Non-Interactive-Protocol specifies that
if all counter-party CET and funding signatures are received
then the nodeMUST finalize the funding transaction with a local SIGHASH_ALL signatures
andMUST broadcast the funding transaction
However, if a node does not perform these actions, it puts the counter-party in an awkward situation. If they do nothing, then the node can monitor changes in the market, and broadcast when it is optimal for them.
In this case, the counter-party should move their UTXOs, either to a new address in their wallet or into a new DLC, they should blacklist the node, and they should also monitor the chain to ensure the node doesn't broadcast the funding transaction at a later point.
This should be specified in the spec, and there should probably also be a
timeout
value in the offer message / accept message to specify how long a party will wait for a transaction to be broadcast.