aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Chow <achow101-github@achow101.com>2021-06-04 17:35:47 -0400
committerAndrew Chow <achow101-github@achow101.com>2021-06-22 21:57:04 -0400
commit87a0e7a3b7c0ffd545e537bd497cdc3e67d045f6 (patch)
tree0b7a64337d330fcbeefe685b2808fa573f375e71 /src
parent6dbe4d10728f882986ed0d9ed77bc736f051c662 (diff)
downloadbitcoin-87a0e7a3b7c0ffd545e537bd497cdc3e67d045f6.tar.xz
Disallow bech32m addresses for legacy wallet things
We don't want the legacy wallet to ever have bech32m addresses so don't allow importing them. This includes addmultisigaddress as that is a legacy wallet only RPC Additionally, bech32m multisigs are not available yet, so disallow them in createmultisig.
Diffstat (limited to 'src')
-rw-r--r--src/outputtype.cpp16
-rw-r--r--src/outputtype.h3
-rw-r--r--src/rpc/misc.cpp3
-rw-r--r--src/script/descriptor.cpp16
-rw-r--r--src/wallet/rpcdump.cpp9
-rw-r--r--src/wallet/rpcwallet.cpp9
-rw-r--r--src/wallet/scriptpubkeyman.cpp5
7 files changed, 45 insertions, 16 deletions
diff --git a/src/outputtype.cpp b/src/outputtype.cpp
index 9748fe24c7..8ede7b9974 100644
--- a/src/outputtype.cpp
+++ b/src/outputtype.cpp
@@ -108,3 +108,19 @@ CTxDestination AddAndGetDestinationForScript(FillableSigningProvider& keystore,
} // no default case, so the compiler can warn about missing cases
assert(false);
}
+
+std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& dest) {
+ if (std::holds_alternative<PKHash>(dest) ||
+ std::holds_alternative<ScriptHash>(dest)) {
+ return OutputType::LEGACY;
+ }
+ if (std::holds_alternative<WitnessV0KeyHash>(dest) ||
+ std::holds_alternative<WitnessV0ScriptHash>(dest)) {
+ return OutputType::BECH32;
+ }
+ if (std::holds_alternative<WitnessV1Taproot>(dest) ||
+ std::holds_alternative<WitnessUnknown>(dest)) {
+ return OutputType::BECH32M;
+ }
+ return std::nullopt;
+}
diff --git a/src/outputtype.h b/src/outputtype.h
index 8727d3f543..2b83235cd0 100644
--- a/src/outputtype.h
+++ b/src/outputtype.h
@@ -47,4 +47,7 @@ std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key);
*/
CTxDestination AddAndGetDestinationForScript(FillableSigningProvider& keystore, const CScript& script, OutputType);
+/** Get the OutputType for a CTxDestination */
+std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& dest);
+
#endif // BITCOIN_OUTPUTTYPE_H
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index ab239fe79c..5178ce60e8 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -131,6 +131,9 @@ static RPCHelpMan createmultisig()
if (!ParseOutputType(request.params[2].get_str(), output_type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[2].get_str()));
}
+ if (output_type == OutputType::BECH32M) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "createmultisig cannot create bech32m multisig addresses");
+ }
}
// Construct using pay-to-script-hash:
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 5da249b7f9..d796ed26aa 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -640,22 +640,6 @@ public:
std::optional<OutputType> GetOutputType() const override { return std::nullopt; }
};
-static std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& dest) {
- if (std::holds_alternative<PKHash>(dest) ||
- std::holds_alternative<ScriptHash>(dest)) {
- return OutputType::LEGACY;
- }
- if (std::holds_alternative<WitnessV0KeyHash>(dest) ||
- std::holds_alternative<WitnessV0ScriptHash>(dest)) {
- return OutputType::BECH32;
- }
- if (std::holds_alternative<WitnessV1Taproot>(dest) ||
- std::holds_alternative<WitnessUnknown>(dest)) {
- return OutputType::BECH32M;
- }
- return std::nullopt;
-}
-
/** A parsed addr(A) descriptor. */
class AddressDescriptor final : public DescriptorImpl
{
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 4e9ba83ead..35649ab02c 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -286,6 +286,9 @@ RPCHelpMan importaddress()
if (fP2SH) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
}
+ if (OutputTypeFromDestination(dest) == OutputType::BECH32M) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Bech32m addresses cannot be imported into legacy wallets");
+ }
pwallet->MarkDirty();
@@ -962,6 +965,9 @@ static UniValue ProcessImportLegacy(ImportData& import_data, std::map<CKeyID, CP
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address \"" + output + "\"");
}
+ if (OutputTypeFromDestination(dest) == OutputType::BECH32M) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Bech32m addresses cannot be imported into legacy wallets");
+ }
script = GetScriptForDestination(dest);
} else {
if (!IsHex(output)) {
@@ -1086,6 +1092,9 @@ static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID
if (!parsed_desc) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
}
+ if (parsed_desc->GetOutputType() == OutputType::BECH32M) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Bech32m descriptors cannot be imported into legacy wallets");
+ }
have_solving_data = parsed_desc->IsSolvable();
const bool watch_only = data.exists("watchonly") ? data["watchonly"].get_bool() : false;
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 8b1b6c6d95..951f575c2f 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -269,6 +269,9 @@ static RPCHelpMan getnewaddress()
if (!ParseOutputType(request.params[1].get_str(), output_type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[1].get_str()));
}
+ if (output_type == OutputType::BECH32M && pwallet->GetLegacyScriptPubKeyMan()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Legacy wallets cannot provide bech32m addresses");
+ }
}
CTxDestination dest;
@@ -313,6 +316,9 @@ static RPCHelpMan getrawchangeaddress()
if (!ParseOutputType(request.params[0].get_str(), output_type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[0].get_str()));
}
+ if (output_type == OutputType::BECH32M && pwallet->GetLegacyScriptPubKeyMan()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Legacy wallets cannot provide bech32m addresses");
+ }
}
CTxDestination dest;
@@ -1004,6 +1010,9 @@ static RPCHelpMan addmultisigaddress()
if (!ParseOutputType(request.params[3].get_str(), output_type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str()));
}
+ if (output_type == OutputType::BECH32M) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Bech32m multisig addresses cannot be created with legacy wallets");
+ }
}
// Construct using pay-to-script-hash:
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index dedd40694e..2f7729a901 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -26,6 +26,7 @@ bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestinat
error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types").translated;
return false;
}
+ assert(type != OutputType::BECH32M);
LOCK(cs_KeyStore);
error.clear();
@@ -299,6 +300,7 @@ bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool i
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
return false;
}
+ assert(type != OutputType::BECH32M);
LOCK(cs_KeyStore);
if (!CanGetAddresses(internal)) {
@@ -1303,6 +1305,7 @@ void LegacyScriptPubKeyMan::AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const
void LegacyScriptPubKeyMan::KeepDestination(int64_t nIndex, const OutputType& type)
{
+ assert(type != OutputType::BECH32M);
// Remove from key pool
WalletBatch batch(m_storage.GetDatabase());
batch.ErasePool(nIndex);
@@ -1336,6 +1339,7 @@ void LegacyScriptPubKeyMan::ReturnDestination(int64_t nIndex, bool fInternal, co
bool LegacyScriptPubKeyMan::GetKeyFromPool(CPubKey& result, const OutputType type, bool internal)
{
+ assert(type != OutputType::BECH32M);
if (!CanGetAddresses(internal)) {
return false;
}
@@ -1404,6 +1408,7 @@ bool LegacyScriptPubKeyMan::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& key
void LegacyScriptPubKeyMan::LearnRelatedScripts(const CPubKey& key, OutputType type)
{
+ assert(type != OutputType::BECH32M);
if (key.IsCompressed() && (type == OutputType::P2SH_SEGWIT || type == OutputType::BECH32)) {
CTxDestination witdest = WitnessV0KeyHash(key.GetID());
CScript witprog = GetScriptForDestination(witdest);