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.
1001}1003private:1004internal::Ops CalcOps() const {1005switch (fragment) {1006case Fragment::JUST_1: return {0, 0, {}};1007case Fragment::JUST_0: return {0, {}, 0};1008case Fragment::PK_K: return {0, 0, 0};1009case Fragment::PK_H: return {3, 0, 0};1010case Fragment::OLDER:1011case Fragment::AFTER: return {1, 0, {}};1012case Fragment::SHA256:1013case Fragment::RIPEMD160:1014case Fragment::HASH256:1015case Fragment::HASH160: return {4, 0, {}};1016case Fragment::AND_V: return {subs[0].ops.count + subs[1].ops.count, subs[0].ops.sat + subs[1].ops.sat, {}};1017case Fragment::AND_B: {1018const auto count{1 + subs[0].ops.count + subs[1].ops.count};1019const auto sat{subs[0].ops.sat + subs[1].ops.sat};1020const auto dsat{subs[0].ops.dsat + subs[1].ops.dsat};1021return {count, sat, dsat};1022}1023case Fragment::OR_B: {1024const auto count{1 + subs[0].ops.count + subs[1].ops.count};1025const auto sat{(subs[0].ops.sat + subs[1].ops.dsat) | (subs[1].ops.sat + subs[0].ops.dsat)};1026const auto dsat{subs[0].ops.dsat + subs[1].ops.dsat};1027return {count, sat, dsat};1028}1029case Fragment::OR_D: {1030const auto count{3 + subs[0].ops.count + subs[1].ops.count};1031const auto sat{subs[0].ops.sat | (subs[1].ops.sat + subs[0].ops.dsat)};1032const auto dsat{subs[0].ops.dsat + subs[1].ops.dsat};1033return {count, sat, dsat};1034}1035case Fragment::OR_C: {1036const auto count{2 + subs[0].ops.count + subs[1].ops.count};1037const auto sat{subs[0].ops.sat | (subs[1].ops.sat + subs[0].ops.dsat)};1038return {count, sat, {}};1039}1040case Fragment::OR_I: {1041const auto count{3 + subs[0].ops.count + subs[1].ops.count};1042const auto sat{subs[0].ops.sat | subs[1].ops.sat};1043const auto dsat{subs[0].ops.dsat | subs[1].ops.dsat};1044return {count, sat, dsat};1045}1046case Fragment::ANDOR: {1047const auto count{3 + subs[0].ops.count + subs[1].ops.count + subs[2].ops.count};1048const auto sat{(subs[1].ops.sat + subs[0].ops.sat) | (subs[0].ops.dsat + subs[2].ops.sat)};1049const auto dsat{subs[0].ops.dsat + subs[2].ops.dsat};1050return {count, sat, dsat};1051}1052case Fragment::MULTI: return {1, (uint32_t)keys.size(), (uint32_t)keys.size()};1053case Fragment::MULTI_A: return {(uint32_t)keys.size() + 1, 0, 0};1054case Fragment::WRAP_S:1055case Fragment::WRAP_C:1056case Fragment::WRAP_N: return {1 + subs[0].ops.count, subs[0].ops.sat, subs[0].ops.dsat};1057case Fragment::WRAP_A: return {2 + subs[0].ops.count, subs[0].ops.sat, subs[0].ops.dsat};1058case Fragment::WRAP_D: return {3 + subs[0].ops.count, subs[0].ops.sat, 0};1059case Fragment::WRAP_J: return {4 + subs[0].ops.count, subs[0].ops.sat, 0};1060case Fragment::WRAP_V: return {subs[0].ops.count + (subs[0].GetType() << "x"_mst), subs[0].ops.sat, {}};1061case Fragment::THRESH: {1062uint32_t count = 0;1063auto sats = Vector(internal::MaxInt<uint32_t>(0));1064for (const auto& sub : subs) {1065count += sub.ops.count + 1;1066auto next_sats = Vector(sats[0] + sub.ops.dsat);1067for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + sub.ops.dsat) | (sats[j - 1] + sub.ops.sat));1068next_sats.push_back(sats[sats.size() - 1] + sub.ops.sat);1069sats = std::move(next_sats);1070}1071assert(k < sats.size());1072return {count, sats[k], sats[0]};1073}1074}1075assert(false);1076}1078internal::StackSize CalcStackSize() const {1079using namespace internal;1080switch (fragment) {1081case Fragment::JUST_0: return {{}, SatInfo::Push()};1082case Fragment::JUST_1: return {SatInfo::Push(), {}};1083case Fragment::OLDER:1084case Fragment::AFTER: return {SatInfo::Push() + SatInfo::Nop(), {}};1085case Fragment::PK_K: return {SatInfo::Push()};1086case Fragment::PK_H: return {SatInfo::OP_DUP() + SatInfo::Hash() + SatInfo::Push() + SatInfo::OP_EQUALVERIFY()};1087case Fragment::SHA256:1088case Fragment::RIPEMD160:1089case Fragment::HASH256:1090case Fragment::HASH160: return {1091SatInfo::OP_SIZE() + SatInfo::Push() + SatInfo::OP_EQUALVERIFY() + SatInfo::Hash() + SatInfo::Push() + SatInfo::OP_EQUAL(),1092{}1093};1094case Fragment::ANDOR: {1095const auto& x{subs[0].ss};1096const auto& y{subs[1].ss};1097const auto& z{subs[2].ss};1098return {1099(x.Sat() + SatInfo::If() + y.Sat()) | (x.Dsat() + SatInfo::If() + z.Sat()),1100x.Dsat() + SatInfo::If() + z.Dsat()1101};1102}1103case Fragment::AND_V: {1104const auto& x{subs[0].ss};1105const auto& y{subs[1].ss};1106return {x.Sat() + y.Sat(), {}};1107}1108case Fragment::AND_B: {1109const auto& x{subs[0].ss};1110const auto& y{subs[1].ss};1111return {x.Sat() + y.Sat() + SatInfo::BinaryOp(), x.Dsat() + y.Dsat() + SatInfo::BinaryOp()};1112}1113case Fragment::OR_B: {1114const auto& x{subs[0].ss};1115const auto& y{subs[1].ss};1116return {1117((x.Sat() + y.Dsat()) | (x.Dsat() + y.Sat())) + SatInfo::BinaryOp(),1118x.Dsat() + y.Dsat() + SatInfo::BinaryOp()1119};1120}1121case Fragment::OR_C: {1122const auto& x{subs[0].ss};1123const auto& y{subs[1].ss};1124return {(x.Sat() + SatInfo::If()) | (x.Dsat() + SatInfo::If() + y.Sat()), {}};1125}1126case Fragment::OR_D: {1127const auto& x{subs[0].ss};1128const auto& y{subs[1].ss};1129return {1130(x.Sat() + SatInfo::OP_IFDUP(true) + SatInfo::If()) | (x.Dsat() + SatInfo::OP_IFDUP(false) + SatInfo::If() + y.Sat()),1131x.Dsat() + SatInfo::OP_IFDUP(false) + SatInfo::If() + y.Dsat()1132};1133}1134case Fragment::OR_I: {1135const auto& x{subs[0].ss};1136const auto& y{subs[1].ss};1137return {SatInfo::If() + (x.Sat() | y.Sat()), SatInfo::If() + (x.Dsat() | y.Dsat())};1138}1139// multi(k, key1, key2, ..., key_n) starts off with k+1 stack elements (a 0, plus k1140// signatures), then reaches n+k+3 stack elements after pushing the n keys, plus k and1141// n itself, and ends with 1 stack element (success or failure). Thus, it net removes1142// k elements (from k+1 to 1), while reaching k+n+2 more than it ends with.1143case Fragment::MULTI: return {SatInfo(k, k + keys.size() + 2)};1144// multi_a(k, key1, key2, ..., key_n) starts off with n stack elements (the1145// signatures), reaches 1 more (after the first key push), and ends with 1. Thus it net1146// removes n-1 elements (from n to 1) while reaching n more than it ends with.1147case Fragment::MULTI_A: return {SatInfo(keys.size() - 1, keys.size())};1148case Fragment::WRAP_A:1149case Fragment::WRAP_N:1150case Fragment::WRAP_S: return subs[0].ss;1151case Fragment::WRAP_C: return {1152subs[0].ss.Sat() + SatInfo::OP_CHECKSIG(),1153subs[0].ss.Dsat() + SatInfo::OP_CHECKSIG()1154};1155case Fragment::WRAP_D: return {1156SatInfo::OP_DUP() + SatInfo::If() + subs[0].ss.Sat(),1157SatInfo::OP_DUP() + SatInfo::If()1158};1159case Fragment::WRAP_V: return {subs[0].ss.Sat() + SatInfo::OP_VERIFY(), {}};1160case Fragment::WRAP_J: return {1161SatInfo::OP_SIZE() + SatInfo::OP_0NOTEQUAL() + SatInfo::If() + subs[0].ss.Sat(),1162SatInfo::OP_SIZE() + SatInfo::OP_0NOTEQUAL() + SatInfo::If()1163};1164case Fragment::THRESH: {1165// sats[j] is the SatInfo corresponding to all traces reaching j satisfactions.1166auto sats = Vector(SatInfo::Empty());1167for (size_t i = 0; i < subs.size(); ++i) {1168// Loop over the subexpressions, processing them one by one. After adding1169// element i we need to add OP_ADD (if i>0).1170auto add = i ? SatInfo::BinaryOp() : SatInfo::Empty();1171// Construct a variable that will become the next sats, starting with index 0.1172auto next_sats = Vector(sats[0] + subs[i].ss.Dsat() + add);1173// Then loop to construct next_sats[1..i].1174for (size_t j = 1; j < sats.size(); ++j) {1175next_sats.push_back(((sats[j] + subs[i].ss.Dsat()) | (sats[j - 1] + subs[i].ss.Sat())) + add);1176}1177// Finally construct next_sats[i+1].1178next_sats.push_back(sats[sats.size() - 1] + subs[i].ss.Sat() + add);1179// Switch over.1180sats = std::move(next_sats);1181}1182// To satisfy thresh we need k satisfactions; to dissatisfy we need 0. In both1183// cases a push of k and an OP_EQUAL follow.1184return {1185sats[k] + SatInfo::Push() + SatInfo::OP_EQUAL(),1186sats[0] + SatInfo::Push() + SatInfo::OP_EQUAL()1187};1188}1189}1190assert(false);1191}1193internal::WitnessSize CalcWitnessSize() const {1194const uint32_t sig_size = IsTapscript(m_script_ctx) ? 1 + 65 : 1 + 72;1195const uint32_t pubkey_size = IsTapscript(m_script_ctx) ? 1 + 32 : 1 + 33;1196switch (fragment) {1197case Fragment::JUST_0: return {{}, 0};1198case Fragment::JUST_1:1199case Fragment::OLDER:1200case Fragment::AFTER: return {0, {}};1201case Fragment::PK_K: return {sig_size, 1};1202case Fragment::PK_H: return {sig_size + pubkey_size, 1 + pubkey_size};1203case Fragment::SHA256:1204case Fragment::RIPEMD160:1205case Fragment::HASH256:1206case Fragment::HASH160: return {1 + 32, {}};1207case Fragment::ANDOR: {1208const auto sat{(subs[0].ws.sat + subs[1].ws.sat) | (subs[0].ws.dsat + subs[2].ws.sat)};1209const auto dsat{subs[0].ws.dsat + subs[2].ws.dsat};1210return {sat, dsat};1211}1212case Fragment::AND_V: return {subs[0].ws.sat + subs[1].ws.sat, {}};1213case Fragment::AND_B: return {subs[0].ws.sat + subs[1].ws.sat, subs[0].ws.dsat + subs[1].ws.dsat};1214case Fragment::OR_B: {1215const auto sat{(subs[0].ws.dsat + subs[1].ws.sat) | (subs[0].ws.sat + subs[1].ws.dsat)};1216const auto dsat{subs[0].ws.dsat + subs[1].ws.dsat};1217return {sat, dsat};1218}1219case Fragment::OR_C: return {subs[0].ws.sat | (subs[0].ws.dsat + subs[1].ws.sat), {}};1220case Fragment::OR_D: return {subs[0].ws.sat | (subs[0].ws.dsat + subs[1].ws.sat), subs[0].ws.dsat + subs[1].ws.dsat};1221case Fragment::OR_I: return {(subs[0].ws.sat + 1 + 1) | (subs[1].ws.sat + 1), (subs[0].ws.dsat + 1 + 1) | (subs[1].ws.dsat + 1)};1222case Fragment::MULTI: return {k * sig_size + 1, k + 1};1223case Fragment::MULTI_A: return {k * sig_size + static_cast<uint32_t>(keys.size()) - k, static_cast<uint32_t>(keys.size())};1224case Fragment::WRAP_A:1225case Fragment::WRAP_N:1226case Fragment::WRAP_S:1227case Fragment::WRAP_C: return subs[0].ws;1228case Fragment::WRAP_D: return {1 + 1 + subs[0].ws.sat, 1};1229case Fragment::WRAP_V: return {subs[0].ws.sat, {}};1230case Fragment::WRAP_J: return {subs[0].ws.sat, 1};1231case Fragment::THRESH: {1232auto sats = Vector(internal::MaxInt<uint32_t>(0));1233for (const auto& sub : subs) {1234auto next_sats = Vector(sats[0] + sub.ws.dsat);1235for (size_t j = 1; j < sats.size(); ++j) next_sats.push_back((sats[j] + sub.ws.dsat) | (sats[j - 1] + sub.ws.sat));1236next_sats.push_back(sats[sats.size() - 1] + sub.ws.sat);1237sats = std::move(next_sats);1238}1239assert(k < sats.size());1240return {sats[k], sats[0]};1241}1242}1243assert(false);1244}1246template<typename Ctx>1247internal::InputResult ProduceInput(const Ctx& ctx) const {1248using namespace internal;1250// Internal function which is invoked for every tree node, constructing satisfaction/dissatisfactions
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.