mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-10 05:57:59 +01:00
Merge bitcoin/bitcoin#28560: wallet, rpc: FundTransaction refactor
18ad1b9142refactor: pass CRecipient to FundTransaction (josibake)5ad19668dbrefactor: simplify `CreateRecipients` (josibake)47353a608drefactor: remove out param from `ParseRecipients` (josibake)f7384b921crefactor: move parsing to new function (josibake)6f569ac903refactor: move normalization to new function (josibake)435fe5cd96test: add tests for fundrawtx and sendmany rpcs (josibake) Pull request description: ## Motivation The primary motivation for this PR is to enable `FundTransaction` to take a vector of `CRecipient` objects to allow passing BIP352 silent payment addresses to RPCs that use `FundTransaction` (e.g. `send`, `walletcreatefundedpsbt`). To do that, SFFO logic needs to be moved out of `FundTransaction` so the `CRecipient` objects with the correct SFFO information can be created and then passed to `FundTransaction`. As a secondary motivation, this PR moves the SFFO stuff closer to the caller, making the code cleaner and easier to understand. This is done by having a single function which parses RPC inputs for SFFO and consistently using the `set<int>` method for communicating SFFO. I'm also not convinced we need to pass a full `CMutableTx` object to `FundTransaction`, but I'm leaving that for a follow-up PR/discussion, as its not a blocker for silent payments. ACKs for top commit: S3RK: reACK18ad1b9142josibake: > According to my `range-diff` nothing changed. reACK [18ad1b9](18ad1b9142) achow101: ACK18ad1b9142Tree-SHA512: d61f017cf7d98489ef216475b68693fd77e7b53a26a6477dcd73e7e5ceff5036b2d21476e377839e710bb73644759d42c4f9f4b14ed96b3e56ed87b07aa6d1a7
This commit is contained in:
@@ -333,6 +333,8 @@ BASE_SCRIPTS = [
|
||||
'wallet_send.py --descriptors',
|
||||
'wallet_sendall.py --legacy-wallet',
|
||||
'wallet_sendall.py --descriptors',
|
||||
'wallet_sendmany.py --descriptors',
|
||||
'wallet_sendmany.py --legacy-wallet',
|
||||
'wallet_create_tx.py --descriptors',
|
||||
'wallet_inactive_hdchains.py --legacy-wallet',
|
||||
'wallet_spend_unconfirmed.py',
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
from decimal import Decimal
|
||||
from itertools import product
|
||||
from math import ceil
|
||||
from test_framework.address import address_to_scriptpubkey
|
||||
|
||||
from test_framework.descriptors import descsum_create
|
||||
from test_framework.messages import (
|
||||
COIN,
|
||||
CTransaction,
|
||||
CTxOut,
|
||||
)
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
@@ -147,6 +150,34 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
self.test_22670()
|
||||
self.test_feerate_rounding()
|
||||
self.test_input_confs_control()
|
||||
self.test_duplicate_outputs()
|
||||
|
||||
def test_duplicate_outputs(self):
|
||||
self.log.info("Test deserializing and funding a transaction with duplicate outputs")
|
||||
self.nodes[1].createwallet("fundtx_duplicate_outputs")
|
||||
w = self.nodes[1].get_wallet_rpc("fundtx_duplicate_outputs")
|
||||
|
||||
addr = w.getnewaddress(address_type="bech32")
|
||||
self.nodes[0].sendtoaddress(addr, 5)
|
||||
self.generate(self.nodes[0], 1)
|
||||
|
||||
address = self.nodes[0].getnewaddress("bech32")
|
||||
tx = CTransaction()
|
||||
tx.vin = []
|
||||
tx.vout = [CTxOut(1 * COIN, bytearray(address_to_scriptpubkey(address)))] * 2
|
||||
tx.nLockTime = 0
|
||||
tx_hex = tx.serialize().hex()
|
||||
res = w.fundrawtransaction(tx_hex, add_inputs=True)
|
||||
signed_res = w.signrawtransactionwithwallet(res["hex"])
|
||||
txid = w.sendrawtransaction(signed_res["hex"])
|
||||
assert self.nodes[1].getrawtransaction(txid)
|
||||
|
||||
self.log.info("Test SFFO with duplicate outputs")
|
||||
|
||||
res_sffo = w.fundrawtransaction(tx_hex, add_inputs=True, subtractFeeFromOutputs=[0,1])
|
||||
signed_res_sffo = w.signrawtransactionwithwallet(res_sffo["hex"])
|
||||
txid_sffo = w.sendrawtransaction(signed_res_sffo["hex"])
|
||||
assert self.nodes[1].getrawtransaction(txid_sffo)
|
||||
|
||||
def test_change_position(self):
|
||||
"""Ensure setting changePosition in fundraw with an exact match is handled properly."""
|
||||
|
||||
43
test/functional/wallet_sendmany.py
Executable file
43
test/functional/wallet_sendmany.py
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2022 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test the sendmany RPC command."""
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
|
||||
class SendmanyTest(BitcoinTestFramework):
|
||||
# Setup and helpers
|
||||
def add_options(self, parser):
|
||||
self.add_wallet_options(parser)
|
||||
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def test_sffo_repeated_address(self):
|
||||
addr_1 = self.wallet.getnewaddress()
|
||||
addr_2 = self.wallet.getnewaddress()
|
||||
addr_3 = self.wallet.getnewaddress()
|
||||
|
||||
self.log.info("Test using duplicate address in SFFO argument")
|
||||
self.def_wallet.sendmany(dummy='', amounts={addr_1: 1, addr_2: 1}, subtractfeefrom=[addr_1, addr_1, addr_1])
|
||||
self.log.info("Test using address not present in tx.vout in SFFO argument")
|
||||
self.def_wallet.sendmany(dummy='', amounts={addr_1: 1, addr_2: 1}, subtractfeefrom=[addr_3])
|
||||
|
||||
def run_test(self):
|
||||
self.nodes[0].createwallet("activewallet")
|
||||
self.wallet = self.nodes[0].get_wallet_rpc("activewallet")
|
||||
self.def_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
|
||||
self.generate(self.nodes[0], 101)
|
||||
|
||||
self.test_sffo_repeated_address()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
SendmanyTest().main()
|
||||
Reference in New Issue
Block a user