Skip to content

Commit d492dc1

Browse files
committed
Merge bitcoin/bitcoin#24147: Miniscript integration
2da94a4 fuzz: add a fuzz target for Miniscript decoding from Script (Antoine Poinsot) f836999 Miniscript: ops limit and stack size computation (Pieter Wuille) 2e55e88 Miniscript: conversion from script (Pieter Wuille) 1ddaa66 Miniscript: type system, script creation, text notation, tests (Pieter Wuille) 4fe2936 script: expose getter for CScriptNum, add a BuildScript helper (Antoine Poinsot) f4e289f script: move CheckMinimalPush from interpreter to script.h (Antoine Poinsot) 31ec6ae script: make IsPushdataOp non-static (Antoine Poinsot) Pull request description: Miniscript is a language for writing (a subset of) Bitcoin Scripts in a structured way. Miniscript permits: - To safely extend the Output Descriptor language to many more scripting features thanks to the typing system (composition). - Statical analysis of spending conditions, maximum spending cost of each branch, security properties, third-party malleability. - General satisfaction of any correctly typed ("valid" [0]) Miniscript. The satisfaction itself is also analyzable. - To extend the possibilities of external signers, because of all of the above and since it carries enough metadata. Miniscript guarantees: - That for any statically-analyzed as "safe" [0] Script, a witness can be constructed in the bounds of the consensus and standardness rules (standardness complete). - That unless the conditions of the Miniscript are met, no witness can be created for the Script (consensus sound). - Third-party malleability protection for the satisfaction of a sane Miniscript, which is too complex to summarize here. For more details around Miniscript (including the specifications), please refer to the [website](https://bitcoin.sipa.be/miniscript/). Miniscript was designed by Pieter Wuille, Andrew Poelstra and Sanket Kanjalkar. This PR is an updated and rebased version of #16800. See [the commit history of the Miniscript repository](https://github.com/sipa/miniscript/commits/master) for details about the changes made since September 2019 (TL;DR: bugfixes, introduction of timelock conflicts in the type system, `pk()` and `pkh()` aliases, `thresh_m` renamed to `multi`, all recursive algorithms were made non-recursive). This PR is also the first in a series of 3: - The first one (here) integrates the backbone of Miniscript. - The second one (#24148) introduces support for Miniscript in Output Descriptors, allowing for watch-only support of Miniscript Descriptors in the wallet. - The third one (#24149) implements signing for these Miniscript Descriptors, using Miniscript's satisfaction algorithm. Note to reviewers: - Miniscript is currently defined only for P2WSH. No Taproot yet. - Miniscript is different from the policy language (a high-level logical representation of a spending policy). A policy->Miniscript compiler is not included here. - The fuzz target included here is more interestingly extended in the 3rd PR to check a script's satisfaction against `VerifyScript`. I think it could be further improved by having custom mutators as we now have for multisig (see bitcoin/bitcoin#23105). A minified corpus of Miniscript Scripts is available at bitcoin-core/qa-assets#85. [0] We call "valid" any correctly-typed Miniscript. And "safe" any sane Miniscript, ie one whose satisfaction isn't malleable, which requires a key for any spending path, etc.. ACKs for top commit: jb55: ACK 2da94a4 laanwj: Light code review ACK 2da94a4 (mostly reviewed the changes to the existing code and build system) Tree-SHA512: d3ef558436cfcc699a50ad13caf1e776f7d0addddb433ee28ef38f66ea5c3e581382d8c748ccac9b51768e4b95712ed7a6112b0e3281a6551e0f325331de9167
2 parents 0baf6ad + 2da94a4 commit d492dc1

12 files changed

+2419
-32
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ BITCOIN_CORE_H = \
221221
scheduler.h \
222222
script/descriptor.h \
223223
script/keyorigin.h \
224+
script/miniscript.h \
224225
script/sigcache.h \
225226
script/sign.h \
226227
script/signingprovider.h \
@@ -590,6 +591,7 @@ libbitcoin_common_a_SOURCES = \
590591
rpc/util.cpp \
591592
scheduler.cpp \
592593
script/descriptor.cpp \
594+
script/miniscript.cpp \
593595
script/sign.cpp \
594596
script/signingprovider.cpp \
595597
script/standard.cpp \

src/Makefile.test.include

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ BITCOIN_TESTS =\
103103
test/merkle_tests.cpp \
104104
test/merkleblock_tests.cpp \
105105
test/miner_tests.cpp \
106+
test/miniscript_tests.cpp \
106107
test/minisketch_tests.cpp \
107108
test/multisig_tests.cpp \
108109
test/net_peer_eviction_tests.cpp \
@@ -266,6 +267,7 @@ test_fuzz_fuzz_SOURCES = \
266267
test/fuzz/locale.cpp \
267268
test/fuzz/merkleblock.cpp \
268269
test/fuzz/message.cpp \
270+
test/fuzz/miniscript_decode.cpp \
269271
test/fuzz/minisketch.cpp \
270272
test/fuzz/muhash.cpp \
271273
test/fuzz/multiplication_overflow.cpp \

src/script/interpreter.cpp

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -225,31 +225,6 @@ bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags, co
225225
return true;
226226
}
227227

228-
bool CheckMinimalPush(const valtype& data, opcodetype opcode) {
229-
// Excludes OP_1NEGATE, OP_1-16 since they are by definition minimal
230-
assert(0 <= opcode && opcode <= OP_PUSHDATA4);
231-
if (data.size() == 0) {
232-
// Should have used OP_0.
233-
return opcode == OP_0;
234-
} else if (data.size() == 1 && data[0] >= 1 && data[0] <= 16) {
235-
// Should have used OP_1 .. OP_16.
236-
return false;
237-
} else if (data.size() == 1 && data[0] == 0x81) {
238-
// Should have used OP_1NEGATE.
239-
return false;
240-
} else if (data.size() <= 75) {
241-
// Must have used a direct push (opcode indicating number of bytes pushed + those bytes).
242-
return opcode == data.size();
243-
} else if (data.size() <= 255) {
244-
// Must have used OP_PUSHDATA.
245-
return opcode == OP_PUSHDATA1;
246-
} else if (data.size() <= 65535) {
247-
// Must have used OP_PUSHDATA2.
248-
return opcode == OP_PUSHDATA2;
249-
}
250-
return true;
251-
}
252-
253228
int FindAndDelete(CScript& script, const CScript& b)
254229
{
255230
int nFound = 0;

src/script/interpreter.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,6 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
344344

345345
size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags);
346346

347-
bool CheckMinimalPush(const std::vector<unsigned char>& data, opcodetype opcode);
348-
349347
int FindAndDelete(CScript& script, const CScript& b);
350348

351349
#endif // BITCOIN_SCRIPT_INTERPRETER_H

src/script/miniscript.cpp

Lines changed: 348 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)