Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet-accounts.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2016 The Bitcoin Core developers | # Copyright (c) 2016-2017 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Test account RPCs. | """Test label RPCs. | ||||
RPCs tested are: | RPCs tested are: | ||||
- getaccountaddress | - getlabeladdress | ||||
- getaddressesbyaccount | - getaddressesbyaccount | ||||
- listaddressgroupings | - listaddressgroupings | ||||
- setaccount | - setlabel | ||||
- sendfrom (with account arguments) | - sendfrom (with account arguments) | ||||
- move (with account arguments) | - move (with account arguments) | ||||
""" | """ | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import assert_equal | from test_framework.util import assert_equal | ||||
class WalletAccountsTest(BitcoinTestFramework): | class WalletLabelsTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.extra_args = [[]] | self.extra_args = [[]] | ||||
def run_test(self): | def run_test(self): | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
# Check that there's no UTXO on any of the nodes | # Check that there's no UTXO on any of the nodes | ||||
Show All 37 Lines | def run_test(self): | ||||
assert_equal(len(address_groups[0]), 2) | assert_equal(len(address_groups[0]), 2) | ||||
assert_equal(set([a[0] for a in address_groups[0]]), linked_addresses) | assert_equal(set([a[0] for a in address_groups[0]]), linked_addresses) | ||||
assert_equal([a[1] for a in address_groups[0]], [0, 0]) | assert_equal([a[1] for a in address_groups[0]], [0, 0]) | ||||
node.generate(1) | node.generate(1) | ||||
amount_to_send = 1.0 | amount_to_send = 1.0 | ||||
# Create accounts and make sure subsequent account API calls | # Create labels and make sure subsequent label API calls | ||||
# recognize the account/address associations. | # recognize the label/address associations. | ||||
accounts = [Account(name) for name in ("a", "b", "c", "d", "e")] | labels = [Label(name) for name in ("a", "b", "c", "d", "e")] | ||||
for account in accounts: | for label in labels: | ||||
account.add_receive_address(node.getaccountaddress(account.name)) | label.add_receive_address(node.getlabeladdress(label.name)) | ||||
account.verify(node) | label.verify(node) | ||||
# Send a transaction to each account, and make sure this forces | # Send a transaction to each label, and make sure this forces | ||||
# getaccountaddress to generate a new receiving address. | # getlabeladdress to generate a new receiving address. | ||||
for account in accounts: | for label in labels: | ||||
node.sendtoaddress(account.receive_address, amount_to_send) | node.sendtoaddress(label.receive_address, amount_to_send) | ||||
account.add_receive_address(node.getaccountaddress(account.name)) | label.add_receive_address(node.getlabeladdress(label.name)) | ||||
account.verify(node) | label.verify(node) | ||||
# Check the amounts received. | # Check the amounts received. | ||||
node.generate(1) | node.generate(1) | ||||
for account in accounts: | for label in labels: | ||||
assert_equal( | assert_equal( | ||||
node.getreceivedbyaddress(account.addresses[0]), amount_to_send) | node.getreceivedbyaddress(label.addresses[0]), amount_to_send) | ||||
assert_equal(node.getreceivedbyaccount( | assert_equal(node.getreceivedbylabel(label.name), amount_to_send) | ||||
account.name), amount_to_send) | |||||
# Check that sendfrom label reduces listaccounts balances. | |||||
# Check that sendfrom account reduces listaccounts balances. | for i, label in enumerate(labels): | ||||
for i, account in enumerate(accounts): | to_label = labels[(i+1) % len(labels)] | ||||
to_account = accounts[(i+1) % len(accounts)] | node.sendfrom(label.name, to_label.receive_address, amount_to_send) | ||||
node.sendfrom( | |||||
account.name, to_account.receive_address, amount_to_send) | |||||
node.generate(1) | node.generate(1) | ||||
for account in accounts: | for label in labels: | ||||
account.add_receive_address(node.getaccountaddress(account.name)) | label.add_receive_address(node.getlabeladdress(label.name)) | ||||
account.verify(node) | label.verify(node) | ||||
assert_equal(node.getreceivedbyaccount(account.name), 2) | assert_equal(node.getreceivedbylabel(label.name), 2) | ||||
node.move(account.name, "", node.getbalance(account.name)) | node.move(label.name, "", node.getbalance(label.name)) | ||||
account.verify(node) | label.verify(node) | ||||
node.generate(101) | node.generate(101) | ||||
# the "" account has what's expected, plus exactly the fee amount as | |||||
# that's been mined and matures in the next 100 blocks. | |||||
expected_account_balances = {"": 5200 + fee} | expected_account_balances = {"": 5200 + fee} | ||||
for account in accounts: | for label in labels: | ||||
expected_account_balances[account.name] = 0 | expected_account_balances[label.name] = 0 | ||||
assert_equal(node.listaccounts(), expected_account_balances) | assert_equal(node.listaccounts(), expected_account_balances) | ||||
# the "" account has what's expected, plus exactly the fee amount as | |||||
# that's been mined and matures in the next 100 blocks. | |||||
assert_equal(node.getbalance(""), 5200 + fee) | assert_equal(node.getbalance(""), 5200 + fee) | ||||
# Check that setaccount can assign an account to a new unused address. | # Check that setlabel can assign a label to a new unused address. | ||||
for account in accounts: | for label in labels: | ||||
address = node.getaccountaddress("") | address = node.getlabeladdress("") | ||||
node.setaccount(address, account.name) | node.setlabel(address, label.name) | ||||
account.add_address(address) | label.add_address(address) | ||||
account.verify(node) | label.verify(node) | ||||
assert(address not in node.getaddressesbyaccount("")) | assert(address not in node.getaddressesbyaccount("")) | ||||
# Check that addmultisigaddress can assign accounts. | # Check that addmultisigaddress can assign labels. | ||||
for account in accounts: | for label in labels: | ||||
addresses = [] | addresses = [] | ||||
for x in range(10): | for x in range(10): | ||||
addresses.append(node.getnewaddress()) | addresses.append(node.getnewaddress()) | ||||
multisig_address = node.addmultisigaddress( | multisig_address = node.addmultisigaddress( | ||||
5, addresses, account.name) | 5, addresses, label.name) | ||||
account.add_address(multisig_address) | label.add_address(multisig_address) | ||||
account.verify(node) | label.verify(node) | ||||
node.sendfrom("", multisig_address, 50) | node.sendfrom("", multisig_address, 50) | ||||
node.generate(101) | node.generate(101) | ||||
for label in labels: | |||||
assert_equal(node.getbalance(label.name), 50) | |||||
for account in accounts: | # Check that setlabel can change the label of an address from a | ||||
assert_equal(node.getbalance(account.name), 50) | # different label. | ||||
change_label(node, labels[0].addresses[0], labels[0], labels[1]) | |||||
# Check that setaccount can change the account of an address from a | |||||
# different account. | # Check that setlabel can change the label of an address which | ||||
change_account( | # is the receiving address of a different label. | ||||
node, accounts[0].addresses[0], accounts[0], accounts[1]) | change_label(node, labels[0].receive_address, labels[0], labels[1]) | ||||
# Check that setaccount can change the account of an address which | # Check that setlabel can set the label of an address already | ||||
# is the receiving address of a different account. | # in the label. This is a no-op. | ||||
change_account( | change_label(node, labels[2].addresses[0], labels[2], labels[2]) | ||||
node, accounts[0].receive_address, accounts[0], accounts[1]) | |||||
# Check that setaccount can set the account of an address already | |||||
# in the account. This is a no-op. | |||||
change_account( | |||||
node, accounts[2].addresses[0], accounts[2], accounts[2]) | |||||
# Check that setaccount can set the account of an address which is | # Check that setlabel can set the label of an address which is | ||||
# already the receiving address of the account. It would probably make | # already the receiving address of the label. It would probably make | ||||
# sense for this to be a no-op, but right now it resets the receiving | # sense for this to be a no-op, but right now it resets the receiving | ||||
# address, causing getaccountaddress to return a brand new address. | # address, causing getlabeladdress to return a brand new address. | ||||
change_account( | change_label(node, labels[2].receive_address, labels[2], labels[2]) | ||||
node, accounts[2].receive_address, accounts[2], accounts[2]) | |||||
class Account: | class Label: | ||||
def __init__(self, name): | def __init__(self, name): | ||||
# Account name | # Label name | ||||
self.name = name | self.name = name | ||||
# Current receiving address associated with this account. | # Current receiving address associated with this label. | ||||
self.receive_address = None | self.receive_address = None | ||||
# List of all addresses assigned with this account | # List of all addresses assigned with this label | ||||
self.addresses = [] | self.addresses = [] | ||||
def add_address(self, address): | def add_address(self, address): | ||||
assert_equal(address not in self.addresses, True) | assert_equal(address not in self.addresses, True) | ||||
self.addresses.append(address) | self.addresses.append(address) | ||||
def add_receive_address(self, address): | def add_receive_address(self, address): | ||||
self.add_address(address) | self.add_address(address) | ||||
self.receive_address = address | self.receive_address = address | ||||
def verify(self, node): | def verify(self, node): | ||||
if self.receive_address is not None: | if self.receive_address is not None: | ||||
assert self.receive_address in self.addresses | assert self.receive_address in self.addresses | ||||
assert_equal(node.getaccountaddress( | assert_equal(node.getlabeladdress(self.name), self.receive_address) | ||||
self.name), self.receive_address) | |||||
for address in self.addresses: | for address in self.addresses: | ||||
assert_equal(node.getaccount(address), self.name) | assert_equal(node.getaccount(address), self.name) | ||||
assert_equal( | assert_equal( | ||||
set(node.getaddressesbyaccount(self.name)), set(self.addresses)) | set(node.getaddressesbyaccount(self.name)), set(self.addresses)) | ||||
def change_account(node, address, old_account, new_account): | def change_label(node, address, old_label, new_label): | ||||
assert_equal(address in old_account.addresses, True) | assert_equal(address in old_label.addresses, True) | ||||
node.setaccount(address, new_account.name) | node.setlabel(address, new_label.name) | ||||
old_account.addresses.remove(address) | old_label.addresses.remove(address) | ||||
new_account.add_address(address) | new_label.add_address(address) | ||||
# Calling setaccount on an address which was previously the receiving | # Calling setlabel on an address which was previously the receiving | ||||
# address of a different account should reset the receiving address of | # address of a different label should reset the receiving address of | ||||
# the old account, causing getaccountaddress to return a brand new | # the old label, causing getlabeladdress to return a brand new | ||||
# address. | # address. | ||||
if address == old_account.receive_address: | if address == old_label.receive_address: | ||||
new_address = node.getaccountaddress(old_account.name) | new_address = node.getlabeladdress(old_label.name) | ||||
assert_equal(new_address not in old_account.addresses, True) | assert_equal(new_address not in old_label.addresses, True) | ||||
assert_equal(new_address not in new_account.addresses, True) | assert_equal(new_address not in new_label.addresses, True) | ||||
old_account.add_receive_address(new_address) | old_label.add_receive_address(new_address) | ||||
old_account.verify(node) | old_label.verify(node) | ||||
new_account.verify(node) | new_label.verify(node) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
WalletAccountsTest().main() | WalletLabelsTest().main() |