Skip to content

Commit ed7f894

Browse files
committed
wallet: use silent_payments as change if bech32m is not available
This will allow wallets with only silent payment descriptors to use silent payment outputs as a change
1 parent 24d12e5 commit ed7f894

File tree

3 files changed

+37
-6
lines changed

3 files changed

+37
-6
lines changed

src/wallet/spend.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <consensus/amount.h>
1111
#include <consensus/validation.h>
1212
#include <interfaces/chain.h>
13+
#include <key_io.h>
1314
#include <node/types.h>
1415
#include <numeric>
1516
#include <policy/policy.h>
@@ -1299,26 +1300,29 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
12991300
result.GetSelectedValue());
13001301

13011302
std::vector<CRecipient> mutableVecSend = vecSend;
1302-
if (coin_control.m_silent_payment) {
1303+
bool fSilentPayment = coin_control.m_silent_payment || std::holds_alternative<V0SilentPaymentDestination>(change_dest);
1304+
if (fSilentPayment) {
13031305
// Get the silent payment destinations, generate the scriptPubKeys,
13041306
// and update vecSend with the generated scriptPubKeys
13051307
std::map<size_t, V0SilentPaymentDestination> sp_dests;
1308+
size_t sp_change_index = 0;
13061309
for (size_t i = 0; i < mutableVecSend.size(); ++i) {
13071310
if (const auto* sp = std::get_if<V0SilentPaymentDestination>(&mutableVecSend.at(i).dest)) {
13081311
// Keep track of the index in vecSend
13091312
sp_dests[i] = *sp;
1313+
sp_change_index += 1;
13101314
}
13111315
}
1312-
if (const auto* change_sp = std::get_if<V0SilentPaymentDestination>(&change_dest)) {
1316+
if (const auto* sp_change = std::get_if<V0SilentPaymentDestination>(&change_dest)) {
13131317
// Generate output for change too
1314-
sp_dests[mutableVecSend.size()] = *change_sp;
1318+
sp_dests[sp_change_index] = *sp_change;
13151319
}
13161320
const auto& silent_payment_tr_spks = CreateSilentPaymentOutputs(wallet, sp_dests, result.GetInputSet(), error);
13171321
if (!silent_payment_tr_spks.has_value()) {
13181322
return util::Error{error};
13191323
}
13201324
for (const auto& [out_idx, tr_dest] : *silent_payment_tr_spks) {
1321-
if (out_idx == mutableVecSend.size()) {
1325+
if (out_idx == sp_change_index) {
13221326
change_dest = tr_dest;
13231327
continue;
13241328
}

src/wallet/wallet.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,6 +2298,11 @@ OutputType CWallet::TransactionChangeType(const std::optional<OutputType>& chang
22982298
if (has_bech32m_spkman) {
22992299
return OutputType::BECH32M;
23002300
}
2301+
bool is_silent_payments_enabled{!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)};
2302+
if (is_silent_payments_enabled && has_sp_spkman) {
2303+
// If silent payments are enabled, use the silent payments spkman for change
2304+
return OutputType::SILENT_PAYMENTS;
2305+
}
23012306
if (has_bech32_spkman) {
23022307
return OutputType::BECH32;
23032308
}

test/functional/wallet_silentpayments_receiving.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,29 @@ def do_nothing():
147147

148148
self.log.info("Wallet persistence verified successfully")
149149

150-
def test_import_rescan(self):
150+
def test_import_descriptors(self):
151+
self.log.info("Check import silent payments descriptor into blank wallet")
152+
153+
self.nodes[0].createwallet(wallet_name="import_blank", blank=True, silent_payments=True)
154+
wallet = self.nodes[0].get_wallet_rpc("import_blank")
155+
156+
descriptor = "sp([eea23daf/352h/0h/0h/1h/0]cRCGWnoELVHTr9oZWz1TUp7jmdBJPS3Kx8UCaHvfpxL6KiVSHH1A,[eea23daf/352h/0h/0h/0h/0]cUxxbQ67tepsEn3AUKSCWAKrvLwP6MPk55DAptcqxqDiXN6yKkNW)#q42ue5dg"
157+
res = wallet.importdescriptors([{
158+
"desc": descriptor,
159+
"active": True,
160+
"next_index": 0,
161+
"timestamp": "now"
162+
}])
163+
assert_equal(res[0]["success"], True)
164+
165+
self.def_wallet.sendtoaddress(wallet.getnewaddress(address_type="silent-payments"), 10)
166+
self.generate(self.nodes[0], 1)
167+
assert_equal(wallet.getbalance(), 10)
168+
169+
wallet.send({self.def_wallet.getnewaddress(): 5})
170+
self.generate(self.nodes[0], 1)
171+
assert_approx(wallet.getbalance(), 5, 0.0001)
172+
151173
self.log.info("Check import rescan works for silent payments")
152174

153175
self.nodes[0].createwallet(wallet_name="alice", silent_payments=True)
@@ -298,7 +320,7 @@ def run_test(self):
298320
self.test_encrypting_unencrypted()
299321
self.test_basic()
300322
self.test_wallet_persistence()
301-
self.test_import_rescan()
323+
self.test_import_descriptors()
302324
self.test_createwallet_descriptor()
303325
self.test_backup_and_restore()
304326
self.test_getaddressinfo()

0 commit comments

Comments
 (0)