Skip to content

Commit 215caba

Browse files
author
Pedro Branco
committed
Add consistency check to RPC call importmulti
1 parent cb08fdb commit 215caba

File tree

2 files changed

+108
-9
lines changed

2 files changed

+108
-9
lines changed

qa/rpc-tests/importmulti.py

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,76 @@ def run_test (self):
285285
assert_equal(result[0]['error']['code'], -8)
286286
assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys')
287287

288-
# TODO Consistency tests?
289288

289+
# Address + Public key + !Internal + Wrong pubkey
290+
print("Should not import an address with a wrong public key")
291+
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
292+
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
293+
result = self.nodes[1].importmulti([{
294+
"scriptPubKey": {
295+
"address": address['address']
296+
},
297+
"pubkeys": [ address2['pubkey'] ]
298+
}])
299+
assert_equal(result[0]['success'], False)
300+
assert_equal(result[0]['error']['code'], -5)
301+
assert_equal(result[0]['error']['message'], 'Consistency check failed')
302+
address_assert = self.nodes[1].validateaddress(address['address'])
303+
assert_equal(address_assert['iswatchonly'], False)
304+
assert_equal(address_assert['ismine'], False)
305+
306+
307+
# ScriptPubKey + Public key + internal + Wrong pubkey
308+
print("Should not import a scriptPubKey with internal and with a wrong public key")
309+
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
310+
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
311+
request = [{
312+
"scriptPubKey": address['scriptPubKey'],
313+
"pubkeys": [ address2['pubkey'] ],
314+
"internal": True
315+
}];
316+
result = self.nodes[1].importmulti(request)
317+
assert_equal(result[0]['success'], False)
318+
assert_equal(result[0]['error']['code'], -5)
319+
assert_equal(result[0]['error']['message'], 'Consistency check failed')
320+
address_assert = self.nodes[1].validateaddress(address['address'])
321+
assert_equal(address_assert['iswatchonly'], False)
322+
assert_equal(address_assert['ismine'], False)
290323

291324

325+
# Address + Private key + !watchonly + Wrong private key
326+
print("Should not import an address with a wrong private key")
327+
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
328+
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
329+
result = self.nodes[1].importmulti([{
330+
"scriptPubKey": {
331+
"address": address['address']
332+
},
333+
"keys": [ self.nodes[0].dumpprivkey(address2['address']) ]
334+
}])
335+
assert_equal(result[0]['success'], False)
336+
assert_equal(result[0]['error']['code'], -5)
337+
assert_equal(result[0]['error']['message'], 'Consistency check failed')
338+
address_assert = self.nodes[1].validateaddress(address['address'])
339+
assert_equal(address_assert['iswatchonly'], False)
340+
assert_equal(address_assert['ismine'], False)
341+
342+
343+
# ScriptPubKey + Private key + internal + Wrong private key
344+
print("Should not import a scriptPubKey with internal and with a wrong private key")
345+
address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
346+
address2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
347+
result = self.nodes[1].importmulti([{
348+
"scriptPubKey": address['scriptPubKey'],
349+
"keys": [ self.nodes[0].dumpprivkey(address2['address']) ],
350+
"internal": True
351+
}])
352+
assert_equal(result[0]['success'], False)
353+
assert_equal(result[0]['error']['code'], -5)
354+
assert_equal(result[0]['error']['message'], 'Consistency check failed')
355+
address_assert = self.nodes[1].validateaddress(address['address'])
356+
assert_equal(address_assert['iswatchonly'], False)
357+
assert_equal(address_assert['ismine'], False)
358+
292359
if __name__ == '__main__':
293360
ImportMultiTest ().main ()

src/wallet/rpcdump.cpp

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -641,9 +641,6 @@ UniValue dumpwallet(const JSONRPCRequest& request)
641641

642642

643643
UniValue processImport(const UniValue& data) {
644-
// TODO List:
645-
// - Check consistency between pubkeys/privkeys and scriptPubKey/redeemScript.
646-
647644
try {
648645
bool success = false;
649646

@@ -713,8 +710,6 @@ UniValue processImport(const UniValue& data) {
713710

714711
// P2SH
715712
if (isP2SH) {
716-
// TODO: check consistency between private keys and p2sh redeemscript + p2sh address
717-
718713
// Import redeem script.
719714
std::vector<unsigned char> vData(ParseHex(strRedeemScript));
720715
CScript redeemScript = CScript(vData.begin(), vData.end());
@@ -795,8 +790,6 @@ UniValue processImport(const UniValue& data) {
795790

796791
success = true;
797792
} else {
798-
// TODO: check consistency between private/public keys and scriptPubKey / address
799-
800793
// Import public keys.
801794
if (pubKeys.size() && keys.size() == 0) {
802795
const string& strPubKey = pubKeys[0].get_str();
@@ -813,6 +806,25 @@ UniValue processImport(const UniValue& data) {
813806
}
814807

815808
CBitcoinAddress pubKeyAddress = CBitcoinAddress(pubKey.GetID());
809+
810+
// Consistency check.
811+
if (!isScript && pubKeyAddress.Get() != address.Get()) {
812+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
813+
}
814+
815+
// Consistency check.
816+
if (isScript) {
817+
CBitcoinAddress scriptAddress;
818+
CTxDestination destination;
819+
820+
if (ExtractDestination(script, destination)) {
821+
scriptAddress = CBitcoinAddress(destination);
822+
if (scriptAddress.Get() != pubKeyAddress.Get()) {
823+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
824+
}
825+
}
826+
}
827+
816828
CScript pubKeyScript = GetScriptForDestination(pubKeyAddress.Get());
817829

818830
if (::IsMine(*pwalletMain, pubKeyScript) == ISMINE_SPENDABLE) {
@@ -866,7 +878,27 @@ UniValue processImport(const UniValue& data) {
866878
CPubKey pubKey = key.GetPubKey();
867879
assert(key.VerifyPubKey(pubKey));
868880

869-
CKeyID vchAddress = pubkey.GetID();
881+
CBitcoinAddress pubKeyAddress = CBitcoinAddress(pubKey.GetID());
882+
883+
// Consistency check.
884+
if (!isScript && pubKeyAddress.Get() != address.Get()) {
885+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
886+
}
887+
888+
// Consistency check.
889+
if (isScript) {
890+
CBitcoinAddress scriptAddress;
891+
CTxDestination destination;
892+
893+
if (ExtractDestination(script, destination)) {
894+
scriptAddress = CBitcoinAddress(destination);
895+
if (scriptAddress.Get() != pubKeyAddress.Get()) {
896+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
897+
}
898+
}
899+
}
900+
901+
CKeyID vchAddress = pubKey.GetID();
870902
pwalletMain->MarkDirty();
871903
pwalletMain->SetAddressBook(vchAddress, label, "receive");
872904

0 commit comments

Comments
 (0)