Skip to content
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

wallet: respect policy-level transaction size limits when crafting regular and funding transactions #4760

Closed
Roasbeef opened this issue Nov 11, 2020 · 9 comments · Fixed by #8345 · May be fixed by #6400
Closed

wallet: respect policy-level transaction size limits when crafting regular and funding transactions #4760

Roasbeef opened this issue Nov 11, 2020 · 9 comments · Fixed by #8345 · May be fixed by #6400
Assignees
Labels
beginner Issues suitable for new developers bug Unintended code behaviour intermediate Issues suitable for developers moderately familiar with the codebase and LN P1 MUST be fixed or reviewed policy wallet The wallet (lnwallet) which LND uses

Comments

@Roasbeef
Copy link
Member

Tracking this here instead of the btcwallet issue for more visibility. As is, we don't always ensure that a transaction either we construct manually (for funding) or within btcwallet itself is below the current widely used policy that constraints transaction sizes. Thankfully, we can simply start using the existing policy level function within btcd itself to enforce these limits: https://github.com/btcsuite/btcd/blob/master/mempool/policy.go#L271

When a user encounters this issue, they'll see this in the logs:

: unmatched backend error: -26: 64: tx-size

And then end up with a dangling transaction that'll keep being rebroadcast, when instead we should remove it from the tx store.

@Roasbeef Roasbeef added bug Unintended code behaviour wallet The wallet (lnwallet) which LND uses policy labels Nov 11, 2020
@Roasbeef Roasbeef added this to the 0.12.0 milestone Nov 17, 2020
@Roasbeef
Copy link
Member Author

Actually, reading the btcwallet code more closely here, I think we already properly handle this case. What we don't do however, is remove the "pending open" channel from the lnd's DB.

@Roasbeef Roasbeef modified the milestones: 0.12.0, 0.13.0 Dec 12, 2020
@Roasbeef Roasbeef added P1 MUST be fixed or reviewed beginner Issues suitable for new developers intermediate Issues suitable for developers moderately familiar with the codebase and LN labels Jan 28, 2021
@Roasbeef Roasbeef added this to To do in v0.13.0-beta Jan 28, 2021
@Roasbeef Roasbeef moved this from To do to Review in progress in v0.13.0-beta Apr 2, 2021
@Roasbeef Roasbeef moved this from Review in progress to Blocked in v0.13.0-beta Apr 14, 2021
@Roasbeef Roasbeef removed this from Blocked in v0.13.0-beta May 11, 2021
@Roasbeef Roasbeef modified the milestones: 0.13.0, v0.14.0 May 11, 2021
@Roasbeef Roasbeef modified the milestones: v0.14.0, v0.15.0 Aug 30, 2021
@ellemouton
Copy link
Collaborator

Just want to get some feedback re the scope of this before diving any deeper:

seems to me there are 2 issues here with ranging scopes:

  1. missing sanity checks when constructing a funding tx.

This would involve some changes to the ChannelReservation logic to ensure that the funding tx it builds is below a certain size (would need to fetch that size somewhere) and to then retry with different coins if size is too big. ie, this becomes a coin selection issue.

  1. dealing with a pending channel after having tried broadcasting the tx.

This is a lot trickier than problem 1 since with this, we have already sent our tx out into the wild and cant ever be 100% sure that it has not actually broadcast. Not entirely sure what the fix for this should be... yes we can examine the returned errors but i dont think we can assume the errors are trustworthy enough to release the inputs and forget the channel.

Are the above assumptions correct? And if so, should the scope of the fix for this issue address both?

(any thoughts would be much appreciated @yyforyongyu , @Roasbeef @ & @Crypt-iQ (saw that you posted some thoughts on the linked PR))

@Crypt-iQ
Copy link
Collaborator

