|
|
@ -1154,9 +1154,10 @@ class Witnessifier : public boost::static_visitor<bool> |
|
|
|
{ |
|
|
|
{ |
|
|
|
public: |
|
|
|
public: |
|
|
|
CWallet * const pwallet; |
|
|
|
CWallet * const pwallet; |
|
|
|
CScriptID result; |
|
|
|
CTxDestination result; |
|
|
|
|
|
|
|
bool already_witness; |
|
|
|
|
|
|
|
|
|
|
|
explicit Witnessifier(CWallet *_pwallet) : pwallet(_pwallet) {} |
|
|
|
explicit Witnessifier(CWallet *_pwallet) : pwallet(_pwallet), already_witness(false) {} |
|
|
|
|
|
|
|
|
|
|
|
bool operator()(const CKeyID &keyID) { |
|
|
|
bool operator()(const CKeyID &keyID) { |
|
|
|
if (pwallet) { |
|
|
|
if (pwallet) { |
|
|
@ -1170,9 +1171,7 @@ public: |
|
|
|
!VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) { |
|
|
|
!VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
pwallet->AddCScript(witscript); |
|
|
|
return ExtractDestination(witscript, result); |
|
|
|
result = CScriptID(witscript); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
@ -1183,7 +1182,8 @@ public: |
|
|
|
int witnessversion; |
|
|
|
int witnessversion; |
|
|
|
std::vector<unsigned char> witprog; |
|
|
|
std::vector<unsigned char> witprog; |
|
|
|
if (subscript.IsWitnessProgram(witnessversion, witprog)) { |
|
|
|
if (subscript.IsWitnessProgram(witnessversion, witprog)) { |
|
|
|
result = scriptID; |
|
|
|
ExtractDestination(subscript, result); |
|
|
|
|
|
|
|
already_witness = true; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
CScript witscript = GetScriptForWitness(subscript); |
|
|
|
CScript witscript = GetScriptForWitness(subscript); |
|
|
@ -1195,13 +1195,25 @@ public: |
|
|
|
!VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) { |
|
|
|
!VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
pwallet->AddCScript(witscript); |
|
|
|
return ExtractDestination(witscript, result); |
|
|
|
result = CScriptID(witscript); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool operator()(const WitnessV0KeyHash& id) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
already_witness = true; |
|
|
|
|
|
|
|
result = id; |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool operator()(const WitnessV0ScriptHash& id) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
already_witness = true; |
|
|
|
|
|
|
|
result = id; |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<typename T> |
|
|
|
template<typename T> |
|
|
|
bool operator()(const T& dest) { return false; } |
|
|
|
bool operator()(const T& dest) { return false; } |
|
|
|
}; |
|
|
|
}; |
|
|
@ -1213,17 +1225,18 @@ UniValue addwitnessaddress(const JSONRPCRequest& request) |
|
|
|
return NullUniValue; |
|
|
|
return NullUniValue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (request.fHelp || request.params.size() < 1 || request.params.size() > 1) |
|
|
|
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) |
|
|
|
{ |
|
|
|
{ |
|
|
|
std::string msg = "addwitnessaddress \"address\"\n" |
|
|
|
std::string msg = "addwitnessaddress \"address\" ( p2sh )\n" |
|
|
|
"\nAdd a witness address for a script (with pubkey or redeemscript known).\n" |
|
|
|
"\nAdd a witness address for a script (with pubkey or redeemscript known).\n" |
|
|
|
"It returns the witness script.\n" |
|
|
|
"It returns the witness script.\n" |
|
|
|
|
|
|
|
|
|
|
|
"\nArguments:\n" |
|
|
|
"\nArguments:\n" |
|
|
|
"1. \"address\" (string, required) An address known to the wallet\n" |
|
|
|
"1. \"address\" (string, required) An address known to the wallet\n" |
|
|
|
|
|
|
|
"2. p2sh (bool, optional, default=true) Embed inside P2SH\n" |
|
|
|
|
|
|
|
|
|
|
|
"\nResult:\n" |
|
|
|
"\nResult:\n" |
|
|
|
"\"witnessaddress\", (string) The value of the new address (P2SH of witness script).\n" |
|
|
|
"\"witnessaddress\", (string) The value of the new address (P2SH or BIP173).\n" |
|
|
|
"}\n" |
|
|
|
"}\n" |
|
|
|
; |
|
|
|
; |
|
|
|
throw std::runtime_error(msg); |
|
|
|
throw std::runtime_error(msg); |
|
|
@ -1241,13 +1254,31 @@ UniValue addwitnessaddress(const JSONRPCRequest& request) |
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); |
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool p2sh = true; |
|
|
|
|
|
|
|
if (!request.params[1].isNull()) { |
|
|
|
|
|
|
|
p2sh = request.params[1].get_bool(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Witnessifier w(pwallet); |
|
|
|
Witnessifier w(pwallet); |
|
|
|
bool ret = boost::apply_visitor(w, dest); |
|
|
|
bool ret = boost::apply_visitor(w, dest); |
|
|
|
if (!ret) { |
|
|
|
if (!ret) { |
|
|
|
throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed"); |
|
|
|
throw JSONRPCError(RPC_WALLET_ERROR, "Public key or redeemscript not known to wallet, or the key is uncompressed"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CScript witprogram = GetScriptForDestination(w.result); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (p2sh) { |
|
|
|
|
|
|
|
w.result = CScriptID(witprogram); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (w.already_witness) { |
|
|
|
|
|
|
|
if (!(dest == w.result)) { |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot convert between witness address types"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
pwallet->AddCScript(witprogram); |
|
|
|
pwallet->SetAddressBook(w.result, "", "receive"); |
|
|
|
pwallet->SetAddressBook(w.result, "", "receive"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return EncodeDestination(w.result); |
|
|
|
return EncodeDestination(w.result); |
|
|
|
} |
|
|
|
} |
|
|
@ -3200,7 +3231,7 @@ static const CRPCCommand commands[] = |
|
|
|
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} }, |
|
|
|
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} }, |
|
|
|
{ "wallet", "abortrescan", &abortrescan, {} }, |
|
|
|
{ "wallet", "abortrescan", &abortrescan, {} }, |
|
|
|
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account"} }, |
|
|
|
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account"} }, |
|
|
|
{ "wallet", "addwitnessaddress", &addwitnessaddress, {"address"} }, |
|
|
|
{ "wallet", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} }, |
|
|
|
{ "wallet", "backupwallet", &backupwallet, {"destination"} }, |
|
|
|
{ "wallet", "backupwallet", &backupwallet, {"destination"} }, |
|
|
|
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} }, |
|
|
|
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} }, |
|
|
|
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} }, |
|
|
|
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} }, |
|
|
|