Browse Source

Add consistency check to RPC call importmulti

0.14
Pedro Branco 8 years ago
parent
commit
215caba4ed
  1. 69
      qa/rpc-tests/importmulti.py
  2. 48
      src/wallet/rpcdump.cpp

69
qa/rpc-tests/importmulti.py

@ -285,9 +285,76 @@ class ImportMultiTest (BitcoinTestFramework):
assert_equal(result[0]['error']['code'], -8) assert_equal(result[0]['error']['code'], -8)
assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys') assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys')
# TODO Consistency tests?
# Address + Public key + !Internal + Wrong pubkey
print("Should not import an address with a wrong public key")
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
result = self.nodes[1].importmulti([{
"scriptPubKey": {
"address": address['address']
},
"pubkeys": [ address2['pubkey'] ]
}])
assert_equal(result[0]['success'], False)
assert_equal(result[0]['error']['code'], -5)
assert_equal(result[0]['error']['message'], 'Consistency check failed')
address_assert = self.nodes[1].validateaddress(address['address'])
assert_equal(address_assert['iswatchonly'], False)
assert_equal(address_assert['ismine'], False)
# ScriptPubKey + Public key + internal + Wrong pubkey
print("Should not import a scriptPubKey with internal and with a wrong public key")
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
request = [{
"scriptPubKey": address['scriptPubKey'],
"pubkeys": [ address2['pubkey'] ],
"internal": True
}];
result = self.nodes[1].importmulti(request)
assert_equal(result[0]['success'], False)
assert_equal(result[0]['error']['code'], -5)
assert_equal(result[0]['error']['message'], 'Consistency check failed')
address_assert = self.nodes[1].validateaddress(address['address'])
assert_equal(address_assert['iswatchonly'], False)
assert_equal(address_assert['ismine'], False)
# Address + Private key + !watchonly + Wrong private key
print("Should not import an address with a wrong private key")
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
result = self.nodes[1].importmulti([{
"scriptPubKey": {
"address": address['address']
},
"keys": [ self.nodes[0].dumpprivkey(address2['address']) ]
}])
assert_equal(result[0]['success'], False)
assert_equal(result[0]['error']['code'], -5)
assert_equal(result[0]['error']['message'], 'Consistency check failed')
address_assert = self.nodes[1].validateaddress(address['address'])
assert_equal(address_assert['iswatchonly'], False)
assert_equal(address_assert['ismine'], False)
# ScriptPubKey + Private key + internal + Wrong private key
print("Should not import a scriptPubKey with internal and with a wrong private key")
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
result = self.nodes[1].importmulti([{
"scriptPubKey": address['scriptPubKey'],
"keys": [ self.nodes[0].dumpprivkey(address2['address']) ],
"internal": True
}])
assert_equal(result[0]['success'], False)
assert_equal(result[0]['error']['code'], -5)
assert_equal(result[0]['error']['message'], 'Consistency check failed')
address_assert = self.nodes[1].validateaddress(address['address'])
assert_equal(address_assert['iswatchonly'], False)
assert_equal(address_assert['ismine'], False)
if __name__ == '__main__': if __name__ == '__main__':
ImportMultiTest ().main () ImportMultiTest ().main ()

48
src/wallet/rpcdump.cpp

@ -641,9 +641,6 @@ UniValue dumpwallet(const JSONRPCRequest& request)
UniValue processImport(const UniValue& data) { UniValue processImport(const UniValue& data) {
// TODO List:
// - Check consistency between pubkeys/privkeys and scriptPubKey/redeemScript.
try { try {
bool success = false; bool success = false;
@ -713,8 +710,6 @@ UniValue processImport(const UniValue& data) {
// P2SH // P2SH
if (isP2SH) { if (isP2SH) {
// TODO: check consistency between private keys and p2sh redeemscript + p2sh address
// Import redeem script. // Import redeem script.
std::vector<unsigned char> vData(ParseHex(strRedeemScript)); std::vector<unsigned char> vData(ParseHex(strRedeemScript));
CScript redeemScript = CScript(vData.begin(), vData.end()); CScript redeemScript = CScript(vData.begin(), vData.end());
@ -795,8 +790,6 @@ UniValue processImport(const UniValue& data) {
success = true; success = true;
} else { } else {
// TODO: check consistency between private/public keys and scriptPubKey / address
// Import public keys. // Import public keys.
if (pubKeys.size() && keys.size() == 0) { if (pubKeys.size() && keys.size() == 0) {
const string& strPubKey = pubKeys[0].get_str(); const string& strPubKey = pubKeys[0].get_str();
@ -813,6 +806,25 @@ UniValue processImport(const UniValue& data) {
} }
CBitcoinAddress pubKeyAddress = CBitcoinAddress(pubKey.GetID()); CBitcoinAddress pubKeyAddress = CBitcoinAddress(pubKey.GetID());
// Consistency check.
if (!isScript && pubKeyAddress.Get() != address.Get()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
// Consistency check.
if (isScript) {
CBitcoinAddress scriptAddress;
CTxDestination destination;
if (ExtractDestination(script, destination)) {
scriptAddress = CBitcoinAddress(destination);
if (scriptAddress.Get() != pubKeyAddress.Get()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
}
}
CScript pubKeyScript = GetScriptForDestination(pubKeyAddress.Get()); CScript pubKeyScript = GetScriptForDestination(pubKeyAddress.Get());
if (::IsMine(*pwalletMain, pubKeyScript) == ISMINE_SPENDABLE) { if (::IsMine(*pwalletMain, pubKeyScript) == ISMINE_SPENDABLE) {
@ -866,7 +878,27 @@ UniValue processImport(const UniValue& data) {
CPubKey pubKey = key.GetPubKey(); CPubKey pubKey = key.GetPubKey();
assert(key.VerifyPubKey(pubKey)); assert(key.VerifyPubKey(pubKey));
CKeyID vchAddress = pubkey.GetID(); CBitcoinAddress pubKeyAddress = CBitcoinAddress(pubKey.GetID());
// Consistency check.
if (!isScript && pubKeyAddress.Get() != address.Get()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
// Consistency check.
if (isScript) {
CBitcoinAddress scriptAddress;
CTxDestination destination;
if (ExtractDestination(script, destination)) {
scriptAddress = CBitcoinAddress(destination);
if (scriptAddress.Get() != pubKeyAddress.Get()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
}
}
CKeyID vchAddress = pubKey.GetID();
pwalletMain->MarkDirty(); pwalletMain->MarkDirty();
pwalletMain->SetAddressBook(vchAddress, label, "receive"); pwalletMain->SetAddressBook(vchAddress, label, "receive");

Loading…
Cancel
Save