aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Yanofsky <russ@yanofsky.org>2016-11-28 17:19:27 -0500
committerRussell Yanofsky <russ@yanofsky.org>2018-02-22 10:04:42 -0500
commit98ea64cf232c34d4b1aebe738b3956191667cd76 (patch)
treefa5a3e1778d190b28b57e77b2324bd651116684f
parentaae64a21ba25ca86fe2bbb581681dc20d613fb44 (diff)
downloadbitcoin-98ea64cf232c34d4b1aebe738b3956191667cd76.tar.xz
Let wallet importmulti RPC accept labels for standard scriptPubKeys
Allow importmulti RPC to apply address labels when importing standard scriptPubKeys. This makes the importmulti RPC less finnicky about import formats and also simpler internally.
-rw-r--r--src/wallet/rpcdump.cpp42
-rwxr-xr-xtest/functional/wallet_import_rescan.py10
-rwxr-xr-xtest/functional/wallet_importmulti.py27
3 files changed, 28 insertions, 51 deletions
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 741ea25340..caaacdd72c 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -838,6 +838,9 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
std::vector<unsigned char> vData(ParseHex(output));
script = CScript(vData.begin(), vData.end());
+ if (!ExtractDestination(script, dest) && !internal) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set to true for nonstandard scriptPubKey imports.");
+ }
}
// Watchonly and private keys
@@ -850,11 +853,6 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
throw JSONRPCError(RPC_INVALID_PARAMETER, "Incompatibility found between internal and label");
}
- // Not having Internal + Script
- if (!internal && isScript) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set for hex scriptPubKey");
- }
-
// Keys / PubKeys size check.
if (!isP2SH && (keys.size() > 1 || pubKeys.size() > 1)) { // Address / scriptPubKey
throw JSONRPCError(RPC_INVALID_PARAMETER, "More than private key given for one address");
@@ -965,21 +963,10 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
CTxDestination pubkey_dest = pubKey.GetID();
// Consistency check.
- if (!isScript && !(pubkey_dest == dest)) {
+ if (!(pubkey_dest == dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
- // Consistency check.
- if (isScript) {
- CTxDestination destination;
-
- if (ExtractDestination(script, destination)) {
- if (!(destination == pubkey_dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
- }
- }
- }
-
CScript pubKeyScript = GetScriptForDestination(pubkey_dest);
if (::IsMine(*pwallet, pubKeyScript) == ISMINE_SPENDABLE) {
@@ -1036,21 +1023,10 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
CTxDestination pubkey_dest = pubKey.GetID();
// Consistency check.
- if (!isScript && !(pubkey_dest == dest)) {
+ if (!(pubkey_dest == dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
}
- // Consistency check.
- if (isScript) {
- CTxDestination destination;
-
- if (ExtractDestination(script, destination)) {
- if (!(destination == pubkey_dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Consistency check failed");
- }
- }
- }
-
CKeyID vchAddress = pubKey.GetID();
pwallet->MarkDirty();
pwallet->SetAddressBook(vchAddress, label, "receive");
@@ -1082,11 +1058,9 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
- if (scriptPubKey.getType() == UniValue::VOBJ) {
- // add to address book or update label
- if (IsValidDestination(dest)) {
- pwallet->SetAddressBook(dest, label, "receive");
- }
+ // add to address book or update label
+ if (IsValidDestination(dest)) {
+ pwallet->SetAddressBook(dest, label, "receive");
}
success = true;
diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py
index 3288ce4b60..a7095e1a24 100755
--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -26,7 +26,7 @@ import collections
import enum
import itertools
-Call = enum.Enum("Call", "single multi")
+Call = enum.Enum("Call", "single multiaddress multiscript")
Data = enum.Enum("Data", "address pub priv")
Rescan = enum.Enum("Rescan", "no yes late_timestamp")
@@ -54,11 +54,11 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
response = self.try_rpc(self.node.importprivkey, self.key, self.label, self.rescan == Rescan.yes)
assert_equal(response, None)
- elif self.call == Call.multi:
+ elif self.call in (Call.multiaddress, Call.multiscript):
response = self.node.importmulti([{
"scriptPubKey": {
"address": self.address["address"]
- },
+ } if self.call == Call.multiaddress else self.address["scriptPubKey"],
"timestamp": timestamp + TIMESTAMP_WINDOW + (1 if self.rescan == Rescan.late_timestamp else 0),
"pubkeys": [self.address["pubkey"]] if self.data == Data.pub else [],
"keys": [self.key] if self.data == Data.priv else [],
@@ -136,7 +136,7 @@ class ImportRescanTest(BitcoinTestFramework):
variant.label = "label {} {}".format(i, variant)
variant.address = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress(variant.label))
variant.key = self.nodes[1].dumpprivkey(variant.address["address"])
- variant.initial_amount = 10 - (i + 1) / 4.0
+ variant.initial_amount = 1 - (i + 1) / 64
variant.initial_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.initial_amount)
# Generate a block containing the initial transactions, then another
@@ -166,7 +166,7 @@ class ImportRescanTest(BitcoinTestFramework):
# Create new transactions sending to each address.
for i, variant in enumerate(IMPORT_VARIANTS):
- variant.sent_amount = 10 - (2 * i + 1) / 8.0
+ variant.sent_amount = 1 - (2 * i + 1) / 128
variant.sent_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.sent_amount)
# Generate a block containing the new transactions.
diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py
index 56ebc2622a..0b4065ed7e 100755
--- a/test/functional/wallet_importmulti.py
+++ b/test/functional/wallet_importmulti.py
@@ -3,6 +3,8 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the importmulti RPC."""
+
+from test_framework import script
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
@@ -79,16 +81,17 @@ class ImportMultiTest (BitcoinTestFramework):
assert_equal(address_assert['ismine'], False)
assert_equal(address_assert['timestamp'], timestamp)
- # ScriptPubKey + !internal
- self.log.info("Should not import a scriptPubKey without internal flag")
+ # Nonstandard scriptPubKey + !internal
+ self.log.info("Should not import a nonstandard scriptPubKey without internal flag")
+ nonstandardScriptPubKey = address['scriptPubKey'] + bytes_to_hex_str(script.CScript([script.OP_NOP]))
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
result = self.nodes[1].importmulti([{
- "scriptPubKey": address['scriptPubKey'],
+ "scriptPubKey": nonstandardScriptPubKey,
"timestamp": "now",
}])
assert_equal(result[0]['success'], False)
assert_equal(result[0]['error']['code'], -8)
- assert_equal(result[0]['error']['message'], 'Internal must be set for hex scriptPubKey')
+ assert_equal(result[0]['error']['message'], 'Internal must be set to true for nonstandard scriptPubKey imports.')
address_assert = self.nodes[1].getaddressinfo(address['address'])
assert_equal(address_assert['iswatchonly'], False)
assert_equal(address_assert['ismine'], False)
@@ -128,18 +131,18 @@ class ImportMultiTest (BitcoinTestFramework):
assert_equal(address_assert['ismine'], False)
assert_equal(address_assert['timestamp'], timestamp)
- # ScriptPubKey + Public key + !internal
- self.log.info("Should not import a scriptPubKey without internal and with public key")
+ # Nonstandard scriptPubKey + Public key + !internal
+ self.log.info("Should not import a nonstandard scriptPubKey without internal and with public key")
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
request = [{
- "scriptPubKey": address['scriptPubKey'],
+ "scriptPubKey": nonstandardScriptPubKey,
"timestamp": "now",
"pubkeys": [ address['pubkey'] ]
}]
result = self.nodes[1].importmulti(request)
assert_equal(result[0]['success'], False)
assert_equal(result[0]['error']['code'], -8)
- assert_equal(result[0]['error']['message'], 'Internal must be set for hex scriptPubKey')
+ assert_equal(result[0]['error']['message'], 'Internal must be set to true for nonstandard scriptPubKey imports.')
address_assert = self.nodes[1].getaddressinfo(address['address'])
assert_equal(address_assert['iswatchonly'], False)
assert_equal(address_assert['ismine'], False)
@@ -207,17 +210,17 @@ class ImportMultiTest (BitcoinTestFramework):
assert_equal(address_assert['ismine'], True)
assert_equal(address_assert['timestamp'], timestamp)
- # ScriptPubKey + Private key + !internal
- self.log.info("Should not import a scriptPubKey without internal and with private key")
+ # Nonstandard scriptPubKey + Private key + !internal
+ self.log.info("Should not import a nonstandard scriptPubKey without internal and with private key")
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
result = self.nodes[1].importmulti([{
- "scriptPubKey": address['scriptPubKey'],
+ "scriptPubKey": nonstandardScriptPubKey,
"timestamp": "now",
"keys": [ self.nodes[0].dumpprivkey(address['address']) ]
}])
assert_equal(result[0]['success'], False)
assert_equal(result[0]['error']['code'], -8)
- assert_equal(result[0]['error']['message'], 'Internal must be set for hex scriptPubKey')
+ assert_equal(result[0]['error']['message'], 'Internal must be set to true for nonstandard scriptPubKey imports.')
address_assert = self.nodes[1].getaddressinfo(address['address'])
assert_equal(address_assert['iswatchonly'], False)
assert_equal(address_assert['ismine'], False)