diff options
-rw-r--r-- | depends/builders/darwin.mk | 2 | ||||
-rw-r--r-- | doc/build-unix.md | 18 | ||||
-rwxr-xr-x | qa/pull-tester/rpc-tests.py | 1 | ||||
-rwxr-xr-x | qa/rpc-tests/signmessages.py | 40 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/rpc/misc.cpp | 43 | ||||
-rw-r--r-- | src/tinyformat.h | 2 | ||||
-rw-r--r-- | src/txmempool.cpp | 2 | ||||
-rw-r--r-- | src/txmempool.h | 4 | ||||
-rw-r--r-- | src/util.h | 43 |
10 files changed, 126 insertions, 31 deletions
diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index 200d6ed22a..27f550ab03 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -11,7 +11,7 @@ build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONN #darwin host on darwin builder. overrides darwin host preferences. darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) -darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) +darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++ darwin_AR:=$(shell xcrun -f ar) darwin_RANLIB:=$(shell xcrun -f ranlib) darwin_STRIP:=$(shell xcrun -f strip) diff --git a/doc/build-unix.md b/doc/build-unix.md index dc754fc733..27c57088af 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -124,6 +124,24 @@ libqrencode (optional) can be installed with: Once these are installed, they will be found by configure and a bitcoin-qt executable will be built by default. +Dependency Build Instructions: Fedora +------------------------------------- +Build requirements: + + sudo dnf install libtool make autoconf automake openssl-devel libevent-devel boost-devel libdb4-devel libdb4-cxx-devel + +Optional: + + sudo dnf install miniupnpc-devel + +To build with Qt 5 (recommended) you need the following: + + sudo dnf install qt5-qttools-devel qtr5-qtbase-devel protobuf-devel + +libqrencode (optional) can be installed with: + + sudo dnf install qrencode-devel + Notes ----- The release is built with GCC and then "strip bitcoind" to strip the debug diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index c0637209e3..26142c35e9 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -123,6 +123,7 @@ testScripts = [ 'abandonconflict.py', 'p2p-versionbits-warning.py', 'importprunedfunds.py', + 'signmessages.py' ] if ENABLE_ZMQ: testScripts.append('zmq_test.py') diff --git a/qa/rpc-tests/signmessages.py b/qa/rpc-tests/signmessages.py new file mode 100755 index 0000000000..ff22f35300 --- /dev/null +++ b/qa/rpc-tests/signmessages.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python2 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + + +class SignMessagesTest(BitcoinTestFramework): + """Tests RPC commands for signing and verifying messages.""" + + def setup_chain(self): + print('Initializing test directory ' + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 1) + + def setup_network(self, split=False): + self.nodes = start_nodes(1, self.options.tmpdir) + self.is_network_split = False + + def run_test(self): + message = 'This is just a test message' + + # Test the signing with a privkey + privKey = 'cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N' + address = 'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB' + signature = self.nodes[0].signmessagewithprivkey(privKey, message) + + # Verify the message + assert(self.nodes[0].verifymessage(address, signature, message)) + + # Test the signing with an address with wallet + address = self.nodes[0].getnewaddress() + signature = self.nodes[0].signmessage(address, message) + + # Verify the message + assert(self.nodes[0].verifymessage(address, signature, message)) + +if __name__ == '__main__': + SignMessagesTest().main() diff --git a/src/main.cpp b/src/main.cpp index 11ccab253e..2777245654 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1468,7 +1468,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::P if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it int nHeight = -1; { - CCoinsViewCache &view = *pcoinsTip; + const CCoinsViewCache& view = *pcoinsTip; const CCoins* coins = view.AccessCoins(hash); if (coins) nHeight = coins->nHeight; diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index e8a099b445..09f5185781 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -366,6 +366,48 @@ UniValue verifymessage(const UniValue& params, bool fHelp) return (pubkey.GetID() == keyID); } +UniValue signmessagewithprivkey(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "signmessagewithprivkey \"privkey\" \"message\"\n" + "\nSign a message with the private key of an address\n" + "\nArguments:\n" + "1. \"privkey\" (string, required) The private key to sign the message with.\n" + "2. \"message\" (string, required) The message to create a signature of.\n" + "\nResult:\n" + "\"signature\" (string) The signature of the message encoded in base 64\n" + "\nExamples:\n" + "\nCreate the signature\n" + + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") + + "\nVerify the signature\n" + + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") + + "\nAs json rpc\n" + + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") + ); + + string strPrivkey = params[0].get_str(); + string strMessage = params[1].get_str(); + + CBitcoinSecret vchSecret; + bool fGood = vchSecret.SetString(strPrivkey); + if (!fGood) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); + CKey key = vchSecret.GetKey(); + if (!key.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range"); + + CHashWriter ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << strMessage; + + vector<unsigned char> vchSig; + if (!key.SignCompact(ss.GetHash(), vchSig)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed"); + + return EncodeBase64(&vchSig[0], vchSig.size()); +} + UniValue setmocktime(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -404,6 +446,7 @@ static const CRPCCommand commands[] = { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ { "util", "createmultisig", &createmultisig, true }, { "util", "verifymessage", &verifymessage, true }, + { "util", "signmessagewithprivkey", &signmessagewithprivkey, true }, /* Not shown in help */ { "hidden", "setmocktime", &setmocktime, true }, diff --git a/src/tinyformat.h b/src/tinyformat.h index 73d49a1fe4..c6ec0419b3 100644 --- a/src/tinyformat.h +++ b/src/tinyformat.h @@ -113,7 +113,7 @@ namespace tfm = tinyformat; // Define for C++11 variadic templates which make the code shorter & more // general. If you don't define this, C++11 support is autodetected below. -// #define TINYFORMAT_USE_VARIADIC_TEMPLATES +#define TINYFORMAT_USE_VARIADIC_TEMPLATES //------------------------------------------------------------------------------ diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 52c7793118..420f6896b3 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -885,7 +885,7 @@ bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const return true; } -CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } +CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView* baseIn, const CTxMemPool& mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { } bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const { // If an entry in the mempool exists, always return that one, as it's guaranteed to never diff --git a/src/txmempool.h b/src/txmempool.h index de4ba0b371..d17e3322d3 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -672,10 +672,10 @@ private: class CCoinsViewMemPool : public CCoinsViewBacked { protected: - CTxMemPool &mempool; + const CTxMemPool& mempool; public: - CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn); + CCoinsViewMemPool(CCoinsView* baseIn, const CTxMemPool& mempoolIn); bool GetCoins(const uint256 &txid, CCoins &coins) const; bool HaveCoins(const uint256 &txid) const; }; diff --git a/src/util.h b/src/util.h index ac099f1184..25c9b733e8 100644 --- a/src/util.h +++ b/src/util.h @@ -76,40 +76,33 @@ int LogPrintStr(const std::string &str); #define LogPrintf(...) LogPrint(NULL, __VA_ARGS__) -/** - * When we switch to C++11, this can be switched to variadic templates instead - * of this macro-based construction (see tinyformat.h). - */ -#define MAKE_ERROR_AND_LOG_FUNC(n) \ - /** Print to debug.log if -debug=category switch is given OR category is NULL. */ \ - template<TINYFORMAT_ARGTYPES(n)> \ - static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \ - { \ - if(!LogAcceptCategory(category)) return 0; \ - return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \ - } \ - /** Log error and return false */ \ - template<TINYFORMAT_ARGTYPES(n)> \ - static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \ - { \ - LogPrintStr("ERROR: " + tfm::format(format, TINYFORMAT_PASSARGS(n)) + "\n"); \ - return false; \ - } +template<typename T1, typename... Args> +static inline int LogPrint(const char* category, const char* fmt, const T1& v1, const Args&... args) +{ + if(!LogAcceptCategory(category)) return 0; \ + return LogPrintStr(tfm::format(fmt, v1, args...)); +} -TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_AND_LOG_FUNC) +template<typename T1, typename... Args> +bool error(const char* fmt, const T1& v1, const Args&... args) +{ + LogPrintStr("ERROR: " + tfm::format(fmt, v1, args...) + "\n"); + return false; +} /** * Zero-arg versions of logging and error, these are not covered by - * TINYFORMAT_FOREACH_ARGNUM + * the variadic templates above (and don't take format arguments but + * bare strings). */ -static inline int LogPrint(const char* category, const char* format) +static inline int LogPrint(const char* category, const char* s) { if(!LogAcceptCategory(category)) return 0; - return LogPrintStr(format); + return LogPrintStr(s); } -static inline bool error(const char* format) +static inline bool error(const char* s) { - LogPrintStr(std::string("ERROR: ") + format + "\n"); + LogPrintStr(std::string("ERROR: ") + s + "\n"); return false; } |