Skip to content

Commit 435fe5c

Browse files
committed
test: add tests for fundrawtx and sendmany rpcs
If the serialized transaction passed to `fundrawtransaction` contains duplicates, they will be deserialized and added to the transaction. Add a test to ensure this behavior is not changed during the refactor. A user can pass any number of duplicated and unrelated addresses as an SFFO argument to `sendmany` and the RPC will not throw an error (note, all the rest of the RPCs which take SFFO as an argument will error if the user passes duplicates or specifies outputs not present in the transaction). Add a test to ensure this behavior is not changed during the refactor.
1 parent 0375244 commit 435fe5c

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

test/functional/test_runner.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,8 @@
333333
'wallet_send.py --descriptors',
334334
'wallet_sendall.py --legacy-wallet',
335335
'wallet_sendall.py --descriptors',
336+
'wallet_sendmany.py --descriptors',
337+
'wallet_sendmany.py --legacy-wallet',
336338
'wallet_create_tx.py --descriptors',
337339
'wallet_inactive_hdchains.py --legacy-wallet',
338340
'wallet_spend_unconfirmed.py',

test/functional/wallet_fundrawtransaction.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
from decimal import Decimal
99
from itertools import product
1010
from math import ceil
11+
from test_framework.address import address_to_scriptpubkey
1112

1213
from test_framework.descriptors import descsum_create
1314
from test_framework.messages import (
1415
COIN,
16+
CTransaction,
17+
CTxOut,
1518
)
1619
from test_framework.test_framework import BitcoinTestFramework
1720
from test_framework.util import (
@@ -147,6 +150,34 @@ def run_test(self):
147150
self.test_22670()
148151
self.test_feerate_rounding()
149152
self.test_input_confs_control()
153+
self.test_duplicate_outputs()
154+
155+
def test_duplicate_outputs(self):
156+
self.log.info("Test deserializing and funding a transaction with duplicate outputs")
157+
self.nodes[1].createwallet("fundtx_duplicate_outputs")
158+
w = self.nodes[1].get_wallet_rpc("fundtx_duplicate_outputs")
159+
160+
addr = w.getnewaddress(address_type="bech32")
161+
self.nodes[0].sendtoaddress(addr, 5)
162+
self.generate(self.nodes[0], 1)
163+
164+
address = self.nodes[0].getnewaddress("bech32")
165+
tx = CTransaction()
166+
tx.vin = []
167+
tx.vout = [CTxOut(1 * COIN, bytearray(address_to_scriptpubkey(address)))] * 2
168+
tx.nLockTime = 0
169+
tx_hex = tx.serialize().hex()
170+
res = w.fundrawtransaction(tx_hex, add_inputs=True)
171+
signed_res = w.signrawtransactionwithwallet(res["hex"])
172+
txid = w.sendrawtransaction(signed_res["hex"])
173+
assert self.nodes[1].getrawtransaction(txid)
174+
175+
self.log.info("Test SFFO with duplicate outputs")
176+
177+
res_sffo = w.fundrawtransaction(tx_hex, add_inputs=True, subtractFeeFromOutputs=[0,1])
178+
signed_res_sffo = w.signrawtransactionwithwallet(res_sffo["hex"])
179+
txid_sffo = w.sendrawtransaction(signed_res_sffo["hex"])
180+
assert self.nodes[1].getrawtransaction(txid_sffo)
150181

151182
def test_change_position(self):
152183
"""Ensure setting changePosition in fundraw with an exact match is handled properly."""

test/functional/wallet_sendmany.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2022 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
"""Test the sendmany RPC command."""
6+
7+
from test_framework.test_framework import BitcoinTestFramework
8+
9+
class SendmanyTest(BitcoinTestFramework):
10+
# Setup and helpers
11+
def add_options(self, parser):
12+
self.add_wallet_options(parser)
13+
14+
15+
def skip_test_if_missing_module(self):
16+
self.skip_if_no_wallet()
17+
18+
19+
def set_test_params(self):
20+
self.num_nodes = 1
21+
self.setup_clean_chain = True
22+
23+
def test_sffo_repeated_address(self):
24+
addr_1 = self.wallet.getnewaddress()
25+
addr_2 = self.wallet.getnewaddress()
26+
addr_3 = self.wallet.getnewaddress()
27+
28+
self.log.info("Test using duplicate address in SFFO argument")
29+
self.def_wallet.sendmany(dummy='', amounts={addr_1: 1, addr_2: 1}, subtractfeefrom=[addr_1, addr_1, addr_1])
30+
self.log.info("Test using address not present in tx.vout in SFFO argument")
31+
self.def_wallet.sendmany(dummy='', amounts={addr_1: 1, addr_2: 1}, subtractfeefrom=[addr_3])
32+
33+
def run_test(self):
34+
self.nodes[0].createwallet("activewallet")
35+
self.wallet = self.nodes[0].get_wallet_rpc("activewallet")
36+
self.def_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
37+
self.generate(self.nodes[0], 101)
38+
39+
self.test_sffo_repeated_address()
40+
41+
42+
if __name__ == '__main__':
43+
SendmanyTest().main()

0 commit comments

Comments
 (0)