Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_importmulti.py
Show All 20 Lines | class ImportMultiTest (BitcoinTestFramework): | ||||
def run_test(self): | def run_test(self): | ||||
self.log.info("Mining blocks...") | self.log.info("Mining blocks...") | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
timestamp = self.nodes[1].getblock( | timestamp = self.nodes[1].getblock( | ||||
self.nodes[1].getbestblockhash())['mediantime'] | self.nodes[1].getbestblockhash())['mediantime'] | ||||
node0_address1 = self.nodes[0].validateaddress( | node0_address1 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
# Check only one address | # Check only one address | ||||
assert_equal(node0_address1['ismine'], True) | assert_equal(node0_address1['ismine'], True) | ||||
# Node 1 sync test | # Node 1 sync test | ||||
assert_equal(self.nodes[1].getblockcount(), 1) | assert_equal(self.nodes[1].getblockcount(), 1) | ||||
# Address Test - before import | # Address Test - before import | ||||
address_info = self.nodes[1].validateaddress(node0_address1['address']) | address_info = self.nodes[1].getaddressinfo(node0_address1['address']) | ||||
assert_equal(address_info['iswatchonly'], False) | assert_equal(address_info['iswatchonly'], False) | ||||
assert_equal(address_info['ismine'], False) | assert_equal(address_info['ismine'], False) | ||||
# RPC importmulti ----------------------------------------------- | # RPC importmulti ----------------------------------------------- | ||||
# Bitcoin Address | # Bitcoin Address | ||||
self.log.info("Should import an address") | self.log.info("Should import an address") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": address['address'] | "address": address['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], True) | assert_equal(address_assert['iswatchonly'], True) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
watchonly_address = address['address'] | watchonly_address = address['address'] | ||||
watchonly_timestamp = timestamp | watchonly_timestamp = timestamp | ||||
self.log.info("Should not import an invalid address") | self.log.info("Should not import an invalid address") | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": "not valid address", | "address": "not valid address", | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -5) | assert_equal(result[0]['error']['code'], -5) | ||||
assert_equal(result[0]['error']['message'], 'Invalid address') | assert_equal(result[0]['error']['message'], 'Invalid address') | ||||
# ScriptPubKey + internal | # ScriptPubKey + internal | ||||
self.log.info("Should import a scriptPubKey with internal flag") | self.log.info("Should import a scriptPubKey with internal flag") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"internal": True | "internal": True | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], True) | assert_equal(address_assert['iswatchonly'], True) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
# ScriptPubKey + !internal | # ScriptPubKey + !internal | ||||
self.log.info("Should not import a scriptPubKey without internal flag") | self.log.info("Should not import a scriptPubKey without internal flag") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -8) | assert_equal(result[0]['error']['code'], -8) | ||||
assert_equal(result[0]['error']['message'], | assert_equal(result[0]['error']['message'], | ||||
'Internal must be set for hex scriptPubKey') | 'Internal must be set for hex scriptPubKey') | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# Address + Public key + !Internal | # Address + Public key + !Internal | ||||
self.log.info("Should import an address with public key") | self.log.info("Should import an address with public key") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": address['address'] | "address": address['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [address['pubkey']] | "pubkeys": [address['pubkey']] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], True) | assert_equal(address_assert['iswatchonly'], True) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
# ScriptPubKey + Public key + internal | # ScriptPubKey + Public key + internal | ||||
self.log.info( | self.log.info( | ||||
"Should import a scriptPubKey with internal and with public key") | "Should import a scriptPubKey with internal and with public key") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
request = [{ | request = [{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [address['pubkey']], | "pubkeys": [address['pubkey']], | ||||
"internal": True | "internal": True | ||||
}] | }] | ||||
result = self.nodes[1].importmulti(request) | result = self.nodes[1].importmulti(request) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], True) | assert_equal(address_assert['iswatchonly'], True) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
# ScriptPubKey + Public key + !internal | # ScriptPubKey + Public key + !internal | ||||
self.log.info( | self.log.info( | ||||
"Should not import a scriptPubKey without internal and with public key") | "Should not import a scriptPubKey without internal and with public key") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
request = [{ | request = [{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [address['pubkey']] | "pubkeys": [address['pubkey']] | ||||
}] | }] | ||||
result = self.nodes[1].importmulti(request) | result = self.nodes[1].importmulti(request) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -8) | assert_equal(result[0]['error']['code'], -8) | ||||
assert_equal(result[0]['error']['message'], | assert_equal(result[0]['error']['message'], | ||||
'Internal must be set for hex scriptPubKey') | 'Internal must be set for hex scriptPubKey') | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# Address + Private key + !watchonly | # Address + Private key + !watchonly | ||||
self.log.info("Should import an address with private key") | self.log.info("Should import an address with private key") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": address['address'] | "address": address['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address['address'])] | "keys": [self.nodes[0].dumpprivkey(address['address'])] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], True) | assert_equal(address_assert['ismine'], True) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
self.log.info( | self.log.info( | ||||
"Should not import an address with private key if is already imported") | "Should not import an address with private key if is already imported") | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": address['address'] | "address": address['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address['address'])] | "keys": [self.nodes[0].dumpprivkey(address['address'])] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -4) | assert_equal(result[0]['error']['code'], -4) | ||||
assert_equal(result[0]['error']['message'], | assert_equal(result[0]['error']['message'], | ||||
'The wallet already contains the private key for this address or script') | 'The wallet already contains the private key for this address or script') | ||||
# Address + Private key + watchonly | # Address + Private key + watchonly | ||||
self.log.info( | self.log.info( | ||||
"Should not import an address with private key and with watchonly") | "Should not import an address with private key and with watchonly") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": address['address'] | "address": address['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address['address'])], | "keys": [self.nodes[0].dumpprivkey(address['address'])], | ||||
"watchonly": True | "watchonly": True | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -8) | assert_equal(result[0]['error']['code'], -8) | ||||
assert_equal(result[0]['error']['message'], | assert_equal(result[0]['error']['message'], | ||||
'Incompatibility found between watchonly and keys') | 'Incompatibility found between watchonly and keys') | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# ScriptPubKey + Private key + internal | # ScriptPubKey + Private key + internal | ||||
self.log.info( | self.log.info( | ||||
"Should import a scriptPubKey with internal and with private key") | "Should import a scriptPubKey with internal and with private key") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address['address'])], | "keys": [self.nodes[0].dumpprivkey(address['address'])], | ||||
"internal": True | "internal": True | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], True) | assert_equal(address_assert['ismine'], True) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
# ScriptPubKey + Private key + !internal | # ScriptPubKey + Private key + !internal | ||||
self.log.info( | self.log.info( | ||||
"Should not import a scriptPubKey without internal and with private key") | "Should not import a scriptPubKey without internal and with private key") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address['address'])] | "keys": [self.nodes[0].dumpprivkey(address['address'])] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -8) | assert_equal(result[0]['error']['code'], -8) | ||||
assert_equal(result[0]['error']['message'], | assert_equal(result[0]['error']['message'], | ||||
'Internal must be set for hex scriptPubKey') | 'Internal must be set for hex scriptPubKey') | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# P2SH address | # P2SH address | ||||
sig_address_1 = self.nodes[0].validateaddress( | sig_address_1 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
sig_address_2 = self.nodes[0].validateaddress( | sig_address_2 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
sig_address_3 = self.nodes[0].validateaddress( | sig_address_3 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
multi_sig_script = self.nodes[0].createmultisig( | multi_sig_script = self.nodes[0].createmultisig( | ||||
2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) | 2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) | ||||
self.nodes[1].generate(100) | self.nodes[1].generate(100) | ||||
transactionid = self.nodes[1].sendtoaddress( | transactionid = self.nodes[1].sendtoaddress( | ||||
multi_sig_script['address'], 10.00) | multi_sig_script['address'], 10.00) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
timestamp = self.nodes[1].getblock( | timestamp = self.nodes[1].getblock( | ||||
self.nodes[1].getbestblockhash())['mediantime'] | self.nodes[1].getbestblockhash())['mediantime'] | ||||
self.log.info("Should import a p2sh") | self.log.info("Should import a p2sh") | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": multi_sig_script['address'] | "address": multi_sig_script['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].validateaddress( | address_assert = self.nodes[1].getaddressinfo( | ||||
multi_sig_script['address']) | multi_sig_script['address']) | ||||
assert_equal(address_assert['isscript'], True) | assert_equal(address_assert['isscript'], True) | ||||
assert_equal(address_assert['iswatchonly'], True) | assert_equal(address_assert['iswatchonly'], True) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
p2shunspent = self.nodes[1].listunspent( | p2shunspent = self.nodes[1].listunspent( | ||||
0, 999999, [multi_sig_script['address']])[0] | 0, 999999, [multi_sig_script['address']])[0] | ||||
assert_equal(p2shunspent['spendable'], False) | assert_equal(p2shunspent['spendable'], False) | ||||
assert_equal(p2shunspent['solvable'], False) | assert_equal(p2shunspent['solvable'], False) | ||||
# P2SH + Redeem script | # P2SH + Redeem script | ||||
sig_address_1 = self.nodes[0].validateaddress( | sig_address_1 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
sig_address_2 = self.nodes[0].validateaddress( | sig_address_2 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
sig_address_3 = self.nodes[0].validateaddress( | sig_address_3 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
multi_sig_script = self.nodes[0].createmultisig( | multi_sig_script = self.nodes[0].createmultisig( | ||||
2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) | 2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) | ||||
self.nodes[1].generate(100) | self.nodes[1].generate(100) | ||||
transactionid = self.nodes[1].sendtoaddress( | transactionid = self.nodes[1].sendtoaddress( | ||||
multi_sig_script['address'], 10.00) | multi_sig_script['address'], 10.00) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
timestamp = self.nodes[1].getblock( | timestamp = self.nodes[1].getblock( | ||||
self.nodes[1].getbestblockhash())['mediantime'] | self.nodes[1].getbestblockhash())['mediantime'] | ||||
self.log.info("Should import a p2sh with respective redeem script") | self.log.info("Should import a p2sh with respective redeem script") | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": multi_sig_script['address'] | "address": multi_sig_script['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"redeemscript": multi_sig_script['redeemScript'] | "redeemscript": multi_sig_script['redeemScript'] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].validateaddress( | address_assert = self.nodes[1].getaddressinfo( | ||||
multi_sig_script['address']) | multi_sig_script['address']) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
p2shunspent = self.nodes[1].listunspent( | p2shunspent = self.nodes[1].listunspent( | ||||
0, 999999, [multi_sig_script['address']])[0] | 0, 999999, [multi_sig_script['address']])[0] | ||||
assert_equal(p2shunspent['spendable'], False) | assert_equal(p2shunspent['spendable'], False) | ||||
assert_equal(p2shunspent['solvable'], True) | assert_equal(p2shunspent['solvable'], True) | ||||
# P2SH + Redeem script + Private Keys + !Watchonly | # P2SH + Redeem script + Private Keys + !Watchonly | ||||
sig_address_1 = self.nodes[0].validateaddress( | sig_address_1 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
sig_address_2 = self.nodes[0].validateaddress( | sig_address_2 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
sig_address_3 = self.nodes[0].validateaddress( | sig_address_3 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
multi_sig_script = self.nodes[0].createmultisig( | multi_sig_script = self.nodes[0].createmultisig( | ||||
2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) | 2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) | ||||
self.nodes[1].generate(100) | self.nodes[1].generate(100) | ||||
transactionid = self.nodes[1].sendtoaddress( | transactionid = self.nodes[1].sendtoaddress( | ||||
multi_sig_script['address'], 10.00) | multi_sig_script['address'], 10.00) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
timestamp = self.nodes[1].getblock( | timestamp = self.nodes[1].getblock( | ||||
self.nodes[1].getbestblockhash())['mediantime'] | self.nodes[1].getbestblockhash())['mediantime'] | ||||
self.log.info( | self.log.info( | ||||
"Should import a p2sh with respective redeem script and private keys") | "Should import a p2sh with respective redeem script and private keys") | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": multi_sig_script['address'] | "address": multi_sig_script['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"redeemscript": multi_sig_script['redeemScript'], | "redeemscript": multi_sig_script['redeemScript'], | ||||
"keys": [self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])] | "keys": [self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address'])] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].validateaddress( | address_assert = self.nodes[1].getaddressinfo( | ||||
multi_sig_script['address']) | multi_sig_script['address']) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
p2shunspent = self.nodes[1].listunspent( | p2shunspent = self.nodes[1].listunspent( | ||||
0, 999999, [multi_sig_script['address']])[0] | 0, 999999, [multi_sig_script['address']])[0] | ||||
assert_equal(p2shunspent['spendable'], False) | assert_equal(p2shunspent['spendable'], False) | ||||
assert_equal(p2shunspent['solvable'], True) | assert_equal(p2shunspent['solvable'], True) | ||||
# P2SH + Redeem script + Private Keys + Watchonly | # P2SH + Redeem script + Private Keys + Watchonly | ||||
sig_address_1 = self.nodes[0].validateaddress( | sig_address_1 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
sig_address_2 = self.nodes[0].validateaddress( | sig_address_2 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
sig_address_3 = self.nodes[0].validateaddress( | sig_address_3 = self.nodes[0].getaddressinfo( | ||||
self.nodes[0].getnewaddress()) | self.nodes[0].getnewaddress()) | ||||
multi_sig_script = self.nodes[0].createmultisig( | multi_sig_script = self.nodes[0].createmultisig( | ||||
2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) | 2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']]) | ||||
self.nodes[1].generate(100) | self.nodes[1].generate(100) | ||||
transactionid = self.nodes[1].sendtoaddress( | transactionid = self.nodes[1].sendtoaddress( | ||||
multi_sig_script['address'], 10.00) | multi_sig_script['address'], 10.00) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
timestamp = self.nodes[1].getblock( | timestamp = self.nodes[1].getblock( | ||||
Show All 12 Lines | def run_test(self): | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -8) | assert_equal(result[0]['error']['code'], -8) | ||||
assert_equal(result[0]['error']['message'], | assert_equal(result[0]['error']['message'], | ||||
'Incompatibility found between watchonly and keys') | 'Incompatibility found between watchonly and keys') | ||||
# Address + Public key + !Internal + Wrong pubkey | # Address + Public key + !Internal + Wrong pubkey | ||||
self.log.info("Should not import an address with a wrong public key") | self.log.info("Should not import an address with a wrong public key") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": address['address'] | "address": address['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [address2['pubkey']] | "pubkeys": [address2['pubkey']] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -5) | assert_equal(result[0]['error']['code'], -5) | ||||
assert_equal(result[0]['error']['message'], 'Consistency check failed') | assert_equal(result[0]['error']['message'], 'Consistency check failed') | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# ScriptPubKey + Public key + internal + Wrong pubkey | # ScriptPubKey + Public key + internal + Wrong pubkey | ||||
self.log.info( | self.log.info( | ||||
"Should not import a scriptPubKey with internal and with a wrong public key") | "Should not import a scriptPubKey with internal and with a wrong public key") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
request = [{ | request = [{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"pubkeys": [address2['pubkey']], | "pubkeys": [address2['pubkey']], | ||||
"internal": True | "internal": True | ||||
}] | }] | ||||
result = self.nodes[1].importmulti(request) | result = self.nodes[1].importmulti(request) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -5) | assert_equal(result[0]['error']['code'], -5) | ||||
assert_equal(result[0]['error']['message'], 'Consistency check failed') | assert_equal(result[0]['error']['message'], 'Consistency check failed') | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# Address + Private key + !watchonly + Wrong private key | # Address + Private key + !watchonly + Wrong private key | ||||
self.log.info("Should not import an address with a wrong private key") | self.log.info("Should not import an address with a wrong private key") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": address['address'] | "address": address['address'] | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address2['address'])] | "keys": [self.nodes[0].dumpprivkey(address2['address'])] | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -5) | assert_equal(result[0]['error']['code'], -5) | ||||
assert_equal(result[0]['error']['message'], 'Consistency check failed') | assert_equal(result[0]['error']['message'], 'Consistency check failed') | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# ScriptPubKey + Private key + internal + Wrong private key | # ScriptPubKey + Private key + internal + Wrong private key | ||||
self.log.info( | self.log.info( | ||||
"Should not import a scriptPubKey with internal and with a wrong private key") | "Should not import a scriptPubKey with internal and with a wrong private key") | ||||
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress()) | address2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress()) | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": address['scriptPubKey'], | "scriptPubKey": address['scriptPubKey'], | ||||
"timestamp": "now", | "timestamp": "now", | ||||
"keys": [self.nodes[0].dumpprivkey(address2['address'])], | "keys": [self.nodes[0].dumpprivkey(address2['address'])], | ||||
"internal": True | "internal": True | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], False) | assert_equal(result[0]['success'], False) | ||||
assert_equal(result[0]['error']['code'], -5) | assert_equal(result[0]['error']['code'], -5) | ||||
assert_equal(result[0]['error']['message'], 'Consistency check failed') | assert_equal(result[0]['error']['message'], 'Consistency check failed') | ||||
address_assert = self.nodes[1].validateaddress(address['address']) | address_assert = self.nodes[1].getaddressinfo(address['address']) | ||||
assert_equal(address_assert['iswatchonly'], False) | assert_equal(address_assert['iswatchonly'], False) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal('timestamp' in address_assert, False) | assert_equal('timestamp' in address_assert, False) | ||||
# Importing existing watch only address with new timestamp should replace saved timestamp. | # Importing existing watch only address with new timestamp should replace saved timestamp. | ||||
assert_greater_than(timestamp, watchonly_timestamp) | assert_greater_than(timestamp, watchonly_timestamp) | ||||
self.log.info("Should replace previously saved watch only timestamp.") | self.log.info("Should replace previously saved watch only timestamp.") | ||||
result = self.nodes[1].importmulti([{ | result = self.nodes[1].importmulti([{ | ||||
"scriptPubKey": { | "scriptPubKey": { | ||||
"address": watchonly_address, | "address": watchonly_address, | ||||
}, | }, | ||||
"timestamp": "now", | "timestamp": "now", | ||||
}]) | }]) | ||||
assert_equal(result[0]['success'], True) | assert_equal(result[0]['success'], True) | ||||
address_assert = self.nodes[1].validateaddress(watchonly_address) | address_assert = self.nodes[1].getaddressinfo(watchonly_address) | ||||
assert_equal(address_assert['iswatchonly'], True) | assert_equal(address_assert['iswatchonly'], True) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal(address_assert['timestamp'], timestamp) | assert_equal(address_assert['timestamp'], timestamp) | ||||
watchonly_timestamp = timestamp | watchonly_timestamp = timestamp | ||||
# restart nodes to check for proper serialization/deserialization of watch only address | # restart nodes to check for proper serialization/deserialization of watch only address | ||||
self.stop_nodes() | self.stop_nodes() | ||||
self.start_nodes() | self.start_nodes() | ||||
address_assert = self.nodes[1].validateaddress(watchonly_address) | address_assert = self.nodes[1].getaddressinfo(watchonly_address) | ||||
assert_equal(address_assert['iswatchonly'], True) | assert_equal(address_assert['iswatchonly'], True) | ||||
assert_equal(address_assert['ismine'], False) | assert_equal(address_assert['ismine'], False) | ||||
assert_equal(address_assert['timestamp'], watchonly_timestamp) | assert_equal(address_assert['timestamp'], watchonly_timestamp) | ||||
# Bad or missing timestamps | # Bad or missing timestamps | ||||
self.log.info("Should throw on invalid or missing timestamp values") | self.log.info("Should throw on invalid or missing timestamp values") | ||||
assert_raises_rpc_error(-3, 'Missing required timestamp field for key', | assert_raises_rpc_error(-3, 'Missing required timestamp field for key', | ||||
self.nodes[1].importmulti, [{ | self.nodes[1].importmulti, [{ | ||||
Show All 11 Lines |