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// given those of its subnodes.1252auto helper = [&ctx](const Node& node, std::span<InputResult> subres) -> InputResult {1253switch (node.fragment) {1254case Fragment::PK_K: {1255std::vector<unsigned char> sig;1256Availability avail = ctx.Sign(node.keys[0], sig);1257return {ZERO, InputStack(std::move(sig)).SetWithSig().SetAvailable(avail)};1258}1259case Fragment::PK_H: {1260std::vector<unsigned char> key = ctx.ToPKBytes(node.keys[0]), sig;1261Availability avail = ctx.Sign(node.keys[0], sig);1262return {ZERO + InputStack(key), (InputStack(std::move(sig)).SetWithSig() + InputStack(key)).SetAvailable(avail)};1263}1264case Fragment::MULTI_A: {1265// sats[j] represents the best stack containing j valid signatures (out of the first i keys).1266// In the loop below, these stacks are built up using a dynamic programming approach.1267std::vector<InputStack> sats = Vector(EMPTY);1268for (size_t i = 0; i < node.keys.size(); ++i) {1269// Get the signature for the i'th key in reverse order (the signature for the first key needs to1270// be at the top of the stack, contrary to CHECKMULTISIG's satisfaction).1271std::vector<unsigned char> sig;1272Availability avail = ctx.Sign(node.keys[node.keys.size() - 1 - i], sig);1273// Compute signature stack for just this key.1274auto sat = InputStack(std::move(sig)).SetWithSig().SetAvailable(avail);1275// Compute the next sats vector: next_sats[0] is a copy of sats[0] (no signatures). All further1276// next_sats[j] are equal to either the existing sats[j] + ZERO, or sats[j-1] plus a signature1277// for the current (i'th) key. The very last element needs all signatures filled.1278std::vector<InputStack> next_sats;1279next_sats.push_back(sats[0] + ZERO);1280for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + ZERO) | (std::move(sats[j - 1]) + sat));1281next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(sat));1282// Switch over.1283sats = std::move(next_sats);1284}1285// The dissatisfaction consists of as many empty vectors as there are keys, which is the same as1286// satisfying 0 keys.1287auto& nsat{sats[0]};1288CHECK_NONFATAL(node.k != 0);1289assert(node.k < sats.size());1290return {std::move(nsat), std::move(sats[node.k])};1291}1292case Fragment::MULTI: {1293// sats[j] represents the best stack containing j valid signatures (out of the first i keys).1294// In the loop below, these stacks are built up using a dynamic programming approach.1295// sats[0] starts off being {0}, due to the CHECKMULTISIG bug that pops off one element too many.1296std::vector<InputStack> sats = Vector(ZERO);1297for (size_t i = 0; i < node.keys.size(); ++i) {1298std::vector<unsigned char> sig;1299Availability avail = ctx.Sign(node.keys[i], sig);1300// Compute signature stack for just the i'th key.1301auto sat = InputStack(std::move(sig)).SetWithSig().SetAvailable(avail);1302// Compute the next sats vector: next_sats[0] is a copy of sats[0] (no signatures). All further1303// next_sats[j] are equal to either the existing sats[j], or sats[j-1] plus a signature for the1304// current (i'th) key. The very last element needs all signatures filled.1305std::vector<InputStack> next_sats;1306next_sats.push_back(sats[0]);1307for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back(sats[j] | (std::move(sats[j - 1]) + sat));1308next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(sat));1309// Switch over.1310sats = std::move(next_sats);1311}1312// The dissatisfaction consists of k+1 stack elements all equal to 0.1313InputStack nsat = ZERO;1314for (size_t i = 0; i < node.k; ++i) nsat = std::move(nsat) + ZERO;1315assert(node.k < sats.size());1316return {std::move(nsat), std::move(sats[node.k])};1317}1318case Fragment::THRESH: {1319// sats[k] represents the best stack that satisfies k out of the *last* i subexpressions.1320// In the loop below, these stacks are built up using a dynamic programming approach.1321// sats[0] starts off empty.1322std::vector<InputStack> sats = Vector(EMPTY);1323for (size_t i = 0; i < subres.size(); ++i) {1324// Introduce an alias for the i'th last satisfaction/dissatisfaction.1325auto& res = subres[subres.size() - i - 1];1326// Compute the next sats vector: next_sats[0] is sats[0] plus res.nsat (thus containing all dissatisfactions1327// so far. next_sats[j] is either sats[j] + res.nsat (reusing j earlier satisfactions) or sats[j-1] + res.sat1328// (reusing j-1 earlier satisfactions plus a new one). The very last next_sats[j] is all satisfactions.1329std::vector<InputStack> next_sats;1330next_sats.push_back(sats[0] + res.nsat);1331for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + res.nsat) | (std::move(sats[j - 1]) + res.sat));1332next_sats.push_back(std::move(sats[sats.size() - 1]) + std::move(res.sat));1333// Switch over.1334sats = std::move(next_sats);1335}1336// At this point, sats[k].sat is the best satisfaction for the overall thresh() node. The best dissatisfaction1337// is computed by gathering all sats[i].nsat for i != k.1338InputStack nsat = INVALID;1339for (size_t i = 0; i < sats.size(); ++i) {1340// i==k is the satisfaction; i==0 is the canonical dissatisfaction;1341// the rest are non-canonical (a no-signature dissatisfaction - the i=01342// form - is always available) and malleable (due to overcompleteness).1343// Marking the solutions malleable here is not strictly necessary, as they1344// should already never be picked in non-malleable solutions due to the1345// availability of the i=0 form.1346if (i != 0 && i != node.k) sats[i].SetMalleable().SetNonCanon();1347// Include all dissatisfactions (even these non-canonical ones) in nsat.1348if (i != node.k) nsat = std::move(nsat) | std::move(sats[i]);1349}1350assert(node.k < sats.size());1351return {std::move(nsat), std::move(sats[node.k])};1352}1353case Fragment::OLDER: {1354return {INVALID, ctx.CheckOlder(node.k) ? EMPTY : INVALID};1355}1356case Fragment::AFTER: {1357return {INVALID, ctx.CheckAfter(node.k) ? EMPTY : INVALID};1358}1359case Fragment::SHA256: {1360std::vector<unsigned char> preimage;1361Availability avail = ctx.SatSHA256(node.data, preimage);1362return {ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};1363}1364case Fragment::RIPEMD160: {1365std::vector<unsigned char> preimage;1366Availability avail = ctx.SatRIPEMD160(node.data, preimage);1367return {ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};1368}1369case Fragment::HASH256: {1370std::vector<unsigned char> preimage;1371Availability avail = ctx.SatHASH256(node.data, preimage);1372return {ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};1373}1374case Fragment::HASH160: {1375std::vector<unsigned char> preimage;1376Availability avail = ctx.SatHASH160(node.data, preimage);1377return {ZERO32, InputStack(std::move(preimage)).SetAvailable(avail)};1378}1379case Fragment::AND_V: {1380auto& x = subres[0], &y = subres[1];1381// As the dissatisfaction here only consist of a single option, it doesn't1382// actually need to be listed (it's not required for reasoning about malleability of1383// other options), and is never required (no valid miniscript relies on the ability1384// to satisfy the type V left subexpression). It's still listed here for1385// completeness, as a hypothetical (not currently implemented) satisfier that doesn't1386// care about malleability might in some cases prefer it still.1387return {(y.nsat + x.sat).SetNonCanon(), y.sat + x.sat};1388}1389case Fragment::AND_B: {1390auto& x = subres[0], &y = subres[1];1391// Note that it is not strictly necessary to mark the 2nd and 3rd dissatisfaction here1392// as malleable. While they are definitely malleable, they are also non-canonical due1393// to the guaranteed existence of a no-signature other dissatisfaction (the 1st)1394// option. Because of that, the 2nd and 3rd option will never be chosen, even if they1395// weren't marked as malleable.1396return {(y.nsat + x.nsat) | (y.sat + x.nsat).SetMalleable().SetNonCanon() | (y.nsat + x.sat).SetMalleable().SetNonCanon(), y.sat + x.sat};1397}1398case Fragment::OR_B: {1399auto& x = subres[0], &z = subres[1];1400// The (sat(Z) sat(X)) solution is overcomplete (attacker can change either into dsat).1401return {z.nsat + x.nsat, (z.nsat + x.sat) | (z.sat + x.nsat) | (z.sat + x.sat).SetMalleable().SetNonCanon()};1402}1403case Fragment::OR_C: {1404auto& x = subres[0], &z = subres[1];1405return {INVALID, std::move(x.sat) | (z.sat + x.nsat)};1406}1407case Fragment::OR_D: {1408auto& x = subres[0], &z = subres[1];1409return {z.nsat + x.nsat, std::move(x.sat) | (z.sat + x.nsat)};1410}1411case Fragment::OR_I: {1412auto& x = subres[0], &z = subres[1];1413return {(x.nsat + ONE) | (z.nsat + ZERO), (x.sat + ONE) | (z.sat + ZERO)};1414}1415case Fragment::ANDOR: {1416auto& x = subres[0], &y = subres[1], &z = subres[2];1417return {(y.nsat + x.sat).SetNonCanon() | (z.nsat + x.nsat), (y.sat + x.sat) | (z.sat + x.nsat)};1418}1419case Fragment::WRAP_A:1420case Fragment::WRAP_S:1421case Fragment::WRAP_C:1422case Fragment::WRAP_N:1423return std::move(subres[0]);1424case Fragment::WRAP_D: {1425auto &x = subres[0];1426return {ZERO, x.sat + ONE};1427}1428case Fragment::WRAP_J: {1429auto &x = subres[0];1430// If a dissatisfaction with a nonzero top stack element exists, an alternative dissatisfaction exists.1431// As the dissatisfaction logic currently doesn't keep track of this nonzeroness property, and thus even1432// if a dissatisfaction with a top zero element is found, we don't know whether another one with a1433// nonzero top stack element exists. Make the conservative assumption that whenever the subexpression is weakly1434// dissatisfiable, this alternative dissatisfaction exists and leads to malleability.1435return {InputStack(ZERO).SetMalleable(x.nsat.available != Availability::NO && !x.nsat.has_sig), std::move(x.sat)};1436}1437case Fragment::WRAP_V: {1438auto &x = subres[0];1439return {INVALID, std::move(x.sat)};1440}1441case Fragment::JUST_0: return {EMPTY, INVALID};1442case Fragment::JUST_1: return {INVALID, EMPTY};1443}1444assert(false);1445return {INVALID, INVALID};1446};1448auto tester = [&helper](const Node& node, std::span<InputResult> subres) -> InputResult {1449auto ret = helper(node, subres);1451// Do a consistency check between the satisfaction code and the type checker1452// (the actual satisfaction code in ProduceInputHelper does not use GetType)1454// For 'z' nodes, available satisfactions/dissatisfactions must have stack size 0.1455if (node.GetType() << "z"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() == 0);1456if (node.GetType() << "z"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() == 0);1458// For 'o' nodes, available satisfactions/dissatisfactions must have stack size 1.1459if (node.GetType() << "o"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() == 1);1460if (node.GetType() << "o"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() == 1);1462// For 'n' nodes, available satisfactions/dissatisfactions must have stack size 1 or larger. For satisfactions,1463// the top element cannot be 0.1464if (node.GetType() << "n"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.stack.size() >= 1);1465if (node.GetType() << "n"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.stack.size() >= 1);1466if (node.GetType() << "n"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(!ret.sat.stack.back().empty());1468// For 'd' nodes, a dissatisfaction must exist, and they must not need a signature. If it is non-malleable,1469// it must be canonical.1470if (node.GetType() << "d"_mst) CHECK_NONFATAL(ret.nsat.available != Availability::NO);1471if (node.GetType() << "d"_mst) CHECK_NONFATAL(!ret.nsat.has_sig);1472if (node.GetType() << "d"_mst && !ret.nsat.malleable) CHECK_NONFATAL(!ret.nsat.non_canon);1474// For 'f'/'s' nodes, dissatisfactions/satisfactions must have a signature.1475if (node.GetType() << "f"_mst && ret.nsat.available != Availability::NO) CHECK_NONFATAL(ret.nsat.has_sig);1476if (node.GetType() << "s"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(ret.sat.has_sig);1478// For non-malleable 'e' nodes, a non-malleable dissatisfaction must exist.1479if (node.GetType() << "me"_mst) CHECK_NONFATAL(ret.nsat.available != Availability::NO);1480if (node.GetType() << "me"_mst) CHECK_NONFATAL(!ret.nsat.malleable);1482// For 'm' nodes, if a satisfaction exists, it must be non-malleable.1483if (node.GetType() << "m"_mst && ret.sat.available != Availability::NO) CHECK_NONFATAL(!ret.sat.malleable);1485// If a non-malleable satisfaction exists, it must be canonical.1486if (ret.sat.available != Availability::NO && !ret.sat.malleable) CHECK_NONFATAL(!ret.sat.non_canon);1488return ret;1489};1491return TreeEval<InputResult>(tester);1492}1494public:1495/** Update duplicate key information in this Node.1496*1497* This uses a custom key comparator provided by the context in order to still detect duplicates1498* for more complicated types.1499*/1500template<typename Ctx> void DuplicateKeyCheck(const Ctx& ctx) const
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.