Open joostjager opened 3 years ago
Related instance: https://github.com/lightningnetwork/lnd/issues/5863#issue-1026917711
is this issue still free to work on ?
@ziggie1984 yes!
starting my work on it, will report with my first impression on friday the upcoming week !
thanks @joostjager for the hint, yes the inaccuracy is exactly there, always adding e.g. 31 bytes for p2wkh default change:
My plan how to fix this issue:
In addition it would come handy to add a --dry-run handle to the command
lncli wallet psbt fund --dry-run
, just to try some combination without locking the inputs?
Thanks in advance for your thoughts.
I briefly looked at the code and I am not sure if the current implementation is optimal, aside from this issue. The call fetchInputs(amount)
may make things more complicated than necessary, because it already needs an amount including fee. Fee is independent on the selected inputs, which makes it a circular problem.
Perhaps you can take inspiration from tx generation in LND: https://github.com/lightningnetwork/lnd/blob/master/sweep/tx_input_set.go
The approach here is different. It just adds inputs one by one and with each input added, it evaluates the need for a change output and determines the fee. More of a one way flow.
Restarting my work on it!
Releasing the first attempt on friday!
@ziggie1984 what will your fix include? Some changes to coin selection? I'm not sure the problem still persists with the merge of https://github.com/lightningnetwork/lnd/pull/7348 (which should cause the coin selection to properly estimate the fees to omit a change output in the first place), if I understand things correctly.
Hmm so I tested with latest version, and I can still not create a transaction which pays exactly 1 sat/vbyte because the change is always included in the calculation and I will have to pay for the change although its not gonna be created.
For the p2tr output I will have to add additional 43 sats for the change, so thats the thing I am going to fix.
Example on signet:
{
"utxos": [
{
"address_type": 4,
"address": "tb1pgtmc0hspuldjcptkzkswghmg30m2rfw6q5xrms0lfzqx956h7mtq57aahf",
"amount_sat": 19690,
"pk_script": "512042f787de01e7db2c057615a0e45f688bf6a1a5da050c3dc1ff488062d357f6d6",
"outpoint": "1a2417f51a9b21e27e073d899058f3c3e3275723968143f11d53632ba2de7230:1",
"confirmations": 4174
}
]
}
Now I wanna create a Tx which pays everything except 110 sats for the tx when using 1 sat/vbyte
❯ lncli --network signet wallet psbt fund --sat_per_vbyte 1 --outputs='{"tb1pp9840k0frcun9t4eff96sfuwn3e52xdumfdmejylqw8tgpqz6p6smcglvn":19580}'
[lncli] rpc error: code = Unknown desc = wallet couldn't fund PSBT: error creating funding TX: insufficient funds available to construct transaction
10 sats more does also not work because its an issue of the code which always include the change
❯ lncli --network signet wallet psbt fund --sat_per_vbyte 1 --outputs='{"tb1pp9840k0frcun9t4eff96sfuwn3e52xdumfdmejylqw8tgpqz6p6smcglvn":19570}'
[lncli] rpc error: code = Unknown desc = wallet couldn't fund PSBT: error creating funding TX: insufficient funds available to construct transaction
Adding the additional 43 sats for the changeout it works and the tx is created though thats more then we wanna pay
❯ lncli --network signet wallet psbt fund --sat_per_vbyte 1 --outputs='{"tb1pp9840k0frcun9t4eff96sfuwn3e52xdumfdmejylqw8tgpqz6p6smcglvn":19537}'
{
"psbt": "cHNidP8BAF4CAAAAATBy3qIrY1Md8UOBliNXJ+PD81iQiT0HfuIhmxr1FyQaAQAAAAD/////AVFMAAAAAAAAIlEgCU9X2ekeOTKuuUpLqCeOnHNFGbzaW7zInwOOtAQC0HUAAAAAAAEBK+pMAAAAAAAAIlEgQveH3gHn2ywFdhWg5F9oi/ahpdoFDD3B/0iAYtNX9tYiBgMOQsOeYoP6NaeFUPvUirD5NaTIQV3zySUEaXMoOfWUaxgAAAAAVgAAgAAAAIAAAACAAQAAAAIAAAAhFg5Cw55ig/o1p4VQ+9SKsPk1pMhBXfPJJQRpcyg59ZRrGQAAAAAAVgAAgAAAAIAAAACAAQAAAAIAAAAAAA==",
"change_output_index": -1,
"locks": [
{
"id": "ede19a92ed321a4705f8a1cccc1d4f6182545d4bb4fae08bd5937831b7e38f98",
"outpoint": "1a2417f51a9b21e27e073d899058f3c3e3275723968143f11d53632ba2de7230:1",
"expiration": 1675876936,
"pk_script": "512042f787de01e7db2c057615a0e45f688bf6a1a5da050c3dc1ff488062d357f6d6",
"value": 19690
}
]
}
here the tx : https://mempool.space/signet/tx/9c7ff51a29461e29e7fe883230e6d9310c638eff9dfbe2f3c865d710fec9c660
I don't think that https://github.com/lightningnetwork/lnd/pull/7348 will solve the problem.
Indeed, the problem is that in NewUnsignedTransaction we always expect a changeSource (will never be nil).
estimatedSize := txsizes.EstimateVirtualSize(
0, 0, 1, 0, outputs, changeSource.ScriptSize,
)
So the estimateFees for transaction without change output will always be overestimated by NewUnsignedTransaction and we will not be able to have an "exact amount" as in the example of @joostjager
The only thing https://github.com/lightningnetwork/lnd/pull/7348 will help is to estimate the fees that NewUnsignedTransaction
will calculate before calling psbt (because we will know which address type will be used for the change in NewUnsignedTransaction
) and then modify the tx amount accordingly (like @ziggie1984 did with his 43 sats).
Ah yes, I see, it's still taking into account the non-existent change output. The new parameter for the change output type probably only changes the 43 sats overpayment to slightly more if you set it to p2tr, since those outputs are bigger.
Background
I am trying to fund a psbt by specifying one input and one output without change expected, but it doesn't work.
Your environment
Steps to reproduce
lncli-alice wallet psbt fund --inputs='["cb521cafdd9d57357181be99a4d847b0545ddd7969cae76f5fef20141657a59a:1"]' --outputs='{"bcrt1qucshph05ztxfvfxzpv758m98lpmz6k4uryf7um":998900}' --sat_per_vbyte 10
This transaction is 110 vbytes. So at 10 sat/b, we expect a fee of 1100 sat. This is exactly the difference between input and output value, so no change is expected.
Expected behaviour
Tx is created.
Actual behaviour
[lncli] rpc error: code = Unknown desc = wallet couldn't fund PSBT: could not add change address to database: fee estimation not successful: insufficient funds available to construct transaction
Root cause
I think the problem is here: https://github.com/btcsuite/btcwallet/blob/0230b97a7b519e7ae9e5bfe7c6a6dec307b3c528/wallet/txauthor/author.go#L97
It always assumes a change output and then returns the
insufficientFundsError
a few lines later.