Inside Bitcoin
Opening the selected file…
Inside Bitcoin
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.
1251{1252return std::make_unique<PKDescriptor>(m_pubkey_args.at(0)->Clone(), m_xonly);1253}1254};1256/** A parsed pkh(P) descriptor. */1257class PKHDescriptor final : public DescriptorImpl1258{1259protected:1260std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, std::span<const CScript>, FlatSigningProvider&) const override1261{1262CKeyID id = keys[0].GetID();1263return Vector(GetScriptForDestination(PKHash(id)));1264}1265public:1266PKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "pkh") {}1267std::optional<OutputType> GetOutputType() const override { return OutputType::LEGACY; }1268bool IsSingleType() const final { return true; }1270std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 1 + 20 + 1 + 1; }1272std::optional<int64_t> MaxSatSize(bool use_max_sig) const override {1273const auto sig_size = use_max_sig ? 72 : 71;1274return 1 + sig_size + 1 + m_pubkey_args[0]->GetSize();1275}1277std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const override {1278return *MaxSatSize(use_max_sig) * WITNESS_SCALE_FACTOR;1279}1281std::optional<int64_t> MaxSatisfactionElems() const override { return 2; }1283std::unique_ptr<DescriptorImpl> Clone() const override1284{1285return std::make_unique<PKHDescriptor>(m_pubkey_args.at(0)->Clone());1286}1287};1289/** A parsed wpkh(P) descriptor. */1290class WPKHDescriptor final : public DescriptorImpl1291{1292protected:1293std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, std::span<const CScript>, FlatSigningProvider&) const override1294{1295CKeyID id = keys[0].GetID();1296return Vector(GetScriptForDestination(WitnessV0KeyHash(id)));1297}1298public:1299WPKHDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "wpkh") {}1300std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32; }1301bool IsSingleType() const final { return true; }1303std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 20; }1305std::optional<int64_t> MaxSatSize(bool use_max_sig) const override {1306const auto sig_size = use_max_sig ? 72 : 71;1307return (1 + sig_size + 1 + 33);1308}1310std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const override {1311return MaxSatSize(use_max_sig);1312}1314std::optional<int64_t> MaxSatisfactionElems() const override { return 2; }1316std::unique_ptr<DescriptorImpl> Clone() const override1317{1318return std::make_unique<WPKHDescriptor>(m_pubkey_args.at(0)->Clone());1319}1320};1322/** A parsed combo(P) descriptor. */1323class ComboDescriptor final : public DescriptorImpl1324{1325protected:1326std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, std::span<const CScript>, FlatSigningProvider& out) const override1327{1328std::vector<CScript> ret;1329CKeyID id = keys[0].GetID();1330ret.emplace_back(GetScriptForRawPubKey(keys[0])); // P2PK1331ret.emplace_back(GetScriptForDestination(PKHash(id))); // P2PKH1332if (keys[0].IsCompressed()) {1333CScript p2wpkh = GetScriptForDestination(WitnessV0KeyHash(id));1334out.scripts.emplace(CScriptID(p2wpkh), p2wpkh);1335ret.emplace_back(p2wpkh);1336ret.emplace_back(GetScriptForDestination(ScriptHash(p2wpkh))); // P2SH-P2WPKH1337}1338return ret;1339}1340public:1341ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Vector(std::move(prov)), "combo") {}1342bool IsSingleType() const final { return false; }1343std::unique_ptr<DescriptorImpl> Clone() const override1344{1345return std::make_unique<ComboDescriptor>(m_pubkey_args.at(0)->Clone());1346}1347};1349/** A parsed multi(...) or sortedmulti(...) descriptor */1350class MultisigDescriptor final : public DescriptorImpl1351{1352const int m_threshold;1353const bool m_sorted;1354protected:1355std::string ToStringExtra() const override { return strprintf("%i", m_threshold); }1356std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, std::span<const CScript>, FlatSigningProvider&) const override {1357if (m_sorted) {1358std::vector<CPubKey> sorted_keys(keys);1359std::sort(sorted_keys.begin(), sorted_keys.end());1360return Vector(GetScriptForMultisig(m_threshold, sorted_keys));1361}1362return Vector(GetScriptForMultisig(m_threshold, keys));1363}1364public:1365MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), sorted ? "sortedmulti" : "multi"), m_threshold(threshold), m_sorted(sorted) {}1366bool IsSingleType() const final { return true; }1368std::optional<int64_t> ScriptSize() const override {1369const auto n_keys = m_pubkey_args.size();1370auto op = [](int64_t acc, const std::unique_ptr<PubkeyProvider>& pk) { return acc + 1 + pk->GetSize();};1371const auto pubkeys_size{std::accumulate(m_pubkey_args.begin(), m_pubkey_args.end(), int64_t{0}, op)};1372return 1 + BuildScript(n_keys).size() + BuildScript(m_threshold).size() + pubkeys_size;1373}1375std::optional<int64_t> MaxSatSize(bool use_max_sig) const override {1376const auto sig_size = use_max_sig ? 72 : 71;1377return (1 + (1 + sig_size) * m_threshold);1378}1380std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const override {1381return *MaxSatSize(use_max_sig) * WITNESS_SCALE_FACTOR;1382}1384std::optional<int64_t> MaxSatisfactionElems() const override { return 1 + m_threshold; }1386std::unique_ptr<DescriptorImpl> Clone() const override1387{1388std::vector<std::unique_ptr<PubkeyProvider>> providers;1389providers.reserve(m_pubkey_args.size());1390std::transform(m_pubkey_args.begin(), m_pubkey_args.end(), std::back_inserter(providers), [](const std::unique_ptr<PubkeyProvider>& p) { return p->Clone(); });1391return std::make_unique<MultisigDescriptor>(m_threshold, std::move(providers), m_sorted);1392}1393};1395/** A parsed (sorted)multi_a(...) descriptor. Always uses x-only pubkeys. */1396class MultiADescriptor final : public DescriptorImpl1397{1398const int m_threshold;1399const bool m_sorted;1400protected:1401std::string ToStringExtra() const override { return strprintf("%i", m_threshold); }1402std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, std::span<const CScript>, FlatSigningProvider&) const override {1403CScript ret;1404std::vector<XOnlyPubKey> xkeys;1405xkeys.reserve(keys.size());1406for (const auto& key : keys) xkeys.emplace_back(key);1407if (m_sorted) std::sort(xkeys.begin(), xkeys.end());1408ret << ToByteVector(xkeys[0]) << OP_CHECKSIG;1409for (size_t i = 1; i < keys.size(); ++i) {1410ret << ToByteVector(xkeys[i]) << OP_CHECKSIGADD;1411}1412ret << m_threshold << OP_NUMEQUAL;1413return Vector(std::move(ret));1414}1415public:1416MultiADescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), sorted ? "sortedmulti_a" : "multi_a"), m_threshold(threshold), m_sorted(sorted) {}1417bool IsSingleType() const final { return true; }1419std::optional<int64_t> ScriptSize() const override {1420const auto n_keys = m_pubkey_args.size();1421return (1 + 32 + 1) * n_keys + BuildScript(m_threshold).size() + 1;1422}1424std::optional<int64_t> MaxSatSize(bool use_max_sig) const override {1425return (1 + 65) * m_threshold + (m_pubkey_args.size() - m_threshold);1426}1428std::optional<int64_t> MaxSatisfactionElems() const override { return m_pubkey_args.size(); }1430std::unique_ptr<DescriptorImpl> Clone() const override1431{1432std::vector<std::unique_ptr<PubkeyProvider>> providers;1433providers.reserve(m_pubkey_args.size());1434for (const auto& arg : m_pubkey_args) {1435providers.push_back(arg->Clone());1436}1437return std::make_unique<MultiADescriptor>(m_threshold, std::move(providers), m_sorted);1438}1439};1441/** A parsed sh(...) descriptor. */1442class SHDescriptor final : public DescriptorImpl1443{1444protected:1445std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, std::span<const CScript> scripts, FlatSigningProvider& out) const override1446{1447auto ret = Vector(GetScriptForDestination(ScriptHash(scripts[0])));1448if (ret.size()) out.scripts.emplace(CScriptID(scripts[0]), scripts[0]);1449return ret;1450}1452bool IsSegwit() const { return m_subdescriptor_args[0]->GetOutputType() == OutputType::BECH32; }1454public:1455SHDescriptor(std::unique_ptr<DescriptorImpl> desc) : DescriptorImpl({}, std::move(desc), "sh") {}1457std::optional<OutputType> GetOutputType() const override1458{1459assert(m_subdescriptor_args.size() == 1);1460if (IsSegwit()) return OutputType::P2SH_SEGWIT;1461return OutputType::LEGACY;1462}1463bool IsSingleType() const final { return true; }1465std::optional<int64_t> ScriptSize() const override { return 1 + 1 + 20 + 1; }1467std::optional<int64_t> MaxSatisfactionWeight(bool use_max_sig) const override {1468if (const auto sat_size = m_subdescriptor_args[0]->MaxSatSize(use_max_sig)) {1469if (const auto subscript_size = m_subdescriptor_args[0]->ScriptSize()) {1470// The subscript is never witness data.1471const auto subscript_weight = (1 + *subscript_size) * WITNESS_SCALE_FACTOR;1472// The weight depends on whether the inner descriptor is satisfied using the witness stack.1473if (IsSegwit()) return subscript_weight + *sat_size;1474return subscript_weight + *sat_size * WITNESS_SCALE_FACTOR;1475}1476}1477return {};1478}1480std::optional<int64_t> MaxSatisfactionElems() const override {1481if (const auto sub_elems = m_subdescriptor_args[0]->MaxSatisfactionElems()) return 1 + *sub_elems;1482return {};1483}1485std::unique_ptr<DescriptorImpl> Clone() const override1486{1487return std::make_unique<SHDescriptor>(m_subdescriptor_args.at(0)->Clone());1488}1489};1491/** A parsed wsh(...) descriptor. */1492class WSHDescriptor final : public DescriptorImpl1493{1494protected:1495std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, std::span<const CScript> scripts, FlatSigningProvider& out) const override1496{1497auto ret = Vector(GetScriptForDestination(WitnessV0ScriptHash(scripts[0])));1498if (ret.size()) out.scripts.emplace(CScriptID(scripts[0]), scripts[0]);1499return ret;1500}