Add consistency check to RPC call importmulti
This commit is contained in:
parent
cb08fdbf78
commit
215caba4ed
2 changed files with 108 additions and 9 deletions
|
@ -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 ()
|
||||||
|
|
|
@ -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…
Reference in a new issue