Add p2sh option to importaddress to import redeemScripts

This commit is contained in:
Matt Corallo 2015-06-11 00:57:50 -07:00
parent 983d2d90af
commit 907a425aa5
3 changed files with 31 additions and 6 deletions

View file

@ -93,6 +93,16 @@ class ListTransactionsTest(BitcoinTestFramework):
{"category":"receive","amount":Decimal("0.44")}, {"category":"receive","amount":Decimal("0.44")},
{"txid":txid, "account" : "toself"} ) {"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__': if __name__ == '__main__':
ListTransactionsTest().main() ListTransactionsTest().main()

View file

@ -87,6 +87,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "lockunspent", 1 }, { "lockunspent", 1 },
{ "importprivkey", 2 }, { "importprivkey", 2 },
{ "importaddress", 2 }, { "importaddress", 2 },
{ "importaddress", 3 },
{ "verifychain", 0 }, { "verifychain", 0 },
{ "verifychain", 1 }, { "verifychain", 1 },
{ "keypoolrefill", 0 }, { "keypoolrefill", 0 },

View file

@ -146,21 +146,28 @@ UniValue importprivkey(const UniValue& params, bool fHelp)
return NullUniValue; 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"); throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
pwalletMain->MarkDirty(); pwalletMain->MarkDirty();
if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script)) if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script))
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); 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) void ImportAddress(const CBitcoinAddress& address, const string& strLabel)
{ {
CScript script = GetScriptForDestination(address.Get()); CScript script = GetScriptForDestination(address.Get());
ImportScript(script, false); ImportScript(script, strLabel, false);
// add to address book or update label // add to address book or update label
if (address.IsValid()) if (address.IsValid())
pwalletMain->SetAddressBook(address.Get(), strLabel, "receive"); pwalletMain->SetAddressBook(address.Get(), strLabel, "receive");
@ -171,14 +178,15 @@ UniValue importaddress(const UniValue& params, bool fHelp)
if (!EnsureWalletIsAvailable(fHelp)) if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue; return NullUniValue;
if (fHelp || params.size() < 1 || params.size() > 3) if (fHelp || params.size() < 1 || params.size() > 4)
throw runtime_error( 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" "\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" "\nArguments:\n"
"1. \"address\" (string, required) The address\n" "1. \"address\" (string, required) The address\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n" "2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\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" "\nNote: This call can take minutes to complete if rescan is true.\n"
"\nExamples:\n" "\nExamples:\n"
"\nImport an address with rescan\n" "\nImport an address with rescan\n"
@ -201,15 +209,21 @@ UniValue importaddress(const UniValue& params, bool fHelp)
if (params.size() > 2) if (params.size() > 2)
fRescan = params[2].get_bool(); 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); LOCK2(cs_main, pwalletMain->cs_wallet);
CBitcoinAddress address(params[0].get_str()); CBitcoinAddress address(params[0].get_str());
if (address.IsValid()) { 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); ImportAddress(address, strLabel);
} else if (IsHex(params[0].get_str())) { } else if (IsHex(params[0].get_str())) {
std::vector<unsigned char> data(ParseHex(params[0].get_str())); std::vector<unsigned char> data(ParseHex(params[0].get_str()));
ImportScript(CScript(data.begin(), data.end())); ImportScript(CScript(data.begin(), data.end()), strLabel, fP2SH);
} else { } else {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script");
} }