From 907a425aa5b8fd90cf1d28215712a309e934b364 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 11 Jun 2015 00:57:50 -0700 Subject: [PATCH] Add p2sh option to importaddress to import redeemScripts --- qa/rpc-tests/listtransactions.py | 10 ++++++++++ src/rpcclient.cpp | 1 + src/wallet/rpcdump.cpp | 26 ++++++++++++++++++++------ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py index eeae2d2fa..b30a6bc9d 100755 --- a/qa/rpc-tests/listtransactions.py +++ b/qa/rpc-tests/listtransactions.py @@ -93,6 +93,16 @@ class ListTransactionsTest(BitcoinTestFramework): {"category":"receive","amount":Decimal("0.44")}, {"txid":txid, "account" : "toself"} ) + multisig = self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()]) + self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True) + txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1) + self.nodes[1].generate(1) + self.sync_all() + assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0) + check_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True), + {"category":"receive","amount":Decimal("0.1")}, + {"txid":txid, "account" : "watchonly"} ) + if __name__ == '__main__': ListTransactionsTest().main() diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index b41e960e8..450f33b3e 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -87,6 +87,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "lockunspent", 1 }, { "importprivkey", 2 }, { "importaddress", 2 }, + { "importaddress", 3 }, { "verifychain", 0 }, { "verifychain", 1 }, { "keypoolrefill", 0 }, diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index f56ff65f8..3493efc8f 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -146,21 +146,28 @@ UniValue importprivkey(const UniValue& params, bool fHelp) return NullUniValue; } -void ImportScript(const CScript& script) +void ImportAddress(const CBitcoinAddress& address, const string& strLabel); +void ImportScript(const CScript& script, const string& strLabel, bool isRedeemScript) { - if (::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE) + if (!isRedeemScript && ::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE) throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); pwalletMain->MarkDirty(); if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script)) throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + + if (isRedeemScript) { + if (!pwalletMain->HaveCScript(script) && !pwalletMain->AddCScript(script)) + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet"); + ImportAddress(CBitcoinAddress(CScriptID(script)), strLabel); + } } void ImportAddress(const CBitcoinAddress& address, const string& strLabel) { CScript script = GetScriptForDestination(address.Get()); - ImportScript(script, false); + ImportScript(script, strLabel, false); // add to address book or update label if (address.IsValid()) pwalletMain->SetAddressBook(address.Get(), strLabel, "receive"); @@ -171,14 +178,15 @@ UniValue importaddress(const UniValue& params, bool fHelp) if (!EnsureWalletIsAvailable(fHelp)) return NullUniValue; - if (fHelp || params.size() < 1 || params.size() > 3) + if (fHelp || params.size() < 1 || params.size() > 4) throw runtime_error( - "importaddress \"address\" ( \"label\" rescan )\n" + "importaddress \"address\" ( \"label\" rescan p2sh )\n" "\nAdds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend.\n" "\nArguments:\n" "1. \"address\" (string, required) The address\n" "2. \"label\" (string, optional, default=\"\") An optional label\n" "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" + "4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n" "\nNote: This call can take minutes to complete if rescan is true.\n" "\nExamples:\n" "\nImport an address with rescan\n" @@ -201,15 +209,21 @@ UniValue importaddress(const UniValue& params, bool fHelp) if (params.size() > 2) fRescan = params[2].get_bool(); + // Whether to import a p2sh version, too + bool fP2SH = false; + if (params.size() > 3) + fP2SH = params[3].get_bool(); LOCK2(cs_main, pwalletMain->cs_wallet); CBitcoinAddress address(params[0].get_str()); if (address.IsValid()) { + if (fP2SH) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead"); ImportAddress(address, strLabel); } else if (IsHex(params[0].get_str())) { std::vector data(ParseHex(params[0].get_str())); - ImportScript(CScript(data.begin(), data.end())); + ImportScript(CScript(data.begin(), data.end()), strLabel, fP2SH); } else { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script"); }