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// For a large miner the value of the transactions in the best block and1002// the mempool can exceed the cost of deliberately attempting to mine two1003// blocks to orphan the current best block. By setting nLockTime such that1004// only the next block can include the transaction, we discourage this1005// practice as the height restricted and limited blocksize gives miners1006// considering fee sniping fewer options for pulling off this attack.1007//1008// A simple way to think about this is from the wallet's point of view we1009// always want the blockchain to move forward. By setting nLockTime this1010// way we're basically making the statement that we only want this1011// transaction to appear in the next block; we don't want to potentially1012// encourage reorgs by allowing transactions to appear at lower heights1013// than the next block in forks of the best chain.1014//1015// Of course, the subsidy is high enough, and transaction volume low1016// enough, that fee sniping isn't a problem yet, but by implementing a fix1017// now we ensure code won't be written that makes assumptions about1018// nLockTime that preclude a fix later.1019if (IsCurrentForAntiFeeSniping(chain, block_hash)) {1020tx.nLockTime = block_height;1022// Secondly occasionally randomly pick a nLockTime even further back, so1023// that transactions that are delayed after signing for whatever reason,1024// e.g. high-latency mix networks and some CoinJoin implementations, have1025// better privacy.1026if (rng_fast.randrange(10) == 0) {1027tx.nLockTime = std::max(0, int(tx.nLockTime) - int(rng_fast.randrange(100)));1028}1029} else {1030// If our chain is lagging behind, we can't discourage fee sniping nor help1031// the privacy of high-latency transactions. To avoid leaking a potentially1032// unique "nLockTime fingerprint", set nLockTime to a constant.1033tx.nLockTime = 0;1034}1035// Sanity check all values1036assert(tx.nLockTime < LOCKTIME_THRESHOLD); // Type must be block height1037assert(tx.nLockTime <= uint64_t(block_height));1038for (const auto& in : tx.vin) {1039// Can not be FINAL for locktime to work1040assert(in.nSequence != CTxIn::SEQUENCE_FINAL);1041// May be MAX NONFINAL to disable both BIP68 and BIP1251042if (in.nSequence == CTxIn::MAX_SEQUENCE_NONFINAL) continue;1043// May be MAX BIP125 to disable BIP68 and enable BIP1251044if (in.nSequence == MAX_BIP125_RBF_SEQUENCE) continue;1045// The wallet does not support any other sequence-use right now.1046assert(false);1047}1048}1050uint64_t GetSerializeSizeForRecipient(const CRecipient& recipient)1051{1052return ::GetSerializeSize(CTxOut(recipient.nAmount, GetScriptForDestination(recipient.dest)));1053}1055bool IsDust(const CRecipient& recipient, const CFeeRate& dustRelayFee)1056{1057return ::IsDust(CTxOut(recipient.nAmount, GetScriptForDestination(recipient.dest)), dustRelayFee);1058}1060static util::Result<CreatedTransactionResult> CreateTransactionInternal(1061CWallet& wallet,1062const std::vector<CRecipient>& vecSend,1063std::optional<unsigned int> change_pos,1064const CCoinControl& coin_control,1065bool sign) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)1066{1067AssertLockHeld(wallet.cs_wallet);1069FastRandomContext rng_fast;1070CMutableTransaction txNew; // The resulting transaction that we make1072txNew.version = coin_control.m_version;1074CoinSelectionParams coin_selection_params{rng_fast}; // Parameters for coin selection, init with dummy1075coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends;1076coin_selection_params.m_include_unsafe_inputs = coin_control.m_include_unsafe_inputs;1077coin_selection_params.m_max_tx_weight = coin_control.m_max_tx_weight.value_or(MAX_STANDARD_TX_WEIGHT);1078coin_selection_params.m_version = coin_control.m_version;1079int minimum_tx_weight = MIN_STANDARD_TX_NONWITNESS_SIZE * WITNESS_SCALE_FACTOR;1080if (coin_selection_params.m_max_tx_weight.value() < minimum_tx_weight || coin_selection_params.m_max_tx_weight.value() > MAX_STANDARD_TX_WEIGHT) {1081return util::Error{strprintf(_("Maximum transaction weight must be between %d and %d"), minimum_tx_weight, MAX_STANDARD_TX_WEIGHT)};1082}1083// Set the long term feerate estimate to the wallet's consolidate feerate1084coin_selection_params.m_long_term_feerate = wallet.m_consolidate_feerate;1085// Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 witness overhead (dummy, flag, stack size)1086coin_selection_params.tx_noinputs_size = 10 + GetSizeOfCompactSize(vecSend.size()); // bytes for output count1088CAmount recipients_sum = 0;1089const OutputType change_type = wallet.TransactionChangeType(coin_control.m_change_type ? *coin_control.m_change_type : wallet.m_default_change_type, vecSend);1090ReserveDestination reservedest(&wallet, change_type);1091unsigned int outputs_to_subtract_fee_from = 0; // The number of outputs which we are subtracting the fee from1092for (const auto& recipient : vecSend) {1093if (IsDust(recipient, wallet.chain().relayDustFee())) {1094return util::Error{_("Transaction amount too small")};1095}1097// Include the fee cost for outputs.1098coin_selection_params.tx_noinputs_size += GetSerializeSizeForRecipient(recipient);1099recipients_sum += recipient.nAmount;1101if (recipient.fSubtractFeeFromAmount) {1102outputs_to_subtract_fee_from++;1103coin_selection_params.m_subtract_fee_outputs = true;1104}1105}1107// Create change script that will be used if we need change1108CScript scriptChange;1109bilingual_str error; // possible error str1111// coin control: send change to custom address1112if (!std::get_if<CNoDestination>(&coin_control.destChange)) {1113scriptChange = GetScriptForDestination(coin_control.destChange);1114} else { // no coin control: send change to newly generated address1115// Note: We use a new key here to keep it from being obvious which side is the change.1116// The drawback is that by not reusing a previous key, the change may be lost if a1117// backup is restored, if the backup doesn't have the new private key for the change.1118// If we reused the old key, it would be possible to add code to look for and1119// rediscover unknown transactions that were written with keys of ours to recover1120// post-backup change.1122// Reserve a new key pair from key pool. If it fails, provide a dummy1123// destination in case we don't need change.1124CTxDestination dest;1125auto op_dest = reservedest.GetReservedDestination(true);1126if (!op_dest) {1127error = _("Transaction needs a change address, but we can't generate it.") + Untranslated(" ") + util::ErrorString(op_dest);1128} else {1129dest = *op_dest;1130scriptChange = GetScriptForDestination(dest);1131}1132// A valid destination implies a change script (and1133// vice-versa). An empty change script will abort later, if the1134// change keypool ran out, but change is required.1135CHECK_NONFATAL(IsValidDestination(dest) != scriptChange.empty());1136}1137CTxOut change_prototype_txout(0, scriptChange);1138coin_selection_params.change_output_size = GetSerializeSize(change_prototype_txout);1140// Get size of spending the change output1141int change_spend_size = CalculateMaximumSignedInputSize(change_prototype_txout, &wallet, /*coin_control=*/nullptr);1142// If the wallet doesn't know how to sign change output, assume p2sh-p2wpkh1143// as lower-bound to allow BnB to do its thing1144if (change_spend_size == -1) {1145coin_selection_params.change_spend_size = DUMMY_NESTED_P2WPKH_INPUT_SIZE;1146} else {1147coin_selection_params.change_spend_size = change_spend_size;1148}1150// Set discard feerate1151coin_selection_params.m_discard_feerate = GetDiscardRate(wallet);1153// Get the fee rate to use effective values in coin selection1154auto min_fee_rate{GetMinimumFeeRate(wallet, coin_control)};1155coin_selection_params.m_effective_feerate = min_fee_rate.fee_rate;1156// Do not, ever, assume that it's fine to change the fee rate if the user has explicitly1157// provided one1158if (coin_control.m_feerate && coin_selection_params.m_effective_feerate > *coin_control.m_feerate) {1159const auto feerate_format = FeeRateFormat::SAT_VB;1160auto msg{strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)."),1161coin_control.m_feerate->ToString(feerate_format),1162coin_selection_params.m_effective_feerate.ToString(feerate_format))};1163if (min_fee_rate.fee_reason == FeeReason::REQUIRED) {1164msg += strprintf(_("\nConsider modifying %s (%s) or %s (%s)."),1165"-mintxfee",1166wallet.m_min_fee.ToString(feerate_format),1167"-minrelaytxfee",1168wallet.chain().relayMinFee().ToString(feerate_format));1169}1170return util::Error{msg};1171}1172if (min_fee_rate.fee_reason == FeeReason::FALLBACK && !wallet.m_allow_fallback_fee) {1173// eventually allow a fallback fee1174return util::Error{strprintf(_("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable %s."), "-fallbackfee")};1175}1177// Calculate the cost of change1178// Cost of change is the cost of creating the change output + cost of spending the change output in the future.1179// For creating the change output now, we use the effective feerate.1180// For spending the change output in the future, we use the discard feerate for now.1181// So cost of change = (change output size * effective feerate) + (size of spending change output * discard feerate)1182coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size);1183coin_selection_params.m_cost_of_change = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size) + coin_selection_params.m_change_fee;1185coin_selection_params.m_min_change_target = GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), coin_selection_params.m_change_fee, rng_fast);1187// The smallest change amount should be:1188// 1. at least equal to dust threshold1189// 2. at least 1 sat greater than fees to spend it at m_discard_feerate1190const auto dust = GetDustThreshold(change_prototype_txout, coin_selection_params.m_discard_feerate);1191const auto change_spend_fee = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size);1192coin_selection_params.min_viable_change = std::max(change_spend_fee + 1, dust);1194// Include the fees for things that aren't inputs, excluding the change output1195const CAmount not_input_fees = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.m_subtract_fee_outputs ? 0 : coin_selection_params.tx_noinputs_size);1196CAmount selection_target = recipients_sum + not_input_fees;1198// This can only happen if feerate is 0, and requested destinations are value of 0 (e.g. OP_RETURN)1199// and no pre-selected inputs. This will result in 0-input transaction, which is consensus-invalid anyways1200if (selection_target == 0 && !coin_control.HasSelected()) {1201return util::Error{_("Transaction requires one destination of non-zero value, a non-zero feerate, or a pre-selected input")};1202}1204// Fetch manually selected coins1205CoinsResult preset_inputs;1206if (coin_control.HasSelected()) {1207auto res_fetch_inputs = FetchSelectedInputs(wallet, coin_control, coin_selection_params);1208if (!res_fetch_inputs) return util::Error{util::ErrorString(res_fetch_inputs)};1209preset_inputs = *res_fetch_inputs;1210}1212// Fetch wallet available coins if "other inputs" are1213// allowed (coins automatically selected by the wallet)1214CoinsResult available_coins;1215if (coin_control.m_allow_other_inputs) {1216available_coins = AvailableCoins(wallet, &coin_control, coin_selection_params.m_effective_feerate);1217}1219// Choose coins to use1220auto select_coins_res = SelectCoins(wallet, available_coins, preset_inputs, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);1221if (!select_coins_res) {1222// 'SelectCoins' either returns a specific error message or, if empty, means a general "Insufficient funds".1223const bilingual_str& err = util::ErrorString(select_coins_res);1224if (!err.empty()) return util::Error{err};1226// Check if we have enough balance but cannot cover the fees1227CAmount available_balance = preset_inputs.GetTotalAmount() + available_coins.GetTotalAmount();1228// Note: if SelectCoins() fails when SFFO is enabled (recipients_sum = selection_target with SFFO),1229// then recipients_sum > available_balance and we wouldn't enter into the if condition below.1230if (available_balance >= recipients_sum) {1231// If we have coins with balance, they should have effective values since we constructed them with valid feerate.1232assert(!preset_inputs.Size() || preset_inputs.GetEffectiveTotalAmount().has_value());1233assert(!available_coins.Size() || available_coins.GetEffectiveTotalAmount().has_value());1234CAmount available_effective_balance = preset_inputs.GetEffectiveTotalAmount().value_or(0) + available_coins.GetEffectiveTotalAmount().value_or(0);1235if (available_effective_balance < selection_target) {1236Assume(!coin_selection_params.m_subtract_fee_outputs);1237return util::Error{strprintf(_("The total exceeds your balance when the %s transaction fee is included."), FormatMoney(selection_target - recipients_sum))};1238}1239}1241// General failure description1242return util::Error{_("Insufficient funds")};1243}1244const SelectionResult& result = *select_coins_res;1245TRACEPOINT(coin_selection, selected_coins,1246wallet.GetName().c_str(),1247GetAlgorithmName(result.GetAlgo()).c_str(),1248result.GetTarget(),1249result.GetWaste(),1250result.GetSelectedValue());