mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
Merge #16465: test: Test p2sh-witness and bech32 in wallet_import_rescan
fa3c6575cac5e3841797980fe60b8368ae579dba lint: Add false positive to python dead code linter (MarcoFalke) fa25668e1c8982548f1c6f94780709c625811469 test: Test p2sh-witness and bech32 in wallet_import_rescan (MarcoFalke) fa79af298917d501cee26370fdf9d44d05133d15 test: Replace fragile "rng" with call to random() (MarcoFalke) fac3dcf7d052586548f2100a0d576618a85741f9 test: Generate one block for each send in wallet_import_rescan (MarcoFalke) Pull request description: This adds test coverage for segwit in the `wallet_import_rescan` test, among other cleanups. ACKs for top commit: jnewbery: ACK fa3c6575cac5e3841797980fe60b8368ae579dba Tree-SHA512: 877741763c62c1bf9d868864a1e3f0699857e8c028e9fcd65c7eeb73600c22cbe97b7b51093737743d9e87bcb991c1fe1086f673e18765aef0fcfe27951402f0
This commit is contained in:
parent
2307f97784
commit
3e1c8a6a58
@ -26,8 +26,10 @@ from test_framework.util import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
from decimal import Decimal
|
||||||
import enum
|
import enum
|
||||||
import itertools
|
import itertools
|
||||||
|
import random
|
||||||
|
|
||||||
Call = enum.Enum("Call", "single multiaddress multiscript")
|
Call = enum.Enum("Call", "single multiaddress multiscript")
|
||||||
Data = enum.Enum("Data", "address pub priv")
|
Data = enum.Enum("Data", "address pub priv")
|
||||||
@ -50,7 +52,7 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
|
|||||||
assert_equal(response, None)
|
assert_equal(response, None)
|
||||||
|
|
||||||
elif self.call in (Call.multiaddress, Call.multiscript):
|
elif self.call in (Call.multiaddress, Call.multiscript):
|
||||||
response = self.node.importmulti([{
|
request = {
|
||||||
"scriptPubKey": {
|
"scriptPubKey": {
|
||||||
"address": self.address["address"]
|
"address": self.address["address"]
|
||||||
} if self.call == Call.multiaddress else self.address["scriptPubKey"],
|
} if self.call == Call.multiaddress else self.address["scriptPubKey"],
|
||||||
@ -59,13 +61,18 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
|
|||||||
"keys": [self.key] if self.data == Data.priv else [],
|
"keys": [self.key] if self.data == Data.priv else [],
|
||||||
"label": self.label,
|
"label": self.label,
|
||||||
"watchonly": self.data != Data.priv
|
"watchonly": self.data != Data.priv
|
||||||
}], {"rescan": self.rescan in (Rescan.yes, Rescan.late_timestamp)})
|
}
|
||||||
|
response = self.node.importmulti(
|
||||||
|
requests=[request],
|
||||||
|
options={"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, confirmation_height=None):
|
||||||
"""Verify that listtransactions/listreceivedbyaddress return expected values."""
|
"""Verify that listtransactions/listreceivedbyaddress return expected values."""
|
||||||
|
|
||||||
txs = self.node.listtransactions(label=self.label, count=10000, include_watchonly=True)
|
txs = self.node.listtransactions(label=self.label, count=10000, include_watchonly=True)
|
||||||
|
current_height = self.node.getblockcount()
|
||||||
assert_equal(len(txs), self.expected_txs)
|
assert_equal(len(txs), self.expected_txs)
|
||||||
|
|
||||||
addresses = self.node.listreceivedbyaddress(minconf=0, include_watchonly=True, address_filter=self.address['address'])
|
addresses = self.node.listreceivedbyaddress(minconf=0, include_watchonly=True, address_filter=self.address['address'])
|
||||||
@ -80,13 +87,13 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
|
|||||||
assert_equal(tx["category"], "receive")
|
assert_equal(tx["category"], "receive")
|
||||||
assert_equal(tx["label"], self.label)
|
assert_equal(tx["label"], self.label)
|
||||||
assert_equal(tx["txid"], txid)
|
assert_equal(tx["txid"], txid)
|
||||||
assert_equal(tx["confirmations"], confirmations)
|
assert_equal(tx["confirmations"], 1 + current_height - confirmation_height)
|
||||||
assert_equal("trusted" not in tx, True)
|
assert_equal("trusted" not in tx, True)
|
||||||
|
|
||||||
address, = [ad for ad in addresses if txid in ad["txids"]]
|
address, = [ad for ad in addresses if txid in ad["txids"]]
|
||||||
assert_equal(address["address"], self.address["address"])
|
assert_equal(address["address"], self.address["address"])
|
||||||
assert_equal(address["amount"], self.expected_balance)
|
assert_equal(address["amount"], self.expected_balance)
|
||||||
assert_equal(address["confirmations"], confirmations)
|
assert_equal(address["confirmations"], 1 + current_height - confirmation_height)
|
||||||
# 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
|
||||||
@ -114,6 +121,13 @@ IMPORT_NODES = [ImportNode(*fields) for fields in itertools.product((False, True
|
|||||||
# Rescans start at the earliest block up to 2 hours before the key timestamp.
|
# Rescans start at the earliest block up to 2 hours before the key timestamp.
|
||||||
TIMESTAMP_WINDOW = 2 * 60 * 60
|
TIMESTAMP_WINDOW = 2 * 60 * 60
|
||||||
|
|
||||||
|
AMOUNT_DUST = 0.00000546
|
||||||
|
|
||||||
|
|
||||||
|
def get_rand_amount():
|
||||||
|
r = random.uniform(AMOUNT_DUST, 1)
|
||||||
|
return Decimal(str(round(r, 8)))
|
||||||
|
|
||||||
|
|
||||||
class ImportRescanTest(BitcoinTestFramework):
|
class ImportRescanTest(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
@ -125,13 +139,13 @@ class ImportRescanTest(BitcoinTestFramework):
|
|||||||
self.skip_if_no_wallet()
|
self.skip_if_no_wallet()
|
||||||
|
|
||||||
def setup_network(self):
|
def setup_network(self):
|
||||||
extra_args = [[] for _ in range(self.num_nodes)]
|
self.extra_args = [[] 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:
|
||||||
# txindex is enabled by default in Dash and needs to be disabled for import-rescan.py
|
# txindex is enabled by default in Dash and needs to be disabled for import-rescan.py
|
||||||
extra_args[i] += ["-prune=1", "-txindex=0", "-reindex"]
|
self.extra_args[i] += ["-prune=1", "-txindex=0", "-reindex"]
|
||||||
|
|
||||||
self.add_nodes(self.num_nodes, extra_args=extra_args)
|
self.add_nodes(self.num_nodes, extra_args=self.extra_args)
|
||||||
|
|
||||||
# Import keys with pruning disabled
|
# Import keys with pruning disabled
|
||||||
self.start_nodes(extra_args=[[]] * self.num_nodes)
|
self.start_nodes(extra_args=[[]] * self.num_nodes)
|
||||||
@ -149,15 +163,18 @@ class ImportRescanTest(BitcoinTestFramework):
|
|||||||
variant.label = "label {} {}".format(i, variant)
|
variant.label = "label {} {}".format(i, variant)
|
||||||
variant.address = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress(variant.label))
|
variant.address = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress(variant.label))
|
||||||
variant.key = self.nodes[1].dumpprivkey(variant.address["address"])
|
variant.key = self.nodes[1].dumpprivkey(variant.address["address"])
|
||||||
variant.initial_amount = 1 - (i + 1) / 64
|
variant.initial_amount = get_rand_amount()
|
||||||
variant.initial_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.initial_amount)
|
variant.initial_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.initial_amount)
|
||||||
|
self.nodes[0].generate(1) # Generate one block for each send
|
||||||
|
variant.confirmation_height = self.nodes[0].getblockcount()
|
||||||
|
variant.timestamp = self.nodes[0].getblockheader(self.nodes[0].getbestblockhash())["time"]
|
||||||
|
|
||||||
# Generate a block containing the initial transactions, then another
|
# Generate a block further in the future (past the rescan window).
|
||||||
# block further in the future (past the rescan window).
|
|
||||||
self.nodes[0].generate(1)
|
|
||||||
assert_equal(self.nodes[0].getrawmempool(), [])
|
assert_equal(self.nodes[0].getrawmempool(), [])
|
||||||
timestamp = self.nodes[0].getblockheader(self.nodes[0].getbestblockhash())["time"]
|
set_node_times(
|
||||||
set_node_times(self.nodes, timestamp + TIMESTAMP_WINDOW + 1)
|
self.nodes,
|
||||||
|
self.nodes[0].getblockheader(self.nodes[0].getbestblockhash())["time"] + TIMESTAMP_WINDOW + 1,
|
||||||
|
)
|
||||||
self.nodes[0].generate(1)
|
self.nodes[0].generate(1)
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
@ -167,11 +184,11 @@ class ImportRescanTest(BitcoinTestFramework):
|
|||||||
self.log.info('Run import for variant {}'.format(variant))
|
self.log.info('Run import for variant {}'.format(variant))
|
||||||
expect_rescan = variant.rescan == Rescan.yes
|
expect_rescan = variant.rescan == Rescan.yes
|
||||||
variant.node = self.nodes[2 + IMPORT_NODES.index(ImportNode(variant.prune, expect_rescan))]
|
variant.node = self.nodes[2 + IMPORT_NODES.index(ImportNode(variant.prune, expect_rescan))]
|
||||||
variant.do_import(timestamp)
|
variant.do_import(variant.timestamp)
|
||||||
if expect_rescan:
|
if expect_rescan:
|
||||||
variant.expected_balance = variant.initial_amount
|
variant.expected_balance = variant.initial_amount
|
||||||
variant.expected_txs = 1
|
variant.expected_txs = 1
|
||||||
variant.check(variant.initial_txid, variant.initial_amount, 2)
|
variant.check(variant.initial_txid, variant.initial_amount, variant.confirmation_height)
|
||||||
else:
|
else:
|
||||||
variant.expected_balance = 0
|
variant.expected_balance = 0
|
||||||
variant.expected_txs = 0
|
variant.expected_txs = 0
|
||||||
@ -179,11 +196,11 @@ class ImportRescanTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
# Create new transactions sending to each address.
|
# Create new transactions sending to each address.
|
||||||
for i, variant in enumerate(IMPORT_VARIANTS):
|
for i, variant in enumerate(IMPORT_VARIANTS):
|
||||||
variant.sent_amount = 1 - (2 * i + 1) / 128
|
variant.sent_amount = get_rand_amount()
|
||||||
variant.sent_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.sent_amount)
|
variant.sent_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.sent_amount)
|
||||||
|
self.nodes[0].generate(1) # Generate one block for each send
|
||||||
|
variant.confirmation_height = self.nodes[0].getblockcount()
|
||||||
|
|
||||||
# Generate a block containing the new transactions.
|
|
||||||
self.nodes[0].generate(1)
|
|
||||||
assert_equal(self.nodes[0].getrawmempool(), [])
|
assert_equal(self.nodes[0].getrawmempool(), [])
|
||||||
self.sync_all()
|
self.sync_all()
|
||||||
|
|
||||||
@ -192,7 +209,7 @@ class ImportRescanTest(BitcoinTestFramework):
|
|||||||
self.log.info('Run check for variant {}'.format(variant))
|
self.log.info('Run check for variant {}'.format(variant))
|
||||||
variant.expected_balance += variant.sent_amount
|
variant.expected_balance += variant.sent_amount
|
||||||
variant.expected_txs += 1
|
variant.expected_txs += 1
|
||||||
variant.check(variant.sent_txid, variant.sent_amount, 1)
|
variant.check(variant.sent_txid, variant.sent_amount, variant.confirmation_height)
|
||||||
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:
|
||||||
self.stop_node(i, expected_stderr='Warning: You are starting with governance validation disabled. This is expected because you are running a pruned node.')
|
self.stop_node(i, expected_stderr='Warning: You are starting with governance validation disabled. This is expected because you are running a pruned node.')
|
||||||
|
Loading…
Reference in New Issue
Block a user