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.
1251}1253bool DescriptorScriptPubKeyMan::HaveCryptedKeys() const1254{1255LOCK(cs_desc_man);1256return !m_map_crypted_keys.empty();1257}1259unsigned int DescriptorScriptPubKeyMan::GetKeyPoolSize() const1260{1261LOCK(cs_desc_man);1262return m_wallet_descriptor.GetEnd() - m_wallet_descriptor.GetNext();1263}1265int64_t DescriptorScriptPubKeyMan::GetTimeFirstKey() const1266{1267LOCK(cs_desc_man);1268return m_wallet_descriptor.creation_time;1269}1271std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(const CScript& script, bool include_private) const1272{1273LOCK(cs_desc_man);1275// Find the index of the script1276auto it = m_map_script_pub_keys.find(script);1277if (it == m_map_script_pub_keys.end()) {1278return nullptr;1279}1280int32_t index = it->second;1282return GetSigningProvider(index, include_private);1283}1285std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(const CPubKey& pubkey) const1286{1287LOCK(cs_desc_man);1289// Find index of the pubkey1290auto it = m_map_pubkeys.find(pubkey);1291if (it == m_map_pubkeys.end()) {1292return nullptr;1293}1294int32_t index = it->second;1296// Always try to get the signing provider with private keys. This function should only be called during signing anyways1297std::unique_ptr<FlatSigningProvider> out = GetSigningProvider(index, true);1298if (!out->HaveKey(pubkey.GetID())) {1299return nullptr;1300}1301return out;1302}1304std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(int32_t index, bool include_private) const1305{1306AssertLockHeld(cs_desc_man);1308std::unique_ptr<FlatSigningProvider> out_keys = std::make_unique<FlatSigningProvider>();1310// Fetch SigningProvider from cache to avoid re-deriving1311auto it = m_map_signing_providers.find(index);1312if (it != m_map_signing_providers.end()) {1313out_keys->Merge(FlatSigningProvider{it->second});1314} else {1315// Get the scripts, keys, and key origins for this script1316std::vector<CScript> scripts_temp;1317if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;1319// Cache SigningProvider so we don't need to re-derive if we need this SigningProvider again1320m_map_signing_providers[index] = *out_keys;1321}1323if (HavePrivateKeys() && include_private) {1324FlatSigningProvider master_provider;1325master_provider.keys = GetKeys();1326m_wallet_descriptor.descriptor->ExpandPrivate(index, master_provider, *out_keys);1328// Always include musig_secnonces as this descriptor may have a participant private key1329// but not a musig() descriptor1330out_keys->musig2_secnonces = &m_musig2_secnonces;1331}1333return out_keys;1334}1336std::unique_ptr<SigningProvider> DescriptorScriptPubKeyMan::GetSolvingProvider(const CScript& script) const1337{1338return GetSigningProvider(script, false);1339}1341bool DescriptorScriptPubKeyMan::CanProvide(const CScript& script, SignatureData& sigdata)1342{1343return IsMine(script);1344}1346bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const1347{1348std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>();1349for (const auto& coin_pair : coins) {1350std::unique_ptr<FlatSigningProvider> coin_keys = GetSigningProvider(coin_pair.second.out.scriptPubKey, true);1351if (!coin_keys) {1352continue;1353}1354keys->Merge(std::move(*coin_keys));1355}1357return ::SignTransaction(tx, keys.get(), coins, {.sighash_type = sighash}, input_errors);1358}1360SigningResult DescriptorScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const1361{1362std::unique_ptr<FlatSigningProvider> keys = GetSigningProvider(GetScriptForDestination(pkhash), true);1363if (!keys) {1364return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;1365}1367CKey key;1368if (!keys->GetKey(ToKeyID(pkhash), key)) {1369return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;1370}1372if (!MessageSign(key, message, str_sig)) {1373return SigningResult::SIGNING_FAILED;1374}1375return SigningResult::OK;1376}1378std::optional<PSBTError> DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbtx, const PrecomputedTransactionData& txdata, const common::PSBTFillOptions& options, int* n_signed) const1379{1380if (n_signed) {1381*n_signed = 0;1382}1383for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {1384PSBTInput& input = psbtx.inputs.at(i);1386if (PSBTInputSigned(input)) {1387continue;1388}1390// Get the scriptPubKey to know which SigningProvider to use1391CScript script;1392if (!input.witness_utxo.IsNull()) {1393script = input.witness_utxo.scriptPubKey;1394} else if (input.non_witness_utxo) {1395if (input.prev_out >= input.non_witness_utxo->vout.size()) {1396return PSBTError::MISSING_INPUTS;1397}1398script = input.non_witness_utxo->vout[input.prev_out].scriptPubKey;1399} else {1400// There's no UTXO so we can just skip this now1401continue;1402}1404std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>();1405std::unique_ptr<FlatSigningProvider> script_keys = GetSigningProvider(script, /*include_private=*/options.sign);1406if (script_keys) {1407keys->Merge(std::move(*script_keys));1408} else {1409// Maybe there are pubkeys listed that we can sign for1410std::vector<CPubKey> pubkeys;1411pubkeys.reserve(input.hd_keypaths.size() + 2);1413// ECDSA Pubkeys1414for (const auto& [pk, _] : input.hd_keypaths) {1415pubkeys.push_back(pk);1416}1418// Taproot output pubkey1419std::vector<std::vector<unsigned char>> sols;1420if (Solver(script, sols) == TxoutType::WITNESS_V1_TAPROOT) {1421sols[0].insert(sols[0].begin(), 0x02);1422pubkeys.emplace_back(sols[0]);1423sols[0][0] = 0x03;1424pubkeys.emplace_back(sols[0]);1425}1427// Taproot pubkeys1428for (const auto& pk_pair : input.m_tap_bip32_paths) {1429const XOnlyPubKey& pubkey = pk_pair.first;1430for (unsigned char prefix : {0x02, 0x03}) {1431unsigned char b[33] = {prefix};1432std::copy(pubkey.begin(), pubkey.end(), b + 1);1433CPubKey fullpubkey;1434fullpubkey.Set(b, b + 33);1435pubkeys.push_back(fullpubkey);1436}1437}1439for (const auto& pubkey : pubkeys) {1440std::unique_ptr<FlatSigningProvider> pk_keys = GetSigningProvider(pubkey);1441if (pk_keys) {1442keys->Merge(std::move(*pk_keys));1443}1444}1445}1447const auto sign_result = SignPSBTInput(HidingSigningProvider(keys.get(), /*hide_secret=*/!options.sign, /*hide_origin=*/!options.bip32_derivs), psbtx, i, &txdata, options, /*out_sigdata=*/nullptr);1448if (!sign_result.has_value() && sign_result.error() != PSBTError::INCOMPLETE) {1449return sign_result.error();1450}1452bool signed_one = PSBTInputSigned(input);1453if (n_signed && (signed_one || !options.sign)) {1454// If sign is false, we assume that we _could_ sign if we get here. This1455// will never have false negatives; it is hard to tell under what i1456// circumstances it could have false positives.1457(*n_signed)++;1458}1459}1461// Fill in the bip32 keypaths and redeemscripts for the outputs so that hardware wallets can identify change1462for (unsigned int i = 0; i < psbtx.outputs.size(); ++i) {1463std::unique_ptr<SigningProvider> keys = GetSolvingProvider(psbtx.outputs.at(i).script);1464if (!keys) {1465continue;1466}1467UpdatePSBTOutput(HidingSigningProvider(keys.get(), /*hide_secret=*/true, /*hide_origin=*/!options.bip32_derivs), psbtx, i);1468}1470return {};1471}1473std::unique_ptr<CKeyMetadata> DescriptorScriptPubKeyMan::GetMetadata(const CTxDestination& dest) const1474{1475std::unique_ptr<SigningProvider> provider = GetSigningProvider(GetScriptForDestination(dest));1476if (provider) {1477KeyOriginInfo orig;1478CKeyID key_id = GetKeyForDestination(*provider, dest);1479if (provider->GetKeyOrigin(key_id, orig)) {1480LOCK(cs_desc_man);1481std::unique_ptr<CKeyMetadata> meta = std::make_unique<CKeyMetadata>();1482meta->key_origin = orig;1483meta->has_key_origin = true;1484meta->nCreateTime = m_wallet_descriptor.creation_time;1485return meta;1486}1487}1488return nullptr;1489}1491uint256 DescriptorScriptPubKeyMan::GetID() const1492{1493return m_id;1494}1496void DescriptorScriptPubKeyMan::Load()1497{1498LOCK(cs_desc_man);1499std::set<CScript> new_spks;1500for (int32_t i = m_wallet_descriptor.GetStart(); i < m_wallet_descriptor.GetEnd(); ++i) {