diff options
Diffstat (limited to 'test')
44 files changed, 262 insertions, 116 deletions
diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py index e5db9e18c7..eee38ce648 100755 --- a/test/functional/feature_bip68_sequence.py +++ b/test/functional/feature_bip68_sequence.py @@ -129,7 +129,7 @@ class BIP68Test(BitcoinTestFramework): # Track whether any sequence locks used should fail should_pass = True - + # Track whether this transaction was built with sequence locks using_sequence_locks = False @@ -343,7 +343,7 @@ class BIP68Test(BitcoinTestFramework): tx2.rehash() self.nodes[0].sendrawtransaction(ToHex(tx2)) - + # Now make an invalid spend of tx2 according to BIP68 sequence_value = 100 # 100 block relative locktime diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index 181c7f3369..38b76239e5 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -1306,7 +1306,13 @@ class FullBlockTest(BitcoinTestFramework): self.nodes[0].disconnect_p2ps() self.nodes[0].add_p2p_connection(P2PDataStore()) network_thread_start() - self.nodes[0].p2p.wait_for_verack() + # We need to wait for the initial getheaders from the peer before we + # start populating our blockstore. If we don't, then we may run ahead + # to the next subtest before we receive the getheaders. We'd then send + # an INV for the next block and receive two getheaders - one for the + # IBD and one for the INV. We'd respond to both and could get + # unexpectedly disconnected if the DoS score for that error is 50. + self.nodes[0].p2p.wait_for_getheaders(timeout=5) def sync_blocks(self, blocks, success=True, reject_code=None, reject_reason=None, request_block=True, reconnect=False, timeout=60): """Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block. diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index a1d22191af..e9924451d1 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -29,8 +29,13 @@ class ConfArgsTest(BitcoinTestFramework): # Check that using non-existent datadir in conf file fails conf_file = os.path.join(default_data_dir, "bitcoin.conf") - with open(conf_file, 'a', encoding='utf8') as f: + + # datadir needs to be set before [regtest] section + conf_file_contents = open(conf_file, encoding='utf8').read() + with open(conf_file, 'w', encoding='utf8') as f: f.write("datadir=" + new_data_dir + "\n") + f.write(conf_file_contents) + self.nodes[0].assert_start_raises_init_error(['-conf=' + conf_file], 'Error reading configuration file: specified data directory "' + new_data_dir + '" does not exist.') # Create the directory and ensure the config file now works diff --git a/test/functional/feature_logging.py b/test/functional/feature_logging.py index 3c7aecf10a..166f8f8694 100755 --- a/test/functional/feature_logging.py +++ b/test/functional/feature_logging.py @@ -15,13 +15,17 @@ class LoggingTest(BitcoinTestFramework): self.num_nodes = 1 self.setup_clean_chain = True + def relative_log_path(self, name): + return os.path.join(self.nodes[0].datadir, "regtest", name) + def run_test(self): # test default log file name - assert os.path.isfile(os.path.join(self.nodes[0].datadir, "regtest", "debug.log")) + default_log_path = self.relative_log_path("debug.log") + assert os.path.isfile(default_log_path) # test alternative log file name in datadir self.restart_node(0, ["-debuglogfile=foo.log"]) - assert os.path.isfile(os.path.join(self.nodes[0].datadir, "regtest", "foo.log")) + assert os.path.isfile(self.relative_log_path("foo.log")) # test alternative log file name outside datadir tempname = os.path.join(self.options.tmpdir, "foo.log") @@ -29,7 +33,7 @@ class LoggingTest(BitcoinTestFramework): assert os.path.isfile(tempname) # check that invalid log (relative) will cause error - invdir = os.path.join(self.nodes[0].datadir, "regtest", "foo") + invdir = self.relative_log_path("foo") invalidname = os.path.join("foo", "foo.log") self.stop_node(0) exp_stderr = "Error: Could not open debug log file \S+$" @@ -55,6 +59,17 @@ class LoggingTest(BitcoinTestFramework): self.start_node(0, ["-debuglogfile=%s" % (invalidname)]) assert os.path.isfile(os.path.join(invdir, "foo.log")) + # check that -nodebuglogfile disables logging + self.stop_node(0) + os.unlink(default_log_path) + assert not os.path.isfile(default_log_path) + self.start_node(0, ["-nodebuglogfile"]) + assert not os.path.isfile(default_log_path) + + # just sanity check no crash here + self.stop_node(0) + self.start_node(0, ["-debuglogfile=%s" % os.devnull]) + if __name__ == '__main__': LoggingTest().main() diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py index ce6ec76c61..072ba6c7c7 100755 --- a/test/functional/feature_maxuploadtarget.py +++ b/test/functional/feature_maxuploadtarget.py @@ -30,7 +30,7 @@ class TestP2PConn(P2PInterface): self.block_receive_map[message.block.sha256] += 1 class MaxUploadTest(BitcoinTestFramework): - + def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py index 2eb1be47a5..60859de7a5 100755 --- a/test/functional/feature_proxy.py +++ b/test/functional/feature_proxy.py @@ -182,7 +182,7 @@ class ProxyTest(BitcoinTestFramework): assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr)) assert_equal(n1['onion']['proxy_randomize_credentials'], False) assert_equal(n1['onion']['reachable'], True) - + n2 = networks_dict(self.nodes[2].getnetworkinfo()) for net in ['ipv4','ipv6','onion']: assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr)) diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index fa1732c4c5..e835b9d777 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -150,19 +150,11 @@ class SegWitTest(BitcoinTestFramework): self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) #block 426 self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) #block 427 - # TODO: An old node would see these txs without witnesses and be able to mine them - - self.log.info("Verify unsigned bare witness txs in versionbits-setting blocks are valid before the fork") - self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][1], False) #block 428 - self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][1], False) #block 429 - self.log.info("Verify unsigned p2sh witness txs without a redeem script are invalid") self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V0][1], False) self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V1][1], False) - self.log.info("Verify unsigned p2sh witness txs with a redeem script in versionbits-settings blocks are valid before the fork") - self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, witness_script(False, self.pubkey[2])) #block 430 - self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False, witness_script(True, self.pubkey[2])) #block 431 + self.nodes[2].generate(4) # blocks 428-431 self.log.info("Verify previous witness txs skipped for mining can now be mined") assert_equal(len(self.nodes[2].getrawmempool()), 4) diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py index 2ee33aa869..a48939d2e0 100755 --- a/test/functional/interface_rest.py +++ b/test/functional/interface_rest.py @@ -186,10 +186,10 @@ class RESTTest (BitcoinTestFramework): self.test_rest_request("/getutxos/checkmempool", http_method='POST', req_type=ReqType.JSON, status=400, ret_type=RetType.OBJ) # Test limits - long_uri = '/'.join(["{}-{}".format(txid, n) for n in range(20)]) + long_uri = '/'.join(["{}-{}".format(txid, n_) for n_ in range(20)]) self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=400, ret_type=RetType.OBJ) - long_uri = '/'.join(['{}-{}'.format(txid, n) for n in range(15)]) + long_uri = '/'.join(['{}-{}'.format(txid, n_) for n_ in range(15)]) self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=200) self.nodes[0].generate(1) # generate block to not affect upcoming tests diff --git a/test/functional/p2p_mempool.py b/test/functional/p2p_mempool.py index 485a8af3d0..e54843b26f 100755 --- a/test/functional/p2p_mempool.py +++ b/test/functional/p2p_mempool.py @@ -30,6 +30,6 @@ class P2PMempoolTests(BitcoinTestFramework): #mininode must be disconnected at this point assert_equal(len(self.nodes[0].getpeerinfo()), 0) - + if __name__ == '__main__': P2PMempoolTests().main() diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index 5546bf6b29..4fecd4ffee 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -10,6 +10,7 @@ from test_framework.util import * from test_framework.script import * from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment, get_witness_script, WITNESS_COMMITMENT_HEADER from test_framework.key import CECKey, CPubKey +import math import time import random from binascii import hexlify @@ -47,7 +48,7 @@ def test_transaction_acceptance(rpc, p2p, tx, with_witness, accepted, reason=Non with mininode_lock: assert_equal(p2p.last_message["reject"].reason, reason) -def test_witness_block(rpc, p2p, block, accepted, with_witness=True): +def test_witness_block(rpc, p2p, block, accepted, with_witness=True, reason=None): """Send a block to the node and check that it's accepted - Submit the block over the p2p interface @@ -58,6 +59,10 @@ def test_witness_block(rpc, p2p, block, accepted, with_witness=True): p2p.send_message(msg_block(block)) p2p.sync_with_ping() assert_equal(rpc.getbestblockhash() == block.hash, accepted) + if (reason != None and not accepted): + # Check the rejection reason as well. + with mininode_lock: + assert_equal(p2p.last_message["reject"].reason, reason) class TestP2PConn(P2PInterface): def __init__(self): @@ -271,6 +276,80 @@ class SegWitTest(BitcoinTestFramework): self.utxo.pop(0) self.utxo.append(UTXO(tx4.sha256, 0, tx4.vout[0].nValue)) + # ~6 months after segwit activation, the SCRIPT_VERIFY_WITNESS flag was + # backdated so that it applies to all blocks, going back to the genesis + # block. + # + # Consequently, version 0 witness outputs are never spendable without + # witness, and so can't be spent before segwit activation (the point at which + # blocks are permitted to contain witnesses). + def test_v0_outputs_arent_spendable(self): + self.log.info("Testing that v0 witness program outputs aren't spendable before activation") + + assert len(self.utxo), "self.utxo is empty" + + # Create two outputs, a p2wsh and p2sh-p2wsh + witness_program = CScript([OP_TRUE]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + + p2sh_pubkey = hash160(scriptPubKey) + p2sh_scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL]) + + value = self.utxo[0].nValue // 3 + + tx = CTransaction() + tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b'')] + tx.vout = [CTxOut(value, scriptPubKey), CTxOut(value, p2sh_scriptPubKey)] + tx.vout.append(CTxOut(value, CScript([OP_TRUE]))) + tx.rehash() + txid = tx.sha256 + + # Add it to a block + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx]) + # Verify that segwit isn't activated. A block serialized with witness + # should be rejected prior to activation. + test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason = b'unexpected-witness') + # Now send the block without witness. It should be accepted + test_witness_block(self.nodes[0], self.test_node, block, accepted=True, with_witness=False) + + # Now try to spend the outputs. This should fail since SCRIPT_VERIFY_WITNESS is always enabled. + p2wsh_tx = CTransaction() + p2wsh_tx.vin = [CTxIn(COutPoint(txid, 0), b'')] + p2wsh_tx.vout = [CTxOut(value, CScript([OP_TRUE]))] + p2wsh_tx.wit.vtxinwit.append(CTxInWitness()) + p2wsh_tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])] + p2wsh_tx.rehash() + + p2sh_p2wsh_tx = CTransaction() + p2sh_p2wsh_tx.vin = [CTxIn(COutPoint(txid, 1), CScript([scriptPubKey]))] + p2sh_p2wsh_tx.vout = [CTxOut(value, CScript([OP_TRUE]))] + p2sh_p2wsh_tx.wit.vtxinwit.append(CTxInWitness()) + p2sh_p2wsh_tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])] + p2sh_p2wsh_tx.rehash() + + for tx in [p2wsh_tx, p2sh_p2wsh_tx]: + + block = self.build_next_block() + self.update_witness_block_with_transactions(block, [tx]) + + # When the block is serialized with a witness, the block will be rejected because witness + # data isn't allowed in blocks that don't commit to witness data. + test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason=b'unexpected-witness') + + # When the block is serialized without witness, validation fails because the transaction is + # invalid (transactions are always validated with SCRIPT_VERIFY_WITNESS so a segwit v0 transaction + # without a witness is invalid). + # Note: The reject reason for this failure could be + # 'block-validation-failed' (if script check threads > 1) or + # 'non-mandatory-script-verify-flag (Witness program was passed an + # empty witness)' (otherwise). + # TODO: support multiple acceptable reject reasons. + test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=False) + + self.utxo.pop(0) + self.utxo.append(UTXO(txid, 2, value)) # Mine enough blocks for segwit's vb state to be 'started'. def advance_to_segwit_started(self): @@ -450,7 +529,7 @@ class SegWitTest(BitcoinTestFramework): block = self.build_next_block() assert(len(self.utxo) > 0) - + # Create a P2WSH transaction. # The witness program will be a bunch of OP_2DROP's, followed by OP_TRUE. # This should give us plenty of room to tweak the spending tx's @@ -562,7 +641,7 @@ class SegWitTest(BitcoinTestFramework): self.log.info("Testing extra witness data in tx") assert(len(self.utxo) > 0) - + block = self.build_next_block() witness_program = CScript([OP_DROP, OP_TRUE]) @@ -730,7 +809,7 @@ class SegWitTest(BitcoinTestFramework): witness_program = CScript([OP_DROP, OP_TRUE]) witness_hash = sha256(witness_program) scriptPubKey = CScript([OP_0, witness_hash]) - + # Create a transaction that splits our utxo into many outputs tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) @@ -930,8 +1009,10 @@ class SegWitTest(BitcoinTestFramework): raw_tx = self.nodes[0].getrawtransaction(tx3.hash, 1) assert_equal(int(raw_tx["hash"], 16), tx3.calc_sha256(True)) assert_equal(raw_tx["size"], len(tx3.serialize_with_witness())) - vsize = (len(tx3.serialize_with_witness()) + 3*len(tx3.serialize_without_witness()) + 3) / 4 + weight = len(tx3.serialize_with_witness()) + 3*len(tx3.serialize_without_witness()) + vsize = math.ceil(weight / 4) assert_equal(raw_tx["vsize"], vsize) + assert_equal(raw_tx["weight"], weight) assert_equal(len(raw_tx["vin"][0]["txinwitness"]), 1) assert_equal(raw_tx["vin"][0]["txinwitness"][0], hexlify(witness_program).decode('ascii')) assert(vsize != raw_tx["size"]) @@ -1476,9 +1557,10 @@ class SegWitTest(BitcoinTestFramework): block = self.build_next_block() self.update_witness_block_with_transactions(block, [spend_tx]) - # If we're before activation, then sending this without witnesses - # should be valid. If we're after activation, then sending this with - # witnesses should be valid. + # If we're after activation, then sending this with witnesses should be valid. + # This no longer works before activation, because SCRIPT_VERIFY_WITNESS + # is always set. + # TODO: rewrite this test to make clear that it only works after activation. if segwit_activated: test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True) else: @@ -1897,6 +1979,7 @@ class SegWitTest(BitcoinTestFramework): self.test_witness_services() # Verifies NODE_WITNESS self.test_non_witness_transaction() # non-witness tx's are accepted self.test_unnecessary_witness_before_segwit_activation() + self.test_v0_outputs_arent_spendable() self.test_block_relay(segwit_activated=False) # Advance to segwit being 'started' @@ -1914,7 +1997,6 @@ class SegWitTest(BitcoinTestFramework): self.test_unnecessary_witness_before_segwit_activation() self.test_witness_tx_relay_before_segwit_activation() self.test_block_relay(segwit_activated=False) - self.test_p2sh_witness(segwit_activated=False) self.test_standardness_v0(segwit_activated=False) sync_blocks(self.nodes) diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py index 43982cd09a..5c2b1815e5 100644 --- a/test/functional/test_framework/blocktools.py +++ b/test/functional/test_framework/blocktools.py @@ -10,7 +10,24 @@ from .address import ( script_to_p2sh_p2wsh, script_to_p2wsh, ) -from .mininode import * +from .messages import ( + CBlock, + COIN, + COutPoint, + CTransaction, + CTxIn, + CTxInWitness, + CTxOut, + FromHex, + ToHex, + bytes_to_hex_str, + hash256, + hex_str_to_bytes, + ser_string, + ser_uint256, + sha256, + uint256_from_str, +) from .script import ( CScript, OP_0, @@ -23,34 +40,34 @@ from .script import ( ) from .util import assert_equal -# Create a block (with regtest difficulty) -def create_block(hashprev, coinbase, nTime=None): +# From BIP141 +WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed" + +def create_block(hashprev, coinbase, ntime=None): + """Create a block (with regtest difficulty).""" block = CBlock() - if nTime is None: + if ntime is None: import time - block.nTime = int(time.time()+600) + block.nTime = int(time.time() + 600) else: - block.nTime = nTime + block.nTime = ntime block.hashPrevBlock = hashprev - block.nBits = 0x207fffff # Will break after a difficulty adjustment... + block.nBits = 0x207fffff # difficulty retargeting is disabled in REGTEST chainparams block.vtx.append(coinbase) block.hashMerkleRoot = block.calc_merkle_root() block.calc_sha256() return block -# From BIP141 -WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed" - - def get_witness_script(witness_root, witness_nonce): - witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce))) + witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root) + ser_uint256(witness_nonce))) output_data = WITNESS_COMMITMENT_HEADER + ser_uint256(witness_commitment) return CScript([OP_RETURN, output_data]) - -# According to BIP141, blocks with witness rules active must commit to the -# hash of all in-block transactions including witness. def add_witness_commitment(block, nonce=0): + """Add a witness commitment to the block's coinbase transaction. + + According to BIP141, blocks with witness rules active must commit to the + hash of all in-block transactions including witness.""" # First calculate the merkle root of the block's # transactions, with witnesses. witness_nonce = nonce @@ -65,7 +82,6 @@ def add_witness_commitment(block, nonce=0): block.hashMerkleRoot = block.calc_merkle_root() block.rehash() - def serialize_script_num(value): r = bytearray(0) if value == 0: @@ -81,55 +97,59 @@ def serialize_script_num(value): r[-1] |= 0x80 return r -# Create a coinbase transaction, assuming no miner fees. -# If pubkey is passed in, the coinbase output will be a P2PK output; -# otherwise an anyone-can-spend output. -def create_coinbase(height, pubkey = None): +def create_coinbase(height, pubkey=None): + """Create a coinbase transaction, assuming no miner fees. + + If pubkey is passed in, the coinbase output will be a P2PK output; + otherwise an anyone-can-spend output.""" coinbase = CTransaction() - coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff), - ser_string(serialize_script_num(height)), 0xffffffff)) + coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff), + ser_string(serialize_script_num(height)), 0xffffffff)) coinbaseoutput = CTxOut() coinbaseoutput.nValue = 50 * COIN - halvings = int(height/150) # regtest + halvings = int(height / 150) # regtest coinbaseoutput.nValue >>= halvings - if (pubkey != None): + if (pubkey is not None): coinbaseoutput.scriptPubKey = CScript([pubkey, OP_CHECKSIG]) else: coinbaseoutput.scriptPubKey = CScript([OP_TRUE]) - coinbase.vout = [ coinbaseoutput ] + coinbase.vout = [coinbaseoutput] coinbase.calc_sha256() return coinbase -# Create a transaction. -# If the scriptPubKey is not specified, make it anyone-can-spend. -def create_transaction(prevtx, n, sig, value, scriptPubKey=CScript()): +def create_transaction(prevtx, n, sig, value, script_pub_key=CScript()): + """Create a transaction. + + If the script_pub_key is not specified, make it anyone-can-spend.""" tx = CTransaction() assert(n < len(prevtx.vout)) tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff)) - tx.vout.append(CTxOut(value, scriptPubKey)) + tx.vout.append(CTxOut(value, script_pub_key)) tx.calc_sha256() return tx -def get_legacy_sigopcount_block(block, fAccurate=True): +def get_legacy_sigopcount_block(block, accurate=True): count = 0 for tx in block.vtx: - count += get_legacy_sigopcount_tx(tx, fAccurate) + count += get_legacy_sigopcount_tx(tx, accurate) return count -def get_legacy_sigopcount_tx(tx, fAccurate=True): +def get_legacy_sigopcount_tx(tx, accurate=True): count = 0 for i in tx.vout: - count += i.scriptPubKey.GetSigOpCount(fAccurate) + count += i.scriptPubKey.GetSigOpCount(accurate) for j in tx.vin: # scriptSig might be of type bytes, so convert to CScript for the moment - count += CScript(j.scriptSig).GetSigOpCount(fAccurate) + count += CScript(j.scriptSig).GetSigOpCount(accurate) return count -# Create a scriptPubKey corresponding to either a P2WPKH output for the -# given pubkey, or a P2WSH output of a 1-of-1 multisig for the given -# pubkey. Returns the hex encoding of the scriptPubKey. def witness_script(use_p2wsh, pubkey): - if (use_p2wsh == False): + """Create a scriptPubKey for a pay-to-wtiness TxOut. + + This is either a P2WPKH output for the given pubkey, or a P2WSH output of a + 1-of-1 multisig for the given pubkey. Returns the hex encoding of the + scriptPubKey.""" + if not use_p2wsh: # P2WPKH instead pubkeyhash = hash160(hex_str_to_bytes(pubkey)) pkscript = CScript([OP_0, pubkeyhash]) @@ -140,9 +160,10 @@ def witness_script(use_p2wsh, pubkey): pkscript = CScript([OP_0, scripthash]) return bytes_to_hex_str(pkscript) -# Return a transaction (in hex) that spends the given utxo to a segwit output, -# optionally wrapping the segwit output using P2SH. def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount): + """Return a transaction (in hex) that spends the given utxo to a segwit output. + + Optionally wrap the segwit output using P2SH.""" 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) @@ -152,12 +173,13 @@ def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount): assert_equal(node.getaddressinfo(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; -# encode_p2sh determines whether to wrap in P2SH. -# 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=""): + """Create a transaction spending a given utxo to a segwit output. + + The output corresponds to the given pubkey: use_p2wsh determines whether to + use P2WPKH or P2WSH; encode_p2sh determines whether to wrap in P2SH. + sign=True will have the given node sign the transaction. + insert_redeem_script will be added to the scriptSig, if given.""" tx_to_witness = create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount) if (sign): signed = node.signrawtransactionwithwallet(tx_to_witness) diff --git a/test/functional/test_framework/key.py b/test/functional/test_framework/key.py index aa91fb5b0d..1b3e510dc4 100644 --- a/test/functional/test_framework/key.py +++ b/test/functional/test_framework/key.py @@ -10,7 +10,6 @@ This file is modified from python-bitcoinlib. import ctypes import ctypes.util import hashlib -import sys ssl = ctypes.cdll.LoadLibrary(ctypes.util.find_library ('ssl') or 'libeay32') @@ -223,10 +222,5 @@ class CPubKey(bytes): return repr(self) def __repr__(self): - # Always have represent as b'<secret>' so test cases don't have to - # change for py2/3 - if sys.version > '3': - return '%s(%s)' % (self.__class__.__name__, super(CPubKey, self).__repr__()) - else: - return '%s(b%s)' % (self.__class__.__name__, super(CPubKey, self).__repr__()) + return '%s(%s)' % (self.__class__.__name__, super(CPubKey, self).__repr__()) diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py index 6fe0b445da..44650d7584 100644 --- a/test/functional/test_framework/script.py +++ b/test/functional/test_framework/script.py @@ -10,15 +10,6 @@ This file is modified from python-bitcoinlib. from .mininode import CTransaction, CTxOut, sha256, hash256, uint256_from_str, ser_uint256, ser_string from binascii import hexlify import hashlib - -import sys -bchr = chr -bord = ord -if sys.version > '3': - long = int - bchr = lambda x: bytes([x]) - bord = lambda x: x - import struct from .bignum import bn2vch @@ -40,9 +31,9 @@ class CScriptOp(int): def encode_op_pushdata(d): """Encode a PUSHDATA op, returning bytes""" if len(d) < 0x4c: - return b'' + bchr(len(d)) + d # OP_PUSHDATA + return b'' + bytes([len(d)]) + d # OP_PUSHDATA elif len(d) <= 0xff: - return b'\x4c' + bchr(len(d)) + d # OP_PUSHDATA1 + return b'\x4c' + bytes([len(d)]) + d # OP_PUSHDATA1 elif len(d) <= 0xffff: return b'\x4d' + struct.pack(b'<H', len(d)) + d # OP_PUSHDATA2 elif len(d) <= 0xffffffff: @@ -388,7 +379,7 @@ class CScriptNum(): r.append(0x80 if neg else 0) elif neg: r[-1] |= 0x80 - return bytes(bchr(len(r)) + r) + return bytes([len(r)]) + r class CScript(bytes): @@ -405,17 +396,17 @@ class CScript(bytes): def __coerce_instance(cls, other): # Coerce other into bytes if isinstance(other, CScriptOp): - other = bchr(other) + other = bytes([other]) elif isinstance(other, CScriptNum): if (other.value == 0): - other = bchr(CScriptOp(OP_0)) + other = bytes([CScriptOp(OP_0)]) else: other = CScriptNum.encode(other) elif isinstance(other, int): if 0 <= other <= 16: - other = bytes(bchr(CScriptOp.encode_op_n(other))) + other = bytes([CScriptOp.encode_op_n(other)]) elif other == -1: - other = bytes(bchr(OP_1NEGATE)) + other = bytes([OP_1NEGATE]) else: other = CScriptOp.encode_op_pushdata(bn2vch(other)) elif isinstance(other, (bytes, bytearray)): @@ -458,7 +449,7 @@ class CScript(bytes): i = 0 while i < len(self): sop_idx = i - opcode = bord(self[i]) + opcode = self[i] i += 1 if opcode > OP_PUSHDATA4: @@ -474,21 +465,21 @@ class CScript(bytes): pushdata_type = 'PUSHDATA1' if i >= len(self): raise CScriptInvalidError('PUSHDATA1: missing data length') - datasize = bord(self[i]) + datasize = self[i] i += 1 elif opcode == OP_PUSHDATA2: pushdata_type = 'PUSHDATA2' if i + 1 >= len(self): raise CScriptInvalidError('PUSHDATA2: missing data length') - datasize = bord(self[i]) + (bord(self[i+1]) << 8) + datasize = self[i] + (self[i+1] << 8) i += 2 elif opcode == OP_PUSHDATA4: pushdata_type = 'PUSHDATA4' if i + 3 >= len(self): raise CScriptInvalidError('PUSHDATA4: missing data length') - datasize = bord(self[i]) + (bord(self[i+1]) << 8) + (bord(self[i+2]) << 16) + (bord(self[i+3]) << 24) + datasize = self[i] + (self[i+1] << 8) + (self[i+2] << 16) + (self[i+3] << 24) i += 4 else: diff --git a/test/functional/test_framework/socks5.py b/test/functional/test_framework/socks5.py index 4721809a3b..581de0ed5d 100644 --- a/test/functional/test_framework/socks5.py +++ b/test/functional/test_framework/socks5.py @@ -4,12 +4,14 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Dummy Socks5 server for testing.""" -import socket, threading, queue +import socket +import threading +import queue import logging logger = logging.getLogger("TestFramework.socks5") -### Protocol constants +# Protocol constants class Command: CONNECT = 0x01 @@ -18,7 +20,7 @@ class AddressType: DOMAINNAME = 0x03 IPV6 = 0x04 -### Utility functions +# Utility functions def recvall(s, n): """Receive n bytes from a socket, or fail.""" rv = bytearray() @@ -30,7 +32,7 @@ def recvall(s, n): n -= len(d) return rv -### Implementation classes +# Implementation classes class Socks5Configuration(): """Proxy configuration.""" def __init__(self): @@ -141,7 +143,7 @@ class Socks5Server(): thread = threading.Thread(None, conn.handle) thread.daemon = True thread.start() - + def start(self): assert(not self.running) self.running = True diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 0f0d031f35..04d1de8d91 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -78,7 +78,17 @@ class TestNode(): # For those callers that need more flexibility, they can just set the args property directly. # Note that common args are set in the config file (see initialize_datadir) self.extra_args = extra_args - self.args = [self.binary, "-datadir=" + self.datadir, "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(mocktime), "-uacomment=testnode%d" % i] + self.args = [ + self.binary, + "-datadir=" + self.datadir, + "-logtimemicros", + "-debug", + "-debugexclude=libevent", + "-debugexclude=leveldb", + "-mocktime=" + str(mocktime), + "-uacomment=testnode%d" % i, + "-noprinttoconsole" + ] self.cli = TestNodeCLI(os.getenv("BITCOINCLI", "bitcoin-cli"), self.datadir) self.use_cli = use_cli diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index f22322fbbc..4ec3175cd6 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -294,6 +294,7 @@ def initialize_datadir(dirname, n): os.makedirs(datadir) with open(os.path.join(datadir, "bitcoin.conf"), 'w', encoding='utf8') as f: f.write("regtest=1\n") + f.write("[regtest]\n") f.write("port=" + str(p2p_port(n)) + "\n") f.write("rpcport=" + str(rpc_port(n)) + "\n") f.write("server=1\n") diff --git a/test/functional/wallet_importprunedfunds.py b/test/functional/wallet_importprunedfunds.py index 4d349db23f..5f5bfcf683 100755 --- a/test/functional/wallet_importprunedfunds.py +++ b/test/functional/wallet_importprunedfunds.py @@ -16,7 +16,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework): self.nodes[0].generate(101) self.sync_all() - + # address address1 = self.nodes[0].getnewaddress() # pubkey diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py index 9825e4d894..505014e48f 100755 --- a/test/functional/wallet_keypool.py +++ b/test/functional/wallet_keypool.py @@ -17,7 +17,7 @@ class KeyPoolTest(BitcoinTestFramework): addr_before_encrypting_data = nodes[0].getaddressinfo(addr_before_encrypting) wallet_info_old = nodes[0].getwalletinfo() assert(addr_before_encrypting_data['hdmasterkeyid'] == wallet_info_old['hdmasterkeyid']) - + # Encrypt wallet and wait to terminate nodes[0].node_encrypt_wallet('test') # Restart node 0 diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index d742ec4618..7577c4a0d2 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -92,7 +92,8 @@ class TxnMallTest(BitcoinTestFramework): # Node0's balance should be starting balance, plus 50BTC for another # matured block, minus tx1 and tx2 amounts, and minus transaction fees: expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"] - if self.options.mine_block: expected += 50 + if self.options.mine_block: + expected += 50 expected += tx1["amount"] + tx1["fee"] expected += tx2["amount"] + tx2["fee"] assert_equal(self.nodes[0].getbalance(), expected) @@ -131,7 +132,7 @@ class TxnMallTest(BitcoinTestFramework): tx1 = self.nodes[0].gettransaction(txid1) tx1_clone = self.nodes[0].gettransaction(txid1_clone) tx2 = self.nodes[0].gettransaction(txid2) - + # Verify expected confirmations assert_equal(tx1["confirmations"], -2) assert_equal(tx1_clone["confirmations"], 2) diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py index f16756eeaa..8419d6b545 100755 --- a/test/functional/wallet_txn_doublespend.py +++ b/test/functional/wallet_txn_doublespend.py @@ -27,7 +27,7 @@ class TxnMallTest(BitcoinTestFramework): for i in range(4): assert_equal(self.nodes[i].getbalance(), starting_balance) self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress! - + # Assign coins to foo and bar accounts: node0_address_foo = self.nodes[0].getnewaddress("foo") fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, 1219) @@ -64,7 +64,7 @@ class TxnMallTest(BitcoinTestFramework): # Create two spends using 1 50 BTC coin each txid1 = self.nodes[0].sendfrom("foo", node1_address, 40, 0) txid2 = self.nodes[0].sendfrom("bar", node1_address, 20, 0) - + # Have node0 mine a block: if (self.options.mine_block): self.nodes[0].generate(1) @@ -76,7 +76,8 @@ class TxnMallTest(BitcoinTestFramework): # Node0's balance should be starting balance, plus 50BTC for another # matured block, minus 40, minus 20, and minus transaction fees: expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"] - if self.options.mine_block: expected += 50 + if self.options.mine_block: + expected += 50 expected += tx1["amount"] + tx1["fee"] expected += tx2["amount"] + tx2["fee"] assert_equal(self.nodes[0].getbalance(), expected) @@ -93,7 +94,7 @@ class TxnMallTest(BitcoinTestFramework): else: assert_equal(tx1["confirmations"], 0) assert_equal(tx2["confirmations"], 0) - + # Now give doublespend and its parents to miner: self.nodes[2].sendrawtransaction(fund_foo_tx["hex"]) self.nodes[2].sendrawtransaction(fund_bar_tx["hex"]) diff --git a/test/util/data/blanktxv1.json b/test/util/data/blanktxv1.json index 9fe2de649b..3d5a1cccae 100644 --- a/test/util/data/blanktxv1.json +++ b/test/util/data/blanktxv1.json @@ -4,6 +4,7 @@ "version": 1, "size": 10, "vsize": 10, + "weight": 40, "locktime": 0, "vin": [ ], diff --git a/test/util/data/blanktxv2.json b/test/util/data/blanktxv2.json index e97626e421..8374a34adc 100644 --- a/test/util/data/blanktxv2.json +++ b/test/util/data/blanktxv2.json @@ -4,6 +4,7 @@ "version": 2, "size": 10, "vsize": 10, + "weight": 40, "locktime": 0, "vin": [ ], diff --git a/test/util/data/tt-delin1-out.json b/test/util/data/tt-delin1-out.json index de647f98b6..9fc2ddc376 100644 --- a/test/util/data/tt-delin1-out.json +++ b/test/util/data/tt-delin1-out.json @@ -4,6 +4,7 @@ "version": 1, "size": 3040, "vsize": 3040, + "weight": 12160, "locktime": 0, "vin": [ { diff --git a/test/util/data/tt-delout1-out.json b/test/util/data/tt-delout1-out.json index 067ffe74e7..922d048900 100644 --- a/test/util/data/tt-delout1-out.json +++ b/test/util/data/tt-delout1-out.json @@ -4,6 +4,7 @@ "version": 1, "size": 3155, "vsize": 3155, + "weight": 12620, "locktime": 0, "vin": [ { diff --git a/test/util/data/tt-locktime317000-out.json b/test/util/data/tt-locktime317000-out.json index af7903d1dd..c97206f1ea 100644 --- a/test/util/data/tt-locktime317000-out.json +++ b/test/util/data/tt-locktime317000-out.json @@ -4,6 +4,7 @@ "version": 1, "size": 3189, "vsize": 3189, + "weight": 12756, "locktime": 317000, "vin": [ { diff --git a/test/util/data/txcreate1.json b/test/util/data/txcreate1.json index 83a86649e0..ca9eacd546 100644 --- a/test/util/data/txcreate1.json +++ b/test/util/data/txcreate1.json @@ -4,6 +4,7 @@ "version": 2, "size": 201, "vsize": 201, + "weight": 804, "locktime": 0, "vin": [ { diff --git a/test/util/data/txcreate2.json b/test/util/data/txcreate2.json index cca00f752b..ee9b9c3c17 100644 --- a/test/util/data/txcreate2.json +++ b/test/util/data/txcreate2.json @@ -4,6 +4,7 @@ "version": 2, "size": 19, "vsize": 19, + "weight": 76, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatedata1.json b/test/util/data/txcreatedata1.json index 15a4246ae5..39909c2e3f 100644 --- a/test/util/data/txcreatedata1.json +++ b/test/util/data/txcreatedata1.json @@ -4,6 +4,7 @@ "version": 1, "size": 176, "vsize": 176, + "weight": 704, "locktime": 0, "vin": [ { diff --git a/test/util/data/txcreatedata2.json b/test/util/data/txcreatedata2.json index cb93c27971..2958006e58 100644 --- a/test/util/data/txcreatedata2.json +++ b/test/util/data/txcreatedata2.json @@ -4,6 +4,7 @@ "version": 2, "size": 176, "vsize": 176, + "weight": 704, "locktime": 0, "vin": [ { diff --git a/test/util/data/txcreatedata_seq0.json b/test/util/data/txcreatedata_seq0.json index 4b5a7cab4a..a6656b5ad5 100644 --- a/test/util/data/txcreatedata_seq0.json +++ b/test/util/data/txcreatedata_seq0.json @@ -4,6 +4,7 @@ "version": 2, "size": 85, "vsize": 85, + "weight": 340, "locktime": 0, "vin": [ { diff --git a/test/util/data/txcreatedata_seq1.json b/test/util/data/txcreatedata_seq1.json index dea48ba373..e5980427b1 100644 --- a/test/util/data/txcreatedata_seq1.json +++ b/test/util/data/txcreatedata_seq1.json @@ -4,6 +4,7 @@ "version": 1, "size": 126, "vsize": 126, + "weight": 504, "locktime": 0, "vin": [ { diff --git a/test/util/data/txcreatemultisig1.json b/test/util/data/txcreatemultisig1.json index 72e20c8691..c32e755db1 100644 --- a/test/util/data/txcreatemultisig1.json +++ b/test/util/data/txcreatemultisig1.json @@ -4,6 +4,7 @@ "version": 1, "size": 124, "vsize": 124, + "weight": 496, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatemultisig2.json b/test/util/data/txcreatemultisig2.json index 7d94ce7396..f97d265894 100644 --- a/test/util/data/txcreatemultisig2.json +++ b/test/util/data/txcreatemultisig2.json @@ -4,6 +4,7 @@ "version": 1, "size": 42, "vsize": 42, + "weight": 168, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatemultisig3.json b/test/util/data/txcreatemultisig3.json index 6c5b49d876..b355d7b191 100644 --- a/test/util/data/txcreatemultisig3.json +++ b/test/util/data/txcreatemultisig3.json @@ -4,6 +4,7 @@ "version": 1, "size": 53, "vsize": 53, + "weight": 212, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatemultisig4.json b/test/util/data/txcreatemultisig4.json index 9a5d2f4a06..a00dbe3f5d 100644 --- a/test/util/data/txcreatemultisig4.json +++ b/test/util/data/txcreatemultisig4.json @@ -4,6 +4,7 @@ "version": 1, "size": 42, "vsize": 42, + "weight": 168, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatemultisig5.json b/test/util/data/txcreatemultisig5.json index 20e9bb077b..ea07822ddd 100644 --- a/test/util/data/txcreatemultisig5.json +++ b/test/util/data/txcreatemultisig5.json @@ -4,6 +4,7 @@ "version": 2, "size": 42, "vsize": 42, + "weight": 168, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreateoutpubkey1.json b/test/util/data/txcreateoutpubkey1.json index 2704ed7673..32097b3ebe 100644 --- a/test/util/data/txcreateoutpubkey1.json +++ b/test/util/data/txcreateoutpubkey1.json @@ -4,6 +4,7 @@ "version": 1, "size": 54, "vsize": 54, + "weight": 216, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreateoutpubkey2.json b/test/util/data/txcreateoutpubkey2.json index 4ba5dcb282..c0ee181ede 100644 --- a/test/util/data/txcreateoutpubkey2.json +++ b/test/util/data/txcreateoutpubkey2.json @@ -4,6 +4,7 @@ "version": 1, "size": 41, "vsize": 41, + "weight": 164, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreateoutpubkey3.json b/test/util/data/txcreateoutpubkey3.json index 0a5d489e15..4d904df3c8 100644 --- a/test/util/data/txcreateoutpubkey3.json +++ b/test/util/data/txcreateoutpubkey3.json @@ -4,6 +4,7 @@ "version": 1, "size": 42, "vsize": 42, + "weight": 168, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatescript1.json b/test/util/data/txcreatescript1.json index 5072452fed..af1c4c35e2 100644 --- a/test/util/data/txcreatescript1.json +++ b/test/util/data/txcreatescript1.json @@ -4,6 +4,7 @@ "version": 1, "size": 20, "vsize": 20, + "weight": 80, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatescript2.json b/test/util/data/txcreatescript2.json index 94b669ffb6..32dd644579 100644 --- a/test/util/data/txcreatescript2.json +++ b/test/util/data/txcreatescript2.json @@ -4,6 +4,7 @@ "version": 1, "size": 42, "vsize": 42, + "weight": 168, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatescript3.json b/test/util/data/txcreatescript3.json index 31b6459214..b9192d9a82 100644 --- a/test/util/data/txcreatescript3.json +++ b/test/util/data/txcreatescript3.json @@ -4,6 +4,7 @@ "version": 1, "size": 53, "vsize": 53, + "weight": 212, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatescript4.json b/test/util/data/txcreatescript4.json index eecdf858b7..2271ecfa0a 100644 --- a/test/util/data/txcreatescript4.json +++ b/test/util/data/txcreatescript4.json @@ -4,6 +4,7 @@ "version": 1, "size": 42, "vsize": 42, + "weight": 168, "locktime": 0, "vin": [ ], diff --git a/test/util/data/txcreatesignv1.json b/test/util/data/txcreatesignv1.json index 92a3f76a07..64e5137f4b 100644 --- a/test/util/data/txcreatesignv1.json +++ b/test/util/data/txcreatesignv1.json @@ -4,6 +4,7 @@ "version": 1, "size": 224, "vsize": 224, + "weight": 896, "locktime": 0, "vin": [ { |