Skip to content

Commit 816dabb

Browse files
committed
Add p2sh option to importaddress to import redeemScripts
1 parent 60a20a4 commit 816dabb

File tree

3 files changed

+31
-12
lines changed

3 files changed

+31
-12
lines changed

src/rpc/client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
112112
{"importprivkey", 2},
113113
{"importprivkey", 3},
114114
{"importaddress", 2},
115+
{"importaddress", 3},
115116
{"verifychain", 0},
116117
{"verifychain", 1},
117118
{"keypoolrefill", 0},

src/wallet/rpcdump.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -151,21 +151,29 @@ UniValue importprivkey(const UniValue& params, bool fHelp)
151151
return NullUniValue;
152152
}
153153

154-
void ImportScript(const CScript& script)
154+
void ImportAddress(const CTxDestination& dest, const std::string& strLabel, const std::string& strPurpose);
155+
156+
void ImportScript(const CScript& script, const std::string& strLabel, bool isRedeemScript)
155157
{
156-
if (::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE)
158+
if (!isRedeemScript && ::IsMine(*pwalletMain, script) == ISMINE_SPENDABLE)
157159
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
158160

159161
pwalletMain->MarkDirty();
160162

161163
if (!pwalletMain->HaveWatchOnly(script) && !pwalletMain->AddWatchOnly(script))
162164
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
165+
166+
if (isRedeemScript) {
167+
if (!pwalletMain->HaveCScript(script) && !pwalletMain->AddCScript(script))
168+
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet");
169+
ImportAddress(CScriptID(script), strLabel, "receive");
170+
}
163171
}
164172

165173
void ImportAddress(const CTxDestination& dest, const std::string& strLabel, const std::string& strPurpose)
166174
{
167175
CScript script = GetScriptForDestination(dest);
168-
ImportScript(script);
176+
ImportScript(script, strLabel, false);
169177
// add to address book or update label
170178
if (IsValidDestination(dest)) {
171179
pwalletMain->SetAddressBook(dest, strLabel, strPurpose);
@@ -174,7 +182,7 @@ void ImportAddress(const CTxDestination& dest, const std::string& strLabel, cons
174182

175183
UniValue importaddress(const UniValue& params, bool fHelp)
176184
{
177-
if (fHelp || params.size() < 1 || params.size() > 3)
185+
if (fHelp || params.size() < 1 || params.size() > 4)
178186
throw std::runtime_error(
179187
"importaddress \"address\" ( \"label\" rescan )\n"
180188
"\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"
@@ -183,6 +191,7 @@ UniValue importaddress(const UniValue& params, bool fHelp)
183191
"1. \"address\" (string, required) The address\n"
184192
"2. \"label\" (string, optional, default=\"\") An optional label\n"
185193
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
194+
"4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n"
186195

187196
"\nNote: This call can take minutes to complete if rescan is true.\n"
188197

@@ -194,28 +203,27 @@ UniValue importaddress(const UniValue& params, bool fHelp)
194203
"\nAs a JSON-RPC call\n" +
195204
HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false"));
196205

197-
std::string strLabel = "";
198-
if (params.size() > 1)
199-
strLabel = params[1].get_str();
200-
206+
const std::string strLabel = (params.size() > 1 ? params[1].get_str() : "");
201207
// Whether to perform rescan after import
202-
bool fRescan = true;
203-
if (params.size() > 2)
204-
fRescan = params[2].get_bool();
208+
const bool fRescan = (params.size() > 2 ? params[2].get_bool() : true);
209+
// Whether to import a p2sh version, too
210+
const bool fP2SH = (params.size() > 3 ? params[3].get_bool() : false);
205211

206212
LOCK2(cs_main, pwalletMain->cs_wallet);
207213

208214
bool isStakingAddress = false;
209215
CTxDestination dest = DecodeDestination(params[0].get_str(), isStakingAddress);
210216

211217
if (IsValidDestination(dest)) {
218+
if (fP2SH)
219+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
212220
ImportAddress(dest, strLabel, isStakingAddress ?
213221
AddressBook::AddressBookPurpose::COLD_STAKING :
214222
AddressBook::AddressBookPurpose::RECEIVE);
215223

216224
} else if (IsHex(params[0].get_str())) {
217225
std::vector<unsigned char> data(ParseHex(params[0].get_str()));
218-
ImportScript(CScript(data.begin(), data.end()));
226+
ImportScript(CScript(data.begin(), data.end()), strLabel, fP2SH);
219227

220228
} else {
221229
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid PIVX address or script");

test/functional/rpc_listtransactions.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ def run_test(self):
8181
{"category":"receive","amount":Decimal("0.44")},
8282
{"txid":txid, "account" : "toself"} )
8383

84+
multisig = self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()])
85+
self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True)
86+
txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
87+
self.nodes[1].generate(1)
88+
self.sync_all()
89+
assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0)
90+
assert_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True),
91+
{"category": "receive", "amount": Decimal("0.1")},
92+
{"txid": txid, "account": "watchonly"})
93+
8494

8595
if __name__ == '__main__':
8696
ListTransactionsTest().main()

0 commit comments

Comments
 (0)