Skip to content

Commit c3fe53f

Browse files
committed
Add witness address RPCs (using P2SH)
Includes support for pushkeyhash wit v0 by Alex Morcos.
1 parent abbe085 commit c3fe53f

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

src/rpc/misc.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,39 @@ UniValue createmultisig(const UniValue& params, bool fHelp)
312312
return result;
313313
}
314314

315+
UniValue createwitnessaddress(const UniValue& params, bool fHelp)
316+
{
317+
if (fHelp || params.size() < 1 || params.size() > 1)
318+
{
319+
string msg = "createwitnessaddress \"script\"\n"
320+
"\nCreates a witness address for a particular script.\n"
321+
"It returns a json object with the address and witness script.\n"
322+
323+
"\nArguments:\n"
324+
"1. \"script\" (string, required) A hex encoded script\n"
325+
326+
"\nResult:\n"
327+
"{\n"
328+
" \"address\":\"multisigaddress\", (string) The value of the new address (P2SH of witness script).\n"
329+
" \"witnessScript\":\"script\" (string) The string value of the hex-encoded witness script.\n"
330+
"}\n"
331+
;
332+
throw runtime_error(msg);
333+
}
334+
335+
std::vector<unsigned char> code = ParseHex(params[0].get_str());
336+
CScript script(code.begin(), code.end());
337+
CScript witscript = GetScriptForWitness(script);
338+
CScriptID witscriptid(witscript);
339+
CBitcoinAddress address(witscriptid);
340+
341+
UniValue result(UniValue::VOBJ);
342+
result.push_back(Pair("address", address.ToString()));
343+
result.push_back(Pair("witnessScript", HexStr(witscript.begin(), witscript.end())));
344+
345+
return result;
346+
}
347+
315348
UniValue verifymessage(const UniValue& params, bool fHelp)
316349
{
317350
if (fHelp || params.size() != 3)
@@ -403,6 +436,7 @@ static const CRPCCommand commands[] =
403436
{ "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */
404437
{ "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */
405438
{ "util", "createmultisig", &createmultisig, true },
439+
{ "util", "createwitnessaddress", &createwitnessaddress, true },
406440
{ "util", "verifymessage", &verifymessage, true },
407441

408442
/* Not shown in help */

src/wallet/rpcwallet.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,75 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp)
10951095
return CBitcoinAddress(innerID).ToString();
10961096
}
10971097

1098+
class Witnessifier : public boost::static_visitor<bool>
1099+
{
1100+
public:
1101+
CScriptID result;
1102+
1103+
bool operator()(const CNoDestination &dest) const { return false; }
1104+
1105+
bool operator()(const CKeyID &keyID) {
1106+
CPubKey pubkey;
1107+
if (pwalletMain && pwalletMain->GetPubKey(keyID, pubkey)) {
1108+
CScript basescript;
1109+
basescript << ToByteVector(pubkey) << OP_CHECKSIG;
1110+
CScript witscript = GetScriptForWitness(basescript);
1111+
pwalletMain->AddCScript(witscript);
1112+
result = CScriptID(witscript);
1113+
return true;
1114+
}
1115+
return false;
1116+
}
1117+
1118+
bool operator()(const CScriptID &scriptID) {
1119+
CScript subscript;
1120+
if (pwalletMain && pwalletMain->GetCScript(scriptID, subscript)) {
1121+
int witnessversion;
1122+
std::vector<unsigned char> witprog;
1123+
if (subscript.IsWitnessProgram(witnessversion, witprog)) {
1124+
result = scriptID;
1125+
return true;
1126+
}
1127+
CScript witscript = GetScriptForWitness(subscript);
1128+
pwalletMain->AddCScript(witscript);
1129+
result = CScriptID(witscript);
1130+
return true;
1131+
}
1132+
return false;
1133+
}
1134+
};
1135+
1136+
UniValue addwitnessaddress(const UniValue& params, bool fHelp)
1137+
{
1138+
if (fHelp || params.size() < 1 || params.size() > 1)
1139+
{
1140+
string msg = "addwitnessaddress \"address\"\n"
1141+
"\nAdd a witness address for a script (with pubkey or redeemscript known).\n"
1142+
"It returns the witness script.\n"
1143+
1144+
"\nArguments:\n"
1145+
"1. \"address\" (string, required) An address known to the wallet\n"
1146+
1147+
"\nResult:\n"
1148+
"\"witnessaddress\", (string) The value of the new address (P2SH of witness script).\n"
1149+
"}\n"
1150+
;
1151+
throw runtime_error(msg);
1152+
}
1153+
1154+
CBitcoinAddress address(params[0].get_str());
1155+
if (!address.IsValid())
1156+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
1157+
1158+
Witnessifier w;
1159+
CTxDestination dest = address.Get();
1160+
bool ret = boost::apply_visitor(w, dest);
1161+
if (!ret) {
1162+
throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet");
1163+
}
1164+
1165+
return CBitcoinAddress(w.result).ToString();
1166+
}
10981167

10991168
struct tallyitem
11001169
{
@@ -2555,6 +2624,7 @@ static const CRPCCommand commands[] =
25552624
{ "hidden", "resendwallettransactions", &resendwallettransactions, true },
25562625
{ "wallet", "abandontransaction", &abandontransaction, false },
25572626
{ "wallet", "addmultisigaddress", &addmultisigaddress, true },
2627+
{ "wallet", "addwitnessaddress", &addwitnessaddress, true },
25582628
{ "wallet", "backupwallet", &backupwallet, true },
25592629
{ "wallet", "dumpprivkey", &dumpprivkey, true },
25602630
{ "wallet", "dumpwallet", &dumpwallet, true },

0 commit comments

Comments
 (0)