Skip to content

Commit e278f12

Browse files
committed
Support BIP173 in addwitnessaddress
1 parent c091b99 commit e278f12

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

src/rpc/client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
129129
{ "logging", 0, "include" },
130130
{ "logging", 1, "exclude" },
131131
{ "disconnectnode", 1, "nodeid" },
132+
{ "addwitnessaddress", 1, "p2sh" },
132133
// Echo with conversion (For testing only)
133134
{ "echojson", 0, "arg0" },
134135
{ "echojson", 1, "arg1" },

src/wallet/rpcwallet.cpp

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,9 +1154,10 @@ class Witnessifier : public boost::static_visitor<bool>
11541154
{
11551155
public:
11561156
CWallet * const pwallet;
1157-
CScriptID result;
1157+
CTxDestination result;
1158+
bool already_witness;
11581159

1159-
explicit Witnessifier(CWallet *_pwallet) : pwallet(_pwallet) {}
1160+
explicit Witnessifier(CWallet *_pwallet) : pwallet(_pwallet), already_witness(false) {}
11601161

11611162
bool operator()(const CKeyID &keyID) {
11621163
if (pwallet) {
@@ -1170,9 +1171,7 @@ class Witnessifier : public boost::static_visitor<bool>
11701171
!VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
11711172
return false;
11721173
}
1173-
pwallet->AddCScript(witscript);
1174-
result = CScriptID(witscript);
1175-
return true;
1174+
return ExtractDestination(witscript, result);
11761175
}
11771176
return false;
11781177
}
@@ -1183,7 +1182,8 @@ class Witnessifier : public boost::static_visitor<bool>
11831182
int witnessversion;
11841183
std::vector<unsigned char> witprog;
11851184
if (subscript.IsWitnessProgram(witnessversion, witprog)) {
1186-
result = scriptID;
1185+
ExtractDestination(subscript, result);
1186+
already_witness = true;
11871187
return true;
11881188
}
11891189
CScript witscript = GetScriptForWitness(subscript);
@@ -1195,13 +1195,25 @@ class Witnessifier : public boost::static_visitor<bool>
11951195
!VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
11961196
return false;
11971197
}
1198-
pwallet->AddCScript(witscript);
1199-
result = CScriptID(witscript);
1200-
return true;
1198+
return ExtractDestination(witscript, result);
12011199
}
12021200
return false;
12031201
}
12041202

1203+
bool operator()(const WitnessV0KeyHash& id)
1204+
{
1205+
already_witness = true;
1206+
result = id;
1207+
return true;
1208+
}
1209+
1210+
bool operator()(const WitnessV0ScriptHash& id)
1211+
{
1212+
already_witness = true;
1213+
result = id;
1214+
return true;
1215+
}
1216+
12051217
template<typename T>
12061218
bool operator()(const T& dest) { return false; }
12071219
};
@@ -1213,17 +1225,18 @@ UniValue addwitnessaddress(const JSONRPCRequest& request)
12131225
return NullUniValue;
12141226
}
12151227

1216-
if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
1228+
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
12171229
{
1218-
std::string msg = "addwitnessaddress \"address\"\n"
1230+
std::string msg = "addwitnessaddress \"address\" ( p2sh )\n"
12191231
"\nAdd a witness address for a script (with pubkey or redeemscript known).\n"
12201232
"It returns the witness script.\n"
12211233

12221234
"\nArguments:\n"
12231235
"1. \"address\" (string, required) An address known to the wallet\n"
1236+
"2. p2sh (bool, optional, default=true) Embed inside P2SH\n"
12241237

12251238
"\nResult:\n"
1226-
"\"witnessaddress\", (string) The value of the new address (P2SH of witness script).\n"
1239+
"\"witnessaddress\", (string) The value of the new address (P2SH or BIP173).\n"
12271240
"}\n"
12281241
;
12291242
throw std::runtime_error(msg);
@@ -1241,13 +1254,31 @@ UniValue addwitnessaddress(const JSONRPCRequest& request)
12411254
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
12421255
}
12431256

1257+
bool p2sh = true;
1258+
if (!request.params[1].isNull()) {
1259+
p2sh = request.params[1].get_bool();
1260+
}
1261+
12441262
Witnessifier w(pwallet);
12451263
bool ret = boost::apply_visitor(w, dest);
12461264
if (!ret) {
12471265
throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed");
12481266
}
12491267

1250-
pwallet->SetAddressBook(w.result, "", "receive");
1268+
CScript witprogram = GetScriptForDestination(w.result);
1269+
1270+
if (p2sh) {
1271+
w.result = CScriptID(witprogram);
1272+
}
1273+
1274+
if (w.already_witness) {
1275+
if (!(dest == w.result)) {
1276+
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot convert between witness address types");
1277+
}
1278+
} else {
1279+
pwallet->AddCScript(witprogram);
1280+
pwallet->SetAddressBook(w.result, "", "receive");
1281+
}
12511282

12521283
return EncodeDestination(w.result);
12531284
}
@@ -3200,7 +3231,7 @@ static const CRPCCommand commands[] =
32003231
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
32013232
{ "wallet", "abortrescan", &abortrescan, {} },
32023233
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account"} },
3203-
{ "wallet", "addwitnessaddress", &addwitnessaddress, {"address"} },
3234+
{ "wallet", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} },
32043235
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
32053236
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
32063237
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} },

0 commit comments

Comments
 (0)