diff options
Diffstat (limited to 'qa')
-rwxr-xr-x | qa/pull-tester/rpc-tests.py | 1 | ||||
-rwxr-xr-x | qa/rpc-tests/keypool.py | 10 | ||||
-rwxr-xr-x | qa/rpc-tests/p2p-segwit.py | 78 | ||||
-rwxr-xr-x | qa/rpc-tests/wallet-dump.py | 120 |
4 files changed, 209 insertions, 0 deletions
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index 84ab9d92c5..e3921cfbed 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -107,6 +107,7 @@ testScripts = [ 'bip68-112-113-p2p.py', 'wallet.py', 'wallet-hd.py', + 'wallet-dump.py', 'listtransactions.py', 'receivedby.py', 'mempool_resurrect_test.py', diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index c75303ecbf..fa39476568 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -12,6 +12,11 @@ class KeyPoolTest(BitcoinTestFramework): def run_test(self): nodes = self.nodes + addr_before_encrypting = nodes[0].getnewaddress() + addr_before_encrypting_data = nodes[0].validateaddress(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].encryptwallet('test') bitcoind_processes[0].wait() @@ -19,6 +24,11 @@ class KeyPoolTest(BitcoinTestFramework): nodes[0] = start_node(0, self.options.tmpdir) # Keep creating keys addr = nodes[0].getnewaddress() + addr_data = nodes[0].validateaddress(addr) + wallet_info = nodes[0].getwalletinfo() + assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['hdmasterkeyid']) + assert(addr_data['hdmasterkeyid'] == wallet_info['hdmasterkeyid']) + try: addr = nodes[0].getnewaddress() raise AssertionError('Keypool should be exhausted after one address') diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index fa2c5d1f05..cd02692b1e 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -1086,6 +1086,82 @@ class SegWitTest(BitcoinTestFramework): self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0]) assert(block4.sha256 not in self.old_node.getdataset) + # V0 segwit outputs should be standard after activation, but not before. + def test_standardness_v0(self, segwit_activated): + print("\tTesting standardness of v0 outputs (%s activation)" % ("after" if segwit_activated else "before")) + assert(len(self.utxo)) + + witness_program = CScript([OP_TRUE]) + witness_hash = sha256(witness_program) + scriptPubKey = CScript([OP_0, witness_hash]) + + p2sh_pubkey = hash160(witness_program) + p2sh_scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL]) + + # First prepare a p2sh output (so that spending it will pass standardness) + p2sh_tx = CTransaction() + p2sh_tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")] + p2sh_tx.vout = [CTxOut(self.utxo[0].nValue-1000, p2sh_scriptPubKey)] + p2sh_tx.rehash() + + # Mine it on test_node to create the confirmed output. + self.test_node.test_transaction_acceptance(p2sh_tx, with_witness=True, accepted=True) + self.nodes[0].generate(1) + sync_blocks(self.nodes) + + # Now test standardness of v0 P2WSH outputs. + # Start by creating a transaction with two outputs. + tx = CTransaction() + tx.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))] + tx.vout = [CTxOut(p2sh_tx.vout[0].nValue-10000, scriptPubKey)] + tx.vout.append(CTxOut(8000, scriptPubKey)) # Might burn this later + tx.rehash() + + self.std_node.test_transaction_acceptance(tx, with_witness=True, accepted=segwit_activated) + + # Now create something that looks like a P2PKH output. This won't be spendable. + scriptPubKey = CScript([OP_0, hash160(witness_hash)]) + tx2 = CTransaction() + if segwit_activated: + # if tx was accepted, then we spend the second output. + tx2.vin = [CTxIn(COutPoint(tx.sha256, 1), b"")] + tx2.vout = [CTxOut(7000, scriptPubKey)] + tx2.wit.vtxinwit.append(CTxInWitness()) + tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program] + else: + # if tx wasn't accepted, we just re-spend the p2sh output we started with. + tx2.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))] + tx2.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, scriptPubKey)] + tx2.rehash() + + self.std_node.test_transaction_acceptance(tx2, with_witness=True, accepted=segwit_activated) + + # Now update self.utxo for later tests. + tx3 = CTransaction() + if segwit_activated: + # tx and tx2 were both accepted. Don't bother trying to reclaim the + # P2PKH output; just send tx's first output back to an anyone-can-spend. + sync_mempools(self.nodes) + tx3.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")] + tx3.vout = [CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))] + tx3.wit.vtxinwit.append(CTxInWitness()) + tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program] + tx3.rehash() + self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True) + else: + # tx and tx2 didn't go anywhere; just clean up the p2sh_tx output. + tx3.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))] + tx3.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, witness_program)] + tx3.rehash() + self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True) + + self.nodes[0].generate(1) + sync_blocks(self.nodes) + self.utxo.pop(0) + self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue)) + assert_equal(len(self.nodes[1].getrawmempool()), 0) + + # Verify that future segwit upgraded transactions are non-standard, # but valid in blocks. Can run this before and after segwit activation. def test_segwit_versions(self): @@ -1658,6 +1734,7 @@ class SegWitTest(BitcoinTestFramework): 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) @@ -1679,6 +1756,7 @@ class SegWitTest(BitcoinTestFramework): self.test_witness_input_length() self.test_block_relay(segwit_activated=True) self.test_tx_relay_after_segwit_activation() + self.test_standardness_v0(segwit_activated=True) self.test_segwit_versions() self.test_premature_coinbase_witness_spend() self.test_signature_version_1() diff --git a/qa/rpc-tests/wallet-dump.py b/qa/rpc-tests/wallet-dump.py new file mode 100755 index 0000000000..dd675f57fc --- /dev/null +++ b/qa/rpc-tests/wallet-dump.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import os +import shutil + + +class WalletDumpTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.setup_clean_chain = False + self.num_nodes = 1 + + def setup_network(self, split=False): + extra_args = [["-keypool=100"]] + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + + def run_test (self): + tmpdir = self.options.tmpdir + + #generate 20 addresses to compare against the dump + test_addr_count = 20 + addrs = [] + for i in range(0,test_addr_count): + addr = self.nodes[0].getnewaddress() + vaddr= self.nodes[0].validateaddress(addr) #required to get hd keypath + addrs.append(vaddr) + + # dump unencrypted wallet + self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump") + + #open file + inputfile = open(tmpdir + "/node0/wallet.unencrypted.dump") + found_addr = 0 + found_addr_chg = 0 + found_addr_rsv = 0 + hdmasteraddr = "" + for line in inputfile: + #only read non comment lines + if line[0] != "#" and len(line) > 10: + #split out some data + keyLabel, comment = line.split("#") + key = keyLabel.split(" ")[0] + keytype = keyLabel.split(" ")[2] + if len(comment) > 1: + addrKeypath = comment.split(" addr=")[1] + addr = addrKeypath.split(" ")[0] + keypath = "" + if keytype != "hdmaster=1": + keypath = addrKeypath.rstrip().split("hdkeypath=")[1] + else: + #keep hd master for later comp. + hdmasteraddr = addr + + #count key types + for addrObj in addrs: + if (addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label="): + found_addr+=1 + break + elif (keytype == "change=1"): + found_addr_chg+=1 + break + elif (keytype == "reserve=1"): + found_addr_rsv+=1 + break + assert(found_addr == test_addr_count) #all keys must be in the dump + assert(found_addr_chg == 50) #50 blocks where mined + assert(found_addr_rsv == 100) #100 reserve keys (keypool) + + #encrypt wallet, restart, unlock and dump + self.nodes[0].encryptwallet('test') + bitcoind_processes[0].wait() + self.nodes[0] = start_node(0, self.options.tmpdir) + self.nodes[0].walletpassphrase('test', 10) + self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump") + + #open dump done with an encrypted wallet + inputfile = open(tmpdir + "/node0/wallet.encrypted.dump") + found_addr = 0 + found_addr_chg = 0 + found_addr_rsv = 0 + for line in inputfile: + if line[0] != "#" and len(line) > 10: + keyLabel, comment = line.split("#") + key = keyLabel.split(" ")[0] + keytype = keyLabel.split(" ")[2] + if len(comment) > 1: + addrKeypath = comment.split(" addr=")[1] + addr = addrKeypath.split(" ")[0] + keypath = "" + if keytype != "hdmaster=1": + keypath = addrKeypath.rstrip().split("hdkeypath=")[1] + else: + #ensure we have generated a new hd master key + assert(hdmasteraddr != addr) + if keytype == "inactivehdmaster=1": + #ensure the old master is still available + assert(hdmasteraddr == addr) + for addrObj in addrs: + if (addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label="): + found_addr+=1 + break + elif (keytype == "change=1"): + found_addr_chg+=1 + break + elif (keytype == "reserve=1"): + found_addr_rsv+=1 + break + + assert(found_addr == test_addr_count) + assert(found_addr_chg == 150) #old reserve keys are marked as change now + assert(found_addr_rsv == 100) #keypool size + +if __name__ == '__main__': + WalletDumpTest().main () |