aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/assumevalid.py2
-rwxr-xr-xtest/functional/bitcoin_cli.py47
-rwxr-xr-xtest/functional/blockchain.py31
-rwxr-xr-xtest/functional/dbcrash.py2
-rwxr-xr-xtest/functional/deprecated_rpc.py23
-rwxr-xr-xtest/functional/keypool-topup.py2
-rwxr-xr-xtest/functional/mining.py1
-rwxr-xr-xtest/functional/multiwallet.py2
-rwxr-xr-xtest/functional/p2p-leaktests.py9
-rwxr-xr-xtest/functional/p2p-versionbits-warning.py9
-rwxr-xr-xtest/functional/rpcnamedargs.py6
-rwxr-xr-xtest/functional/segwit.py63
-rwxr-xr-xtest/functional/smartfees.py2
-rw-r--r--test/functional/test_framework/address.py28
-rwxr-xr-xtest/functional/test_framework/mininode.py11
-rw-r--r--test/functional/test_framework/segwit_addr.py107
-rwxr-xr-xtest/functional/test_framework/test_framework.py5
-rwxr-xr-xtest/functional/test_framework/test_node.py19
-rw-r--r--test/functional/test_framework/util.py29
-rwxr-xr-xtest/functional/test_runner.py1
-rwxr-xr-xtest/functional/wallet-hd.py2
-rwxr-xr-xtest/functional/wallet.py3
-rwxr-xr-xtest/functional/zapwallettxes.py10
-rw-r--r--test/util/data/bitcoin-util-test.json18
-rw-r--r--test/util/data/txcreatemultisig3.json6
-rw-r--r--test/util/data/txcreatemultisig5.json26
-rw-r--r--test/util/data/txcreateoutpubkey2.json6
-rw-r--r--test/util/data/txcreatescript3.json6
28 files changed, 427 insertions, 49 deletions
diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py
index beaf8c7055..65685c48b7 100755
--- a/test/functional/assumevalid.py
+++ b/test/functional/assumevalid.py
@@ -68,6 +68,8 @@ class AssumeValidTest(BitcoinTestFramework):
def send_blocks_until_disconnected(self, node):
"""Keep sending blocks to the node until we're disconnected."""
for i in range(len(self.blocks)):
+ if not node.connection:
+ break
try:
node.send_message(msg_block(self.blocks[i]))
except IOError as e:
diff --git a/test/functional/bitcoin_cli.py b/test/functional/bitcoin_cli.py
index 7acfede3f7..996cbb8a12 100755
--- a/test/functional/bitcoin_cli.py
+++ b/test/functional/bitcoin_cli.py
@@ -4,7 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test bitcoin-cli"""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal
+from test_framework.util import assert_equal, assert_raises_process_error, get_auth_cookie
class TestBitcoinCli(BitcoinTestFramework):
@@ -15,11 +15,48 @@ class TestBitcoinCli(BitcoinTestFramework):
def run_test(self):
"""Main test logic"""
- self.log.info("Compare responses from getinfo RPC and `bitcoin-cli getinfo`")
- cli_get_info = self.nodes[0].cli.getinfo()
- rpc_get_info = self.nodes[0].getinfo()
+ self.log.info("Compare responses from gewalletinfo RPC and `bitcoin-cli getwalletinfo`")
+ cli_response = self.nodes[0].cli.getwalletinfo()
+ rpc_response = self.nodes[0].getwalletinfo()
+ assert_equal(cli_response, rpc_response)
- assert_equal(cli_get_info, rpc_get_info)
+ self.log.info("Compare responses from getblockchaininfo RPC and `bitcoin-cli getblockchaininfo`")
+ cli_response = self.nodes[0].cli.getblockchaininfo()
+ rpc_response = self.nodes[0].getblockchaininfo()
+ assert_equal(cli_response, rpc_response)
+
+ user, password = get_auth_cookie(self.nodes[0].datadir)
+
+ self.log.info("Test -stdinrpcpass option")
+ assert_equal(0, self.nodes[0].cli('-rpcuser=%s' % user, '-stdinrpcpass', input=password).getblockcount())
+ assert_raises_process_error(1, "incorrect rpcuser or rpcpassword", self.nodes[0].cli('-rpcuser=%s' % user, '-stdinrpcpass', input="foo").echo)
+
+ self.log.info("Test -stdin and -stdinrpcpass")
+ assert_equal(["foo", "bar"], self.nodes[0].cli('-rpcuser=%s' % user, '-stdin', '-stdinrpcpass', input=password + "\nfoo\nbar").echo())
+ assert_raises_process_error(1, "incorrect rpcuser or rpcpassword", self.nodes[0].cli('-rpcuser=%s' % user, '-stdin', '-stdinrpcpass', input="foo").echo)
+
+ self.log.info("Compare responses from `bitcoin-cli -getinfo` and the RPCs data is retrieved from.")
+ cli_get_info = self.nodes[0].cli('-getinfo').help()
+ wallet_info = self.nodes[0].getwalletinfo()
+ network_info = self.nodes[0].getnetworkinfo()
+ blockchain_info = self.nodes[0].getblockchaininfo()
+
+ assert_equal(cli_get_info['version'], network_info['version'])
+ assert_equal(cli_get_info['protocolversion'], network_info['protocolversion'])
+ assert_equal(cli_get_info['walletversion'], wallet_info['walletversion'])
+ assert_equal(cli_get_info['balance'], wallet_info['balance'])
+ assert_equal(cli_get_info['blocks'], blockchain_info['blocks'])
+ assert_equal(cli_get_info['timeoffset'], network_info['timeoffset'])
+ assert_equal(cli_get_info['connections'], network_info['connections'])
+ assert_equal(cli_get_info['proxy'], network_info['networks'][0]['proxy'])
+ assert_equal(cli_get_info['difficulty'], blockchain_info['difficulty'])
+ assert_equal(cli_get_info['testnet'], blockchain_info['chain'] == "test")
+ assert_equal(cli_get_info['balance'], wallet_info['balance'])
+ assert_equal(cli_get_info['keypoololdest'], wallet_info['keypoololdest'])
+ assert_equal(cli_get_info['keypoolsize'], wallet_info['keypoolsize'])
+ assert_equal(cli_get_info['paytxfee'], wallet_info['paytxfee'])
+ assert_equal(cli_get_info['relayfee'], network_info['relayfee'])
+ # unlocked_until is not tested because the wallet is not encrypted
if __name__ == '__main__':
TestBitcoinCli().main()
diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py
index 50be9262e4..c5967aa10b 100755
--- a/test/functional/blockchain.py
+++ b/test/functional/blockchain.py
@@ -33,9 +33,10 @@ from test_framework.util import (
class BlockchainTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
- self.extra_args = [['-stopatheight=207']]
+ self.extra_args = [['-stopatheight=207', '-prune=1']]
def run_test(self):
+ self._test_getblockchaininfo()
self._test_getchaintxstats()
self._test_gettxoutsetinfo()
self._test_getblockheader()
@@ -44,6 +45,34 @@ class BlockchainTest(BitcoinTestFramework):
self._test_stopatheight()
assert self.nodes[0].verifychain(4, 0)
+ def _test_getblockchaininfo(self):
+ self.log.info("Test getblockchaininfo")
+
+ keys = [
+ 'bestblockhash',
+ 'bip9_softforks',
+ 'blocks',
+ 'chain',
+ 'chainwork',
+ 'difficulty',
+ 'headers',
+ 'mediantime',
+ 'pruned',
+ 'softforks',
+ 'verificationprogress',
+ 'warnings',
+ ]
+ res = self.nodes[0].getblockchaininfo()
+ # result should have pruneheight and default keys if pruning is enabled
+ assert_equal(sorted(res.keys()), sorted(['pruneheight'] + keys))
+ # pruneheight should be greater or equal to 0
+ assert res['pruneheight'] >= 0
+
+ self.restart_node(0, ['-stopatheight=207'])
+ res = self.nodes[0].getblockchaininfo()
+ # should have exact keys
+ assert_equal(sorted(res.keys()), keys)
+
def _test_getchaintxstats(self):
chaintxstats = self.nodes[0].getchaintxstats(1)
# 200 txs plus genesis tx
diff --git a/test/functional/dbcrash.py b/test/functional/dbcrash.py
index 71424f641b..24b9765b4e 100755
--- a/test/functional/dbcrash.py
+++ b/test/functional/dbcrash.py
@@ -64,7 +64,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
def setup_network(self):
# Need a bit of extra time for the nodes to start up for this test
- self.add_nodes(self.num_nodes, timewait=90)
+ self.add_nodes(self.num_nodes, extra_args=self.extra_args, timewait=90)
self.start_nodes()
# Leave them unconnected, we'll use submitblock directly in this test
diff --git a/test/functional/deprecated_rpc.py b/test/functional/deprecated_rpc.py
new file mode 100755
index 0000000000..ec500ccbf9
--- /dev/null
+++ b/test/functional/deprecated_rpc.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017 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 deprecation of RPC calls."""
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_raises_jsonrpc
+
+class DeprecatedRpcTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 2
+ self.setup_clean_chain = True
+ self.extra_args = [[], ["-deprecatedrpc=estimatefee"]]
+
+ def run_test(self):
+ self.log.info("estimatefee: Shows deprecated message")
+ assert_raises_jsonrpc(-32, 'estimatefee is deprecated', self.nodes[0].estimatefee, 1)
+
+ self.log.info("Using -deprecatedrpc=estimatefee bypasses the error")
+ self.nodes[1].estimatefee(1)
+
+if __name__ == '__main__':
+ DeprecatedRpcTest().main()
diff --git a/test/functional/keypool-topup.py b/test/functional/keypool-topup.py
index b87433a9c5..160a0f7ae5 100755
--- a/test/functional/keypool-topup.py
+++ b/test/functional/keypool-topup.py
@@ -23,7 +23,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
- self.extra_args = [['-usehd=0'], ['-usehd=1', '-keypool=100', '-keypoolmin=20']]
+ self.extra_args = [[], ['-keypool=100', '-keypoolmin=20']]
def run_test(self):
self.tmpdir = self.options.tmpdir
diff --git a/test/functional/mining.py b/test/functional/mining.py
index 93f9838896..c8fb1062b7 100755
--- a/test/functional/mining.py
+++ b/test/functional/mining.py
@@ -38,7 +38,6 @@ class MiningTest(BitcoinTestFramework):
mining_info = node.getmininginfo()
assert_equal(mining_info['blocks'], 200)
assert_equal(mining_info['chain'], 'regtest')
- assert_equal(mining_info['currentblocksize'], 0)
assert_equal(mining_info['currentblocktx'], 0)
assert_equal(mining_info['currentblockweight'], 0)
assert_equal(mining_info['difficulty'], Decimal('4.656542373906925E-10'))
diff --git a/test/functional/multiwallet.py b/test/functional/multiwallet.py
index e5453e9aad..b4e15a3322 100755
--- a/test/functional/multiwallet.py
+++ b/test/functional/multiwallet.py
@@ -18,6 +18,8 @@ class MultiWalletTest(BitcoinTestFramework):
self.extra_args = [['-wallet=w1', '-wallet=w2', '-wallet=w3']]
def run_test(self):
+ assert_equal(set(self.nodes[0].listwallets()), {"w1", "w2", "w3"})
+
self.stop_node(0)
# should not initialize if there are duplicate wallets
diff --git a/test/functional/p2p-leaktests.py b/test/functional/p2p-leaktests.py
index f27086c97e..1dc8f72cd6 100755
--- a/test/functional/p2p-leaktests.py
+++ b/test/functional/p2p-leaktests.py
@@ -139,6 +139,9 @@ class P2PLeakTest(BitcoinTestFramework):
[conn.disconnect_node() for conn in connections]
+ # Wait until all connections are closed
+ wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 0)
+
# Make sure no unexpected messages came in
assert(no_version_bannode.unexpected_msg == False)
assert(no_version_idlenode.unexpected_msg == False)
@@ -157,8 +160,10 @@ class P2PLeakTest(BitcoinTestFramework):
allowed_service_bit5_node.add_connection(connections[5])
allowed_service_bit7_node.add_connection(connections[6])
- wait_until(lambda: allowed_service_bit5_node.message_count["verack"], timeout=10, lock=mininode_lock)
- wait_until(lambda: allowed_service_bit7_node.message_count["verack"], timeout=10, lock=mininode_lock)
+ NetworkThread().start() # Network thread stopped when all previous NodeConnCBs disconnected. Restart it
+
+ wait_until(lambda: allowed_service_bit5_node.message_count["verack"], lock=mininode_lock)
+ wait_until(lambda: allowed_service_bit7_node.message_count["verack"], lock=mininode_lock)
if __name__ == '__main__':
P2PLeakTest().main()
diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py
index 5dfac6dd10..f9bef2580a 100755
--- a/test/functional/p2p-versionbits-warning.py
+++ b/test/functional/p2p-versionbits-warning.py
@@ -87,8 +87,7 @@ class VersionBitsWarningTest(BitcoinTestFramework):
self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD + 1)
# Check that we're not getting any versionbit-related errors in
# get*info()
- assert(not VB_PATTERN.match(self.nodes[0].getinfo()["errors"]))
- assert(not VB_PATTERN.match(self.nodes[0].getmininginfo()["errors"]))
+ assert(not VB_PATTERN.match(self.nodes[0].getmininginfo()["warnings"]))
assert(not VB_PATTERN.match(self.nodes[0].getnetworkinfo()["warnings"]))
# 3. Now build one period of blocks with >= VB_THRESHOLD blocks signaling
@@ -99,8 +98,7 @@ class VersionBitsWarningTest(BitcoinTestFramework):
# have gotten a different alert due to more than 51/100 blocks
# being of unexpected version.
# Check that get*info() shows some kind of error.
- assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getinfo()["errors"])
- assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getmininginfo()["errors"])
+ assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getmininginfo()["warnings"])
assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getnetworkinfo()["warnings"])
# Mine a period worth of expected blocks so the generic block-version warning
@@ -115,8 +113,7 @@ class VersionBitsWarningTest(BitcoinTestFramework):
# Connecting one block should be enough to generate an error.
self.nodes[0].generate(1)
- assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getinfo()["errors"])
- assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getmininginfo()["errors"])
+ assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getmininginfo()["warnings"])
assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getnetworkinfo()["warnings"])
self.stop_nodes()
self.test_versionbits_in_alert_file()
diff --git a/test/functional/rpcnamedargs.py b/test/functional/rpcnamedargs.py
index da61cc66e6..b3cc681dad 100755
--- a/test/functional/rpcnamedargs.py
+++ b/test/functional/rpcnamedargs.py
@@ -16,10 +16,10 @@ class NamedArgumentTest(BitcoinTestFramework):
def run_test(self):
node = self.nodes[0]
- h = node.help(command='getinfo')
- assert(h.startswith('getinfo\n'))
+ h = node.help(command='getblockchaininfo')
+ assert(h.startswith('getblockchaininfo\n'))
- assert_raises_jsonrpc(-8, 'Unknown named parameter', node.help, random='getinfo')
+ assert_raises_jsonrpc(-8, 'Unknown named parameter', node.help, random='getblockchaininfo')
h = node.getblockhash(height=0)
node.getblock(blockhash=h)
diff --git a/test/functional/segwit.py b/test/functional/segwit.py
index f465c1683b..de5c8c6c87 100755
--- a/test/functional/segwit.py
+++ b/test/functional/segwit.py
@@ -7,7 +7,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.mininode import sha256, CTransaction, CTxIn, COutPoint, CTxOut, COIN, ToHex, FromHex
-from test_framework.address import script_to_p2sh, key_to_p2pkh
+from test_framework.address import script_to_p2sh, key_to_p2pkh, key_to_p2sh_p2wpkh, key_to_p2wpkh, script_to_p2sh_p2wsh, script_to_p2wsh, program_to_witness
from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, OP_TRUE
from io import BytesIO
@@ -33,15 +33,15 @@ def witness_script(use_p2wsh, pubkey):
# Return a transaction (in hex) that spends the given utxo to a segwit output,
# optionally wrapping the segwit output using P2SH.
-def create_witnessprogram(use_p2wsh, utxo, pubkey, encode_p2sh, amount):
- pkscript = hex_str_to_bytes(witness_script(use_p2wsh, pubkey))
- if (encode_p2sh):
- p2sh_hash = hash160(pkscript)
- pkscript = CScript([OP_HASH160, p2sh_hash, OP_EQUAL])
- tx = CTransaction()
- tx.vin.append(CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), b""))
- tx.vout.append(CTxOut(int(amount*COIN), pkscript))
- return ToHex(tx)
+def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount):
+ if use_p2wsh:
+ program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG])
+ addr = script_to_p2sh_p2wsh(program) if encode_p2sh else script_to_p2wsh(program)
+ else:
+ addr = key_to_p2sh_p2wpkh(pubkey) if encode_p2sh else key_to_p2wpkh(pubkey)
+ if not encode_p2sh:
+ assert_equal(node.validateaddress(addr)['scriptPubKey'], witness_script(use_p2wsh, pubkey))
+ return node.createrawtransaction([utxo], {addr: amount})
# Create a transaction spending a given utxo to a segwit output corresponding
# to the given pubkey: use_p2wsh determines whether to use P2WPKH or P2WSH;
@@ -49,7 +49,7 @@ def create_witnessprogram(use_p2wsh, utxo, pubkey, encode_p2sh, amount):
# sign=True will have the given node sign the transaction.
# insert_redeem_script will be added to the scriptSig, if given.
def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""):
- tx_to_witness = create_witnessprogram(use_p2wsh, utxo, pubkey, encode_p2sh, amount)
+ tx_to_witness = create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount)
if (sign):
signed = node.signrawtransaction(tx_to_witness)
assert("errors" not in signed or len(["errors"]) == 0)
@@ -133,8 +133,15 @@ class SegWitTest(BitcoinTestFramework):
newaddress = self.nodes[i].getnewaddress()
self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"])
multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]])
- self.nodes[i].addwitnessaddress(newaddress)
- self.nodes[i].addwitnessaddress(multiaddress)
+ multiscript = CScript([OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG])
+ p2sh_addr = self.nodes[i].addwitnessaddress(newaddress, True)
+ bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False)
+ p2sh_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, True)
+ bip173_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, False)
+ assert_equal(p2sh_addr, key_to_p2sh_p2wpkh(self.pubkey[-1]))
+ assert_equal(bip173_addr, key_to_p2wpkh(self.pubkey[-1]))
+ assert_equal(p2sh_ms_addr, script_to_p2sh_p2wsh(multiscript))
+ assert_equal(bip173_ms_addr, script_to_p2wsh(multiscript))
p2sh_ids.append([])
wit_ids.append([])
for v in range(2):
@@ -558,6 +565,13 @@ class SegWitTest(BitcoinTestFramework):
solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress, 1))
self.mine_and_test_listunspent(unseen_anytime, 0)
+ # Check that createrawtransaction/decoderawtransaction with non-v0 Bech32 works
+ v1_addr = program_to_witness(1, [3,5])
+ v1_tx = self.nodes[0].createrawtransaction([getutxo(spendable_txid[0])],{v1_addr: 1})
+ v1_decoded = self.nodes[1].decoderawtransaction(v1_tx)
+ assert_equal(v1_decoded['vout'][0]['scriptPubKey']['addresses'][0], v1_addr)
+ assert_equal(v1_decoded['vout'][0]['scriptPubKey']['hex'], "51020305")
+
# Check that spendable outputs are really spendable
self.create_and_mine_tx_from_txids(spendable_txid)
@@ -570,6 +584,29 @@ class SegWitTest(BitcoinTestFramework):
self.nodes[0].importprivkey("cTW5mR5M45vHxXkeChZdtSPozrFwFgmEvTNnanCW6wrqwaCZ1X7K")
self.create_and_mine_tx_from_txids(solvable_txid)
+ # Test that importing native P2WPKH/P2WSH scripts works
+ for use_p2wsh in [False, True]:
+ if use_p2wsh:
+ scriptPubKey = "00203a59f3f56b713fdcf5d1a57357f02c44342cbf306ffe0c4741046837bf90561a"
+ transaction = "01000000000100e1f505000000002200203a59f3f56b713fdcf5d1a57357f02c44342cbf306ffe0c4741046837bf90561a00000000"
+ else:
+ scriptPubKey = "a9142f8c469c2f0084c48e11f998ffbe7efa7549f26d87"
+ transaction = "01000000000100e1f5050000000017a9142f8c469c2f0084c48e11f998ffbe7efa7549f26d8700000000"
+
+ self.nodes[1].importaddress(scriptPubKey, "", False)
+ rawtxfund = self.nodes[1].fundrawtransaction(transaction)['hex']
+ rawtxfund = self.nodes[1].signrawtransaction(rawtxfund)["hex"]
+ txid = self.nodes[1].sendrawtransaction(rawtxfund)
+
+ assert_equal(self.nodes[1].gettransaction(txid, True)["txid"], txid)
+ assert_equal(self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid)
+
+ # Assert it is properly saved
+ self.stop_node(1)
+ self.start_node(1)
+ assert_equal(self.nodes[1].gettransaction(txid, True)["txid"], txid)
+ assert_equal(self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid)
+
def mine_and_test_listunspent(self, script_list, ismine):
utxo = find_unspent(self.nodes[0], 50)
tx = CTransaction()
diff --git a/test/functional/smartfees.py b/test/functional/smartfees.py
index 76632fc578..986f4546a8 100755
--- a/test/functional/smartfees.py
+++ b/test/functional/smartfees.py
@@ -151,7 +151,7 @@ class EstimateFeeTest(BitcoinTestFramework):
which we will use to generate our transactions.
"""
self.add_nodes(3, extra_args=[["-maxorphantx=1000", "-whitelist=127.0.0.1"],
- ["-blockmaxsize=17000", "-maxorphantx=1000"],
+ ["-blockmaxsize=17000", "-maxorphantx=1000", "-deprecatedrpc=estimatefee"],
["-blockmaxsize=8000", "-maxorphantx=1000"]])
# Use node0 to mine blocks for input splitting
# Node1 mines small blocks but that are bigger than the expected transaction rate.
diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py
index 180dac197e..2e2db5ffb2 100644
--- a/test/functional/test_framework/address.py
+++ b/test/functional/test_framework/address.py
@@ -7,6 +7,8 @@
from .script import hash256, hash160, sha256, CScript, OP_0
from .util import bytes_to_hex_str, hex_str_to_bytes
+from . import segwit_addr
+
chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
def byte_to_base58(b, version):
@@ -44,6 +46,32 @@ def script_to_p2sh(script, main = False):
script = check_script(script)
return scripthash_to_p2sh(hash160(script), main)
+def key_to_p2sh_p2wpkh(key, main = False):
+ key = check_key(key)
+ p2shscript = CScript([OP_0, hash160(key)])
+ return script_to_p2sh(p2shscript, main)
+
+def program_to_witness(version, program, main = False):
+ if (type(program) is str):
+ program = hex_str_to_bytes(program)
+ assert 0 <= version <= 16
+ assert 2 <= len(program) <= 40
+ assert version > 0 or len(program) in [20, 32]
+ return segwit_addr.encode("bc" if main else "bcrt", version, program)
+
+def script_to_p2wsh(script, main = False):
+ script = check_script(script)
+ return program_to_witness(0, sha256(script), main)
+
+def key_to_p2wpkh(key, main = False):
+ key = check_key(key)
+ return program_to_witness(0, hash160(key), main)
+
+def script_to_p2sh_p2wsh(script, main = False):
+ script = check_script(script)
+ p2shscript = CScript([OP_0, sha256(script)])
+ return script_to_p2sh(p2shscript, main)
+
def check_key(key):
if (type(key) is str):
key = hex_str_to_bytes(key) # Assuming this is hex string
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index 2607b9b07c..abed661f37 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -1654,6 +1654,7 @@ class NodeConn(asyncore.dispatcher):
self.dstaddr = dstaddr
self.dstport = dstport
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self.sendbuf = b""
self.recvbuf = b""
self.ver_send = 209
@@ -1792,7 +1793,14 @@ class NodeConn(asyncore.dispatcher):
tmsg += h[:4]
tmsg += data
with mininode_lock:
- self.sendbuf += tmsg
+ if (len(self.sendbuf) == 0 and not pushbuf):
+ try:
+ sent = self.send(tmsg)
+ self.sendbuf = tmsg[sent:]
+ except BlockingIOError:
+ self.sendbuf = tmsg
+ else:
+ self.sendbuf += tmsg
self.last_sent = time.time()
def got_message(self, message):
@@ -1830,6 +1838,7 @@ class NetworkThread(Thread):
disconnected.append(obj)
[ obj.handle_close() for obj in disconnected ]
asyncore.loop(0.1, use_poll=True, map=mininode_socket_map, count=1)
+ logger.debug("Network thread closing")
# An exception we can raise if we detect a potential disconnect
diff --git a/test/functional/test_framework/segwit_addr.py b/test/functional/test_framework/segwit_addr.py
new file mode 100644
index 0000000000..02368e938f
--- /dev/null
+++ b/test/functional/test_framework/segwit_addr.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017 Pieter Wuille
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Reference implementation for Bech32 and segwit addresses."""
+
+
+CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+
+
+def bech32_polymod(values):
+ """Internal function that computes the Bech32 checksum."""
+ generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
+ chk = 1
+ for value in values:
+ top = chk >> 25
+ chk = (chk & 0x1ffffff) << 5 ^ value
+ for i in range(5):
+ chk ^= generator[i] if ((top >> i) & 1) else 0
+ return chk
+
+
+def bech32_hrp_expand(hrp):
+ """Expand the HRP into values for checksum computation."""
+ return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]
+
+
+def bech32_verify_checksum(hrp, data):
+ """Verify a checksum given HRP and converted data characters."""
+ return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1
+
+
+def bech32_create_checksum(hrp, data):
+ """Compute the checksum values given HRP and data."""
+ values = bech32_hrp_expand(hrp) + data
+ polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
+ return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
+
+
+def bech32_encode(hrp, data):
+ """Compute a Bech32 string given HRP and data values."""
+ combined = data + bech32_create_checksum(hrp, data)
+ return hrp + '1' + ''.join([CHARSET[d] for d in combined])
+
+
+def bech32_decode(bech):
+ """Validate a Bech32 string, and determine HRP and data."""
+ if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
+ (bech.lower() != bech and bech.upper() != bech)):
+ return (None, None)
+ bech = bech.lower()
+ pos = bech.rfind('1')
+ if pos < 1 or pos + 7 > len(bech) or len(bech) > 90:
+ return (None, None)
+ if not all(x in CHARSET for x in bech[pos+1:]):
+ return (None, None)
+ hrp = bech[:pos]
+ data = [CHARSET.find(x) for x in bech[pos+1:]]
+ if not bech32_verify_checksum(hrp, data):
+ return (None, None)
+ return (hrp, data[:-6])
+
+
+def convertbits(data, frombits, tobits, pad=True):
+ """General power-of-2 base conversion."""
+ acc = 0
+ bits = 0
+ ret = []
+ maxv = (1 << tobits) - 1
+ max_acc = (1 << (frombits + tobits - 1)) - 1
+ for value in data:
+ if value < 0 or (value >> frombits):
+ return None
+ acc = ((acc << frombits) | value) & max_acc
+ bits += frombits
+ while bits >= tobits:
+ bits -= tobits
+ ret.append((acc >> bits) & maxv)
+ if pad:
+ if bits:
+ ret.append((acc << (tobits - bits)) & maxv)
+ elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
+ return None
+ return ret
+
+
+def decode(hrp, addr):
+ """Decode a segwit address."""
+ hrpgot, data = bech32_decode(addr)
+ if hrpgot != hrp:
+ return (None, None)
+ decoded = convertbits(data[1:], 5, 8, False)
+ if decoded is None or len(decoded) < 2 or len(decoded) > 40:
+ return (None, None)
+ if data[0] > 16:
+ return (None, None)
+ if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32:
+ return (None, None)
+ return (data[0], decoded)
+
+
+def encode(hrp, witver, witprog):
+ """Encode a segwit address."""
+ ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5))
+ if decode(hrp, ret) == (None, None):
+ return None
+ return ret
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index a53eb51799..381513ab9e 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -273,6 +273,11 @@ class BitcoinTestFramework(object):
# Wait for nodes to stop
node.wait_until_stopped()
+ def restart_node(self, i, extra_args=None):
+ """Stop and start a test node"""
+ self.stop_node(i)
+ self.start_node(i, extra_args)
+
def assert_start_raises_init_error(self, i, extra_args=None, expected_msg=None):
with tempfile.SpooledTemporaryFile(max_size=2**16) as log_stderr:
try:
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index f58a372a14..12dab57a02 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -155,8 +155,16 @@ class TestNodeCLI():
"""Interface to bitcoin-cli for an individual node"""
def __init__(self, binary, datadir):
+ self.args = []
self.binary = binary
self.datadir = datadir
+ self.input = None
+
+ def __call__(self, *args, input=None):
+ # TestNodeCLI is callable with bitcoin-cli command-line args
+ self.args = [str(arg) for arg in args]
+ self.input = input
+ return self
def __getattr__(self, command):
def dispatcher(*args, **kwargs):
@@ -169,9 +177,14 @@ class TestNodeCLI():
pos_args = [str(arg) for arg in args]
named_args = [str(key) + "=" + str(value) for (key, value) in kwargs.items()]
assert not (pos_args and named_args), "Cannot use positional arguments and named arguments in the same bitcoin-cli call"
- p_args = [self.binary, "-datadir=" + self.datadir]
+ p_args = [self.binary, "-datadir=" + self.datadir] + self.args
if named_args:
p_args += ["-named"]
p_args += [command] + pos_args + named_args
- cli_output = subprocess.check_output(p_args, universal_newlines=True)
- return json.loads(cli_output, parse_float=decimal.Decimal)
+ process = subprocess.Popen(p_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
+ cli_stdout, cli_stderr = process.communicate(input=self.input)
+ returncode = process.poll()
+ if returncode:
+ # Ignore cli_stdout, raise with cli_stderr
+ raise subprocess.CalledProcessError(returncode, self.binary, output=cli_stderr)
+ return json.loads(cli_stdout, parse_float=decimal.Decimal)
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index f819edcc3d..64966adb97 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -13,6 +13,7 @@ import logging
import os
import random
import re
+from subprocess import CalledProcessError
import time
from . import coverage
@@ -58,18 +59,42 @@ def assert_raises_message(exc, message, fun, *args, **kwds):
else:
raise AssertionError("No exception raised")
+def assert_raises_process_error(returncode, output, fun, *args, **kwds):
+ """Execute a process and asserts the process return code and output.
+
+ Calls function `fun` with arguments `args` and `kwds`. Catches a CalledProcessError
+ and verifies that the return code and output are as expected. Throws AssertionError if
+ no CalledProcessError was raised or if the return code and output are not as expected.
+
+ Args:
+ returncode (int): the process return code.
+ output (string): [a substring of] the process output.
+ fun (function): the function to call. This should execute a process.
+ args*: positional arguments for the function.
+ kwds**: named arguments for the function.
+ """
+ try:
+ fun(*args, **kwds)
+ except CalledProcessError as e:
+ if returncode != e.returncode:
+ raise AssertionError("Unexpected returncode %i" % e.returncode)
+ if output not in e.output:
+ raise AssertionError("Expected substring not found:" + e.output)
+ else:
+ raise AssertionError("No exception raised")
+
def assert_raises_jsonrpc(code, message, fun, *args, **kwds):
"""Run an RPC and verify that a specific JSONRPC exception code and message is raised.
Calls function `fun` with arguments `args` and `kwds`. Catches a JSONRPCException
and verifies that the error code and message are as expected. Throws AssertionError if
- no JSONRPCException was returned or if the error code/message are not as expected.
+ no JSONRPCException was raised or if the error code/message are not as expected.
Args:
code (int), optional: the error code returned by the RPC call (defined
in src/rpc/protocol.h). Set to None if checking the error code is not required.
message (string), optional: [a substring of] the error string returned by the
- RPC call. Set to None if checking the error string is not required
+ RPC call. Set to None if checking the error string is not required.
fun (function): the function to call. This should be the name of an RPC.
args*: positional arguments for the function.
kwds**: named arguments for the function.
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 8dbe6247ee..5c8740d7cd 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -98,6 +98,7 @@ BASE_SCRIPTS= [
'disconnect_ban.py',
'decodescript.py',
'blockchain.py',
+ 'deprecated_rpc.py',
'disablewallet.py',
'net.py',
'keypool.py',
diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py
index a6b96b7455..5ef3bf5bff 100755
--- a/test/functional/wallet-hd.py
+++ b/test/functional/wallet-hd.py
@@ -15,7 +15,7 @@ class WalletHDTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
- self.extra_args = [['-usehd=0'], ['-usehd=1', '-keypool=0']]
+ self.extra_args = [[], ['-keypool=0']]
def run_test (self):
tmpdir = self.options.tmpdir
diff --git a/test/functional/wallet.py b/test/functional/wallet.py
index 27089e8845..a643684c7f 100755
--- a/test/functional/wallet.py
+++ b/test/functional/wallet.py
@@ -10,10 +10,9 @@ class WalletTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 4
self.setup_clean_chain = True
- self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)]
def setup_network(self):
- self.add_nodes(4, self.extra_args)
+ self.add_nodes(4)
self.start_node(0)
self.start_node(1)
self.start_node(2)
diff --git a/test/functional/zapwallettxes.py b/test/functional/zapwallettxes.py
index c001517a6d..83b11035c8 100755
--- a/test/functional/zapwallettxes.py
+++ b/test/functional/zapwallettxes.py
@@ -15,9 +15,11 @@
been zapped.
"""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import (assert_equal,
- assert_raises_jsonrpc,
- )
+from test_framework.util import (
+ assert_equal,
+ assert_raises_jsonrpc,
+ wait_until,
+)
class ZapWalletTXesTest (BitcoinTestFramework):
def set_test_params(self):
@@ -56,6 +58,8 @@ class ZapWalletTXesTest (BitcoinTestFramework):
self.stop_node(0)
self.start_node(0, ["-persistmempool=1", "-zapwallettxes=2"])
+ wait_until(lambda: self.nodes[0].getmempoolinfo()['size'] == 1, timeout=3)
+
assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2)
diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json
index b61a4f7f8f..89b28bba6c 100644
--- a/test/util/data/bitcoin-util-test.json
+++ b/test/util/data/bitcoin-util-test.json
@@ -263,6 +263,13 @@
},
{ "exec": "./bitcoin-tx",
"args":
+ ["-json", "-create", "outpubkey=0:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:WS", "nversion=1"],
+ "return_code": 1,
+ "error_txt": "error: Uncompressed pubkeys are not useable for SegWit outputs",
+ "description": "Creates a new transaction with a single pay-to-pub-key output, wrapped in P2SH (output as json)"
+ },
+ { "exec": "./bitcoin-tx",
+ "args":
["-create",
"in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0",
"outdata=4:badhexdata"],
@@ -388,5 +395,16 @@
"args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:WS", "nversion=1"],
"output_cmp": "txcreatemultisig4.json",
"description": "Creates a new transaction with a single 2-of-3 multisig in a P2WSH output, wrapped in P2SH (output in json)"
+ },
+ { "exec": "./bitcoin-tx",
+ "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:S"],
+ "output_cmp": "txcreatemultisig5.json",
+ "description": "Uncompressed pubkeys should work just fine for non-witness outputs"
+ },
+ { "exec": "./bitcoin-tx",
+ "args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:047d1368ba7ae01c94bc32293efd70bd7e3be7aa7912d07d0b1c659c1008d179b8642f5fb90f47580feb29f045e216ff5a4716d3a0fed36da414d332046303c44a:WS"],
+ "return_code": 1,
+ "error_txt": "error: Uncompressed pubkeys are not useable for SegWit outputs",
+ "description": "Ensure adding witness outputs with uncompressed pubkeys fails"
}
]
diff --git a/test/util/data/txcreatemultisig3.json b/test/util/data/txcreatemultisig3.json
index 06e093e224..6c5b49d876 100644
--- a/test/util/data/txcreatemultisig3.json
+++ b/test/util/data/txcreatemultisig3.json
@@ -14,7 +14,11 @@
"scriptPubKey": {
"asm": "0 e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f05",
"hex": "0020e15a86a23178f433d514dbbce042e87d72662b8b5edcacfd2e37ab7a2d135f05",
- "type": "witness_v0_scripthash"
+ "reqSigs": 1,
+ "type": "witness_v0_scripthash",
+ "addresses": [
+ "bc1qu9dgdg330r6r84g5mw7wqshg04exv2uttmw2elfwx74h5tgntuzs44gyfg"
+ ]
}
}
],
diff --git a/test/util/data/txcreatemultisig5.json b/test/util/data/txcreatemultisig5.json
new file mode 100644
index 0000000000..20e9bb077b
--- /dev/null
+++ b/test/util/data/txcreatemultisig5.json
@@ -0,0 +1,26 @@
+{
+ "txid": "813cf75e1f08debd242ef7c8192b7d478fb651355209369499a0de779ba7eb2f",
+ "hash": "813cf75e1f08debd242ef7c8192b7d478fb651355209369499a0de779ba7eb2f",
+ "version": 2,
+ "size": 42,
+ "vsize": 42,
+ "locktime": 0,
+ "vin": [
+ ],
+ "vout": [
+ {
+ "value": 1.00000000,
+ "n": 0,
+ "scriptPubKey": {
+ "asm": "OP_HASH160 a4051c02398868af83f28f083208fae99a769263 OP_EQUAL",
+ "hex": "a914a4051c02398868af83f28f083208fae99a76926387",
+ "reqSigs": 1,
+ "type": "scripthash",
+ "addresses": [
+ "3GeGs1eHUxPz5YyuFe9WPpXid2UsUb5Jos"
+ ]
+ }
+ }
+ ],
+ "hex": "02000000000100e1f5050000000017a914a4051c02398868af83f28f083208fae99a7692638700000000"
+}
diff --git a/test/util/data/txcreateoutpubkey2.json b/test/util/data/txcreateoutpubkey2.json
index 5144722230..4ba5dcb282 100644
--- a/test/util/data/txcreateoutpubkey2.json
+++ b/test/util/data/txcreateoutpubkey2.json
@@ -14,7 +14,11 @@
"scriptPubKey": {
"asm": "0 a2516e770582864a6a56ed21a102044e388c62e3",
"hex": "0014a2516e770582864a6a56ed21a102044e388c62e3",
- "type": "witness_v0_keyhash"
+ "reqSigs": 1,
+ "type": "witness_v0_keyhash",
+ "addresses": [
+ "bc1q5fgkuac9s2ry56jka5s6zqsyfcugcchry5cwu0"
+ ]
}
}
],
diff --git a/test/util/data/txcreatescript3.json b/test/util/data/txcreatescript3.json
index 980da2fb31..31b6459214 100644
--- a/test/util/data/txcreatescript3.json
+++ b/test/util/data/txcreatescript3.json
@@ -14,7 +14,11 @@
"scriptPubKey": {
"asm": "0 0bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad6",
"hex": "00200bfe935e70c321c7ca3afc75ce0d0ca2f98b5422e008bb31c00c6d7f1f1c0ad6",
- "type": "witness_v0_scripthash"
+ "reqSigs": 1,
+ "type": "witness_v0_scripthash",
+ "addresses": [
+ "bc1qp0lfxhnscvsu0j36l36uurgv5tuck4pzuqytkvwqp3kh78cupttqyf705v"
+ ]
}
}
],