This causes crash on elements wallet when dealing with transactions that
have explicit values and confidential assets. This creates a somewhat
serious DoS attack as the sender can cause the reciever's wallet to
crash by partially blinding the change output. To make matters worse,
the wallet initially accepts the transaction, but fails while spending
the output.
This is likely caused by a combination of two bugs:
1) The wallet's current behaviour stores the complete transaction of interest
in CWalletTx instead of just Outpoints. Only that the spend time do we
iterate over all outputs, try to unblind them and check which are
isMine. When calling wtx.GetOutputValueOut() or similar calls, we hit this assertion.
While the current behaviour is okay, I think the correct way is move
the IsMine == ISMINE_NO at the start of the loop. We should not do be
any checks on outputs that are not ours. This is used in multiple
places at different parts of the codebase for different RPCs.
2) When dealing with partially blinded trasactions, ComputeBlindingData
correctly sets value = -1, and the cache byte to 1. When getting the
data again with GetBlindingData for explicit value and confidential
asset, we load the precomputed data with value = -1 and assert the
loaded value be the explicit value in the transaction. This is only true
for explicit value and explicit asset.
The changed assertion checks that written value should be same as the
explicit value that was written only when the amounts are valid
Conflicts were mostly obvious, except for those in CreateTransactionInternal.
(This function was moved from wallet.cpp to spend.cpp, and substantially
rewritten, between 0.21 and 22.0.) For those I manually applied the changes
from the diff, which wound up taking a slightly different form.
Also had to update the new test because the `addresses` field of the RPC
output was removed.
When the user specifies a change address manually, use the change address
to obtain blinding parameters (either extract the blinding key from the
address or don't blind the change).
The previous behavior would assume that the change address was owned by
the wallet and always generate a blinding key internally. If the user
were to pass a non-wallet-owned change address, the result would be an
output that could not be unblinded by its owner.
1204b91c2d re-enable fallbackfee by default (Andrew Poelstra)
Pull request description:
Upstream disabled the default `fallbackfee` option in 0.17, which caused us some user error reports in 0.18. Re-enable the option in 0.21.
ACKs for top commit:
stevenroose:
utACK 1204b91c2d
Tree-SHA512: 62d053405c00f5ca31ae3fb24ab8def2c9e3bd52909dfac57e65224947295a56f0b8a322ffeb0dfcdcb3103fcaf310a9554f3ed3a8490859ca82aaeae26c7fb2
How to review this PR:
* Skim the description of https://github.com/bitcoin/bitcoin/issues/20347
to see that it's roughly "when pick_new_inputs is unset but bnb_used is
set, one the next iteration of the loop an assumption may be wrong"
* See that in this case, we just add another iteration to the loop...
* ...in exactly the same way as the other place that pick_new_inputs is
turned off, I just missed this one before
* Observe that the regression test fails before the patch but passes after.
Surprisingly easy to do. Almost all of the diff resolution was mechanically
* replacing boost::variant with std::variant
* replacing Optional with std::optional
* then replacing `nullopt` with `std::nullopt`
* updating the RPC functions for the new RPCArg::Default type
* update the tests/ directory to make new (since 22) tests use arrays for
createrawtransaction outputs
* other ad-hoc changes to function parameters etc (not too many of these)
I had to "really" change the code in PrecomputePSBTData, which was introduced
in 22.0 and affected by PSET, but this function was like 8 lines long so it
was easy.
Reviewing the diff may be a bit difficult because of the mix of mechanical
changes and ad-hoc things. Probably the most straightforward thing to do
is to redo the merge, `sed -i` to fix the boost::variant and Optional stuff,
then diff the remaining conflicts against this commit.
TODO: grep for `blindpsbt` and you will see that this RPC is still referenced
in documentation and help text even though it was deleted. Need to fix this
in 0.21 in a separate PR.
92993aa5cf Change SignTransaction's input_errors to use bilingual_str (Andrew Chow)
171366e89b Use bilingual_str for address fetching functions (Andrew Chow)
9571c69b51 Add bilingual_str::clear() (Andrew Chow)
Pull request description:
In a couple of places in the wallet, errors are `std::string`. In order for these errors to be translated, change them to use `bilingual_str`.
ACKs for top commit:
hebasto:
re-ACK 92993aa5cf, only rebased since my [previous](https://github.com/bitcoin/bitcoin/pull/22337#pullrequestreview-694542729) review, verified with
klementtan:
Code review ACK 92993aa5cf
meshcollider:
Code review ACK 92993aa5cf
Tree-SHA512: 5400e419dd87db8c49b67ed0964de2d44b58010a566ca246f2f0760ed9ef6a9b6f6df7a6adcb211b315b74c727bfe8c7d07eb5690b5922fa5828ceef4c83461f
fa6fd3dd6a wallet: Properly set fInMempool in mempool notifications (MarcoFalke)
Pull request description:
A wallet method (like bumping the fee) might have set `fInMempool` to false because the transaction was removed from the mempool (See commit fa4e088cba).
Avoid setting it back to true (incorrectly) in the validation interface background thread.
Fixes#22357
ACKs for top commit:
ryanofsky:
Code review ACK fa6fd3dd6a. Only change since last review is extending workaround to `transactionRemovedFromMempool`. Since we know this workaround is imperfect and the goal of this PR is mainly to fix CI errors, I would probably be inclined to limit the workaround to as few places as possible where we have seen actual failures, instead of adding the workaround to as many places as possible, where there is some chance it might trigger new failures. But since this workaround is so straightforward and almost looks like a real fix, probably it doesn't matter.
meshcollider:
utACK fa6fd3dd6a
Tree-SHA512: d690136a577f1f532aa1fee80d3f6600ff7fc61286fbf564a53d7938d5ae52d33f0dbb0fef8b8c041a4970fb424f0b9f1ee7ce791e0ff8354e0000ecc9e22b84
This introduces Taproot wallet support. I fixed all the merge conflicts
and ensured that the tests pass, but this is still using the old sighash
(before Russell/Sanket/I redid it) so is not actually production ready.
Will be fixed when we bring Elements #1002 in.
DEBUG_LOCKORDER expects cs_wallet, cs_main, and cs_KeyStore to be
acquired in that order. However dumpwallet would take these in the order
cs_wallet, cs_KeyStore, cs_main. So when configured with
`--enable-debug`, it is possible to hit the lock order assertion when
using dumpwallet.
To fix this, cs_wallet and cs_KeyStore are no longer locked at the same
time. Instead cs_wallet will be locked first. Then the functions which
lock cs_main will be run. Lastly cs_KeyStore will be locked afterwards.
This avoids the lock order issue.
Furthermore, since GetKeyBirthTimes (only used by dumpwallet) also uses
a function that locks cs_main, and itself also locks cs_KeyStore, the
same reordering is done here.
This removes a lot of the craziness that was added during the 0.21
rebase 240f03f586 (Bitcoin PR #17290)
as well as a lot of other upstream craziness. It's a very positive
change but will probably be a bear to review.
There are two places where I (purposely) nontrivially changed the
logic beyond what the upstream PR did:
1. When setting the change output positions, I used a uniform
distribution for all change outputs and also obeyed the user's
`change_position` choice. The old code was non-uniform and
had a bug where it would offset the change position.
For non-policy assets, I do not create zero-sized change
since we would just remove them later. For the policy asset,
I do sometimes create zero-sized change since the upstream
logic expects it to exist.
2. Rather than "reblinding whenever something changes" we blind
once for size/fee estimation purposes and then again at the
end after all potential adjustments have been made. The
resulting code should be closer to upstream.
We should really redo this code though because our use of the
`BlindDetails` structure is very confusing and stateful.
3. We consider whether or not we're using CT/CA when estimating
the size of change outpust. This is because we now use branch
and bound far more often (yay!) which selects coins such that
there will be no change output. This is implemented however
by adding a change output then dumping it to fees ... meaning
that if we dramatically overestimate the size of a change out
then we'll end up dramatically dumping too many coins to fees.
There are another couple small things, which I apologize for .. this
PR took me 2 hours to get compiling and 11 hours to get working(!!)
and some things got away from me.
One fun thing is that I changed CWallet::SelectCoinsMinConf to gate
an addition on coin_selection_params.m_subtract_fee_outputs ... this
is actually an upstream bug that I'll file whenever I get around to
producing a test that triggers it. (A bit hard as I have to gin up
a scenario where branch-and-bound fails to hit this codepath.)
Also, in test/functional/wallet_bumpfee.py I had to change the feerate
required to force selection to add another input from 500 to 800. I
don't know why and I don't care to figure it out.
I hacked up rpc_fundrawtransaction.py a little bit because our `get_address`
method here depends on nobody having called `createwallet` on a particular
node ... the "correct" fix for this would be to redo the Elements changes
to this functional test for the 0.20+ createwallet changes, but because
there will be big future changes to this test (in Elements #900 (PSET))
I did the quick/hacky thing, and will defer cleanups to a separate
post-rebase PR.