Fixing both at once sounds good (could split up into 2 pr's)

  1. Does not have to be in ChannelReservation logic. Ideally we'd have a testmempoolaccept api that handled this instead of trying to mimic standardness rules in the funding code.
  2. If step 1 is implemented and an error is returned, then something besides standardness is going on. Maybe this is an unreliable error. I see two paths here:
    2a. If an error occurs, try to double-spend the transaction. This would need Funding detect double spends  #5567 to detect the double-spend, release inputs, and forget the channel.
    2b. Continually rebroadcast the funding transaction if an error occurs.

2a & 2b could be combined so that 2b falls back to 2a after some time.

@yyforyongyu
Copy link
Collaborator

we have already sent our tx out into the wild and cant ever be 100% sure that it has not actually broadcast.

I don't think this is something we want to deal here. We use the interface PublishTransaction here, which is implemented in btcwallet. If the above statement is an issue then we should fix it in btcwallet.

Basically we rely on this interface here, and it must do what it guarantees. Otherwise we'd have an issue not just in funding, but every call site of this interface in lnd.

As for the scope, I think this issue deals specifically with the error : unmatched backend error: -26: 64: tx-size. However, PublishTransaction doesn't explicitly return this error, as it maps the error codes here. So to continue the work in #5158, I think if we could explicitly check this error we'd be safe. So either,

  • we change btcwallet to catch and return this error explicitly, or,
  • we can do an error match in lnd to be sure we are getting this exact error when PublishTransaction fails.

@Crypt-iQ
Copy link
Collaborator

Crypt-iQ commented Mar 24, 2022

we have already sent our tx out into the wild and cant ever be 100% sure that it has not actually broadcast.

I don't think this is something we want to deal here. We use the interface PublishTransaction here, which is implemented in btcwallet. If the above statement is an issue then we should fix it in btcwallet.

I believe elle is referring to the case where we send a transaction and we receive a malicious MsgReject in neutrino. Or another scenario like maybe we're eclipsed and have sent it out, but it hasn't propagated. This neutrino case should definitely be fixed in addition to the PR that fixes this issue.

Basically we rely on this interface here, and it must do what it guarantees. Otherwise we'd have an issue not just in funding, but every call site of this interface in lnd.

I still think having some API that calls PublishTransaction and continues to do so until some block-timeout would be useful.

As for the scope, I think this issue deals specifically with the error : unmatched backend error: -26: 64: tx-size. However, PublishTransaction doesn't explicitly return this error, as it maps the error codes here. So to continue the work in #5158, I think if we could explicitly check this error we'd be safe. So either,

* we change `btcwallet` to catch and return this error explicitly, or,

* we can do an error match in `lnd` to be sure we are getting this exact error when `PublishTransaction` fails.

This is what a testmempoolaccept api could pre-emptively handle. This is already something that we need as having one would have caught the high-S signatures CVE. I do think though that a minimum fix would be something along the lines of your original PR, but we'd want to catch more than just tx-size since there are other policy checks that can fail besides size. As an example, an error that is returned that is not policy and wouldn't be caught if we'd only catch tx-size is mempool min fee not met. If all non-double-spend errors are caught, however, I think it would be a good idea on error to wait until the input is double-spent or the channel is confirmed on chain (either we missed something or the user took their raw tx and broadcast it elsewhere) before cleaning up as a safety measure in case something was missed.

@yyforyongyu
Copy link
Collaborator

@Crypt-iQ If we want to handle more than tx-size error, it'd be nice but another story. This testmempoolaccept is dope and can be implemented in btcwallet. I think our abstractions are pretty clear here, lnd defines all types of transactions, btcwallet treats them as raw tx and handles the validation and broadcast. Behind the wallet there are three chain backends handling layer one stuff. If we want to fix the issues across the layers of abs, then a good first step IMO is to refactor PublishTransaction to return a list of explicitly defined errors, and we handle the errors one by one in lnd. I don't think there's one solution to fit in all the scenarios, eg if tx-size is not right we are sure we can abandon the funding flow.

or the user took their raw tx and broadcast it elsewhere

If this happens it's nice to handle it but not necessary or urgent IMO. Meanwhile, curious why would a user do that?

@Crypt-iQ
Copy link
Collaborator

testmempoolaccept would probably be written in btcd and called from btcwallet. My point is there are more policy errors besides tx-size that a user can hit and these would probably occur with the psbt api. This issue is concerned with tx-size, but it could easily include every policy violation and PublishTransaction would just return some PolicyError. Also the mempool-min-fee error should be caught and special-cased probably

Meanwhile, curious why would a user do that?

Users pretty much do anything and everything given some large timeframe. I was thinking this would happen using the psbt api.

@Roasbeef
Copy link
Member Author

Seeing this in #6566 but odd in that if you go to my last linked comment there, in the code we should always remove the transaction on startup when/if we go to rebroadcast it, but also the very first time we go to broadcast it (unless that fails for some reason).

Roasbeef added a commit to Roasbeef/lnd that referenced this issue May 26, 2022
…ore broadcast

In this commit, we start to use the `CheckTransactionStandard` function
from the `mempool` package to validate transactions further before
broadcast. This'll help catch instances where we make a massive
transaction, and therefor can't actually propagate it across the
network.

Fixes lightningnetwork#4760
Fixes lightningnetwork#6556
Roasbeef added a commit to Roasbeef/lnd that referenced this issue May 26, 2022
…ore broadcast

In this commit, we start to use the `CheckTransactionStandard` function
from the `mempool` package to validate transactions further before
broadcast. This'll help catch instances where we make a massive
transaction, and therefor can't actually propagate it across the
network.

Fixes lightningnetwork#4760
Fixes lightningnetwork#6556
@Roasbeef Roasbeef modified the milestones: v0.15.1, v0.16.0 Jul 27, 2022
@saubyk saubyk modified the milestones: v0.16.0, v0.16.1 Dec 6, 2022
@ellemouton
Copy link
Collaborator

More details from users who have run into this for both sendcoins and during channel open can be found in these issues:

#6556
#7622

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
beginner Issues suitable for new developers bug Unintended code behaviour intermediate Issues suitable for developers moderately familiar with the codebase and LN P1 MUST be fixed or reviewed policy wallet The wallet (lnwallet) which LND uses
Projects
None yet
5 participants