Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_import_rescan.py
Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | def try_rpc(self, func, *args, **kwargs): | ||||
if self.expect_disabled: | if self.expect_disabled: | ||||
assert_raises_rpc_error(-4, "Rescan is disabled in pruned mode", | assert_raises_rpc_error(-4, "Rescan is disabled in pruned mode", | ||||
func, *args, **kwargs) | func, *args, **kwargs) | ||||
else: | else: | ||||
return func(*args, **kwargs) | return func(*args, **kwargs) | ||||
def do_import(self, timestamp): | def do_import(self, timestamp): | ||||
"""Call one key import RPC.""" | """Call one key import RPC.""" | ||||
rescan = self.rescan == Rescan.yes | |||||
if self.call == Call.single: | if self.call == Call.single: | ||||
if self.data == Data.address: | if self.data == Data.address: | ||||
response = self.try_rpc(self.node.importaddress, self.address["address"], self.label, | response = self.try_rpc( | ||||
self.rescan == Rescan.yes) | self.node.importaddress, address=self.address["address"], rescan=rescan) | ||||
elif self.data == Data.pub: | elif self.data == Data.pub: | ||||
response = self.try_rpc(self.node.importpubkey, self.address["pubkey"], self.label, | response = self.try_rpc( | ||||
self.rescan == Rescan.yes) | self.node.importpubkey, pubkey=self.address["pubkey"], rescan=rescan) | ||||
elif self.data == Data.priv: | elif self.data == Data.priv: | ||||
response = self.try_rpc( | response = self.try_rpc( | ||||
self.node.importprivkey, self.key, self.label, self.rescan == Rescan.yes) | self.node.importprivkey, privkey=self.key, rescan=rescan) | ||||
assert_equal(response, None) | assert_equal(response, None) | ||||
elif self.call == Call.multi: | elif self.call == Call.multi: | ||||
response = self.node.importmulti([{ | response = self.node.importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": self.address["address"] | "address": self.address["address"] | ||||
}, | }, | ||||
"timestamp": timestamp + TIMESTAMP_WINDOW + (1 if self.rescan == Rescan.late_timestamp else 0), | "timestamp": timestamp + TIMESTAMP_WINDOW + (1 if self.rescan == Rescan.late_timestamp else 0), | ||||
"pubkeys": [self.address["pubkey"]] if self.data == Data.pub else [], | "pubkeys": [self.address["pubkey"]] if self.data == Data.pub else [], | ||||
"keys": [self.key] if self.data == Data.priv else [], | "keys": [self.key] if self.data == Data.priv else [], | ||||
"label": self.label, | |||||
"watchonly": self.data != Data.priv | "watchonly": self.data != Data.priv | ||||
}], {"rescan": self.rescan in (Rescan.yes, Rescan.late_timestamp)}) | }], {"rescan": self.rescan in (Rescan.yes, Rescan.late_timestamp)}) | ||||
assert_equal(response, [{"success": True}]) | assert_equal(response, [{"success": True}]) | ||||
def check(self, txid=None, amount=None, confirmations=None): | def check(self, txid=None, amount=None, confirmations=None): | ||||
"""Verify that getbalance/listtransactions return expected values.""" | """Verify that listreceivedbyaddress returns expected values.""" | ||||
balance = self.node.getbalance(self.label, 0, True) | |||||
assert_equal(balance, self.expected_balance) | |||||
txs = self.node.listtransactions(self.label, 10000, 0, True) | addresses = self.node.listreceivedbyaddress( | ||||
assert_equal(len(txs), self.expected_txs) | minconf=0, include_watchonly=True, address_filter=self.address['address']) | ||||
if self.expected_txs: | |||||
assert_equal(len(addresses[0]["txids"]), self.expected_txs) | |||||
if txid is not None: | if txid is not None: | ||||
tx, = [tx for tx in txs if tx["txid"] == txid] | address, = [ad for ad in addresses if txid in ad["txids"]] | ||||
assert_equal(tx["label"], self.label) | assert_equal(address["address"], self.address["address"]) | ||||
assert_equal(tx["address"], self.address["address"]) | assert_equal(address["amount"], self.expected_balance) | ||||
assert_equal(tx["amount"], amount) | assert_equal(address["confirmations"], confirmations) | ||||
assert_equal(tx["category"], "receive") | |||||
assert_equal(tx["label"], self.label) | |||||
assert_equal(tx["txid"], txid) | |||||
assert_equal(tx["confirmations"], confirmations) | |||||
assert_equal("trusted" not in tx, True) | |||||
# Verify the transaction is correctly marked watchonly depending on | # Verify the transaction is correctly marked watchonly depending on | ||||
# whether the transaction pays to an imported public key or | # whether the transaction pays to an imported public key or | ||||
# imported private key. The test setup ensures that transaction | # imported private key. The test setup ensures that transaction | ||||
# inputs will not be from watchonly keys (important because | # inputs will not be from watchonly keys (important because | ||||
# involvesWatchonly will be true if either the transaction output | # involvesWatchonly will be true if either the transaction output | ||||
# or inputs are watchonly). | # or inputs are watchonly). | ||||
if self.data != Data.priv: | if self.data != Data.priv: | ||||
assert_equal(tx["involvesWatchonly"], True) | assert_equal(address["involvesWatchonly"], True) | ||||
else: | else: | ||||
assert_equal("involvesWatchonly" not in tx, True) | assert_equal("involvesWatchonly" not in address, True) | ||||
# List of Variants for each way a key or address could be imported. | # List of Variants for each way a key or address could be imported. | ||||
IMPORT_VARIANTS = [Variant(*variants) | IMPORT_VARIANTS = [Variant(*variants) | ||||
for variants in itertools.product(Call, Data, Rescan, (False, True))] | for variants in itertools.product(Call, Data, Rescan, (False, True))] | ||||
# List of nodes to import keys to. Half the nodes will have pruning disabled, | # List of nodes to import keys to. Half the nodes will have pruning disabled, | ||||
# half will have it enabled. Different nodes will be used for imports that are | # half will have it enabled. Different nodes will be used for imports that are | ||||
Show All 9 Lines | |||||
TIMESTAMP_WINDOW = 2 * 60 * 60 | TIMESTAMP_WINDOW = 2 * 60 * 60 | ||||
class ImportRescanTest(BitcoinTestFramework): | class ImportRescanTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 2 + len(IMPORT_NODES) | self.num_nodes = 2 + len(IMPORT_NODES) | ||||
def setup_network(self): | def setup_network(self): | ||||
extra_args = [['-deprecatedrpc=accounts'] | extra_args = [[] for _ in range(self.num_nodes)] | ||||
for _ in range(self.num_nodes)] | |||||
for i, import_node in enumerate(IMPORT_NODES, 2): | for i, import_node in enumerate(IMPORT_NODES, 2): | ||||
if import_node.prune: | if import_node.prune: | ||||
extra_args[i] += ["-prune=1"] | extra_args[i] += ["-prune=1"] | ||||
self.add_nodes(self.num_nodes, extra_args=extra_args) | self.add_nodes(self.num_nodes, extra_args=extra_args) | ||||
# Import keys | # Import keys | ||||
self.start_nodes(extra_args=[[]] * self.num_nodes) | self.start_nodes(extra_args=[[]] * self.num_nodes) | ||||
super().import_deterministic_coinbase_privkeys() | super().import_deterministic_coinbase_privkeys() | ||||
self.stop_nodes() | self.stop_nodes() | ||||
self.start_nodes() | self.start_nodes() | ||||
for i in range(1, self.num_nodes): | for i in range(1, self.num_nodes): | ||||
connect_nodes(self.nodes[i], self.nodes[0]) | connect_nodes(self.nodes[i], self.nodes[0]) | ||||
def import_deterministic_coinbase_privkeys(self): | def import_deterministic_coinbase_privkeys(self): | ||||
pass | pass | ||||
def run_test(self): | def run_test(self): | ||||
# Create one transaction on node 0 with a unique amount and label for | # Create one transaction on node 0 with a unique amount for | ||||
# each possible type of wallet import RPC. | # each possible type of wallet import RPC. | ||||
for i, variant in enumerate(IMPORT_VARIANTS): | for i, variant in enumerate(IMPORT_VARIANTS): | ||||
variant.label = "label {} {}".format(i, variant) | |||||
variant.address = self.nodes[1].getaddressinfo( | variant.address = self.nodes[1].getaddressinfo( | ||||
self.nodes[1].getnewaddress(variant.label)) | self.nodes[1].getnewaddress()) | ||||
variant.key = self.nodes[1].dumpprivkey(variant.address["address"]) | variant.key = self.nodes[1].dumpprivkey(variant.address["address"]) | ||||
variant.initial_amount = 10 - (i + 1) / 4.0 | variant.initial_amount = 10 - (i + 1) / 4.0 | ||||
variant.initial_txid = self.nodes[0].sendtoaddress( | variant.initial_txid = self.nodes[0].sendtoaddress( | ||||
variant.address["address"], variant.initial_amount) | variant.address["address"], variant.initial_amount) | ||||
# Generate a block containing the initial transactions, then another | # Generate a block containing the initial transactions, then another | ||||
# block further in the future (past the rescan window). | # block further in the future (past the rescan window). | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
▲ Show 20 Lines • Show All 47 Lines • Show Last 20 Lines |