aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci/test/06_script_b.sh6
-rw-r--r--src/Makefile.am1
-rw-r--r--src/rpc/misc.cpp96
-rw-r--r--src/rpc/register.h2
-rw-r--r--src/rpc/signmessage.cpp113
5 files changed, 122 insertions, 96 deletions
diff --git a/ci/test/06_script_b.sh b/ci/test/06_script_b.sh
index afab4c5e78..40547f19ef 100755
--- a/ci/test/06_script_b.sh
+++ b/ci/test/06_script_b.sh
@@ -38,7 +38,11 @@ if [ "${RUN_TIDY}" = "true" ]; then
export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST/src/"
CI_EXEC run-clang-tidy "${MAKEJOBS}"
export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST/"
- CI_EXEC "python3 ${BASE_SCRATCH_DIR}/iwyu/include-what-you-use/iwyu_tool.py src/compat src/init -p . ${MAKEJOBS} -- -Xiwyu --cxx17ns -Xiwyu --mapping_file=${BASE_BUILD_DIR}/bitcoin-$HOST/contrib/devtools/iwyu/bitcoin.core.imp"
+ CI_EXEC "python3 ${BASE_SCRATCH_DIR}/iwyu/include-what-you-use/iwyu_tool.py"\
+ " src/compat"\
+ " src/init"\
+ " src/rpc/signmessage.cpp"\
+ " -p . ${MAKEJOBS} -- -Xiwyu --cxx17ns -Xiwyu --mapping_file=${BASE_BUILD_DIR}/bitcoin-$HOST/contrib/devtools/iwyu/bitcoin.core.imp"
fi
if [ "$RUN_SECURITY_TESTS" = "true" ]; then
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);
+ }
+}