74c77825e5 test: Unit test for inferring scripts with hybrid and uncompressed keys (Andrew Chow)
f895f97014 test: Scripts with hybrid pubkeys are migrated to watchonly (Andrew Chow)
37b9b73477 descriptors: Move InferScript's pubkey validity checks to InferPubkey (Andrew Chow)
b7485f11ab descriptors: Check result of InferPubkey (Andrew Chow)
Pull request description:
`InferDescriptor` was not always checking that the pubkey it was placing into the descriptor was an allowed pubkey. For example, given a P2WPKH script that uses an uncompressed pubkey, it would produce a `wpkh()` with the uncompressed key. Additionally, the hybrid key check was only being done for `pk()` scripts, where it should've been done for all scripts.
This PR moves the key checking into `InferPubkey`. If the key is not valid for the context, then `nullptr` is returned and the inferring will fall through to the defaults of either `raw()` or `addr()`.
This also resolves an issue with migrating legacy wallets that contain hybrid pubkeys as such watchonly scripts will become `raw()` or `addr()` and go to the watchonly wallet. Note that a legacy wallet cannot sign for hybrid pubkeys. A test has been added for the migration case.
Also added unit tests for `InferDescriptor` itself as the edge cases with that function are not covered by the descriptor roundtrip test.
ACKs for top commit:
furszy:
ACK 74c77825
Sjors:
utACK 74c77825e5
Tree-SHA512: ed5f63e42a2e46120245a6b0288b90d2a6912860814c6c08fe393332add1cb364dc5eca72f16980352143570aef0c07bf1a91acd294099463bd028b6ce2fe40c
ed52e71176 Periodically check disk space to avoid corruption (Aurèle Oulès)
7fe537f7a4 Implement CCoinsViewErrorCatcher::HaveCoin (Aurèle Oulès)
Pull request description:
Attempt to fix #26112.
As suggested by sipa in https://github.com/bitcoin/bitcoin/issues/26112#issuecomment-1249683401:
> CCoinsViewErrorCatcher, the wrapper class used around CCoinsViewDB that's supposed to detect these problems and forcefully exit the application, has an override for GetCoins. But in CheckTxInputs, HaveInputs is first invoked, which on its turn calls HaveCoin. HaveCoin is implemented in CCoinsViewDB, but not in CCoinsViewErrorCatcher, and thus the disk read exception escapes.
> A solution may be to just add an override for HaveCoin in CCoinsViewErrorCatcher.
I implemented `CCoinsViewErrorCatcher::HaveCoin` and also added a periodic disk space check that shutdowns the node if there is not enough space left on disk, the minimum here is 50MB.
For reviewers, it's possible to saturate disk space to test the PR by creating large files with `fallocate -l 50G test.bin`
ACKs for top commit:
achow101:
ACK ed52e71176
w0xlt:
Code Review ACK ed52e71176
sipa:
utACK ed52e71176
Tree-SHA512: 456aa7b996023df42b4fbb5158ee429d9abf7374b7b1ec129b21aea1188ad19be8da4ae8e0edd90b85b7a3042b8e44e17d3742e33808a4234d5ddbe9bcef1b78
5f50406554 Adjust Gradle properties (Hennadii Stepanov)
Pull request description:
On the master branch @ d2b8c5e123, building the `apk` target fails:
```
$ make -C src/qt apk
...
> Task :compileDebugJavaWithJavac FAILED
/home/hebasto/git/gui/src/qt/android/src/org/qtproject/qt5/android/QtActivityDelegate.java:690: error: cannot find symbol
Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
^
symbol: variable R
location: class VERSION_CODES
/home/hebasto/git/gui/src/qt/android/src/org/qtproject/qt5/android/QtActivityDelegate.java:692: error: cannot find symbol
: m_activity.getDisplay();
^
symbol: method getDisplay()
location: variable m_activity of type Activity
/home/hebasto/git/gui/src/qt/android/src/org/qtproject/qt5/android/QtActivityDelegate.java:833: error: cannot find symbol
float refreshRate = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
^
symbol: variable R
location: class VERSION_CODES
/home/hebasto/git/gui/src/qt/android/src/org/qtproject/qt5/android/QtActivityDelegate.java:835: error: cannot find symbol
: m_activity.getDisplay().getRefreshRate();
^
symbol: method getDisplay()
location: variable m_activity of type Activity
/home/hebasto/git/gui/src/qt/android/src/org/qtproject/qt5/android/QtLayout.java:95: error: cannot find symbol
Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
^
symbol: variable R
location: class VERSION_CODES
/home/hebasto/git/gui/src/qt/android/src/org/qtproject/qt5/android/QtLayout.java:97: error: cannot find symbol
: ((Activity)getContext()).getDisplay();
^
symbol: method getDisplay()
location: class Activity
/home/hebasto/git/gui/src/qt/android/src/org/qtproject/qt5/android/ExtractStyle.java:418: error: cannot find symbol
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
^
symbol: variable Q
location: class VERSION_CODES
/home/hebasto/git/gui/src/qt/android/src/org/qtproject/qt5/android/ExtractStyle.java:421: error: cannot find symbol
numStates = stateList.getStateCount();
^
symbol: method getStateCount()
location: variable stateList of type StateListDrawable
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
8 errors
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.6.1/userguide/command_line_interface.html#sec:command_line_warnings
BUILD FAILED in 827ms
...
```
Fixing it by updating the Gradle tool's properties.
ACKs for top commit:
fanquake:
ACK 5f50406554 - seems fine.
Tree-SHA512: 52e59fe1c69841370ce2eb670f3618182bf2843582074af4895b8ecb6e5f70dc3fe4eecbffa212efaa534b423ced5b75020f6f09917b52f452121c1e55fbcaac
We make the Satisfier a base in which to store the common methods
between the Tapscript and P2WSH satisfier, and from which they both
inherit.
A field is added to SignatureData to be able to satisfy pkh() under
Tapscript context (to get the pubkey hash preimage) without wallet data.
For instance in `finalizepsbt` RPC. See also the next commits for a
functional test that exercises this.
64-hex-characters public keys are valid in Miniscript key expressions
within a Tapscript context.
Keys under a Tapscript context always serialize as 32-bytes x-only
public keys (and that's what get hashed by OP_HASH160 on the stack too).
In order to exacerbate a mistake in the stack size tracking logic,
sometimes pad the witness to make the script execute at the brink of the
stack size limit. This way if the stack size is underestimated for a
script it would immediately fail `VerifyScript`.
Under Tapscript, due to the lifting of some standardness and consensus
limits, scripts can now run into the maximum stack size during
execution. Any Miniscript that may hit the limit on any of its spending
paths must be marked as unsafe.
Co-Authored-By: Pieter Wuille <pieter@wuille.net>
We introduce another global that dictates the script context under which
to operate when running the target.
For miniscript_script, just consume another byte to set the context.
This should only affect existing seeds to the extent they contain a
CHECKMULTISIG. However it would not invalidate them entirely as they may
contain a NUMEQUAL or a CHECKSIGADD, and this still exercises a bit of
the parser.
For miniscript_string, reduce the string size by one byte and use the
last byte to determine the context. This is the change that i think
would invalidate the lowest number of existing seeds.
For miniscript_stable, we don't want to invalidate any seed. Instead of
creating a new miniscript_stable_tapscript, simply run the target once
for P2WSH and once for Tapscript (with the same seed).
For miniscript_smart, consume one byte before generating a pseudo-random
node to set the context. We have less regard for seed stability for this
target anyways.
Adapt the test data and the parsing context to support x-only keys.
Adapt the Test() helper to test existing cases under both Tapscript and
P2WSH context, asserting what needs to be valid or not in each.
Finally, add more cases that exercise the logic that was added in the
previous commits (multi_a, different resource checks and keys
serialization under Tapscript, different properties for 'd:' fragment,
..).
Under Tapscript, there is:
- No limit on the number of OPs
- No limit on the script size, it's implicitly limited by the maximum
(standard) transaction size.
- No standardness limit on the number of stack items, it's limited by
the consensus MAX_STACK_SIZE. This requires tracking the maximum stack
size at all times during script execution, which will be tackled in
its own commit.
In order to avoid any Miniscript that would not be spendable by a
standard transaction because of the size of the witness, we limit the
script size under Tapscript to the maximum standard transaction size
minus the maximum possible witness and Taproot control block sizes. Note
this is a conservative limit but it still allows for scripts more than a
hundred times larger than under P2WSH.
In Tapscript MINIMALIF is a consensus rule, so we can rely on the fact
that the `DUP IF [X] ENDIF` will always put an exact 1 on the stack upon
satisfaction.
It is the equivalent of multi() but for Tapscript, using CHECKSIGADD
instead of CHECKMULTISIG.
It shares the same properties as multi() but for 'n', since a threshold
multi_a() may have an empty vector as the top element of its
satisfaction. It could also have the 'o' property when it only has a
single key, but in this case a 'pk()' is always preferable anyways.
We are going to introduce Tapscript support in Miniscript, for which
some of Miniscript rules and properties change (new or modified
fragments, different typing rules, different resources consumption, ..).
It's true that for any public key there'll be a signature check in a
valid Miniscript. The code would previously, when computing the size of
a satisfaction, account for the signature when it sees a public key
push. Instead, account for it when it is required (ie when encountering
the `c:` wrapper). This has two benefits:
- Allows to accurately compute the net effect of a fragment on the stack
size. This is necessary to track the size of the stack during the
execution of a Script.
- It also just makes more sense, making the code more accessible to
future contributors.
b442580ed2 gui: remove legacy wallet creation (furszy)
Pull request description:
Fixes #763
Preventing users from creating a legacy wallet prior to its deprecation in the upcoming releases.
Note:
This is still available using the `createwallet` RPC command.
Future Note:
Would be nice to re-write this modal as a wizard. And improve the design.
<details><summary> Pre-Changes Screenshot </summary>
<img width="611" alt="Screenshot 2023-10-06 at 11 30 14" src="https://github.com/bitcoin-core/gui/assets/5377650/ca10c97d-46e8-4aed-82da-068f2afbe25c">
</details>
<details><summary> Post-Changes Screenshot </summary>
<img width="729" alt="Screenshot 2023-10-06 at 11 32 58" src="https://github.com/bitcoin-core/gui/assets/5377650/f6bdcb57-646a-43d8-86a7-476e3cca683f">
</details>
ACKs for top commit:
achow101:
ACK b442580ed2
hebasto:
re-ACK b442580ed2
pablomartin4btc:
tACK b442580ed2
Tree-SHA512: f5d26ffbb0962648b9edf273b325e89425a318e136df26a26acb21b88730fd7d6499c68a705680539dc1b40862fbf413a1e0c8572436a0cfc665e2d08a3cf97d