MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / ToScript

Method ToScript

src/script/miniscript.h:798–874  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

796public:
797 template<typename Ctx>
798 CScript ToScript(const Ctx& ctx) const
799 {
800 // To construct the CScript for a Miniscript object, we use the TreeEval algorithm.
801 // The State is a boolean: whether or not the node's script expansion is followed
802 // by an OP_VERIFY (which may need to be combined with the last script opcode).
803 auto downfn = [](bool verify, const Node& node, size_t index) {
804 // For WRAP_V, the subexpression is certainly followed by OP_VERIFY.
805 if (node.fragment == Fragment::WRAP_V) return true;
806 // The subexpression of WRAP_S, and the last subexpression of AND_V
807 // inherit the followed-by-OP_VERIFY property from the parent.
808 if (node.fragment == Fragment::WRAP_S ||
809 (node.fragment == Fragment::AND_V && index == 1)) return verify;
810 return false;
811 };
812 // The upward function computes for a node, given its followed-by-OP_VERIFY status
813 // and the CScripts of its child nodes, the CScript of the node.
814 const bool is_tapscript{IsTapscript(m_script_ctx)};
815 auto upfn = [&ctx, is_tapscript](bool verify, const Node& node, std::span<CScript> subs) -> CScript {
816 switch (node.fragment) {
817 case Fragment::PK_K: return BuildScript(ctx.ToPKBytes(node.keys[0]));
818 case Fragment::PK_H: return BuildScript(OP_DUP, OP_HASH160, ctx.ToPKHBytes(node.keys[0]), OP_EQUALVERIFY);
819 case Fragment::OLDER: return BuildScript(node.k, OP_CHECKSEQUENCEVERIFY);
820 case Fragment::AFTER: return BuildScript(node.k, OP_CHECKLOCKTIMEVERIFY);
821 case Fragment::SHA256: return BuildScript(OP_SIZE, 32, OP_EQUALVERIFY, OP_SHA256, node.data, verify ? OP_EQUALVERIFY : OP_EQUAL);
822 case Fragment::RIPEMD160: return BuildScript(OP_SIZE, 32, OP_EQUALVERIFY, OP_RIPEMD160, node.data, verify ? OP_EQUALVERIFY : OP_EQUAL);
823 case Fragment::HASH256: return BuildScript(OP_SIZE, 32, OP_EQUALVERIFY, OP_HASH256, node.data, verify ? OP_EQUALVERIFY : OP_EQUAL);
824 case Fragment::HASH160: return BuildScript(OP_SIZE, 32, OP_EQUALVERIFY, OP_HASH160, node.data, verify ? OP_EQUALVERIFY : OP_EQUAL);
825 case Fragment::WRAP_A: return BuildScript(OP_TOALTSTACK, subs[0], OP_FROMALTSTACK);
826 case Fragment::WRAP_S: return BuildScript(OP_SWAP, subs[0]);
827 case Fragment::WRAP_C: return BuildScript(std::move(subs[0]), verify ? OP_CHECKSIGVERIFY : OP_CHECKSIG);
828 case Fragment::WRAP_D: return BuildScript(OP_DUP, OP_IF, subs[0], OP_ENDIF);
829 case Fragment::WRAP_V: {
830 if (node.subs[0].GetType() << "x"_mst) {
831 return BuildScript(std::move(subs[0]), OP_VERIFY);
832 } else {
833 return std::move(subs[0]);
834 }
835 }
836 case Fragment::WRAP_J: return BuildScript(OP_SIZE, OP_0NOTEQUAL, OP_IF, subs[0], OP_ENDIF);
837 case Fragment::WRAP_N: return BuildScript(std::move(subs[0]), OP_0NOTEQUAL);
838 case Fragment::JUST_1: return BuildScript(OP_1);
839 case Fragment::JUST_0: return BuildScript(OP_0);
840 case Fragment::AND_V: return BuildScript(std::move(subs[0]), subs[1]);
841 case Fragment::AND_B: return BuildScript(std::move(subs[0]), subs[1], OP_BOOLAND);
842 case Fragment::OR_B: return BuildScript(std::move(subs[0]), subs[1], OP_BOOLOR);
843 case Fragment::OR_D: return BuildScript(std::move(subs[0]), OP_IFDUP, OP_NOTIF, subs[1], OP_ENDIF);
844 case Fragment::OR_C: return BuildScript(std::move(subs[0]), OP_NOTIF, subs[1], OP_ENDIF);
845 case Fragment::OR_I: return BuildScript(OP_IF, subs[0], OP_ELSE, subs[1], OP_ENDIF);
846 case Fragment::ANDOR: return BuildScript(std::move(subs[0]), OP_NOTIF, subs[2], OP_ELSE, subs[1], OP_ENDIF);
847 case Fragment::MULTI: {
848 CHECK_NONFATAL(!is_tapscript);
849 CScript script = BuildScript(node.k);
850 for (const auto& key : node.keys) {
851 script = BuildScript(std::move(script), ctx.ToPKBytes(key));
852 }
853 return BuildScript(std::move(script), node.keys.size(), verify ? OP_CHECKMULTISIGVERIFY : OP_CHECKMULTISIG);
854 }
855 case Fragment::MULTI_A: {

Callers 5

MakeScriptsMethod · 0.80
TestSatisfyMethod · 0.80
TestMethod · 0.80
TestNodeFunction · 0.80
FUZZ_TARGETFunction · 0.80

Calls 8

IsTapscriptFunction · 0.85
BuildScriptFunction · 0.85
ToPKBytesMethod · 0.45
ToPKHBytesMethod · 0.45
GetTypeMethod · 0.45
sizeMethod · 0.45
beginMethod · 0.45
endMethod · 0.45

Tested by 4

TestSatisfyMethod · 0.64
TestMethod · 0.64
TestNodeFunction · 0.64
FUZZ_TARGETFunction · 0.64