@@ -1180,12 +1180,12 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
1180
1180
}
1181
1181
1182
1182
// Create change script that will be used if we need change
1183
- CScript scriptChange ;
1183
+ CTxDestination change_dest ;
1184
1184
bilingual_str error; // possible error str
1185
1185
1186
1186
// coin control: send change to custom address
1187
1187
if (!std::get_if<CNoDestination>(&coin_control.destChange )) {
1188
- scriptChange = GetScriptForDestination ( coin_control.destChange ) ;
1188
+ change_dest = coin_control.destChange ;
1189
1189
} else { // no coin control: send change to newly generated address
1190
1190
// Note: We use a new key here to keep it from being obvious which side is the change.
1191
1191
// The drawback is that by not reusing a previous key, the change may be lost if a
@@ -1196,20 +1196,18 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
1196
1196
1197
1197
// Reserve a new key pair from key pool. If it fails, provide a dummy
1198
1198
// destination in case we don't need change.
1199
- CTxDestination dest;
1200
1199
auto op_dest = reservedest.GetReservedDestination (true );
1201
1200
if (!op_dest) {
1202
1201
error = _ (" Transaction needs a change address, but we can't generate it." ) + Untranslated (" " ) + util::ErrorString (op_dest);
1203
1202
} else {
1204
- dest = *op_dest;
1205
- scriptChange = GetScriptForDestination (dest);
1203
+ change_dest = *op_dest;
1206
1204
}
1207
- // A valid destination implies a change script (and
1208
- // vice-versa). An empty change script will abort later, if the
1209
- // change keypool ran out, but change is required.
1210
- CHECK_NONFATAL (IsValidDestination (dest) != scriptChange.empty ());
1211
1205
}
1212
- CTxOut change_prototype_txout (0 , scriptChange);
1206
+ CScript change_prototype_script = GetScriptForDestination (change_dest);
1207
+ if (std::get_if<V0SilentPaymentDestination>(&change_dest)) {
1208
+ change_prototype_script = GetScriptForDestination (WitnessV1Taproot ());
1209
+ }
1210
+ CTxOut change_prototype_txout (0 , change_prototype_script);
1213
1211
coin_selection_params.change_output_size = GetSerializeSize (change_prototype_txout);
1214
1212
1215
1213
// Get size of spending the change output
@@ -1314,17 +1312,33 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
1314
1312
assert (out_idx < mutableVecSend.size ());
1315
1313
mutableVecSend[out_idx].dest = tr_dest;
1316
1314
}
1317
-
1318
1315
}
1319
1316
// vouts to the payees
1320
1317
txNew.vout .reserve (vecSend.size () + 1 ); // + 1 because of possible later insert
1321
- for (const auto & recipient : mutableVecSend)
1322
- {
1318
+ for (const auto & recipient : mutableVecSend) {
1323
1319
txNew.vout .emplace_back (recipient.nAmount , GetScriptForDestination (recipient.dest ));
1324
1320
}
1325
1321
const CAmount change_amount = result.GetChange (coin_selection_params.min_viable_change , coin_selection_params.m_change_fee );
1326
1322
if (change_amount > 0 ) {
1327
- CTxOut newTxOut (change_amount, scriptChange);
1323
+ // Give up if change keypool ran out as change is required
1324
+ if (!IsValidDestination (change_dest)) {
1325
+ return util::Error{error};
1326
+ }
1327
+ if (const auto * sp = std::get_if<V0SilentPaymentDestination>(&change_dest)) {
1328
+ // Since we will be getting the final destination
1329
+ // for only the change output, the index doesn't matter.
1330
+ std::map<size_t , V0SilentPaymentDestination> change_sp_dest;
1331
+ change_sp_dest[0 ] = *sp;
1332
+ auto taproot_change = CreateSilentPaymentOutputs (wallet, change_sp_dest, result.GetInputSet (), error);
1333
+ if (taproot_change.has_value ()) {
1334
+ change_dest = taproot_change->at (0 );
1335
+ }
1336
+ }
1337
+
1338
+ CScript change_script = GetScriptForDestination (change_dest);
1339
+ Assert (!change_script.empty ());
1340
+
1341
+ CTxOut newTxOut (change_amount, change_script);
1328
1342
if (!change_pos) {
1329
1343
// Insert change txn at random position:
1330
1344
change_pos = rng_fast.randrange (txNew.vout .size () + 1 );
@@ -1465,11 +1479,6 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
1465
1479
return util::Error{Untranslated (STR_INTERNAL_BUG (" Fee needed > fee paid" ))};
1466
1480
}
1467
1481
1468
- // Give up if change keypool ran out and change is required
1469
- if (scriptChange.empty () && change_pos) {
1470
- return util::Error{error};
1471
- }
1472
-
1473
1482
if (sign && !wallet.SignTransaction (txNew)) {
1474
1483
return util::Error{_ (" Signing transaction failed" )};
1475
1484
}
0 commit comments