diff options
author | fanquake <fanquake@gmail.com> | 2022-04-29 12:07:01 +0100 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2022-04-29 12:20:10 +0100 |
commit | 91ac12be44262deaeb918c67495dd16717548144 (patch) | |
tree | 867e0129afd0412bbbb219a684b7887ab4ece307 /src | |
parent | 91a67361364691e765982d6d6f6dafc032423aea (diff) | |
parent | fa60169811d6991a116bd37e1ff58049d2beee77 (diff) | |
download | bitcoin-91ac12be44262deaeb918c67495dd16717548144.tar.xz |
Merge bitcoin/bitcoin#25013: Remove cs_main from verifymessage, move msg utils to new file
fa60169811d6991a116bd37e1ff58049d2beee77 rpc: Move signmessage RPC util to new file (MacroFake)
fa9425177e6be2c53fb5c1333636fa4d678ab401 Remove cs_main from verifymessage (MacroFake)
Pull request description:
The `verifymessage` RPC has several issues:
* It takes `cs_main` for no reason, blocking progress on removing the `cs_main` global mutex.
* It is located in a file called `misc`, which is not a very helpful name.
Fix all issues.
ACKs for top commit:
vincenzopalazzo:
ACK https://github.com/bitcoin/bitcoin/pull/25013/commits/fa60169811d6991a116bd37e1ff58049d2beee77
Tree-SHA512: c71a1f481b828e0a544405fecbbc7ca44e66ea46b498d7aed1f1c584d6a99724deb13e89d90b9d5cdeecbce293e6a41e9f7ae299543f6d761bf9e7a839b6c7f3
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/rpc/misc.cpp | 96 | ||||
-rw-r--r-- | src/rpc/register.h | 2 | ||||
-rw-r--r-- | src/rpc/signmessage.cpp | 113 |
4 files changed, 117 insertions, 95 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index f77c2f919c..65151582fb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -386,6 +386,7 @@ libbitcoin_node_a_SOURCES = \ rpc/rawtransaction.cpp \ rpc/server.cpp \ rpc/server_util.cpp \ + rpc/signmessage.cpp \ rpc/txoutproof.cpp \ script/sigcache.cpp \ shutdown.cpp \ diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 98d751e69d..7525b859ee 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -14,14 +14,13 @@ #include <key_io.h> #include <node/context.h> #include <outputtype.h> -#include <rpc/blockchain.h> #include <rpc/server.h> #include <rpc/server_util.h> #include <rpc/util.h> #include <scheduler.h> #include <script/descriptor.h> +#include <univalue.h> #include <util/check.h> -#include <util/message.h> // For MessageSign(), MessageVerify() #include <util/strencodings.h> #include <util/syscall_sandbox.h> #include <util/system.h> @@ -33,8 +32,6 @@ #include <malloc.h> #endif -#include <univalue.h> - using node::NodeContext; static RPCHelpMan validateaddress() @@ -311,95 +308,6 @@ static RPCHelpMan deriveaddresses() }; } -static RPCHelpMan verifymessage() -{ - return RPCHelpMan{"verifymessage", - "Verify a signed message.", - { - {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the signature."}, - {"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."}, - {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."}, - }, - RPCResult{ - RPCResult::Type::BOOL, "", "If the signature is verified or not." - }, - RPCExamples{ - "\nUnlock the wallet for 30 seconds\n" - + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") + - "\nCreate the signature\n" - + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") + - "\nVerify the signature\n" - + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"") - }, - [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue -{ - LOCK(cs_main); - - std::string strAddress = request.params[0].get_str(); - std::string strSign = request.params[1].get_str(); - std::string strMessage = request.params[2].get_str(); - - switch (MessageVerify(strAddress, strSign, strMessage)) { - case MessageVerificationResult::ERR_INVALID_ADDRESS: - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); - case MessageVerificationResult::ERR_ADDRESS_NO_KEY: - throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); - case MessageVerificationResult::ERR_MALFORMED_SIGNATURE: - throw JSONRPCError(RPC_TYPE_ERROR, "Malformed base64 encoding"); - case MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED: - case MessageVerificationResult::ERR_NOT_SIGNED: - return false; - case MessageVerificationResult::OK: - return true; - } - - return false; -}, - }; -} - -static RPCHelpMan signmessagewithprivkey() -{ - return RPCHelpMan{"signmessagewithprivkey", - "\nSign a message with the private key of an address\n", - { - {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."}, - {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."}, - }, - RPCResult{ - RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64" - }, - RPCExamples{ - "\nCreate the signature\n" - + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") + - "\nVerify the signature\n" - + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") - }, - [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue -{ - std::string strPrivkey = request.params[0].get_str(); - std::string strMessage = request.params[1].get_str(); - - CKey key = DecodeSecret(strPrivkey); - if (!key.IsValid()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); - } - - std::string signature; - - if (!MessageSign(key, strMessage, signature)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed"); - } - - return signature; -}, - }; -} - static RPCHelpMan setmocktime() { return RPCHelpMan{"setmocktime", @@ -799,8 +707,6 @@ void RegisterMiscRPCCommands(CRPCTable& t) {"util", &createmultisig}, {"util", &deriveaddresses}, {"util", &getdescriptorinfo}, - {"util", &verifymessage}, - {"util", &signmessagewithprivkey}, {"util", &getindexinfo}, {"hidden", &setmocktime}, {"hidden", &mockscheduler}, diff --git a/src/rpc/register.h b/src/rpc/register.h index 5a604ad428..f3dba08b6c 100644 --- a/src/rpc/register.h +++ b/src/rpc/register.h @@ -16,6 +16,7 @@ void RegisterNetRPCCommands(CRPCTable &tableRPC); void RegisterMiscRPCCommands(CRPCTable &tableRPC); void RegisterMiningRPCCommands(CRPCTable &tableRPC); void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC); +void RegisterSignMessageRPCCommands(CRPCTable&); void RegisterSignerRPCCommands(CRPCTable &tableRPC); static inline void RegisterAllCoreRPCCommands(CRPCTable &t) @@ -27,6 +28,7 @@ static inline void RegisterAllCoreRPCCommands(CRPCTable &t) RegisterMiscRPCCommands(t); RegisterMiningRPCCommands(t); RegisterRawTransactionRPCCommands(t); + RegisterSignMessageRPCCommands(t); #ifdef ENABLE_EXTERNAL_SIGNER RegisterSignerRPCCommands(t); #endif // ENABLE_EXTERNAL_SIGNER diff --git a/src/rpc/signmessage.cpp b/src/rpc/signmessage.cpp new file mode 100644 index 0000000000..8c752ba1fd --- /dev/null +++ b/src/rpc/signmessage.cpp @@ -0,0 +1,113 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <key.h> +#include <key_io.h> +#include <rpc/protocol.h> +#include <rpc/request.h> +#include <rpc/server.h> +#include <rpc/util.h> +#include <univalue.h> +#include <util/message.h> + +#include <string> + +static RPCHelpMan verifymessage() +{ + return RPCHelpMan{"verifymessage", + "Verify a signed message.", + { + {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the signature."}, + {"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."}, + {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."}, + }, + RPCResult{ + RPCResult::Type::BOOL, "", "If the signature is verified or not." + }, + RPCExamples{ + "\nUnlock the wallet for 30 seconds\n" + + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") + + "\nCreate the signature\n" + + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") + + "\nVerify the signature\n" + + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"") + }, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue + { + std::string strAddress = request.params[0].get_str(); + std::string strSign = request.params[1].get_str(); + std::string strMessage = request.params[2].get_str(); + + switch (MessageVerify(strAddress, strSign, strMessage)) { + case MessageVerificationResult::ERR_INVALID_ADDRESS: + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + case MessageVerificationResult::ERR_ADDRESS_NO_KEY: + throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); + case MessageVerificationResult::ERR_MALFORMED_SIGNATURE: + throw JSONRPCError(RPC_TYPE_ERROR, "Malformed base64 encoding"); + case MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED: + case MessageVerificationResult::ERR_NOT_SIGNED: + return false; + case MessageVerificationResult::OK: + return true; + } + + return false; + }, + }; +} + +static RPCHelpMan signmessagewithprivkey() +{ + return RPCHelpMan{"signmessagewithprivkey", + "\nSign a message with the private key of an address\n", + { + {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."}, + {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."}, + }, + RPCResult{ + RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64" + }, + RPCExamples{ + "\nCreate the signature\n" + + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") + + "\nVerify the signature\n" + + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") + }, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue + { + std::string strPrivkey = request.params[0].get_str(); + std::string strMessage = request.params[1].get_str(); + + CKey key = DecodeSecret(strPrivkey); + if (!key.IsValid()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); + } + + std::string signature; + + if (!MessageSign(key, strMessage, signature)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed"); + } + + return signature; + }, + }; +} + +void RegisterSignMessageRPCCommands(CRPCTable& t) +{ + static const CRPCCommand commands[]{ + {"util", &verifymessage}, + {"util", &signmessagewithprivkey}, + }; + for (const auto& c : commands) { + t.appendCommand(c.name, &c); + } +} |