Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
751bool solved = SignStep(provider, creator, fromPubKey, result, whichType, SigVersion::BASE, sigdata);752bool P2SH = false;753CScript subscript;755if (solved && whichType == TxoutType::SCRIPTHASH)756{757// Solver returns the subscript that needs to be evaluated;758// the final scriptSig is the signatures from that759// and then the serialized subscript:760subscript = CScript(result[0].begin(), result[0].end());761sigdata.redeem_script = subscript;762solved = solved && SignStep(provider, creator, subscript, result, whichType, SigVersion::BASE, sigdata) && whichType != TxoutType::SCRIPTHASH;763P2SH = true;764}766if (solved && whichType == TxoutType::WITNESS_V0_KEYHASH)767{768CScript witnessscript;769witnessscript << OP_DUP << OP_HASH160 << ToByteVector(result[0]) << OP_EQUALVERIFY << OP_CHECKSIG;770TxoutType subType;771solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata);772sigdata.scriptWitness.stack = result;773sigdata.witness = true;774result.clear();775}776else if (solved && whichType == TxoutType::WITNESS_V0_SCRIPTHASH)777{778CScript witnessscript(result[0].begin(), result[0].end());779sigdata.witness_script = witnessscript;781TxoutType subType{TxoutType::NONSTANDARD};782solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata) && subType != TxoutType::SCRIPTHASH && subType != TxoutType::WITNESS_V0_SCRIPTHASH && subType != TxoutType::WITNESS_V0_KEYHASH;784// If we couldn't find a solution with the legacy satisfier, try satisfying the script using Miniscript.785// Note we need to check if the result stack is empty before, because it might be used even if the Script786// isn't fully solved. For instance the CHECKMULTISIG satisfaction in SignStep() pushes partial signatures787// and the extractor relies on this behaviour to combine witnesses.788if (!solved && result.empty()) {789WshSatisfier ms_satisfier{provider, sigdata, creator, witnessscript};790const auto ms = miniscript::FromScript(witnessscript, ms_satisfier);791solved = ms && ms->Satisfy(ms_satisfier, result) == miniscript::Availability::YES;792}793result.emplace_back(witnessscript.begin(), witnessscript.end());795sigdata.scriptWitness.stack = result;796sigdata.witness = true;797result.clear();798} else if (whichType == TxoutType::WITNESS_V1_TAPROOT && !P2SH) {799sigdata.witness = true;800if (solved) {801sigdata.scriptWitness.stack = std::move(result);802}803result.clear();804} else if (solved && whichType == TxoutType::WITNESS_UNKNOWN) {805sigdata.witness = true;806}808if (!sigdata.witness) sigdata.scriptWitness.stack.clear();809if (P2SH) {810result.emplace_back(subscript.begin(), subscript.end());811}812sigdata.scriptSig = PushAll(result);814// Test solution815sigdata.complete = solved && VerifyScript(sigdata.scriptSig, fromPubKey, &sigdata.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());816return sigdata.complete;817}819namespace {820class SignatureExtractorChecker final : public DeferringSignatureChecker821{822private:823SignatureData& sigdata;825public:826SignatureExtractorChecker(SignatureData& sigdata, BaseSignatureChecker& checker) : DeferringSignatureChecker(checker), sigdata(sigdata) {}828bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override829{830if (m_checker.CheckECDSASignature(scriptSig, vchPubKey, scriptCode, sigversion)) {831CPubKey pubkey(vchPubKey);832sigdata.signatures.emplace(pubkey.GetID(), SigPair(pubkey, scriptSig));833return true;834}835return false;836}837};839struct Stacks840{841std::vector<valtype> script;842std::vector<valtype> witness;844Stacks() = delete;845Stacks(const Stacks&) = delete;846explicit Stacks(const SignatureData& data) : witness(data.scriptWitness.stack) {847EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SigVersion::BASE);848}849};850}852// Extracts signatures and scripts from incomplete scriptSigs. Please do not extend this, use PSBT instead853SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout)854{855SignatureData data;856assert(tx.vin.size() > nIn);857data.scriptSig = tx.vin[nIn].scriptSig;858data.scriptWitness = tx.vin[nIn].scriptWitness;859Stacks stack(data);861// Get signatures862MutableTransactionSignatureChecker tx_checker(&tx, nIn, txout.nValue, MissingDataBehavior::FAIL);863SignatureExtractorChecker extractor_checker(data, tx_checker);864if (VerifyScript(data.scriptSig, txout.scriptPubKey, &data.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, extractor_checker)) {865data.complete = true;866return data;867}869// Get scripts870std::vector<std::vector<unsigned char>> solutions;871TxoutType script_type = Solver(txout.scriptPubKey, solutions);872SigVersion sigversion = SigVersion::BASE;873CScript next_script = txout.scriptPubKey;875if (script_type == TxoutType::SCRIPTHASH && !stack.script.empty() && !stack.script.back().empty()) {876// Get the redeemScript877CScript redeem_script(stack.script.back().begin(), stack.script.back().end());878data.redeem_script = redeem_script;879next_script = std::move(redeem_script);881// Get redeemScript type882script_type = Solver(next_script, solutions);883stack.script.pop_back();884}885if (script_type == TxoutType::WITNESS_V0_SCRIPTHASH && !stack.witness.empty() && !stack.witness.back().empty()) {886// Get the witnessScript887CScript witness_script(stack.witness.back().begin(), stack.witness.back().end());888data.witness_script = witness_script;889next_script = std::move(witness_script);891// Get witnessScript type892script_type = Solver(next_script, solutions);893stack.witness.pop_back();894stack.script = std::move(stack.witness);895stack.witness.clear();896sigversion = SigVersion::WITNESS_V0;897}898if (script_type == TxoutType::MULTISIG && !stack.script.empty()) {899// Build a map of pubkey -> signature by matching sigs to pubkeys:900assert(solutions.size() > 1);901unsigned int num_pubkeys = solutions.size()-2;902unsigned int last_success_key = 0;903for (const valtype& sig : stack.script) {904for (unsigned int i = last_success_key; i < num_pubkeys; ++i) {905const valtype& pubkey = solutions[i+1];906// We either have a signature for this pubkey, or we have found a signature and it is valid907if (data.signatures.contains(CPubKey(pubkey).GetID()) || extractor_checker.CheckECDSASignature(sig, pubkey, next_script, sigversion)) {908last_success_key = i + 1;909break;910}911}912}913}915return data;916}918void UpdateInput(CTxIn& input, const SignatureData& data)919{920input.scriptSig = data.scriptSig;921input.scriptWitness = data.scriptWitness;922}924void SignatureData::MergeSignatureData(SignatureData sigdata)925{926if (complete) return;927if (sigdata.complete) {928*this = std::move(sigdata);929return;930}931if (redeem_script.empty() && !sigdata.redeem_script.empty()) {932redeem_script = sigdata.redeem_script;933}934if (witness_script.empty() && !sigdata.witness_script.empty()) {935witness_script = sigdata.witness_script;936}937signatures.insert(std::make_move_iterator(sigdata.signatures.begin()), std::make_move_iterator(sigdata.signatures.end()));938}940namespace {941/** Dummy signature checker which accepts all signatures. */942class DummySignatureChecker final : public BaseSignatureChecker943{944public:945DummySignatureChecker() = default;946bool CheckECDSASignature(const std::vector<unsigned char>& sig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return sig.size() != 0; }947bool CheckSchnorrSignature(std::span<const unsigned char> sig, std::span<const unsigned char> pubkey, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror) const override { return sig.size() != 0; }948bool CheckLockTime(const CScriptNum& nLockTime) const override { return true; }949bool CheckSequence(const CScriptNum& nSequence) const override { return true; }950};951}953const BaseSignatureChecker& DUMMY_CHECKER = DummySignatureChecker();955namespace {956class DummySignatureCreator final : public BaseSignatureCreator {957private:958char m_r_len = 32;959char m_s_len = 32;960public:961DummySignatureCreator(char r_len, char s_len) : m_r_len(r_len), m_s_len(s_len) {}962const BaseSignatureChecker& Checker() const override { return DUMMY_CHECKER; }963bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override964{965// Create a dummy signature that is a valid DER-encoding966vchSig.assign(m_r_len + m_s_len + 7, '\000');967vchSig[0] = 0x30;968vchSig[1] = m_r_len + m_s_len + 4;969vchSig[2] = 0x02;970vchSig[3] = m_r_len;971vchSig[4] = 0x01;972vchSig[4 + m_r_len] = 0x02;973vchSig[5 + m_r_len] = m_s_len;974vchSig[6 + m_r_len] = 0x01;975vchSig[6 + m_r_len + m_s_len] = SIGHASH_ALL;976return true;977}978bool CreateSchnorrSig(const SigningProvider& provider, std::vector<unsigned char>& sig, const XOnlyPubKey& pubkey, const uint256* leaf_hash, const uint256* tweak, SigVersion sigversion) const override979{980sig.assign(64, '\000');981return true;982}983std::vector<uint8_t> CreateMuSig2Nonce(const SigningProvider& provider, const CPubKey& aggregate_pubkey, const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion, const SignatureData& sigdata) const override984{985std::vector<uint8_t> out;986out.assign(MUSIG2_PUBNONCE_SIZE, '\000');987return out;988}989bool CreateMuSig2PartialSig(const SigningProvider& provider, uint256& partial_sig, const CPubKey& aggregate_pubkey, const CPubKey& script_pubkey, const CPubKey& part_pubkey, const uint256* leaf_hash, const std::vector<std::pair<uint256, bool>>& tweaks, SigVersion sigversion, const SignatureData& sigdata) const override990{991partial_sig = uint256::ONE;992return true;993}994bool CreateMuSig2AggregateSig(const std::vector<CPubKey>& participants, std::vector<uint8_t>& sig, const CPubKey& aggregate_pubkey, const CPubKey& script_pubkey, const uint256* leaf_hash, const std::vector<std::pair<uint256, bool>>& tweaks, SigVersion sigversion, const SignatureData& sigdata) const override995{996sig.assign(64, '\000');997return true;998}999};