Skip to content

Commit 5867f71

Browse files
laanwjknst
authored andcommitted
Merge 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 bitcoin#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 (bitcoin#24148) introduces support for Miniscript in Output Descriptors, allowing for watch-only support of Miniscript Descriptors in the wallet. - The third one (bitcoin#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#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
1 parent fcfb96e commit 5867f71

File tree

12 files changed

+2416
-32
lines changed

12 files changed

+2416
-32
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ BITCOIN_CORE_H = \
345345
scheduler.h \
346346
script/descriptor.h \
347347
script/keyorigin.h \
348+
script/miniscript.h \
348349
script/sigcache.h \
349350
script/sign.h \
350351
script/signingprovider.h \
@@ -923,6 +924,7 @@ libbitcoin_common_a_SOURCES = \
923924
saltedhasher.cpp \
924925
scheduler.cpp \
925926
script/descriptor.cpp \
927+
script/miniscript.cpp \
926928
script/sign.cpp \
927929
script/signingprovider.cpp \
928930
script/standard.cpp \

src/Makefile.test.include

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ BITCOIN_TESTS =\
145145
test/mempool_tests.cpp \
146146
test/merkle_tests.cpp \
147147
test/merkleblock_tests.cpp \
148+
test/miniscript_tests.cpp \
148149
test/minisketch_tests.cpp \
149150
test/miner_tests.cpp \
150151
test/multisig_tests.cpp \
@@ -320,6 +321,7 @@ test_fuzz_fuzz_SOURCES = \
320321
test/fuzz/locale.cpp \
321322
test/fuzz/merkleblock.cpp \
322323
test/fuzz/message.cpp \
324+
test/fuzz/miniscript_decode.cpp \
323325
test/fuzz/minisketch.cpp \
324326
test/fuzz/muhash.cpp \
325327
test/fuzz/multiplication_overflow.cpp \

src/script/interpreter.cpp

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

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

src/script/interpreter.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,6 @@ class DeferringSignatureChecker : public BaseSignatureChecker
214214
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr);
215215
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = nullptr);
216216

217-
bool CheckMinimalPush(const std::vector<unsigned char>& data, opcodetype opcode);
218-
219217
int FindAndDelete(CScript& script, const CScript& b);
220218

221219
#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)