diff options
Diffstat (limited to 'src')
255 files changed, 13619 insertions, 2992 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 3da833d733..69b3a6d4f1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,6 @@ +DIST_SUBDIRS = secp256k1 AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) -if USE_LIBSECP256K1 -secp256k1/libsecp256k1.la: $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) - @$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) -endif if EMBEDDED_LEVELDB LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include @@ -23,9 +20,7 @@ endif BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) -if USE_LIBSECP256K1 BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include -endif LIBBITCOIN_SERVER=libbitcoin_server.a LIBBITCOIN_WALLET=libbitcoin_wallet.a @@ -35,6 +30,10 @@ LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBBITCOIN_UNIVALUE=univalue/libbitcoin_univalue.a LIBBITCOINQT=qt/libbitcoinqt.a +LIBSECP256K1=secp256k1/libsecp256k1.la + +$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: @@ -50,6 +49,13 @@ BITCOIN_INCLUDES += $(BDB_CPPFLAGS) noinst_LIBRARIES += libbitcoin_wallet.a endif +if BUILD_BITCOIN_LIBS +lib_LTLIBRARIES = libbitcoinconsensus.la +LIBBITCOIN_CONSENSUS=libbitcoinconsensus.la +else +LIBBITCOIN_CONSENSUS= +endif + bin_PROGRAMS = TESTS = @@ -81,8 +87,8 @@ BITCOIN_CORE_H = \ coins.h \ compat.h \ compressor.h \ - core/block.h \ - core/transaction.h \ + primitives/block.h \ + primitives/transaction.h \ core_io.h \ crypter.h \ db.h \ @@ -197,10 +203,18 @@ libbitcoin_wallet_a_SOURCES = \ crypto_libbitcoin_crypto_a_CPPFLAGS = $(BITCOIN_CONFIG_INCLUDES) crypto_libbitcoin_crypto_a_SOURCES = \ crypto/sha1.cpp \ - crypto/sha2.cpp \ + crypto/sha256.cpp \ + crypto/sha512.cpp \ + crypto/hmac_sha256.cpp \ + crypto/rfc6979_hmac_sha256.cpp \ + crypto/hmac_sha512.cpp \ crypto/ripemd160.cpp \ crypto/common.h \ - crypto/sha2.h \ + crypto/sha256.h \ + crypto/sha512.h \ + crypto/hmac_sha256.h \ + crypto/rfc6979_hmac_sha256.h \ + crypto/hmac_sha512.h \ crypto/sha1.h \ crypto/ripemd160.h @@ -221,8 +235,8 @@ libbitcoin_common_a_SOURCES = \ chainparams.cpp \ coins.cpp \ compressor.cpp \ - core/block.cpp \ - core/transaction.cpp \ + primitives/block.cpp \ + primitives/transaction.cpp \ core_read.cpp \ core_write.cpp \ eccryptoverify.cpp \ @@ -245,6 +259,7 @@ libbitcoin_common_a_SOURCES = \ # backward-compatibility objects and their sanity checks are linked. libbitcoin_util_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_util_a_SOURCES = \ + compat/strnlen.cpp \ compat/glibc_sanity.cpp \ compat/glibcxx_sanity.cpp \ chainparamsbase.cpp \ @@ -281,11 +296,8 @@ bitcoind_LDADD = \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) \ $(LIBLEVELDB) \ - $(LIBMEMENV) - -if USE_LIBSECP256K1 - bitcoind_LDADD += secp256k1/libsecp256k1.la -endif + $(LIBMEMENV) \ + $(LIBSECP256K1) if ENABLE_WALLET bitcoind_LDADD += libbitcoin_wallet.a @@ -299,7 +311,7 @@ endif bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES) -bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) +bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) # bitcoin-cli binary # bitcoin_cli_LDADD = \ @@ -312,9 +324,6 @@ bitcoin_cli_LDADD = \ bitcoin_cli_SOURCES = \ bitcoin-cli.cpp -if USE_LIBSECP256K1 - bitcoin_cli_LDADD += secp256k1/libsecp256k1.la -endif bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES) # @@ -323,34 +332,62 @@ bitcoin_tx_LDADD = \ $(LIBBITCOIN_UNIVALUE) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CRYPTO) - -if USE_LIBSECP256K1 - bitcoin_tx_LDADD += secp256k1/libsecp256k1.la -endif - - bitcoin_tx_LDADD += $(BOOST_LIBS) \ + $(LIBBITCOIN_CRYPTO) \ + $(LIBSECP256K1) \ + $(BOOST_LIBS) \ $(CRYPTO_LIBS) bitcoin_tx_SOURCES = bitcoin-tx.cpp bitcoin_tx_CPPFLAGS = $(BITCOIN_INCLUDES) # -bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) +bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoin_cli_SOURCES += bitcoin-cli-res.rc endif -bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) +bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) + +if BUILD_BITCOIN_LIBS +include_HEADERS = script/bitcoinconsensus.h +libbitcoinconsensus_la_SOURCES = \ + primitives/transaction.cpp \ + crypto/hmac_sha512.cpp \ + crypto/sha1.cpp \ + crypto/sha256.cpp \ + crypto/sha512.cpp \ + crypto/ripemd160.cpp \ + eccryptoverify.cpp \ + ecwrapper.cpp \ + hash.cpp \ + pubkey.cpp \ + script/script.cpp \ + script/interpreter.cpp \ + script/bitcoinconsensus.cpp \ + uint256.cpp \ + utilstrencodings.cpp + +if GLIBC_BACK_COMPAT + libbitcoinconsensus_la_SOURCES += compat/glibc_compat.cpp + libbitcoinconsensus_la_SOURCES += compat/glibcxx_compat.cpp +endif + +libbitcoinconsensus_la_LDFLAGS = -no-undefined $(RELDFLAGS) +libbitcoinconsensus_la_LIBADD = $(CRYPTO_LIBS) +libbitcoinconsensus_la_CPPFLAGS = $(CRYPTO_CFLAGS) -I$(builddir)/obj -DBUILD_BITCOIN_INTERNAL +if USE_LIBSECP256K1 +libbitcoinconsensus_la_LIBADD += secp256k1/libsecp256k1.la +endif +endif CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno DISTCLEANFILES = obj/build.h -EXTRA_DIST = leveldb secp256k1 +EXTRA_DIST = leveldb clean-local: -$(MAKE) -C leveldb clean - -$(MAKE) -C secp256k1 clean 2>/dev/null + -$(MAKE) -C secp256k1 clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno -rm -f config.h diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index ac6d60df03..898337ad6f 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -360,11 +360,8 @@ if ENABLE_WALLET qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \ - $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) -if USE_LIBSECP256K1 - qt_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la -endif -qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) + $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) +qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_bitcoin_qt_LIBTOOLFLAGS = --tag CXX #locale/foo.ts -> locale/foo.qm diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 064b531b93..c5392cf307 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -32,11 +32,8 @@ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) \ $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ - $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) -if USE_LIBSECP256K1 - qt_test_test_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la -endif -qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) + $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) +qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 6a8d9e58a4..9e9f478d8f 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -80,17 +80,13 @@ endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \ - $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) + $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) if ENABLE_WALLET test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) endif -if USE_LIBSECP256K1 - test_test_bitcoin_LDADD += secp256k1/libsecp256k1.la -endif - -test_test_bitcoin_LDADD += $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) -test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) +test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) +test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) @@ -108,6 +104,9 @@ bitcoin_test_check: $(TEST_BINARY) FORCE bitcoin_test_clean : FORCE rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY) +check-local: + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check + %.json.h: %.json @$(MKDIR_P) $(@D) @echo "namespace json_tests{" > $@ diff --git a/src/base58.cpp b/src/base58.cpp index d94db2c51b..c594993ea0 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "base58.h" @@ -15,7 +15,7 @@ #include <boost/variant/apply_visitor.hpp> #include <boost/variant/static_visitor.hpp> -/* All alphanumeric characters except for "0", "I", "O", and "l" */ +/** All alphanumeric characters except for "0", "I", "O", and "l" */ static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch) diff --git a/src/base58.h b/src/base58.h index 7cd2d651a1..c4cb96814c 100644 --- a/src/base58.h +++ b/src/base58.h @@ -1,16 +1,16 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -// -// Why base-58 instead of standard base-64 encoding? -// - Don't want 0OIl characters that look the same in some fonts and -// could be used to create visually identical looking account numbers. -// - A string with non-alphanumeric characters is not as easily accepted as an account number. -// - E-mail usually won't line-break if there's no punctuation to break at. -// - Double-clicking selects the whole number as one word if it's all alphanumeric. -// +/** + * Why base-58 instead of standard base-64 encoding? + * - Don't want 0OIl characters that look the same in some fonts and + * could be used to create visually identical looking account numbers. + * - A string with non-alphanumeric characters is not as easily accepted as an account number. + * - E-mail usually won't line-break if there's no punctuation to break at. + * - Double-clicking selects the whole number as one word if it's all alphanumeric. + */ #ifndef BITCOIN_BASE58_H #define BITCOIN_BASE58_H @@ -70,10 +70,10 @@ inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char> class CBase58Data { protected: - // the version byte(s) + //! the version byte(s) std::vector<unsigned char> vchVersion; - // the actually encoded data + //! the actually encoded data typedef std::vector<unsigned char, zero_after_free_allocator<unsigned char> > vector_uchar; vector_uchar vchData; diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index a2b95d5086..1b638e99e9 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -66,6 +66,20 @@ static bool AppInitRPC(int argc, char* argv[]) // Parameters // ParseParameters(argc, argv); + if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) { + std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n"; + if (!mapArgs.count("-version")) { + strUsage += "\n" + _("Usage:") + "\n" + + " bitcoin-cli [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" + + " bitcoin-cli [options] help " + _("List commands") + "\n" + + " bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n"; + + strUsage += "\n" + HelpMessageCli(); + } + + fprintf(stdout, "%s", strUsage.c_str()); + return false; + } if (!boost::filesystem::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str()); return false; @@ -81,20 +95,6 @@ static bool AppInitRPC(int argc, char* argv[]) fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); return false; } - if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) { - std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n"; - if (!mapArgs.count("-version")) { - strUsage += "\n" + _("Usage:") + "\n" + - " bitcoin-cli [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" + - " bitcoin-cli [options] help " + _("List commands") + "\n" + - " bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n"; - - strUsage += "\n" + HelpMessageCli(); - } - - fprintf(stdout, "%s", strUsage.c_str()); - return false; - } return true; } diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index c0d21ed36f..1cceab3188 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -4,7 +4,7 @@ #include "base58.h" #include "clientversion.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "core_io.h" #include "keystore.h" #include "main.h" // for MAX_BLOCK_SIZE diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index a79e581a80..be7757b0b6 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -59,13 +59,36 @@ bool AppInit(int argc, char* argv[]) boost::thread* detectShutdownThread = NULL; bool fRet = false; + + // + // Parameters + // + // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main() + ParseParameters(argc, argv); + + // Process help and version before taking care about datadir + if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) + { + std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n"; + + if (mapArgs.count("-version")) + { + strUsage += LicenseInfo(); + } + else + { + strUsage += "\n" + _("Usage:") + "\n" + + " bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n"; + + strUsage += "\n" + HelpMessage(HMM_BITCOIND); + } + + fprintf(stdout, "%s", strUsage.c_str()); + return false; + } + try { - // - // Parameters - // - // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main() - ParseParameters(argc, argv); if (!boost::filesystem::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str()); @@ -84,26 +107,6 @@ bool AppInit(int argc, char* argv[]) return false; } - if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) - { - std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n"; - - if (mapArgs.count("-version")) - { - strUsage += LicenseInfo(); - } - else - { - strUsage += "\n" + _("Usage:") + "\n" + - " bitcoind [options] " + _("Start Bitcoin Core Daemon") + "\n"; - - strUsage += "\n" + HelpMessage(HMM_BITCOIND); - } - - fprintf(stdout, "%s", strUsage.c_str()); - return false; - } - // Command-line RPC bool fCommandLine = false; for (int i = 1; i < argc; i++) diff --git a/src/bloom.cpp b/src/bloom.cpp index df8cedaf6a..da30e6f355 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -1,10 +1,10 @@ -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2012-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "bloom.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "hash.h" #include "script/script.h" #include "script/standard.h" @@ -21,13 +21,17 @@ using namespace std; CBloomFilter::CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweakIn, unsigned char nFlagsIn) : -// The ideal size for a bloom filter with a given number of elements and false positive rate is: -// - nElements * log(fp rate) / ln(2)^2 -// We ignore filter parameters which will create a bloom filter larger than the protocol limits +/** + * The ideal size for a bloom filter with a given number of elements and false positive rate is: + * - nElements * log(fp rate) / ln(2)^2 + * We ignore filter parameters which will create a bloom filter larger than the protocol limits + */ vData(min((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)), MAX_BLOOM_FILTER_SIZE * 8) / 8), -// The ideal number of hash functions is filter size * ln(2) / number of elements -// Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits -// See http://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas +/** + * The ideal number of hash functions is filter size * ln(2) / number of elements + * Again, we ignore filter parameters which will create a bloom filter with more hash functions than the protocol limits + * See https://en.wikipedia.org/wiki/Bloom_filter for an explanation of these formulas + */ isFull(false), isEmpty(false), nHashFuncs(min((unsigned int)(vData.size() * 8 / nElements * LN2), MAX_HASH_FUNCS)), diff --git a/src/bloom.h b/src/bloom.h index 143e3b4c79..f54922edb9 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -1,5 +1,5 @@ -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2012-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_BLOOM_H @@ -13,12 +13,14 @@ class COutPoint; class CTransaction; class uint256; -// 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001% +//! 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001% static const unsigned int MAX_BLOOM_FILTER_SIZE = 36000; // bytes static const unsigned int MAX_HASH_FUNCS = 50; -// First two bits of nFlags control how much IsRelevantAndUpdate actually updates -// The remaining bits are reserved +/** + * First two bits of nFlags control how much IsRelevantAndUpdate actually updates + * The remaining bits are reserved + */ enum bloomflags { BLOOM_UPDATE_NONE = 0, @@ -52,13 +54,15 @@ private: unsigned int Hash(unsigned int nHashNum, const std::vector<unsigned char>& vDataToHash) const; public: - // Creates a new bloom filter which will provide the given fp rate when filled with the given number of elements - // Note that if the given parameters will result in a filter outside the bounds of the protocol limits, - // the filter created will be as close to the given parameters as possible within the protocol limits. - // This will apply if nFPRate is very low or nElements is unreasonably high. - // nTweak is a constant which is added to the seed value passed to the hash function - // It should generally always be a random value (and is largely only exposed for unit testing) - // nFlags should be one of the BLOOM_UPDATE_* enums (not _MASK) + /** + * Creates a new bloom filter which will provide the given fp rate when filled with the given number of elements + * Note that if the given parameters will result in a filter outside the bounds of the protocol limits, + * the filter created will be as close to the given parameters as possible within the protocol limits. + * This will apply if nFPRate is very low or nElements is unreasonably high. + * nTweak is a constant which is added to the seed value passed to the hash function + * It should generally always be a random value (and is largely only exposed for unit testing) + * nFlags should be one of the BLOOM_UPDATE_* enums (not _MASK) + */ CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak, unsigned char nFlagsIn); CBloomFilter() : isFull(true), isEmpty(false), nHashFuncs(0), nTweak(0), nFlags(0) {} @@ -82,14 +86,14 @@ public: void clear(); - // True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS - // (catch a filter which was just deserialized which was too big) + //! True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS + //! (catch a filter which was just deserialized which was too big) bool IsWithinSizeConstraints() const; - // Also adds any outputs which match the filter to the filter (to match their spending txes) + //! Also adds any outputs which match the filter to the filter (to match their spending txes) bool IsRelevantAndUpdate(const CTransaction& tx); - // Checks for empty and full filters to avoid wasting cpu + //! Checks for empty and full filters to avoid wasting cpu void UpdateEmptyFull(); }; diff --git a/src/chain.h b/src/chain.h index f99fd113b7..d834790f06 100644 --- a/src/chain.h +++ b/src/chain.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_CHAIN_H #define BITCOIN_CHAIN_H -#include "core/block.h" +#include "primitives/block.h" #include "pow.h" #include "tinyformat.h" #include "uint256.h" @@ -220,11 +220,6 @@ public: return (int64_t)nTime; } - uint256 GetBlockWork() const - { - return GetProofIncrement(nBits); - } - enum { nMedianTimeSpan=11 }; int64_t GetMedianTimePast() const diff --git a/src/chainparams.cpp b/src/chainparams.cpp index e539eb7bd7..8a6a061ea1 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -192,11 +192,6 @@ public: CTestNetParams() { networkID = CBaseChainParams::TESTNET; strNetworkID = "test"; - /** - * The message start string is designed to be unlikely to occur in normal data. - * The characters are rarely used upper ASCII, not valid as UTF-8, and produce - * a large 4-byte int at any alignment. - */ pchMessageStart[0] = 0x0b; pchMessageStart[1] = 0x11; pchMessageStart[2] = 0x09; diff --git a/src/chainparams.h b/src/chainparams.h index 9f24b70a26..5d1ee1d3c6 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -8,7 +8,7 @@ #include "chainparamsbase.h" #include "checkpoints.h" -#include "core/block.h" +#include "primitives/block.h" #include "protocol.h" #include "uint256.h" diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index fbde47339d..0fb4411e63 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "checkpoints.h" @@ -14,11 +14,13 @@ namespace Checkpoints { - // How many times we expect transactions after the last checkpoint to - // be slower. This number is a compromise, as it can't be accurate for - // every system. When reindexing from a fast disk with a slow CPU, it - // can be up to 20, while when downloading from a slow network with a - // fast multicore CPU, it won't be much higher than 1. + /** + * How many times we expect transactions after the last checkpoint to + * be slower. This number is a compromise, as it can't be accurate for + * every system. When reindexing from a fast disk with a slow CPU, it + * can be up to 20, while when downloading from a slow network with a + * fast multicore CPU, it won't be much higher than 1. + */ static const double SIGCHECK_VERIFICATION_FACTOR = 5.0; bool fEnabled = true; @@ -35,7 +37,7 @@ namespace Checkpoints { return hash == i->second; } - // Guess how far we are in the verification process at the given block index + //! Guess how far we are in the verification process at the given block index double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks) { if (pindex==NULL) return 0.0; diff --git a/src/checkpoints.h b/src/checkpoints.h index 847524a9f2..65c5165f0f 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -1,5 +1,5 @@ -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CHECKPOINTS_H @@ -11,7 +11,8 @@ class CBlockIndex; -/** Block-chain checkpoints are compiled-in sanity checks. +/** + * Block-chain checkpoints are compiled-in sanity checks. * They are updated every release or three. */ namespace Checkpoints @@ -25,13 +26,13 @@ struct CCheckpointData { double fTransactionsPerDay; }; -// Returns true if block passes checkpoint checks +//! Returns true if block passes checkpoint checks bool CheckBlock(int nHeight, const uint256& hash); -// Return conservative estimate of total number of blocks, 0 if unknown +//! Return conservative estimate of total number of blocks, 0 if unknown int GetTotalBlocksEstimate(); -// Returns last CBlockIndex* in mapBlockIndex that is a checkpoint +//! Returns last CBlockIndex* in mapBlockIndex that is a checkpoint CBlockIndex* GetLastCheckpoint(); double GuessVerificationProgress(CBlockIndex* pindex, bool fSigchecks = true); diff --git a/src/checkqueue.h b/src/checkqueue.h index afecfeede5..2ee46a1210 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -1,5 +1,5 @@ -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2012-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CHECKQUEUE_H @@ -16,7 +16,8 @@ template <typename T> class CCheckQueueControl; -/** Queue for verifications that have to be performed. +/** + * Queue for verifications that have to be performed. * The verifications are represented by a type T, which must provide an * operator(), returning a bool. * @@ -29,40 +30,42 @@ template <typename T> class CCheckQueue { private: - // Mutex to protect the inner state + //! Mutex to protect the inner state boost::mutex mutex; - // Worker threads block on this when out of work + //! Worker threads block on this when out of work boost::condition_variable condWorker; - // Master thread blocks on this when out of work + //! Master thread blocks on this when out of work boost::condition_variable condMaster; - // The queue of elements to be processed. - // As the order of booleans doesn't matter, it is used as a LIFO (stack) + //! The queue of elements to be processed. + //! As the order of booleans doesn't matter, it is used as a LIFO (stack) std::vector<T> queue; - // The number of workers (including the master) that are idle. + //! The number of workers (including the master) that are idle. int nIdle; - // The total number of workers (including the master). + //! The total number of workers (including the master). int nTotal; - // The temporary evaluation result. + //! The temporary evaluation result. bool fAllOk; - // Number of verifications that haven't completed yet. - // This includes elements that are not anymore in queue, but still in - // worker's own batches. + /** + * Number of verifications that haven't completed yet. + * This includes elements that are not anymore in queue, but still in + * worker's own batches. + */ unsigned int nTodo; - // Whether we're shutting down. + //! Whether we're shutting down. bool fQuit; - // The maximum number of elements to be processed in one batch + //! The maximum number of elements to be processed in one batch unsigned int nBatchSize; - // Internal function that does bulk of the verification work. + /** Internal function that does bulk of the verification work. */ bool Loop(bool fMaster = false) { boost::condition_variable& cond = fMaster ? condMaster : condWorker; @@ -124,22 +127,22 @@ private: } public: - // Create a new check queue + //! Create a new check queue CCheckQueue(unsigned int nBatchSizeIn) : nIdle(0), nTotal(0), fAllOk(true), nTodo(0), fQuit(false), nBatchSize(nBatchSizeIn) {} - // Worker thread + //! Worker thread void Thread() { Loop(); } - // Wait until execution finishes, and return whether all evaluations where succesful. + //! Wait until execution finishes, and return whether all evaluations where successful. bool Wait() { return Loop(true); } - // Add a batch of checks to the queue + //! Add a batch of checks to the queue void Add(std::vector<T>& vChecks) { boost::unique_lock<boost::mutex> lock(mutex); @@ -161,8 +164,9 @@ public: friend class CCheckQueueControl<T>; }; -/** RAII-style controller object for a CCheckQueue that guarantees the passed - * queue is finished before continuing. +/** + * RAII-style controller object for a CCheckQueue that guarantees the passed + * queue is finished before continuing. */ template <typename T> class CCheckQueueControl diff --git a/src/coincontrol.h b/src/coincontrol.h index c8bdd3b39d..cf61998723 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_COINCONTROL_H #define BITCOIN_COINCONTROL_H -#include "core/transaction.h" +#include "primitives/transaction.h" /** Coin Control Features. */ class CCoinControl diff --git a/src/coins.cpp b/src/coins.cpp index e4f3e67aeb..c2e802c953 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -1,5 +1,5 @@ -// Copyright (c) 2012-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2012-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "coins.h" @@ -8,9 +8,11 @@ #include <assert.h> -// calculate number of bytes for the bitmask, and its number of non-zero bytes -// each bit in the bitmask represents the availability of one output, but the -// availabilities of the first two outputs are encoded separately +/** + * calculate number of bytes for the bitmask, and its number of non-zero bytes + * each bit in the bitmask represents the availability of one output, but the + * availabilities of the first two outputs are encoded separately + */ void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const { unsigned int nLastUsedByte = 0; for (unsigned int b = 0; 2+b*8 < vout.size(); b++) { @@ -133,7 +135,7 @@ const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const { bool CCoinsViewCache::HaveCoins(const uint256 &txid) const { CCoinsMap::const_iterator it = FetchCoins(txid); // We're using vtx.empty() instead of IsPruned here for performance reasons, - // as we only care about the case where an transaction was replaced entirely + // as we only care about the case where a transaction was replaced entirely // in a reorganization (which wipes vout entirely, as opposed to spending // which just cleans individual outputs). return (it != cacheCoins.end() && !it->second.coins.vout.empty()); diff --git a/src/coins.h b/src/coins.h index ee9051562b..dbe3f8bd31 100644 --- a/src/coins.h +++ b/src/coins.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_COINS_H @@ -17,7 +17,8 @@ #include <boost/foreach.hpp> #include <boost/unordered_map.hpp> -/** pruned version of CTransaction: only retains metadata and unspent transaction outputs +/** + * Pruned version of CTransaction: only retains metadata and unspent transaction outputs * * Serialized format: * - VARINT(nVersion) @@ -71,17 +72,17 @@ class CCoins { public: - // whether transaction is a coinbase + //! whether transaction is a coinbase bool fCoinBase; - // unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped + //! unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped std::vector<CTxOut> vout; - // at which height this transaction was included in the active block chain + //! at which height this transaction was included in the active block chain int nHeight; - // version of the CTransaction; accesses to this value should probably check for nHeight as well, - // as new tx version will probably only be introduced at certain heights + //! version of the CTransaction; accesses to this value should probably check for nHeight as well, + //! as new tx version will probably only be introduced at certain heights int nVersion; void FromTx(const CTransaction &tx, int nHeightIn) { @@ -92,7 +93,7 @@ public: ClearUnspendable(); } - // construct a CCoins from a CTransaction, at a given height + //! construct a CCoins from a CTransaction, at a given height CCoins(const CTransaction &tx, int nHeightIn) { FromTx(tx, nHeightIn); } @@ -104,10 +105,10 @@ public: nVersion = 0; } - // empty constructor + //! empty constructor CCoins() : fCoinBase(false), vout(0), nHeight(0), nVersion(0) { } - // remove spent outputs at the end of vout + //!remove spent outputs at the end of vout void Cleanup() { while (vout.size() > 0 && vout.back().IsNull()) vout.pop_back(); @@ -130,7 +131,7 @@ public: std::swap(to.nVersion, nVersion); } - // equality test + //! equality test friend bool operator==(const CCoins &a, const CCoins &b) { // Empty CCoins objects are always equal. if (a.IsPruned() && b.IsPruned()) @@ -236,19 +237,19 @@ public: Cleanup(); } - // mark an outpoint spent, and construct undo information + //! mark an outpoint spent, and construct undo information bool Spend(const COutPoint &out, CTxInUndo &undo); - // mark a vout spent + //! mark a vout spent bool Spend(int nPos); - // check whether a particular output is still available + //! check whether a particular output is still available bool IsAvailable(unsigned int nPos) const { return (nPos < vout.size() && !vout[nPos].IsNull()); } - // check whether the entire CCoins is spent - // note that only !IsPruned() CCoins can be serialized + //! check whether the entire CCoins is spent + //! note that only !IsPruned() CCoins can be serialized bool IsPruned() const { BOOST_FOREACH(const CTxOut &out, vout) if (!out.IsNull()) @@ -264,9 +265,12 @@ private: public: CCoinsKeyHasher(); - // This *must* return size_t. With Boost 1.46 on 32-bit systems the - // unordered_map will behave unpredictably if the custom hasher returns a - // uint64_t, resulting in failures when syncing the chain (#4634). + + /** + * This *must* return size_t. With Boost 1.46 on 32-bit systems the + * unordered_map will behave unpredictably if the custom hasher returns a + * uint64_t, resulting in failures when syncing the chain (#4634). + */ size_t operator()(const uint256& key) const { return key.GetHash(salt); } @@ -305,24 +309,24 @@ struct CCoinsStats class CCoinsView { public: - // Retrieve the CCoins (unspent transaction outputs) for a given txid + //! Retrieve the CCoins (unspent transaction outputs) for a given txid virtual bool GetCoins(const uint256 &txid, CCoins &coins) const; - // Just check whether we have data for a given txid. - // This may (but cannot always) return true for fully spent transactions + //! Just check whether we have data for a given txid. + //! This may (but cannot always) return true for fully spent transactions virtual bool HaveCoins(const uint256 &txid) const; - // Retrieve the block hash whose state this CCoinsView currently represents + //! Retrieve the block hash whose state this CCoinsView currently represents virtual uint256 GetBestBlock() const; - // Do a bulk modification (multiple CCoins changes + BestBlock change). - // The passed mapCoins can be modified. + //! Do a bulk modification (multiple CCoins changes + BestBlock change). + //! The passed mapCoins can be modified. virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock); - // Calculate statistics about the unspent transaction output set + //! Calculate statistics about the unspent transaction output set virtual bool GetStats(CCoinsStats &stats) const; - // As we use CCoinsViews polymorphically, have a virtual destructor + //! As we use CCoinsViews polymorphically, have a virtual destructor virtual ~CCoinsView() {} }; @@ -346,9 +350,11 @@ public: class CCoinsViewCache; -/** A reference to a mutable cache entry. Encapsulating it allows us to run +/** + * A reference to a mutable cache entry. Encapsulating it allows us to run * cleanup code after the modification is finished, and keeping track of - * concurrent modifications. */ + * concurrent modifications. + */ class CCoinsModifier { private: @@ -370,8 +376,10 @@ protected: /* Whether this cache has an active modifier. */ bool hasModifier; - /* Make mutable so that we can "fill the cache" even from Get-methods - declared as "const". */ + /** + * Make mutable so that we can "fill the cache" even from Get-methods + * declared as "const". + */ mutable uint256 hashBlock; mutable CCoinsMap cacheCoins; @@ -386,37 +394,44 @@ public: void SetBestBlock(const uint256 &hashBlock); bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock); - // Return a pointer to CCoins in the cache, or NULL if not found. This is - // more efficient than GetCoins. Modifications to other cache entries are - // allowed while accessing the returned pointer. + /** + * Return a pointer to CCoins in the cache, or NULL if not found. This is + * more efficient than GetCoins. Modifications to other cache entries are + * allowed while accessing the returned pointer. + */ const CCoins* AccessCoins(const uint256 &txid) const; - // Return a modifiable reference to a CCoins. If no entry with the given - // txid exists, a new one is created. Simultaneous modifications are not - // allowed. + /** + * Return a modifiable reference to a CCoins. If no entry with the given + * txid exists, a new one is created. Simultaneous modifications are not + * allowed. + */ CCoinsModifier ModifyCoins(const uint256 &txid); - // Push the modifications applied to this cache to its base. - // Failure to call this method before destruction will cause the changes to be forgotten. - // If false is returned, the state of this cache (and its backing view) will be undefined. + /** + * Push the modifications applied to this cache to its base. + * Failure to call this method before destruction will cause the changes to be forgotten. + * If false is returned, the state of this cache (and its backing view) will be undefined. + */ bool Flush(); - // Calculate the size of the cache (in number of transactions) + //! Calculate the size of the cache (in number of transactions) unsigned int GetCacheSize() const; - /** Amount of bitcoins coming in to a transaction - Note that lightweight clients may not know anything besides the hash of previous transactions, - so may not be able to calculate this. - - @param[in] tx transaction for which we are checking input total - @return Sum of value of all inputs (scriptSigs) + /** + * Amount of bitcoins coming in to a transaction + * Note that lightweight clients may not know anything besides the hash of previous transactions, + * so may not be able to calculate this. + * + * @param[in] tx transaction for which we are checking input total + * @return Sum of value of all inputs (scriptSigs) */ CAmount GetValueIn(const CTransaction& tx) const; - // Check whether all prevouts of the transaction are present in the UTXO set represented by this view + //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view bool HaveInputs(const CTransaction& tx) const; - // Return priority of tx at height nHeight + //! Return priority of tx at height nHeight double GetPriority(const CTransaction &tx, int nHeight) const; const CTxOut &GetOutputFor(const CTxIn& input) const; diff --git a/src/compat.h b/src/compat.h index dade79aae0..dffd4ecf52 100644 --- a/src/compat.h +++ b/src/compat.h @@ -6,6 +6,10 @@ #ifndef BITCOIN_COMPAT_H #define BITCOIN_COMPAT_H +#if defined(HAVE_CONFIG_H) +#include "config/bitcoin-config.h" +#endif + #ifdef WIN32 #ifdef _WIN32_WINNT #undef _WIN32_WINNT @@ -84,4 +88,8 @@ typedef u_int SOCKET; #define THREAD_PRIORITY_ABOVE_NORMAL (-2) #endif +#if HAVE_DECL_STRNLEN == 0 +size_t strnlen( const char *start, size_t max_len); +#endif // HAVE_DECL_STRNLEN + #endif // BITCOIN_COMPAT_H diff --git a/src/compat/strnlen.cpp b/src/compat/strnlen.cpp new file mode 100644 index 0000000000..7f3e159887 --- /dev/null +++ b/src/compat/strnlen.cpp @@ -0,0 +1,18 @@ +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#if defined(HAVE_CONFIG_H) +#include "config/bitcoin-config.h" +#endif + +#include <cstring> + +#if HAVE_DECL_STRNLEN == 0 +size_t strnlen( const char *start, size_t max_len) +{ + const char *end = (const char *)memchr(start, '\0', max_len); + + return end ? (size_t)(end - start) : max_len; +} +#endif // HAVE_DECL_STRNLEN diff --git a/src/compressor.h b/src/compressor.h index 226be620e8..efb8119d01 100644 --- a/src/compressor.h +++ b/src/compressor.h @@ -6,7 +6,7 @@ #ifndef BITCOIN_COMPRESSOR_H #define BITCOIN_COMPRESSOR_H -#include "core/transaction.h" +#include "primitives/transaction.h" #include "script/script.h" #include "serialize.h" @@ -28,19 +28,23 @@ class CScriptID; class CScriptCompressor { private: - // make this static for now (there are only 6 special scripts defined) - // this can potentially be extended together with a new nVersion for - // transactions, in which case this value becomes dependent on nVersion - // and nHeight of the enclosing transaction. + /** + * make this static for now (there are only 6 special scripts defined) + * this can potentially be extended together with a new nVersion for + * transactions, in which case this value becomes dependent on nVersion + * and nHeight of the enclosing transaction. + */ static const unsigned int nSpecialScripts = 6; CScript &script; protected: - // These check for scripts for which a special case with a shorter encoding is defined. - // They are implemented separately from the CScript test, as these test for exact byte - // sequence correspondences, and are more strict. For example, IsToPubKey also verifies - // whether the public key is valid (as invalid ones cannot be represented in compressed - // form). + /** + * These check for scripts for which a special case with a shorter encoding is defined. + * They are implemented separately from the CScript test, as these test for exact byte + * sequence correspondences, and are more strict. For example, IsToPubKey also verifies + * whether the public key is valid (as invalid ones cannot be represented in compressed + * form). + */ bool IsToKeyID(CKeyID &hash) const; bool IsToScriptID(CScriptID &hash) const; bool IsToPubKey(CPubKey &pubkey) const; diff --git a/src/core_io.h b/src/core_io.h index b5ed03b8c8..aba1928a36 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -8,6 +8,7 @@ #include <string> #include <vector> +class CBlock; class CScript; class CTransaction; class uint256; @@ -16,6 +17,7 @@ class UniValue; // core_read.cpp extern CScript ParseScript(std::string s); extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx); +extern bool DecodeHexBlk(CBlock&, const std::string& strHexBlk); extern uint256 ParseHashUV(const UniValue& v, const std::string& strName); extern std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName); diff --git a/src/core_read.cpp b/src/core_read.cpp index d39bc9a780..65c3a08c55 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -4,7 +4,8 @@ #include "core_io.h" -#include "core/transaction.h" +#include "primitives/block.h" +#include "primitives/transaction.h" #include "script/script.h" #include "serialize.h" #include "streams.h" @@ -108,6 +109,23 @@ bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx) return true; } +bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk) +{ + if (!IsHex(strHexBlk)) + return false; + + std::vector<unsigned char> blockData(ParseHex(strHexBlk)); + CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION); + try { + ssBlock >> block; + } + catch (const std::exception &) { + return false; + } + + return true; +} + uint256 ParseHashUV(const UniValue& v, const string& strName) { string strHex; diff --git a/src/core_write.cpp b/src/core_write.cpp index a3ae8eec07..b4e82b986e 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -5,7 +5,7 @@ #include "core_io.h" #include "base58.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "script/script.h" #include "script/standard.h" #include "serialize.h" diff --git a/src/crypter.h b/src/crypter.h index b589987c4f..f7018cfdbe 100644 --- a/src/crypter.h +++ b/src/crypter.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2013 The Bitcoin developers +// Copyright (c) 2009-2014 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -14,20 +14,20 @@ class uint256; const unsigned int WALLET_CRYPTO_KEY_SIZE = 32; const unsigned int WALLET_CRYPTO_SALT_SIZE = 8; -/* -Private key encryption is done based on a CMasterKey, -which holds a salt and random encryption key. - -CMasterKeys are encrypted using AES-256-CBC using a key -derived using derivation method nDerivationMethod -(0 == EVP_sha512()) and derivation iterations nDeriveIterations. -vchOtherDerivationParameters is provided for alternative algorithms -which may require more parameters (such as scrypt). - -Wallet Private Keys are then encrypted using AES-256-CBC -with the double-sha256 of the public key as the IV, and the -master key's key as the encryption key (see keystore.[ch]). -*/ +/** + * Private key encryption is done based on a CMasterKey, + * which holds a salt and random encryption key. + * + * CMasterKeys are encrypted using AES-256-CBC using a key + * derived using derivation method nDerivationMethod + * (0 == EVP_sha512()) and derivation iterations nDeriveIterations. + * vchOtherDerivationParameters is provided for alternative algorithms + * which may require more parameters (such as scrypt). + * + * Wallet Private Keys are then encrypted using AES-256-CBC + * with the double-sha256 of the public key as the IV, and the + * master key's key as the encryption key (see keystore.[ch]). + */ /** Master key for wallet encryption */ class CMasterKey @@ -35,12 +35,12 @@ class CMasterKey public: std::vector<unsigned char> vchCryptedKey; std::vector<unsigned char> vchSalt; - // 0 = EVP_sha512() - // 1 = scrypt() + //! 0 = EVP_sha512() + //! 1 = scrypt() unsigned int nDerivationMethod; unsigned int nDeriveIterations; - // Use this for more parameters to key derivation, - // such as the various parameters to scrypt + //! Use this for more parameters to key derivation, + //! such as the various parameters to scrypt std::vector<unsigned char> vchOtherDerivationParameters; ADD_SERIALIZE_METHODS; @@ -120,17 +120,17 @@ private: CKeyingMaterial vMasterKey; - // if fUseCrypto is true, mapKeys must be empty - // if fUseCrypto is false, vMasterKey must be empty + //! if fUseCrypto is true, mapKeys must be empty + //! if fUseCrypto is false, vMasterKey must be empty bool fUseCrypto; - // keeps track of whether Unlock has run a thourough check before + //! keeps track of whether Unlock has run a thorough check before bool fDecryptionThoroughlyChecked; protected: bool SetCrypted(); - // will encrypt previously unencrypted keys + //! will encrypt previously unencrypted keys bool EncryptKeys(CKeyingMaterial& vMasterKeyIn); bool Unlock(const CKeyingMaterial& vMasterKeyIn); @@ -189,7 +189,8 @@ public: } } - /* Wallet status (encrypted, locked) changed. + /** + * Wallet status (encrypted, locked) changed. * Note: Called without locks held. */ boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged; diff --git a/src/crypto/hmac_sha256.cpp b/src/crypto/hmac_sha256.cpp new file mode 100644 index 0000000000..435896538b --- /dev/null +++ b/src/crypto/hmac_sha256.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "crypto/hmac_sha256.h" + +#include <string.h> + +CHMAC_SHA256::CHMAC_SHA256(const unsigned char* key, size_t keylen) +{ + unsigned char rkey[64]; + if (keylen <= 64) { + memcpy(rkey, key, keylen); + memset(rkey + keylen, 0, 64 - keylen); + } else { + CSHA256().Write(key, keylen).Finalize(rkey); + memset(rkey + 32, 0, 32); + } + + for (int n = 0; n < 64; n++) + rkey[n] ^= 0x5c; + outer.Write(rkey, 64); + + for (int n = 0; n < 64; n++) + rkey[n] ^= 0x5c ^ 0x36; + inner.Write(rkey, 64); +} + +void CHMAC_SHA256::Finalize(unsigned char hash[OUTPUT_SIZE]) +{ + unsigned char temp[32]; + inner.Finalize(temp); + outer.Write(temp, 32).Finalize(hash); +} diff --git a/src/crypto/hmac_sha256.h b/src/crypto/hmac_sha256.h new file mode 100644 index 0000000000..1fdee5a7cd --- /dev/null +++ b/src/crypto/hmac_sha256.h @@ -0,0 +1,32 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CRYPTO_HMAC_SHA256_H +#define BITCOIN_CRYPTO_HMAC_SHA256_H + +#include "crypto/sha256.h" + +#include <stdint.h> +#include <stdlib.h> + +/** A hasher class for HMAC-SHA-512. */ +class CHMAC_SHA256 +{ +private: + CSHA256 outer; + CSHA256 inner; + +public: + static const size_t OUTPUT_SIZE = 32; + + CHMAC_SHA256(const unsigned char* key, size_t keylen); + CHMAC_SHA256& Write(const unsigned char* data, size_t len) + { + inner.Write(data, len); + return *this; + } + void Finalize(unsigned char hash[OUTPUT_SIZE]); +}; + +#endif // BITCOIN_CRYPTO_HMAC_SHA256_H diff --git a/src/crypto/hmac_sha512.cpp b/src/crypto/hmac_sha512.cpp new file mode 100644 index 0000000000..940a93277c --- /dev/null +++ b/src/crypto/hmac_sha512.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "crypto/hmac_sha512.h" + +#include <string.h> + +CHMAC_SHA512::CHMAC_SHA512(const unsigned char* key, size_t keylen) +{ + unsigned char rkey[128]; + if (keylen <= 128) { + memcpy(rkey, key, keylen); + memset(rkey + keylen, 0, 128 - keylen); + } else { + CSHA512().Write(key, keylen).Finalize(rkey); + memset(rkey + 64, 0, 64); + } + + for (int n = 0; n < 128; n++) + rkey[n] ^= 0x5c; + outer.Write(rkey, 128); + + for (int n = 0; n < 128; n++) + rkey[n] ^= 0x5c ^ 0x36; + inner.Write(rkey, 128); +} + +void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) +{ + unsigned char temp[64]; + inner.Finalize(temp); + outer.Write(temp, 64).Finalize(hash); +} diff --git a/src/crypto/hmac_sha512.h b/src/crypto/hmac_sha512.h new file mode 100644 index 0000000000..17d75021aa --- /dev/null +++ b/src/crypto/hmac_sha512.h @@ -0,0 +1,32 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CRYPTO_HMAC_SHA512_H +#define BITCOIN_CRYPTO_HMAC_SHA512_H + +#include "crypto/sha512.h" + +#include <stdint.h> +#include <stdlib.h> + +/** A hasher class for HMAC-SHA-512. */ +class CHMAC_SHA512 +{ +private: + CSHA512 outer; + CSHA512 inner; + +public: + static const size_t OUTPUT_SIZE = 64; + + CHMAC_SHA512(const unsigned char* key, size_t keylen); + CHMAC_SHA512& Write(const unsigned char* data, size_t len) + { + inner.Write(data, len); + return *this; + } + void Finalize(unsigned char hash[OUTPUT_SIZE]); +}; + +#endif // BITCOIN_CRYPTO_HMAC_SHA512_H diff --git a/src/crypto/rfc6979_hmac_sha256.cpp b/src/crypto/rfc6979_hmac_sha256.cpp new file mode 100644 index 0000000000..3f935abfea --- /dev/null +++ b/src/crypto/rfc6979_hmac_sha256.cpp @@ -0,0 +1,47 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "crypto/rfc6979_hmac_sha256.h" + +#include <string.h> + +#include <algorithm> + +static const unsigned char zero[1] = {0x00}; +static const unsigned char one[1] = {0x01}; + +RFC6979_HMAC_SHA256::RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen) : retry(false) +{ + memset(V, 0x01, sizeof(V)); + memset(K, 0x00, sizeof(K)); + + CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Write(key, keylen).Write(msg, msglen).Finalize(K); + CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V); + CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(one, sizeof(one)).Write(key, keylen).Write(msg, msglen).Finalize(K); + CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V); +} + +RFC6979_HMAC_SHA256::~RFC6979_HMAC_SHA256() +{ + memset(V, 0x01, sizeof(V)); + memset(K, 0x00, sizeof(K)); +} + +void RFC6979_HMAC_SHA256::Generate(unsigned char* output, size_t outputlen) +{ + if (retry) { + CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Write(zero, sizeof(zero)).Finalize(K); + CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V); + } + + while (outputlen > 0) { + CHMAC_SHA256(K, sizeof(K)).Write(V, sizeof(V)).Finalize(V); + size_t len = std::min(outputlen, sizeof(V)); + memcpy(output, V, len); + output += len; + outputlen -= len; + } + + retry = true; +} diff --git a/src/crypto/rfc6979_hmac_sha256.h b/src/crypto/rfc6979_hmac_sha256.h new file mode 100644 index 0000000000..e67ddcf8fe --- /dev/null +++ b/src/crypto/rfc6979_hmac_sha256.h @@ -0,0 +1,36 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_RFC6979_HMAC_SHA256_H +#define BITCOIN_RFC6979_HMAC_SHA256_H + +#include "crypto/hmac_sha256.h" + +#include <stdint.h> +#include <stdlib.h> + +/** The RFC 6979 PRNG using HMAC-SHA256. */ +class RFC6979_HMAC_SHA256 +{ +private: + unsigned char V[CHMAC_SHA256::OUTPUT_SIZE]; + unsigned char K[CHMAC_SHA256::OUTPUT_SIZE]; + bool retry; + +public: + /** + * Construct a new RFC6979 PRNG, using the given key and message. + * The message is assumed to be already hashed. + */ + RFC6979_HMAC_SHA256(const unsigned char* key, size_t keylen, const unsigned char* msg, size_t msglen); + + /** + * Generate a byte array. + */ + void Generate(unsigned char* output, size_t outputlen); + + ~RFC6979_HMAC_SHA256(); +}; + +#endif // BITCOIN_RFC6979_HMAC_SHA256_H diff --git a/src/crypto/sha2.h b/src/crypto/sha2.h deleted file mode 100644 index 329c6675ab..0000000000 --- a/src/crypto/sha2.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_CRYPTO_SHA2_H -#define BITCOIN_CRYPTO_SHA2_H - -#include <stdint.h> -#include <stdlib.h> - -/** A hasher class for SHA-256. */ -class CSHA256 -{ -private: - uint32_t s[8]; - unsigned char buf[64]; - size_t bytes; - -public: - static const size_t OUTPUT_SIZE = 32; - - CSHA256(); - CSHA256& Write(const unsigned char* data, size_t len); - void Finalize(unsigned char hash[OUTPUT_SIZE]); - CSHA256& Reset(); -}; - -/** A hasher class for SHA-512. */ -class CSHA512 -{ -private: - uint64_t s[8]; - unsigned char buf[128]; - size_t bytes; - -public: - static const size_t OUTPUT_SIZE = 64; - - CSHA512(); - CSHA512& Write(const unsigned char* data, size_t len); - void Finalize(unsigned char hash[OUTPUT_SIZE]); - CSHA512& Reset(); -}; - -/** A hasher class for HMAC-SHA-512. */ -class CHMAC_SHA512 -{ -private: - CSHA512 outer; - CSHA512 inner; - -public: - static const size_t OUTPUT_SIZE = 64; - - CHMAC_SHA512(const unsigned char* key, size_t keylen); - CHMAC_SHA512& Write(const unsigned char* data, size_t len) - { - inner.Write(data, len); - return *this; - } - void Finalize(unsigned char hash[OUTPUT_SIZE]); -}; - -#endif // BITCOIN_CRYPTO_SHA2_H diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp new file mode 100644 index 0000000000..8410e59305 --- /dev/null +++ b/src/crypto/sha256.cpp @@ -0,0 +1,189 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "crypto/sha256.h" + +#include "crypto/common.h" + +#include <string.h> + +// Internal implementation code. +namespace +{ +/// Internal SHA-256 implementation. +namespace sha256 +{ +uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); } +uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); } +uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); } +uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); } +uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); } +uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); } + +/** One round of SHA-256. */ +void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k, uint32_t w) +{ + uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w; + uint32_t t2 = Sigma0(a) + Maj(a, b, c); + d += t1; + h = t1 + t2; +} + +/** Initialize SHA-256 state. */ +void inline Initialize(uint32_t* s) +{ + s[0] = 0x6a09e667ul; + s[1] = 0xbb67ae85ul; + s[2] = 0x3c6ef372ul; + s[3] = 0xa54ff53aul; + s[4] = 0x510e527ful; + s[5] = 0x9b05688cul; + s[6] = 0x1f83d9abul; + s[7] = 0x5be0cd19ul; +} + +/** Perform one SHA-256 transformation, processing a 64-byte chunk. */ +void Transform(uint32_t* s, const unsigned char* chunk) +{ + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0)); + Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4)); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8)); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12)); + Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16)); + Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20)); + Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24)); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28)); + Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32)); + Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36)); + Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40)); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44)); + Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48)); + Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52)); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56)); + Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60)); + + Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + +} // namespace sha256 +} // namespace + + +////// SHA-256 + +CSHA256::CSHA256() : bytes(0) +{ + sha256::Initialize(s); +} + +CSHA256& CSHA256::Write(const unsigned char* data, size_t len) +{ + const unsigned char* end = data + len; + size_t bufsize = bytes % 64; + if (bufsize && bufsize + len >= 64) { + // Fill the buffer, and process it. + memcpy(buf + bufsize, data, 64 - bufsize); + bytes += 64 - bufsize; + data += 64 - bufsize; + sha256::Transform(s, buf); + bufsize = 0; + } + while (end >= data + 64) { + // Process full chunks directly from the source. + sha256::Transform(s, data); + bytes += 64; + data += 64; + } + if (end > data) { + // Fill the buffer with what remains. + memcpy(buf + bufsize, data, end - data); + bytes += end - data; + } + return *this; +} + +void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE]) +{ + static const unsigned char pad[64] = {0x80}; + unsigned char sizedesc[8]; + WriteBE64(sizedesc, bytes << 3); + Write(pad, 1 + ((119 - (bytes % 64)) % 64)); + Write(sizedesc, 8); + WriteBE32(hash, s[0]); + WriteBE32(hash + 4, s[1]); + WriteBE32(hash + 8, s[2]); + WriteBE32(hash + 12, s[3]); + WriteBE32(hash + 16, s[4]); + WriteBE32(hash + 20, s[5]); + WriteBE32(hash + 24, s[6]); + WriteBE32(hash + 28, s[7]); +} + +CSHA256& CSHA256::Reset() +{ + bytes = 0; + sha256::Initialize(s); + return *this; +} diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h new file mode 100644 index 0000000000..bde1a59bed --- /dev/null +++ b/src/crypto/sha256.h @@ -0,0 +1,28 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CRYPTO_SHA256_H +#define BITCOIN_CRYPTO_SHA256_H + +#include <stdint.h> +#include <stdlib.h> + +/** A hasher class for SHA-256. */ +class CSHA256 +{ +private: + uint32_t s[8]; + unsigned char buf[64]; + size_t bytes; + +public: + static const size_t OUTPUT_SIZE = 32; + + CSHA256(); + CSHA256& Write(const unsigned char* data, size_t len); + void Finalize(unsigned char hash[OUTPUT_SIZE]); + CSHA256& Reset(); +}; + +#endif // BITCOIN_CRYPTO_SHA256_H diff --git a/src/crypto/sha2.cpp b/src/crypto/sha512.cpp index 613aac2d71..22c3103bed 100644 --- a/src/crypto/sha2.cpp +++ b/src/crypto/sha512.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "crypto/sha2.h" +#include "crypto/sha512.h" #include "crypto/common.h" @@ -11,124 +11,6 @@ // Internal implementation code. namespace { -/// Internal SHA-256 implementation. -namespace sha256 -{ -uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); } -uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); } -uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); } -uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); } -uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); } -uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); } - -/** One round of SHA-256. */ -void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k, uint32_t w) -{ - uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w; - uint32_t t2 = Sigma0(a) + Maj(a, b, c); - d += t1; - h = t1 + t2; -} - -/** Initialize SHA-256 state. */ -void inline Initialize(uint32_t* s) -{ - s[0] = 0x6a09e667ul; - s[1] = 0xbb67ae85ul; - s[2] = 0x3c6ef372ul; - s[3] = 0xa54ff53aul; - s[4] = 0x510e527ful; - s[5] = 0x9b05688cul; - s[6] = 0x1f83d9abul; - s[7] = 0x5be0cd19ul; -} - -/** Perform one SHA-256 transformation, processing a 64-byte chunk. */ -void Transform(uint32_t* s, const unsigned char* chunk) -{ - uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; - uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - - Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0)); - Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4)); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8)); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12)); - Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16)); - Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20)); - Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24)); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28)); - Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32)); - Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36)); - Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40)); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44)); - Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48)); - Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52)); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56)); - Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60)); - - Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); - - s[0] += a; - s[1] += b; - s[2] += c; - s[3] += d; - s[4] += e; - s[5] += f; - s[6] += g; - s[7] += h; -} - -} // namespace sha256 - /// Internal SHA-512 implementation. namespace sha512 { @@ -249,8 +131,8 @@ void Transform(uint64_t* s, const unsigned char* chunk) Round(f, g, h, a, b, c, d, e, 0x431d67c49c100d4cull, w11 += sigma1(w9) + w4 + sigma0(w12)); Round(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6ull, w12 += sigma1(w10) + w5 + sigma0(w13)); Round(d, e, f, g, h, a, b, c, 0x597f299cfc657e2aull, w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 += sigma1(w13) + w8 + sigma0(w0)); + Round(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faecull, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x6c44198c4a475817ull, w15 + sigma1(w13) + w8 + sigma0(w0)); s[0] += a; s[1] += b; @@ -267,63 +149,6 @@ void Transform(uint64_t* s, const unsigned char* chunk) } // namespace -////// SHA-256 - -CSHA256::CSHA256() : bytes(0) -{ - sha256::Initialize(s); -} - -CSHA256& CSHA256::Write(const unsigned char* data, size_t len) -{ - const unsigned char* end = data + len; - size_t bufsize = bytes % 64; - if (bufsize && bufsize + len >= 64) { - // Fill the buffer, and process it. - memcpy(buf + bufsize, data, 64 - bufsize); - bytes += 64 - bufsize; - data += 64 - bufsize; - sha256::Transform(s, buf); - bufsize = 0; - } - while (end >= data + 64) { - // Process full chunks directly from the source. - sha256::Transform(s, data); - bytes += 64; - data += 64; - } - if (end > data) { - // Fill the buffer with what remains. - memcpy(buf + bufsize, data, end - data); - bytes += end - data; - } - return *this; -} - -void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE]) -{ - static const unsigned char pad[64] = {0x80}; - unsigned char sizedesc[8]; - WriteBE64(sizedesc, bytes << 3); - Write(pad, 1 + ((119 - (bytes % 64)) % 64)); - Write(sizedesc, 8); - WriteBE32(hash, s[0]); - WriteBE32(hash + 4, s[1]); - WriteBE32(hash + 8, s[2]); - WriteBE32(hash + 12, s[3]); - WriteBE32(hash + 16, s[4]); - WriteBE32(hash + 20, s[5]); - WriteBE32(hash + 24, s[6]); - WriteBE32(hash + 28, s[7]); -} - -CSHA256& CSHA256::Reset() -{ - bytes = 0; - sha256::Initialize(s); - return *this; -} - ////// SHA-512 CSHA512::CSHA512() : bytes(0) @@ -380,32 +205,3 @@ CSHA512& CSHA512::Reset() sha512::Initialize(s); return *this; } - -////// HMAC-SHA-512 - -CHMAC_SHA512::CHMAC_SHA512(const unsigned char* key, size_t keylen) -{ - unsigned char rkey[128]; - if (keylen <= 128) { - memcpy(rkey, key, keylen); - memset(rkey + keylen, 0, 128 - keylen); - } else { - CSHA512().Write(key, keylen).Finalize(rkey); - memset(rkey + 64, 0, 64); - } - - for (int n = 0; n < 128; n++) - rkey[n] ^= 0x5c; - outer.Write(rkey, 128); - - for (int n = 0; n < 128; n++) - rkey[n] ^= 0x5c ^ 0x36; - inner.Write(rkey, 128); -} - -void CHMAC_SHA512::Finalize(unsigned char hash[OUTPUT_SIZE]) -{ - unsigned char temp[64]; - inner.Finalize(temp); - outer.Write(temp, 64).Finalize(hash); -} diff --git a/src/crypto/sha512.h b/src/crypto/sha512.h new file mode 100644 index 0000000000..5566d5db3e --- /dev/null +++ b/src/crypto/sha512.h @@ -0,0 +1,28 @@ +// Copyright (c) 2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CRYPTO_SHA512_H +#define BITCOIN_CRYPTO_SHA512_H + +#include <stdint.h> +#include <stdlib.h> + +/** A hasher class for SHA-512. */ +class CSHA512 +{ +private: + uint64_t s[8]; + unsigned char buf[128]; + size_t bytes; + +public: + static const size_t OUTPUT_SIZE = 64; + + CSHA512(); + CSHA512& Write(const unsigned char* data, size_t len); + void Finalize(unsigned char hash[OUTPUT_SIZE]); + CSHA512& Reset(); +}; + +#endif // BITCOIN_CRYPTO_SHA512_H @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_DB_H @@ -50,7 +50,7 @@ public: void MakeMock(); bool IsMock() { return fMockDb; } - /* + /** * Verify that database file strFile is OK. If it is not, * call the callback to try to recover. * This must be called BEFORE strFile is opened. @@ -60,7 +60,7 @@ public: RECOVER_OK, RECOVER_FAIL }; VerifyResult Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile)); - /* + /** * Salvage data from a file that Verify says is bad. * fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation). * Appends binary key/value pairs to vResult, returns true if successful. diff --git a/src/ecwrapper.cpp b/src/ecwrapper.cpp index 3377dce0c1..5ce7e61294 100644 --- a/src/ecwrapper.cpp +++ b/src/ecwrapper.cpp @@ -13,46 +13,11 @@ namespace { -// Generate a private key from just the secret parameter -int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key) -{ - int ok = 0; - BN_CTX *ctx = NULL; - EC_POINT *pub_key = NULL; - - if (!eckey) return 0; - - const EC_GROUP *group = EC_KEY_get0_group(eckey); - - if ((ctx = BN_CTX_new()) == NULL) - goto err; - - pub_key = EC_POINT_new(group); - - if (pub_key == NULL) - goto err; - - if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) - goto err; - - EC_KEY_set_private_key(eckey,priv_key); - EC_KEY_set_public_key(eckey,pub_key); - - ok = 1; - -err: - - if (pub_key) - EC_POINT_free(pub_key); - if (ctx != NULL) - BN_CTX_free(ctx); - - return(ok); -} - -// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields -// recid selects which key is recovered -// if check is non-zero, additional checks are performed +/** + * Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields + * recid selects which key is recovered + * if check is non-zero, additional checks are performed + */ int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check) { if (!eckey) return 0; @@ -135,48 +100,6 @@ CECKey::~CECKey() { EC_KEY_free(pkey); } -void CECKey::GetSecretBytes(unsigned char vch[32]) const { - const BIGNUM *bn = EC_KEY_get0_private_key(pkey); - assert(bn); - int nBytes = BN_num_bytes(bn); - int n=BN_bn2bin(bn,&vch[32 - nBytes]); - assert(n == nBytes); - memset(vch, 0, 32 - nBytes); -} - -void CECKey::SetSecretBytes(const unsigned char vch[32]) { - bool ret; - BIGNUM bn; - BN_init(&bn); - ret = BN_bin2bn(vch, 32, &bn) != NULL; - assert(ret); - ret = EC_KEY_regenerate_key(pkey, &bn) != 0; - assert(ret); - BN_clear_free(&bn); -} - -int CECKey::GetPrivKeySize(bool fCompressed) { - EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED); - return i2d_ECPrivateKey(pkey, NULL); -} -int CECKey::GetPrivKey(unsigned char* privkey, bool fCompressed) { - EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED); - return i2d_ECPrivateKey(pkey, &privkey); -} - -bool CECKey::SetPrivKey(const unsigned char* privkey, size_t size, bool fSkipCheck) { - if (d2i_ECPrivateKey(&pkey, &privkey, size)) { - if(fSkipCheck) - return true; - - // d2i_ECPrivateKey returns true if parsing succeeds. - // This doesn't necessarily mean the key is valid. - if (EC_KEY_check_key(pkey)) - return true; - } - return false; -} - void CECKey::GetPubKey(std::vector<unsigned char> &pubkey, bool fCompressed) { EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED); int nSize = i2o_ECPublicKey(pkey, NULL); @@ -193,33 +116,6 @@ bool CECKey::SetPubKey(const unsigned char* pubkey, size_t size) { return o2i_ECPublicKey(&pkey, &pubkey, size) != NULL; } -bool CECKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) { - vchSig.clear(); - ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); - if (sig == NULL) - return false; - BN_CTX *ctx = BN_CTX_new(); - BN_CTX_start(ctx); - const EC_GROUP *group = EC_KEY_get0_group(pkey); - BIGNUM *order = BN_CTX_get(ctx); - BIGNUM *halforder = BN_CTX_get(ctx); - EC_GROUP_get_order(group, order, ctx); - BN_rshift1(halforder, order); - if (BN_cmp(sig->s, halforder) > 0) { - // enforce low S values, by negating the value (modulo the order) if above order/2. - BN_sub(sig->s, order, sig->s); - } - BN_CTX_end(ctx); - BN_CTX_free(ctx); - unsigned int nSize = ECDSA_size(pkey); - vchSig.resize(nSize); // Make sure it is big enough - unsigned char *pos = &vchSig[0]; - nSize = i2d_ECDSA_SIG(sig, &pos); - ECDSA_SIG_free(sig); - vchSig.resize(nSize); // Shrink to fit actual size - return true; -} - bool CECKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) { // -1 = error, 0 = bad sig, 1 = good if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) @@ -227,37 +123,6 @@ bool CECKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSi return true; } -bool CECKey::SignCompact(const uint256 &hash, unsigned char *p64, int &rec) { - bool fOk = false; - ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); - if (sig==NULL) - return false; - memset(p64, 0, 64); - int nBitsR = BN_num_bits(sig->r); - int nBitsS = BN_num_bits(sig->s); - if (nBitsR <= 256 && nBitsS <= 256) { - std::vector<unsigned char> pubkey; - GetPubKey(pubkey, true); - for (int i=0; i<4; i++) { - CECKey keyRec; - if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1) { - std::vector<unsigned char> pubkeyRec; - keyRec.GetPubKey(pubkeyRec, true); - if (pubkeyRec == pubkey) { - rec = i; - fOk = true; - break; - } - } - } - assert(fOk); - BN_bn2bin(sig->r,&p64[32-(nBitsR+7)/8]); - BN_bn2bin(sig->s,&p64[64-(nBitsS+7)/8]); - } - ECDSA_SIG_free(sig); - return fOk; -} - bool CECKey::Recover(const uint256 &hash, const unsigned char *p64, int rec) { if (rec<0 || rec>=3) @@ -270,33 +135,6 @@ bool CECKey::Recover(const uint256 &hash, const unsigned char *p64, int rec) return ret; } -bool CECKey::TweakSecret(unsigned char vchSecretOut[32], const unsigned char vchSecretIn[32], const unsigned char vchTweak[32]) -{ - bool ret = true; - BN_CTX *ctx = BN_CTX_new(); - BN_CTX_start(ctx); - BIGNUM *bnSecret = BN_CTX_get(ctx); - BIGNUM *bnTweak = BN_CTX_get(ctx); - BIGNUM *bnOrder = BN_CTX_get(ctx); - EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp256k1); - EC_GROUP_get_order(group, bnOrder, ctx); // what a grossly inefficient way to get the (constant) group order... - BN_bin2bn(vchTweak, 32, bnTweak); - if (BN_cmp(bnTweak, bnOrder) >= 0) - ret = false; // extremely unlikely - BN_bin2bn(vchSecretIn, 32, bnSecret); - BN_add(bnSecret, bnSecret, bnTweak); - BN_nnmod(bnSecret, bnSecret, bnOrder, ctx); - if (BN_is_zero(bnSecret)) - ret = false; // ridiculously unlikely - int nBits = BN_num_bits(bnSecret); - memset(vchSecretOut, 0, 32); - BN_bn2bin(bnSecret, &vchSecretOut[32-(nBits+7)/8]); - EC_GROUP_free(group); - BN_CTX_end(ctx); - BN_CTX_free(ctx); - return ret; -} - bool CECKey::TweakPublic(const unsigned char vchTweak[32]) { bool ret = true; BN_CTX *ctx = BN_CTX_new(); diff --git a/src/ecwrapper.h b/src/ecwrapper.h index a7847d190c..4efde51650 100644 --- a/src/ecwrapper.h +++ b/src/ecwrapper.h @@ -12,7 +12,7 @@ class uint256; -// RAII Wrapper around OpenSSL's EC_KEY +/** RAII Wrapper around OpenSSL's EC_KEY */ class CECKey { private: EC_KEY *pkey; @@ -21,24 +21,18 @@ public: CECKey(); ~CECKey(); - void GetSecretBytes(unsigned char vch[32]) const; - void SetSecretBytes(const unsigned char vch[32]); - int GetPrivKeySize(bool fCompressed); - int GetPrivKey(unsigned char* privkey, bool fCompressed); - bool SetPrivKey(const unsigned char* privkey, size_t size, bool fSkipCheck=false); void GetPubKey(std::vector<unsigned char>& pubkey, bool fCompressed); bool SetPubKey(const unsigned char* pubkey, size_t size); - bool Sign(const uint256 &hash, std::vector<unsigned char>& vchSig); bool Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig); - bool SignCompact(const uint256 &hash, unsigned char *p64, int &rec); - // reconstruct public key from a compact signature - // This is only slightly more CPU intensive than just verifying it. - // If this function succeeds, the recovered public key is guaranteed to be valid - // (the signature is a valid signature of the given data for that key) + /** + * reconstruct public key from a compact signature + * This is only slightly more CPU intensive than just verifying it. + * If this function succeeds, the recovered public key is guaranteed to be valid + * (the signature is a valid signature of the given data for that key) + */ bool Recover(const uint256 &hash, const unsigned char *p64, int rec); - static bool TweakSecret(unsigned char vchSecretOut[32], const unsigned char vchSecretIn[32], const unsigned char vchTweak[32]); bool TweakPublic(const unsigned char vchTweak[32]); static bool SanityCheck(); }; diff --git a/src/hash.cpp b/src/hash.cpp index 2cca06ae23..aaca00ea2d 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "hash.h" +#include "crypto/hmac_sha512.h" inline uint32_t ROTL32(uint32_t x, int8_t r) { diff --git a/src/hash.h b/src/hash.h index 75695160e6..5a34cdc5c3 100644 --- a/src/hash.h +++ b/src/hash.h @@ -7,7 +7,7 @@ #define BITCOIN_HASH_H #include "crypto/ripemd160.h" -#include "crypto/sha2.h" +#include "crypto/sha256.h" #include "serialize.h" #include "uint256.h" #include "version.h" diff --git a/src/init.cpp b/src/init.cpp index b290d54158..11329c16aa 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) @@ -60,7 +60,7 @@ bool fFeeEstimatesInitialized = false; #define MIN_CORE_FILEDESCRIPTORS 150 #endif -// Used to pass flags to the Bind() function +/** Used to pass flags to the Bind() function */ enum BindFlags { BF_NONE = 0, BF_EXPLICIT = (1U << 0), @@ -150,14 +150,9 @@ void Shutdown() { LOCK(cs_main); -#ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->SetBestChain(chainActive.GetLocator()); -#endif - if (pblocktree) - pblocktree->Flush(); - if (pcoinsTip) - pcoinsTip->Flush(); + if (pcoinsTip != NULL) { + FlushStateToDisk(); + } delete pcoinsTip; pcoinsTip = NULL; delete pcoinsdbview; @@ -180,9 +175,9 @@ void Shutdown() LogPrintf("%s: done\n", __func__); } -// -// Signal handlers are very limited in what they are allowed to do, so: -// +/** + * Signal handlers are very limited in what they are allowed to do, so: + */ void HandleSIGTERM(int) { fRequestShutdown = true; @@ -290,6 +285,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -paytxfee=<amt> " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n"; strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n"; strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n"; + strUsage += " -sendfreetransactions " + strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0) + "\n"; strUsage += " -spendzeroconfchange " + strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1) + "\n"; strUsage += " -txconfirmtarget=<n> " + strprintf(_("If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: %u)"), 1) + "\n"; strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n"; @@ -334,8 +330,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n"; if (GetBoolArg("-help-debug", false)) { - strUsage += " -printblock=<hash> " + _("Print block on startup, if found in block index") + "\n"; - strUsage += " -printblocktree " + strprintf(_("Print block tree on startup (default: %u)"), 0) + "\n"; strUsage += " -printpriority " + strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), 0) + "\n"; strUsage += " -privdb " + strprintf(_("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)"), 1) + "\n"; strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n"; @@ -356,6 +350,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += "\n" + _("RPC server options:") + "\n"; strUsage += " -server " + _("Accept command line and JSON-RPC commands") + "\n"; + strUsage += " -rest " + strprintf(_("Accept public REST requests (default: %u)"), 0) + "\n"; strUsage += " -rpcbind=<addr> " + _("Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)") + "\n"; strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n"; strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n"; @@ -378,7 +373,7 @@ std::string LicenseInfo() "\n" + FormatParagraph(_("This is experimental software.")) + "\n" + "\n" + - FormatParagraph(_("Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.")) + "\n" + + FormatParagraph(_("Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.")) + "\n" + "\n" + FormatParagraph(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.")) + "\n"; @@ -704,6 +699,7 @@ bool AppInit2(boost::thread_group& threadGroup) } nTxConfirmTarget = GetArg("-txconfirmtarget", 1); bSpendZeroConfChange = GetArg("-spendzeroconfchange", true); + fSendFreeTransactions = GetArg("-sendfreetransactions", false); std::string strWalletFile = GetArg("-wallet", "wallet.dat"); #endif // ENABLE_WALLET @@ -852,10 +848,8 @@ bool AppInit2(boost::thread_group& threadGroup) if (!addrProxy.IsValid()) return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"])); - if (!IsLimited(NET_IPV4)) - SetProxy(NET_IPV4, addrProxy); - if (!IsLimited(NET_IPV6)) - SetProxy(NET_IPV6, addrProxy); + SetProxy(NET_IPV4, addrProxy); + SetProxy(NET_IPV6, addrProxy); SetNameProxy(addrProxy); fProxy = true; } @@ -1052,34 +1046,6 @@ bool AppInit2(boost::thread_group& threadGroup) } LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); - if (GetBoolArg("-printblockindex", false) || GetBoolArg("-printblocktree", false)) - { - PrintBlockTree(); - return false; - } - - if (mapArgs.count("-printblock")) - { - string strMatch = mapArgs["-printblock"]; - int nFound = 0; - for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) - { - uint256 hash = (*mi).first; - if (boost::algorithm::starts_with(hash.ToString(), strMatch)) - { - CBlockIndex* pindex = (*mi).second; - CBlock block; - ReadBlockFromDisk(block, pindex); - block.BuildMerkleTree(); - LogPrintf("%s\n", block.ToString()); - nFound++; - } - } - if (nFound == 0) - LogPrintf("No blocks matching %s were found\n", strMatch); - return false; - } - boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION); // Allowed to fail as this file IS missing on first startup. diff --git a/src/init.h b/src/init.h index aaf8c07e6e..f2f7ac6747 100644 --- a/src/init.h +++ b/src/init.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_INIT_H @@ -22,7 +22,7 @@ bool ShutdownRequested(); void Shutdown(); bool AppInit2(boost::thread_group& threadGroup); -/* The help message mode determines what help message to show */ +/** The help message mode determines what help message to show */ enum HelpMessageMode { HMM_BITCOIND, HMM_BITCOIN_QT diff --git a/src/key.cpp b/src/key.cpp index 0ca9a681a3..acf62360a4 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -4,26 +4,22 @@ #include "key.h" -#include "crypto/sha2.h" +#include "crypto/hmac_sha512.h" +#include "crypto/rfc6979_hmac_sha256.h" #include "eccryptoverify.h" #include "pubkey.h" #include "random.h" -#ifdef USE_SECP256K1 #include <secp256k1.h> -#else #include "ecwrapper.h" -#endif //! anonymous namespace namespace { -#ifdef USE_SECP256K1 -#include <secp256k1.h> class CSecp256k1Init { public: CSecp256k1Init() { - secp256k1_start(); + secp256k1_start(SECP256K1_START_SIGN); } ~CSecp256k1Init() { secp256k1_stop(); @@ -31,7 +27,6 @@ public: }; static CSecp256k1Init instance_of_csecp256k1; -#endif } // anon namespace bool CKey::Check(const unsigned char *vch) { @@ -47,15 +42,8 @@ void CKey::MakeNewKey(bool fCompressedIn) { } bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) { -#ifdef USE_SECP256K1 - if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size())) - return false; -#else - CECKey key; - if (!key.SetPrivKey(&privkey[0], privkey.size())) + if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size())) return false; - key.GetSecretBytes(vch); -#endif fCompressed = fCompressedIn; fValid = true; return true; @@ -65,62 +53,56 @@ CPrivKey CKey::GetPrivKey() const { assert(fValid); CPrivKey privkey; int privkeylen, ret; -#ifdef USE_SECP256K1 privkey.resize(279); privkeylen = 279; - ret = secp256k1_ecdsa_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed); + ret = secp256k1_ec_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed); assert(ret); privkey.resize(privkeylen); -#else - CECKey key; - key.SetSecretBytes(vch); - privkeylen = key.GetPrivKeySize(fCompressed); - assert(privkeylen); - privkey.resize(privkeylen); - ret = key.GetPrivKey(&privkey[0], fCompressed); - assert(ret == (int)privkey.size()); -#endif return privkey; } CPubKey CKey::GetPubKey() const { assert(fValid); CPubKey result; -#ifdef USE_SECP256K1 int clen = 65; - int ret = secp256k1_ecdsa_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed); + int ret = secp256k1_ec_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed); assert((int)result.size() == clen); assert(ret); -#else - std::vector<unsigned char> pubkey; - CECKey key; - key.SetSecretBytes(vch); - key.GetPubKey(pubkey, fCompressed); - result.Set(pubkey.begin(), pubkey.end()); -#endif assert(result.IsValid()); return result; } -bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const { +bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const { if (!fValid) return false; -#ifdef USE_SECP256K1 vchSig.resize(72); - int nSigLen = 72; - CKey nonce; + RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32); do { - nonce.MakeNewKey(true); - if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin())) - break; + uint256 nonce; + prng.Generate((unsigned char*)&nonce, 32); + nonce += test_case; + int nSigLen = 72; + int ret = secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), (unsigned char*)&nonce); + nonce = 0; + if (ret) { + vchSig.resize(nSigLen); + return true; + } } while(true); - vchSig.resize(nSigLen); - return true; -#else - CECKey key; - key.SetSecretBytes(vch); - return key.Sign(hash, vchSig); -#endif +} + +bool CKey::VerifyPubKey(const CPubKey& pubkey) const { + if (pubkey.IsCompressed() != fCompressed) { + return false; + } + unsigned char rnd[8]; + std::string str = "Bitcoin key verification\n"; + GetRandBytes(rnd, sizeof(rnd)); + uint256 hash; + CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize((unsigned char*)&hash); + std::vector<unsigned char> vchSig; + Sign(hash, vchSig); + return pubkey.Verify(hash, vchSig); } bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const { @@ -128,44 +110,30 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) return false; vchSig.resize(65); int rec = -1; -#ifdef USE_SECP256K1 - CKey nonce; + RFC6979_HMAC_SHA256 prng(begin(), 32, (unsigned char*)&hash, 32); do { - nonce.MakeNewKey(true); - if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec)) + uint256 nonce; + prng.Generate((unsigned char*)&nonce, 32); + int ret = secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), (unsigned char*)&nonce, &rec); + nonce = 0; + if (ret) break; } while(true); -#else - CECKey key; - key.SetSecretBytes(vch); - if (!key.SignCompact(hash, &vchSig[1], rec)) - return false; -#endif assert(rec != -1); vchSig[0] = 27 + rec + (fCompressed ? 4 : 0); return true; } bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) { -#ifdef USE_SECP256K1 - if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size())) + if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size())) return false; -#else - CECKey key; - if (!key.SetPrivKey(&privkey[0], privkey.size(), fSkipCheck)) - return false; - key.GetSecretBytes(vch); -#endif fCompressed = vchPubKey.IsCompressed(); fValid = true; if (fSkipCheck) return true; - if (GetPubKey() != vchPubKey) - return false; - - return true; + return VerifyPubKey(vchPubKey); } bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const { @@ -182,12 +150,8 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild BIP32Hash(cc, nChild, 0, begin(), out); } memcpy(ccChild, out+32, 32); -#ifdef USE_SECP256K1 memcpy((unsigned char*)keyChild.begin(), begin(), 32); - bool ret = secp256k1_ecdsa_privkey_tweak_add((unsigned char*)keyChild.begin(), out); -#else - bool ret = CECKey::TweakSecret((unsigned char*)keyChild.begin(), begin(), out); -#endif + bool ret = secp256k1_ec_privkey_tweak_add((unsigned char*)keyChild.begin(), out); UnlockObject(out); keyChild.fCompressed = true; keyChild.fValid = ret; @@ -245,9 +209,13 @@ void CExtKey::Decode(const unsigned char code[74]) { } bool ECC_InitSanityCheck() { -#ifdef USE_SECP256K1 - return true; -#else - return CECKey::SanityCheck(); +#if !defined(USE_SECP256K1) + if (!CECKey::SanityCheck()) { + return false; + } #endif + CKey key; + key.MakeNewKey(true); + CPubKey pubkey = key.GetPubKey(); + return key.VerifyPubKey(pubkey); } @@ -13,9 +13,10 @@ #include <stdexcept> #include <vector> -struct CExtPubKey; class CPubKey; +struct CExtPubKey; + /** * secp256k1: * const unsigned int PRIVATE_KEY_SIZE = 279; @@ -121,8 +122,12 @@ public: */ CPubKey GetPubKey() const; - //! Create a DER-serialized signature. - bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig) const; + /** + * Create a DER-serialized signature. + * The test_case parameter tweaks the deterministic nonce, and is only for + * testing. It should be zero for normal use. + */ + bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, uint32_t test_case = 0) const; /** * Create a compact signature (65 bytes), which allows reconstructing the used public key. @@ -136,6 +141,12 @@ public: //! Derive BIP32 child key. bool Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const; + /** + * Verify thoroughly whether a private key and a public key match. + * This is done using a different mechanism than just regenerating it. + */ + bool VerifyPubKey(const CPubKey& vchPubKey) const; + //! Load private key and check that public key matches. bool Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck); diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h index 10b7a2427c..42479206c8 100644 --- a/src/leveldbwrapper.h +++ b/src/leveldbwrapper.h @@ -1,5 +1,5 @@ -// Copyright (c) 2012-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2012-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_LEVELDBWRAPPER_H @@ -24,7 +24,7 @@ public: void HandleError(const leveldb::Status& status) throw(leveldb_error); -// Batch of changes queued to be written to a CLevelDBWrapper +/** Batch of changes queued to be written to a CLevelDBWrapper */ class CLevelDBBatch { friend class CLevelDBWrapper; @@ -64,25 +64,25 @@ public: class CLevelDBWrapper { private: - // custom environment this database is using (may be NULL in case of default environment) + //! custom environment this database is using (may be NULL in case of default environment) leveldb::Env* penv; - // database options used + //! database options used leveldb::Options options; - // options used when reading from the database + //! options used when reading from the database leveldb::ReadOptions readoptions; - // options used when iterating over values of the database + //! options used when iterating over values of the database leveldb::ReadOptions iteroptions; - // options used when writing to the database + //! options used when writing to the database leveldb::WriteOptions writeoptions; - // options used when sync writing to the database + //! options used when sync writing to the database leveldb::WriteOptions syncoptions; - // the database itself + //! the database itself leveldb::DB* pdb; public: diff --git a/src/main.cpp b/src/main.cpp index 512df775d0..60e1db6647 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "main.h" @@ -33,9 +33,9 @@ using namespace std; # error "Bitcoin cannot be compiled without assertions." #endif -// -// Global state -// +/** + * Global state + */ CCriticalSection cs_main; @@ -66,7 +66,7 @@ map<uint256, COrphanTx> mapOrphanTransactions; map<uint256, set<uint256> > mapOrphanTransactionsByPrev; void EraseOrphansFor(NodeId peer); -// Constant stuff for coinbase transactions we create: +/** Constant stuff for coinbase transactions we create: */ CScript COINBASE_FLAGS; const string strMessageMagic = "Bitcoin Signed Message:\n"; @@ -97,39 +97,50 @@ namespace { CBlockIndex *pindexBestInvalid; - // The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least - // as good as our current tip. Entries may be failed, though. + /** + * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least + * as good as our current tip. Entries may be failed, though. + */ set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates; - // Number of nodes with fSyncStarted. + /** Number of nodes with fSyncStarted. */ int nSyncStarted = 0; - // All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions. + /** All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions. */ multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; CCriticalSection cs_LastBlockFile; std::vector<CBlockFileInfo> vinfoBlockFile; int nLastBlockFile = 0; - // Every received block is assigned a unique and increasing identifier, so we - // know which one to give priority in case of a fork. + /** + * Every received block is assigned a unique and increasing identifier, so we + * know which one to give priority in case of a fork. + */ CCriticalSection cs_nBlockSequenceId; - // Blocks loaded from disk are assigned id 0, so start the counter at 1. + /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */ uint32_t nBlockSequenceId = 1; - // Sources of received blocks, to be able to send them reject messages or ban - // them, if processing happens afterwards. Protected by cs_main. + /** + * Sources of received blocks, to be able to send them reject messages or ban + * them, if processing happens afterwards. Protected by cs_main. + */ map<uint256, NodeId> mapBlockSource; - // Blocks that are in flight, and that are in the queue to be downloaded. - // Protected by cs_main. + /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ struct QueuedBlock { uint256 hash; - CBlockIndex *pindex; // Optional. - int64_t nTime; // Time of "getdata" request in microseconds. + CBlockIndex *pindex; //! Optional. + int64_t nTime; //! Time of "getdata" request in microseconds. }; map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight; - // Number of preferrable block download peers. + /** Number of preferable block download peers. */ int nPreferredDownload = 0; + + /** Dirty block index entries. */ + set<CBlockIndex*> setDirtyBlockIndex; + + /** Dirty block file entries. */ + set<int> setDirtyFileInfo; } // anon namespace ////////////////////////////////////////////////////////////////////////////// @@ -142,19 +153,19 @@ namespace { namespace { struct CMainSignals { - // Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. + /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */ boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction; - // Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). + /** Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). */ boost::signals2::signal<void (const uint256 &)> EraseTransaction; - // Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). + /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */ boost::signals2::signal<void (const uint256 &)> UpdatedTransaction; - // Notifies listeners of a new active block chain. + /** Notifies listeners of a new active block chain. */ boost::signals2::signal<void (const CBlockLocator &)> SetBestChain; - // Notifies listeners about an inventory item being seen on the network. + /** Notifies listeners about an inventory item being seen on the network. */ boost::signals2::signal<void (const uint256 &)> Inventory; - // Tells listeners to broadcast their data. + /** Tells listeners to broadcast their data. */ boost::signals2::signal<void ()> Broadcast; - // Notifies listeners of a block validation result + /** Notifies listeners of a block validation result */ boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked; } g_signals; @@ -207,32 +218,34 @@ struct CBlockReject { uint256 hashBlock; }; -// Maintain validation-specific state about nodes, protected by cs_main, instead -// by CNode's own locks. This simplifies asynchronous operation, where -// processing of incoming data is done after the ProcessMessage call returns, -// and we're no longer holding the node's locks. +/** + * Maintain validation-specific state about nodes, protected by cs_main, instead + * by CNode's own locks. This simplifies asynchronous operation, where + * processing of incoming data is done after the ProcessMessage call returns, + * and we're no longer holding the node's locks. + */ struct CNodeState { - // Accumulated misbehaviour score for this peer. + //! Accumulated misbehaviour score for this peer. int nMisbehavior; - // Whether this peer should be disconnected and banned (unless whitelisted). + //! Whether this peer should be disconnected and banned (unless whitelisted). bool fShouldBan; - // String name of this peer (debugging/logging purposes). + //! String name of this peer (debugging/logging purposes). std::string name; - // List of asynchronously-determined block rejections to notify this peer about. + //! List of asynchronously-determined block rejections to notify this peer about. std::vector<CBlockReject> rejects; - // The best known block we know this peer has announced. + //! The best known block we know this peer has announced. CBlockIndex *pindexBestKnownBlock; - // The hash of the last unknown block this peer has announced. + //! The hash of the last unknown block this peer has announced. uint256 hashLastUnknownBlock; - // The last full block we both have. + //! The last full block we both have. CBlockIndex *pindexLastCommonBlock; - // Whether we've started headers synchronization with this peer. + //! Whether we've started headers synchronization with this peer. bool fSyncStarted; - // Since when we're stalling block download progress (in microseconds), or 0. + //! Since when we're stalling block download progress (in microseconds), or 0. int64_t nStallingSince; list<QueuedBlock> vBlocksInFlight; int nBlocksInFlight; - // Whether we consider this a preferred download peer. + //! Whether we consider this a preferred download peer. bool fPreferredDownload; CNodeState() { @@ -248,7 +261,7 @@ struct CNodeState { } }; -// Map maintaining per-node state. Requires cs_main. +/** Map maintaining per-node state. Requires cs_main. */ map<NodeId, CNodeState> mapNodeState; // Requires cs_main. @@ -702,15 +715,15 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) return true; } -// -// Check transaction inputs to mitigate two -// potential denial-of-service attacks: -// -// 1. scriptSigs with extra data stuffed into them, -// not consumed by scriptPubKey (or P2SH script) -// 2. P2SH scripts with a crazy number of expensive -// CHECKSIG/CHECKMULTISIG operations -// +/** + * Check transaction inputs to mitigate two + * potential denial-of-service attacks: + * + * 1. scriptSigs with extra data stuffed into them, + * not consumed by scriptPubKey (or P2SH script) + * 2. P2SH scripts with a crazy number of expensive + * CHECKSIG/CHECKMULTISIG operations + */ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) { if (tx.IsCoinBase()) @@ -1048,7 +1061,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return true; } -// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock +/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) { CBlockIndex *pindexSlow = NULL; @@ -1137,11 +1150,6 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos) pos.nPos = (unsigned int)fileOutPos; fileout << block; - // Flush stdio buffers and commit to disk before returning - fflush(fileout.Get()); - if (!IsInitialBlockDownload()) - FileCommit(fileout.Get()); - return true; } @@ -1198,15 +1206,14 @@ bool IsInitialBlockDownload() LOCK(cs_main); if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate()) return true; - static int64_t nLastUpdate; - static CBlockIndex* pindexLastBest; - if (chainActive.Tip() != pindexLastBest) - { - pindexLastBest = chainActive.Tip(); - nLastUpdate = GetTime(); - } - return (GetTime() - nLastUpdate < 10 && - chainActive.Tip()->GetBlockTime() < GetTime() - 24 * 60 * 60); + static bool lockIBDState = false; + if (lockIBDState) + return false; + bool state = (chainActive.Height() < pindexBestHeader->nHeight - 24 * 6 || + pindexBestHeader->GetBlockTime() < GetTime() - 24 * 60 * 60); + if (!state) + lockIBDState = true; + return state; } bool fLargeWorkForkFound = false; @@ -1226,15 +1233,15 @@ void CheckForkWarningConditions() if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 72) pindexBestForkTip = NULL; - if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (chainActive.Tip()->GetBlockWork() * 6))) + if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (GetBlockProof(*chainActive.Tip()) * 6))) { - if (!fLargeWorkForkFound) + if (!fLargeWorkForkFound && pindexBestForkBase) { std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") + pindexBestForkBase->phashBlock->ToString() + std::string("'"); CAlert::Notify(warning, true); } - if (pindexBestForkTip) + if (pindexBestForkTip && pindexBestForkBase) { LogPrintf("CheckForkWarningConditions: Warning: Large valid fork found\n forking the chain at height %d (%s)\n lasting to height %d (%s).\nChain state database corruption likely.\n", pindexBestForkBase->nHeight, pindexBestForkBase->phashBlock->ToString(), @@ -1277,7 +1284,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) // We define it this way because it allows us to only store the highest fork tip (+ base) which meets // the 7-block condition and from this always have the most-likely-to-cause-warning fork if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) && - pindexNewForkTip->nChainWork - pfork->nChainWork > (pfork->GetBlockWork() * 7) && + pindexNewForkTip->nChainWork - pfork->nChainWork > (GetBlockProof(*pfork) * 7) && chainActive.Height() - pindexNewForkTip->nHeight < 72) { pindexBestForkTip = pindexNewForkTip; @@ -1327,7 +1334,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state if (state.IsInvalid(nDoS)) { std::map<uint256, NodeId>::iterator it = mapBlockSource.find(pindex->GetBlockHash()); if (it != mapBlockSource.end() && State(it->second)) { - CBlockReject reject = {state.GetRejectCode(), state.GetRejectReason(), pindex->GetBlockHash()}; + CBlockReject reject = {state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash()}; State(it->second)->rejects.push_back(reject); if (nDoS > 0) Misbehaving(it->second, nDoS); @@ -1335,7 +1342,7 @@ void static InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state } if (!state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; - pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex)); + setDirtyBlockIndex.insert(pindex); setBlockIndexCandidates.erase(pindex); InvalidChainFound(pindex); } @@ -1357,10 +1364,11 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight); } -bool CScriptCheck::operator()() const { +bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; - if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore))) - return error("CScriptCheck() : %s:%d VerifySignature failed", ptxTo->GetHash().ToString(), nIn); + if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore), &error)) { + return ::error("CScriptCheck() : %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error)); + } return true; } @@ -1448,7 +1456,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi CScriptCheck check(*coins, tx, i, flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore); if (check()) - return state.Invalid(false, REJECT_NONSTANDARD, "non-mandatory-script-verify-flag"); + return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); } // Failures of other flags indicate a transaction that is // invalid in new blocks, e.g. a invalid P2SH. We DoS ban @@ -1457,7 +1465,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // as to the correct behavior - we may want to continue // peering with non-upgraded nodes even after a soft-fork // super-majority vote has passed. - return state.DoS(100,false, REJECT_INVALID, "mandatory-script-verify-flag-failed"); + return state.DoS(100,false, REJECT_INVALID, strprintf("mandatory-script-verify-flag-failed (%s)", ScriptErrorString(check.GetScriptError()))); } } } @@ -1593,7 +1601,7 @@ static int64_t nTimeIndex = 0; static int64_t nTimeCallbacks = 0; static int64_t nTimeTotal = 0; -bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck) +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck) { AssertLockHeld(cs_main); // Check it again in case a previous version let a bad block in @@ -1732,10 +1740,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C } pindex->RaiseValidity(BLOCK_VALID_SCRIPTS); - - CDiskBlockIndex blockindex(pindex); - if (!pblocktree->WriteBlockIndex(blockindex)) - return state.Abort("Failed to write block index"); + setDirtyBlockIndex.insert(pindex); } if (fTxIndex) @@ -1759,10 +1764,23 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C return true; } -// Update the on-disk chain state. -bool static WriteChainState(CValidationState &state, bool forceWrite=false) { +enum FlushStateMode { + FLUSH_STATE_IF_NEEDED, + FLUSH_STATE_PERIODIC, + FLUSH_STATE_ALWAYS +}; + +/** + * Update the on-disk chain state. + * The caches and indexes are flushed if either they're too large, forceWrite is set, or + * fast is not set and it's been a while since the last write. + */ +bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { + LOCK(cs_main); static int64_t nLastWrite = 0; - if (forceWrite || pcoinsTip->GetCacheSize() > nCoinCacheSize || (!IsInitialBlockDownload() && GetTimeMicros() > nLastWrite + 600*1000000)) { + if ((mode == FLUSH_STATE_ALWAYS) || + ((mode == FLUSH_STATE_PERIODIC || mode == FLUSH_STATE_IF_NEEDED) && pcoinsTip->GetCacheSize() > nCoinCacheSize) || + (mode == FLUSH_STATE_PERIODIC && GetTimeMicros() > nLastWrite + DATABASE_WRITE_INTERVAL * 1000000)) { // Typical CCoins structures on disk are around 100 bytes in size. // Pushing a new one to the database can cause it to be written // twice (once in the log, and once in the tables). This is already @@ -1770,16 +1788,45 @@ bool static WriteChainState(CValidationState &state, bool forceWrite=false) { // overwrite one. Still, use a conservative safety factor of 2. if (!CheckDiskSpace(100 * 2 * 2 * pcoinsTip->GetCacheSize())) return state.Error("out of disk space"); + // First make sure all block and undo data is flushed to disk. FlushBlockFile(); + // Then update all block file information (which may refer to block and undo files). + bool fileschanged = false; + for (set<int>::iterator it = setDirtyFileInfo.begin(); it != setDirtyFileInfo.end(); ) { + if (!pblocktree->WriteBlockFileInfo(*it, vinfoBlockFile[*it])) { + return state.Abort("Failed to write to block index"); + } + fileschanged = true; + setDirtyFileInfo.erase(it++); + } + if (fileschanged && !pblocktree->WriteLastBlockFile(nLastBlockFile)) { + return state.Abort("Failed to write to block index"); + } + for (set<CBlockIndex*>::iterator it = setDirtyBlockIndex.begin(); it != setDirtyBlockIndex.end(); ) { + if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(*it))) { + return state.Abort("Failed to write to block index"); + } + setDirtyBlockIndex.erase(it++); + } pblocktree->Sync(); + // Finally flush the chainstate (which may refer to block index entries). if (!pcoinsTip->Flush()) return state.Abort("Failed to write to coin database"); + // Update best block in wallet (so we can detect restored wallets). + if (mode != FLUSH_STATE_IF_NEEDED) { + g_signals.SetBestChain(chainActive.GetLocator()); + } nLastWrite = GetTimeMicros(); } return true; } -// Update chainActive and related internal data structures. +void FlushStateToDisk() { + CValidationState state; + FlushStateToDisk(state, FLUSH_STATE_ALWAYS); +} + +/** Update chainActive and related internal data structures. */ void static UpdateTip(CBlockIndex *pindexNew) { chainActive.SetTip(pindexNew); @@ -1818,7 +1865,7 @@ void static UpdateTip(CBlockIndex *pindexNew) { } } -// Disconnect chainActive's tip. +/** Disconnect chainActive's tip. */ bool static DisconnectTip(CValidationState &state) { CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); @@ -1837,7 +1884,7 @@ bool static DisconnectTip(CValidationState &state) { } LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); // Write the chain state to disk, if necessary. - if (!WriteChainState(state)) + if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED)) return false; // Resurrect mempool transactions from the disconnected block. BOOST_FOREACH(const CTransaction &tx, block.vtx) { @@ -1865,8 +1912,10 @@ static int64_t nTimeFlush = 0; static int64_t nTimeChainState = 0; static int64_t nTimePostConnect = 0; -// Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock -// corresponding to pindexNew, to bypass loading it again from disk. +/** + * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock + * corresponding to pindexNew, to bypass loading it again from disk. + */ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) { assert(pindexNew->pprev == chainActive.Tip()); mempool.check(pcoinsTip); @@ -1900,7 +1949,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3; LogPrint("bench", " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001); // Write the chain state to disk, if necessary. - if (!WriteChainState(state)) + if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED)) return false; int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4; LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); @@ -1919,10 +1968,6 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * BOOST_FOREACH(const CTransaction &tx, pblock->vtx) { SyncWithWallets(tx, pblock); } - // Update best block in wallet (so we can detect restored wallets) - // Emit this signal after the SyncWithWallets signals as the wallet relies on that everything up to this point has been synced - if ((chainActive.Height() % 20160) == 0 || ((chainActive.Height() % 144) == 0 && !IsInitialBlockDownload())) - g_signals.SetBestChain(chainActive.GetLocator()); int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); @@ -1930,8 +1975,10 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * return true; } -// Return the tip of the chain with the most work in it, that isn't -// known to be invalid (it's however far from certain to be valid). +/** + * Return the tip of the chain with the most work in it, that isn't + * known to be invalid (it's however far from certain to be valid). + */ static CBlockIndex* FindMostWorkChain() { do { CBlockIndex *pindexNew = NULL; @@ -1972,8 +2019,22 @@ static CBlockIndex* FindMostWorkChain() { } while(true); } -// Try to make some progress towards making pindexMostWork the active block. -// pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. +/** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */ +static void PruneBlockIndexCandidates() { + // Note that we can't delete the current block itself, as we may need to return to it later in case a + // reorganization to a better block fails. + std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin(); + while (it != setBlockIndexCandidates.end() && setBlockIndexCandidates.value_comp()(*it, chainActive.Tip())) { + setBlockIndexCandidates.erase(it++); + } + // Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates. + assert(!setBlockIndexCandidates.empty()); +} + +/** + * Try to make some progress towards making pindexMostWork the active block. + * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. + */ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) { AssertLockHeld(cs_main); bool fInvalidFound = false; @@ -2019,15 +2080,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo return false; } } else { - // Delete all entries in setBlockIndexCandidates that are worse than our new current block. - // Note that we can't delete the current block itself, as we may need to return to it later in case a - // reorganization to a better block fails. - std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin(); - while (setBlockIndexCandidates.value_comp()(*it, chainActive.Tip())) { - setBlockIndexCandidates.erase(it++); - } - // Either the current tip or a successor of it we're working towards is left in setBlockIndexCandidates. - assert(!setBlockIndexCandidates.empty()); + PruneBlockIndexCandidates(); if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) { // We're in a better position than we were. Return temporarily to release the lock. fContinue = false; @@ -2043,15 +2096,14 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo else CheckForkWarningConditions(); - if (!pblocktree->Flush()) - return state.Abort("Failed to sync block index"); - return true; } -// Make the best chain active, in multiple steps. The result is either failure -// or an activated best chain. pblock is either NULL or a pointer to a block -// that is already loaded (to avoid loading it again from disk). +/** + * Make the best chain active, in multiple steps. The result is either failure + * or an activated best chain. pblock is either NULL or a pointer to a block + * that is already loaded (to avoid loading it again from disk). + */ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { CBlockIndex *pindexNewTip = NULL; CBlockIndex *pindexMostWork = NULL; @@ -2086,11 +2138,83 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate)) pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip)); } - + // Notify external listeners about the new tip. uiInterface.NotifyBlockTip(hashNewTip); } } while(pindexMostWork != chainActive.Tip()); + // Write changes periodically to disk, after relay. + if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) { + return false; + } + + return true; +} + +bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) { + AssertLockHeld(cs_main); + + // Mark the block itself as invalid. + pindex->nStatus |= BLOCK_FAILED_VALID; + setDirtyBlockIndex.insert(pindex); + setBlockIndexCandidates.erase(pindex); + + while (chainActive.Contains(pindex)) { + CBlockIndex *pindexWalk = chainActive.Tip(); + pindexWalk->nStatus |= BLOCK_FAILED_CHILD; + setDirtyBlockIndex.insert(pindexWalk); + setBlockIndexCandidates.erase(pindexWalk); + // ActivateBestChain considers blocks already in chainActive + // unconditionally valid already, so force disconnect away from it. + if (!DisconnectTip(state)) { + return false; + } + } + + // The resulting new best tip may not be in setBlockIndexCandidates anymore, so + // add them again. + BlockMap::iterator it = mapBlockIndex.begin(); + while (it != mapBlockIndex.end()) { + if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) { + setBlockIndexCandidates.insert(pindex); + } + it++; + } + + InvalidChainFound(pindex); + return true; +} + +bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex) { + AssertLockHeld(cs_main); + + int nHeight = pindex->nHeight; + + // Remove the invalidity flag from this block and all its descendants. + BlockMap::iterator it = mapBlockIndex.begin(); + while (it != mapBlockIndex.end()) { + if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) { + it->second->nStatus &= ~BLOCK_FAILED_MASK; + setDirtyBlockIndex.insert(it->second); + if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) { + setBlockIndexCandidates.insert(it->second); + } + if (it->second == pindexBestInvalid) { + // Reset invalid block marker if it was pointing to one of those. + pindexBestInvalid = NULL; + } + } + it++; + } + + // Remove the invalidity flag from all ancestors too. + while (pindex != NULL) { + if (pindex->nStatus & BLOCK_FAILED_MASK) { + pindex->nStatus &= ~BLOCK_FAILED_MASK; + setDirtyBlockIndex.insert(pindex); + } + pindex = pindex->pprev; + } return true; } @@ -2118,18 +2242,17 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block) pindexNew->nHeight = pindexNew->pprev->nHeight + 1; pindexNew->BuildSkip(); } - pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork(); + pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew); pindexNew->RaiseValidity(BLOCK_VALID_TREE); if (pindexBestHeader == NULL || pindexBestHeader->nChainWork < pindexNew->nChainWork) pindexBestHeader = pindexNew; - // Ok if it fails, we'll download the header again next time. - pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)); + setDirtyBlockIndex.insert(pindexNew); return pindexNew; } -// Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). +/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) { pindexNew->nTx = block.vtx.size(); @@ -2143,6 +2266,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl LOCK(cs_nBlockSequenceId); pindexNew->nSequenceId = nBlockSequenceId++; } + setDirtyBlockIndex.insert(pindexNew); if (pindexNew->pprev == NULL || pindexNew->pprev->nChainTx) { // If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS. @@ -2162,15 +2286,11 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl range.first++; mapBlocksUnlinked.erase(it); } - if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex))) - return state.Abort("Failed to write block index"); } } else { if (pindexNew->pprev && pindexNew->pprev->IsValid(BLOCK_VALID_TREE)) { mapBlocksUnlinked.insert(std::make_pair(pindexNew->pprev, pindexNew)); } - if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew))) - return state.Abort("Failed to write block index"); } return true; @@ -2178,8 +2298,6 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) { - bool fUpdatedLast = false; - LOCK(cs_LastBlockFile); unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile; @@ -2195,7 +2313,6 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd if (vinfoBlockFile.size() <= nFile) { vinfoBlockFile.resize(nFile + 1); } - fUpdatedLast = true; } pos.nFile = nFile; pos.nPos = vinfoBlockFile[nFile].nSize; @@ -2222,11 +2339,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd } } - if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, vinfoBlockFile[nFile])) - return state.Abort("Failed to write file info"); - if (fUpdatedLast) - pblocktree->WriteLastBlockFile(nLastBlockFile); - + setDirtyFileInfo.insert(nFile); return true; } @@ -2239,9 +2352,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne unsigned int nNewSize; pos.nPos = vinfoBlockFile[nFile].nUndoSize; nNewSize = vinfoBlockFile[nFile].nUndoSize += nAddSize; - if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, vinfoBlockFile[nLastBlockFile])) { - return state.Abort("Failed to write block info"); - } + setDirtyFileInfo.insert(nFile); unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE; unsigned int nNewChunks = (nNewSize + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE; @@ -2280,6 +2391,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo { // These are checks that are independent of context. + // Check that the header is valid (particularly PoW). This is mostly + // redundant with the call in AcceptBlockHeader. if (!CheckBlockHeader(block, state, fCheckPOW)) return false; @@ -2334,6 +2447,73 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo return true; } +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev) +{ + uint256 hash = block.GetHash(); + if (hash == Params().HashGenesisBlock()) + return true; + + assert(pindexPrev); + + int nHeight = pindexPrev->nHeight+1; + + // Check proof of work + if ((!Params().SkipProofOfWorkCheck()) && + (block.nBits != GetNextWorkRequired(pindexPrev, &block))) + return state.DoS(100, error("%s : incorrect proof of work", __func__), + REJECT_INVALID, "bad-diffbits"); + + // Check timestamp against prev + if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) + return state.Invalid(error("%s : block's timestamp is too early", __func__), + REJECT_INVALID, "time-too-old"); + + // Check that the block chain matches the known block chain up to a checkpoint + if (!Checkpoints::CheckBlock(nHeight, hash)) + return state.DoS(100, error("%s : rejected by checkpoint lock-in at %d", __func__, nHeight), + REJECT_CHECKPOINT, "checkpoint mismatch"); + + // Don't accept any forks from the main chain prior to last checkpoint + CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(); + if (pcheckpoint && nHeight < pcheckpoint->nHeight) + return state.DoS(100, error("%s : forked chain older than last checkpoint (height %d)", __func__, nHeight)); + + // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: + if (block.nVersion < 2 && + CBlockIndex::IsSuperMajority(2, pindexPrev, Params().RejectBlockOutdatedMajority())) + { + return state.Invalid(error("%s : rejected nVersion=1 block", __func__), + REJECT_OBSOLETE, "bad-version"); + } + + return true; +} + +bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex * const pindexPrev) +{ + const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1; + + // Check that all transactions are finalized + BOOST_FOREACH(const CTransaction& tx, block.vtx) + if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) { + return state.DoS(10, error("%s : contains a non-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal"); + } + + // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height + // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): + if (block.nVersion >= 2 && + CBlockIndex::IsSuperMajority(2, pindexPrev, Params().EnforceBlockUpgradeMajority())) + { + CScript expect = CScript() << nHeight; + if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || + !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) { + return state.DoS(100, error("%s : block height mismatch in coinbase", __func__), REJECT_INVALID, "bad-cb-height"); + } + } + + return true; +} + bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex) { AssertLockHeld(cs_main); @@ -2351,46 +2531,21 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc return true; } + if (!CheckBlockHeader(block, state)) + return false; + // Get prev block index CBlockIndex* pindexPrev = NULL; - int nHeight = 0; if (hash != Params().HashGenesisBlock()) { BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); if (mi == mapBlockIndex.end()) return state.DoS(10, error("%s : prev block not found", __func__), 0, "bad-prevblk"); pindexPrev = (*mi).second; - nHeight = pindexPrev->nHeight+1; - - // Check proof of work - if ((!Params().SkipProofOfWorkCheck()) && - (block.nBits != GetNextWorkRequired(pindexPrev, &block))) - return state.DoS(100, error("%s : incorrect proof of work", __func__), - REJECT_INVALID, "bad-diffbits"); - - // Check timestamp against prev - if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) - return state.Invalid(error("%s : block's timestamp is too early", __func__), - REJECT_INVALID, "time-too-old"); - - // Check that the block chain matches the known block chain up to a checkpoint - if (!Checkpoints::CheckBlock(nHeight, hash)) - return state.DoS(100, error("%s : rejected by checkpoint lock-in at %d", __func__, nHeight), - REJECT_CHECKPOINT, "checkpoint mismatch"); - - // Don't accept any forks from the main chain prior to last checkpoint - CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(); - if (pcheckpoint && nHeight < pcheckpoint->nHeight) - return state.DoS(100, error("%s : forked chain older than last checkpoint (height %d)", __func__, nHeight)); - - // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: - if (block.nVersion < 2 && - CBlockIndex::IsSuperMajority(2, pindexPrev, Params().RejectBlockOutdatedMajority())) - { - return state.Invalid(error("%s : rejected nVersion=1 block", __func__), - REJECT_OBSOLETE, "bad-version"); - } } + if (!ContextualCheckBlockHeader(block, state, pindexPrev)) + return false; + if (pindex == NULL) pindex = AddToBlockIndex(block); @@ -2415,36 +2570,16 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, return true; } - if (!CheckBlock(block, state)) { + if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) { if (state.IsInvalid() && !state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; + setDirtyBlockIndex.insert(pindex); } return false; } int nHeight = pindex->nHeight; - // Check that all transactions are finalized - BOOST_FOREACH(const CTransaction& tx, block.vtx) - if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) { - pindex->nStatus |= BLOCK_FAILED_VALID; - return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"), - REJECT_INVALID, "bad-txns-nonfinal"); - } - - // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height - // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): - if (block.nVersion >= 2 && - CBlockIndex::IsSuperMajority(2, pindex->pprev, Params().EnforceBlockUpgradeMajority())) - { - CScript expect = CScript() << nHeight; - if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || - !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) { - pindex->nStatus |= BLOCK_FAILED_VALID; - return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), REJECT_INVALID, "bad-cb-height"); - } - } - // Write block to history file try { unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); @@ -2555,6 +2690,30 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDis return true; } +bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex * const pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot) +{ + AssertLockHeld(cs_main); + assert(pindexPrev == chainActive.Tip()); + + CCoinsViewCache viewNew(pcoinsTip); + CBlockIndex indexDummy(block); + indexDummy.pprev = pindexPrev; + indexDummy.nHeight = pindexPrev->nHeight + 1; + + // NOTE: CheckBlockHeader is called by CheckBlock + if (!ContextualCheckBlockHeader(block, state, pindexPrev)) + return false; + if (!CheckBlock(block, state, fCheckPOW, fCheckMerkleRoot)) + return false; + if (!ContextualCheckBlock(block, state, pindexPrev)) + return false; + if (!ConnectBlock(block, state, &indexDummy, viewNew, true)) + return false; + assert(state.IsValid()); + + return true; +} + @@ -2602,7 +2761,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve } else { // calculate left hash uint256 left = CalcHash(height-1, pos*2, vTxid), right; - // calculate right hash if not beyong the end of the array - copy left hash otherwise1 + // calculate right hash if not beyond the end of the array - copy left hash otherwise1 if (pos*2+1 < CalcTreeWidth(height-1)) right = CalcHash(height-1, pos*2+1, vTxid); else @@ -2811,7 +2970,7 @@ bool static LoadBlockIndexDB() BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) { CBlockIndex* pindex = item.second; - pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + pindex->GetBlockWork(); + pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex); if (pindex->nStatus & BLOCK_HAVE_DATA) { if (pindex->pprev) { if (pindex->pprev->nChainTx) { @@ -2883,6 +3042,9 @@ bool static LoadBlockIndexDB() if (it == mapBlockIndex.end()) return true; chainActive.SetTip(it->second); + + PruneBlockIndexCandidates(); + LogPrintf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s progress=%f\n", chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), @@ -3023,7 +3185,7 @@ bool InitBlockIndex() { if (!ActivateBestChain(state, &block)) return error("LoadBlockIndex() : genesis block cannot be activated"); // Force a chainstate write so that when we VerifyDB in a moment, it doesnt check stale data - return WriteChainState(state, true); + return FlushStateToDisk(state, FLUSH_STATE_ALWAYS); } catch(std::runtime_error &e) { return error("LoadBlockIndex() : failed to initialize block database: %s", e.what()); } @@ -3034,75 +3196,6 @@ bool InitBlockIndex() { -void PrintBlockTree() -{ - AssertLockHeld(cs_main); - // pre-compute tree structure - map<CBlockIndex*, vector<CBlockIndex*> > mapNext; - for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) - { - CBlockIndex* pindex = (*mi).second; - mapNext[pindex->pprev].push_back(pindex); - // test - //while (rand() % 3 == 0) - // mapNext[pindex->pprev].push_back(pindex); - } - - vector<pair<int, CBlockIndex*> > vStack; - vStack.push_back(make_pair(0, chainActive.Genesis())); - - int nPrevCol = 0; - while (!vStack.empty()) - { - int nCol = vStack.back().first; - CBlockIndex* pindex = vStack.back().second; - vStack.pop_back(); - - // print split or gap - if (nCol > nPrevCol) - { - for (int i = 0; i < nCol-1; i++) - LogPrintf("| "); - LogPrintf("|\\\n"); - } - else if (nCol < nPrevCol) - { - for (int i = 0; i < nCol; i++) - LogPrintf("| "); - LogPrintf("|\n"); - } - nPrevCol = nCol; - - // print columns - for (int i = 0; i < nCol; i++) - LogPrintf("| "); - - // print item - CBlock block; - ReadBlockFromDisk(block, pindex); - LogPrintf("%d (blk%05u.dat:0x%x) %s tx %u\n", - pindex->nHeight, - pindex->GetBlockPos().nFile, pindex->GetBlockPos().nPos, - DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()), - block.vtx.size()); - - // put the main time-chain first - vector<CBlockIndex*>& vNext = mapNext[pindex]; - for (unsigned int i = 0; i < vNext.size(); i++) - { - if (chainActive.Next(vNext[i])) - { - swap(vNext[0], vNext[i]); - break; - } - } - - // iterate children - for (unsigned int i = 0; i < vNext.size(); i++) - vStack.push_back(make_pair(nCol+i, vNext[i])); - } -} - bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) { // Map of disk positions for blocks with unknown parent (only used for reindex) @@ -3216,12 +3309,12 @@ string GetWarnings(string strFor) string strStatusBar; string strRPC; - if (GetBoolArg("-testsafemode", false)) - strRPC = "test"; - if (!CLIENT_VERSION_IS_RELEASE) strStatusBar = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications"); + if (GetBoolArg("-testsafemode", false)) + strStatusBar = strRPC = "testsafemode enabled"; + // Misc warnings like out of disk space and clock is wrong if (strMiscWarning != "") { @@ -3898,7 +3991,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->id, pfrom->cleanSubVer, state.GetRejectReason()); pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), - state.GetRejectReason(), inv.hash); + state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash); if (nDoS > 0) Misbehaving(pfrom->GetId(), nDoS); } @@ -3972,7 +4065,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int nDoS; if (state.IsInvalid(nDoS)) { pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), - state.GetRejectReason(), inv.hash); + state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash); if (nDoS > 0) { LOCK(cs_main); Misbehaving(pfrom->GetId(), nDoS); @@ -4179,7 +4272,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (fDebug) { try { string strMsg; unsigned char ccode; string strReason; - vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, 111); + vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, MAX_REJECT_MESSAGE_LENGTH); ostringstream ss; ss << strMsg << " code " << itostr(ccode) << ": " << strReason; @@ -4594,11 +4687,6 @@ bool CBlockUndo::WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock) hasher << *this; fileout << hasher.GetHash(); - // Flush stdio buffers and commit to disk before returning - fflush(fileout.Get()); - if (!IsInitialBlockDownload()) - FileCommit(fileout.Get()); - return true; } diff --git a/src/main.h b/src/main.h index 1bb0919817..f3d30fafb3 100644 --- a/src/main.h +++ b/src/main.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_MAIN_H @@ -14,8 +14,8 @@ #include "chain.h" #include "chainparams.h" #include "coins.h" -#include "core/block.h" -#include "core/transaction.h" +#include "primitives/block.h" +#include "primitives/transaction.h" #include "net.h" #include "pow.h" #include "script/script.h" @@ -60,7 +60,7 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000; static const unsigned int MAX_STANDARD_TX_SIZE = 100000; /** The maximum allowed number of signature check operations in a block (network rule) */ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; -/** Maxiumum number of signature check operations in an IsStandard() P2SH script */ +/** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; @@ -94,8 +94,12 @@ static const unsigned int MAX_HEADERS_RESULTS = 2000; * degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning * harder). We'll probably want to make this a per-peer adaptive value at some point. */ static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024; +/** Time to wait (in seconds) between writing blockchain state to disk. */ +static const unsigned int DATABASE_WRITE_INTERVAL = 3600; +/** Maximum length of reject messages. */ +static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; -/** "reject" message codes **/ +/** "reject" message codes */ static const unsigned char REJECT_MALFORMED = 0x01; static const unsigned char REJECT_INVALID = 0x10; static const unsigned char REJECT_OBSOLETE = 0x11; @@ -129,10 +133,10 @@ extern bool fIsBareMultisigStd; extern unsigned int nCoinCacheSize; extern CFeeRate minRelayTxFee; -// Best header we've seen so far (used for getheaders queries' starting points). +/** Best header we've seen so far (used for getheaders queries' starting points). */ extern CBlockIndex *pindexBestHeader; -// Minimum disk space required - used in CheckDiskSpace() +/** Minimum disk space required - used in CheckDiskSpace() */ static const uint64_t nMinDiskSpace = 52428800; /** Register a wallet to receive updates from core */ @@ -149,15 +153,17 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals); /** Unregister a network node */ void UnregisterNodeSignals(CNodeSignals& nodeSignals); -/** Process an incoming block. This only returns after the best known valid - block is made active. Note that it does not, however, guarantee that the - specific block passed to it has been checked for validity! - @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state iff pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation. - @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. - @param[in] pblock The block we want to process. - @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. - @return True if state.IsValid() -*/ +/** + * Process an incoming block. This only returns after the best known valid + * block is made active. Note that it does not, however, guarantee that the + * specific block passed to it has been checked for validity! + * + * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation. + * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. + * @param[in] pblock The block we want to process. + * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. + * @return True if state.IsValid() + */ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); @@ -175,8 +181,6 @@ bool InitBlockIndex(); bool LoadBlockIndex(); /** Unload database information */ void UnloadBlockIndex(); -/** Print the loaded block tree */ -void PrintBlockTree(); /** Process protocol messages received from a given node */ bool ProcessMessages(CNode* pfrom); /** Send queued protocol messages to be sent to a give node */ @@ -201,6 +205,8 @@ bool AbortNode(const std::string &msg, const std::string &userMessage=""); bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats); /** Increase a node's misbehavior score. */ void Misbehaving(NodeId nodeid, int howmuch); +/** Flush all state, indexes and buffers to disk. */ +void FlushStateToDisk(); /** (try to) add transaction to memory pool **/ @@ -243,54 +249,59 @@ struct CDiskTxPos : public CDiskBlockPos CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); -// -// Check transaction inputs, and make sure any -// pay-to-script-hash transactions are evaluating IsStandard scripts -// -// Why bother? To avoid denial-of-service attacks; an attacker -// can submit a standard HASH... OP_EQUAL transaction, -// which will get accepted into blocks. The redemption -// script can be anything; an attacker could use a very -// expensive-to-check-upon-redemption script like: -// DUP CHECKSIG DROP ... repeated 100 times... OP_1 -// +/** + * Check transaction inputs, and make sure any + * pay-to-script-hash transactions are evaluating IsStandard scripts + * + * Why bother? To avoid denial-of-service attacks; an attacker + * can submit a standard HASH... OP_EQUAL transaction, + * which will get accepted into blocks. The redemption + * script can be anything; an attacker could use a very + * expensive-to-check-upon-redemption script like: + * DUP CHECKSIG DROP ... repeated 100 times... OP_1 + */ -/** Check for standard transaction types - @param[in] mapInputs Map of previous transactions that have outputs we're spending - @return True if all inputs (scriptSigs) use only standard transaction forms -*/ +/** + * Check for standard transaction types + * @param[in] mapInputs Map of previous transactions that have outputs we're spending + * @return True if all inputs (scriptSigs) use only standard transaction forms + */ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); -/** Count ECDSA signature operations the old-fashioned (pre-0.6) way - @return number of sigops this transaction's outputs will produce when spent - @see CTransaction::FetchInputs -*/ +/** + * Count ECDSA signature operations the old-fashioned (pre-0.6) way + * @return number of sigops this transaction's outputs will produce when spent + * @see CTransaction::FetchInputs + */ unsigned int GetLegacySigOpCount(const CTransaction& tx); -/** Count ECDSA signature operations in pay-to-script-hash inputs. - - @param[in] mapInputs Map of previous transactions that have outputs we're spending - @return maximum number of sigops required to validate this transaction's inputs - @see CTransaction::FetchInputs +/** + * Count ECDSA signature operations in pay-to-script-hash inputs. + * + * @param[in] mapInputs Map of previous transactions that have outputs we're spending + * @return maximum number of sigops required to validate this transaction's inputs + * @see CTransaction::FetchInputs */ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs); -// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) -// This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it -// instead of being performed inline. +/** + * Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) + * This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it + * instead of being performed inline. + */ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL); -// Apply the effects of this transaction on the UTXO set represented by view +/** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight); -// Context-independent validity checks +/** Context-independent validity checks */ bool CheckTransaction(const CTransaction& tx, CValidationState& state); /** Check for standard transaction types - @return True if all outputs (scriptPubKeys) use only standard transaction forms -*/ + * @return True if all outputs (scriptPubKeys) use only standard transaction forms + */ bool IsStandardTx(const CTransaction& tx, std::string& reason); bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0); @@ -313,8 +324,10 @@ public: }; -/** Closure representing one script verification - * Note that this stores references to the spending transaction */ +/** + * Closure representing one script verification + * Note that this stores references to the spending transaction + */ class CScriptCheck { private: @@ -323,14 +336,15 @@ private: unsigned int nIn; unsigned int nFlags; bool cacheStore; + ScriptError error; public: - CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false) {} + CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {} CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) : scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), - ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn) { } + ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { } - bool operator()() const; + bool operator()(); void swap(CScriptCheck &check) { scriptPubKey.swap(check.scriptPubKey); @@ -338,12 +352,15 @@ public: std::swap(nIn, check.nIn); std::swap(nFlags, check.nFlags); std::swap(cacheStore, check.cacheStore); + std::swap(error, check.error); } + + ScriptError GetScriptError() const { return error; } }; /** Data structure that represents a partial merkle tree. * - * It respresents a subset of the txid's of a known block, in a way that + * It represents a subset of the txid's of a known block, in a way that * allows recovery of the list of txid's and the merkle root, in an * authenticated way. * @@ -378,36 +395,38 @@ public: class CPartialMerkleTree { protected: - // the total number of transactions in the block + /** the total number of transactions in the block */ unsigned int nTransactions; - // node-is-parent-of-matched-txid bits + /** node-is-parent-of-matched-txid bits */ std::vector<bool> vBits; - // txids and internal hashes + /** txids and internal hashes */ std::vector<uint256> vHash; - // flag set when encountering invalid data + /** flag set when encountering invalid data */ bool fBad; - // helper function to efficiently calculate the number of nodes at given height in the merkle tree + /** helper function to efficiently calculate the number of nodes at given height in the merkle tree */ unsigned int CalcTreeWidth(int height) { return (nTransactions+(1 << height)-1) >> height; } - // calculate the hash of a node in the merkle tree (at leaf level: the txid's themself) + /** calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves) */ uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid); - // recursive function that traverses tree nodes, storing the data as bits and hashes + /** recursive function that traverses tree nodes, storing the data as bits and hashes */ void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch); - // recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild. - // it returns the hash of the respective node. + /** + * recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild. + * it returns the hash of the respective node. + */ uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch); public: - // serialization implementation + /** serialization implementation */ ADD_SERIALIZE_METHODS; template <typename Stream, typename Operation> @@ -430,13 +449,15 @@ public: } } - // Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them + /** Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them */ CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch); CPartialMerkleTree(); - // extract the matching txid's represented by this partial merkle tree. - // returns the merkle root, or 0 in case of failure + /** + * extract the matching txid's represented by this partial merkle tree. + * returns the merkle root, or 0 in case of failure + */ uint256 ExtractMatches(std::vector<uint256> &vMatch); }; @@ -456,15 +477,21 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex); * of problems. Note that in any case, coins may be modified. */ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL); -// Apply the effects of this block (with given index) on the UTXO set represented by coins -bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); +/** Apply the effects of this block (with given index) on the UTXO set represented by coins */ +bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); -// Context-independent validity checks +/** Context-independent validity checks */ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true); -// Store block on disk -// if dbp is provided, the file is known to already reside on disk +/** Context-dependent validity checks */ +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev); +bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); + +/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ +bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex *pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); + +/** Store block on disk. If dbp is provided, the file is known to already reside on disk */ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL); bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); @@ -473,13 +500,13 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc class CBlockFileInfo { public: - unsigned int nBlocks; // number of blocks stored in file - unsigned int nSize; // number of used bytes of block file - unsigned int nUndoSize; // number of used bytes in the undo file - unsigned int nHeightFirst; // lowest height of block in file - unsigned int nHeightLast; // highest height of block in file - uint64_t nTimeFirst; // earliest time of block in file - uint64_t nTimeLast; // latest time of block in file + unsigned int nBlocks; //! number of blocks stored in file + unsigned int nSize; //! number of used bytes of block file + unsigned int nUndoSize; //! number of used bytes in the undo file + unsigned int nHeightFirst; //! lowest height of block in file + unsigned int nHeightLast; //! highest height of block in file + uint64_t nTimeFirst; //! earliest time of block in file + uint64_t nTimeLast; //! latest time of block in file ADD_SERIALIZE_METHODS; @@ -510,7 +537,7 @@ public: std::string ToString() const; - // update statistics (does not update nSize) + /** update statistics (does not update nSize) */ void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { if (nBlocks==0 || nHeightFirst > nHeightIn) nHeightFirst = nHeightIn; @@ -528,9 +555,9 @@ public: class CValidationState { private: enum mode_state { - MODE_VALID, // everything ok - MODE_INVALID, // network rule violation (DoS value may be set) - MODE_ERROR, // run-time error + MODE_VALID, //! everything ok + MODE_INVALID, //! network rule violation (DoS value may be set) + MODE_ERROR, //! run-time error } mode; int nDoS; std::string strRejectReason; @@ -598,6 +625,12 @@ public: /** Find the last common block between the parameter chain and a locator. */ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); +/** Mark a block as invalid. */ +bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex); + +/** Remove invalidity status from a block and its descendants. */ +bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex); + /** The currently-connected chain of blocks. */ extern CChain chainActive; @@ -619,24 +652,26 @@ struct CBlockTemplate -/** Used to relay blocks as header + vector<merkle branch> +/** + * Used to relay blocks as header + vector<merkle branch> * to filtered nodes. */ class CMerkleBlock { public: - // Public only for unit testing + /** Public only for unit testing */ CBlockHeader header; CPartialMerkleTree txn; public: - // Public only for unit testing and relay testing - // (not relayed) + /** Public only for unit testing and relay testing (not relayed) */ std::vector<std::pair<unsigned int, uint256> > vMatchedTxn; - // Create from a CBlock, filtering transactions according to filter - // Note that this will call IsRelevantAndUpdate on the filter for each transaction, - // thus the filter will likely be modified. + /** + * Create from a CBlock, filtering transactions according to filter + * Note that this will call IsRelevantAndUpdate on the filter for each transaction, + * thus the filter will likely be modified. + */ CMerkleBlock(const CBlock& block, CBloomFilter& filter); ADD_SERIALIZE_METHODS; diff --git a/src/miner.cpp b/src/miner.cpp index b5bfa9c7be..ad29431421 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -6,12 +6,13 @@ #include "miner.h" #include "amount.h" -#include "core/block.h" -#include "core/transaction.h" +#include "primitives/block.h" +#include "primitives/transaction.h" #include "hash.h" #include "main.h" #include "net.h" #include "pow.h" +#include "timedata.h" #include "util.h" #include "utilmoneystr.h" #ifdef ENABLE_WALLET @@ -78,6 +79,15 @@ public: } }; +void UpdateTime(CBlockHeader* pblock, const CBlockIndex* pindexPrev) +{ + pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); + + // Updating time can change work required on testnet: + if (Params().AllowMinDifficultyBlocks()) + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock); +} + CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) { // Create new block @@ -124,6 +134,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) { LOCK2(cs_main, mempool.cs); CBlockIndex* pindexPrev = chainActive.Tip(); + const int nHeight = pindexPrev->nHeight + 1; CCoinsViewCache view(pcoinsTip); // Priority order to process transactions @@ -138,7 +149,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) mi != mempool.mapTx.end(); ++mi) { const CTransaction& tx = mi->second.GetTx(); - if (tx.IsCoinBase() || !IsFinalTx(tx, pindexPrev->nHeight + 1)) + if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight)) continue; COrphan* porphan = NULL; @@ -181,7 +192,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) CAmount nValueIn = coins->vout[txin.prevout.n].nValue; nTotalIn += nValueIn; - int nConf = pindexPrev->nHeight - coins->nHeight + 1; + int nConf = nHeight - coins->nHeight; dPriority += (double)nValueIn * nConf; } @@ -269,7 +280,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) continue; CTxUndo txundo; - UpdateCoins(tx, state, view, txundo, pindexPrev->nHeight+1); + UpdateCoins(tx, state, view, txundo, nHeight); // Added pblock->vtx.push_back(tx); @@ -309,8 +320,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize); // Compute final coinbase transaction. - txNew.vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees); - txNew.vin[0].scriptSig = CScript() << OP_0 << OP_0; + txNew.vout[0].nValue = GetBlockValue(nHeight, nFees); + txNew.vin[0].scriptSig = CScript() << nHeight << OP_0; pblock->vtx[0] = txNew; pblocktemplate->vTxFees[0] = -nFees; @@ -321,13 +332,9 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) pblock->nNonce = 0; pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); - CBlockIndex indexDummy(*pblock); - indexDummy.pprev = pindexPrev; - indexDummy.nHeight = pindexPrev->nHeight + 1; - CCoinsViewCache viewNew(pcoinsTip); CValidationState state; - if (!ConnectBlock(*pblock, state, &indexDummy, viewNew, true)) - throw std::runtime_error("CreateNewBlock() : ConnectBlock failed"); + if (!TestBlockValidity(state, *pblock, pindexPrev, false, false)) + throw std::runtime_error("CreateNewBlock() : TestBlockValidity failed"); } return pblocktemplate.release(); diff --git a/src/miner.h b/src/miner.h index 1fa499dc5b..aede0e6d4b 100644 --- a/src/miner.h +++ b/src/miner.h @@ -9,6 +9,7 @@ #include <stdint.h> class CBlock; +class CBlockHeader; class CBlockIndex; class CReserveKey; class CScript; @@ -25,6 +26,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey); void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); /** Check mined block */ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey); +void UpdateTime(CBlockHeader* block, const CBlockIndex* pindexPrev); extern double dHashesPerSec; extern int64_t nHPSTimerStart; diff --git a/src/net.cpp b/src/net.cpp index a66875a894..8668d5017d 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -12,7 +12,7 @@ #include "addrman.h" #include "chainparams.h" #include "clientversion.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "ui_interface.h" #ifdef WIN32 @@ -1559,7 +1559,7 @@ void static Discover(boost::thread_group& threadGroup) #ifdef WIN32 // Get local host IP - char pszHostName[1000] = ""; + char pszHostName[256] = ""; if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) { vector<CNetAddr> vaddr; @@ -1567,7 +1567,8 @@ void static Discover(boost::thread_group& threadGroup) { BOOST_FOREACH (const CNetAddr &addr, vaddr) { - AddLocal(addr, LOCAL_IF); + if (AddLocal(addr, LOCAL_IF)) + LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToString()); } } } @@ -1587,20 +1588,19 @@ void static Discover(boost::thread_group& threadGroup) struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr); CNetAddr addr(s4->sin_addr); if (AddLocal(addr, LOCAL_IF)) - LogPrintf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString()); + LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, addr.ToString()); } else if (ifa->ifa_addr->sa_family == AF_INET6) { struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr); CNetAddr addr(s6->sin6_addr); if (AddLocal(addr, LOCAL_IF)) - LogPrintf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString()); + LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, addr.ToString()); } } freeifaddrs(myaddrs); } #endif - } void StartNode(boost::thread_group& threadGroup) @@ -44,6 +44,8 @@ static const int PING_INTERVAL = 2 * 60; static const int TIMEOUT_INTERVAL = 20 * 60; /** The maximum number of entries in an 'inv' protocol message */ static const unsigned int MAX_INV_SZ = 50000; +/** The maximum number of new addresses to accumulate before announcing. */ +static const unsigned int MAX_ADDR_TO_SEND = 1000; /** -listen default */ static const bool DEFAULT_LISTEN = true; /** -upnp default */ @@ -368,8 +370,13 @@ public: // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. - if (addr.IsValid() && !setAddrKnown.count(addr)) - vAddrToSend.push_back(addr); + if (addr.IsValid() && !setAddrKnown.count(addr)) { + if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { + vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr; + } else { + vAddrToSend.push_back(addr); + } + } } diff --git a/src/netbase.cpp b/src/netbase.cpp index ea05b8766f..aca5a107fe 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifdef HAVE_CONFIG_H -#include "bitcoin-config.h" +#include "config/bitcoin-config.h" #endif #include "netbase.h" diff --git a/src/pow.cpp b/src/pow.cpp index af7fc488ef..bdcfa852f4 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -5,10 +5,9 @@ #include "pow.h" +#include "chain.h" #include "chainparams.h" -#include "core/block.h" -#include "main.h" -#include "timedata.h" +#include "primitives/block.h" #include "uint256.h" #include "util.h" @@ -98,21 +97,12 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits) return true; } -void UpdateTime(CBlockHeader* pblock, const CBlockIndex* pindexPrev) -{ - pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); - - // Updating time can change work required on testnet: - if (Params().AllowMinDifficultyBlocks()) - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock); -} - -uint256 GetProofIncrement(unsigned int nBits) +uint256 GetBlockProof(const CBlockIndex& block) { uint256 bnTarget; bool fNegative; bool fOverflow; - bnTarget.SetCompact(nBits, &fNegative, &fOverflow); + bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow); if (fNegative || fOverflow || bnTarget == 0) return 0; // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 @@ -16,9 +16,6 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ bool CheckProofOfWork(uint256 hash, unsigned int nBits); - -void UpdateTime(CBlockHeader* block, const CBlockIndex* pindexPrev); - -uint256 GetProofIncrement(unsigned int nBits); +uint256 GetBlockProof(const CBlockIndex& block); #endif // BITCOIN_POW_H diff --git a/src/core/block.cpp b/src/primitives/block.cpp index 2010d44dac..225bb80be8 100644 --- a/src/core/block.cpp +++ b/src/primitives/block.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "core/block.h" +#include "primitives/block.h" #include "hash.h" #include "tinyformat.h" diff --git a/src/core/block.h b/src/primitives/block.h index 6e119c3699..e663c91e84 100644 --- a/src/core/block.h +++ b/src/primitives/block.h @@ -3,10 +3,10 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_CORE_BLOCK_H -#define BITCOIN_CORE_BLOCK_H +#ifndef BITCOIN_PRIMITIVES_BLOCK_H +#define BITCOIN_PRIMITIVES_BLOCK_H -#include "core/transaction.h" +#include "primitives/transaction.h" #include "serialize.h" #include "uint256.h" @@ -165,4 +165,4 @@ struct CBlockLocator } }; -#endif // BITCOIN_CORE_BLOCK_H +#endif // BITCOIN_PRIMITIVES_BLOCK_H diff --git a/src/core/transaction.cpp b/src/primitives/transaction.cpp index f835bafb9f..336151905c 100644 --- a/src/core/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "core/transaction.h" +#include "primitives/transaction.h" #include "hash.h" #include "tinyformat.h" diff --git a/src/core/transaction.h b/src/primitives/transaction.h index 724348020a..a7a1e013ed 100644 --- a/src/core/transaction.h +++ b/src/primitives/transaction.h @@ -3,8 +3,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_CORE_TRANSACTION_H -#define BITCOIN_CORE_TRANSACTION_H +#ifndef BITCOIN_PRIMITIVES_TRANSACTION_H +#define BITCOIN_PRIMITIVES_TRANSACTION_H #include "amount.h" #include "script/script.h" @@ -273,4 +273,4 @@ struct CMutableTransaction uint256 GetHash() const; }; -#endif // BITCOIN_CORE_TRANSACTION_H +#endif // BITCOIN_PRIMITIVES_TRANSACTION_H diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 9c6f536f21..91979ff4dc 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -4,7 +4,6 @@ #include "pubkey.h" -#include "crypto/sha2.h" #include "eccryptoverify.h" #ifdef USE_SECP256K1 diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index a448d5a9a0..fa9ac6b135 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -23,6 +23,10 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : { ui->setupUi(this); + ui->passEdit1->setMinimumSize(ui->passEdit1->sizeHint()); + ui->passEdit2->setMinimumSize(ui->passEdit2->sizeHint()); + ui->passEdit3->setMinimumSize(ui->passEdit3->sizeHint()); + ui->passEdit1->setMaxLength(MAX_PASSPHRASE_SIZE); ui->passEdit2->setMaxLength(MAX_PASSPHRASE_SIZE); ui->passEdit3->setMaxLength(MAX_PASSPHRASE_SIZE); @@ -35,9 +39,9 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : switch(mode) { case Encrypt: // Ask passphrase x2 + ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>.")); ui->passLabel1->hide(); ui->passEdit1->hide(); - ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>.")); setWindowTitle(tr("Encrypt wallet")); break; case Unlock: // Ask passphrase @@ -61,7 +65,6 @@ AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : ui->warningLabel->setText(tr("Enter the old and new passphrase to the wallet.")); break; } - textChanged(); connect(ui->passEdit1, SIGNAL(textChanged(QString)), this, SLOT(textChanged())); connect(ui->passEdit2, SIGNAL(textChanged(QString)), this, SLOT(textChanged())); diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index 2c100337d2..5b8ab23b26 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -221,6 +221,12 @@ void BitcoinAmountField::clear() unit->setCurrentIndex(0); } +void BitcoinAmountField::setEnabled(bool fEnabled) +{ + amount->setEnabled(fEnabled); + unit->setEnabled(fEnabled); +} + bool BitcoinAmountField::validate() { bool valid = false; diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h index 4ab66001f0..1bad8ce1b8 100644 --- a/src/qt/bitcoinamountfield.h +++ b/src/qt/bitcoinamountfield.h @@ -48,6 +48,9 @@ public: /** Make field empty and ready for new input. */ void clear(); + /** Enable/Disable. */ + void setEnabled(bool fEnabled); + /** Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907), in these cases we have to set it up manually. */ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 450b83a8c6..6a457d361f 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -190,7 +190,7 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle *networkStyle, QWidget *parent) : // Progress bar and label for blocks download progressBarLabel = new QLabel(); progressBarLabel->setVisible(false); - progressBar = new QProgressBar(); + progressBar = new GUIUtil::ProgressBar(); progressBar->setAlignment(Qt::AlignCenter); progressBar->setVisible(false); diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp index 1073b6a472..548529865a 100644 --- a/src/qt/bitcoinstrings.cpp +++ b/src/qt/bitcoinstrings.cpp @@ -54,7 +54,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Delete all wallet transactions and only recover those parts of the " "blockchain through -rescan on startup"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Distributed under the MIT/X11 software license, see the accompanying file " +"Distributed under the MIT software license, see the accompanying file " "COPYING or <http://www.opensource.org/licenses/mit-license.php>."), QT_TRANSLATE_NOOP("bitcoin-core", "" "Enter regression test mode, which uses a special chain in which blocks can " @@ -103,6 +103,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Maintain a full transaction index, used by the getrawtransaction rpc call " "(default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" +"Maximum size of data in data carrier transactions we relay and mine " +"(default: %u)"), +QT_TRANSLATE_NOOP("bitcoin-core", "" "Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "Output debugging information (default: %u, supplying <category> is optional)"), @@ -115,8 +118,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "" "Set the number of script verification threads (%u to %d, 0 = auto, <0 = " "leave that many cores free, default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "" -"Set the processor limit for when generation is on (-1 = unlimited, default: " -"%d)"), +"Set the number of threads for coin generation if enabled (-1 = all cores, " +"default: %d)"), QT_TRANSLATE_NOOP("bitcoin-core", "" "This is a pre-release test build - use at your own risk - do not use for " "mining or merchant applications"), @@ -250,6 +253,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."), QT_TRANSLATE_NOOP("bitcoin-core", "Run a thread to flush wallet periodically (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"), QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"), +QT_TRANSLATE_NOOP("bitcoin-core", "Send transactions as zero-fee transactions if possible (default: %u)"), QT_TRANSLATE_NOOP("bitcoin-core", "Server certificate file (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Server private key (default: %s)"), QT_TRANSLATE_NOOP("bitcoin-core", "Set database cache size in megabytes (%d to %d, default: %d)"), diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp index c85f569fd3..5c542b59ae 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -4,7 +4,7 @@ #include "bitcoinunits.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include <QStringList> @@ -106,10 +106,8 @@ QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, Separator QString quotient_str = QString::number(quotient); QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0'); - // Use SI-stule separators as these are locale indendent and can't be - // confused with the decimal marker. Rule is to use a thin space every - // three digits on *both* sides of the decimal point - but only if there - // are five or more digits + // Use SI-style thin space separators as these are locale independent and can't be + // confused with the decimal marker. QChar thin_sp(THIN_SP_CP); int q_size = quotient_str.size(); if (separators == separatorAlways || (separators == separatorStandard && q_size > 4)) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index ba0febe546..85b43b7b1f 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -24,6 +24,7 @@ #include <QDialogButtonBox> #include <QFlags> #include <QIcon> +#include <QSettings> #include <QString> #include <QTreeWidget> #include <QTreeWidgetItem> @@ -130,10 +131,22 @@ CoinControlDialog::CoinControlDialog(QWidget *parent) : // default view is sorted by amount desc sortView(COLUMN_AMOUNT_INT64, Qt::DescendingOrder); + + // restore list mode and sortorder as a convenience feature + QSettings settings; + if (settings.contains("nCoinControlMode") && !settings.value("nCoinControlMode").toBool()) + ui->radioTreeMode->click(); + if (settings.contains("nCoinControlSortColumn") && settings.contains("nCoinControlSortOrder")) + sortView(settings.value("nCoinControlSortColumn").toInt(), ((Qt::SortOrder)settings.value("nCoinControlSortOrder").toInt())); } CoinControlDialog::~CoinControlDialog() { + QSettings settings; + settings.setValue("nCoinControlMode", ui->radioListMode->isChecked()); + settings.setValue("nCoinControlSortColumn", sortColumn); + settings.setValue("nCoinControlSortOrder", (int)sortOrder); + delete ui; } @@ -290,19 +303,19 @@ void CoinControlDialog::clipboardAmount() // copy label "Fee" to clipboard void CoinControlDialog::clipboardFee() { - GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" "))); + GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")).replace("~", "")); } // copy label "After fee" to clipboard void CoinControlDialog::clipboardAfterFee() { - GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" "))); + GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace("~", "")); } // copy label "Bytes" to clipboard void CoinControlDialog::clipboardBytes() { - GUIUtil::setClipboard(ui->labelCoinControlBytes->text()); + GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace("~", "")); } // copy label "Priority" to clipboard @@ -320,7 +333,7 @@ void CoinControlDialog::clipboardLowOutput() // copy label "Change" to clipboard void CoinControlDialog::clipboardChange() { - GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" "))); + GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")).replace("~", "")); } // treeview: sort @@ -402,26 +415,22 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column) } // return human readable label for priority number -QString CoinControlDialog::getPriorityLabel(const CTxMemPool& pool, double dPriority) +QString CoinControlDialog::getPriorityLabel(double dPriority, double mempoolEstimatePriority) { - // confirmations -> textual description - typedef std::map<unsigned int, QString> PriorityDescription; - const static PriorityDescription priorityDescriptions = boost::assign::map_list_of - (1, tr("highest"))(2, tr("higher"))(3, tr("high")) - (5, tr("medium-high"))(6, tr("medium")) - (10, tr("low-medium"))(15, tr("low")) - (20, tr("lower")); - - BOOST_FOREACH(const PriorityDescription::value_type& i, priorityDescriptions) - { - double p = mempool.estimatePriority(i.first); - if (p > 0 && dPriority >= p) return i.second; - } - // Note: if mempool hasn't accumulated enough history (estimatePriority - // returns -1) we're conservative and classify as "lowest" - if (mempool.estimatePriority(nTxConfirmTarget) <= 0 && AllowFree(dPriority)) - return ">=" + tr("medium"); - return tr("lowest"); + double dPriorityMedium = mempoolEstimatePriority; + + if (dPriorityMedium <= 0) + dPriorityMedium = AllowFreeThreshold(); // not enough data, back to hard-coded + + if (dPriority / 1000000 > dPriorityMedium) return tr("highest"); + else if (dPriority / 100000 > dPriorityMedium) return tr("higher"); + else if (dPriority / 10000 > dPriorityMedium) return tr("high"); + else if (dPriority / 1000 > dPriorityMedium) return tr("medium-high"); + else if (dPriority > dPriorityMedium) return tr("medium"); + else if (dPriority * 10 > dPriorityMedium) return tr("low-medium"); + else if (dPriority * 100 > dPriorityMedium) return tr("low"); + else if (dPriority * 1000 > dPriorityMedium) return tr("lower"); + else return tr("lowest"); } // shows count of locked unspent outputs @@ -470,6 +479,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) double dPriorityInputs = 0; unsigned int nQuantity = 0; int nQuantityUncompressed = 0; + bool fAllowFree = false; vector<COutPoint> vCoinControl; vector<COutput> vOutputs; @@ -522,24 +532,22 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here // Priority + double mempoolEstimatePriority = mempool.estimatePriority(nTxConfirmTarget); dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority) - sPriorityLabel = CoinControlDialog::getPriorityLabel(mempool, dPriority); + sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority, mempoolEstimatePriority); - // Voluntary Fee - nPayFee = payTxFee.GetFee(max((unsigned int)1000, nBytes)); + // Fee + nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool); - // Min Fee - if (nPayFee == 0) - { - nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool); - - double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget); - if (dPriorityNeeded <= 0 && !AllowFree(dPriority)) // not enough mempool history: never send free - dPriorityNeeded = std::numeric_limits<double>::max(); + // Allow free? + double dPriorityNeeded = mempoolEstimatePriority; + if (dPriorityNeeded <= 0) + dPriorityNeeded = AllowFreeThreshold(); // not enough data, back to hard-coded + fAllowFree = (dPriority >= dPriorityNeeded); - if (nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE && dPriority >= dPriorityNeeded) + if (fSendFreeTransactions) + if (fAllowFree && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE) nPayFee = 0; - } if (nPayAmount > 0) { @@ -595,7 +603,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) l6->setText(sPriorityLabel); // Priority l7->setText(fDust ? tr("yes") : tr("no")); // Dust l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change - if (nPayFee > 0) + if (nPayFee > 0 && !(payTxFee.GetFeePerK() > 0 && fPayAtLeastCustomFee && nBytes < 1000)) { l3->setText("~" + l3->text()); l4->setText("~" + l4->text()); @@ -605,7 +613,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // turn labels "red" l5->setStyleSheet((nBytes >= MAX_FREE_TRANSACTION_CREATE_SIZE) ? "color:red;" : "");// Bytes >= 1000 - l6->setStyleSheet((dPriority > 0 && !AllowFree(dPriority)) ? "color:red;" : ""); // Priority < "medium" + l6->setStyleSheet((dPriority > 0 && !fAllowFree) ? "color:red;" : ""); // Priority < "medium" l7->setStyleSheet((fDust) ? "color:red;" : ""); // Dust = "yes" // tool tips @@ -620,7 +628,11 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, ::minRelayTxFee.GetFee(546))); // how many satoshis the estimated fee can vary per byte we guess wrong - double dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), std::max(payTxFee.GetFeePerK(), mempool.estimateFee(nTxConfirmTarget).GetFeePerK())) / 1000; + double dFeeVary; + if (payTxFee.GetFeePerK() > 0) + dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000; + else + dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), mempool.estimateFee(nTxConfirmTarget).GetFeePerK()) / 1000; QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary); l3->setToolTip(toolTip4); @@ -656,6 +668,7 @@ void CoinControlDialog::updateView() QFlags<Qt::ItemFlag> flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate; int nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); + double mempoolEstimatePriority = mempool.estimatePriority(nTxConfirmTarget); map<QString, vector<COutput> > mapCoins; model->listCoins(mapCoins); @@ -745,7 +758,7 @@ void CoinControlDialog::updateView() // priority double dPriority = ((double)out.tx->vout[out.i].nValue / (nInputSize + 78)) * (out.nDepth+1); // 78 = 2 * 34 + 10 - itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(mempool, dPriority)); + itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPriority, mempoolEstimatePriority)); itemOutput->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPriority), 20, " ")); dPrioritySum += (double)out.tx->vout[out.i].nValue * (out.nDepth+1); nInputSum += nInputSize; @@ -778,7 +791,7 @@ void CoinControlDialog::updateView() itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")"); itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum)); itemWalletAddress->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(nSum), 15, " ")); - itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(mempool, dPrioritySum)); + itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPrioritySum, mempoolEstimatePriority)); itemWalletAddress->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPrioritySum), 20, " ")); } } diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index cc388d626e..bd4f5d7f1e 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -37,7 +37,7 @@ public: // static because also called from sendcoinsdialog static void updateLabels(WalletModel*, QDialog*); - static QString getPriorityLabel(const CTxMemPool& pool, double); + static QString getPriorityLabel(double dPriority, double mempoolEstimatePriority); static QList<CAmount> payAmounts; static CCoinControl *coinControl; diff --git a/src/qt/forms/askpassphrasedialog.ui b/src/qt/forms/askpassphrasedialog.ui index bc4921455f..a2105ecd0a 100644 --- a/src/qt/forms/askpassphrasedialog.ui +++ b/src/qt/forms/askpassphrasedialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>598</width> - <height>198</height> + <height>222</height> </rect> </property> <property name="sizePolicy"> @@ -26,8 +26,14 @@ <string>Passphrase Dialog</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinimumSize</enum> + </property> <item> <widget class="QLabel" name="warningLabel"> + <property name="text"> + <string notr="true">Placeholder text</string> + </property> <property name="textFormat"> <enum>Qt::RichText</enum> </property> @@ -38,6 +44,9 @@ </item> <item> <layout class="QFormLayout" name="formLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinimumSize</enum> + </property> <property name="fieldGrowthPolicy"> <enum>QFormLayout::AllNonFixedFieldsGrow</enum> </property> diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 9d094c1a73..51156ade4f 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -138,65 +138,6 @@ </attribute> <layout class="QVBoxLayout" name="verticalLayout_Wallet"> <item> - <widget class="QLabel" name="transactionFeeInfoLabel"> - <property name="text"> - <string>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_1_Wallet"> - <item> - <widget class="QLabel" name="transactionFeeLabel"> - <property name="text"> - <string>Pay transaction &fee</string> - </property> - <property name="textFormat"> - <enum>Qt::PlainText</enum> - </property> - <property name="buddy"> - <cstring>transactionFee</cstring> - </property> - </widget> - </item> - <item> - <widget class="BitcoinAmountField" name="transactionFee"/> - </item> - <item> - <spacer name="horizontalSpacer_1_Wallet"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <spacer name="verticalSpacer_Wallet"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item> <widget class="QGroupBox" name="groupBox"> <property name="title"> <string>Expert</string> @@ -225,6 +166,19 @@ </layout> </widget> </item> + <item> + <spacer name="verticalSpacer_Wallet"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> </layout> </widget> <widget class="QWidget" name="tabNetwork"> @@ -255,10 +209,10 @@ <item> <widget class="QCheckBox" name="connectSocks"> <property name="toolTip"> - <string>Connect to the Bitcoin network through a SOCKS proxy.</string> + <string>Connect to the Bitcoin network through a SOCKS5 proxy.</string> </property> <property name="text"> - <string>&Connect through SOCKS proxy (default proxy):</string> + <string>&Connect through SOCKS5 proxy (default proxy):</string> </property> </widget> </item> @@ -633,12 +587,6 @@ </widget> <customwidgets> <customwidget> - <class>BitcoinAmountField</class> - <extends>QLineEdit</extends> - <header>bitcoinamountfield.h</header> - <container>1</container> - </customwidget> - <customwidget> <class>QValidatedLineEdit</class> <extends>QLineEdit</extends> <header>qvalidatedlineedit.h</header> diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index dce7f4ce4c..0bf04c75eb 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -7,13 +7,13 @@ <x>0</x> <y>0</y> <width>850</width> - <height>400</height> + <height>526</height> </rect> </property> <property name="windowTitle"> <string>Send Coins</string> </property> - <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0"> + <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0,0"> <property name="bottomMargin"> <number>8</number> </property> @@ -617,7 +617,7 @@ <x>0</x> <y>0</y> <width>830</width> - <height>178</height> + <height>68</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1"> @@ -658,6 +658,590 @@ </widget> </item> <item> + <widget class="QFrame" name="frameFee"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayoutFee1"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QVBoxLayout" name="verticalLayoutFee2" stretch="0,0,0"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>10</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayoutFee1"> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QVBoxLayout" name="verticalLayoutFee7"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <spacer name="verticalSpacerSmartFee"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>4</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayoutSmartFee"> + <property name="spacing"> + <number>10</number> + </property> + <item> + <widget class="QLabel" name="labelFeeHeadline"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="styleSheet"> + <string notr="true">font-weight:bold;</string> + </property> + <property name="text"> + <string>Transaction Fee:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="labelFeeMinimized"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="buttonChooseFee"> + <property name="text"> + <string>Choose...</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="buttonMinimizeFee"> + <property name="toolTip"> + <string>collapse fee-settings</string> + </property> + <property name="text"> + <string>Minimize</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_5"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QFrame" name="frameFeeSelection"> + <layout class="QVBoxLayout" name="verticalLayoutFee12"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QGridLayout" name="gridLayoutFee"> + <property name="topMargin"> + <number>10</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <property name="horizontalSpacing"> + <number>10</number> + </property> + <property name="verticalSpacing"> + <number>4</number> + </property> + <item row="1" column="1"> + <layout class="QVBoxLayout" name="verticalLayoutFee8"> + <property name="spacing"> + <number>6</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayoutFee13"> + <item> + <widget class="QRadioButton" name="radioCustomPerKilobyte"> + <property name="toolTip"> + <string>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</string> + </property> + <property name="text"> + <string>per kilobyte</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <attribute name="buttonGroup"> + <string notr="true">groupCustomFee</string> + </attribute> + </widget> + </item> + <item> + <widget class="QRadioButton" name="radioCustomAtLeast"> + <property name="toolTip"> + <string>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</string> + </property> + <property name="text"> + <string>total at least</string> + </property> + <attribute name="buttonGroup"> + <string notr="true">groupCustomFee</string> + </attribute> + </widget> + </item> + <item> + <widget class="BitcoinAmountField" name="customFee"/> + </item> + <item> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayoutFee8"> + <item> + <widget class="QCheckBox" name="checkBoxMinimumFee"> + <property name="toolTip"> + <string>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="labelMinFeeWarning"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="toolTip"> + <string>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</string> + </property> + <property name="text"> + <string>(read the tooltip)</string> + </property> + <property name="margin"> + <number>5</number> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + <item row="0" column="0"> + <layout class="QVBoxLayout" name="verticalLayoutFee4" stretch="0,1"> + <item> + <widget class="QRadioButton" name="radioSmartFee"> + <property name="text"> + <string>Recommended:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <attribute name="buttonGroup"> + <string notr="true">groupFee</string> + </attribute> + </widget> + </item> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="0"> + <layout class="QVBoxLayout" name="verticalLayoutFee9" stretch="0,1"> + <item> + <widget class="QRadioButton" name="radioCustomFee"> + <property name="text"> + <string>Custom:</string> + </property> + <attribute name="buttonGroup"> + <string notr="true">groupFee</string> + </attribute> + </widget> + </item> + <item> + <spacer name="verticalSpacer_6"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="0" column="1"> + <layout class="QVBoxLayout" name="verticalLayoutFee3" stretch="0,0,1"> + <property name="spacing"> + <number>6</number> + </property> + <property name="topMargin"> + <number>2</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayoutFee12"> + <item> + <widget class="QLabel" name="labelSmartFee"> + <property name="text"> + <string/> + </property> + <property name="margin"> + <number>2</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="labelFeeEstimation"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="labelSmartFee2"> + <property name="text"> + <string>(Smart fee not initialized yet. This usually takes a few blocks...)</string> + </property> + <property name="margin"> + <number>2</number> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayoutFee9"> + <item> + <layout class="QVBoxLayout" name="verticalLayoutFee6"> + <item> + <widget class="QLabel" name="labelSmartFee3"> + <property name="text"> + <string>Confirmation time:</string> + </property> + <property name="margin"> + <number>2</number> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayoutFee5"> + <property name="rightMargin"> + <number>30</number> + </property> + <item> + <widget class="QSlider" name="sliderSmartFee"> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>24</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="value"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="invertedAppearance"> + <bool>false</bool> + </property> + <property name="invertedControls"> + <bool>false</bool> + </property> + <property name="tickPosition"> + <enum>QSlider::NoTicks</enum> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayoutFee10"> + <item> + <widget class="QLabel" name="labelSmartFeeNormal"> + <property name="text"> + <string>normal</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="labelSmartFeeFast"> + <property name="text"> + <string>fast</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_4"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayoutFee5" stretch="0,0,0"> + <property name="spacing"> + <number>8</number> + </property> + <property name="bottomMargin"> + <number>4</number> + </property> + <item> + <widget class="QCheckBox" name="checkBoxFreeTx"> + <property name="text"> + <string>Send as zero-fee transaction if possible</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="labelFreeTx"> + <property name="text"> + <string>(confirmation may take longer)</string> + </property> + <property name="margin"> + <number>5</number> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacerFee5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacerFee2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>1</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacerFee"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>800</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QPushButton" name="sendButton"> @@ -787,9 +1371,19 @@ <extends>QLineEdit</extends> <header>qvalidatedlineedit.h</header> </customwidget> + <customwidget> + <class>BitcoinAmountField</class> + <extends>QLineEdit</extends> + <header>bitcoinamountfield.h</header> + <container>1</container> + </customwidget> </customwidgets> <resources> <include location="../bitcoin.qrc"/> </resources> <connections/> + <buttongroups> + <buttongroup name="groupFee"/> + <buttongroup name="groupCustomFee"/> + </buttongroups> </ui> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 22a1f019e9..a1ae756c43 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -9,7 +9,7 @@ #include "qvalidatedlineedit.h" #include "walletmodel.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "init.h" #include "main.h" #include "protocol.h" diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 5666744bd3..09c79db2d9 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -7,9 +7,11 @@ #include "amount.h" +#include <QEvent> #include <QHeaderView> #include <QMessageBox> #include <QObject> +#include <QProgressBar> #include <QString> #include <QTableView> @@ -186,6 +188,21 @@ namespace GUIUtil /* Format a CNodeCombinedStats.dPingTime into a user-readable string or display N/A, if 0*/ QString formatPingTime(double dPingTime); + +#if defined(Q_OS_MAC) && QT_VERSION >= 0x050000 + // workaround for Qt OSX Bug: + // https://bugreports.qt-project.org/browse/QTBUG-15631 + // QProgressBar uses around 10% CPU even when app is in background + class ProgressBar : public QProgressBar + { + bool event(QEvent *e) { + return (e->type() != QEvent::StyleAnimationUpdate) ? QProgressBar::event(e) : false; + } + }; +#else + typedef QProgressBar ProgressBar; +#endif + } // namespace GUIUtil #endif // BITCOIN_QT_GUIUTIL_H diff --git a/src/qt/locale/bitcoin_ach.ts b/src/qt/locale/bitcoin_ach.ts index 835ddb8eaa..ddb9fb85ce 100644 --- a/src/qt/locale/bitcoin_ach.ts +++ b/src/qt/locale/bitcoin_ach.ts @@ -1,4 +1,4 @@ -<TS language="ach" version="2.1"> +<TS language="ach" version="2.0"> <context> <name>AddressBookPage</name> </context> diff --git a/src/qt/locale/bitcoin_af_ZA.ts b/src/qt/locale/bitcoin_af_ZA.ts index 851c261d0b..c369c3c68f 100644 --- a/src/qt/locale/bitcoin_af_ZA.ts +++ b/src/qt/locale/bitcoin_af_ZA.ts @@ -1,4 +1,4 @@ -<TS language="af_ZA" version="2.1"> +<TS language="af_ZA" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -201,10 +201,6 @@ <translation>Bedrag</translation> </message> <message> - <source>Address</source> - <translation>Adres</translation> - </message> - <message> <source>Date</source> <translation>Datum</translation> </message> diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts index f05270a9fa..101f51f8dc 100644 --- a/src/qt/locale/bitcoin_ar.ts +++ b/src/qt/locale/bitcoin_ar.ts @@ -1,4 +1,4 @@ -<TS language="ar" version="2.1"> +<TS language="ar" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -457,10 +457,6 @@ <translation>المبلغ</translation> </message> <message> - <source>Address</source> - <translation>عنوان</translation> - </message> - <message> <source>Date</source> <translation>التاريخ</translation> </message> @@ -525,6 +521,10 @@ <translation>عالي</translation> </message> <message> + <source>medium-high</source> + <translation>متوسط-مرتفع</translation> + </message> + <message> <source>low</source> <translation>منخفض</translation> </message> @@ -683,10 +683,6 @@ <translation>&الرئيسي</translation> </message> <message> - <source>Pay transaction &fee</source> - <translation>ادفع &رسوم المعاملة</translation> - </message> - <message> <source>MB</source> <translation>م ب</translation> </message> diff --git a/src/qt/locale/bitcoin_be_BY.ts b/src/qt/locale/bitcoin_be_BY.ts index f4b82ce2cc..e63628396c 100644 --- a/src/qt/locale/bitcoin_be_BY.ts +++ b/src/qt/locale/bitcoin_be_BY.ts @@ -1,4 +1,4 @@ -<TS language="be_BY" version="2.1"> +<TS language="be_BY" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -353,10 +353,6 @@ Address: %4 <translation>Колькасць</translation> </message> <message> - <source>Address</source> - <translation>Адрас</translation> - </message> - <message> <source>Date</source> <translation>Дата</translation> </message> diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts index a1f3dd092a..3095aa1172 100644 --- a/src/qt/locale/bitcoin_bg.ts +++ b/src/qt/locale/bitcoin_bg.ts @@ -1,4 +1,4 @@ -<TS language="bg" version="2.1"> +<TS language="bg" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -365,10 +365,6 @@ <translation>Сума</translation> </message> <message> - <source>Address</source> - <translation>Адрес</translation> - </message> - <message> <source>Date</source> <translation>Дата</translation> </message> @@ -511,10 +507,6 @@ <translation>&Основни</translation> </message> <message> - <source>Pay transaction &fee</source> - <translation>&Такса за изходяща трансакция</translation> - </message> - <message> <source>&Start Bitcoin on system login</source> <translation>&Пускане на Биткоин при вход в системата</translation> </message> diff --git a/src/qt/locale/bitcoin_bs.ts b/src/qt/locale/bitcoin_bs.ts index fc5e6d270e..86526022fe 100644 --- a/src/qt/locale/bitcoin_bs.ts +++ b/src/qt/locale/bitcoin_bs.ts @@ -1,4 +1,4 @@ -<TS language="bs" version="2.1"> +<TS language="bs" version="2.0"> <context> <name>AddressBookPage</name> </context> diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts index 1e19a3ff18..8f06ac3aa7 100644 --- a/src/qt/locale/bitcoin_ca.ts +++ b/src/qt/locale/bitcoin_ca.ts @@ -1,4 +1,4 @@ -<TS language="ca" version="2.1"> +<TS language="ca" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -517,10 +517,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Selecció de l'adreça de control de monedes</translation> - </message> - <message> <source>Quantity:</source> <translation>Quantitat:</translation> </message> @@ -569,10 +565,6 @@ Address: %4 <translation>Quantitat</translation> </message> <message> - <source>Address</source> - <translation>Adreça</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> @@ -939,14 +931,6 @@ Address: %4 <translation>&Principal</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Comissió opcional de transacció per kB que ajuda a assegurar que les transaccions es processen ràpidament. La majoria de transaccions són d'1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Paga &comissió de transacció</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Inicia automàticament el Bitcoin després de l'inici de sessió del sistema.</translation> </message> @@ -975,14 +959,6 @@ Address: %4 <translation>Permet connexions entrants</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Connecta a la xarxa Bitcoin a través d'un proxy SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Connecta a través d'un proxy SOCKS (proxy per defecte):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Adreça IP del proxy (p. ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -2930,10 +2906,6 @@ per exemple: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Distribuït sota la llicència de programari MIT/X11. Vegeu el fitxer acompanyant COPYING o <http://www.opensource.org/licenses/mit-license.php>.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation> </message> diff --git a/src/qt/locale/bitcoin_ca@valencia.ts b/src/qt/locale/bitcoin_ca@valencia.ts index 9d49da2dbd..d3bf33ebfb 100644 --- a/src/qt/locale/bitcoin_ca@valencia.ts +++ b/src/qt/locale/bitcoin_ca@valencia.ts @@ -1,4 +1,4 @@ -<TS language="ca@valencia" version="2.1"> +<TS language="ca@valencia" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -497,10 +497,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Selecció de l'adreça de control de monedes</translation> - </message> - <message> <source>Quantity:</source> <translation>Quantitat:</translation> </message> @@ -549,10 +545,6 @@ Address: %4 <translation>Quantitat</translation> </message> <message> - <source>Address</source> - <translation>Adreça</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> @@ -919,14 +911,6 @@ Address: %4 <translation>&Principal</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Comissió opcional de transacció per kB que ajuda a assegurar que les transaccions es processen ràpidament. La majoria de transaccions són d'1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Paga &comissió de transacció</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Inicia automàticament el Bitcoin després de l'inici de sessió del sistema.</translation> </message> @@ -955,14 +939,6 @@ Address: %4 <translation>Permet connexions entrants</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Connecta a la xarxa Bitcoin a través d'un proxy SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Connecta a través d'un proxy SOCKS (proxy per defecte):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Adreça IP del proxy (p. ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -2894,10 +2870,6 @@ per exemple: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Distribuït sota la llicència de programari MIT/X11. Vegeu el fitxer acompanyant COPYING o <http://www.opensource.org/licenses/mit-license.php>.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation> </message> diff --git a/src/qt/locale/bitcoin_ca_ES.ts b/src/qt/locale/bitcoin_ca_ES.ts index 5fa69e798d..60c6fa30f4 100644 --- a/src/qt/locale/bitcoin_ca_ES.ts +++ b/src/qt/locale/bitcoin_ca_ES.ts @@ -1,4 +1,4 @@ -<TS language="ca_ES" version="2.1"> +<TS language="ca_ES" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -517,10 +517,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Selecció de l'adreça de control de monedes</translation> - </message> - <message> <source>Quantity:</source> <translation>Quantitat:</translation> </message> @@ -569,10 +565,6 @@ Address: %4 <translation>Quantitat</translation> </message> <message> - <source>Address</source> - <translation>Adreça</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> @@ -939,14 +931,6 @@ Address: %4 <translation>&Principal</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Comissió opcional de transacció per kB que ajuda a assegurar que les transaccions es processen ràpidament. La majoria de transaccions són d'1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Paga &comissió de transacció</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Inicia automàticament el Bitcoin després de l'inici de sessió del sistema.</translation> </message> @@ -975,14 +959,6 @@ Address: %4 <translation>Permet connexions entrants</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Connecta a la xarxa Bitcoin a través d'un proxy SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Connecta a través d'un proxy SOCKS (proxy per defecte):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Adreça IP del proxy (p. ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -2930,10 +2906,6 @@ per exemple: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Crea fitxers nous amb els permisos per defecte del sistema, en comptes de l'umask 077 (només efectiu amb la funcionalitat de moneder inhabilitada)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Distribuït sota la llicència de programari MIT/X11. Vegeu el fitxer acompanyant COPYING o <http://www.opensource.org/licenses/mit-license.php>.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation> </message> diff --git a/src/qt/locale/bitcoin_cmn.ts b/src/qt/locale/bitcoin_cmn.ts index 3286f12698..09ff0acf02 100644 --- a/src/qt/locale/bitcoin_cmn.ts +++ b/src/qt/locale/bitcoin_cmn.ts @@ -1,4 +1,4 @@ -<TS language="cmn" version="2.1"> +<TS language="cmn" version="2.0"> <context> <name>AddressBookPage</name> </context> diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts index 44fda5afed..bc2a2ef7b5 100644 --- a/src/qt/locale/bitcoin_cs.ts +++ b/src/qt/locale/bitcoin_cs.ts @@ -1,4 +1,4 @@ -<TS language="cs" version="2.1"> +<TS language="cs" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -505,10 +505,6 @@ Adresa: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Volba adres v rámci ruční správy mincí</translation> - </message> - <message> <source>Quantity:</source> <translation>Počet:</translation> </message> @@ -557,10 +553,6 @@ Adresa: %4 <translation>Částka</translation> </message> <message> - <source>Address</source> - <translation>Adresa</translation> - </message> - <message> <source>Date</source> <translation>Datum</translation> </message> @@ -927,14 +919,6 @@ Adresa: %4 <translation>&Hlavní</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Dobrovolný transakční poplatek za každý započatý kB dopomáhá k rychlému zpracování tvých transakcí. Většina transakcí má do 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Platit &transakční poplatek</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Automaticky spustí Bitcoin po přihlášení do systému.</translation> </message> @@ -963,14 +947,6 @@ Adresa: %4 <translation>Přijímat příchozí spojení</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Připojí se do Bitcoinové sítě přes SOCKS proxy.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Připojit přes SOCKS proxy (výchozí proxy):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>IP adresa proxy (např. IPv4: 127.0.0.1/IPv6: ::1)</translation> </message> @@ -2919,10 +2895,6 @@ například: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Vytvářet nové soubory s výchozími systémovými právy namísto umask 077 (uplatní se, pouze pokud je vypnutá funkce peněženky)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Šířen pod licencí MIT/X11, viz přiložený soubor COPYING nebo <http://www.opensource.org/licenses/mit-license.php>.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>Chyba: Nelze naslouchat příchozí spojení (listen vrátil chybu %s)</translation> </message> diff --git a/src/qt/locale/bitcoin_cy.ts b/src/qt/locale/bitcoin_cy.ts index cf82f2be27..c68fc274f3 100644 --- a/src/qt/locale/bitcoin_cy.ts +++ b/src/qt/locale/bitcoin_cy.ts @@ -1,4 +1,4 @@ -<TS language="cy" version="2.1"> +<TS language="cy" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -197,10 +197,6 @@ <context> <name>CoinControlDialog</name> <message> - <source>Address</source> - <translation>Cyfeiriad</translation> - </message> - <message> <source>Date</source> <translation>Dyddiad</translation> </message> diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts index 05ee62e020..f733591098 100644 --- a/src/qt/locale/bitcoin_da.ts +++ b/src/qt/locale/bitcoin_da.ts @@ -1,4 +1,4 @@ -<TS language="da" version="2.1"> +<TS language="da" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -525,8 +525,8 @@ Adresse: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Adressevalg for coin-styring</translation> + <source>Coin Selection</source> + <translation>Coin-styring</translation> </message> <message> <source>Quantity:</source> @@ -577,8 +577,12 @@ Adresse: %4 <translation>Beløb</translation> </message> <message> - <source>Address</source> - <translation>Adresse</translation> + <source>Received with label</source> + <translation>Modtaget med mærke</translation> + </message> + <message> + <source>Received with address</source> + <translation>Modtaget med adresse</translation> </message> <message> <source>Date</source> @@ -951,14 +955,6 @@ Adresse: %4 <translation>&Generelt</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Valgfrit transaktionsgebyr pr. kB, der hjælper dine transaktioner med at blive behandlet hurtigt. De fleste transaktioner er på 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Betal transaktions&gebyr</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Start Bitcoin automatisk, når der logges ind på systemet.</translation> </message> @@ -987,14 +983,6 @@ Adresse: %4 <translation>Tillad indkommende forbindelser</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Forbind til Bitcoin-netværket gennem en SOCKS-proxy.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Forbind gennem SOCKS-proxy (standard-proxy):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>IP-adresse for proxyen (fx IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1055,6 +1043,14 @@ Adresse: %4 <translation>Konfigurér port vha. &UPnP</translation> </message> <message> + <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> + <translation>Forbind til Bitcoin-netværket gennem en SOCKS5-proxy.</translation> + </message> + <message> + <source>&Connect through SOCKS5 proxy (default proxy):</source> + <translation>&Forbind gennem SOCKS5-proxy (standard-proxy):</translation> + </message> + <message> <source>Proxy &IP:</source> <translation>Proxy-&IP:</translation> </message> @@ -1845,6 +1841,78 @@ Adresse: %4 <translation>Tilpasset byttepengeadresse</translation> </message> <message> + <source>Transaction Fee:</source> + <translation>Transaktionsgebyr:</translation> + </message> + <message> + <source>Choose...</source> + <translation>Vælg …</translation> + </message> + <message> + <source>collapse fee-settings</source> + <translation>sammenfold gebyropsætning</translation> + </message> + <message> + <source>Minimize</source> + <translation>Minimér</translation> + </message> + <message> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation>Hvis det brugertilpassede gebyr er sat til 1000 satoshis, og transaktionen kun fylder 250 byte, betaler "pr. kilobyte" kun 250 satoshis i gebyr, mens "mindst" betaler 1000 satoshis. For transaktioner større end en kilobyte betaler begge pr. kilobyte.</translation> + </message> + <message> + <source>per kilobyte</source> + <translation>pr. kilobyte</translation> + </message> + <message> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation>Hvis det brugertilpassede gebyr er sat til 1000 satoshis, og transaktionen kun fylder 250 byte, betaler "pr. kilobyte" kun 250 satoshis i gebyr, mens "total mindst" betaler 1000 satoshis. For transaktioner større end en kilobyte betaler begge pr. kilobyte.</translation> + </message> + <message> + <source>total at least</source> + <translation>total mindst</translation> + </message> + <message> + <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> + <translation>Det er helt fint kun at betale det minimale gebyr, så længe den totale transaktionsvolumen er mindre end den plads, der er tilgængelig i blokkene. Men vær opmærksom på, at dette kan ende ud i transaktioner, der aldrig bliver bekræftet, når der bliver større forespørgsel efter bitcoin-transaktioner, end hvad netværket kan bearbejde.</translation> + </message> + <message> + <source>(read the tooltip)</source> + <translation>(læs værktøjstippet)</translation> + </message> + <message> + <source>Recommended:</source> + <translation>Anbefalet:</translation> + </message> + <message> + <source>Custom:</source> + <translation>Brugertilpasset:</translation> + </message> + <message> + <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source> + <translation>(Smart-gebyr er ikke initialiseret endnu. Dette tager typisk nogle få blokke …)</translation> + </message> + <message> + <source>Confirmation time:</source> + <translation>Bekræftelsestid:</translation> + </message> + <message> + <source>normal</source> + <translation>normal</translation> + </message> + <message> + <source>fast</source> + <translation>hurtig</translation> + </message> + <message> + <source>Send as zero-fee transaction if possible</source> + <translation>Send som nul-gebyr-transaktion hvis muligt</translation> + </message> + <message> + <source>(confirmation may take longer)</source> + <translation>(bekræftelse kan tage længere)</translation> + </message> + <message> <source>Send to multiple recipients at once</source> <translation>Send til flere modtagere på en gang</translation> </message> @@ -1949,6 +2017,18 @@ Adresse: %4 <translation>Transaktionen blev afvist! Dette kan ske, hvis nogle af dine bitcoins i din tegnebog allerede er brugt, som hvis du brugte en kopi af wallet.dat og dine bitcoins er blevet brugt i kopien, men ikke er markeret som brugt her.</translation> </message> <message> + <source>A fee higher than %1 is considered an insanely high fee.</source> + <translation>Et gebyr højere end %1 anses som et vanvittigt højt gebyr.</translation> + </message> + <message> + <source>Pay only the minimum fee of %1</source> + <translation>Betal kun det minimale gebyr på %1</translation> + </message> + <message> + <source>Estimated to begin confirmation within %1 block(s).</source> + <translation>Bekræftelse vurderes at begynde inden for %1 blok(ke).</translation> + </message> + <message> <source>Warning: Invalid Bitcoin address</source> <translation>Advarsel: Ugyldig Bitcoin-adresse</translation> </message> @@ -2755,6 +2835,10 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Slet alle transaktioner i tegnebogen og genskab kun disse dele af blokkæden gennem -rescan under opstart</translation> </message> <message> + <source>Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> + <translation>Distribueret under MIT-softwarelicensen; se den vedlagte fil COPYING eller <http://www.opensource.org/licenses/mit-license.php>.</translation> + </message> + <message> <source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly.</source> <translation>Start regressionstesttilstand, som bruger en speciel kæde, hvor blokke kan løses med det samme.</translation> </message> @@ -2987,10 +3071,6 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Opret nye filer med systemstandard for rettigheder i stedet for umask 077 (kun virksomt med tegnebogsfunktionalitet slået fra)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Distribueret under MIT/X11-softwarelicensen. Se medfølgende fil COPYING eller <http://www.opensource.org/licenses/mit-license.php>.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>Fejl: Lytning efter indkommende forbindelser mislykkedes (lytning resultarede i fejl %s)</translation> </message> @@ -3011,6 +3091,10 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Gebyrer (i BTC/Kb) mindre end dette opfattes som nulgebyr for oprettelse af transaktion (standard: %s)</translation> </message> <message> + <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source> + <translation>Maksimal størrelse på data i transaktioner til dataoverførsel, som vi videresender og miner (standard: %u)</translation> + </message> + <message> <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source> <translation>Forespørgsel</translation> </message> @@ -3019,6 +3103,10 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Sæt maksimumstørrelse for højprioritet/lavgebyr-transaktioner i byte (standard: %d)</translation> </message> <message> + <source>Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)</source> + <translation>Sæt antaller af tråde for coin-generering, hvis aktiveret (-1 = alle kerner, standard: %d)</translation> + </message> + <message> <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source> <translation>Dette produkt indeholder software, der er udviklet af OpenSSL-projektet for brug i OpenSSL-værktøjskassen <https://www.openssl.org/>, samt kryptografisk software, der er skrevet af Eric Young, samt UPnP-software, der er skrevet af Thomas Bernard.</translation> </message> @@ -3123,6 +3211,10 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Send sporings-/fejlsøgningsinformation til konsollen i stedet for debug.log filen</translation> </message> <message> + <source>Send transactions as zero-fee transactions if possible (default: %u)</source> + <translation>Send transaktioner som nul-gebyr-transaktioner hvis muligt (standard: %u)</translation> + </message> + <message> <source>Show all debugging options (usage: --help -help-debug)</source> <translation>Vis alle tilvalg for fejlsøgning (brug: --help -help-debug)</translation> </message> @@ -3263,10 +3355,6 @@ fx: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Udskriv fejlsøgningsinformation (standard: %u, angivelse af <kategori> er valgfri)</translation> </message> <message> - <source>Set the processor limit for when generation is on (-1 = unlimited, default: %d)</source> - <translation>Sæt processorbegrænsning for når generering er slået til (-1 = ubegrænset, standard: %d)</translation> - </message> - <message> <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> <translation>Brug separat SOCS5-proxy for at nå andre knuder via Tor skjulte tjenester (standard: %s)</translation> </message> diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts index 8bc1c046a1..9462f668d3 100644 --- a/src/qt/locale/bitcoin_de.ts +++ b/src/qt/locale/bitcoin_de.ts @@ -1,4 +1,4 @@ -<TS language="de" version="2.1"> +<TS language="de" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -520,8 +520,8 @@ Adresse: %4</translation> <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>"Coin Control"-Adressauswahl</translation> + <source>Coin Selection</source> + <translation>Münzauswahl ("Coin Control")</translation> </message> <message> <source>Quantity:</source> @@ -572,8 +572,12 @@ Adresse: %4</translation> <translation>Betrag</translation> </message> <message> - <source>Address</source> - <translation>Adresse</translation> + <source>Received with label</source> + <translation>Empfangen über Bezeichnung</translation> + </message> + <message> + <source>Received with address</source> + <translation>Empfangen über Adresse</translation> </message> <message> <source>Date</source> @@ -950,14 +954,6 @@ Adresse: %4</translation> <translation>&Allgemein</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Optionale Transaktionsgebühr pro kB, die sicherstellt, dass Ihre Transaktionen schnell bearbeitet werden. Die meisten Transaktionen sind 1 kB groß.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Transaktions&gebühr bezahlen</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Bitcoin nach der Anmeldung am System automatisch ausführen.</translation> </message> @@ -986,14 +982,6 @@ Adresse: %4</translation> <translation>Erlaubt eingehende Verbindungen</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Über einen SOCKS-Proxy mit dem Bitcoin-Netzwerk verbinden.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>Über einen SOCKS-Proxy &verbinden (Standardproxy):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>IP-Adresse des Proxies (z.B. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1054,6 +1042,14 @@ Adresse: %4</translation> <translation>Portweiterleitung via &UPnP</translation> </message> <message> + <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> + <translation>Über einen SOCKS5-Proxy mit dem Bitcoin-Netzwerk verbinden.</translation> + </message> + <message> + <source>&Connect through SOCKS5 proxy (default proxy):</source> + <translation>Über einen SOCKS5-Proxy &verbinden (Standardproxy):</translation> + </message> + <message> <source>Proxy &IP:</source> <translation>Proxy-&IP:</translation> </message> @@ -1844,6 +1840,66 @@ Adresse: %4</translation> <translation>Benutzerdefinierte Wechselgeld-Adresse</translation> </message> <message> + <source>Transaction Fee:</source> + <translation>Transaktionsgebühr:</translation> + </message> + <message> + <source>Choose...</source> + <translation>Auswählen...</translation> + </message> + <message> + <source>collapse fee-settings</source> + <translation>Transaktionsgebühreneinstellungen ausblenden</translation> + </message> + <message> + <source>Minimize</source> + <translation>Minimieren</translation> + </message> + <message> + <source>per kilobyte</source> + <translation>pro Kilobyte</translation> + </message> + <message> + <source>total at least</source> + <translation>Mindestbetrag</translation> + </message> + <message> + <source>(read the tooltip)</source> + <translation>(den Hinweistext lesen)</translation> + </message> + <message> + <source>Recommended:</source> + <translation>Empfehlungen:</translation> + </message> + <message> + <source>Custom:</source> + <translation>Benutzerdefiniert:</translation> + </message> + <message> + <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source> + <translation>(Intelligente Gebührenlogik ist noch nicht verfügbar. Normalerweise dauert dies einige Blöcke lang...)</translation> + </message> + <message> + <source>Confirmation time:</source> + <translation>Bestätigungszeit:</translation> + </message> + <message> + <source>normal</source> + <translation>normal</translation> + </message> + <message> + <source>fast</source> + <translation>schnell</translation> + </message> + <message> + <source>Send as zero-fee transaction if possible</source> + <translation>Wenn möglich als gebührenfreie Transaktion senden</translation> + </message> + <message> + <source>(confirmation may take longer)</source> + <translation>(Bestätigung kann länger dauern)</translation> + </message> + <message> <source>Send to multiple recipients at once</source> <translation>An mehrere Empfänger auf einmal überweisen</translation> </message> @@ -1948,6 +2004,18 @@ Adresse: %4</translation> <translation>Die Transaktion wurde abgelehnt! Dies kann passieren, wenn einige Bitcoins aus Ihrer Wallet bereits ausgegeben wurden. Beispielsweise weil Sie eine Kopie Ihrer wallet.dat genutzt, die Bitcoins dort ausgegeben haben und dies daher in der derzeit aktiven Wallet nicht vermerkt ist.</translation> </message> <message> + <source>A fee higher than %1 is considered an insanely high fee.</source> + <translation>Eine höhere Gebühr als %1 wird als unsinnig hohe Gebühr angesehen.</translation> + </message> + <message> + <source>Pay only the minimum fee of %1</source> + <translation>Nur die minimale Gebühr in Höhe von %1 zahlen</translation> + </message> + <message> + <source>Estimated to begin confirmation within %1 block(s).</source> + <translation>Voraussichtlicher Beginn der Bestätigung innerhalb von %1 Blöcken.</translation> + </message> + <message> <source>Warning: Invalid Bitcoin address</source> <translation>Warnung: Ungültige Bitcoin-Adresse</translation> </message> @@ -2806,6 +2874,10 @@ zum Beispiel: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com <translation>Warnung: wallet.dat beschädigt, Datenrettung erfolgreich! Original wallet.dat wurde als wallet.{Zeitstempel}.dat in %s gespeichert. Falls Ihr Kontostand oder Transaktionen nicht korrekt sind, sollten Sie von einer Datensicherung wiederherstellen.</translation> </message> <message> + <source>Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.</source> + <translation>Gegenstellen die sich von der angegebenen Netzmaske oder IP-Adresse aus verbinden immer zulassen. Kann mehrmals angegeben werden.</translation> + </message> + <message> <source>(default: 1)</source> <translation>(Standard: 1)</translation> </message> @@ -2982,10 +3054,6 @@ zum Beispiel: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com <translation>Neue Dateien mit Standard-Systemrechten erzeugen, anstatt mit umask 077 (nur mit deaktivierter Walletfunktion nutzbar)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Veröffentlicht unter der MIT/X11-Softwarelizenz, siehe beiligende Datei COPYING oder <http://www.opensource.org/licenses/mit-license.php>.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>Fehler: Abhören nach eingehenden Verbindungen fehlgeschlagen (listen meldete Fehler %s)</translation> </message> @@ -3006,12 +3074,20 @@ zum Beispiel: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com <translation>Niedrigere Gebühren (in BTC/Kb) als diese werden bei der Transaktionserstellung als gebührenfrei angesehen (Standard: %s)</translation> </message> <message> + <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source> + <translation>Maximale Datengröße in "Data Carrier"-Transaktionen die weitergeleitet und erarbeitet werden (Standard: %u)</translation> + </message> + <message> <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source> <translation>Adressen von Gegenstellen via DNS-Namensauflösung finden, falls zu wenige Adressen verfügbar sind (Standard: 1, außer bei -connect)</translation> </message> <message> <source>Set maximum size of high-priority/low-fee transactions in bytes (default: %d)</source> - <translation>Maximale Größe in Byte von Transaktionen hoher Priorität/mit niedrigen Gebühren festlegen (Standard: %d)</translation> + <translation>Maximale Größe in Byte von "high-priority/low-fee"-Transaktionen festlegen (Standard: %d)</translation> + </message> + <message> + <source>Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)</source> + <translation>Maximale Anzahl an Threads zur Bitcoinerzeugung, wenn aktiviert, festlegen (-1 = alle Kerne, Standard: %d)</translation> </message> <message> <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source> @@ -3118,6 +3194,10 @@ zum Beispiel: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com <translation>Rückverfolgungs- und Debuginformationen an die Konsole senden, anstatt sie in debug.log zu schreiben</translation> </message> <message> + <source>Send transactions as zero-fee transactions if possible (default: %u)</source> + <translation>Transaktionen, wenn möglich, als gebührenfreie Transaktion senden (Standard: %u)</translation> + </message> + <message> <source>Show all debugging options (usage: --help -help-debug)</source> <translation>Zeige alle Debuggingoptionen (Benutzung: --help -help-debug)</translation> </message> @@ -3226,6 +3306,10 @@ zum Beispiel: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com <translation>Fehler beim Laden von wallet.dat: Wallet beschädigt</translation> </message> <message> + <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source> + <translation>(1 = TX-Metadaten wie z.B. Accountbesitzer und Zahlungsanforderungsinformationen behalten, 2 = TX-Metadaten verwerfen)</translation> + </message> + <message> <source>Flush database activity from memory pool to disk log every <n> megabytes (default: %u)</source> <translation>Datenbankaktivitäten vom Arbeitsspeicher-Pool alle <n> Megabyte auf den Datenträger schreiben (Standard: %u)</translation> </message> @@ -3234,6 +3318,10 @@ zum Beispiel: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com <translation>Legt fest, wie gründlich die Blockverifikation von -checkblocks ist (0-4, Standard: %u)</translation> </message> <message> + <source>If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: %u)</source> + <translation>Wenn keine Transaktionsgebühr festgelegt wurde eine Gebühr einbeziehen, sodass Transaktionen im Schnitt innerhalb von <n> Blöcken bestätigt werden (Standard: %u)</translation> + </message> + <message> <source>Log transaction priority and fee per kB when mining blocks (default: %u)</source> <translation>Transaktionspriorität und Gebühr pro kB beim Erzeugen von Blöcken protokollieren (Standard: %u)</translation> </message> @@ -3250,10 +3338,6 @@ zum Beispiel: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com <translation>Debugginginformationen ausgeben (Standard: %u, <category> anzugeben ist optional)</translation> </message> <message> - <source>Set the processor limit for when generation is on (-1 = unlimited, default: %d)</source> - <translation>Legt ein Prozessor-/CPU-Kernlimit fest, wenn CPU-Mining aktiviert ist (-1 = unbegrenzt, Standard: %d)</translation> - </message> - <message> <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> <translation>Separaten SOCKS5-Proxy verwenden, um Gegenstellen über versteckte Tor-Dienste zu erreichen (Standard: %s)</translation> </message> @@ -3266,6 +3350,10 @@ zum Beispiel: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com <translation>Zulässige Chiffren (Standard: %s)</translation> </message> <message> + <source>Always query for peer addresses via DNS lookup (default: %u)</source> + <translation>Adressen von Gegenstellen immer über DNS-Namensauflösung abfragen (Standard: %u)</translation> + </message> + <message> <source>Disable safemode, override a real safe mode event (default: %u)</source> <translation>Sicherheitsmodus deaktivieren, übergeht ein echtes Sicherheitsmodusereignis (Standard: %u)</translation> </message> @@ -3378,6 +3466,10 @@ zum Beispiel: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com <translation>Unbestätigtes Wechselgeld darf beim Senden von Transaktionen ausgegeben werden (Standard: %u)</translation> </message> <message> + <source>Stop running after importing blocks from disk (default: %u)</source> + <translation>Beenden, nachdem Blöcke vom Datenträger importiert wurden (Standard: %u)</translation> + </message> + <message> <source>Threshold for disconnecting misbehaving peers (default: %u)</source> <translation>Schwellenwert, um Verbindungen zu sich nicht konform verhaltenden Gegenstellen zu beenden (Standard: %u)</translation> </message> diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts index b4e15ae2df..1a1c918c5b 100644 --- a/src/qt/locale/bitcoin_el_GR.ts +++ b/src/qt/locale/bitcoin_el_GR.ts @@ -1,4 +1,4 @@ -<TS language="el_GR" version="2.1"> +<TS language="el_GR" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -498,10 +498,6 @@ Address: %4 <translation>Ποσό</translation> </message> <message> - <source>Address</source> - <translation>Διεύθυνση</translation> - </message> - <message> <source>Date</source> <translation>Ημερομηνία</translation> </message> @@ -777,14 +773,6 @@ Address: %4 <translation>&Κύριο</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Η προαιρετική αμοιβή για κάθε kB επισπεύδει την επεξεργασία των συναλλαγών σας. Οι περισσότερες συναλλαγές είναι 1 kB. </translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Αμοιβή &συναλλαγής</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Αυτόματη εκκίνηση του Bitcoin μετά την εισαγωγή στο σύστημα</translation> </message> diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index df285441e1..71c626be4b 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> -<TS version="2.1" language="en"> +<TS version="2.0" language="en"> <context> <name>AddressBookPage</name> <message> @@ -150,7 +150,7 @@ <translation>Passphrase Dialog</translation> </message> <message> - <location line="+21"/> + <location line="+30"/> <source>Enter passphrase</source> <translation>Enter passphrase</translation> </message> @@ -165,7 +165,7 @@ <translation>Repeat new passphrase</translation> </message> <message> - <location filename="../askpassphrasedialog.cpp" line="+41"/> + <location filename="../askpassphrasedialog.cpp" line="+45"/> <source>Encrypt wallet</source> <translation>Encrypt wallet</translation> </message> @@ -200,7 +200,7 @@ <translation>Enter the old and new passphrase to the wallet.</translation> </message> <message> - <location line="+46"/> + <location line="+45"/> <source>Confirm wallet encryption</source> <translation>Confirm wallet encryption</translation> </message> @@ -232,12 +232,12 @@ <translation>Wallet encrypted</translation> </message> <message> - <location line="-135"/> + <location line="-136"/> <source>Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>.</source> <translation type="unfinished"></translation> </message> <message> - <location line="+79"/> + <location line="+80"/> <source>Bitcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source> <translation>Bitcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</translation> </message> @@ -286,7 +286,7 @@ <context> <name>BitcoinGUI</name> <message> - <location filename="../bitcoingui.cpp" line="+309"/> + <location filename="../bitcoingui.cpp" line="+311"/> <source>Sign &message...</source> <translation>Sign &message...</translation> </message> @@ -296,7 +296,7 @@ <translation>Synchronizing with network...</translation> </message> <message> - <location line="-405"/> + <location line="-407"/> <source>&Overview</source> <translation>&Overview</translation> </message> @@ -321,7 +321,7 @@ <translation>Browse transaction history</translation> </message> <message> - <location line="+17"/> + <location line="+19"/> <source>E&xit</source> <translation>E&xit</translation> </message> @@ -392,12 +392,12 @@ <translation>Reindexing blocks on disk...</translation> </message> <message> - <location line="-403"/> + <location line="-405"/> <source>Send coins to a Bitcoin address</source> <translation>Send coins to a Bitcoin address</translation> </message> <message> - <location line="+46"/> + <location line="+48"/> <source>Modify configuration options for Bitcoin</source> <translation>Modify configuration options for Bitcoin</translation> </message> @@ -432,7 +432,7 @@ <translation>Bitcoin</translation> </message> <message> - <location line="-636"/> + <location line="-638"/> <source>Wallet</source> <translation>Wallet</translation> </message> @@ -447,7 +447,7 @@ <translation>&Receive</translation> </message> <message> - <location line="+30"/> + <location line="+32"/> <source>Show information about Bitcoin Core</source> <translation type="unfinished"></translation> </message> @@ -497,7 +497,7 @@ <translation>Tabs toolbar</translation> </message> <message> - <location line="-295"/> + <location line="-297"/> <source>Bitcoin Core</source> <translation type="unfinished">Bitcoin Core</translation> </message> @@ -507,7 +507,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+28"/> + <location line="+30"/> <source>&About Bitcoin Core</source> <translation type="unfinished"></translation> </message> @@ -672,7 +672,7 @@ Address: %4 <context> <name>ClientModel</name> <message> - <location filename="../clientmodel.cpp" line="+139"/> + <location filename="../clientmodel.cpp" line="+140"/> <source>Network Alert</source> <translation>Network Alert</translation> </message> @@ -681,7 +681,7 @@ Address: %4 <name>CoinControlDialog</name> <message> <location filename="../forms/coincontroldialog.ui" line="+14"/> - <source>Coin Control Address Selection</source> + <source>Coin Selection</source> <translation type="unfinished"></translation> </message> <message> @@ -735,19 +735,24 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+16"/> + <location line="+13"/> <source>List mode</source> <translation type="unfinished"></translation> </message> <message> - <location line="+53"/> + <location line="+56"/> <source>Amount</source> <translation type="unfinished">Amount</translation> </message> <message> - <location line="+10"/> - <source>Address</source> - <translation type="unfinished">Address</translation> + <location line="+5"/> + <source>Received with label</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+5"/> + <source>Received with address</source> + <translation type="unfinished"></translation> </message> <message> <location line="+5"/> @@ -770,7 +775,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location filename="../coincontroldialog.cpp" line="+43"/> + <location filename="../coincontroldialog.cpp" line="+44"/> <source>Copy address</source> <translation type="unfinished">Copy address</translation> </message> @@ -836,17 +841,17 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+333"/> + <location line="+347"/> <source>highest</source> <translation type="unfinished"></translation> </message> <message> - <location line="+0"/> + <location line="+1"/> <source>higher</source> <translation type="unfinished"></translation> </message> <message> - <location line="+0"/> + <location line="+1"/> <source>high</source> <translation type="unfinished"></translation> </message> @@ -856,18 +861,17 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+0"/> - <location line="+12"/> + <location line="+1"/> <source>medium</source> <translation type="unfinished"></translation> </message> <message> - <location line="-11"/> + <location line="+1"/> <source>low-medium</source> <translation type="unfinished"></translation> </message> <message> - <location line="+0"/> + <location line="+1"/> <source>low</source> <translation type="unfinished"></translation> </message> @@ -877,7 +881,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+11"/> + <location line="+1"/> <source>lowest</source> <translation type="unfinished"></translation> </message> @@ -892,12 +896,12 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+162"/> + <location line="+165"/> <source>Can vary +/- %1 satoshi(s) per input.</source> <translation type="unfinished"></translation> </message> <message> - <location line="-28"/> + <location line="-32"/> <source>yes</source> <translation type="unfinished"></translation> </message> @@ -938,7 +942,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+50"/> + <location line="+55"/> <location line="+61"/> <source>(no label)</source> <translation type="unfinished">(no label)</translation> @@ -1224,17 +1228,7 @@ Address: %4 <translation>&Main</translation> </message> <message> - <location line="+116"/> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</translation> - </message> - <message> - <location line="+15"/> - <source>Pay transaction &fee</source> - <translation>Pay transaction &fee</translation> - </message> - <message> - <location line="-125"/> + <location line="+6"/> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Automatically start Bitcoin after logging in to the system.</translation> </message> @@ -1259,7 +1253,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+160"/> + <location line="+114"/> <source>Accept connections from outside</source> <translation type="unfinished"></translation> </message> @@ -1269,17 +1263,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+7"/> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+3"/> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+34"/> + <location line="+44"/> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation type="unfinished"></translation> </message> @@ -1315,7 +1299,7 @@ Address: %4 <translation>&Network</translation> </message> <message> - <location line="-131"/> + <location line="-85"/> <source>(0 = auto, <0 = leave that many cores free)</source> <translation type="unfinished"></translation> </message> @@ -1325,7 +1309,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+65"/> + <location line="+6"/> <source>Expert</source> <translation type="unfinished"></translation> </message> @@ -1345,7 +1329,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+17"/> + <location line="+30"/> <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source> <translation>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</translation> </message> @@ -1355,7 +1339,17 @@ Address: %4 <translation>Map port using &UPnP</translation> </message> <message> - <location line="+29"/> + <location line="+17"/> + <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>&Connect through SOCKS5 proxy (default proxy):</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+9"/> <source>Proxy &IP:</source> <translation>Proxy &IP:</translation> </message> @@ -1420,12 +1414,12 @@ Address: %4 <translation>Choose the default subdivision unit to show in the interface and when sending coins.</translation> </message> <message> - <location line="-240"/> + <location line="-253"/> <source>Whether to show coin control features or not.</source> <translation type="unfinished"></translation> </message> <message> - <location line="+402"/> + <location line="+415"/> <source>&OK</source> <translation>&OK</translation> </message> @@ -1435,17 +1429,17 @@ Address: %4 <translation>&Cancel</translation> </message> <message> - <location filename="../optionsdialog.cpp" line="+71"/> + <location filename="../optionsdialog.cpp" line="+76"/> <source>default</source> <translation>default</translation> </message> <message> - <location line="+63"/> + <location line="+60"/> <source>none</source> <translation type="unfinished"></translation> </message> <message> - <location line="+82"/> + <location line="+76"/> <source>Confirm options reset</source> <translation>Confirm options reset</translation> </message> @@ -1466,7 +1460,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+34"/> + <location line="+25"/> <source>The supplied proxy address is invalid.</source> <translation>The supplied proxy address is invalid.</translation> </message> @@ -2268,7 +2262,7 @@ Address: %4 <context> <name>RecentRequestsTableModel</name> <message> - <location filename="../recentrequeststablemodel.cpp" line="+26"/> + <location filename="../recentrequeststablemodel.cpp" line="+28"/> <source>Date</source> <translation type="unfinished">Date</translation> </message> @@ -2307,7 +2301,7 @@ Address: %4 <name>SendCoinsDialog</name> <message> <location filename="../forms/sendcoinsdialog.ui" line="+14"/> - <location filename="../sendcoinsdialog.cpp" line="+447"/> + <location filename="../sendcoinsdialog.cpp" line="+529"/> <source>Send Coins</source> <translation>Send Coins</translation> </message> @@ -2377,7 +2371,98 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+164"/> + <location line="+206"/> + <source>Transaction Fee:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+14"/> + <source>Choose...</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>collapse fee-settings</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>Minimize</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+78"/> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>per kilobyte</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+13"/> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>total at least</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+30"/> + <location line="+13"/> + <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>(read the tooltip)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+29"/> + <source>Recommended:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+30"/> + <source>Custom:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+52"/> + <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+29"/> + <source>Confirmation time:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+60"/> + <source>normal</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+20"/> + <source>fast</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+38"/> + <source>Send as zero-fee transaction if possible</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> + <source>(confirmation may take longer)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+110"/> <source>Send to multiple recipients at once</source> <translation>Send to multiple recipients at once</translation> </message> @@ -2392,12 +2477,12 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="-274"/> + <location line="-858"/> <source>Dust:</source> <translation type="unfinished"></translation> </message> <message> - <location line="+277"/> + <location line="+861"/> <source>Clear &All</source> <translation>Clear &All</translation> </message> @@ -2417,12 +2502,12 @@ Address: %4 <translation>S&end</translation> </message> <message> - <location filename="../sendcoinsdialog.cpp" line="-215"/> + <location filename="../sendcoinsdialog.cpp" line="-221"/> <source>Confirm send coins</source> <translation>Confirm send coins</translation> </message> <message> - <location line="-74"/> + <location line="-77"/> <location line="+5"/> <location line="+5"/> <location line="+4"/> @@ -2430,7 +2515,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="-122"/> + <location line="-192"/> <source>Copy quantity</source> <translation type="unfinished"></translation> </message> @@ -2465,7 +2550,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+171"/> + <location line="+244"/> <source>Total Amount %1 (= %2)</source> <translation type="unfinished"></translation> </message> @@ -2475,7 +2560,7 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+189"/> + <location line="+192"/> <source>The recipient address is not valid, please recheck.</source> <translation>The recipient address is not valid, please recheck.</translation> </message> @@ -2510,7 +2595,22 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="+113"/> + <location line="+4"/> + <source>A fee higher than %1 is considered an insanely high fee.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+87"/> + <source>Pay only the minimum fee of %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+22"/> + <source>Estimated to begin confirmation within %1 block(s).</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+107"/> <source>Warning: Invalid Bitcoin address</source> <translation type="unfinished"></translation> </message> @@ -2525,12 +2625,12 @@ Address: %4 <translation type="unfinished"></translation> </message> <message> - <location line="-504"/> + <location line="-687"/> <source>Copy dust</source> <translation type="unfinished"></translation> </message> <message> - <location line="+151"/> + <location line="+221"/> <source>Are you sure you want to send?</source> <translation type="unfinished"></translation> </message> @@ -3087,7 +3187,7 @@ Address: %4 <context> <name>TransactionTableModel</name> <message> - <location filename="../transactiontablemodel.cpp" line="+235"/> + <location filename="../transactiontablemodel.cpp" line="+229"/> <source>Date</source> <translation>Date</translation> </message> @@ -3102,7 +3202,7 @@ Address: %4 <translation>Address</translation> </message> <message> - <location line="+76"/> + <location line="+79"/> <source>Immature (%1 confirmations, will be available after %2)</source> <translation type="unfinished"></translation> </message> @@ -3418,7 +3518,7 @@ Address: %4 <context> <name>WalletModel</name> <message> - <location filename="../walletmodel.cpp" line="+280"/> + <location filename="../walletmodel.cpp" line="+276"/> <source>Send Coins</source> <translation>Send Coins</translation> </message> @@ -3436,7 +3536,7 @@ Address: %4 <translation>Export the data in the current tab to a file</translation> </message> <message> - <location line="+184"/> + <location line="+187"/> <source>Backup Wallet</source> <translation>Backup Wallet</translation> </message> @@ -3469,27 +3569,27 @@ Address: %4 <context> <name>bitcoin-core</name> <message> - <location filename="../bitcoinstrings.cpp" line="+236"/> + <location filename="../bitcoinstrings.cpp" line="+239"/> <source>Options:</source> <translation>Options:</translation> </message> <message> - <location line="+30"/> + <location line="+31"/> <source>Specify data directory</source> <translation>Specify data directory</translation> </message> <message> - <location line="-90"/> + <location line="-91"/> <source>Connect to a node to retrieve peer addresses, and disconnect</source> <translation>Connect to a node to retrieve peer addresses, and disconnect</translation> </message> <message> - <location line="+93"/> + <location line="+94"/> <source>Specify your own public address</source> <translation>Specify your own public address</translation> </message> <message> - <location line="-108"/> + <location line="-109"/> <source>Accept command line and JSON-RPC commands</source> <translation>Accept command line and JSON-RPC commands</translation> </message> @@ -3499,17 +3599,17 @@ Address: %4 <translation>Run in the background as a daemon and accept commands</translation> </message> <message> - <location line="+35"/> + <location line="+36"/> <source>Use the test network</source> <translation>Use the test network</translation> </message> <message> - <location line="-124"/> + <location line="-125"/> <source>Accept connections from outside (default: 1 if no -proxy or -connect)</source> <translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation> </message> <message> - <location line="-150"/> + <location line="-153"/> <source>%s, you must set a rpcpassword in the configuration file: %s It is recommended you use the following random password: @@ -3544,7 +3644,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+6"/> + <location line="+3"/> + <source>Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> <source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly.</source> <translation type="unfinished"></translation> </message> @@ -3569,7 +3674,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+17"/> + <location line="+20"/> <source>Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)</source> <translation type="unfinished"></translation> </message> @@ -3744,7 +3849,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Rebuild block chain index from current blk000??.dat files</translation> </message> <message> - <location line="+10"/> + <location line="+11"/> <source>Set database cache size in megabytes (%d to %d, default: %d)</source> <translation type="unfinished"></translation> </message> @@ -3794,12 +3899,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>You need to rebuild the database using -reindex to change -txindex</translation> </message> <message> - <location line="-91"/> + <location line="-92"/> <source>Imports blocks from external blk000??.dat file</source> <translation>Imports blocks from external blk000??.dat file</translation> </message> <message> - <location line="-179"/> + <location line="-182"/> <source>Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times</source> <translation type="unfinished"></translation> </message> @@ -3834,12 +3939,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+6"/> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+6"/> + <location line="+12"/> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation type="unfinished"></translation> </message> @@ -3864,7 +3964,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+23"/> + <location line="+19"/> + <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+7"/> <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source> <translation type="unfinished"></translation> </message> @@ -3874,7 +3979,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+11"/> + <location line="+5"/> + <source>Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+6"/> <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source> <translation type="unfinished"></translation> </message> @@ -4004,6 +4114,11 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Send trace/debug info to console instead of debug.log file</translation> </message> <message> + <location line="+1"/> + <source>Send transactions as zero-fee transactions if possible (default: %u)</source> + <translation type="unfinished"></translation> + </message> + <message> <location line="+9"/> <source>Show all debugging options (usage: --help -help-debug)</source> <translation type="unfinished"></translation> @@ -4094,27 +4209,27 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>wallet.dat corrupt, salvage failed</translation> </message> <message> - <location line="-63"/> + <location line="-64"/> <source>Password for JSON-RPC connections</source> <translation>Password for JSON-RPC connections</translation> </message> <message> - <location line="-157"/> + <location line="-160"/> <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source> <translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation> </message> <message> - <location line="+202"/> + <location line="+206"/> <source>Upgrade wallet to latest format</source> <translation>Upgrade wallet to latest format</translation> </message> <message> - <location line="-34"/> + <location line="-35"/> <source>Rescan the block chain for missing wallet transactions</source> <translation>Rescan the block chain for missing wallet transactions</translation> </message> <message> - <location line="+35"/> + <location line="+36"/> <source>Use OpenSSL (https) for JSON-RPC connections</source> <translation>Use OpenSSL (https) for JSON-RPC connections</translation> </message> @@ -4124,7 +4239,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>This help message</translation> </message> <message> - <location line="-107"/> + <location line="-108"/> <source>Allow DNS lookups for -addnode, -seednode and -connect</source> <translation>Allow DNS lookups for -addnode, -seednode and -connect</translation> </message> @@ -4139,7 +4254,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Error loading wallet.dat: Wallet corrupted</translation> </message> <message> - <location line="-167"/> + <location line="-170"/> <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source> <translation type="unfinished"></translation> </message> @@ -4169,7 +4284,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+3"/> + <location line="+6"/> <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source> <translation type="unfinished"></translation> </message> @@ -4179,12 +4294,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+10"/> - <source>Set the processor limit for when generation is on (-1 = unlimited, default: %d)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+13"/> + <location line="+23"/> <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> <translation type="unfinished"></translation> </message> @@ -4299,7 +4409,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation type="unfinished"></translation> </message> <message> - <location line="+3"/> + <location line="+4"/> <source>Server certificate file (default: %s)</source> <translation type="unfinished"></translation> </message> @@ -4364,7 +4474,7 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Unknown network specified in -onlynet: '%s'</translation> </message> <message> - <location line="-111"/> + <location line="-112"/> <source>Cannot resolve -bind address: '%s'</source> <translation>Cannot resolve -bind address: '%s'</translation> </message> @@ -4424,12 +4534,12 @@ for example: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo. <translation>Done loading</translation> </message> <message> - <location line="+90"/> + <location line="+91"/> <source>To use the %s option</source> <translation>To use the %s option</translation> </message> <message> - <location line="-82"/> + <location line="-83"/> <source>Error</source> <translation>Error</translation> </message> diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts index 4496dcc3d9..5189310e64 100644 --- a/src/qt/locale/bitcoin_eo.ts +++ b/src/qt/locale/bitcoin_eo.ts @@ -1,4 +1,4 @@ -<TS language="eo" version="2.1"> +<TS language="eo" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -537,10 +537,6 @@ Adreso: %4 <translation>Sumo</translation> </message> <message> - <source>Address</source> - <translation>Adreso</translation> - </message> - <message> <source>Date</source> <translation>Dato</translation> </message> @@ -883,14 +879,6 @@ Adreso: %4 <translation>Ĉ&efa</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Nedeviga krompago por ĉiu kB, kiu helpas plirapidigi la traktadon de via transakcio. Plej multaj transakcioj grandas je 1kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Krompago</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Aŭtomate lanĉi Bitmonon post ensaluto al la sistemo.</translation> </message> diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts index 0cb8991e11..71f7e9f4c9 100644 --- a/src/qt/locale/bitcoin_es.ts +++ b/src/qt/locale/bitcoin_es.ts @@ -1,4 +1,4 @@ -<TS language="es" version="2.1"> +<TS language="es" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -525,10 +525,6 @@ Dirección: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Selección de direcciones bajo Coin Control</translation> - </message> - <message> <source>Quantity:</source> <translation>Cantidad:</translation> </message> @@ -577,10 +573,6 @@ Dirección: %4 <translation>Cantidad</translation> </message> <message> - <source>Address</source> - <translation>Dirección</translation> - </message> - <message> <source>Date</source> <translation>Fecha</translation> </message> @@ -955,14 +947,6 @@ Dirección: %4 <translation>&Principal</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Comisión de transacción opcional por kB que ayuda a asegurar que sus transacciones sean procesadas rápidamente. La mayoría de transacciones son de 1kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Pagar comisión de &transacción</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Iniciar Bitcoin automáticamente al encender el sistema.</translation> </message> @@ -991,14 +975,6 @@ Dirección: %4 <translation>Aceptar conexiones entrantes</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Conectarse a la red Bitcoin a través de un proxy SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Conectarse a través de proxy SOCKS (proxy predeterminado):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Dirección IP del proxy (p. ej. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -2481,6 +2457,10 @@ Dirección: %4 <translation>Tipo de transacción.</translation> </message> <message> + <source>Whether or not a watch-only address is involved in this transaction.</source> + <translation>Sea o no una dirección sólo está involucrada en esta transacción.</translation> + </message> + <message> <source>Destination address of transaction.</source> <translation>Dirección de destino de la transacción.</translation> </message> @@ -2963,6 +2943,10 @@ Por ejemplo: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Importa los bloques desde un archivo blk000??.dat externo</translation> </message> <message> + <source>Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times</source> + <translation>Permitir conexiones JSON-RPC de origen especificado. Válido para son una sola IP (por ejemplo 1.2.3.4), una red/máscara de red (por ejemplo 1.2.3.4/255.255.255.0) o una red/CIDR (e.g. 1.2.3.4/24). Esta opción se puede especificar varias veces</translation> + </message> + <message> <source>An error occurred while setting up the RPC address %s port %u for listening: %s</source> <translation>Ocurrió un error al configurar la dirección de RPC %s puerto %u para escuchar en: %s</translation> </message> @@ -2987,18 +2971,30 @@ Por ejemplo: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Crear nuevos archivos con permisos por defecto del sistema, en lugar de umask 077 (sólo efectivo con la funcionalidad de monedero desactivada)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Distribuido bajo la licencia de software MIT/X11, vea la copia del archivo adjunto o <http://www.opensource.org/licenses/mit-license.php>.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>Error: la escucha para conexiones entrantes falló (la escucha regresó el error %s)</translation> </message> <message> + <source>Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.</source> + <translation>Error: Unsupported argumento -socks encontrados. SOCKS versión ajuste ya no es posible, sólo SOCKS5 proxies son compatibles.</translation> + </message> + <message> <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source> <translation>Ejecutar un comando cuando se reciba una alerta importante o cuando veamos un fork demasiado largo (%s en cmd se reemplazará por el mensaje)</translation> </message> <message> + <source>Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)</source> + <translation>Tarifas (en BTC/Kb) más pequeños que esto se consideran cero cuota de reinstalación (por defecto: %s)</translation> + </message> + <message> + <source>Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)</source> + <translation>Tarifas (en BTC/Kb) más pequeños que esto se consideran cero cuota para la creación de la transacción (por defecto: %s)</translation> + </message> + <message> + <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source> + <translation>Consulta de direcciones pares mediante búsqueda de DNS, si bajo en direcciones (por defecto: 1 a menos que - conectar)</translation> + </message> + <message> <source>Set maximum size of high-priority/low-fee transactions in bytes (default: %d)</source> <translation>Establecer tamaño máximo de las transacciones de alta prioridad/baja comisión en bytes (predeterminado: %d)</translation> </message> @@ -3011,6 +3007,10 @@ Por ejemplo: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Aviso: ¡Comprueba la fecha y hora de tu ordenador y verifica si es correcta! Si no es correcta Bitcoin Core no funcionará adecuadamente.</translation> </message> <message> + <source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source> + <translation>A los equipos en lista blanca no se les pueden prohibir los ataques DoS y sus transacciones siempre son retransmitidas, incluso si ya están en el mempool, es útil por ejemplo para un gateway.</translation> + </message> + <message> <source>Connect through SOCKS5 proxy</source> <translation>Conectar usando SOCKS5 proxy</translation> </message> @@ -3023,10 +3023,18 @@ Por ejemplo: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Error al cargar wallet.dat: El monedero requiere una versión más reciente de Bitcoin Core</translation> </message> <message> + <source>Fee (in BTC/kB) to add to transactions you send (default: %s)</source> + <translation>Cuota (in BTC/kB) para añadir a las transacciones que envíes (por defecto: %s)</translation> + </message> + <message> <source>Information</source> <translation>Información</translation> </message> <message> + <source>Initialization sanity check failed. Bitcoin Core is shutting down.</source> + <translation>La inicialización de la verificación de validez falló. Se está apagando Bitcoin Core.</translation> + </message> + <message> <source>Invalid amount for -minrelaytxfee=<amount>: '%s'</source> <translation>Cantidad inválida para -minrelaytxfee=<amount>: '%s'</translation> </message> @@ -3035,6 +3043,26 @@ Por ejemplo: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Cantidad inválida para -mintxfee=<amount>: '%s'</translation> </message> <message> + <source>Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)</source> + <translation>Cantidad inválida para -paytxfee=<amount>: '%s' (debe ser por lo menos %s)</translation> + </message> + <message> + <source>Invalid netmask specified in -whitelist: '%s'</source> + <translation>Máscara de red inválida especificada en -whitelist: '%s'</translation> + </message> + <message> + <source>Keep at most <n> unconnectable blocks in memory (default: %u)</source> + <translation>Mantener como máximo <n> bloques no conectables en memoria (por defecto: %u)</translation> + </message> + <message> + <source>Keep at most <n> unconnectable transactions in memory (default: %u)</source> + <translation>Mantener como máximo <n> transacciones no conectables en memoria (por defecto: %u)</translation> + </message> + <message> + <source>Need to specify a port with -whitebind: '%s'</source> + <translation>Necesita especificar un puerto con -whitebind: '%s'</translation> + </message> + <message> <source>Node relay options:</source> <translation>Opciones de nodos de retransmisión:</translation> </message> @@ -3183,6 +3211,10 @@ Por ejemplo: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Registrar prioridad de las transacciones y cuota por kB cuando se minen bloques (por defecto: %u)</translation> </message> <message> + <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source> + <translation>Mantener el índice completo de transacciones, usado por la llamada rpc de getrawtransaction (por defecto: %u)</translation> + </message> + <message> <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source> <translation>Número de segundos en que se evita la reconexión de pares con mal comportamiento (predeterminado: %u)</translation> </message> @@ -3271,6 +3303,10 @@ Por ejemplo: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Imprimir árbol de bloques al iniciar (predeterminado: %u)</translation> </message> <message> + <source>Relay and mine data carrier transactions (default: %u)</source> + <translation>Retransmitir y minar transacciones de transporte de datos (por defecto: %u)</translation> + </message> + <message> <source>Run a thread to flush wallet periodically (default: %u)</source> <translation>Ejecutar un hilo para limpiar de la memoria el monedero periódicamente (predeterminado: %u)</translation> </message> @@ -3372,7 +3408,7 @@ Por ejemplo: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com </message> <message> <source>Done loading</source> - <translation>Generado pero no aceptado</translation> + <translation>Se terminó de cargar</translation> </message> <message> <source>To use the %s option</source> diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts index 930aac8449..e6f81e650f 100644 --- a/src/qt/locale/bitcoin_es_CL.ts +++ b/src/qt/locale/bitcoin_es_CL.ts @@ -1,4 +1,4 @@ -<TS language="es_CL" version="2.1"> +<TS language="es_CL" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -356,10 +356,6 @@ Dirección: %4</translation> <translation>Cantidad</translation> </message> <message> - <source>Address</source> - <translation>Dirección</translation> - </message> - <message> <source>Date</source> <translation>Fecha</translation> </message> @@ -479,10 +475,6 @@ Dirección: %4</translation> <translation>&Principal</translation> </message> <message> - <source>Pay transaction &fee</source> - <translation>Comisión de &transacciónes</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Inicia Bitcoin automáticamente despues de encender el computador</translation> </message> diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts index 8099b182ae..2e5daf4cdb 100644 --- a/src/qt/locale/bitcoin_es_DO.ts +++ b/src/qt/locale/bitcoin_es_DO.ts @@ -1,4 +1,4 @@ -<TS language="es_DO" version="2.1"> +<TS language="es_DO" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -477,10 +477,6 @@ Dirección: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Selección de la dirección de control de la moneda</translation> - </message> - <message> <source>Quantity:</source> <translation>Cantidad:</translation> </message> @@ -525,10 +521,6 @@ Dirección: %4 <translation>Cantidad</translation> </message> <message> - <source>Address</source> - <translation>Dirección</translation> - </message> - <message> <source>Date</source> <translation>Fecha</translation> </message> @@ -875,14 +867,6 @@ Dirección: %4 <translation>&Principal</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Tarifa de transacción opcional por kB que ayuda a asegurar que sus transacciones sean procesadas rápidamente. La mayoría de transacciones son de 1kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Comisión de &transacciones</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Iniciar Bitcoin automáticamente al encender el sistema.</translation> </message> @@ -895,10 +879,6 @@ Dirección: %4 <translation>MB</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Conéctese a la red Bitcoin través de un proxy SOCKS.</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Dirección IP del proxy (ej. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts index 93d9f6473d..bedc5d243e 100644 --- a/src/qt/locale/bitcoin_es_MX.ts +++ b/src/qt/locale/bitcoin_es_MX.ts @@ -1,4 +1,4 @@ -<TS language="es_MX" version="2.1"> +<TS language="es_MX" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -397,10 +397,6 @@ <translation>Monto</translation> </message> <message> - <source>Address</source> - <translation>Domicilio</translation> - </message> - <message> <source>Date</source> <translation>Fecha</translation> </message> diff --git a/src/qt/locale/bitcoin_es_UY.ts b/src/qt/locale/bitcoin_es_UY.ts index 8bca84c219..a5a1583b19 100644 --- a/src/qt/locale/bitcoin_es_UY.ts +++ b/src/qt/locale/bitcoin_es_UY.ts @@ -1,4 +1,4 @@ -<TS language="es_UY" version="2.1"> +<TS language="es_UY" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -197,10 +197,6 @@ <context> <name>CoinControlDialog</name> <message> - <source>Address</source> - <translation>Direccion </translation> - </message> - <message> <source>Date</source> <translation>Fecha</translation> </message> diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts index 82ed0337ab..801fcf6258 100644 --- a/src/qt/locale/bitcoin_et.ts +++ b/src/qt/locale/bitcoin_et.ts @@ -1,4 +1,4 @@ -<TS language="et" version="2.1"> +<TS language="et" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -408,10 +408,6 @@ Aadress: %4⏎</translation> <translation>Kogus</translation> </message> <message> - <source>Address</source> - <translation>Aadress</translation> - </message> - <message> <source>Date</source> <translation>Kuupäev</translation> </message> @@ -550,10 +546,6 @@ Aadress: %4⏎</translation> <translation>Valikud</translation> </message> <message> - <source>Pay transaction &fee</source> - <translation>Tasu tehingu &fee</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Käivita Bitcoin süsteemi logimisel.</translation> </message> diff --git a/src/qt/locale/bitcoin_eu_ES.ts b/src/qt/locale/bitcoin_eu_ES.ts index 9a570890a1..ea0ce1a67d 100644 --- a/src/qt/locale/bitcoin_eu_ES.ts +++ b/src/qt/locale/bitcoin_eu_ES.ts @@ -1,4 +1,4 @@ -<TS language="eu_ES" version="2.1"> +<TS language="eu_ES" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -213,10 +213,6 @@ <translation>Kopurua</translation> </message> <message> - <source>Address</source> - <translation>Helbidea</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts index c33bbdf6b4..475515f4b7 100644 --- a/src/qt/locale/bitcoin_fa.ts +++ b/src/qt/locale/bitcoin_fa.ts @@ -1,4 +1,4 @@ -<TS language="fa" version="2.1"> +<TS language="fa" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -437,10 +437,6 @@ Address: %4 <translation>مبلغ</translation> </message> <message> - <source>Address</source> - <translation>نشانی</translation> - </message> - <message> <source>Date</source> <translation>تاریخ</translation> </message> @@ -627,14 +623,6 @@ Address: %4 <translation>&عمومی</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>کارمزد اختیاریِ هر کیلوبایت برای انتقال سریعتر تراکنش. اکثر تراکنشها ۱ کیلوبایتی هستند.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>پرداخت &کارمزد تراکنش</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>اجرای خودکار بیتکوین در زمان ورود به سیستم.</translation> </message> diff --git a/src/qt/locale/bitcoin_fa_IR.ts b/src/qt/locale/bitcoin_fa_IR.ts index 5ff33fee1a..1a639a8592 100644 --- a/src/qt/locale/bitcoin_fa_IR.ts +++ b/src/qt/locale/bitcoin_fa_IR.ts @@ -1,4 +1,4 @@ -<TS language="fa_IR" version="2.1"> +<TS language="fa_IR" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -290,10 +290,6 @@ Address: %4 <translation>میزان</translation> </message> <message> - <source>Address</source> - <translation>حساب</translation> - </message> - <message> <source>Date</source> <translation>تاریخ</translation> </message> diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts index 76ec6d4bf5..9a2eadd6ea 100644 --- a/src/qt/locale/bitcoin_fi.ts +++ b/src/qt/locale/bitcoin_fi.ts @@ -1,4 +1,4 @@ -<TS language="fi" version="2.1"> +<TS language="fi" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -520,10 +520,6 @@ Osoite: %4</translation> <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Kolikkokontrollin osoitteen valinta</translation> - </message> - <message> <source>Quantity:</source> <translation>Määrä:</translation> </message> @@ -572,10 +568,6 @@ Osoite: %4</translation> <translation>Määrä</translation> </message> <message> - <source>Address</source> - <translation>Osoite</translation> - </message> - <message> <source>Date</source> <translation>Aika</translation> </message> @@ -942,14 +934,6 @@ Osoite: %4</translation> <translation>&Yleiset</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Valinnainen rahansiirtopalkkio per kB auttaa varmistamaan että rahansiirtosi prosessoidaan nopeasti. Useimmat rahansiirrot ovat alle 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Maksa rahansiirtopalkkio</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Käynnistä Bitcoin kirjautumisen yhteydessä.</translation> </message> @@ -978,14 +962,6 @@ Osoite: %4</translation> <translation>Hyväksy sisääntulevia yhteyksiä</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Yhdistä Bitcoin-verkkoon SOCKS proxyn kautta.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Yhdistä SOCKS proxyn kautta (oletus proxy):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>IP osoite proxille (esim. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts index 86c23b6c3e..71a1519411 100644 --- a/src/qt/locale/bitcoin_fr.ts +++ b/src/qt/locale/bitcoin_fr.ts @@ -1,4 +1,4 @@ -<TS language="fr" version="2.1"> +<TS language="fr" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -478,6 +478,10 @@ <source>Up to date</source> <translation>À jour</translation> </message> + <message numerus="yes"> + <source>Processed %n blocks of transaction history.</source> + <translation><numerusform>%n bloc de l'historique transactionnel a été traité</numerusform><numerusform>%n blocs de l'historique transactionnel ont été traités</numerusform></translation> + </message> <message> <source>Catching up...</source> <translation>Rattrapage en cours…</translation> @@ -521,8 +525,8 @@ Adresse : %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Sélection de l'adresse de contrôle des pièces</translation> + <source>Coin Selection</source> + <translation>Sélection des pièces</translation> </message> <message> <source>Quantity:</source> @@ -573,8 +577,12 @@ Adresse : %4 <translation>Montant</translation> </message> <message> - <source>Address</source> - <translation>Adresse</translation> + <source>Received with label</source> + <translation>Reçu avec une étiquette</translation> + </message> + <message> + <source>Received with address</source> + <translation>Reçu avec une adresse</translation> </message> <message> <source>Date</source> @@ -904,6 +912,10 @@ Adresse : %4 <source>Error</source> <translation>Erreur</translation> </message> + <message numerus="yes"> + <source>%n GB of free space available</source> + <translation><numerusform>%n Go d'espace libre disponible</numerusform><numerusform>%n Go d'espace libre disponibles</numerusform></translation> + </message> </context> <context> <name>OpenURIDialog</name> @@ -939,14 +951,6 @@ Adresse : %4 <translation>Réglages &principaux</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Frais de transaction optionnel par ko qui aident à garantir un traitement rapide des transactions. La plupart des transactions utilisent 1 ko.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Payer des &frais de transaction</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Démarrer Bitcoin automatiquement après avoir ouvert une session sur l'ordinateur.</translation> </message> @@ -975,14 +979,6 @@ Adresse : %4 <translation>Permettre les transactions entrantes</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Se connecter au réseau Bitcoin par un mandataire SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>Se &connecter par un mandataire SOCKS (mandataire par défaut) :</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Adresse IP du mandataire (par ex. IPv4 : 127.0.0.1 / IPv6 : ::1)</translation> </message> @@ -1043,6 +1039,14 @@ Adresse : %4 <translation>Mapper le port avec l'&UPnP</translation> </message> <message> + <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> + <translation>Se connecter au réseau Bitcoin par un mandataire SOCKS5.</translation> + </message> + <message> + <source>&Connect through SOCKS5 proxy (default proxy):</source> + <translation>Se &connecter par un mandataire SOCKS5 (mandataire par défaut) :</translation> + </message> + <message> <source>Proxy &IP:</source> <translation>&IP du serveur mandataire :</translation> </message> @@ -1191,7 +1195,7 @@ Adresse : %4 </message> <message> <source>Spendable:</source> - <translation>Disponible:</translation> + <translation>Disponible :</translation> </message> <message> <source>Recent transactions</source> @@ -1833,6 +1837,78 @@ Adresse : %4 <translation>Adresse personnalisée de monnaie rendue</translation> </message> <message> + <source>Transaction Fee:</source> + <translation>Frais de transaction :</translation> + </message> + <message> + <source>Choose...</source> + <translation>Choisir...</translation> + </message> + <message> + <source>collapse fee-settings</source> + <translation>réduire les paramètres des frais</translation> + </message> + <message> + <source>Minimize</source> + <translation>Minimiser</translation> + </message> + <message> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation>Si les frais personnalisés sont définis à 1 000 satoshis et que la transaction est seulement de 250 octets, donc le « par kilo-octet » ne paiera que 250 satoshis de frais, alors que le « au moins » paiera 1 000 satoshis. Pour des transactions supérieures à un kilo-octet, les deux paieront par kilo-octets.</translation> + </message> + <message> + <source>per kilobyte</source> + <translation>par kilo-octet</translation> + </message> + <message> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation>Si les frais personnalisés sont définis à 1 000 satoshis et que la transaction est seulement de 250 octets, donc le « par kilo-octet » ne paiera que 250 satoshis de frais, alors que le « total au moins » paiera 1 000 satoshis. Pour des transactions supérieures à un kilo-octet, les deux paieront par kilo-octets.</translation> + </message> + <message> + <source>total at least</source> + <translation>total au moins</translation> + </message> + <message> + <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> + <translation>Il est correct de payer les frais minimum tant que le volume transactionnel est inférieur à l'espace dans les blocs. Mais soyez conscient que ceci pourrait résulter en une transaction n'étant jamais confirmée une fois qu'il y aura plus de transactions que le réseau ne pourra en traiter.</translation> + </message> + <message> + <source>(read the tooltip)</source> + <translation>(lire l'infobulle)</translation> + </message> + <message> + <source>Recommended:</source> + <translation>Recommandés :</translation> + </message> + <message> + <source>Custom:</source> + <translation>Personnalisés : </translation> + </message> + <message> + <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source> + <translation>(Les frais intelligents ne sont pas encore initialisés. Ceci prend habituellement quelques blocs...)</translation> + </message> + <message> + <source>Confirmation time:</source> + <translation>Temps de confirmation :</translation> + </message> + <message> + <source>normal</source> + <translation>normal</translation> + </message> + <message> + <source>fast</source> + <translation>rapide</translation> + </message> + <message> + <source>Send as zero-fee transaction if possible</source> + <translation>Envoyer si possible une transaction sans frais</translation> + </message> + <message> + <source>(confirmation may take longer)</source> + <translation>(la confirmation pourrait prendre plus longtemps)</translation> + </message> + <message> <source>Send to multiple recipients at once</source> <translation>Envoyer à plusieurs destinataires à la fois</translation> </message> @@ -1937,6 +2013,18 @@ Adresse : %4 <translation>La transaction a été rejetée ! Ceci peut arriver si certaines pièces de votre portefeuille étaient déjà dépensées, par exemple si vous avez utilisé une copie de wallet.dat et que des pièces ont été dépensées dans la copie sans être marquées comme telles ici.</translation> </message> <message> + <source>A fee higher than %1 is considered an insanely high fee.</source> + <translation>Des frais supérieurs à %1 sont considérés comme follement élevés.</translation> + </message> + <message> + <source>Pay only the minimum fee of %1</source> + <translation>Payer seulement les frais minimum de %1</translation> + </message> + <message> + <source>Estimated to begin confirmation within %1 block(s).</source> + <translation>Début de confirmation estimé à %1 bloc(s).</translation> + </message> + <message> <source>Warning: Invalid Bitcoin address</source> <translation>Avertissement : adresse Bitcoin invalide</translation> </message> @@ -2466,7 +2554,7 @@ Adresse : %4 </message> <message> <source>Whether or not a watch-only address is involved in this transaction.</source> - <translation>Détermine si une adresse de type watch-only est impliquée dans cette transaction.</translation> + <translation>Une adresse juste-regarder est-elle impliquée dans cette transaction.</translation> </message> <message> <source>Destination address of transaction.</source> @@ -2564,6 +2652,10 @@ Adresse : %4 <translation>Exporter l'historique des transactions</translation> </message> <message> + <source>Watch-only</source> + <translation>Juste-regarder :</translation> + </message> + <message> <source>Exporting Failed</source> <translation>L'exportation a échoué</translation> </message> @@ -2739,6 +2831,10 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com <translation>Supprimer toutes les transactions du portefeuille et ne récupérer que ces parties de la chaîne de bloc avec -rescan au démarrage</translation> </message> <message> + <source>Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> + <translation>Distribué sous la licence MIT d'utilisation d'un logiciel. Consultez le fichier joint COPYING ou <http://www.opensource.org/licenses/mit-license.php>.</translation> + </message> + <message> <source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly.</source> <translation>Passer en mode de test de régression qui utilise une chaîne spéciale dans laquelle les blocs sont résolus instantanément.</translation> </message> @@ -2791,6 +2887,10 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com <translation>Avertissement : wallet.dat corrompu, données récupérées ! Le fichier wallet.dat original a été enregistré en tant que wallet.{timestamp}.bak dans %s ; si votre solde ou transactions sont incorrects vous devriez effectuer une restauration depuis une sauvegarde.</translation> </message> <message> + <source>Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.</source> + <translation>Pairs de la liste blanche se connectant à partir du masque réseau ou de l'IP donné. Peut être spécifié plusieurs fois.</translation> + </message> + <message> <source>(default: 1)</source> <translation>(par défaut : 1)</translation> </message> @@ -2852,7 +2952,7 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com </message> <message> <source>Error: A fatal internal error occured, see debug.log for details</source> - <translation>Erreur: Une erreur fatale s'est produite, voir debug.log pour plus de détails</translation> + <translation>Erreur : une erreur interne fatale s'est produite. Voir debug.log pour des détails</translation> </message> <message> <source>Error: Disk space is low!</source> @@ -2888,7 +2988,7 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com </message> <message> <source>Only connect to nodes in network <net> (ipv4, ipv6 or onion)</source> - <translation>Se connecter uniquement aux nœuds du réseau <net> (IPv4, IPv6 ou Tor)</translation> + <translation>Seulement se connecter aux nœuds du réseau <net> (IPv4, IPv6 ou oignon)</translation> </message> <message> <source>Rebuild block chain index from current blk000??.dat files</source> @@ -2911,6 +3011,10 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com <translation>Ceci est à l'intention des outils de test de régression et du développement applicatif.</translation> </message> <message> + <source>Use UPnP to map the listening port (default: %u)</source> + <translation>Utiliser l'UPnP pour mapper le port d'écoute (par défaut : %u)</translation> + </message> + <message> <source>Verifying blocks...</source> <translation>Vérification des blocs en cours...</translation> </message> @@ -2955,12 +3059,12 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com <translation>Impossible d’obtenir un verrou sur le répertoire de données %s. Bitcoin Core fonctionne probablement déjà.</translation> </message> <message> - <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> - <translation>Créer de nouveaux fichiers avec les permissions système par défaut, au lieu de umask 077 (effectif seulement avec la fonction du portefeuille désactivée)</translation> + <source>Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:%u)</source> + <translation>Limiter continuellement les transactions gratuites à <n>*1000 octets par minute (par défaut : %u)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Distribué sous la licence logiciel MIT/X11, consultez le fichier joint COPYING ou <http://www.opensource.org/licenses/mit-license.php>.</translation> + <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> + <translation>Créer de nouveaux fichiers avec les permissions système par défaut, au lieu de umask 077 (effectif seulement avec la fonction du portefeuille désactivée)</translation> </message> <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> @@ -2983,6 +3087,10 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com <translation>Les frais (en BTC/Ko) inférieurs à ce seuil sont considérés comme étant nuls pour la création de transactions (par défaut : %s)</translation> </message> <message> + <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source> + <translation>Quantité maximale de données dans les transactions du porteur de données que nous relayons et minons (par défaut : %u)</translation> + </message> + <message> <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source> <translation>Demander les adresses des pairs par recherche DNS si l'on manque d'adresses (par défaut : 1 sauf si -connect)</translation> </message> @@ -2991,6 +3099,10 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com <translation>Définir la taille maximale en octets des transactions prioritaires/à frais modiques (par défaut : %d)</translation> </message> <message> + <source>Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)</source> + <translation>Définir le nombre de fils de génération de pièces, si elle est activée (-1 = tous les cœurs, par défaut : %d)</translation> + </message> + <message> <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source> <translation>Ce produit comprend des logiciels développés par le projet OpenSSL pour être utilisés dans la boîte à outils OpenSSL <https://www.openssl.org/> et un logiciel cryptographique écrit par Eric Young, ainsi qu'un logiciel UPnP écrit par Thomas Bernard.</translation> </message> @@ -3060,7 +3172,7 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com </message> <message> <source>Keep at most <n> unconnectable transactions in memory (default: %u)</source> - <translation>Garder au plus <n> blocs non connectables en mémoire (par défaut : %u)</translation> + <translation>Garder au plus <n> transactions non connectables en mémoire (par défaut : %u)</translation> </message> <message> <source>Need to specify a port with -whitebind: '%s'</source> @@ -3095,6 +3207,10 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com <translation>Envoyer les informations de débogage/trace à la console au lieu du fichier debug.log</translation> </message> <message> + <source>Send transactions as zero-fee transactions if possible (default: %u)</source> + <translation>Envoyer si possible les transactions comme étant sans frais (par défaut : %u)</translation> + </message> + <message> <source>Show all debugging options (usage: --help -help-debug)</source> <translation>Montrer toutes les options de débogage (utilisation : --help --help-debug)</translation> </message> @@ -3128,7 +3244,7 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com </message> <message> <source>Use UPnP to map the listening port (default: 1 when listening)</source> - <translation>Utiliser l'UPnP pour rediriger le port d'écoute (par défaut : 1 lors de l'écoute)</translation> + <translation>Utiliser l'UPnP pour mapper le port d'écoute (par défaut : 1 lors de l'écoute)</translation> </message> <message> <source>Username for JSON-RPC connections</source> @@ -3203,14 +3319,166 @@ par exemple : alertnotify=echo %%s | mail -s "Alerte Bitcoin" admin@foo.com <translation>Erreur lors du chargement de wallet.dat : portefeuille corrompu</translation> </message> <message> + <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source> + <translation>(1 = conserver les métadonnées de transmission, par ex. les informations du propriétaire du compte et de la demande de paiement, 2 = abandonner les métadonnées de transmission)</translation> + </message> + <message> + <source>Flush database activity from memory pool to disk log every <n> megabytes (default: %u)</source> + <translation>Purger l’activité de la base de données de la zone de mémoire vers le journal sur disque tous les <n> mégaoctets (par défaut : %u)</translation> + </message> + <message> + <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source> + <translation>Degré de profondeur de la vérification des blocs -checkblocks (0-4, par défaut : %u)</translation> + </message> + <message> + <source>If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: %u)</source> + <translation>Si paytxfee n'est pas défini, inclure des frais suffisants afin que les transactions soient confirmées en moyenne en n blocs (par défaut : %u)</translation> + </message> + <message> + <source>Log transaction priority and fee per kB when mining blocks (default: %u)</source> + <translation>Lors du minage, journaliser la priorité des transactions et les frais par ko (par défaut : %u) </translation> + </message> + <message> + <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source> + <translation>Maintenir un index complet des transactions, utilisé par l'appel RPC getrawtransaction (obtenir la transaction brute) (par défaut : %u)</translation> + </message> + <message> + <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source> + <translation>Délai en secondes de refus de reconnexion pour les pairs présentant un mauvais comportement (par défaut : %u)</translation> + </message> + <message> + <source>Output debugging information (default: %u, supplying <category> is optional)</source> + <translation>Extraire les informations de débogage (par défaut : %u, fournir <category> est optionnel)</translation> + </message> + <message> + <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> + <translation>Utiliser un serveur mandataire SOCKS5 séparé pour atteindre les pairs par les services cachés de Tor (par défaut : %s)</translation> + </message> + <message> + <source>(default: %s)</source> + <translation>(par défaut : %s)</translation> + </message> + <message> + <source>Acceptable ciphers (default: %s)</source> + <translation>Chiffrements acceptables (par défaut : %s)</translation> + </message> + <message> + <source>Always query for peer addresses via DNS lookup (default: %u)</source> + <translation>Toujours demander les adresses des pairs par recherche DNS (par défaut : %u)</translation> + </message> + <message> + <source>Disable safemode, override a real safe mode event (default: %u)</source> + <translation>Désactiver le mode sans échec, passer outre un événement sans échec réel (par défaut : %u)</translation> + </message> + <message> <source>Error loading wallet.dat</source> <translation>Erreur lors du chargement de wallet.dat</translation> </message> <message> + <source>Force safe mode (default: %u)</source> + <translation>Forcer le mode sans échec (par défaut : %u)</translation> + </message> + <message> + <source>Generate coins (default: %u)</source> + <translation>Générer des pièces (défaut : %u)</translation> + </message> + <message> + <source>How many blocks to check at startup (default: %u, 0 = all)</source> + <translation>Nombre de blocs à vérifier au démarrage (par défaut : %u, 0 = tous)</translation> + </message> + <message> + <source>Include IP addresses in debug output (default: %u)</source> + <translation>Inclure les adresses IP à la sortie de débogage (par défaut : %u)</translation> + </message> + <message> <source>Invalid -proxy address: '%s'</source> <translation>Adresse -proxy invalide : « %s »</translation> </message> <message> + <source>Limit size of signature cache to <n> entries (default: %u)</source> + <translation>Limiter la taille du cache des signatures à <n> entrées (par défaut : %u)</translation> + </message> + <message> + <source>Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)</source> + <translation>Écouter les connexions JSON-RPC sur <port> (par défaut : %u ou tesnet : %u)</translation> + </message> + <message> + <source>Listen for connections on <port> (default: %u or testnet: %u)</source> + <translation>Écouter les connexions sur <port> (par défaut : %u ou tesnet : %u)</translation> + </message> + <message> + <source>Maintain at most <n> connections to peers (default: %u)</source> + <translation>Garder au plus <n> connexions avec les pairs (par défaut : %u)</translation> + </message> + <message> + <source>Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)</source> + <translation>Tampon maximal de réception par connexion, <n>*1000 octets (par défaut : %u)</translation> + </message> + <message> + <source>Maximum per-connection send buffer, <n>*1000 bytes (default: %u)</source> + <translation>Tampon maximal d'envoi par connexion », <n>*1000 octets (par défaut : %u)</translation> + </message> + <message> + <source>Only accept block chain matching built-in checkpoints (default: %u)</source> + <translation>N'accepter qu'une chaîne de blocs correspondant aux points de vérification intégrés (par défaut : %u)</translation> + </message> + <message> + <source>Prepend debug output with timestamp (default: %u)</source> + <translation>Ajouter l'horodatage au début de la sortie de débogage (par défaut : %u)</translation> + </message> + <message> + <source>Print block tree on startup (default: %u)</source> + <translation>Imprimer l'arborescence des blocs au démarrage (par défaut : %u)</translation> + </message> + <message> + <source>Relay and mine data carrier transactions (default: %u)</source> + <translation>Relayer et miner les transactions du porteur de données (par défaut : %u)</translation> + </message> + <message> + <source>Relay non-P2SH multisig (default: %u)</source> + <translation>Relayer les multisignatures non-P2SH (par défaut : %u)</translation> + </message> + <message> + <source>Run a thread to flush wallet periodically (default: %u)</source> + <translation>Exécuter une tâche pour purger le portefeuille périodiquement (par défaut : %u) </translation> + </message> + <message> + <source>Set key pool size to <n> (default: %u)</source> + <translation>Définir la taille de la réserve de clefs à <n> (par défaut : %u)</translation> + </message> + <message> + <source>Set minimum block size in bytes (default: %u)</source> + <translation>Définir la taille de bloc minimale en octets (par défaut : %u)</translation> + </message> + <message> + <source>Sets the DB_PRIVATE flag in the wallet db environment (default: %u)</source> + <translation>Définit le drapeau DB_PRIVATE dans l'environnement de la BD du portefeuille (par défaut : %u)</translation> + </message> + <message> + <source>Specify configuration file (default: %s)</source> + <translation>Spécifier le fichier de configuration (par défaut : %s)</translation> + </message> + <message> + <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source> + <translation>Spécifier le délai d'expiration de la connexion en millisecondes (minimum : 1, par défaut : %d)</translation> + </message> + <message> + <source>Specify pid file (default: %s)</source> + <translation>Spécifier le fichier pid (par défaut : %s)</translation> + </message> + <message> + <source>Spend unconfirmed change when sending transactions (default: %u)</source> + <translation>Dépenser la monnaie non confirmée lors de l'envoi de transactions (par défaut : %u)</translation> + </message> + <message> + <source>Stop running after importing blocks from disk (default: %u)</source> + <translation>Cesser l'exécution après l'importation des blocs du disque (par défaut : %u)</translation> + </message> + <message> + <source>Threshold for disconnecting misbehaving peers (default: %u)</source> + <translation>Seuil de déconnexion des pairs présentant un mauvais comportement (par défaut : %u)</translation> + </message> + <message> <source>Unknown network specified in -onlynet: '%s'</source> <translation>Réseau inconnu spécifié sur -onlynet : « %s »</translation> </message> diff --git a/src/qt/locale/bitcoin_fr_CA.ts b/src/qt/locale/bitcoin_fr_CA.ts index 56be717a8d..eae0b00b76 100644 --- a/src/qt/locale/bitcoin_fr_CA.ts +++ b/src/qt/locale/bitcoin_fr_CA.ts @@ -1,4 +1,4 @@ -<TS language="fr_CA" version="2.1"> +<TS language="fr_CA" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -77,10 +77,6 @@ <context> <name>CoinControlDialog</name> <message> - <source>Address</source> - <translation>Addresse</translation> - </message> - <message> <source>(no label)</source> <translation>(pas de record)</translation> </message> diff --git a/src/qt/locale/bitcoin_gl.ts b/src/qt/locale/bitcoin_gl.ts index 8d9295e5c9..2252baec73 100644 --- a/src/qt/locale/bitcoin_gl.ts +++ b/src/qt/locale/bitcoin_gl.ts @@ -1,4 +1,4 @@ -<TS language="gl" version="2.1"> +<TS language="gl" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -513,10 +513,6 @@ Dirección: %4 <translation>Cantidade</translation> </message> <message> - <source>Address</source> - <translation>Dirección</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> @@ -819,14 +815,6 @@ Dirección: %4 <translation>&Principal</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Tarifa por kB de transacción opcional que axuda a asegurar que as túas transaccións son procesadas rapidamente. A maioría das transaccións son 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Pagar &tarifa da transacción</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Comezar Bitcoin automáticamente despois de loguearse no sistema.</translation> </message> diff --git a/src/qt/locale/bitcoin_gu_IN.ts b/src/qt/locale/bitcoin_gu_IN.ts index b7b091aa39..ef99b0dd39 100644 --- a/src/qt/locale/bitcoin_gu_IN.ts +++ b/src/qt/locale/bitcoin_gu_IN.ts @@ -1,4 +1,4 @@ -<TS language="gu_IN" version="2.1"> +<TS language="gu_IN" version="2.0"> <context> <name>AddressBookPage</name> </context> diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts index 8c05228dbf..b547058986 100644 --- a/src/qt/locale/bitcoin_he.ts +++ b/src/qt/locale/bitcoin_he.ts @@ -1,4 +1,4 @@ -<TS language="he" version="2.1"> +<TS language="he" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -508,10 +508,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>בחירת כתובת שליטה במטבעות</translation> - </message> - <message> <source>Quantity:</source> <translation>כמות:</translation> </message> @@ -560,10 +556,6 @@ Address: %4 <translation>כמות</translation> </message> <message> - <source>Address</source> - <translation>כתובת</translation> - </message> - <message> <source>Date</source> <translation>תאריך</translation> </message> @@ -922,14 +914,6 @@ Address: %4 <translation>&ראשי</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>עמלת העברה כרשות לכל ק״ב תבטיח שההעברה שלך תעובד בזריזות. רוב ההעברות הן בנפח של ק״ב אחד.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>תשלום &עמלת העברה</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>הפעלת ביטקוין אוטומטית לאחר כניסה למערכת.</translation> </message> @@ -958,14 +942,6 @@ Address: %4 <translation>לאפשר חיבורים נכנסים</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>התחברות לרשת ביטקוין דרך מתווך SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>הת&חברות באמצעות מתווך SOCKS (מתווך בררת מחדל):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>כתובת ה־IP של המתווך (לדוגמה IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_hi_IN.ts b/src/qt/locale/bitcoin_hi_IN.ts index fcb094703f..09a8392c27 100644 --- a/src/qt/locale/bitcoin_hi_IN.ts +++ b/src/qt/locale/bitcoin_hi_IN.ts @@ -1,4 +1,4 @@ -<TS language="hi_IN" version="2.1"> +<TS language="hi_IN" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -269,10 +269,6 @@ Address: %4 <translation>राशि</translation> </message> <message> - <source>Address</source> - <translation>पता</translation> - </message> - <message> <source>Date</source> <translation>taareek</translation> </message> diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts index 794a7167e3..22831a0fd5 100644 --- a/src/qt/locale/bitcoin_hr.ts +++ b/src/qt/locale/bitcoin_hr.ts @@ -1,4 +1,4 @@ -<TS language="hr" version="2.1"> +<TS language="hr" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -477,10 +477,6 @@ Adresa:%4 <translation>Iznos</translation> </message> <message> - <source>Address</source> - <translation>Adresa</translation> - </message> - <message> <source>Date</source> <translation>Datum</translation> </message> @@ -615,10 +611,6 @@ Adresa:%4 <translation>&Glavno</translation> </message> <message> - <source>Pay transaction &fee</source> - <translation>Plati &naknadu za transakciju</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Automatski pokreni Bitcoin kad se uključi računalo</translation> </message> diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts index 1edd2511eb..8109542405 100644 --- a/src/qt/locale/bitcoin_hu.ts +++ b/src/qt/locale/bitcoin_hu.ts @@ -1,4 +1,4 @@ -<TS language="hu" version="2.1"> +<TS language="hu" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -521,10 +521,6 @@ Cím: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Ellenőrző cím kiválasztása</translation> - </message> - <message> <source>Quantity:</source> <translation>Mennyiség:</translation> </message> @@ -573,10 +569,6 @@ Cím: %4 <translation>Összeg</translation> </message> <message> - <source>Address</source> - <translation>Cím</translation> - </message> - <message> <source>Date</source> <translation>Dátum</translation> </message> @@ -916,14 +908,6 @@ Cím: %4 <translation>&Fő</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Opcionális, kB-onkénti tranzakciós díj a tranzakcióid minél gyorsabb feldolgozásának elősegítésére. A legtöbb tranzakció 1 kB-os.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Tranzakciós &díj fizetése</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Induljon el a Bitcoin a számítógép bekapcsolásakor</translation> </message> @@ -936,10 +920,6 @@ Cím: %4 <translation>MB</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>SOCKS proxyn keresztüli csatlakozás a Bitcoin hálózatához.</translation> - </message> - <message> <source>Reset all client options to default.</source> <translation>Minden kliensbeállítás alapértelmezettre állítása.</translation> </message> diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts index 6056c3a736..ea2750ed08 100644 --- a/src/qt/locale/bitcoin_id_ID.ts +++ b/src/qt/locale/bitcoin_id_ID.ts @@ -1,4 +1,4 @@ -<TS language="id_ID" version="2.1"> +<TS language="id_ID" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -505,10 +505,6 @@ Alamat: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Pilihan alamat pengaturan koin</translation> - </message> - <message> <source>Quantity:</source> <translation>Kuantitas:</translation> </message> @@ -553,10 +549,6 @@ Alamat: %4 <translation>Nilai</translation> </message> <message> - <source>Address</source> - <translation>Alamat</translation> - </message> - <message> <source>Date</source> <translation>Tanggal</translation> </message> @@ -891,14 +883,6 @@ Alamat: %4 <translation>&Utama</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Biaya transaksi untuk setiap kB yang membantu transaksi Andi diproses cepat (biayanya opsional). Ukuran transaksi biasanya 1kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Bayar &biaya transaksi</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Menyalakan Bitcoin secara otomatis setelah masuk ke dalam sistem.</translation> </message> @@ -911,14 +895,6 @@ Alamat: %4 <translation>MB</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Menghubungkan jaringan Bitcoin lewat proxy SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Hubungkan melalui proxy SOCKS (proxy biasa):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Alamat IP proxy (cth. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts index ddc7e44c47..5dbe98b0f8 100644 --- a/src/qt/locale/bitcoin_it.ts +++ b/src/qt/locale/bitcoin_it.ts @@ -1,4 +1,4 @@ -<TS language="it" version="2.1"> +<TS language="it" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -522,10 +522,6 @@ Indirizzo: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Selezione Indirizzo Coin Control</translation> - </message> - <message> <source>Quantity:</source> <translation>Quantità:</translation> </message> @@ -574,10 +570,6 @@ Indirizzo: %4 <translation>Importo</translation> </message> <message> - <source>Address</source> - <translation>Indirizzo</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> @@ -944,14 +936,6 @@ Indirizzo: %4 <translation>&Principale</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Commissione di transazione per kB: è opzionale e contribuisce ad assicurare che le transazioni siano elaborate velocemente. La maggior parte della transazioni ha dimensioni pari a 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Paga la &commissione</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Avvia automaticamente Bitcoin una volta effettuato l'accesso al sistema.</translation> </message> @@ -980,14 +964,6 @@ Indirizzo: %4 <translation>Permetti connessioni in entrata</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Connessione alla rete Bitcoin attraverso un proxy SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Connessione attraverso proxy SOCKS (proxy predefinito):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Indirizzo IP del proxy (es: IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1208,6 +1184,10 @@ Più URL vengono separati da una barra verticale |.</translation> <translation>Transazioni non confermate su indirizzi di sola lettura</translation> </message> <message> + <source>Mined balance in watch-only addresses that has not yet matured</source> + <translation>l'equilibrio estratto solo nello sguardo degli indirizzi non è ancora maturo </translation> + </message> + <message> <source>out of sync</source> <translation>non sincronizzato</translation> </message> @@ -1471,6 +1451,14 @@ Più URL vengono separati da una barra verticale |.</translation> <translation>Blocco di partenza</translation> </message> <message> + <source>Sync Height</source> + <translation>valore di sincronizzazione</translation> + </message> + <message> + <source>Ban Score</source> + <translation>divieto di segnalazione </translation> + </message> + <message> <source>Connection Time</source> <translation>Tempo di connessione</translation> </message> @@ -1590,7 +1578,11 @@ Più URL vengono separati da una barra verticale |.</translation> <source>Unknown</source> <translation>Sconosciuto</translation> </message> - </context> + <message> + <source>Fetching...</source> + <translation>attraente</translation> + </message> +</context> <context> <name>ReceiveCoinsDialog</name> <message> diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts index c6ba60ec48..dd2d8c8c72 100644 --- a/src/qt/locale/bitcoin_ja.ts +++ b/src/qt/locale/bitcoin_ja.ts @@ -1,4 +1,4 @@ -<TS language="ja" version="2.1"> +<TS language="ja" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -524,10 +524,6 @@ Address: %4 <translation>総額</translation> </message> <message> - <source>Address</source> - <translation>アドレス</translation> - </message> - <message> <source>Date</source> <translation>日付</translation> </message> @@ -774,14 +770,6 @@ Address: %4 <translation>メイン (&M)</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>あたなの取引が早く処理されるように任意で kB 毎の取引手数料を設定します。ほとんどの取引は 1 kB です。</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>支払う取引手数料 (&f)</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>システムにログインした時に自動的に Bitcoin を起動します。</translation> </message> diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts index 5a566d4445..3faad159ad 100644 --- a/src/qt/locale/bitcoin_ka.ts +++ b/src/qt/locale/bitcoin_ka.ts @@ -1,4 +1,4 @@ -<TS language="ka" version="2.1"> +<TS language="ka" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -485,10 +485,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>მონეტების კონტროლის მისამართის არჩევა</translation> - </message> - <message> <source>Quantity:</source> <translation>რაოდენობა:</translation> </message> @@ -533,10 +529,6 @@ Address: %4 <translation>თანხა</translation> </message> <message> - <source>Address</source> - <translation>მისამართი</translation> - </message> - <message> <source>Date</source> <translation>თარიღი</translation> </message> @@ -879,14 +871,6 @@ Address: %4 <translation>&მთავარი</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>დამატებითი საკომისიო თითო კილობაიტზე; აჩქარებს ტრანსაქციის შესრულებას. ტრანსაქციების უმეტესობა არის 1 კბ.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>ტრანსაქციის სა&ფასურის გადახდა</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>სისტემაში შესვლის შემდეგ Bitcoin-ის ავტომატური გაშვება.</translation> </message> @@ -907,14 +891,6 @@ Address: %4 <translation>სკრიპტის &ვერიფიცირების ნაკადების რაოდენობა</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Bitcoin-ქსელზე მიერთება SOCKS-პროქსით.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>SO&CKS (ნაგულისხმევი) პროქსი მიერთებისათვის:</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>პროქსის IP-მისამართი (მაგ.: IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_kk_KZ.ts b/src/qt/locale/bitcoin_kk_KZ.ts index e9eddd503c..3d38b00217 100644 --- a/src/qt/locale/bitcoin_kk_KZ.ts +++ b/src/qt/locale/bitcoin_kk_KZ.ts @@ -1,4 +1,4 @@ -<TS language="kk_KZ" version="2.1"> +<TS language="kk_KZ" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -85,10 +85,6 @@ <context> <name>CoinControlDialog</name> <message> - <source>Address</source> - <translation>Адрес</translation> - </message> - <message> <source>(no label)</source> <translation>(таңбасыз)</translation> </message> diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts index a8a2fbd16a..efc41ec6b7 100644 --- a/src/qt/locale/bitcoin_ko_KR.ts +++ b/src/qt/locale/bitcoin_ko_KR.ts @@ -1,4 +1,4 @@ -<TS language="ko_KR" version="2.1"> +<TS language="ko_KR" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -505,10 +505,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>코인 컨트롤 주소 선택</translation> - </message> - <message> <source>Quantity:</source> <translation>수량:</translation> </message> @@ -557,10 +553,6 @@ Address: %4 <translation>거래량</translation> </message> <message> - <source>Address</source> - <translation>주소</translation> - </message> - <message> <source>Date</source> <translation>날짜</translation> </message> @@ -895,14 +887,6 @@ Address: %4 <translation>메인(&M)</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>당신의 거래가 더욱 빠르게 처리될 수 있도록 선택적으로 kBd당 거래 수수료를 지정합니다. 참고로 대부분의 거래들은 1kB입니다.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>송금 수수료(&F)</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>시스템 로그인후에 비트코인을 자동으로 시작합니다.</translation> </message> @@ -931,14 +915,6 @@ Address: %4 <translation>연결 요청을 허용합니다.</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>SOCKS 프록시를 통해 비트코인 네트워크 연결</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>SOCKS 프록시를 거쳐 연결합니다 (기본값 프록시):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>프록시 아이피 주소(예. IPv4:127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1728,6 +1704,10 @@ Address: %4 <translation>사용된 주소 목록에 새 주소를 추가하기 위해 제목을 입력합니다. </translation> </message> <message> + <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source> + <translation>비트코인에 첨부된 메시지: 참고용으로 거래와 함께 저장될 URI. 메모: 이 메시지는 비트코인 네트워크로 전송되지 않습니다.</translation> + </message> + <message> <source>This is an unverified payment request.</source> <translation>지급요청 미확인입니다</translation> </message> @@ -2469,6 +2449,10 @@ Address: %4 <translation>어떤 포트도 반응하지 않습니다. 사용자 반응=0 만약 원한다면</translation> </message> <message> + <source>If <category> is not supplied, output all debugging information.</source> + <translation><카테고리>가 제공되지 않을 경우, 모든 디버깅 정보를 출력</translation> + </message> + <message> <source>Importing...</source> <translation>들여오기 중...</translation> </message> diff --git a/src/qt/locale/bitcoin_ky.ts b/src/qt/locale/bitcoin_ky.ts index 91b3ccaf10..ed7542261c 100644 --- a/src/qt/locale/bitcoin_ky.ts +++ b/src/qt/locale/bitcoin_ky.ts @@ -1,4 +1,4 @@ -<TS language="ky" version="2.1"> +<TS language="ky" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -73,10 +73,6 @@ <context> <name>CoinControlDialog</name> <message> - <source>Address</source> - <translation>Дарек</translation> - </message> - <message> <source>Date</source> <translation>Дата</translation> </message> diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts index cc43762310..c399f36159 100644 --- a/src/qt/locale/bitcoin_la.ts +++ b/src/qt/locale/bitcoin_la.ts @@ -1,4 +1,4 @@ -<TS language="la" version="2.1"> +<TS language="la" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -417,10 +417,6 @@ Inscriptio: %4 <translation>Quantitas</translation> </message> <message> - <source>Address</source> - <translation>Inscriptio</translation> - </message> - <message> <source>Date</source> <translation>Dies</translation> </message> @@ -563,14 +559,6 @@ Inscriptio: %4 <translation>&Princeps</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Optionalis merces transactionum singulis kB quae adiuvat curare tuas transactiones processas esse celeriter. Plurimi transactiones 1kB sunt.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Solve &mercedem transactionis</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Pelle Bitcoin per se postquam in systema inire.</translation> </message> diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts index b195a75d0f..1f70400df6 100644 --- a/src/qt/locale/bitcoin_lt.ts +++ b/src/qt/locale/bitcoin_lt.ts @@ -1,4 +1,4 @@ -<TS language="lt" version="2.1"> +<TS language="lt" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -476,10 +476,6 @@ Adresas: %4</translation> <translation>Suma</translation> </message> <message> - <source>Address</source> - <translation>Adresas</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> @@ -706,10 +702,6 @@ Adresas: %4</translation> <translation>&Pagrindinės</translation> </message> <message> - <source>Pay transaction &fee</source> - <translation>&Mokėti sandorio mokestį</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Automatiškai paleisti Bitkoin programą įjungus sistemą.</translation> </message> diff --git a/src/qt/locale/bitcoin_lv_LV.ts b/src/qt/locale/bitcoin_lv_LV.ts index f901b14d36..ac5a1a1396 100644 --- a/src/qt/locale/bitcoin_lv_LV.ts +++ b/src/qt/locale/bitcoin_lv_LV.ts @@ -1,4 +1,4 @@ -<TS language="lv_LV" version="2.1"> +<TS language="lv_LV" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -275,6 +275,10 @@ <translation>Atvērt &URI...</translation> </message> <message> + <source>Bitcoin Core client</source> + <translation>Bitcoin Core klients</translation> + </message> + <message> <source>Importing blocks from disk...</source> <translation>Importē blokus no diska...</translation> </message> @@ -324,7 +328,11 @@ </message> <message> <source>&Receive</source> - <translation>Saņe&mt</translation> + <translation>&Saņemt</translation> + </message> + <message> + <source>Show information about Bitcoin Core</source> + <translation>Parādīt informāciju par Bitcoin Core</translation> </message> <message> <source>&Show / Hide</source> @@ -477,10 +485,6 @@ Adrese: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Bitcoin Kontroles Adrešu Atlase</translation> - </message> - <message> <source>Quantity:</source> <translation>Daudzums:</translation> </message> @@ -525,10 +529,6 @@ Adrese: %4 <translation>Daudzums</translation> </message> <message> - <source>Address</source> - <translation>Adrese</translation> - </message> - <message> <source>Date</source> <translation>Datums</translation> </message> @@ -827,10 +827,6 @@ Adrese: %4 <translation>&Galvenais</translation> </message> <message> - <source>Pay transaction &fee</source> - <translation>&Maksāt par transakciju</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Automātiski sākt Bitcoin pēc pieteikšanās sistēmā.</translation> </message> @@ -851,14 +847,6 @@ Adrese: %4 <translation>Skriptu &pārbaudes pavedienu skaits</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Savienoties ar Bitcoin tīklu caur SOCKS starpniekserveri.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Savienoties caur SOCKS starpniekserveri (noklusējuma starpniekserveris)</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Starpniekservera IP adrese (piem. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_mn.ts b/src/qt/locale/bitcoin_mn.ts index 515d1b90df..f1b0174111 100644 --- a/src/qt/locale/bitcoin_mn.ts +++ b/src/qt/locale/bitcoin_mn.ts @@ -1,4 +1,4 @@ -<TS language="mn" version="2.1"> +<TS language="mn" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -288,10 +288,6 @@ Address: %4 <translation>Хэмжээ</translation> </message> <message> - <source>Address</source> - <translation>Хаяг</translation> - </message> - <message> <source>Date</source> <translation>Огноо</translation> </message> @@ -402,10 +398,6 @@ Address: %4 <translation>МБ</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Биткойны сүлжээрүү SOCKS проксигоор холбогдох.</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>проксигийн IP хаяг (жишээ нь: IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_ms_MY.ts b/src/qt/locale/bitcoin_ms_MY.ts index 47e74111c2..d2e8efbb49 100644 --- a/src/qt/locale/bitcoin_ms_MY.ts +++ b/src/qt/locale/bitcoin_ms_MY.ts @@ -1,4 +1,4 @@ -<TS language="ms_MY" version="2.1"> +<TS language="ms_MY" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -72,10 +72,6 @@ </context> <context> <name>CoinControlDialog</name> - <message> - <source>Address</source> - <translation>Alamat</translation> - </message> </context> <context> <name>EditAddressDialog</name> diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts index 435a412d09..bdde3da534 100644 --- a/src/qt/locale/bitcoin_nb.ts +++ b/src/qt/locale/bitcoin_nb.ts @@ -1,4 +1,4 @@ -<TS language="nb" version="2.1"> +<TS language="nb" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -525,8 +525,8 @@ Adresse: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Myntkontroll Adresse Valg</translation> + <source>Coin Selection</source> + <translation>Mynt Valg</translation> </message> <message> <source>Quantity:</source> @@ -577,8 +577,12 @@ Adresse: %4 <translation>Beløp</translation> </message> <message> - <source>Address</source> - <translation>Adresse</translation> + <source>Received with label</source> + <translation>Mottatt med merkelapp</translation> + </message> + <message> + <source>Received with address</source> + <translation>Mottatt med adresse</translation> </message> <message> <source>Date</source> @@ -955,14 +959,6 @@ Adresse: %4 <translation>&Hoved</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Valgfritt transaksjonsgebyr per kB som sikrer at dine transaksjoner blir raskt prosessert. De fleste transaksjoner er 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Betal &transaksjonsgebyr</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Start Bitcoin automatisk etter innlogging.</translation> </message> @@ -991,14 +987,6 @@ Adresse: %4 <translation>Tillatt innkommende tilkoblinger</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Koble til Bitcoin-nettverket gjennom en SOCKS proxy.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Koble til gjennom SOCKS proxy (standardvalg proxy):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>IP-adressen til proxyen (f.eks. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1059,6 +1047,14 @@ Adresse: %4 <translation>Sett opp port ved hjelp av &UPnP</translation> </message> <message> + <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> + <translation>Koble til Bitcoin-nettverket gjennom en SOCKS5 proxy.</translation> + </message> + <message> + <source>&Connect through SOCKS5 proxy (default proxy):</source> + <translation>&Koble til gjennom SOCKS5 proxy (standardvalg proxy):</translation> + </message> + <message> <source>Proxy &IP:</source> <translation>Proxy &IP:</translation> </message> @@ -1849,6 +1845,78 @@ Adresse: %4 <translation>Egendefinert adresse for veksel</translation> </message> <message> + <source>Transaction Fee:</source> + <translation>Transaksjonsgebyr:</translation> + </message> + <message> + <source>Choose...</source> + <translation>Velg...</translation> + </message> + <message> + <source>collapse fee-settings</source> + <translation>Legg ned gebyrinnstillinger</translation> + </message> + <message> + <source>Minimize</source> + <translation>Minimer</translation> + </message> + <message> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation>Hvis den egendefinerte avgiften er satt til 1000 satoshis og transaksjonen bare er 250 bytes, da vil "per kilobyte" bare betale 250 satoshis i gebyr, mens "minst" betaler 1000 satoshis. For transaksjoner større enn en kilobyte vil begge betale for antall kilobyte.</translation> + </message> + <message> + <source>per kilobyte</source> + <translation>per kilobyte</translation> + </message> + <message> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation>Hvis den egendefinerte avgiften er satt til 1000 satoshis og transaksjonen bare er 250 bytes, da vil "per kilobyte" bare betale 250 satoshis i gebyr, mens "minstebeløp" betaler 1000 satoshis. For transaksjoner større enn en kilobyte vil begge betale for antall kilobyte.</translation> + </message> + <message> + <source>total at least</source> + <translation>minstebeløp</translation> + </message> + <message> + <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> + <translation>Betaling av bare minimumsavgiften går helt fint så lenge det er mindre transaksjonsvolum enn plass i blokkene. Men vær klar over at dette kan ende opp i en transaksjon som aldri blir bekreftet når det er mer etterspørsel etter Bitcoin-transaksjoner enn nettverket kan behandle.</translation> + </message> + <message> + <source>(read the tooltip)</source> + <translation>(les verktøytipset)</translation> + </message> + <message> + <source>Recommended:</source> + <translation>Anbefalt:</translation> + </message> + <message> + <source>Custom:</source> + <translation>Egendefinert:</translation> + </message> + <message> + <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source> + <translation>(Smartgebyr ikke innført ennå. Dette tar vanligvis noen blokker...)</translation> + </message> + <message> + <source>Confirmation time:</source> + <translation>Bekreftelsestid:</translation> + </message> + <message> + <source>normal</source> + <translation>normal</translation> + </message> + <message> + <source>fast</source> + <translation>rask</translation> + </message> + <message> + <source>Send as zero-fee transaction if possible</source> + <translation>Send uten transaksjonsgebyr hvis mulig</translation> + </message> + <message> + <source>(confirmation may take longer)</source> + <translation>(bekreftelse kan ta lengre tid)</translation> + </message> + <message> <source>Send to multiple recipients at once</source> <translation>Send til flere enn en mottaker</translation> </message> @@ -1953,6 +2021,18 @@ Adresse: %4 <translation>Transaksjonen ble avvist! Dette kan skje hvis noen av myntene i lommeboken allerede er brukt, som hvis du kopierte wallet.dat og mynter ble brukt i kopien uten å bli markert som brukt her.</translation> </message> <message> + <source>A fee higher than %1 is considered an insanely high fee.</source> + <translation>Et gebyr høyere enn %1 er ansett som et sinnsykt høyt gebyr.</translation> + </message> + <message> + <source>Pay only the minimum fee of %1</source> + <translation>Betal kun minimumsgebyret på %1</translation> + </message> + <message> + <source>Estimated to begin confirmation within %1 block(s).</source> + <translation>Beregner å begynne bekreftelse innen %1 blokk(er).</translation> + </message> + <message> <source>Warning: Invalid Bitcoin address</source> <translation>Advarsel: Ugyldig Bitcoin-adresse</translation> </message> @@ -2758,6 +2838,10 @@ For eksempel: varselmelding=echo %%s | mail -s "Bitcoin Varsel" admin@foo.com</t <translation>Slett alle transaksjoner i lommeboken og gjenopprett kun de delene av blokkjeden gjennom -rescan ved oppstart</translation> </message> <message> + <source>Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> + <translation>Distribuert under MIT programvarelisensen, se medfølgende fil COPYING eller <http://www.opensource.org/licenses/mit-license.php>.</translation> + </message> + <message> <source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly.</source> <translation>Gå til modus for regresjonstesting, som bruker en spesiell blokkjede der blokker kan bli løst momentant.</translation> </message> @@ -2990,10 +3074,6 @@ For eksempel: varselmelding=echo %%s | mail -s "Bitcoin Varsel" admin@foo.com</t <translation>Opprett nye filer med standardtillatelser i systemet, i stedet for umask 077 (kun virksom med lommebokfunksjonalitet slått av)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Distribuert under MIT/X11 programvarelisensen, se medfølgende fil COPYING eller <http://www.opensource.org/licenses/mit-license.php>.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>Feil: Lytting etter innkommende tilkoblinger feilet (lytting returnerte feil %s)</translation> </message> @@ -3014,6 +3094,10 @@ For eksempel: varselmelding=echo %%s | mail -s "Bitcoin Varsel" admin@foo.com</t <translation>Gebyrer (i BTC/Kb) mindre enn dette anses som null gebyr for laging av transaksjoner (standardverdi: %s)</translation> </message> <message> + <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source> + <translation>Maksimal størrelse på data i databærende transaksjoner vi videresender og ufører graving på (standardverdi: %u)</translation> + </message> + <message> <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source> <translation>Søk etter nodeadresser via DNS-oppslag, hvis vi har få adresser å koble til (standard: 1 med mindre -connect)</translation> </message> @@ -3022,6 +3106,10 @@ For eksempel: varselmelding=echo %%s | mail -s "Bitcoin Varsel" admin@foo.com</t <translation>Sett maksimum størrelse for transaksjoner med høy prioritet / lavt gebyr, i bytes (standardverdi: %d)</translation> </message> <message> + <source>Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)</source> + <translation>Angi antall tråder for mynt generering hvis aktivert (-1 = alle kjerner, standardverdi: %d)</translation> + </message> + <message> <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source> <translation>Dette produktet inneholder programvare utviklet av OpenSSL Project for bruk i OpenSSL Toolkit <https://www.openssl.org/> og kryptografisk programvare skrevet av Eric Young og UPnP-programvare skrevet av Thomas Bernard.</translation> </message> @@ -3126,6 +3214,10 @@ For eksempel: varselmelding=echo %%s | mail -s "Bitcoin Varsel" admin@foo.com</t <translation>Send spor-/feilsøkingsinformasjon til konsollen istedenfor filen debug.log</translation> </message> <message> + <source>Send transactions as zero-fee transactions if possible (default: %u)</source> + <translation>Send transaksjoner uten transaksjonsgebyr hvis mulig (standardverdi: %u)</translation> + </message> + <message> <source>Show all debugging options (usage: --help -help-debug)</source> <translation>Vis alle feilsøkingsvalg (bruk: --help -help-debug)</translation> </message> @@ -3266,10 +3358,6 @@ For eksempel: varselmelding=echo %%s | mail -s "Bitcoin Varsel" admin@foo.com</t <translation>Ta ut feilsøkingsinformasjon (standardverdi: %u, bruk av <category> er valgfritt)</translation> </message> <message> - <source>Set the processor limit for when generation is on (-1 = unlimited, default: %d)</source> - <translation>Sett prosessorgrensen for når blokkutvinning er på (-1 = ubegrenset, standardverdi: %d)</translation> - </message> - <message> <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> <translation>Bruk separate SOCKS5 proxyer for å nå noder via Tor skjulte tjenester (standardverdi: %s)</translation> </message> diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts index fb81042d8e..e57362d7fd 100644 --- a/src/qt/locale/bitcoin_nl.ts +++ b/src/qt/locale/bitcoin_nl.ts @@ -1,4 +1,4 @@ -<TS language="nl" version="2.1"> +<TS language="nl" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -184,6 +184,10 @@ <translation>Portemonnee versleuteld</translation> </message> <message> + <source>Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>.</source> + <translation>Vul een nieuw </translation> + </message> + <message> <source>Bitcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source> <translation>Bitcoin zal nu afsluiten om het versleutelingsproces te voltooien. Onthoud dat het versleutelen van uw portemonnee u niet volledig kan beschermen: Malware kan uw computer infecteren en uw bitcoins stelen.</translation> </message> @@ -517,10 +521,6 @@ Adres: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Coin controle adres selectie</translation> - </message> - <message> <source>Quantity:</source> <translation>Kwantiteit</translation> </message> @@ -569,10 +569,6 @@ Adres: %4 <translation>Bedrag</translation> </message> <message> - <source>Address</source> - <translation>Adres</translation> - </message> - <message> <source>Date</source> <translation>Datum</translation> </message> @@ -943,14 +939,6 @@ Adres: %4 <translation>&Algemeen</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Optionele transactiekosten per kB. Transactiekosten helpen ervoor te zorgen dat uw transacties snel verwerkt worden. De meeste transacties zijn 1kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Betaal &transactiekosten</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Start Bitcoin automatisch na inloggen in het systeem</translation> </message> @@ -979,14 +967,6 @@ Adres: %4 <translation>Sta inkomende verbindingen toe</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Verbind met het Bitcoin-netwerk via een SOCKS-proxy.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Verbind via een SOCKS-proxy (standaardproxy):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>IP-adres van de proxy (bijv. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1150,6 +1130,10 @@ Adres: %4 <translation>De weergegeven informatie kan verouderd zijn. Uw portemonnee synchroniseert automaticsh met het Bitcoinnetwerk nadat een verbinding is gelegd, maar dit proces is nog niet voltooid.</translation> </message> <message> + <source>Watch-only:</source> + <translation>Alleen-bekijkbaar:</translation> + </message> + <message> <source>Available:</source> <translation>Beschikbaar:</translation> </message> diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts index c42cc73484..b0a92a1578 100644 --- a/src/qt/locale/bitcoin_pam.ts +++ b/src/qt/locale/bitcoin_pam.ts @@ -1,4 +1,4 @@ -<TS language="pam" version="2.1"> +<TS language="pam" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -389,10 +389,6 @@ Address: %4 <translation>Alaga</translation> </message> <message> - <source>Address</source> - <translation>Address</translation> - </message> - <message> <source>Date</source> <translation>Kaaldauan</translation> </message> @@ -535,10 +531,6 @@ Address: %4 <translation>&Pun</translation> </message> <message> - <source>Pay transaction &fee</source> - <translation>Mamayad &bayad para king transaksion </translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Umpisan yang antimu ing Bitcoin kaibat mekapag-log in king sistema.</translation> </message> diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts index 25d04a0d49..c53a9970ef 100644 --- a/src/qt/locale/bitcoin_pl.ts +++ b/src/qt/locale/bitcoin_pl.ts @@ -1,4 +1,4 @@ -<TS language="pl" version="2.1"> +<TS language="pl" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -557,10 +557,6 @@ Adres: %4 <translation>Kwota</translation> </message> <message> - <source>Address</source> - <translation>Adres</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> @@ -915,14 +911,6 @@ Adres: %4 <translation>Główne</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Opcjonalna prowizja za transakcje za kB, wspomaga ona szybkość przebiegu transakcji. Większość transakcji jest 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Płać prowizję za transakcje</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Automatycznie uruchamia Bitcoin po zalogowaniu do systemu.</translation> </message> @@ -947,10 +935,6 @@ Adres: %4 <translation>Zezwól na połączenia przychodzące</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Połącz się z siecią Bitcoin poprzez SOCKS proxy.</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Adres IP serwera proxy (np. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts index cbd730bde4..65f07ca59c 100644 --- a/src/qt/locale/bitcoin_pt_BR.ts +++ b/src/qt/locale/bitcoin_pt_BR.ts @@ -1,4 +1,4 @@ -<TS language="pt_BR" version="2.1"> +<TS language="pt_BR" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -520,10 +520,6 @@ Endereço: %4</translation> <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Coin Control Address Selection</translation> - </message> - <message> <source>Quantity:</source> <translation>Quantidade:</translation> </message> @@ -572,10 +568,6 @@ Endereço: %4</translation> <translation>Quantidade</translation> </message> <message> - <source>Address</source> - <translation>Endereço</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> @@ -907,7 +899,15 @@ Endereço: %4</translation> <source>Error</source> <translation>Erro</translation> </message> - </context> + <message numerus="yes"> + <source>%n GB of free space available</source> + <translation><numerusform>%n GB de espaço livre disponível</numerusform><numerusform>%n GB de espaço livre disponível</numerusform></translation> + </message> + <message numerus="yes"> + <source>(of %n GB needed)</source> + <translation><numerusform>(de %n GB necessário)</numerusform><numerusform>(de %n GB necessário)</numerusform></translation> + </message> +</context> <context> <name>OpenURIDialog</name> <message> @@ -942,14 +942,6 @@ Endereço: %4</translation> <translation>Principal</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Taxa de transação opcional por kB que ajuda a garantir que suas transações sejam processadas rapidamente. A maioria das transações são de 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Pagar taxa de &transação</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Iniciar Bitcoin automaticamente após se logar no sistema.</translation> </message> @@ -978,14 +970,6 @@ Endereço: %4</translation> <translation>Permitir conexões de entrada</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Conectado na rede do Bitcoin através de proxy SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Conectado via proxy SOCKS (padrão proxy):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Endereço de IP do proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1177,6 +1161,10 @@ Endereço: %4</translation> <translation>Saldo minerado que ainda não maturou</translation> </message> <message> + <source>Balances</source> + <translation>Saldos</translation> + </message> + <message> <source>Total:</source> <translation>Total:</translation> </message> @@ -1189,6 +1177,10 @@ Endereço: %4</translation> <translation>Sua balança atual em endereços apenas visualizados</translation> </message> <message> + <source>Recent transactions</source> + <translation>Transações recentes</translation> + </message> + <message> <source>out of sync</source> <translation>fora de sincronia</translation> </message> diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts index edb1e87b6f..dc016623e4 100644 --- a/src/qt/locale/bitcoin_pt_PT.ts +++ b/src/qt/locale/bitcoin_pt_PT.ts @@ -1,4 +1,4 @@ -<TS language="pt_PT" version="2.1"> +<TS language="pt_PT" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -508,10 +508,6 @@ Endereço: %4</translation> <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Seleção de Endereço Coin Control</translation> - </message> - <message> <source>Quantity:</source> <translation>Quantidade:</translation> </message> @@ -556,10 +552,6 @@ Endereço: %4</translation> <translation>Quantia</translation> </message> <message> - <source>Address</source> - <translation>Endereço</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> @@ -906,14 +898,6 @@ Endereço: %4</translation> <translation>&Principal</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Taxa de transação opcional por KB que ajuda a assegurar que as suas transações serão processadas rapidamente. A maioria das transações tem 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Pagar &taxa de transação</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Começar o Bitcoin automaticamente ao iniciar sessão no sistema.</translation> </message> @@ -934,14 +918,6 @@ Endereço: %4</translation> <translation>Número de processos de &verificação de scripts</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Ligar à rede Bitcoin através de um proxy SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>Ligar através de um proxy SO&CKS (proxy por defeito):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Endereço IP do proxy (p.ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts index a20bc677a0..ccae9482da 100644 --- a/src/qt/locale/bitcoin_ro_RO.ts +++ b/src/qt/locale/bitcoin_ro_RO.ts @@ -1,4 +1,4 @@ -<TS language="ro_RO" version="2.1"> +<TS language="ro_RO" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -501,10 +501,6 @@ Adresa: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Selectare Adresă de Comandă Monedă</translation> - </message> - <message> <source>Quantity:</source> <translation>Cantitate:</translation> </message> @@ -549,10 +545,6 @@ Adresa: %4 <translation>Sumă</translation> </message> <message> - <source>Address</source> - <translation>Adresă</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> @@ -883,14 +875,6 @@ Adresa: %4 <translation>&Principal</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Taxa optionala de tranzactie per kB care ajuta ca tranzactiile dumneavoastra sa fie procesate rapid. Majoritatea tranzactiilor sunt 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Plăteşte comision pentru tranzacţie &f</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Porneşte automat programul Bitcoin la pornirea computerului.</translation> </message> @@ -903,10 +887,6 @@ Adresa: %4 <translation>MB</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Conecteaza-te la reteaua Bitcoin printr-un proxy SOCKS</translation> - </message> - <message> <source>Reset all client options to default.</source> <translation>Resetează toate setările clientului la valorile implicite.</translation> </message> diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index 93c116d0a2..fa66297779 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -1,4 +1,4 @@ -<TS language="ru" version="2.1"> +<TS language="ru" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -521,10 +521,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Выбор адреса контроля монет</translation> - </message> - <message> <source>Quantity:</source> <translation>Количество:</translation> </message> @@ -573,8 +569,12 @@ Address: %4 <translation>Сумма</translation> </message> <message> - <source>Address</source> - <translation>Адрес</translation> + <source>Received with label</source> + <translation>Получено с пометкой</translation> + </message> + <message> + <source>Received with address</source> + <translation>Получено с адреса</translation> </message> <message> <source>Date</source> @@ -951,14 +951,6 @@ Address: %4 <translation>&Главная</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Необязательная комиссия за каждый КБ транзакции, которая ускоряет обработку Ваших транзакций. Большинство транзакций занимают 1КБ.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Заплатить ко&миссию</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Автоматически запускать Bitcoin после входа в систему</translation> </message> @@ -987,14 +979,6 @@ Address: %4 <translation>Разрешить входящие подключения</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Подключаться к сети Bitcoin через прокси SOCKS.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Подключаться через SOCKS прокси (прокси по умолчанию):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>IP-адрес прокси (например IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1055,6 +1039,14 @@ Address: %4 <translation>Пробросить порт через &UPnP</translation> </message> <message> + <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> + <translation>Подключаться к сети Bitcoin через прокси SOCKS5</translation> + </message> + <message> + <source>&Connect through SOCKS5 proxy (default proxy):</source> + <translation>&Подключаться к сети Bitcoin через прокси SOCKS5 (прокси по умолчанию):</translation> + </message> + <message> <source>Proxy &IP:</source> <translation>&IP Прокси: </translation> </message> @@ -1845,6 +1837,54 @@ Address: %4 <translation>Свой адрес для сдачи</translation> </message> <message> + <source>Transaction Fee:</source> + <translation>Комиссия</translation> + </message> + <message> + <source>Choose...</source> + <translation>Выберите...</translation> + </message> + <message> + <source>Minimize</source> + <translation>Сворачивать</translation> + </message> + <message> + <source>per kilobyte</source> + <translation>за килобайт</translation> + </message> + <message> + <source>total at least</source> + <translation>Итого</translation> + </message> + <message> + <source>Recommended:</source> + <translation>Рекомендовано:</translation> + </message> + <message> + <source>Custom:</source> + <translation>Выборочно:</translation> + </message> + <message> + <source>Confirmation time:</source> + <translation>Время подтверждения:</translation> + </message> + <message> + <source>normal</source> + <translation>обычный</translation> + </message> + <message> + <source>fast</source> + <translation>ускоренный</translation> + </message> + <message> + <source>Send as zero-fee transaction if possible</source> + <translation>Осуществить транзакцию бесплатно, если возможно</translation> + </message> + <message> + <source>(confirmation may take longer)</source> + <translation>(подтверждение может занять больше времени)</translation> + </message> + <message> <source>Send to multiple recipients at once</source> <translation>Отправить нескольким получателям одновременно</translation> </message> @@ -1949,6 +1989,14 @@ Address: %4 <translation>Транзакция была отклонена! Такое может произойти, если некоторые монеты уже были потрачены, например, если Вы используете одну копию бумажника (wallet.dat), а монеты были потрачены из другой копии, но не были отмечены как потраченные в этой.</translation> </message> <message> + <source>A fee higher than %1 is considered an insanely high fee.</source> + <translation>Комиссия больше, чем %1, считается невероятно большой.</translation> + </message> + <message> + <source>Estimated to begin confirmation within %1 block(s).</source> + <translation>Ожидается начать подтверждение через %1 блок(ов).</translation> + </message> + <message> <source>Warning: Invalid Bitcoin address</source> <translation>Внимание: неверный адрес Bitcoin</translation> </message> @@ -2803,6 +2851,10 @@ rpcpassword=%s <translation>Внимание: wallet.dat повреждён, данные спасены! Оригинальный wallet.dat сохранён как wallet.{timestamp}.bak в %s; если ваш баланс или транзакции некорректны, вы должны восстановить файл из резервной копии.</translation> </message> <message> + <source>Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.</source> + <translation>Вносить в белый список участников, подключающихся с указанной маски сети или IP. Можно использовать многократно.</translation> + </message> + <message> <source>(default: 1)</source> <translation>(по умолчанию: 1)</translation> </message> @@ -2923,6 +2975,10 @@ rpcpassword=%s <translation>Это рассчитано на инструменты регрессионного тестирования и разработку приложений.</translation> </message> <message> + <source>Use UPnP to map the listening port (default: %u)</source> + <translation>Использовать UPnP для проброса порта (по умолчанию: %u)</translation> + </message> + <message> <source>Verifying blocks...</source> <translation>Проверка блоков...</translation> </message> @@ -2967,12 +3023,12 @@ rpcpassword=%s <translation>Не удалось установить блокировку на каталог данных %s. Возможно, Bitcoin Core уже запущен.</translation> </message> <message> - <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> - <translation>Создавать новые файлы с системными правами по умолчанию вместо umask 077 (эффективно только при отключенном бумажнике)</translation> + <source>Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:%u)</source> + <translation>Ограничить скорость передачи бесплатных транзакций до <n>*1000 байт в минуту (по умолчанию: %u)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Распространяется под лицензией MIT/X11, см. приложенный файл COPYING или <http://www.opensource.org/licenses/mit-license.php>.</translation> + <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> + <translation>Создавать новые файлы с системными правами по умолчанию вместо umask 077 (эффективно только при отключенном бумажнике)</translation> </message> <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> @@ -2995,6 +3051,10 @@ rpcpassword=%s <translation>Комиссии (в BTC/Кб) меньшие этого значения считаются нулевыми для создания транзакции (по умолчанию: %s)</translation> </message> <message> + <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source> + <translation>Наибольший размер данных в носителе данных транзакций, которые мы передаем и генерируем (по умолчанию: %u)</translation> + </message> + <message> <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source> <translation>Запрашивать адреса участников с помощью DNS, если адресов мало (по умолчанию: 1, если не указан -connect)</translation> </message> @@ -3003,6 +3063,10 @@ rpcpassword=%s <translation>Задать максимальный размер высокоприоритетных/низкокомиссионных транзакций в байтах (по умолчанию: %d)</translation> </message> <message> + <source>Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)</source> + <translation>Задать число потоков генерации монет, если включена (-1 = число ядер процессора, по умолчанию: %d)</translation> + </message> + <message> <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source> <translation>Этот продукт включает ПО, разработанное OpenSSL Project для использования в OpenSSL Toolkit <https://www.openssl.org/> и криптографическое ПО, написанное Eric Young и ПО для работы с UPnP, написанное Thomas Bernard.</translation> </message> @@ -3107,6 +3171,10 @@ rpcpassword=%s <translation>Выводить информацию трассировки/отладки на консоль вместо файла debug.log</translation> </message> <message> + <source>Send transactions as zero-fee transactions if possible (default: %u)</source> + <translation>Осуществить транзакцию бесплатно, если возможно (по умолчанию: %u)</translation> + </message> + <message> <source>Show all debugging options (usage: --help -help-debug)</source> <translation>Показать все отладочные параметры (использование: --help -help-debug)</translation> </message> @@ -3215,18 +3283,174 @@ rpcpassword=%s <translation>Ошибка загрузки wallet.dat: Бумажник поврежден</translation> </message> <message> + <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source> + <translation>(1 = сохранять метаданные транзакции: например, владельца аккаунта и информацию запроса платежа; 2 = отбросить метаданные)</translation> + </message> + <message> + <source>Flush database activity from memory pool to disk log every <n> megabytes (default: %u)</source> + <translation>Сбрасывать активность базы данных из памяти на диск каждые <n> мегабайт (по умолчанию: %u)</translation> + </message> + <message> + <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source> + <translation>Насколько тщательна проверка контрольных блоков -checkblocks (0-4, по умолчанию: %u)</translation> + </message> + <message> + <source>If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: %u)</source> + <translation>Если paytxfee не задан, включить достаточную комиссию для подтверждения транзакции в среднем за n блоков (по умолчанию: %u)</translation> + </message> + <message> + <source>Log transaction priority and fee per kB when mining blocks (default: %u)</source> + <translation>Записывать в лог приоритет транзакции и комиссию на килобайт во время добычи блоков (по умолчанию: %u)</translation> + </message> + <message> + <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source> + <translation>Держать полный индекс транзакций, используемый RPC-запросом getrawtransaction (по умолчанию: %u)</translation> + </message> + <message> + <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source> + <translation>Число секунд блокирования неправильно ведущих себя узлов (по умолчанию: %u)</translation> + </message> + <message> + <source>Output debugging information (default: %u, supplying <category> is optional)</source> + <translation>Выводить отладочную информацию (по умолчанию: %u, указание <category> необязательно)</translation> + </message> + <message> + <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> + <translation>Использовать отдельный прокси SOCKS5 для соединения с участниками через скрытые сервисы Tor (по умолчанию: %s)</translation> + </message> + <message> <source>(default: %s)</source> <translation>(по умолчанию: %s)</translation> </message> <message> + <source>Acceptable ciphers (default: %s)</source> + <translation>Допустимые шифры (по умолчанию: %s)</translation> + </message> + <message> + <source>Always query for peer addresses via DNS lookup (default: %u)</source> + <translation>Всегда запрашивать адреса участников с помощью DNS (по умолчанию: %u)</translation> + </message> + <message> + <source>Disable safemode, override a real safe mode event (default: %u)</source> + <translation>Отключить безопасный режим, отклонить реальное событие безопасного режима (по умолчанию: %u)</translation> + </message> + <message> <source>Error loading wallet.dat</source> <translation>Ошибка при загрузке wallet.dat</translation> </message> <message> + <source>Force safe mode (default: %u)</source> + <translation>Принудительный безопасный режим (по умолчанию: %u)</translation> + </message> + <message> + <source>Generate coins (default: %u)</source> + <translation>Включить добычу монет (по умолчанию: %u)</translation> + </message> + <message> + <source>How many blocks to check at startup (default: %u, 0 = all)</source> + <translation>Сколько блоков проверять при запуске (по умолчанию: %u, 0 = все)</translation> + </message> + <message> + <source>Include IP addresses in debug output (default: %u)</source> + <translation>Включить IP-адреса в отладочный вывод (по умолчанию: %u)</translation> + </message> + <message> <source>Invalid -proxy address: '%s'</source> <translation>Неверный адрес -proxy: '%s'</translation> </message> <message> + <source>Limit size of signature cache to <n> entries (default: %u)</source> + <translation>Ограничить размер кэша подписей <n> записями (по умолчанию: %u)</translation> + </message> + <message> + <source>Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)</source> + <translation>Прослушивать подключения JSON-RPC на <порту> (по умолчанию: %u или %u в тестовой сети)</translation> + </message> + <message> + <source>Listen for connections on <port> (default: %u or testnet: %u)</source> + <translation>Принимать входящие подключения на <port> (по умолчанию: %u или %u в тестовой сети)</translation> + </message> + <message> + <source>Maintain at most <n> connections to peers (default: %u)</source> + <translation>Поддерживать не более <n> подключений к узлам (по умолчанию: %u)</translation> + </message> + <message> + <source>Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)</source> + <translation>Максимальный размер буфера приёма на соединение, <n>*1000 байт (по умолчанию: %u)</translation> + </message> + <message> + <source>Maximum per-connection send buffer, <n>*1000 bytes (default: %u)</source> + <translation>Максимальный размер буфера отправки на соединение, <n>*1000 байт (по умолчанию: %u)</translation> + </message> + <message> + <source>Only accept block chain matching built-in checkpoints (default: %u)</source> + <translation>Принимать цепь блоков, лишь если она соответствует встроенным контрольным точкам (по умолчанию: %u)</translation> + </message> + <message> + <source>Prepend debug output with timestamp (default: %u)</source> + <translation>Дописывать отметки времени к отладочному выводу (по умолчанию: %u)</translation> + </message> + <message> + <source>Print block tree on startup (default: %u)</source> + <translation>Печатать дерево блоков при запуске (по умолчанию: %u)</translation> + </message> + <message> + <source>Relay and mine data carrier transactions (default: %u)</source> + <translation>Транслировать и генерировать транзакции носителей данных (по умолчанию: %u)</translation> + </message> + <message> + <source>Relay non-P2SH multisig (default: %u)</source> + <translation>Транслировать не-P2SH мультиподпись (по умолчанию: %u)</translation> + </message> + <message> + <source>Run a thread to flush wallet periodically (default: %u)</source> + <translation>Запустить поток для периодического сохранения бумажника (по умолчанию: %u)</translation> + </message> + <message> + <source>Server certificate file (default: %s)</source> + <translation>Файл сертификата сервера (по умолчанию: %s)</translation> + </message> + <message> + <source>Server private key (default: %s)</source> + <translation>Закрытый ключ сервера (по умолчанию: %s)</translation> + </message> + <message> + <source>Set key pool size to <n> (default: %u)</source> + <translation>Установить размер пула ключей в <n> (по умолчанию: %u)</translation> + </message> + <message> + <source>Set the number of threads to service RPC calls (default: %d)</source> + <translation>Задать число потоков выполнения запросов RPC (по умолчанию: %d)</translation> + </message> + <message> + <source>Sets the DB_PRIVATE flag in the wallet db environment (default: %u)</source> + <translation>Установить флаг DB_PRIVATE в окружении базы данных бумажника (по умолчанию: %u)</translation> + </message> + <message> + <source>Specify configuration file (default: %s)</source> + <translation>Указать конфигурационный файл (по умолчанию: %s)</translation> + </message> + <message> + <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source> + <translation>Указать тайм-аут соединения в миллисекундах (минимум: 1, по умолчанию: %d)</translation> + </message> + <message> + <source>Specify pid file (default: %s)</source> + <translation>Указать pid-файл (по умолчанию: %s)</translation> + </message> + <message> + <source>Spend unconfirmed change when sending transactions (default: %u)</source> + <translation>Тратить неподтвержденную сдачу при отправке транзакций (по умолчанию: %u)</translation> + </message> + <message> + <source>Stop running after importing blocks from disk (default: %u)</source> + <translation>Остановиться после импорта блоков с диска (по умолчанию: %u)</translation> + </message> + <message> + <source>Threshold for disconnecting misbehaving peers (default: %u)</source> + <translation>Порог для отключения неправильно ведущих себя узлов (по умолчанию: %u)</translation> + </message> + <message> <source>Unknown network specified in -onlynet: '%s'</source> <translation>В параметре -onlynet указана неизвестная сеть: '%s'</translation> </message> diff --git a/src/qt/locale/bitcoin_sah.ts b/src/qt/locale/bitcoin_sah.ts index a951e10ab9..84b973bf92 100644 --- a/src/qt/locale/bitcoin_sah.ts +++ b/src/qt/locale/bitcoin_sah.ts @@ -1,4 +1,4 @@ -<TS language="sah" version="2.1"> +<TS language="sah" version="2.0"> <context> <name>AddressBookPage</name> <message> diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts index 7768288294..fe7c62cd60 100644 --- a/src/qt/locale/bitcoin_sk.ts +++ b/src/qt/locale/bitcoin_sk.ts @@ -1,4 +1,4 @@ -<TS language="sk" version="2.1"> +<TS language="sk" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -422,14 +422,34 @@ <source>Show the Bitcoin Core help message to get a list with possible Bitcoin command-line options</source> <translation>Zobraziť pomocnú správu od Bitcoin Jadra pre získanie zoznamu dostupných možností príkazového riadku</translation> </message> + <message numerus="yes"> + <source>%n active connection(s) to Bitcoin network</source> + <translation><numerusform>%n aktívne pripojenie do siete Bitcoin</numerusform><numerusform>%n aktívne pripojenia do siete Bitcoin</numerusform><numerusform>%n aktívnych pripojení do siete Bitcoin</numerusform></translation> + </message> <message> <source>No block source available...</source> <translation>Nedostupný zdroj blokov...</translation> </message> + <message numerus="yes"> + <source>%n hour(s)</source> + <translation><numerusform>%n hodina</numerusform><numerusform>%n hodiny</numerusform><numerusform>%n hodín</numerusform></translation> + </message> + <message numerus="yes"> + <source>%n day(s)</source> + <translation><numerusform>%n deň</numerusform><numerusform>%n dni</numerusform><numerusform>%n dní</numerusform></translation> + </message> + <message numerus="yes"> + <source>%n week(s)</source> + <translation><numerusform>%n týždeň</numerusform><numerusform>%n týždne</numerusform><numerusform>%n týždňov</numerusform></translation> + </message> <message> <source>%1 and %2</source> <translation> %1 a %2</translation> </message> + <message numerus="yes"> + <source>%n year(s)</source> + <translation><numerusform>%n rok</numerusform><numerusform>%n roky</numerusform><numerusform>%n rokov</numerusform></translation> + </message> <message> <source>%1 behind</source> <translation>%1 pozadu</translation> @@ -500,10 +520,6 @@ Adresa: %4</translation> <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Coin Control výber adresy</translation> - </message> - <message> <source>Quantity:</source> <translation>Množstvo:</translation> </message> @@ -548,10 +564,6 @@ Adresa: %4</translation> <translation>Suma</translation> </message> <message> - <source>Address</source> - <translation>Adresa</translation> - </message> - <message> <source>Date</source> <translation>Dátum</translation> </message> @@ -906,14 +918,6 @@ Adresa: %4</translation> <translation>&Hlavné</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Voliteľný transakčný poplatok za kB ktorý pomôže rýchlemu spracovaniu transakcie. Väčšina transakcií má 1 kB. Poplatok 0.01 je odporúčaný.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Zaplatiť transakčné &poplatky</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Automaticky spustiť Bitcoin po zapnutí počítača</translation> </message> @@ -934,14 +938,6 @@ Adresa: %4</translation> <translation>Počet skript overujucich vlákien</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Pripojiť k Bitcoin sieti cez SOCKS proxy.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>Pripojiť sa cez SOCKS proxy (predvolené proxy)</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>IP adresy proxy (napr. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts index ed6f813e7d..60fc4a93e5 100644 --- a/src/qt/locale/bitcoin_sl_SI.ts +++ b/src/qt/locale/bitcoin_sl_SI.ts @@ -1,4 +1,4 @@ -<TS language="sl_SI" version="2.1"> +<TS language="sl_SI" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -521,10 +521,6 @@ Naslov: %4 <translation>Količina</translation> </message> <message> - <source>Address</source> - <translation>Naslov</translation> - </message> - <message> <source>Date</source> <translation>Datum</translation> </message> @@ -875,14 +871,6 @@ Naslov: %4 <translation>&Glavno</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Neobvezna pristojbina k transakciji poskrbi, da je transackcija hitro opravljena. Velikost povprečne transakcije je 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Nakazilo plačila & provizija</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Po prijavi v sistem samodejno zaženite Bitcoin.</translation> </message> @@ -907,14 +895,6 @@ Naslov: %4 <translation>Dovoli prihajajoče povezave</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>V Bitcoin omrežje se poveži skozu SOCKS proxy.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Poveži se skozi SOCKS proxy (privzet proxy):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>IP naslov proxy strežnika (npr. IPv4: 127.0.0.1 ali IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_sq.ts b/src/qt/locale/bitcoin_sq.ts index 0c60e482fe..7e63f239ca 100644 --- a/src/qt/locale/bitcoin_sq.ts +++ b/src/qt/locale/bitcoin_sq.ts @@ -1,4 +1,4 @@ -<TS language="sq" version="2.1"> +<TS language="sq" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -197,10 +197,6 @@ <translation>Sasia</translation> </message> <message> - <source>Address</source> - <translation>Adresë</translation> - </message> - <message> <source>Date</source> <translation>Data</translation> </message> diff --git a/src/qt/locale/bitcoin_sr.ts b/src/qt/locale/bitcoin_sr.ts index c3dc42e2f3..64c68a2226 100644 --- a/src/qt/locale/bitcoin_sr.ts +++ b/src/qt/locale/bitcoin_sr.ts @@ -1,4 +1,4 @@ -<TS language="sr" version="2.1"> +<TS language="sr" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -265,10 +265,6 @@ Address: %4 <translation>iznos</translation> </message> <message> - <source>Address</source> - <translation>Адреса</translation> - </message> - <message> <source>Date</source> <translation>datum</translation> </message> diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts index 39cca4b278..551f6976cf 100644 --- a/src/qt/locale/bitcoin_sv.ts +++ b/src/qt/locale/bitcoin_sv.ts @@ -1,4 +1,4 @@ -<TS language="sv" version="2.1"> +<TS language="sv" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -479,6 +479,10 @@ Var vänlig och försök igen.</translation> <source>Up to date</source> <translation>Uppdaterad</translation> </message> + <message numerus="yes"> + <source>Processed %n blocks of transaction history.</source> + <translation><numerusform>Bearbetat %n block av transaktionshistoriken.</numerusform><numerusform>Bearbetat %n block av transaktionshistoriken.</numerusform></translation> + </message> <message> <source>Catching up...</source> <translation>Hämtar senaste...</translation> @@ -522,8 +526,8 @@ Adress: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Adressval för myntkontroll</translation> + <source>Coin Selection</source> + <translation>Myntval</translation> </message> <message> <source>Quantity:</source> @@ -574,8 +578,12 @@ Adress: %4 <translation>Mängd</translation> </message> <message> - <source>Address</source> - <translation>Adress</translation> + <source>Received with label</source> + <translation>Mottagen med etikett</translation> + </message> + <message> + <source>Received with address</source> + <translation>Mottagen med adress</translation> </message> <message> <source>Date</source> @@ -905,7 +913,15 @@ Adress: %4 <source>Error</source> <translation>Fel</translation> </message> - </context> + <message numerus="yes"> + <source>%n GB of free space available</source> + <translation><numerusform>%n GB fritt utrymme kvar</numerusform><numerusform>%n GB fritt utrymme kvar</numerusform></translation> + </message> + <message numerus="yes"> + <source>(of %n GB needed)</source> + <translation><numerusform>(av %n GB behövs)</numerusform><numerusform>(av %n GB behövs)</numerusform></translation> + </message> +</context> <context> <name>OpenURIDialog</name> <message> @@ -940,14 +956,6 @@ Adress: %4 <translation>&Allmänt</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Valfri transaktionsavgift per kB som ser till att dina transaktioner behandlas snabbt. De flesta transaktioner är 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Betala överförings&avgift</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Starta Bitcoin automatiskt efter inloggning.</translation> </message> @@ -976,14 +984,6 @@ Adress: %4 <translation>Acceptera inkommande anslutningar</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Anslut till Bitcoin-nätverket genom en SOCKS-proxy.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Anslut genom SOCKS-proxy (förvald proxy):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Proxyns IP-adress (t.ex. IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1044,6 +1044,14 @@ Adress: %4 <translation>Tilldela port med hjälp av &UPnP</translation> </message> <message> + <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> + <translation>Anslut till Bitcoin-nätverket genom en SOCKS5-proxy.</translation> + </message> + <message> + <source>&Connect through SOCKS5 proxy (default proxy):</source> + <translation>&Anslut genom SOCKS5-proxy (förvald proxy):</translation> + </message> + <message> <source>Proxy &IP:</source> <translation>Proxy-&IP: </translation> </message> @@ -1175,6 +1183,10 @@ Adress: %4 <translation>Den genererade balansen som ännu inte har mognat</translation> </message> <message> + <source>Balances</source> + <translation>Balanser</translation> + </message> + <message> <source>Total:</source> <translation>Totalt:</translation> </message> @@ -1187,6 +1199,14 @@ Adress: %4 <translation>Ditt nuvarande saldo i granska-bara adresser</translation> </message> <message> + <source>Spendable:</source> + <translation>Spenderbar:</translation> + </message> + <message> + <source>Recent transactions</source> + <translation>Nyligen genomförda transaktioner</translation> + </message> + <message> <source>Unconfirmed transactions to watch-only addresses</source> <translation>Okonfirmerade transaktioner till granska-bara adresser</translation> </message> @@ -1818,6 +1838,78 @@ Adress: %4 <translation>Specialväxeladress</translation> </message> <message> + <source>Transaction Fee:</source> + <translation>Transaktionsavgift:</translation> + </message> + <message> + <source>Choose...</source> + <translation>Välj...</translation> + </message> + <message> + <source>collapse fee-settings</source> + <translation>Fäll ihop avgiftsinställningarna</translation> + </message> + <message> + <source>Minimize</source> + <translation>Minimera</translation> + </message> + <message> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation>Om den anpassad avgiften är satt till 1000 satoshi och transaktionen bara är 250 byte, betalar "per kilobyte" bara 250 satoshi i avgift, medans "minst" betalar 1000 satoshi. För transaktioner större än en kilobyte betalar både per kilobyte.</translation> + </message> + <message> + <source>per kilobyte</source> + <translation>per kilobyte</translation> + </message> + <message> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation>Om den anpassad avgiften är satt till 1000 satoshi och transaktionen bara är 250 byte, betalar "per kilobyte" bara 250 satoshi i avgift, medans "totalt minst" betalar 1000 satoshi. För transaktioner större än en kilobyte betalar både per kilobyte.</translation> + </message> + <message> + <source>total at least</source> + <translation>totalt minst</translation> + </message> + <message> + <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> + <translation>Att betala endast den minsta avgiften är bara bra så länge det är mindre transaktionsvolym än utrymme i blocken. Men tänk på att det kan hamna i en aldrig bekräftar transaktion när det finns mer efterfrågan på bitcoin transaktioner än nätverket kan bearbeta.</translation> + </message> + <message> + <source>(read the tooltip)</source> + <translation>(läs verktygstips)</translation> + </message> + <message> + <source>Recommended:</source> + <translation>Rekommenderad:</translation> + </message> + <message> + <source>Custom:</source> + <translation>Anpassad:</translation> + </message> + <message> + <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source> + <translation>(Smartavgiften är inte initierad än. Detta tar vanligen några block...)</translation> + </message> + <message> + <source>Confirmation time:</source> + <translation>Bekräftelsetid:</translation> + </message> + <message> + <source>normal</source> + <translation>normal</translation> + </message> + <message> + <source>fast</source> + <translation>snabb</translation> + </message> + <message> + <source>Send as zero-fee transaction if possible</source> + <translation>Sänd som nollavgiftstransaktion om möjligt</translation> + </message> + <message> + <source>(confirmation may take longer)</source> + <translation>(bekräftelse kan ta längre tid)</translation> + </message> + <message> <source>Send to multiple recipients at once</source> <translation>Skicka till flera mottagare samtidigt</translation> </message> @@ -1922,6 +2014,18 @@ Adress: %4 <translation>Transaktionen avslogs! Detta kan hända om några av mynten i plånboken redan spenderats, t.ex om du använt en kopia av wallet.dat och mynt spenderades i kopian men inte markerats som spenderade här.</translation> </message> <message> + <source>A fee higher than %1 is considered an insanely high fee.</source> + <translation>En avgift högre än %1 anses som en onormalt hög avgift.</translation> + </message> + <message> + <source>Pay only the minimum fee of %1</source> + <translation>Betala endast den minimala avgiften på %1</translation> + </message> + <message> + <source>Estimated to begin confirmation within %1 block(s).</source> + <translation>Bekräftelsen beräknas börja inom %1 block.</translation> + </message> + <message> <source>Warning: Invalid Bitcoin address</source> <translation>Varning: Felaktig Bitcoinadress</translation> </message> @@ -2450,6 +2554,10 @@ Adress: %4 <translation>Transaktionstyp.</translation> </message> <message> + <source>Whether or not a watch-only address is involved in this transaction.</source> + <translation>Anger om granska-bara--adresser är involverade i denna transaktion.</translation> + </message> + <message> <source>Destination address of transaction.</source> <translation>Transaktionens destinationsadress.</translation> </message> @@ -2545,6 +2653,10 @@ Adress: %4 <translation>Exportera Transaktionshistoriken</translation> </message> <message> + <source>Watch-only</source> + <translation>Granska-bara</translation> + </message> + <message> <source>Exporting Failed</source> <translation>Exporteringen misslyckades</translation> </message> @@ -2720,6 +2832,10 @@ till exempel: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Ta bort alla plånbokstransaktioner och återskapa bara dom som är en del av blockkedjan genom att ange -rescan vid uppstart</translation> </message> <message> + <source>Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> + <translation>Distribuerad under MIT mjukvarulicens, se den bifogade filen COPYING eller <http://www.opensource.org/licenses/mit-license.php>.</translation> + </message> + <message> <source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly.</source> <translation>Ange regressiontestläge, som använder en speciell kedja i vilka block kan lösas omedelbart.</translation> </message> @@ -2772,6 +2888,10 @@ till exempel: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Varning: wallet.dat korrupt, datan har räddats! Den ursprungliga wallet.dat har sparas som wallet.{timestamp}.bak i %s; om ditt saldo eller transaktioner är felaktiga ska du återställa från en säkerhetskopia.</translation> </message> <message> + <source>Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.</source> + <translation>Vitlista klienter som ansluter från angivna nätmasker eller IP-adresser. Kan specificeras flera gånger.</translation> + </message> + <message> <source>(default: 1)</source> <translation>(förvalt: 1)</translation> </message> @@ -2832,6 +2952,10 @@ till exempel: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Fel vid öppning av blockdatabasen</translation> </message> <message> + <source>Error: A fatal internal error occured, see debug.log for details</source> + <translation>Fel: Ett fatalt internt fel inträffade. Se debug.log för detaljer</translation> + </message> + <message> <source>Error: Disk space is low!</source> <translation>Fel: Hårddiskutrymme är lågt!</translation> </message> @@ -2864,6 +2988,10 @@ till exempel: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Inte tillräckligt med filbeskrivningar tillgängliga.</translation> </message> <message> + <source>Only connect to nodes in network <net> (ipv4, ipv6 or onion)</source> + <translation>Anslut enbart till noder i nätverket <net> (IPv4, IPv6 eller onion)</translation> + </message> + <message> <source>Rebuild block chain index from current blk000??.dat files</source> <translation>Återskapa blockkedjans index från nuvarande blk000??.dat filer</translation> </message> @@ -2884,6 +3012,10 @@ till exempel: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Detta är avsett för regressionstestningsverktyg och applikationsutveckling.</translation> </message> <message> + <source>Use UPnP to map the listening port (default: %u)</source> + <translation>Använd UPnP för att mappa den lyssnande porten (förvalt: %u)</translation> + </message> + <message> <source>Verifying blocks...</source> <translation>Verifierar block...</translation> </message> @@ -2928,12 +3060,12 @@ till exempel: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Kan inte låsa data-mappen %s. Bitcoin Core körs förmodligen redan.</translation> </message> <message> - <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> - <translation>Skapa nya filer med systemets förvalda rättigheter, istället för umask 077 (bara effektivt med avaktiverad plånboks funktionalitet)</translation> + <source>Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:%u)</source> + <translation>Antalsbegränsa kontinuerligt fria transaktioner till <n>*1000 bytes per minut (förvalt:%u)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Distribuerad under MIT/X11 mjukvarulicens, se den bifogade filen COPYING eller <http://www.opensource.org/licenses/mit-license.php>.</translation> + <source>Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)</source> + <translation>Skapa nya filer med systemets förvalda rättigheter, istället för umask 077 (bara effektivt med avaktiverad plånboks funktionalitet)</translation> </message> <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> @@ -2956,6 +3088,10 @@ till exempel: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Avgifter (i BTC/Kb) mindre än detta betraktas som nollavgift för transaktionsskapande (förvalt: %s)</translation> </message> <message> + <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source> + <translation>Maximal storlek på data i databärartransaktioner som vi reläar och bryter (förvalt: %u) </translation> + </message> + <message> <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source> <translation>Sök efter klientadresser med DNS sökningen, om det finns otillräckligt med adresser (förvalt: 1 om inte -connect)</translation> </message> @@ -3032,6 +3168,10 @@ till exempel: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Håll som mest <n> oanslutningsbara block i minnet (förvalt: %u)</translation> </message> <message> + <source>Keep at most <n> unconnectable transactions in memory (default: %u)</source> + <translation>Håll som mest <n> oanslutningsbara transaktioner i minnet (förvalt: %u)</translation> + </message> + <message> <source>Need to specify a port with -whitebind: '%s'</source> <translation>Port måste anges med -whitelist: '%s'</translation> </message> @@ -3064,6 +3204,10 @@ till exempel: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Skicka trace-/debuginformation till terminalen istället för till debug.log</translation> </message> <message> + <source>Send transactions as zero-fee transactions if possible (default: %u)</source> + <translation>Sänd transaktioner som nollavgiftstransaktioner om möjligt (förvalt: %u)</translation> + </message> + <message> <source>Show all debugging options (usage: --help -help-debug)</source> <translation>Visa alla avlusningsoptioner (använd: --help -help-debug)</translation> </message> @@ -3172,14 +3316,178 @@ till exempel: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Fel vid inläsningen av wallet.dat: Plånboken är skadad</translation> </message> <message> + <source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source> + <translation>(1 = spara tx metadata t.ex. kontoägare och betalningsbegäransinformation, 2 = släng tx metadata)</translation> + </message> + <message> + <source>Flush database activity from memory pool to disk log every <n> megabytes (default: %u)</source> + <translation>Töm databasens minnespool till disk varje <n> megabytes (förvalt: %u)</translation> + </message> + <message> + <source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source> + <translation>Hur grundlig blockverifikationen vid -checkblocks är (0-4, förvalt: %u)</translation> + </message> + <message> + <source>If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: %u)</source> + <translation>Om paytxfee inte är satt, inkludera tillräcklig avgift så att transaktionen konfirmeras inom n blocks (förvalt: %u)</translation> + </message> + <message> + <source>Log transaction priority and fee per kB when mining blocks (default: %u)</source> + <translation>Logga transaktionsprioritet och avgift per kB vid blockbrytning (förvalt: %u)</translation> + </message> + <message> + <source>Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)</source> + <translation>Upprätthåll ett fullständigt transaktionsindex, som används av getrawtransaction rpc-anrop (förval: %u)</translation> + </message> + <message> + <source>Number of seconds to keep misbehaving peers from reconnecting (default: %u)</source> + <translation>Antal sekunder att hindra klienter som missköter sig från att ansluta (förvalt: %u)</translation> + </message> + <message> + <source>Output debugging information (default: %u, supplying <category> is optional)</source> + <translation>Skriv ut avlusningsinformation (förvalt: %u, att ange <category> är frivilligt)</translation> + </message> + <message> + <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> + <translation>Använd separat SOCKS5 proxy för att nå kollegor via dolda tjänster i Tor (förvalt: -%s)</translation> + </message> + <message> + <source>(default: %s)</source> + <translation>(förvalt: %s)</translation> + </message> + <message> + <source>Acceptable ciphers (default: %s)</source> + <translation>Accepterbara chiffer (förvalt: %s)</translation> + </message> + <message> + <source>Always query for peer addresses via DNS lookup (default: %u)</source> + <translation>Sök alltid efter klientadresser med DNS sökningen (förvalt: %u)</translation> + </message> + <message> + <source>Disable safemode, override a real safe mode event (default: %u)</source> + <translation>Avaktivera säkert läge. Åsidosätt en riktigt säkert läge händelse (förvalt: %u)</translation> + </message> + <message> <source>Error loading wallet.dat</source> <translation>Fel vid inläsning av plånboksfilen wallet.dat</translation> </message> <message> + <source>Force safe mode (default: %u)</source> + <translation>Tvångskör i säkert läge (förvalt: %u)</translation> + </message> + <message> + <source>Generate coins (default: %u)</source> + <translation>Generera mynt (förvalt: %u)</translation> + </message> + <message> + <source>How many blocks to check at startup (default: %u, 0 = all)</source> + <translation>Hur många block att kontrollera vid uppstart (förvalt: %u, 0 = alla)</translation> + </message> + <message> + <source>Include IP addresses in debug output (default: %u)</source> + <translation>Inkludera IP-adresser i debugutskrift (förvalt: %u)</translation> + </message> + <message> <source>Invalid -proxy address: '%s'</source> <translation>Ogiltig -proxy adress: '%s'</translation> </message> <message> + <source>Limit size of signature cache to <n> entries (default: %u)</source> + <translation>Begränsa signaturcachestorleken till <n> poster (förvalt: %u)</translation> + </message> + <message> + <source>Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)</source> + <translation>Lyssna på JSON-RPC-anslutningar på <port> (förval: %u eller testnet: %u)</translation> + </message> + <message> + <source>Listen for connections on <port> (default: %u or testnet: %u)</source> + <translation>Lyssna efter anslutningar på <port> (förvalt: %u eller testnet: %u)</translation> + </message> + <message> + <source>Maintain at most <n> connections to peers (default: %u)</source> + <translation>Ha som mest <n> anslutningar till andra klienter (förvalt: %u)</translation> + </message> + <message> + <source>Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)</source> + <translation>Maximal mottagningsbuffert per anslutning, <n>*1000 byte (förvalt: %u)</translation> + </message> + <message> + <source>Maximum per-connection send buffer, <n>*1000 bytes (default: %u)</source> + <translation>Maximal sändningsbuffert per anslutning, <n>*1000 byte (förvalt: %u)</translation> + </message> + <message> + <source>Only accept block chain matching built-in checkpoints (default: %u)</source> + <translation>Acceptera bara blockkedjans matchande inbyggda kontrollpunkter (förvalt: %u)</translation> + </message> + <message> + <source>Prepend debug output with timestamp (default: %u)</source> + <translation>Skriv ut tidsstämpel i avlusningsinformationen (förvalt: %u)</translation> + </message> + <message> + <source>Print block tree on startup (default: %u)</source> + <translation>Skriv ut blockträdet vid uppstart (förvalt: %u)</translation> + </message> + <message> + <source>Relay and mine data carrier transactions (default: %u)</source> + <translation>Reläa och bearbeta databärartransaktioner (förvalt: %u) </translation> + </message> + <message> + <source>Relay non-P2SH multisig (default: %u)</source> + <translation>Reläa icke P2SH multisig (förvalt: %u)</translation> + </message> + <message> + <source>Run a thread to flush wallet periodically (default: %u)</source> + <translation>Kör en tråd för att tömma plånboken periodiskt (förvalt: %u)</translation> + </message> + <message> + <source>Server certificate file (default: %s)</source> + <translation>Serverns certifikatfil (förvalt: %s)</translation> + </message> + <message> + <source>Server private key (default: %s)</source> + <translation>Serverns privata nyckel (förvalt: %s)</translation> + </message> + <message> + <source>Set key pool size to <n> (default: %u)</source> + <translation>Sätt storleken på nyckelpoolen till <n> (förvalt: %u)</translation> + </message> + <message> + <source>Set minimum block size in bytes (default: %u)</source> + <translation>Sätt minsta blockstorlek i byte (standard: %u)</translation> + </message> + <message> + <source>Set the number of threads to service RPC calls (default: %d)</source> + <translation>Ange antalet trådar för att hantera RPC anrop (förvalt: %d)</translation> + </message> + <message> + <source>Sets the DB_PRIVATE flag in the wallet db environment (default: %u)</source> + <translation>Sätt DB_PRIVATE flaggan i plånbokens databasmiljö (förvalt: %u)</translation> + </message> + <message> + <source>Specify configuration file (default: %s)</source> + <translation>Ange konfigurationsfil (förvalt: %s)</translation> + </message> + <message> + <source>Specify connection timeout in milliseconds (minimum: 1, default: %d)</source> + <translation>Ange timeout för uppkoppling i millisekunder (minimum:1, förvalt: %d)</translation> + </message> + <message> + <source>Specify pid file (default: %s)</source> + <translation>Ange pid-fil (förvalt: %s)</translation> + </message> + <message> + <source>Spend unconfirmed change when sending transactions (default: %u)</source> + <translation>Spendera okonfirmerad växel när transaktioner sänds (förvalt: %u)</translation> + </message> + <message> + <source>Stop running after importing blocks from disk (default: %u)</source> + <translation>Sluta köra efter importen av block från disk är klar (förvalt: %u)</translation> + </message> + <message> + <source>Threshold for disconnecting misbehaving peers (default: %u)</source> + <translation>Tröskelvärde för att koppla ifrån klienter som missköter sig (förvalt: %u)</translation> + </message> + <message> <source>Unknown network specified in -onlynet: '%s'</source> <translation>Okänt nätverk som anges i -onlynet: '%s'</translation> </message> diff --git a/src/qt/locale/bitcoin_th_TH.ts b/src/qt/locale/bitcoin_th_TH.ts index e4b1e069cd..174816aaef 100644 --- a/src/qt/locale/bitcoin_th_TH.ts +++ b/src/qt/locale/bitcoin_th_TH.ts @@ -1,4 +1,4 @@ -<TS language="th_TH" version="2.1"> +<TS language="th_TH" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -197,10 +197,6 @@ <context> <name>CoinControlDialog</name> <message> - <source>Address</source> - <translation>ที่อยู่</translation> - </message> - <message> <source>(no label)</source> <translation>(ไม่มีชื่อ)</translation> </message> diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts index b5d00bc24e..ab02cc92a6 100644 --- a/src/qt/locale/bitcoin_tr.ts +++ b/src/qt/locale/bitcoin_tr.ts @@ -1,4 +1,4 @@ -<TS language="tr" version="2.1"> +<TS language="tr" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -525,8 +525,8 @@ Adres: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Para kontrolü adres seçimi</translation> + <source>Coin Selection</source> + <translation>Bitcoin Seçimi</translation> </message> <message> <source>Quantity:</source> @@ -577,8 +577,12 @@ Adres: %4 <translation>Meblağ</translation> </message> <message> - <source>Address</source> - <translation>Adres</translation> + <source>Received with label</source> + <translation>Şu etiketle alındı</translation> + </message> + <message> + <source>Received with address</source> + <translation>Şu adresle alındı</translation> </message> <message> <source>Date</source> @@ -955,14 +959,6 @@ Adres: %4 <translation>&Esas ayarlar</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Muamelelerin hızlı işlenmesini garantilemeye yardım eden, seçime dayalı kB başı muamele ücreti. Muamelelerin çoğunluğunun boyutu 1 kB'dir.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Muamele ücreti &öde</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Sistemde oturum açıldığında Bitcoin'i otomatik olarak başlat.</translation> </message> @@ -991,14 +987,6 @@ Adres: %4 <translation>Gelen bağlantılara izin ver</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Bitcoin şebekesine bir SOCKS vekil sunucusu vasıtasıyla bağlan.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>SOCKS vekil sunucusuyla &bağlan (varsayılan vekil):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Vekil sunucusunun IP adresi (mesela IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1059,6 +1047,14 @@ Adres: %4 <translation>Portları &UPnP kullanarak haritala</translation> </message> <message> + <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source> + <translation>Bitcoin şebekesine SOCKS5 vekil sunucusu vasıtasıyla bağlan.</translation> + </message> + <message> + <source>&Connect through SOCKS5 proxy (default proxy):</source> + <translation>SOCKS5 vekil sunucusu vasıtasıyla &bağlan (varsayılan vekil sunucusu):</translation> + </message> + <message> <source>Proxy &IP:</source> <translation>Vekil &İP:</translation> </message> @@ -1849,6 +1845,78 @@ Adres: %4 <translation>Özel para üstü adresi</translation> </message> <message> + <source>Transaction Fee:</source> + <translation>Muamele ücreti:</translation> + </message> + <message> + <source>Choose...</source> + <translation>Seç...</translation> + </message> + <message> + <source>collapse fee-settings</source> + <translation>ücret-ayarlarını-küçült</translation> + </message> + <message> + <source>Minimize</source> + <translation>Küçült</translation> + </message> + <message> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation>Eğer özel ücret 1000 satoşi olarak ayarlandıysa ve muamele sadece 250 baytsa, "kilobayt başı" ücret olarak sadece 250 satoşi öder ve "asgari" 1000 satoşi öder. Bir kilobayttan yüksek muameleler için ikisi de kilobayt başı ödeme yapar.</translation> + </message> + <message> + <source>per kilobyte</source> + <translation>kilobayt başı</translation> + </message> + <message> + <source>If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte.</source> + <translation>Eğer özel ücret 1000 satoşi olarak ayarlandıysa ve muamele sadece 250 baytsa, "kilobayt başı" ücret olarak sadece 250 satoşi öder ve "toplam asgari" 1000 satoşi öder. Bir kilobayttan yüksek muameleler için ikisi de kilobayt başı ödeme yapar.</translation> + </message> + <message> + <source>total at least</source> + <translation>toplam asgari</translation> + </message> + <message> + <source>Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source> + <translation>Asgari ücreti ödemek, bloklarda boşluktan daha az muamele hacmi olduğu sürece bir sorun çıkarmaz. Fakat şebekenin işleyecebileceğinden daha çok bitcoin muameleleri talebi olduğunda bunun asla teyit edilmeyen bir muamele olabileceğinin farkında olmalısınız.</translation> + </message> + <message> + <source>(read the tooltip)</source> + <translation>(bilgi balonunu oku)</translation> + </message> + <message> + <source>Recommended:</source> + <translation>Tavsiye edilen:</translation> + </message> + <message> + <source>Custom:</source> + <translation>Özel:</translation> + </message> + <message> + <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source> + <translation>(Zeki ücret henüz başlatılmadı. Bu genelde birkaç blok alır...)</translation> + </message> + <message> + <source>Confirmation time:</source> + <translation>Teyit süresi:</translation> + </message> + <message> + <source>normal</source> + <translation>normal</translation> + </message> + <message> + <source>fast</source> + <translation>çabuk</translation> + </message> + <message> + <source>Send as zero-fee transaction if possible</source> + <translation>Mümkünse ücretsiz muamele olarak gönder</translation> + </message> + <message> + <source>(confirmation may take longer)</source> + <translation>(teyit daha uzun süre alabilir)</translation> + </message> + <message> <source>Send to multiple recipients at once</source> <translation>Birçok alıcıya aynı anda gönder</translation> </message> @@ -1953,6 +2021,18 @@ Adres: %4 <translation>Muamele reddedildi! Cüzdanınızdaki madenî paraların bazıları zaten harcanmış olduğunda bu meydana gelebilir. Örneğin wallet.dat dosyasının bir kopyasını kullandıysanız ve kopyada para harcandığında ancak burada harcandığı işaretlenmediğinde.</translation> </message> <message> + <source>A fee higher than %1 is considered an insanely high fee.</source> + <translation>%1 tutarından yüksek ücret delicesine aşırı yüksek bir ücret olarak kabul edilir.</translation> + </message> + <message> + <source>Pay only the minimum fee of %1</source> + <translation>Sadece asgari ücret olan %1 tutarını öde</translation> + </message> + <message> + <source>Estimated to begin confirmation within %1 block(s).</source> + <translation>Tahmini olarak %1 blok içinde teyide başlanacaktır.</translation> + </message> + <message> <source>Warning: Invalid Bitcoin address</source> <translation>Uyarı: geçersiz Bitcoin adresi</translation> </message> @@ -2759,6 +2839,10 @@ mesela: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Tüm cüzdan muamelelerini sil ve başlangıçta -rescan ile sadece blok zincirinin parçası olanları geri getir</translation> </message> <message> + <source>Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> + <translation>MIT yazılım lisansı kapsamında yayınlanmıştır, ekteki COPYING dosyasına ya da <http://www.opensource.org/licenses/mit-license.php> adresine bakınız.</translation> + </message> + <message> <source>Enter regression test mode, which uses a special chain in which blocks can be solved instantly.</source> <translation>Blokların anında çözülebileceği özel bir zincir kullanan regresyon deneme kipine gir.</translation> </message> @@ -2991,10 +3075,6 @@ mesela: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Yeni dosyaları umask 077 yerine varsayılan izinlerle oluştur (sadece devre dışı cüzdan işlevselliği ile etkilidir)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>MIT/X11 yazılım lisansı kapsamında yayınlanmıştır, ekteki COPYING dosyasına ya da <http://www.opensource.org/licenses/mit-license.php> adresine bakınız.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>Hata: İçeri gelen bağlantıların dinlenmesi başarısız oldu (dinleme %s hatasını verdi)</translation> </message> @@ -3015,6 +3095,10 @@ mesela: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Kb başına BTC olarak bundan düşük ücretler muamele oluşturulması için sıfır değerinde ücret olarak kabul edilir (varsayılan: %s)</translation> </message> <message> + <source>Maximum size of data in data carrier transactions we relay and mine (default: %u)</source> + <translation>Aktardığımız ve oluşturduğumuz veri taşıyıcı muamelelerindeki azami veri boyutu (varsayılan: %u)</translation> + </message> + <message> <source>Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)</source> <translation>Adres sayısı azaldıysa DNS sorgulamasıyla eş adresleri ara (varsayılan: 1 -connect kullanılmadıysa)</translation> </message> @@ -3023,6 +3107,10 @@ mesela: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Yüksek öncelikli/düşük ücretli muamelelerin azami boyutunu bayt olarak ayarla (varsayılan: %d)</translation> </message> <message> + <source>Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)</source> + <translation>Etkinse bitcoin oluşuturulmasına atanan iş parçacığı sayısını ayarla (-1 = tüm çekirdekler, varsayılan: %d)</translation> + </message> + <message> <source>This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.</source> <translation>Bu ürün OpenSSL projesi tarafından OpenSSL araç takımı (http://www.openssl.org/) için geliştirilen yazılımlar, Eric Young (eay@cryptsoft.com) tarafından hazırlanmış şifreleme yazılımları ve Thomas Bernard tarafından programlanmış UPnP yazılımı içerir.</translation> </message> @@ -3127,6 +3215,10 @@ mesela: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Trace/hata ayıklama verilerini debug.log dosyası yerine konsola gönder</translation> </message> <message> + <source>Send transactions as zero-fee transactions if possible (default: %u)</source> + <translation>Muameleleri mümkünse ücretsiz olarak gönder (varsayılan: %u)</translation> + </message> + <message> <source>Show all debugging options (usage: --help -help-debug)</source> <translation>Tüm hata ayıklama seçeneklerini göster (kullanımı: --help -help-debug)</translation> </message> @@ -3267,10 +3359,6 @@ mesela: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com <translation>Hata ayıklama bilgisi dök (varsayılan: %u, <kategori> sağlanması seçime dayalıdır)</translation> </message> <message> - <source>Set the processor limit for when generation is on (-1 = unlimited, default: %d)</source> - <translation>Oluşturma etkinken işlemci sınırını belirle (-1 = sınırsız, varsayılan: %d)</translation> - </message> - <message> <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> <translation>Eşlere gizli Tor servisleri ile ulaşmak için ayrı SOCKS5 vekil sunucusu kullan (varsayılan: %s)</translation> </message> diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts index c8fe1df9bf..b6ba507e9b 100644 --- a/src/qt/locale/bitcoin_uk.ts +++ b/src/qt/locale/bitcoin_uk.ts @@ -1,4 +1,4 @@ -<TS language="uk" version="2.1"> +<TS language="uk" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -87,7 +87,7 @@ </message> <message> <source>Comma separated file (*.csv)</source> - <translation>Файли, розділені комою (*.csv)</translation> + <translation>Значення, розділені комою (*.csv)</translation> </message> <message> <source>Exporting Failed</source> @@ -525,10 +525,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Вибір адрес для керування монетами</translation> - </message> - <message> <source>Quantity:</source> <translation>Кількість:</translation> </message> @@ -577,10 +573,6 @@ Address: %4 <translation>Кількість</translation> </message> <message> - <source>Address</source> - <translation>Адреса</translation> - </message> - <message> <source>Date</source> <translation>Дата</translation> </message> @@ -955,14 +947,6 @@ Address: %4 <translation>&Головні</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Необов'язкова комісия за Кб допомагає переконатися, що ваші транзакції обробляються швидше. Більшість транзакцій є 1 Кб.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Заплатити комісі&ю</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Автоматично запускати гаманець при вході до системи.</translation> </message> @@ -991,14 +975,6 @@ Address: %4 <translation>Дозволити вхідні з’єднання</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Підключатись до мережі Bitcoin через SOCKS-проксі.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>&Підключатись через SOCKS-проксі (типовий проксі):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>IP-адреса проксі-сервера (наприклад IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> @@ -1274,7 +1250,7 @@ Address: %4 </message> <message> <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source> - <translation>Неможливо обробити URI! Це може бути викликано неправильною Bitcoin-адресою, чи невірними параметрами URI.</translation> + <translation>Неможливо обробити URI! Причиною цього може бути некоректна Bitcoin-адреса або неправильні параметри URI.</translation> </message> <message> <source>Payment request file handling</source> @@ -2601,7 +2577,7 @@ Address: %4 </message> <message> <source>Comma separated file (*.csv)</source> - <translation>Файли, розділені комою (*.csv)</translation> + <translation>Значення, розділені комою (*.csv)</translation> </message> <message> <source>Confirmed</source> @@ -2747,7 +2723,7 @@ rpcpassword=%s Ім’я користувача та пароль ПОВИННІ бути різними. Якщо файлу не існує, створіть його, обмеживши доступ правом читання для власника. Також рекомендується використовувати alertnotify для того, щоб отримувати сповіщення про проблеми; -наприклад: alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com +наприклад: alertnotify=echo %%s | mail -s "Сповіщення Bitcoin" admin@foo.com </translation> </message> <message> @@ -2991,10 +2967,6 @@ rpcpassword=%s <translation>Створювати нові файли з типовими для системи атрибутами доступу замість маски 077 (діє тільки при вимкненому гаманці)</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>Поширюється за ліцензією MIT/X11, додаткова інформація міститься у файлі COPYING, а також за адресою <http://www.opensource.org/licenses/mit-license.php>.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>Помилка: Не вдалося налаштувати прослуховування вхідних підключень (listen повернув помилку: %s)</translation> </message> @@ -3004,7 +2976,7 @@ rpcpassword=%s </message> <message> <source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source> - <translation>Виконати команду при надходженні важливого попереджувального повідомлення або при спостереженні тривалого розгалуження ланцюжка (замість %s буде підставлено повідомлення)</translation> + <translation>Виконати команду при надходженні важливого сповіщення або при спостереженні тривалого розгалуження ланцюжка (замість %s буде підставлено повідомлення)</translation> </message> <message> <source>Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)</source> @@ -3072,15 +3044,15 @@ rpcpassword=%s </message> <message> <source>Invalid amount for -minrelaytxfee=<amount>: '%s'</source> - <translation>Вказано некоректну суму для параметру -minrelaytxfee: '%s'</translation> + <translation>Вказано некоректну суму для параметру -minrelaytxfee: «%s»</translation> </message> <message> <source>Invalid amount for -mintxfee=<amount>: '%s'</source> - <translation>Вказано некоректну суму для параметру -mintxfee: '%s'</translation> + <translation>Вказано некоректну суму для параметру -mintxfee: «%s»</translation> </message> <message> <source>Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)</source> - <translation>Вказано некоректну суму для параметру -paytxfee: '%s' (повинно бути щонайменше %s)</translation> + <translation>Вказано некоректну суму для параметру -paytxfee: «%s» (повинно бути щонайменше %s)</translation> </message> <message> <source>Invalid netmask specified in -whitelist: '%s'</source> @@ -3267,10 +3239,6 @@ rpcpassword=%s <translation>Виводити налагоджувальну інформацію (типово: %u, вказання <category> необов'язкове)</translation> </message> <message> - <source>Set the processor limit for when generation is on (-1 = unlimited, default: %d)</source> - <translation>Встановити максимальну кількість процесорів, що будуть використовуватися при ввімкненій генерації (-1 = необмежено, типово: %d)</translation> - </message> - <message> <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source> <translation>Використовувати окремий SOCKS5-проксі для з'єднання з учасниками через приховані сервіси Tor (типово: %s)</translation> </message> diff --git a/src/qt/locale/bitcoin_ur_PK.ts b/src/qt/locale/bitcoin_ur_PK.ts index 5bf7ce4344..86f3226269 100644 --- a/src/qt/locale/bitcoin_ur_PK.ts +++ b/src/qt/locale/bitcoin_ur_PK.ts @@ -1,4 +1,4 @@ -<TS language="ur_PK" version="2.1"> +<TS language="ur_PK" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -101,10 +101,6 @@ <translation>رقم</translation> </message> <message> - <source>Address</source> - <translation> پتہ</translation> - </message> - <message> <source>Date</source> <translation>تاریخ</translation> </message> diff --git a/src/qt/locale/bitcoin_uz@Cyrl.ts b/src/qt/locale/bitcoin_uz@Cyrl.ts index ab4439b419..54e649aede 100644 --- a/src/qt/locale/bitcoin_uz@Cyrl.ts +++ b/src/qt/locale/bitcoin_uz@Cyrl.ts @@ -1,4 +1,4 @@ -<TS language="uz@Cyrl" version="2.1"> +<TS language="uz@Cyrl" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -521,10 +521,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>Танга бошқарув манзилини танлаш</translation> - </message> - <message> <source>Quantity:</source> <translation>Сони:</translation> </message> @@ -573,10 +569,6 @@ Address: %4 <translation>Миқдори</translation> </message> <message> - <source>Address</source> - <translation>Манзил</translation> - </message> - <message> <source>Date</source> <translation>Сана</translation> </message> @@ -931,14 +923,6 @@ Address: %4 <translation>&Асосий</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>Ҳар бир кб учун ўтказма солиғи ўтказмаларингизни тезроқ ўтишига ишонишингизга ёрдам беради. Кўпгина ўтказмалар 1 кб.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>Ўтказма &солиғини тўлаш</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>Тизимга киргандан сўнг Bitcoin дастури автоматик ишга туширилсин.</translation> </message> @@ -967,14 +951,6 @@ Address: %4 <translation>Кирувчи уланишларга рухсат бериш</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>Bitcoin тармоққа SOCKS прокси орқали уланинг.</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>SOCKS прокси орқали &уланинг (стандарт прокси):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>Прокси IP манзили (масалан: IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_vi.ts b/src/qt/locale/bitcoin_vi.ts index e03349b383..3ca5605883 100644 --- a/src/qt/locale/bitcoin_vi.ts +++ b/src/qt/locale/bitcoin_vi.ts @@ -1,4 +1,4 @@ -<TS language="vi" version="2.1"> +<TS language="vi" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -53,10 +53,6 @@ <translation>Số lượng</translation> </message> <message> - <source>Address</source> - <translation>Địa chỉ</translation> - </message> - <message> <source>(no label)</source> <translation>(chưa có nhãn)</translation> </message> diff --git a/src/qt/locale/bitcoin_vi_VN.ts b/src/qt/locale/bitcoin_vi_VN.ts index 20ebd7b594..bf76c8638a 100644 --- a/src/qt/locale/bitcoin_vi_VN.ts +++ b/src/qt/locale/bitcoin_vi_VN.ts @@ -1,4 +1,4 @@ -<TS language="vi_VN" version="2.1"> +<TS language="vi_VN" version="2.0"> <context> <name>AddressBookPage</name> <message> diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts index 75867460ab..94d0675bfd 100644 --- a/src/qt/locale/bitcoin_zh_CN.ts +++ b/src/qt/locale/bitcoin_zh_CN.ts @@ -1,4 +1,4 @@ -<TS language="zh_CN" version="2.1"> +<TS language="zh_CN" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -517,10 +517,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>选择交易源地址</translation> - </message> - <message> <source>Quantity:</source> <translation>总量:</translation> </message> @@ -569,10 +565,6 @@ Address: %4 <translation>金额</translation> </message> <message> - <source>Address</source> - <translation>地址</translation> - </message> - <message> <source>Date</source> <translation>日期</translation> </message> @@ -932,14 +924,6 @@ Address: %4 <translation>主要(&M)</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>可选的每 kB 交易费,这有助于您的交易被更快的处理。大多数交易都是 1 kB。</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>支付交易费用(&F)</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>登录系统后自动开启比特币客户端</translation> </message> @@ -968,14 +952,6 @@ Address: %4 <translation>允许流入连接</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>通过 SOCKS 代理连接到比特币网络。</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>通过 SO&CKS 代理连接 (默认代理):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>代理的 IP 地址 (例如 IPv4: 127.0.0.1 / IPv6: ::1)</translation> </message> diff --git a/src/qt/locale/bitcoin_zh_HK.ts b/src/qt/locale/bitcoin_zh_HK.ts index dfdbb7d1da..7062377f45 100644 --- a/src/qt/locale/bitcoin_zh_HK.ts +++ b/src/qt/locale/bitcoin_zh_HK.ts @@ -1,4 +1,4 @@ -<TS language="zh_HK" version="2.1"> +<TS language="zh_HK" version="2.0"> <context> <name>AddressBookPage</name> </context> diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts index 6301bd4587..b70596d83a 100644 --- a/src/qt/locale/bitcoin_zh_TW.ts +++ b/src/qt/locale/bitcoin_zh_TW.ts @@ -1,4 +1,4 @@ -<TS language="zh_TW" version="2.1"> +<TS language="zh_TW" version="2.0"> <context> <name>AddressBookPage</name> <message> @@ -7,7 +7,7 @@ </message> <message> <source>Create a new address</source> - <translation>製造新的位址</translation> + <translation>新增新的位址</translation> </message> <message> <source>&New</source> @@ -521,10 +521,6 @@ Address: %4 <context> <name>CoinControlDialog</name> <message> - <source>Coin Control Address Selection</source> - <translation>錢幣控制的位址選擇</translation> - </message> - <message> <source>Quantity:</source> <translation>數目:</translation> </message> @@ -573,10 +569,6 @@ Address: %4 <translation>金額</translation> </message> <message> - <source>Address</source> - <translation>位址</translation> - </message> - <message> <source>Date</source> <translation>日期</translation> </message> @@ -908,7 +900,15 @@ Address: %4 <source>Error</source> <translation>錯誤</translation> </message> - </context> + <message numerus="yes"> + <source>%n GB of free space available</source> + <translation><numerusform>可用空間尚存 %n GB</numerusform></translation> + </message> + <message numerus="yes"> + <source>(of %n GB needed)</source> + <translation><numerusform>(需要 %n GB)</numerusform></translation> + </message> +</context> <context> <name>OpenURIDialog</name> <message> @@ -943,14 +943,6 @@ Address: %4 <translation>主要</translation> </message> <message> - <source>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</source> - <translation>每一千位元組(kB)要付的交易手續費,如果有付可以加速網路處理你的交易。大部份交易資料的大小是 1 kB.</translation> - </message> - <message> - <source>Pay transaction &fee</source> - <translation>付交易手續費</translation> - </message> - <message> <source>Automatically start Bitcoin after logging in to the system.</source> <translation>在登入系統後自動啓動位元幣軟體。</translation> </message> @@ -979,14 +971,6 @@ Address: %4 <translation>接受外來連線</translation> </message> <message> - <source>Connect to the Bitcoin network through a SOCKS proxy.</source> - <translation>透過 SOCKS 代理伺服器來連線到位元幣網路。</translation> - </message> - <message> - <source>&Connect through SOCKS proxy (default proxy):</source> - <translation>透過 SOCKS 代理伺服器連線(預設代理伺服器):</translation> - </message> - <message> <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source> <translation>代理伺服器的網際網路位址(像是 IPv4 的 127.0.0.1 或 IPv6 的 ::1)</translation> </message> @@ -2968,10 +2952,6 @@ alertnotify=echo %%s | mail -s "Bitcoin Alert" admin@foo.com</translation> <translation>用系統預設權限來造出新的檔案,而不是用使用者權限罩遮(umask)值 077 (只有在關掉錢包功能時才有作用)。</translation> </message> <message> - <source>Distributed under the MIT/X11 software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.</source> - <translation>這套軟體是依據 MIT/X11 軟體授權條款散布,詳情請見附帶的 COPYING 檔案,或是以下網站: <http://www.opensource.org/licenses/mit-license.php>.</translation> - </message> - <message> <source>Error: Listening for incoming connections failed (listen returned error %s)</source> <translation>錯誤: 聽候外來連線失敗(回傳錯誤 %s)</translation> </message> diff --git a/src/qt/macnotificationhandler.mm b/src/qt/macnotificationhandler.mm index 8a4c94cc5c..aa50a0d9fb 100644 --- a/src/qt/macnotificationhandler.mm +++ b/src/qt/macnotificationhandler.mm @@ -5,8 +5,21 @@ #include "macnotificationhandler.h" #undef slots +#import <objc/runtime.h> #include <Cocoa/Cocoa.h> +// Add an obj-c category (extension) to return the expected bundle identifier +@implementation NSBundle(returnCorrectIdentifier) +- (NSString *)__bundleIdentifier +{ + if (self == [NSBundle mainBundle]) { + return @"org.bitcoinfoundation.Bitcoin-Qt"; + } else { + return [self __bundleIdentifier]; + } +} +@end + void MacNotificationHandler::showNotification(const QString &title, const QString &text) { // check if users OS has support for NSUserNotification @@ -63,7 +76,16 @@ bool MacNotificationHandler::hasUserNotificationCenterSupport(void) MacNotificationHandler *MacNotificationHandler::instance() { static MacNotificationHandler *s_instance = NULL; - if (!s_instance) + if (!s_instance) { s_instance = new MacNotificationHandler(); + + Class aPossibleClass = objc_getClass("NSBundle"); + if (aPossibleClass) { + // change NSBundle -bundleIdentifier method to return a correct bundle identifier + // a bundle identifier is required to use OSXs User Notification Center + method_exchangeImplementations(class_getInstanceMethod(aPossibleClass, @selector(bundleIdentifier)), + class_getInstanceMethod(aPossibleClass, @selector(__bundleIdentifier))); + } + } return s_instance; } diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index f5a0759c92..069080219e 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -105,9 +105,6 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : #endif ui->unit->setModel(new BitcoinUnits(this)); -#ifdef ENABLE_WALLET - ui->transactionFee->setSingleStep(CWallet::minTxFee.GetFeePerK()); -#endif /* Widget-to-option mapper */ mapper = new QDataWidgetMapper(this); @@ -139,16 +136,11 @@ void OptionsDialog::setModel(OptionsModel *model) strLabel = tr("none"); ui->overriddenByCommandLineLabel->setText(strLabel); - connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); - mapper->setModel(model); setMapper(); mapper->toFirst(); } - /* update the display unit, to not use the default ("BTC") */ - updateDisplayUnit(); - /* warn when one of the following settings changes by user action (placed here so init via mapper doesn't trigger them) */ /* Main */ @@ -172,7 +164,6 @@ void OptionsDialog::setMapper() mapper->addMapping(ui->databaseCache, OptionsModel::DatabaseCache); /* Wallet */ - mapper->addMapping(ui->transactionFee, OptionsModel::Fee); mapper->addMapping(ui->spendZeroConfChange, OptionsModel::SpendZeroConfChange); mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures); @@ -264,15 +255,6 @@ void OptionsDialog::clearStatusLabel() ui->statusLabel->clear(); } -void OptionsDialog::updateDisplayUnit() -{ - if(model) - { - /* Update transactionFee with the current unit */ - ui->transactionFee->setDisplayUnit(model->getDisplayUnit()); - } -} - void OptionsDialog::doProxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort) { Q_UNUSED(nProxyPort); diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index 794a39590c..511719f53c 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -46,7 +46,6 @@ private slots: void showRestartWarning(bool fPersistent = false); void clearStatusLabel(); - void updateDisplayUnit(); void doProxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort); signals: diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index c941ebd4ca..7054509fe6 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -90,12 +90,6 @@ void OptionsModel::Init() // Wallet #ifdef ENABLE_WALLET - if (!settings.contains("nTransactionFee")) - settings.setValue("nTransactionFee", (qint64)DEFAULT_TRANSACTION_FEE); - payTxFee = CFeeRate(settings.value("nTransactionFee").toLongLong()); // if -paytxfee is set, this will be overridden later in init.cpp - if (mapArgs.count("-paytxfee")) - addOverriddenOption("-paytxfee"); - if (!settings.contains("bSpendZeroConfChange")) settings.setValue("bSpendZeroConfChange", true); if (!SoftSetBoolArg("-spendzeroconfchange", settings.value("bSpendZeroConfChange").toBool())) @@ -185,16 +179,6 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const } #ifdef ENABLE_WALLET - case Fee: { - // Attention: Init() is called before payTxFee is set in AppInit2()! - // To ensure we can change the fee on-the-fly update our QSetting when - // opening OptionsDialog, which queries Fee via the mapper. - if (!(payTxFee == CFeeRate(settings.value("nTransactionFee").toLongLong(), 1000))) - settings.setValue("nTransactionFee", (qint64)payTxFee.GetFeePerK()); - // Todo: Consider to revert back to use just payTxFee here, if we don't want - // -paytxfee to update our QSettings! - return settings.value("nTransactionFee"); - } case SpendZeroConfChange: return settings.value("bSpendZeroConfChange"); #endif @@ -276,14 +260,6 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in } break; #ifdef ENABLE_WALLET - case Fee: { // core option - can be changed on-the-fly - // Todo: Add is valid check and warn via message, if not - CAmount nTransactionFee(value.toLongLong()); - payTxFee = CFeeRate(nTransactionFee, 1000); - settings.setValue("nTransactionFee", qint64(nTransactionFee)); - emit transactionFeeChanged(nTransactionFee); - break; - } case SpendZeroConfChange: if (settings.value("bSpendZeroConfChange") != value) { settings.setValue("bSpendZeroConfChange", value); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index e2dc067edb..84fd49a7b8 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -34,7 +34,6 @@ public: ProxyUse, // bool ProxyIP, // QString ProxyPort, // int - Fee, // qint64 DisplayUnit, // BitcoinUnits::Unit ThirdPartyTxUrls, // QString Language, // QString @@ -84,7 +83,6 @@ private: signals: void displayUnitChanged(int unit); - void transactionFeeChanged(const CAmount&); void coinControlFeaturesChanged(bool); }; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index ce94131cce..46eb58ca43 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -7,6 +7,7 @@ #include "addresstablemodel.h" #include "bitcoinunits.h" +#include "clientmodel.h" #include "coincontroldialog.h" #include "guiutil.h" #include "optionsmodel.h" @@ -16,15 +17,20 @@ #include "base58.h" #include "coincontrol.h" #include "ui_interface.h" +#include "wallet.h" #include <QMessageBox> #include <QScrollBar> +#include <QSettings> #include <QTextDocument> SendCoinsDialog::SendCoinsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::SendCoinsDialog), - model(0) + clientModel(0), + model(0), + fNewRecipientAllowed(true), + fFeeMinimized(true) { ui->setupUi(this); @@ -72,7 +78,46 @@ SendCoinsDialog::SendCoinsDialog(QWidget *parent) : ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction); ui->labelCoinControlChange->addAction(clipboardChangeAction); - fNewRecipientAllowed = true; + // init transaction fee section + QSettings settings; + if (!settings.contains("fFeeSectionMinimized")) + settings.setValue("fFeeSectionMinimized", true); + if (!settings.contains("nFeeRadio") && settings.contains("nTransactionFee") && settings.value("nTransactionFee").toLongLong() > 0) // compatibility + settings.setValue("nFeeRadio", 1); // custom + if (!settings.contains("nFeeRadio")) + settings.setValue("nFeeRadio", 0); // recommended + if (!settings.contains("nCustomFeeRadio") && settings.contains("nTransactionFee") && settings.value("nTransactionFee").toLongLong() > 0) // compatibility + settings.setValue("nCustomFeeRadio", 1); // total at least + if (!settings.contains("nCustomFeeRadio")) + settings.setValue("nCustomFeeRadio", 0); // per kilobyte + if (!settings.contains("nSmartFeeSliderPosition")) + settings.setValue("nSmartFeeSliderPosition", 0); + if (!settings.contains("nTransactionFee")) + settings.setValue("nTransactionFee", (qint64)DEFAULT_TRANSACTION_FEE); + if (!settings.contains("fPayOnlyMinFee")) + settings.setValue("fPayOnlyMinFee", false); + if (!settings.contains("fSendFreeTransactions")) + settings.setValue("fSendFreeTransactions", false); + ui->groupFee->setId(ui->radioSmartFee, 0); + ui->groupFee->setId(ui->radioCustomFee, 1); + ui->groupFee->button((int)std::max(0, std::min(1, settings.value("nFeeRadio").toInt())))->setChecked(true); + ui->groupCustomFee->setId(ui->radioCustomPerKilobyte, 0); + ui->groupCustomFee->setId(ui->radioCustomAtLeast, 1); + ui->groupCustomFee->button((int)std::max(0, std::min(1, settings.value("nCustomFeeRadio").toInt())))->setChecked(true); + ui->sliderSmartFee->setValue(settings.value("nSmartFeeSliderPosition").toInt()); + ui->customFee->setValue(settings.value("nTransactionFee").toLongLong()); + ui->checkBoxMinimumFee->setChecked(settings.value("fPayOnlyMinFee").toBool()); + ui->checkBoxFreeTx->setChecked(settings.value("fSendFreeTransactions").toBool()); + minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool()); +} + +void SendCoinsDialog::setClientModel(ClientModel *clientModel) +{ + this->clientModel = clientModel; + + if (clientModel) { + connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(updateSmartFeeLabel())); + } } void SendCoinsDialog::setModel(WalletModel *model) @@ -94,18 +139,50 @@ void SendCoinsDialog::setModel(WalletModel *model) model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); connect(model, SIGNAL(balanceChanged(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount)), this, SLOT(setBalance(CAmount,CAmount,CAmount,CAmount,CAmount,CAmount))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + updateDisplayUnit(); // Coin Control connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(coinControlUpdateLabels())); connect(model->getOptionsModel(), SIGNAL(coinControlFeaturesChanged(bool)), this, SLOT(coinControlFeatureChanged(bool))); - connect(model->getOptionsModel(), SIGNAL(transactionFeeChanged(CAmount)), this, SLOT(coinControlUpdateLabels())); ui->frameCoinControl->setVisible(model->getOptionsModel()->getCoinControlFeatures()); coinControlUpdateLabels(); + + // fee section + connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, SLOT(updateSmartFeeLabel())); + connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, SLOT(updateGlobalFeeVariables())); + connect(ui->sliderSmartFee, SIGNAL(valueChanged(int)), this, SLOT(coinControlUpdateLabels())); + connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateFeeSectionControls())); + connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateGlobalFeeVariables())); + connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels())); + connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, SLOT(updateGlobalFeeVariables())); + connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels())); + connect(ui->customFee, SIGNAL(valueChanged()), this, SLOT(updateGlobalFeeVariables())); + connect(ui->customFee, SIGNAL(valueChanged()), this, SLOT(coinControlUpdateLabels())); + connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(setMinimumFee())); + connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateFeeSectionControls())); + connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables())); + connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels())); + connect(ui->checkBoxFreeTx, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables())); + connect(ui->checkBoxFreeTx, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels())); + ui->customFee->setSingleStep(CWallet::minTxFee.GetFeePerK()); + updateFeeSectionControls(); + updateMinFeeLabel(); + updateSmartFeeLabel(); + updateGlobalFeeVariables(); } } SendCoinsDialog::~SendCoinsDialog() { + QSettings settings; + settings.setValue("fFeeSectionMinimized", fFeeMinimized); + settings.setValue("nFeeRadio", ui->groupFee->checkedId()); + settings.setValue("nCustomFeeRadio", ui->groupCustomFee->checkedId()); + settings.setValue("nSmartFeeSliderPosition", ui->sliderSmartFee->value()); + settings.setValue("nTransactionFee", (qint64)ui->customFee->value()); + settings.setValue("fPayOnlyMinFee", ui->checkBoxMinimumFee->isChecked()); + settings.setValue("fSendFreeTransactions", ui->checkBoxFreeTx->isChecked()); + delete ui; } @@ -214,6 +291,9 @@ void SendCoinsDialog::on_sendButton_clicked() questionString.append(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), txFee)); questionString.append("</span> "); questionString.append(tr("added as transaction fee")); + + // append transaction size + questionString.append(" (" + QString::number((double)currentTransaction.getTransactionSize() / 1000) + " kB)"); } // add total amount in all subdivision units @@ -384,7 +464,7 @@ bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv) return true; } -void SendCoinsDialog::setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, +void SendCoinsDialog::setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, const CAmount& watchBalance, const CAmount& watchUnconfirmedBalance, const CAmount& watchImmatureBalance) { Q_UNUSED(unconfirmedBalance); @@ -402,6 +482,9 @@ void SendCoinsDialog::setBalance(const CAmount& balance, const CAmount& unconfir void SendCoinsDialog::updateDisplayUnit() { setBalance(model->getBalance(), 0, 0, 0, 0, 0); + ui->customFee->setDisplayUnit(model->getOptionsModel()->getDisplayUnit()); + updateMinFeeLabel(); + updateSmartFeeLabel(); } void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg) @@ -438,6 +521,9 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn msgParams.first = tr("The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); msgParams.second = CClientUIInterface::MSG_ERROR; break; + case WalletModel::InsaneFee: + msgParams.first = tr("A fee higher than %1 is considered an insanely high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), 10000000)); + break; // included to prevent a compiler warning. case WalletModel::OK: default: @@ -447,6 +533,110 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn emit message(tr("Send Coins"), msgParams.first, msgParams.second); } +void SendCoinsDialog::minimizeFeeSection(bool fMinimize) +{ + ui->labelFeeMinimized->setVisible(fMinimize); + ui->buttonChooseFee ->setVisible(fMinimize); + ui->buttonMinimizeFee->setVisible(!fMinimize); + ui->frameFeeSelection->setVisible(!fMinimize); + ui->horizontalLayoutSmartFee->setContentsMargins(0, (fMinimize ? 0 : 6), 0, 0); + fFeeMinimized = fMinimize; +} + +void SendCoinsDialog::on_buttonChooseFee_clicked() +{ + minimizeFeeSection(false); +} + +void SendCoinsDialog::on_buttonMinimizeFee_clicked() +{ + updateFeeMinimizedLabel(); + minimizeFeeSection(true); +} + +void SendCoinsDialog::setMinimumFee() +{ + ui->radioCustomPerKilobyte->setChecked(true); + ui->customFee->setValue(CWallet::minTxFee.GetFeePerK()); +} + +void SendCoinsDialog::updateFeeSectionControls() +{ + ui->sliderSmartFee ->setEnabled(ui->radioSmartFee->isChecked()); + ui->labelSmartFee ->setEnabled(ui->radioSmartFee->isChecked()); + ui->labelSmartFee2 ->setEnabled(ui->radioSmartFee->isChecked()); + ui->labelSmartFee3 ->setEnabled(ui->radioSmartFee->isChecked()); + ui->labelFeeEstimation ->setEnabled(ui->radioSmartFee->isChecked()); + ui->labelSmartFeeNormal ->setEnabled(ui->radioSmartFee->isChecked()); + ui->labelSmartFeeFast ->setEnabled(ui->radioSmartFee->isChecked()); + ui->checkBoxMinimumFee ->setEnabled(ui->radioCustomFee->isChecked()); + ui->labelMinFeeWarning ->setEnabled(ui->radioCustomFee->isChecked()); + ui->radioCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); + ui->radioCustomAtLeast ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); + ui->customFee ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); +} + +void SendCoinsDialog::updateGlobalFeeVariables() +{ + if (ui->radioSmartFee->isChecked()) + { + nTxConfirmTarget = (int)25 - (int)std::max(0, std::min(24, ui->sliderSmartFee->value())); + payTxFee = CFeeRate(0); + } + else + { + nTxConfirmTarget = 25; + payTxFee = CFeeRate(ui->customFee->value()); + fPayAtLeastCustomFee = ui->radioCustomAtLeast->isChecked(); + } + + fSendFreeTransactions = ui->checkBoxFreeTx->isChecked(); +} + +void SendCoinsDialog::updateFeeMinimizedLabel() +{ + if(!model || !model->getOptionsModel()) + return; + + if (ui->radioSmartFee->isChecked()) + ui->labelFeeMinimized->setText(ui->labelSmartFee->text()); + else { + ui->labelFeeMinimized->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), ui->customFee->value()) + + ((ui->radioCustomPerKilobyte->isChecked()) ? "/kB" : "")); + } +} + +void SendCoinsDialog::updateMinFeeLabel() +{ + if (model && model->getOptionsModel()) + ui->checkBoxMinimumFee->setText(tr("Pay only the minimum fee of %1").arg( + BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), CWallet::minTxFee.GetFeePerK()) + "/kB") + ); +} + +void SendCoinsDialog::updateSmartFeeLabel() +{ + if(!model || !model->getOptionsModel()) + return; + + int nBlocksToConfirm = (int)25 - (int)std::max(0, std::min(24, ui->sliderSmartFee->value())); + CFeeRate feeRate = mempool.estimateFee(nBlocksToConfirm); + if (feeRate <= CFeeRate(0)) // not enough data => minfee + { + ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), CWallet::minTxFee.GetFeePerK()) + "/kB"); + ui->labelSmartFee2->show(); // (Smart fee not initialized yet. This usually takes a few blocks...) + ui->labelFeeEstimation->setText(""); + } + else + { + ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK()) + "/kB"); + ui->labelSmartFee2->hide(); + ui->labelFeeEstimation->setText(tr("Estimated to begin confirmation within %1 block(s).").arg(nBlocksToConfirm)); + } + + updateFeeMinimizedLabel(); +} + // Coin Control: copy label "Quantity" to clipboard void SendCoinsDialog::coinControlClipboardQuantity() { @@ -462,19 +652,19 @@ void SendCoinsDialog::coinControlClipboardAmount() // Coin Control: copy label "Fee" to clipboard void SendCoinsDialog::coinControlClipboardFee() { - GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" "))); + GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")).replace("~", "")); } // Coin Control: copy label "After fee" to clipboard void SendCoinsDialog::coinControlClipboardAfterFee() { - GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" "))); + GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace("~", "")); } // Coin Control: copy label "Bytes" to clipboard void SendCoinsDialog::coinControlClipboardBytes() { - GUIUtil::setClipboard(ui->labelCoinControlBytes->text()); + GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace("~", "")); } // Coin Control: copy label "Priority" to clipboard @@ -492,7 +682,7 @@ void SendCoinsDialog::coinControlClipboardLowOutput() // Coin Control: copy label "Change" to clipboard void SendCoinsDialog::coinControlClipboardChange() { - GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" "))); + GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")).replace("~", "")); } // Coin Control: settings menu - coin control enabled/disabled by user diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index eec661cbd0..15d39782a1 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -10,6 +10,7 @@ #include <QDialog> #include <QString> +class ClientModel; class OptionsModel; class SendCoinsEntry; class SendCoinsRecipient; @@ -31,6 +32,7 @@ public: explicit SendCoinsDialog(QWidget *parent = 0); ~SendCoinsDialog(); + void setClientModel(ClientModel *clientModel); void setModel(WalletModel *model); /** Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907). @@ -52,16 +54,22 @@ public slots: private: Ui::SendCoinsDialog *ui; + ClientModel *clientModel; WalletModel *model; bool fNewRecipientAllowed; + bool fFeeMinimized; // Process WalletModel::SendCoinsReturn and generate a pair consisting // of a message and message flags for use in emit message(). // Additional parameter msgArg can be used via .arg(msgArg). void processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg = QString()); + void minimizeFeeSection(bool fMinimize); + void updateFeeMinimizedLabel(); private slots: void on_sendButton_clicked(); + void on_buttonChooseFee_clicked(); + void on_buttonMinimizeFee_clicked(); void removeEntry(SendCoinsEntry* entry); void updateDisplayUnit(); void coinControlFeatureChanged(bool); @@ -77,6 +85,11 @@ private slots: void coinControlClipboardPriority(); void coinControlClipboardLowOutput(); void coinControlClipboardChange(); + void setMinimumFee(); + void updateFeeSectionControls(); + void updateMinFeeLabel(); + void updateSmartFeeLabel(); + void updateGlobalFeeVariables(); signals: // Fired when a message should be reported to the user diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index f7b1552f3e..b20465794d 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -277,6 +277,10 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact CClientUIInterface::MSG_ERROR); return TransactionCreationFailed; } + + // reject insane fee > 0.1 bitcoin + if (nFeeRequired > 10000000) + return InsaneFee; } return SendCoinsReturn(OK); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 0c6077963d..d7e391f8d1 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -110,7 +110,8 @@ public: AmountWithFeeExceedsBalance, DuplicateAddress, TransactionCreationFailed, // Error returned when wallet is still locked - TransactionCommitFailed + TransactionCommitFailed, + InsaneFee }; enum EncryptionStatus diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index ddd2d09bb5..e9e20c7d51 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -31,6 +31,11 @@ CWalletTx *WalletModelTransaction::getTransaction() return walletTransaction; } +unsigned int WalletModelTransaction::getTransactionSize() +{ + return (!walletTransaction ? 0 : (::GetSerializeSize(*(CTransaction*)walletTransaction, SER_NETWORK, PROTOCOL_VERSION))); +} + CAmount WalletModelTransaction::getTransactionFee() { return fee; diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h index a880384ed6..4272529abe 100644 --- a/src/qt/walletmodeltransaction.h +++ b/src/qt/walletmodeltransaction.h @@ -25,6 +25,7 @@ public: QList<SendCoinsRecipient> getRecipients(); CWalletTx *getTransaction(); + unsigned int getTransactionSize(); void setTransactionFee(const CAmount& newFee); CAmount getTransactionFee(); diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index 3b8fdd7e5f..9bab180108 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -101,6 +101,7 @@ void WalletView::setClientModel(ClientModel *clientModel) this->clientModel = clientModel; overviewPage->setClientModel(clientModel); + sendCoinsPage->setClientModel(clientModel); } void WalletView::setWalletModel(WalletModel *walletModel) diff --git a/src/random.h b/src/random.h index ec73d910c4..aa55ca2b6f 100644 --- a/src/random.h +++ b/src/random.h @@ -26,7 +26,7 @@ uint256 GetRandHash(); /** * Seed insecure_rand using the random pool. - * @param Deterministic Use a determinstic seed + * @param Deterministic Use a deterministic seed */ void seed_insecure_rand(bool fDeterministic = false); diff --git a/src/rest.cpp b/src/rest.cpp index 9a8793a517..6285784af5 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -1,22 +1,24 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <boost/algorithm/string.hpp> +#include "primitives/block.h" +#include "primitives/transaction.h" +#include "main.h" #include "rpcserver.h" #include "streams.h" +#include "sync.h" #include "utilstrencodings.h" -#include "core/block.h" -#include "core/transaction.h" #include "version.h" -#include "main.h" -#include "sync.h" + +#include <boost/algorithm/string.hpp> using namespace std; using namespace json_spirit; enum RetFormat { + RF_UNDEF, RF_BINARY, RF_HEX, RF_JSON, @@ -24,14 +26,16 @@ enum RetFormat { static const struct { enum RetFormat rf; - const char *name; + const char* name; } rf_names[] = { - { RF_BINARY, "binary" }, // default, if match not found - { RF_HEX, "hex" }, - { RF_JSON, "json" }, + {RF_UNDEF, ""}, + {RF_BINARY, "bin"}, + {RF_HEX, "hex"}, + {RF_JSON, "json"}, }; -class RestErr { +class RestErr +{ public: enum HTTPStatusCode status; string message; @@ -48,15 +52,34 @@ static RestErr RESTERR(enum HTTPStatusCode status, string message) return re; } -static enum RetFormat ParseDataFormat(const string& format) +static enum RetFormat ParseDataFormat(vector<string>& params, const string strReq) { - for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++) - if (format == rf_names[i].name) - return rf_names[i].rf; + boost::split(params, strReq, boost::is_any_of(".")); + if (params.size() > 1) { + for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++) + if (params[1] == rf_names[i].name) + return rf_names[i].rf; + } return rf_names[0].rf; } +static string AvailableDataFormatsString() +{ + string formats = ""; + for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++) + if (strlen(rf_names[i].name) > 0) { + formats.append("."); + formats.append(rf_names[i].name); + formats.append(", "); + } + + if (formats.length() > 0) + return formats.substr(0, formats.length() - 2); + + return formats; +} + static bool ParseHashStr(const string& strReq, uint256& v) { if (!IsHex(strReq) || (strReq.size() != 64)) @@ -66,15 +89,13 @@ static bool ParseHashStr(const string& strReq, uint256& v) return true; } -static bool rest_block(AcceptedConnection *conn, +static bool rest_block(AcceptedConnection* conn, string& strReq, map<string, string>& mapHeaders, bool fRun) { vector<string> params; - boost::split(params, strReq, boost::is_any_of("/")); - - enum RetFormat rf = ParseDataFormat(params.size() > 1 ? params[1] : string("")); + enum RetFormat rf = ParseDataFormat(params, strReq); string hashStr = params[0]; uint256 hash; @@ -99,12 +120,12 @@ static bool rest_block(AcceptedConnection *conn, switch (rf) { case RF_BINARY: { string binaryBlock = ssBlock.str(); - conn->stream() << HTTPReply(HTTP_OK, binaryBlock, fRun, true, "application/octet-stream") << binaryBlock << std::flush; + conn->stream() << HTTPReplyHeader(HTTP_OK, fRun, binaryBlock.size(), "application/octet-stream") << binaryBlock << std::flush; return true; } case RF_HEX: { - string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";; + string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n"; conn->stream() << HTTPReply(HTTP_OK, strHex, fRun, false, "text/plain") << std::flush; return true; } @@ -114,22 +135,24 @@ static bool rest_block(AcceptedConnection *conn, string strJSON = write_string(Value(objBlock), false) + "\n"; conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush; return true; - } + } + + default: { + throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")"); + } } // not reached - return true; // continue to process further HTTP reqs on this cxn + return true; // continue to process further HTTP reqs on this cxn } -static bool rest_tx(AcceptedConnection *conn, +static bool rest_tx(AcceptedConnection* conn, string& strReq, map<string, string>& mapHeaders, bool fRun) { vector<string> params; - boost::split(params, strReq, boost::is_any_of("/")); - - enum RetFormat rf = ParseDataFormat(params.size() > 1 ? params[1] : string("")); + enum RetFormat rf = ParseDataFormat(params, strReq); string hashStr = params[0]; uint256 hash; @@ -147,12 +170,12 @@ static bool rest_tx(AcceptedConnection *conn, switch (rf) { case RF_BINARY: { string binaryTx = ssTx.str(); - conn->stream() << HTTPReply(HTTP_OK, binaryTx, fRun, true, "application/octet-stream") << binaryTx << std::flush; + conn->stream() << HTTPReplyHeader(HTTP_OK, fRun, binaryTx.size(), "application/octet-stream") << binaryTx << std::flush; return true; } case RF_HEX: { - string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";; + string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n"; conn->stream() << HTTPReply(HTTP_OK, strHex, fRun, false, "text/plain") << std::flush; return true; } @@ -163,30 +186,38 @@ static bool rest_tx(AcceptedConnection *conn, string strJSON = write_string(Value(objTx), false) + "\n"; conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush; return true; - } + } + + default: { + throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")"); + } } // not reached - return true; // continue to process further HTTP reqs on this cxn + return true; // continue to process further HTTP reqs on this cxn } static const struct { - const char *prefix; - bool (*handler)(AcceptedConnection *conn, + const char* prefix; + bool (*handler)(AcceptedConnection* conn, string& strURI, map<string, string>& mapHeaders, bool fRun); } uri_prefixes[] = { - { "/rest/tx/", rest_tx }, - { "/rest/block/", rest_block }, + {"/rest/tx/", rest_tx}, + {"/rest/block/", rest_block}, }; -bool HTTPReq_REST(AcceptedConnection *conn, +bool HTTPReq_REST(AcceptedConnection* conn, string& strURI, map<string, string>& mapHeaders, bool fRun) { try { + std::string statusmessage; + if (RPCIsInWarmup(&statusmessage)) + throw RESTERR(HTTP_SERVICE_UNAVAILABLE, "Service temporarily unavailable: " + statusmessage); + for (unsigned int i = 0; i < ARRAYLEN(uri_prefixes); i++) { unsigned int plen = strlen(uri_prefixes[i].prefix); if (strURI.substr(0, plen) == uri_prefixes[i].prefix) { @@ -194,8 +225,7 @@ bool HTTPReq_REST(AcceptedConnection *conn, return uri_prefixes[i].handler(conn, strReq, mapHeaders, fRun); } } - } - catch (RestErr& re) { + } catch (RestErr& re) { conn->stream() << HTTPReply(re.status, re.message + "\r\n", false, false, "text/plain") << std::flush; return false; } @@ -203,4 +233,3 @@ bool HTTPReq_REST(AcceptedConnection *conn, conn->stream() << HTTPError(HTTP_NOT_FOUND, false) << std::flush; return false; } - diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index a7cd63bd95..924f416904 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "checkpoints.h" @@ -319,7 +319,7 @@ Value gettxoutsetinfo(const Array& params, bool fHelp) Object ret; CCoinsStats stats; - pcoinsTip->Flush(); + FlushStateToDisk(); if (pcoinsTip->GetStats(stats)) { ret.push_back(Pair("height", (int64_t)stats.nHeight)); ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); @@ -468,7 +468,7 @@ Value getblockchaininfo(const Array& params, bool fHelp) return obj; } -/* Comparison function for sorting the getchaintips heads. */ +/** Comparison function for sorting the getchaintips heads. */ struct CompareBlocksByHeight { bool operator()(const CBlockIndex* a, const CBlockIndex* b) const @@ -496,13 +496,21 @@ Value getchaintips(const Array& params, bool fHelp) " \"height\": xxxx, (numeric) height of the chain tip\n" " \"hash\": \"xxxx\", (string) block hash of the tip\n" " \"branchlen\": 0 (numeric) zero for main chain\n" + " \"status\": \"active\" (string) \"active\" for the main chain\n" " },\n" " {\n" " \"height\": xxxx,\n" " \"hash\": \"xxxx\",\n" " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" + " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" " }\n" "]\n" + "Possible values for status:\n" + "1. \"invalid\" This branch contains at least one invalid block\n" + "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" + "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" + "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" + "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" "\nExamples:\n" + HelpExampleCli("getchaintips", "") + HelpExampleRpc("getchaintips", "") @@ -521,6 +529,9 @@ Value getchaintips(const Array& params, bool fHelp) setTips.erase(pprev); } + // Always report the currently active tip. + setTips.insert(chainActive.Tip()); + /* Construct the output array. */ Array res; BOOST_FOREACH(const CBlockIndex* block, setTips) @@ -532,6 +543,28 @@ Value getchaintips(const Array& params, bool fHelp) const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight; obj.push_back(Pair("branchlen", branchLen)); + string status; + if (chainActive.Contains(block)) { + // This block is part of the currently active chain. + status = "active"; + } else if (block->nStatus & BLOCK_FAILED_MASK) { + // This block or one of its ancestors is invalid. + status = "invalid"; + } else if (block->nChainTx == 0) { + // This block cannot be connected because full block data for it or one of its parents is missing. + status = "headers-only"; + } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) { + // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized. + status = "valid-fork"; + } else if (block->IsValid(BLOCK_VALID_TREE)) { + // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain. + status = "valid-headers"; + } else { + // No clue. + status = "unknown"; + } + obj.push_back(Pair("status", status)); + res.push_back(obj); } @@ -561,3 +594,79 @@ Value getmempoolinfo(const Array& params, bool fHelp) return ret; } +Value invalidateblock(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "invalidateblock \"hash\"\n" + "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the block to mark as invalid\n" + "\nResult:\n" + "\nExamples:\n" + + HelpExampleCli("invalidateblock", "\"blockhash\"") + + HelpExampleRpc("invalidateblock", "\"blockhash\"") + ); + + std::string strHash = params[0].get_str(); + uint256 hash(strHash); + CValidationState state; + + { + LOCK(cs_main); + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlockIndex* pblockindex = mapBlockIndex[hash]; + InvalidateBlock(state, pblockindex); + } + + if (state.IsValid()) { + ActivateBestChain(state); + } + + if (!state.IsValid()) { + throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); + } + + return Value::null; +} + +Value reconsiderblock(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "reconsiderblock \"hash\"\n" + "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" + "This can be used to undo the effects of invalidateblock.\n" + "\nArguments:\n" + "1. hash (string, required) the hash of the block to reconsider\n" + "\nResult:\n" + "\nExamples:\n" + + HelpExampleCli("reconsiderblock", "\"blockhash\"") + + HelpExampleRpc("reconsiderblock", "\"blockhash\"") + ); + + std::string strHash = params[0].get_str(); + uint256 hash(strHash); + CValidationState state; + + { + LOCK(cs_main); + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlockIndex* pblockindex = mapBlockIndex[hash]; + ReconsiderBlock(state, pblockindex); + } + + if (state.IsValid()) { + ActivateBestChain(state); + } + + if (!state.IsValid()) { + throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); + } + + return Value::null; +} diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 7a1f1918f6..03ce9acbbf 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "rpcclient.h" @@ -18,8 +18,8 @@ using namespace json_spirit; class CRPCConvertParam { public: - std::string methodName; // method whose params want conversion - int paramIdx; // 0-based idx of param to convert + std::string methodName; //! method whose params want conversion + int paramIdx; //! 0-based idx of param to convert }; static const CRPCConvertParam vRPCConvertParams[] = @@ -116,7 +116,7 @@ CRPCConvertTable::CRPCConvertTable() static CRPCConvertTable rpcCvtTable; -// Convert strings to command-specific RPC representation +/** Convert strings to command-specific RPC representation */ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams) { Array params; diff --git a/src/rpcclient.h b/src/rpcclient.h index cd11f177e8..a91c2eb033 100644 --- a/src/rpcclient.h +++ b/src/rpcclient.h @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_RPCCLIENT_H diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 9da0a7d091..8b95373cff 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "base58.h" @@ -112,6 +112,7 @@ Value importprivkey(const Array& params, bool fHelp) if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range"); CPubKey pubkey = key.GetPubKey(); + assert(key.VerifyPubKey(pubkey)); CKeyID vchAddress = pubkey.GetID(); { pwalletMain->MarkDirty(); @@ -253,6 +254,7 @@ Value importwallet(const Array& params, bool fHelp) continue; CKey key = vchSecret.GetKey(); CPubKey pubkey = key.GetPubKey(); + assert(key.VerifyPubKey(pubkey)); CKeyID keyid = pubkey.GetID(); if (pwalletMain->HaveKey(keyid)) { LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString()); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 2bde02c0a1..837a7593b6 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "amount.h" @@ -28,9 +28,11 @@ using namespace json_spirit; using namespace std; -// Return average network hashes per second based on the last 'lookup' blocks, -// or from the last difficulty change if 'lookup' is nonpositive. -// If 'height' is nonnegative, compute the estimate at the time when a given block was found. +/** + * Return average network hashes per second based on the last 'lookup' blocks, + * or from the last difficulty change if 'lookup' is nonpositive. + * If 'height' is nonnegative, compute the estimate at the time when a given block was found. + */ Value GetNetworkHashPS(int lookup, int height) { CBlockIndex *pb = chainActive.Tip(); @@ -297,6 +299,25 @@ Value prioritisetransaction(const Array& params, bool fHelp) } +// NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller +static Value BIP22ValidationResult(const CValidationState& state) +{ + if (state.IsValid()) + return Value::null; + + std::string strRejectReason = state.GetRejectReason(); + if (state.IsError()) + throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason); + if (state.IsInvalid()) + { + if (strRejectReason.empty()) + return "rejected"; + return strRejectReason; + } + // Should be impossible + return "valid?"; +} + Value getblocktemplate(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) @@ -374,6 +395,36 @@ Value getblocktemplate(const Array& params, bool fHelp) else throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); lpval = find_value(oparam, "longpollid"); + + if (strMode == "proposal") + { + const Value& dataval = find_value(oparam, "data"); + if (dataval.type() != str_type) + throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal"); + + CBlock block; + if (!DecodeHexBlk(block, dataval.get_str())) + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); + + uint256 hash = block.GetHash(); + BlockMap::iterator mi = mapBlockIndex.find(hash); + if (mi != mapBlockIndex.end()) { + CBlockIndex *pindex = mi->second; + if (pindex->IsValid(BLOCK_VALID_SCRIPTS)) + return "duplicate"; + if (pindex->nStatus & BLOCK_FAILED_MASK) + return "duplicate-invalid"; + return "duplicate-inconclusive"; + } + + CBlockIndex* const pindexPrev = chainActive.Tip(); + // TestBlockValidity only supports blocks built on the current Tip + if (block.hashPrevBlock != pindexPrev->GetBlockHash()) + return "inconclusive-not-best-prevblk"; + CValidationState state; + TestBlockValidity(state, block, pindexPrev, false, true); + return BIP22ValidationResult(state); + } } if (strMode != "template") @@ -476,6 +527,8 @@ Value getblocktemplate(const Array& params, bool fHelp) UpdateTime(pblock, pindexPrev); pblock->nNonce = 0; + static const Array aCaps = boost::assign::list_of("proposal"); + Array transactions; map<uint256, int64_t> setTxIndex; int i = 0; @@ -522,6 +575,7 @@ Value getblocktemplate(const Array& params, bool fHelp) } Object result; + result.push_back(Pair("capabilities", aCaps)); result.push_back(Pair("version", pblock->nVersion)); result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); result.push_back(Pair("transactions", transactions)); @@ -580,41 +634,39 @@ Value submitblock(const Array& params, bool fHelp) + HelpExampleRpc("submitblock", "\"mydata\"") ); - vector<unsigned char> blockData(ParseHex(params[0].get_str())); - CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION); - CBlock pblock; - try { - ssBlock >> pblock; - } - catch (const std::exception &) { + CBlock block; + if (!DecodeHexBlk(block, params[0].get_str())) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); + + uint256 hash = block.GetHash(); + BlockMap::iterator mi = mapBlockIndex.find(hash); + if (mi != mapBlockIndex.end()) { + CBlockIndex *pindex = mi->second; + if (pindex->IsValid(BLOCK_VALID_SCRIPTS)) + return "duplicate"; + if (pindex->nStatus & BLOCK_FAILED_MASK) + return "duplicate-invalid"; + // Otherwise, we might only have the header - process the block before returning } CValidationState state; - submitblock_StateCatcher sc(pblock.GetHash()); + submitblock_StateCatcher sc(block.GetHash()); RegisterValidationInterface(&sc); - bool fAccepted = ProcessNewBlock(state, NULL, &pblock); + bool fAccepted = ProcessNewBlock(state, NULL, &block); UnregisterValidationInterface(&sc); + if (mi != mapBlockIndex.end()) + { + if (fAccepted && !sc.found) + return "duplicate-inconclusive"; + return "duplicate"; + } if (fAccepted) { if (!sc.found) return "inconclusive"; state = sc.state; } - if (state.IsError()) - { - std::string strRejectReason = state.GetRejectReason(); - throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason); - } - if (state.IsInvalid()) - { - std::string strRejectReason = state.GetRejectReason(); - if (strRejectReason.empty()) - return "rejected"; - return strRejectReason; - } - - return Value::null; + return BIP22ValidationResult(state); } Value estimatefee(const Array& params, bool fHelp) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 31eaae6162..90b9c99caa 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "base58.h" @@ -30,7 +30,7 @@ using namespace std; /** * @note Do not add or change anything in the information returned by this - * method. `getinfo` exists for backwards-compatibilty only. It combines + * method. `getinfo` exists for backwards-compatibility only. It combines * information from wildly different sources in the program, which is a mess, * and is thus planned to be deprecated eventually. * @@ -198,9 +198,9 @@ Value validateaddress(const Array& params, bool fHelp) return ret; } -// -// Used by addmultisigaddress / createmultisig: -// +/** + * Used by addmultisigaddress / createmultisig: + */ CScript _createmultisig_redeemScript(const Array& params) { int nRequired = params[0].get_int(); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 46b5f3d7ad..6ddbd62fca 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "rpcserver.h" diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index c2ce73106f..2f7c491f3d 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "rpcprotocol.h" @@ -30,15 +30,15 @@ using namespace boost; using namespace boost::asio; using namespace json_spirit; -// Number of bytes to allocate and read at most at once in post data +//! Number of bytes to allocate and read at most at once in post data const size_t POST_READ_SIZE = 256 * 1024; -// -// HTTP protocol -// -// This ain't Apache. We're just using HTTP header for the length field -// and to be compatible with other JSON-RPC implementations. -// +/** + * HTTP protocol + * + * This ain't Apache. We're just using HTTP header for the length field + * and to be compatible with other JSON-RPC implementations. + */ string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders) { @@ -246,15 +246,15 @@ int ReadHTTPMessage(std::basic_istream<char>& stream, map<string, return HTTP_OK; } -// -// JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, -// but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were -// unspecified (HTTP errors and contents of 'error'). -// -// 1.0 spec: http://json-rpc.org/wiki/specification -// 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html -// http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx -// +/** + * JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, + * but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were + * unspecified (HTTP errors and contents of 'error'). + * + * 1.0 spec: http://json-rpc.org/wiki/specification + * 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html + * http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx + */ string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id) { diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index f0d0f3445c..f7cd50f9f6 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_RPCPROTOCOL_H @@ -19,7 +19,7 @@ #include "json/json_spirit_utils.h" #include "json/json_spirit_writer_template.h" -// HTTP status codes +//! HTTP status codes enum HTTPStatusCode { HTTP_OK = 200, @@ -28,58 +28,59 @@ enum HTTPStatusCode HTTP_FORBIDDEN = 403, HTTP_NOT_FOUND = 404, HTTP_INTERNAL_SERVER_ERROR = 500, + HTTP_SERVICE_UNAVAILABLE = 503, }; -// Bitcoin RPC error codes +//! Bitcoin RPC error codes enum RPCErrorCode { - // Standard JSON-RPC 2.0 errors + //! Standard JSON-RPC 2.0 errors RPC_INVALID_REQUEST = -32600, RPC_METHOD_NOT_FOUND = -32601, RPC_INVALID_PARAMS = -32602, RPC_INTERNAL_ERROR = -32603, RPC_PARSE_ERROR = -32700, - // General application defined errors - RPC_MISC_ERROR = -1, // std::exception thrown in command handling - RPC_FORBIDDEN_BY_SAFE_MODE = -2, // Server is in safe mode, and command is not allowed in safe mode - RPC_TYPE_ERROR = -3, // Unexpected type was passed as parameter - RPC_INVALID_ADDRESS_OR_KEY = -5, // Invalid address or key - RPC_OUT_OF_MEMORY = -7, // Ran out of memory during operation - RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter - RPC_DATABASE_ERROR = -20, // Database error - RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format - RPC_VERIFY_ERROR = -25, // General error during transaction or block submission - RPC_VERIFY_REJECTED = -26, // Transaction or block was rejected by network rules - RPC_VERIFY_ALREADY_IN_CHAIN = -27, // Transaction already in chain - RPC_IN_WARMUP = -28, // Client still warming up + //! General application defined errors + RPC_MISC_ERROR = -1, //! std::exception thrown in command handling + RPC_FORBIDDEN_BY_SAFE_MODE = -2, //! Server is in safe mode, and command is not allowed in safe mode + RPC_TYPE_ERROR = -3, //! Unexpected type was passed as parameter + RPC_INVALID_ADDRESS_OR_KEY = -5, //! Invalid address or key + RPC_OUT_OF_MEMORY = -7, //! Ran out of memory during operation + RPC_INVALID_PARAMETER = -8, //! Invalid, missing or duplicate parameter + RPC_DATABASE_ERROR = -20, //! Database error + RPC_DESERIALIZATION_ERROR = -22, //! Error parsing or validating structure in raw format + RPC_VERIFY_ERROR = -25, //! General error during transaction or block submission + RPC_VERIFY_REJECTED = -26, //! Transaction or block was rejected by network rules + RPC_VERIFY_ALREADY_IN_CHAIN = -27, //! Transaction already in chain + RPC_IN_WARMUP = -28, //! Client still warming up - // Aliases for backward compatibility + //! Aliases for backward compatibility RPC_TRANSACTION_ERROR = RPC_VERIFY_ERROR, RPC_TRANSACTION_REJECTED = RPC_VERIFY_REJECTED, RPC_TRANSACTION_ALREADY_IN_CHAIN= RPC_VERIFY_ALREADY_IN_CHAIN, - // P2P client errors - RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected - RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, // Still downloading initial blocks - RPC_CLIENT_NODE_ALREADY_ADDED = -23, // Node is already added - RPC_CLIENT_NODE_NOT_ADDED = -24, // Node has not been added before + //! P2P client errors + RPC_CLIENT_NOT_CONNECTED = -9, //! Bitcoin is not connected + RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, //! Still downloading initial blocks + RPC_CLIENT_NODE_ALREADY_ADDED = -23, //! Node is already added + RPC_CLIENT_NODE_NOT_ADDED = -24, //! Node has not been added before - // Wallet errors - RPC_WALLET_ERROR = -4, // Unspecified problem with wallet (key not found etc.) - RPC_WALLET_INSUFFICIENT_FUNDS = -6, // Not enough funds in wallet or account - RPC_WALLET_INVALID_ACCOUNT_NAME = -11, // Invalid account name - RPC_WALLET_KEYPOOL_RAN_OUT = -12, // Keypool ran out, call keypoolrefill first - RPC_WALLET_UNLOCK_NEEDED = -13, // Enter the wallet passphrase with walletpassphrase first - RPC_WALLET_PASSPHRASE_INCORRECT = -14, // The wallet passphrase entered was incorrect - RPC_WALLET_WRONG_ENC_STATE = -15, // Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) - RPC_WALLET_ENCRYPTION_FAILED = -16, // Failed to encrypt the wallet - RPC_WALLET_ALREADY_UNLOCKED = -17, // Wallet is already unlocked + //! Wallet errors + RPC_WALLET_ERROR = -4, //! Unspecified problem with wallet (key not found etc.) + RPC_WALLET_INSUFFICIENT_FUNDS = -6, //! Not enough funds in wallet or account + RPC_WALLET_INVALID_ACCOUNT_NAME = -11, //! Invalid account name + RPC_WALLET_KEYPOOL_RAN_OUT = -12, //! Keypool ran out, call keypoolrefill first + RPC_WALLET_UNLOCK_NEEDED = -13, //! Enter the wallet passphrase with walletpassphrase first + RPC_WALLET_PASSPHRASE_INCORRECT = -14, //! The wallet passphrase entered was incorrect + RPC_WALLET_WRONG_ENC_STATE = -15, //! Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) + RPC_WALLET_ENCRYPTION_FAILED = -16, //! Failed to encrypt the wallet + RPC_WALLET_ALREADY_UNLOCKED = -17, //! Wallet is already unlocked }; -// -// IOStream device that speaks SSL but can also speak non-SSL -// +/** + * IOStream device that speaks SSL but can also speak non-SSL + */ template <typename Protocol> class SSLIOStreamDevice : public boost::iostreams::device<boost::iostreams::bidirectional> { public: diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index d3ce3b3191..8de15ff9e2 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -1,10 +1,10 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "base58.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "core_io.h" #include "init.h" #include "keystore.h" diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 01005c1cee..90695611f2 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -160,7 +160,7 @@ string CRPCTable::help(string strCommand) const // We already filter duplicates, but these deprecated screw up the sort order if (strMethod.find("label") != string::npos) continue; - if (strCommand != "" && strMethod != strCommand) + if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand) continue; #ifdef ENABLE_WALLET if (pcmd->reqWallet && !pwalletMain) @@ -246,7 +246,6 @@ static const CRPCCommand vRPCCommands[] = { "control", "getinfo", &getinfo, true, false, false }, /* uses wallet if enabled */ { "control", "help", &help, true, true, false }, { "control", "stop", &stop, true, true, false }, - { "control", "setmocktime", &setmocktime, true, false, false }, /* P2P networking */ { "network", "getnetworkinfo", &getnetworkinfo, true, false, false }, @@ -270,6 +269,8 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "gettxout", &gettxout, true, false, false }, { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, false, false }, { "blockchain", "verifychain", &verifychain, true, false, false }, + { "blockchain", "invalidateblock", &invalidateblock, true, true, false }, + { "blockchain", "reconsiderblock", &reconsiderblock, true, true, false }, /* Mining */ { "mining", "getblocktemplate", &getblocktemplate, true, false, false }, @@ -300,6 +301,11 @@ static const CRPCCommand vRPCCommands[] = { "util", "estimatefee", &estimatefee, true, true, false }, { "util", "estimatepriority", &estimatepriority, true, true, false }, + /* Not shown in help */ + { "hidden", "invalidateblock", &invalidateblock, true, true, false }, + { "hidden", "reconsiderblock", &reconsiderblock, true, true, false }, + { "hidden", "setmocktime", &setmocktime, true, false, false }, + #ifdef ENABLE_WALLET /* Wallet */ { "wallet", "addmultisigaddress", &addmultisigaddress, true, false, true }, @@ -565,13 +571,8 @@ void StartRPCThreads() { unsigned char rand_pwd[32]; GetRandBytes(rand_pwd, 32); - string strWhatAmI = "To use bitcoind"; - if (mapArgs.count("-server")) - strWhatAmI = strprintf(_("To use the %s option"), "\"-server\""); - else if (mapArgs.count("-daemon")) - strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\""); uiInterface.ThreadSafeMessageBox(strprintf( - _("%s, you must set a rpcpassword in the configuration file:\n" + _("To use bitcoind, or the -server option to bitcoin-qt, you must set an rpcpassword in the configuration file:\n" "%s\n" "It is recommended you use the following random password:\n" "rpcuser=bitcoinrpc\n" @@ -581,7 +582,6 @@ void StartRPCThreads() "If the file does not exist, create it with owner-readable-only file permissions.\n" "It is also recommended to set alertnotify so you are notified of problems;\n" "for example: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com\n"), - strWhatAmI, GetConfigFile().string(), EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32)), "", CClientUIInterface::MSG_ERROR | CClientUIInterface::SECURE); @@ -762,6 +762,14 @@ void SetRPCWarmupFinished() fRPCInWarmup = false; } +bool RPCIsInWarmup(std::string *outStatus) +{ + LOCK(cs_rpcWarmup); + if (outStatus) + *outStatus = rpcWarmupStatus; + return fRPCInWarmup; +} + void RPCRunHandler(const boost::system::error_code& err, boost::function<void(void)> func) { if (!err) @@ -953,7 +961,7 @@ void ServiceConnection(AcceptedConnection *conn) break; // Process via HTTP REST API - } else if (strURI.substr(0, 6) == "/rest/") { + } else if (strURI.substr(0, 6) == "/rest/" && GetBoolArg("-rest", false)) { if (!HTTPReq_REST(conn, strURI, mapHeaders, fRun)) break; diff --git a/src/rpcserver.h b/src/rpcserver.h index b3234f65f2..2b2428445d 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -40,18 +40,22 @@ void StartRPCThreads(); * If real RPC threads have already been started this is a no-op. */ void StartDummyRPCThread(); -/* Stop RPC threads */ +/** Stop RPC threads */ void StopRPCThreads(); -/* Query whether RPC is running */ +/** Query whether RPC is running */ bool IsRPCRunning(); -/* Set the RPC warmup status. When this is done, all RPC calls will error out +/** + * Set the RPC warmup status. When this is done, all RPC calls will error out * immediately with RPC_IN_WARMUP. */ void SetRPCWarmupStatus(const std::string& newStatus); /* Mark warmup as done. RPC calls will be processed from now on. */ void SetRPCWarmupFinished(); +/* returns the current warmup state. */ +bool RPCIsInWarmup(std::string *statusOut); + /** * Type-check arguments; throws JSONRPCError if wrong type given. Does not check that * the right number of arguments are passed, just that any passed are the correct type. @@ -218,6 +222,8 @@ extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getchaintips(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value invalidateblock(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value reconsiderblock(const json_spirit::Array& params, bool fHelp); // in rest.cpp extern bool HTTPReq_REST(AcceptedConnection *conn, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 4d9e5ea137..d2d14ad9f4 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "amount.h" diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp new file mode 100644 index 0000000000..d4fd2ad7d9 --- /dev/null +++ b/src/script/bitcoinconsensus.cpp @@ -0,0 +1,91 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "bitcoinconsensus.h" + +#include "primitives/transaction.h" +#include "script/interpreter.h" +#include "version.h" + +namespace { + +/** A class that deserializes a single CTransaction one time. */ +class TxInputStream +{ +public: + TxInputStream(int nTypeIn, int nVersionIn, const unsigned char *txTo, size_t txToLen) : + m_type(nTypeIn), + m_version(nVersionIn), + m_data(txTo), + m_remaining(txToLen) + {} + + TxInputStream& read(char* pch, size_t nSize) + { + if (nSize > m_remaining) + throw std::ios_base::failure(std::string(__func__) + ": end of data"); + + if (pch == NULL) + throw std::ios_base::failure(std::string(__func__) + ": bad destination buffer"); + + if (m_data == NULL) + throw std::ios_base::failure(std::string(__func__) + ": bad source buffer"); + + memcpy(pch, m_data, nSize); + m_remaining -= nSize; + m_data += nSize; + return *this; + } + + template<typename T> + TxInputStream& operator>>(T& obj) + { + ::Unserialize(*this, obj, m_type, m_version); + return *this; + } + +private: + const int m_type; + const int m_version; + const unsigned char* m_data; + size_t m_remaining; +}; + +inline int set_error(bitcoinconsensus_error* ret, bitcoinconsensus_error serror) +{ + if (ret) + *ret = serror; + return 0; +} + +} // anon namespace + +int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, + const unsigned char *txTo , unsigned int txToLen, + unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err) +{ + try { + TxInputStream stream(SER_NETWORK, PROTOCOL_VERSION, txTo, txToLen); + CTransaction tx; + stream >> tx; + if (nIn >= tx.vin.size()) + return set_error(err, bitcoinconsensus_ERR_TX_INDEX); + if (tx.GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION) != txToLen) + return set_error(err, bitcoinconsensus_ERR_TX_SIZE_MISMATCH); + + // Regardless of the verification result, the tx did not error. + set_error(err, bitcoinconsensus_ERR_OK); + + return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, SignatureChecker(tx, nIn), NULL); + } catch (std::exception &e) { + return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing + } +} + +unsigned int bitcoinconsensus_version() +{ + // Just use the API version for now + return BITCOINCONSENSUS_API_VER; +} diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h new file mode 100644 index 0000000000..15e3337a8d --- /dev/null +++ b/src/script/bitcoinconsensus.h @@ -0,0 +1,67 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_BITCOINCONSENSUS_H +#define BITCOIN_BITCOINCONSENSUS_H + +#if defined(BUILD_BITCOIN_INTERNAL) && defined(HAVE_CONFIG_H) +#include "config/bitcoin-config.h" + #if defined(_WIN32) + #if defined(DLL_EXPORT) + #if defined(HAVE_FUNC_ATTRIBUTE_DLLEXPORT) + #define EXPORT_SYMBOL __declspec(dllexport) + #else + #define EXPORT_SYMBOL + #endif + #endif + #elif defined(HAVE_FUNC_ATTRIBUTE_VISIBILITY) + #define EXPORT_SYMBOL __attribute__ ((visibility ("default"))) + #endif +#elif defined(MSC_VER) && !defined(STATIC_LIBBITCOINCONSENSUS) + #define EXPORT_SYMBOL __declspec(dllimport) +#endif + +#ifndef EXPORT_SYMBOL + #define EXPORT_SYMBOL +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define BITCOINCONSENSUS_API_VER 0 + +typedef enum bitcoinconsensus_error_t +{ + bitcoinconsensus_ERR_OK = 0, + bitcoinconsensus_ERR_TX_INDEX, + bitcoinconsensus_ERR_TX_SIZE_MISMATCH, + bitcoinconsensus_ERR_TX_DESERIALIZE, +} bitcoinconsensus_error; + +/** Script verification flags */ +enum +{ + bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE = 0, + bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts +}; + +/// Returns 1 if the input nIn of the serialized transaction pointed to by +/// txTo correctly spends the scriptPubKey pointed to by scriptPubKey under +/// the additional constraints specified by flags. +/// If not NULL, err will contain an error/success code for the operation +EXPORT_SYMBOL int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, + const unsigned char *txTo , unsigned int txToLen, + unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err); + +EXPORT_SYMBOL unsigned int bitcoinconsensus_version(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#undef EXPORT_SYMBOL + +#endif // BITCOIN_BITCOINCONSENSUS_H diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index cf81fe30a2..3231f2e74e 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -5,10 +5,10 @@ #include "interpreter.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" -#include "crypto/sha2.h" +#include "crypto/sha256.h" #include "eccryptoverify.h" #include "pubkey.h" #include "script/script.h" @@ -17,13 +17,6 @@ using namespace std; typedef vector<unsigned char> valtype; -static const valtype vchFalse(0); -static const valtype vchZero(0); -static const valtype vchTrue(1, 1); -static const CScriptNum bnZero(0); -static const CScriptNum bnOne(1); -static const CScriptNum bnFalse(0); -static const CScriptNum bnTrue(1); namespace { @@ -207,9 +200,9 @@ bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, Sc return true; } -bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags) { +bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) { if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchSig)) { - return false; + return set_error(serror, SCRIPT_ERR_PUBKEYTYPE); } return true; } @@ -239,6 +232,14 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) { bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) { + static const CScriptNum bnZero(0); + static const CScriptNum bnOne(1); + static const CScriptNum bnFalse(0); + static const CScriptNum bnTrue(1); + static const valtype vchFalse(0); + static const valtype vchZero(0); + static const valtype vchTrue(1, 1); + CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); CScript::const_iterator pbegincodehash = script.begin(); @@ -329,8 +330,14 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // Control // case OP_NOP: + break; + case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: + { + if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) + return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); + } break; case OP_IF: @@ -786,11 +793,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // Drop the signature, since there's no way for a signature to sign itself scriptCode.FindAndDelete(CScript(vchSig)); - if (!CheckSignatureEncoding(vchSig, flags, serror)) { + if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) { //serror is set return false; } - bool fSuccess = CheckPubKeyEncoding(vchPubKey, flags) && checker.CheckSig(vchSig, vchPubKey, scriptCode); + bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode); popstack(stack); popstack(stack); @@ -849,13 +856,16 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un valtype& vchSig = stacktop(-isig); valtype& vchPubKey = stacktop(-ikey); - if (!CheckSignatureEncoding(vchSig, flags, serror)) { + // Note how this makes the exact order of pubkey/signature evaluation + // distinguishable by CHECKMULTISIG NOT if the STRICTENC flag is set. + // See the script_(in)valid tests for details. + if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) { // serror is set return false; } // Check signature - bool fOk = CheckPubKeyEncoding(vchPubKey, flags) && checker.CheckSig(vchSig, vchPubKey, scriptCode); + bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode); if (fOk) { isig++; @@ -865,7 +875,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un nKeysCount--; // If there are more signatures left than keys left, - // then too many signatures have failed + // then too many signatures have failed. Exit early, + // without checking any further signatures. if (nSigsCount > nKeysCount) fSuccess = false; } diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 14cccc558f..35b2f6c65a 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -35,8 +35,8 @@ enum SCRIPT_VERIFY_P2SH = (1U << 0), // Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure. - // Passing a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) to checksig causes that pubkey to be - // skipped (not softfork safe: this flag can widen the validity of OP_CHECKSIG OP_NOT). + // Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure. + // (softfork safe, but not used or intended as a consensus rule). SCRIPT_VERIFY_STRICTENC = (1U << 1), // Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1) @@ -57,7 +57,18 @@ enum // any other push causes the script to fail (BIP62 rule 3). // In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4). // (softfork safe) - SCRIPT_VERIFY_MINIMALDATA = (1U << 6) + SCRIPT_VERIFY_MINIMALDATA = (1U << 6), + + // Discourage use of NOPs reserved for upgrades (NOP1-10) + // + // Provided so that nodes can avoid accepting or mining transactions + // containing executed NOP's whose meaning may change after a soft-fork, + // thus rendering the script invalid; with this flag set executing + // discouraged NOPs fails the script. This verification flag will never be + // a mandatory flag applied to scripts in a block. NOPs that are not + // executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected. + SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7) + }; uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp index 4a3df268ec..5d24ed98ba 100644 --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -59,6 +59,10 @@ const char* ScriptErrorString(const ScriptError serror) return "Non-canonical signature: S value is unnecessarily high"; case SCRIPT_ERR_SIG_NULLDUMMY: return "Dummy CHECKMULTISIG argument must be zero"; + case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS: + return "NOPx reserved for soft-fork upgrades"; + case SCRIPT_ERR_PUBKEYTYPE: + return "Public key is neither compressed or uncompressed"; case SCRIPT_ERR_UNKNOWN_ERROR: case SCRIPT_ERR_ERROR_COUNT: default: break; diff --git a/src/script/script_error.h b/src/script/script_error.h index ae6626b257..ac1f2deae5 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -42,6 +42,10 @@ typedef enum ScriptError_t SCRIPT_ERR_SIG_PUSHONLY, SCRIPT_ERR_SIG_HIGH_S, SCRIPT_ERR_SIG_NULLDUMMY, + SCRIPT_ERR_PUBKEYTYPE, + + /* softfork safeness */ + SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, SCRIPT_ERR_ERROR_COUNT } ScriptError; diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 7dfed751b6..03c33ad9b5 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -5,7 +5,7 @@ #include "script/sign.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "key.h" #include "keystore.h" #include "script/standard.h" diff --git a/src/script/standard.h b/src/script/standard.h index f3dcc75fdc..c4b82b4c45 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -47,7 +47,8 @@ static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH; static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_STRICTENC | SCRIPT_VERIFY_MINIMALDATA | - SCRIPT_VERIFY_NULLDUMMY; + SCRIPT_VERIFY_NULLDUMMY | + SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS; /** For convenience, standard but not mandatory verify flags. */ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; diff --git a/src/secp256k1/.gitignore b/src/secp256k1/.gitignore new file mode 100644 index 0000000000..f0a54077a5 --- /dev/null +++ b/src/secp256k1/.gitignore @@ -0,0 +1,35 @@ +bench_inv +bench_sign +bench_verify +tests +*.exe +*.so +*.a +!.gitignore + +Makefile +configure +.libs/ +Makefile.in +aclocal.m4 +autom4te.cache/ +config.log +config.status +*.tar.gz +*.la +libtool +.deps/ +.dirstamp +build-aux/ +*.lo +*.o +*~ +src/libsecp256k1-config.h +src/libsecp256k1-config.h.in +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +src/stamp-h1 +libsecp256k1.pc diff --git a/src/secp256k1/.travis.yml b/src/secp256k1/.travis.yml new file mode 100644 index 0000000000..24a86b561b --- /dev/null +++ b/src/secp256k1/.travis.yml @@ -0,0 +1,25 @@ +language: cpp +compiler: gcc +install: + - sudo apt-get install -qq libssl-dev + - if [ "$BIGNUM" = "gmp" -o "$BIGNUM" = "auto" -o "$FIELD" = "gmp" ]; then sudo apt-get install -qq libgmp-dev; fi + - if [ "$FIELD" = "64bit_asm" ]; then sudo apt-get install -qq yasm; fi +env: + global: + - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no BUILD=check EXTRAFLAGS= + matrix: + - SCALAR=32bit + - SCALAR=64bit + - FIELD=gmp + - FIELD=gmp ENDOMORPHISM=yes + - FIELD=64bit_asm + - FIELD=64bit_asm ENDOMORPHISM=yes + - FIELD=64bit + - FIELD=64bit ENDOMORPHISM=yes + - FIELD=32bit + - FIELD=32bit ENDOMORPHISM=yes + - BUILD=distcheck + - EXTRAFLAGS=CFLAGS=-DDETERMINISTIC +before_script: ./autogen.sh +script: ./configure --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR $EXTRAFLAGS && make -j2 $BUILD +os: linux diff --git a/src/secp256k1/COPYING b/src/secp256k1/COPYING new file mode 100644 index 0000000000..4522a5990e --- /dev/null +++ b/src/secp256k1/COPYING @@ -0,0 +1,19 @@ +Copyright (c) 2013 Pieter Wuille + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am new file mode 100644 index 0000000000..d527da6b77 --- /dev/null +++ b/src/secp256k1/Makefile.am @@ -0,0 +1,88 @@ +ACLOCAL_AMFLAGS = -I build-aux/m4 + +lib_LTLIBRARIES = libsecp256k1.la +if USE_ASM +COMMON_LIB = libsecp256k1_common.la +else +COMMON_LIB = +endif +noinst_LTLIBRARIES = $(COMMON_LIB) +include_HEADERS = include/secp256k1.h +noinst_HEADERS = +noinst_HEADERS += src/scalar.h +noinst_HEADERS += src/scalar_4x64.h +noinst_HEADERS += src/scalar_8x32.h +noinst_HEADERS += src/scalar_impl.h +noinst_HEADERS += src/scalar_4x64_impl.h +noinst_HEADERS += src/scalar_8x32_impl.h +noinst_HEADERS += src/group.h +noinst_HEADERS += src/group_impl.h +noinst_HEADERS += src/num_gmp.h +noinst_HEADERS += src/num_gmp_impl.h +noinst_HEADERS += src/ecdsa.h +noinst_HEADERS += src/ecdsa_impl.h +noinst_HEADERS += src/eckey.h +noinst_HEADERS += src/eckey_impl.h +noinst_HEADERS += src/ecmult.h +noinst_HEADERS += src/ecmult_impl.h +noinst_HEADERS += src/ecmult_gen.h +noinst_HEADERS += src/ecmult_gen_impl.h +noinst_HEADERS += src/num.h +noinst_HEADERS += src/num_impl.h +noinst_HEADERS += src/field_10x26.h +noinst_HEADERS += src/field_10x26_impl.h +noinst_HEADERS += src/field_5x52.h +noinst_HEADERS += src/field_5x52_impl.h +noinst_HEADERS += src/field_5x52_int128_impl.h +noinst_HEADERS += src/field_5x52_asm_impl.h +noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h +noinst_HEADERS += src/util.h +noinst_HEADERS += src/testrand.h +noinst_HEADERS += src/testrand_impl.h +noinst_HEADERS += src/field_gmp.h +noinst_HEADERS += src/field_gmp_impl.h +noinst_HEADERS += src/field.h +noinst_HEADERS += src/field_impl.h + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libsecp256k1.pc + +if USE_ASM +libsecp256k1_common_la_SOURCES = src/field_5x52_asm.asm +endif + +libsecp256k1_la_SOURCES = src/secp256k1.c +libsecp256k1_la_CPPFLAGS = -I$(top_srcdir)/include $(SECP_INCLUDES) +libsecp256k1_la_LIBADD = $(COMMON_LIB) $(SECP_LIBS) + + +noinst_PROGRAMS = +if USE_BENCHMARK +noinst_PROGRAMS += bench_verify bench_sign bench_inv +bench_verify_SOURCES = src/bench_verify.c +bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) +bench_verify_LDFLAGS = -static +bench_sign_SOURCES = src/bench_sign.c +bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) +bench_sign_LDFLAGS = -static +bench_inv_SOURCES = src/bench_inv.c +bench_inv_LDADD = $(COMMON_LIB) $(SECP_LIBS) +bench_inv_LDFLAGS = -static +endif + +if USE_TESTS +noinst_PROGRAMS += tests +tests_SOURCES = src/tests.c +tests_CPPFLAGS = -DVERIFY $(SECP_TEST_INCLUDES) +tests_LDADD = $(COMMON_LIB) $(SECP_LIBS) $(SECP_TEST_LIBS) +tests_LDFLAGS = -static +TESTS = tests +endif + +EXTRA_DIST = autogen.sh nasm_lt.sh + +#x86_64 only +if USE_ASM +.asm.lo: + $(LIBTOOL) --mode=compile --tag YASM $(srcdir)/nasm_lt.sh $(YASM) -f $(YASM_BINFMT) $(YAFLAGS) -I$(srcdir) -I. $< -o $@ +endif diff --git a/src/secp256k1/README.md b/src/secp256k1/README.md new file mode 100644 index 0000000000..1e49f49416 --- /dev/null +++ b/src/secp256k1/README.md @@ -0,0 +1,55 @@ +libsecp256k1 +============ + +[![Build Status](https://travis-ci.org/bitcoin/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin/secp256k1) + +Optimized C library for EC operations on curve secp256k1. + +This library is experimental, so use at your own risk. + +Features: +* Low-level field and group operations on secp256k1. +* ECDSA signing/verification and key generation. +* Adding/multiplying private/public keys. +* Serialization/parsing of private keys, public keys, signatures. +* Very efficient implementation. + +Implementation details +---------------------- + +* General + * Avoid dynamic memory usage almost everywhere. +* Field operations + * Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1). + * Using 5 52-bit limbs (including hand-optimized assembly for x86_64, by Diederik Huys). + * Using 10 26-bit limbs. + * Using GMP. + * Field inverses and square roots using a sliding window over blocks of 1s (by Peter Dettman). +* Scalar operations + * Optimized implementation without data-dependent branches of arithmetic modulo the curve's order. + * Using 4 64-bit limbs (relying on __int128 support in the compiler). + * Using 8 32-bit limbs. +* Group operations + * Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7). + * Use addition between points in Jacobian and affine coordinates where possible. + * Use a unified addition/doubling formula where necessary to avoid data-dependent branches. +* Point multiplication for verification (a*P + b*G). + * Use wNAF notation for point multiplicands. + * Use a much larger window for multiples of G, using precomputed multiples. + * Use Shamir's trick to do the multiplication with the public key and the generator simultaneously. + * Optionally use secp256k1's efficiently-computable endomorphism to split the multiplicands into 4 half-sized ones first. +* Point multiplication for signing + * Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. + * Slice the precomputed table in memory per byte, so memory access to the table becomes uniform. + * No data-dependent branches + * The precomputed tables add and eventually subtract points for which no known scalar (private key) is known, preventing even an attacker with control over the private key used to control the data internally. + +Build steps +----------- + +libsecp256k1 is built using autotools: + + $ ./autogen.sh + $ ./configure + $ make + $ sudo make install # optional diff --git a/src/secp256k1/TODO b/src/secp256k1/TODO new file mode 100644 index 0000000000..a300e1c5eb --- /dev/null +++ b/src/secp256k1/TODO @@ -0,0 +1,3 @@ +* Unit tests for fieldelem/groupelem, including ones intended to + trigger fieldelem's boundary cases. +* Complete constant-time operations for signing/keygen diff --git a/src/secp256k1/autogen.sh b/src/secp256k1/autogen.sh new file mode 100755 index 0000000000..65286b9353 --- /dev/null +++ b/src/secp256k1/autogen.sh @@ -0,0 +1,3 @@ +#!/bin/sh +set -e +autoreconf -if --warnings=all diff --git a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 b/src/secp256k1/build-aux/m4/bitcoin_secp.m4 new file mode 100644 index 0000000000..e6f3470ed7 --- /dev/null +++ b/src/secp256k1/build-aux/m4/bitcoin_secp.m4 @@ -0,0 +1,90 @@ +dnl libsecp25k1 helper checks +AC_DEFUN([SECP_INT128_CHECK],[ +has_int128=$ac_cv_type___int128 +if test x"$has_int128" != x"yes" && test x"$set_field" = x"64bit"; then + AC_MSG_ERROR([$set_field field support explicitly requested but is not compatible with this host]) +fi +if test x"$has_int128" != x"yes" && test x"$set_scalar" = x"64bit"; then + AC_MSG_ERROR([$set_scalar scalar support explicitly requested but is not compatible with this host]) +fi +]) + +dnl +AC_DEFUN([SECP_64BIT_ASM_CHECK],[ +if test x"$host_cpu" == x"x86_64"; then + AC_CHECK_PROG(YASM, yasm, yasm) +else + if test x"$set_field" = x"64bit_asm"; then + AC_MSG_ERROR([$set_field field support explicitly requested but is not compatible with this host]) + fi +fi +if test x$YASM = x; then + if test x"$set_field" = x"64bit_asm"; then + AC_MSG_ERROR([$set_field field support explicitly requested but yasm was not found]) + fi + has_64bit_asm=no +else + case x"$host_os" in + xdarwin*) + YASM_BINFMT=macho64 + ;; + x*-gnux32) + YASM_BINFMT=elfx32 + ;; + *) + YASM_BINFMT=elf64 + ;; + esac + if $YASM -f help | grep -q $YASM_BINFMT; then + has_64bit_asm=yes + else + if test x"$set_field" = x"64bit_asm"; then + AC_MSG_ERROR([$set_field field support explicitly requested but yasm doesn't support $YASM_BINFMT format]) + fi + AC_MSG_WARN([yasm too old for $YASM_BINFMT format]) + has_64bit_asm=no + fi +fi +]) + +dnl +AC_DEFUN([SECP_OPENSSL_CHECK],[ +if test x"$use_pkgconfig" = x"yes"; then + : #NOP + m4_ifdef([PKG_CHECK_MODULES],[ + PKG_CHECK_MODULES([CRYPTO], [libcrypto], [has_libcrypto=yes; AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])],[has_libcrypto=no]) + : #NOP + ]) +else + AC_CHECK_HEADER(openssl/crypto.h,[AC_CHECK_LIB(crypto, main,[has_libcrypto=yes; CRYPTO_LIBS=-lcrypto; AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])] +)]) + LIBS= +fi +if test x"$has_libcrypto" == x"yes" && test x"$has_openssl_ec" = x; then + AC_MSG_CHECKING(for EC functions in libcrypto) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include <openssl/ec.h> + #include <openssl/ecdsa.h> + #include <openssl/obj_mac.h>]],[[ + EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1); + ECDSA_sign(0, NULL, 0, NULL, NULL, eckey); + ECDSA_verify(0, NULL, 0, NULL, 0, eckey); + EC_KEY_free(eckey); + ]])],[has_openssl_ec=yes],[has_openssl_ec=no]) + AC_MSG_RESULT([$has_openssl_ec]) +fi +]) + +dnl +AC_DEFUN([SECP_GMP_CHECK],[ +if test x"$has_gmp" != x"yes"; then + AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; GMP_LIBS=-lgmp; AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])])]) +fi +if test x"$set_field" = x"gmp" && test x"$has_gmp" != x"yes"; then + AC_MSG_ERROR([$set_field field support explicitly requested but libgmp was not found]) +fi +if test x"$set_bignum" = x"gmp" && test x"$has_gmp" != x"yes"; then + AC_MSG_ERROR([$set_bignum field support explicitly requested but libgmp was not found]) +fi +]) + diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac new file mode 100644 index 0000000000..2da5709834 --- /dev/null +++ b/src/secp256k1/configure.ac @@ -0,0 +1,259 @@ +AC_PREREQ([2.60]) +AC_INIT([libsecp256k1],[0.1]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([build-aux/m4]) +AC_CANONICAL_HOST +AH_TOP([#ifndef LIBSECP256K1_CONFIG_H]) +AH_TOP([#define LIBSECP256K1_CONFIG_H]) +AH_BOTTOM([#endif //LIBSECP256K1_CONFIG_H]) +AM_INIT_AUTOMAKE([foreign]) +LT_INIT + +dnl make the compilation flags quiet unless V=1 is used +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +PKG_PROG_PKG_CONFIG + +AC_PATH_TOOL(AR, ar) +AC_PATH_TOOL(RANLIB, ranlib) +AC_PATH_TOOL(STRIP, strip) + +AC_PROG_CC_C99 +if test x"$ac_cv_prog_cc_c99" == x"no"; then + AC_MSG_ERROR([c99 compiler support required]) +fi + +case $host in + *mingw*) + use_pkgconfig=no + ;; + *) + use_pkgconfig=yes + ;; +esac + +case $host_os in + darwin*) + CPPFLAGS="$CPPFLAGS -I/opt/local/include" + LDFLAGS="$LDFLAGS -L/opt/local/lib" + ;; +esac + +CFLAGS="$CFLAGS -W" + +warn_CFLAGS="-Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function" +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $warn_CFLAGS" +AC_MSG_CHECKING([if ${CC} supports ${warn_CFLAGS}]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], + [ AC_MSG_RESULT([yes]) ], + [ AC_MSG_RESULT([no]) + CFLAGS="$saved_CFLAGS" + ]) + + +AC_ARG_ENABLE(benchmark, + AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is yes)]), + [use_benchmark=$enableval], + [use_benchmark=yes]) + +AC_ARG_ENABLE(tests, + AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), + [use_tests=$enableval], + [use_tests=yes]) + +AC_ARG_ENABLE(endomorphism, + AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), + [use_endomorphism=$enableval], + [use_endomorphism=no]) + +AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=gmp|64bit|64bit_asm|32bit|auto], +[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) + +AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|auto], +[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto]) + +AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto], +[Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto]) + +AC_CHECK_TYPES([__int128]) + +AC_CHECK_DECL(__builtin_expect,AC_DEFINE(HAVE_BUILTIN_EXPECT,1,[Define this symbol if __builtin_expect is available]),,) + +if test x"$req_field" = x"auto"; then + SECP_64BIT_ASM_CHECK + if test x"$has_64bit_asm" = x"yes"; then + set_field=64bit_asm + fi + + if test x"$set_field" = x; then + SECP_INT128_CHECK + if test x"$has_int128" = x"yes"; then + set_field=64bit + fi + fi + + if test x"$set_field" = x; then + SECP_GMP_CHECK + if test x"$has_gmp" = x"yes"; then + set_field=gmp + fi + fi + + if test x"$set_field" = x; then + set_field=32bit + fi +else + set_field=$req_field + case $set_field in + 64bit_asm) + SECP_64BIT_ASM_CHECK + ;; + 64bit) + SECP_INT128_CHECK + ;; + gmp) + SECP_GMP_CHECK + ;; + 32bit) + ;; + *) + AC_MSG_ERROR([invalid field implementation selection]) + ;; + esac +fi + +if test x"$req_scalar" = x"auto"; then + if test x"$set_scalar" = x; then + SECP_INT128_CHECK + if test x"$has_int128" = x"yes"; then + set_scalar=64bit + fi + fi + if test x"$set_scalar" = x; then + set_scalar=32bit + fi +else + set_scalar=$req_scalar + case $set_scalar in + 64bit) + SECP_INT128_CHECK + ;; + 32bit) + ;; + *) + AC_MSG_ERROR([invalid scalar implementation selected]) + ;; + esac +fi + +if test x"$req_bignum" = x"auto"; then + SECP_GMP_CHECK + if test x"$has_gmp" = x"yes"; then + set_bignum=gmp + fi + + if test x"$set_bignum" = x; then + AC_MSG_ERROR([no working bignum implementation found]) + fi +else + set_bignum=$req_bignum + case $set_bignum in + gmp) + SECP_GMP_CHECK + ;; + openssl) + SECP_OPENSSL_CHECK + ;; + *) + AC_MSG_ERROR([invalid bignum implementation selection]) + ;; + esac +fi + +# select field implementation +case $set_field in +64bit_asm) + AC_DEFINE(USE_FIELD_5X52_ASM, 1, [Define this symbol to use the assembly version for the 5x52 field implementation]) + AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation]) + ;; +64bit) + AC_DEFINE(USE_FIELD_5X52_INT128, 1, [Define this symbol to use the __int128 version for the 5x52 field implementation]) + AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation]) + ;; +gmp) + AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed]) + AC_DEFINE(USE_FIELD_GMP, 1, [Define this symbol to use the FIELD_GMP implementation]) + ;; +32bit) + AC_DEFINE(USE_FIELD_10X26, 1, [Define this symbol to use the FIELD_10X26 implementation]) + ;; +*) + AC_MSG_ERROR([invalid field implementation]) + ;; +esac + +# select bignum implementation +case $set_bignum in +gmp) + AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed]) + AC_DEFINE(USE_NUM_GMP, 1, [Define this symbol to use the gmp implementation]) + AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the USE_FIELD_INV_NUM implementation]) + ;; +*) + AC_MSG_ERROR([invalid bignum implementation]) + ;; +esac + +#select scalar implementation +case $set_scalar in +64bit) + AC_DEFINE(USE_SCALAR_4X64, 1, [Define this symbol to use the 4x64 scalar implementation]) + ;; +32bit) + AC_DEFINE(USE_SCALAR_8X32, 1, [Define this symbol to use the 8x32 scalar implementation]) + ;; +*) + AC_MSG_ERROR([invalid scalar implementation]) + ;; +esac + +if test x"$use_tests" = x"yes"; then + SECP_OPENSSL_CHECK + if test x"$has_openssl_ec" == x"yes"; then + AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available]) + SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS" + SECP_TEST_LIBS="$CRYPTO_LIBS" + + case $host in + *mingw*) + SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32" + ;; + esac + + fi +fi + +if test x"$set_field" = x"gmp" || test x"$set_bignum" = x"gmp"; then + SECP_LIBS="$SECP_LIBS $GMP_LIBS" +fi + +if test x"$use_endomorphism" = x"yes"; then + AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism]) +fi + +AC_MSG_NOTICE([Using field implementation: $set_field]) +AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) +AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) + +AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) +AC_CONFIG_FILES([Makefile libsecp256k1.pc]) +AC_SUBST(SECP_INCLUDES) +AC_SUBST(SECP_LIBS) +AC_SUBST(SECP_TEST_LIBS) +AC_SUBST(SECP_TEST_INCLUDES) +AC_SUBST(YASM_BINFMT) +AM_CONDITIONAL([USE_ASM], [test x"$set_field" == x"64bit_asm"]) +AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) +AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" != x"no"]) +AC_OUTPUT diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h new file mode 100644 index 0000000000..932bf0279f --- /dev/null +++ b/src/secp256k1/include/secp256k1.h @@ -0,0 +1,252 @@ +#ifndef _SECP256K1_ +# define _SECP256K1_ + +# ifdef __cplusplus +extern "C" { +# endif + +# if !defined(SECP256K1_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define SECP256K1_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define SECP256K1_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if SECP256K1_GNUC_PREREQ(3,0) +# define SECP256K1_RESTRICT __restrict__ +# elif (defined(_MSC_VER) && _MSC_VER >= 1400) +# define SECP256K1_RESTRICT __restrict +# else +# define SECP256K1_RESTRICT +# endif +# else +# define SECP256K1_RESTRICT restrict +# endif + +# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if SECP256K1_GNUC_PREREQ(2,7) +# define SECP256K1_INLINE __inline__ +# elif (defined(_MSC_VER)) +# define SECP256K1_INLINE __inline +# else +# define SECP256K1_INLINE +# endif +# else +# define SECP256K1_INLINE inline +# endif + +/**Warning attributes + * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out + * some paranoid null checks. */ +# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) +# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) +# else +# define SECP256K1_WARN_UNUSED_RESULT +# endif +# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) +# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) +# else +# define SECP256K1_ARG_NONNULL(_x) +# endif + + +/** Flags to pass to secp256k1_start. */ +# define SECP256K1_START_VERIFY (1 << 0) +# define SECP256K1_START_SIGN (1 << 1) + +/** Initialize the library. This may take some time (10-100 ms). + * You need to call this before calling any other function. + * It cannot run in parallel with any other functions, but once + * secp256k1_start() returns, all other functions are thread-safe. + */ +void secp256k1_start(unsigned int flags); + +/** Free all memory associated with this library. After this, no + * functions can be called anymore, except secp256k1_start() + */ +void secp256k1_stop(void); + +/** Verify an ECDSA signature. + * Returns: 1: correct signature + * 0: incorrect signature + * -1: invalid public key + * -2: invalid signature + * In: msg: the message being verified (cannot be NULL) + * msglen: the length of the message (at most 32) + * sig: the signature being verified (cannot be NULL) + * siglen: the length of the signature + * pubkey: the public key to verify with (cannot be NULL) + * pubkeylen: the length of pubkey + * Requires starting using SECP256K1_START_VERIFY. + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( + const unsigned char *msg, + int msglen, + const unsigned char *sig, + int siglen, + const unsigned char *pubkey, + int pubkeylen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5); + +/** Create an ECDSA signature. + * Returns: 1: signature created + * 0: nonce invalid, try another one + * In: msg: the message being signed (cannot be NULL) + * msglen: the length of the message being signed (at most 32) + * seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid) + * nonce: pointer to a 32-byte nonce (cannot be NULL, generated with a cryptographic PRNG) + * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) + * In/Out: siglen: pointer to an int with the length of sig, which will be updated + * to contain the actual signature length (<=72). + * Requires starting using SECP256K1_START_SIGN. + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign( + const unsigned char *msg, + int msglen, + unsigned char *sig, + int *siglen, + const unsigned char *seckey, + const unsigned char *nonce +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); + +/** Create a compact ECDSA signature (64 byte + recovery id). + * Returns: 1: signature created + * 0: nonce invalid, try another one + * In: msg: the message being signed (cannot be NULL) + * msglen: the length of the message being signed (at most 32) + * seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid) + * nonce: pointer to a 32-byte nonce (cannot be NULL, generated with a cryptographic PRNG) + * Out: sig: pointer to a 64-byte array where the signature will be placed (cannot be NULL) + * recid: pointer to an int, which will be updated to contain the recovery id (can be NULL) + * Requires starting using SECP256K1_START_SIGN. + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign_compact( + const unsigned char *msg, + int msglen, + unsigned char *sig64, + const unsigned char *seckey, + const unsigned char *nonce, + int *recid +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); + +/** Recover an ECDSA public key from a compact signature. + * Returns: 1: public key successfully recovered (which guarantees a correct signature). + * 0: otherwise. + * In: msg: the message assumed to be signed (cannot be NULL) + * msglen: the length of the message (at most 32) + * sig64: signature as 64 byte array (cannot be NULL) + * compressed: whether to recover a compressed or uncompressed pubkey + * recid: the recovery id (0-3, as returned by ecdsa_sign_compact) + * Out: pubkey: pointer to a 33 or 65 byte array to put the pubkey (cannot be NULL) + * pubkeylen: pointer to an int that will contain the pubkey length (cannot be NULL) + * Requires starting using SECP256K1_START_VERIFY. + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact( + const unsigned char *msg, + int msglen, + const unsigned char *sig64, + unsigned char *pubkey, + int *pubkeylen, + int compressed, + int recid +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); + +/** Verify an ECDSA secret key. + * Returns: 1: secret key is valid + * 0: secret key is invalid + * In: seckey: pointer to a 32-byte secret key (cannot be NULL) + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(const unsigned char *seckey) SECP256K1_ARG_NONNULL(1); + +/** Just validate a public key. + * Returns: 1: valid public key + * 0: invalid public key + * In: pubkey: pointer to a 33-byte or 65-byte public key (cannot be NULL). + * pubkeylen: length of pubkey + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) SECP256K1_ARG_NONNULL(1); + +/** Compute the public key for a secret key. + * In: compressed: whether the computed public key should be compressed + * seckey: pointer to a 32-byte private key (cannot be NULL) + * Out: pubkey: pointer to a 33-byte (if compressed) or 65-byte (if uncompressed) + * area to store the public key (cannot be NULL) + * pubkeylen: pointer to int that will be updated to contains the pubkey's + * length (cannot be NULL) + * Returns: 1: secret was valid, public key stores + * 0: secret was invalid, try again. + * Requires starting using SECP256K1_START_SIGN. + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( + unsigned char *pubkey, + int *pubkeylen, + const unsigned char *seckey, + int compressed +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Decompress a public key. + * In/Out: pubkey: pointer to a 65-byte array to put the decompressed public key. + It must contain a 33-byte or 65-byte public key already (cannot be NULL) + * pubkeylen: pointer to the size of the public key pointed to by pubkey (cannot be NULL) + It will be updated to reflect the new size. + * Returns: 0 if the passed public key was invalid, 1 otherwise. If 1 is returned, the + pubkey is replaced with its decompressed version. + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_decompress( + unsigned char *pubkey, + int *pubkeylen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Export a private key in DER format. */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export( + const unsigned char *seckey, + unsigned char *privkey, + int *privkeylen, + int compressed +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Import a private key in DER format. */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import( + unsigned char *seckey, + const unsigned char *privkey, + int privkeylen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Tweak a private key by adding tweak to it. */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( + unsigned char *seckey, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Tweak a public key by adding tweak times the generator to it. + * Requires starting with SECP256K1_START_VERIFY. + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( + unsigned char *pubkey, + int pubkeylen, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); + +/** Tweak a private key by multiplying it with tweak. */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( + unsigned char *seckey, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Tweak a public key by multiplying it with tweak. + * Requires starting with SECP256K1_START_VERIFY. + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( + unsigned char *pubkey, + int pubkeylen, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/src/secp256k1/libsecp256k1.pc.in b/src/secp256k1/libsecp256k1.pc.in new file mode 100644 index 0000000000..1c72dd0003 --- /dev/null +++ b/src/secp256k1/libsecp256k1.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libsecp256k1 +Description: Optimized C library for EC operations on curve secp256k1 +URL: https://github.com/bitcoin/secp256k1 +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs.private: @SECP_LIBS@ +Libs: -L${libdir} -lsecp256k1 + diff --git a/src/secp256k1/nasm_lt.sh b/src/secp256k1/nasm_lt.sh new file mode 100755 index 0000000000..6cd73294c0 --- /dev/null +++ b/src/secp256k1/nasm_lt.sh @@ -0,0 +1,57 @@ +#! /bin/sh +command="" +infile="" +o_opt=no +pic=no +while [ $# -gt 0 ]; do + case "$1" in + -DPIC|-fPIC|-fpic|-Kpic|-KPIC) + if [ "$pic" != "yes" ] ; then + command="$command -DPIC" + pic=yes + fi + ;; + -f|-fbin|-faout|-faoutb|-fcoff|-felf|-felf64|-fas86| \ + -fobj|-fwin32|-fwin64|-frdf|-fieee|-fmacho|-fmacho64) + # it's a file format specifier for nasm. + command="$command $1" + ;; + -f*) + # maybe a code-generation flag for gcc. + ;; + -[Ii]*) + incdir=`echo "$1" | sed 's/^-[Ii]//'` + if [ "x$incdir" = x -a "x$2" != x ] ; then + case "$2" in + -*) ;; + *) incdir="$2"; shift;; + esac + fi + if [ "x$incdir" != x ] ; then + # In the case of NASM, the trailing slash is necessary. + incdir=`echo "$incdir" | sed 's%/*$%/%'` + command="$command -I$incdir" + fi + ;; + -o*) + o_opt=yes + command="$command $1" + ;; + *.asm) + infile=$1 + command="$command $1" + ;; + *) + command="$command $1" + ;; + esac + shift +done +if [ "$o_opt" != yes ] ; then + # By default, NASM creates an output file + # in the same directory as the input file. + outfile="-o `echo $infile | sed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.o" + command="$command $outfile" +fi +echo $command +exec $command diff --git a/src/secp256k1/.empty b/src/secp256k1/obj/.gitignore index e69de29bb2..e69de29bb2 100644 --- a/src/secp256k1/.empty +++ b/src/secp256k1/obj/.gitignore diff --git a/src/secp256k1/src/bench_inv.c b/src/secp256k1/src/bench_inv.c new file mode 100644 index 0000000000..d6f664333f --- /dev/null +++ b/src/secp256k1/src/bench_inv.c @@ -0,0 +1,41 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ +#include <stdio.h> + +#include "include/secp256k1.h" + +#include "util.h" +#include "num_impl.h" +#include "field_impl.h" +#include "group_impl.h" +#include "scalar_impl.h" + +int main(void) { + static const unsigned char init[32] = { + 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, + 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35, + 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59, + 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83 + }; + static const unsigned char fini[32] = { + 0xba, 0x28, 0x58, 0xd8, 0xaa, 0x11, 0xd6, 0xf2, + 0xfa, 0xce, 0x50, 0xb1, 0x67, 0x19, 0xb1, 0xa6, + 0xe0, 0xaa, 0x84, 0x53, 0xf6, 0x80, 0xfc, 0x23, + 0x88, 0x3c, 0xd6, 0x74, 0x9f, 0x27, 0x09, 0x03 + }; + secp256k1_ge_start(); + secp256k1_scalar_t base, x; + secp256k1_scalar_set_b32(&base, init, NULL); + secp256k1_scalar_set_b32(&x, init, NULL); + for (int i=0; i<1000000; i++) { + secp256k1_scalar_inverse(&x, &x); + secp256k1_scalar_add(&x, &x, &base); + } + unsigned char res[32]; + secp256k1_scalar_get_b32(res, &x); + CHECK(memcmp(res, fini, 32) == 0); + return 0; +} diff --git a/src/secp256k1/src/bench_sign.c b/src/secp256k1/src/bench_sign.c new file mode 100644 index 0000000000..f01f11d689 --- /dev/null +++ b/src/secp256k1/src/bench_sign.c @@ -0,0 +1,49 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ +#include <stdio.h> +#include <string.h> + +#include "include/secp256k1.h" +#include "util.h" + +int main(void) { + secp256k1_start(SECP256K1_START_SIGN); + + unsigned char msg[32]; + unsigned char nonce[32]; + unsigned char key[32]; + + for (int i = 0; i < 32; i++) msg[i] = i + 1; + for (int i = 0; i < 32; i++) nonce[i] = i + 33; + for (int i = 0; i < 32; i++) key[i] = i + 65; + + unsigned char sig[64]; + + for (int i=0; i<1000000; i++) { + int recid = 0; + CHECK(secp256k1_ecdsa_sign_compact(msg, 32, sig, key, nonce, &recid)); + for (int j = 0; j < 32; j++) { + nonce[j] = key[j]; /* Move former key to nonce */ + msg[j] = sig[j]; /* Move former R to message. */ + key[j] = sig[j + 32]; /* Move former S to key. */ + } + } + + static const unsigned char fini[64] = { + 0x92, 0x03, 0xef, 0xf1, 0x58, 0x0b, 0x49, 0x8d, + 0x22, 0x3d, 0x49, 0x0e, 0xbf, 0x26, 0x50, 0x0e, + 0x2d, 0x62, 0x90, 0xd7, 0x82, 0xbd, 0x3d, 0x5c, + 0xa9, 0x10, 0xa5, 0x49, 0xb1, 0xd8, 0x8c, 0xc0, + 0x5b, 0x5e, 0x9e, 0x68, 0x51, 0x3d, 0xe8, 0xec, + 0x82, 0x30, 0x82, 0x88, 0x8c, 0xfd, 0xe7, 0x71, + 0x15, 0x92, 0xfc, 0x14, 0x59, 0x78, 0x31, 0xb3, + 0xf6, 0x07, 0x91, 0x18, 0x00, 0x8d, 0x4c, 0xb2 + }; + CHECK(memcmp(sig, fini, 64) == 0); + + secp256k1_stop(); + return 0; +} diff --git a/src/secp256k1/src/bench_verify.c b/src/secp256k1/src/bench_verify.c new file mode 100644 index 0000000000..690595516d --- /dev/null +++ b/src/secp256k1/src/bench_verify.c @@ -0,0 +1,44 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include <stdio.h> +#include <string.h> + +#include "include/secp256k1.h" +#include "util.h" + +int main(void) { + secp256k1_start(SECP256K1_START_VERIFY); + + unsigned char msg[32]; + unsigned char sig[64]; + + for (int i = 0; i < 32; i++) msg[i] = 1 + i; + for (int i = 0; i < 64; i++) sig[i] = 65 + i; + + unsigned char pubkey[33]; + for (int i=0; i<1000000; i++) { + int pubkeylen = 33; + CHECK(secp256k1_ecdsa_recover_compact(msg, 32, sig, pubkey, &pubkeylen, 1, i % 2)); + for (int j = 0; j < 32; j++) { + sig[j + 32] = msg[j]; /* Move former message to S. */ + msg[j] = sig[j]; /* Move former R to message. */ + sig[j] = pubkey[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ + } + } + + static const unsigned char fini[33] = { + 0x02, + 0x52, 0x63, 0xae, 0x9a, 0x9d, 0x47, 0x1f, 0x1a, + 0xb2, 0x36, 0x65, 0x89, 0x11, 0xe7, 0xcc, 0x86, + 0xa3, 0xab, 0x97, 0xb6, 0xf1, 0xaf, 0xfd, 0x8f, + 0x9b, 0x38, 0xb6, 0x18, 0x55, 0xe5, 0xc2, 0x43 + }; + CHECK(memcmp(fini, pubkey, 33) == 0); + + secp256k1_stop(); + return 0; +} diff --git a/src/secp256k1/src/ecdsa.h b/src/secp256k1/src/ecdsa.h new file mode 100644 index 0000000000..3b1e0484ea --- /dev/null +++ b/src/secp256k1/src/ecdsa.h @@ -0,0 +1,23 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECDSA_ +#define _SECP256K1_ECDSA_ + +#include "num.h" + +typedef struct { + secp256k1_num_t r, s; +} secp256k1_ecdsa_sig_t; + +static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size); +static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a); +static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message); +static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid); +static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid); +static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s); + +#endif diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h new file mode 100644 index 0000000000..4c05ec39f8 --- /dev/null +++ b/src/secp256k1/src/ecdsa_impl.h @@ -0,0 +1,183 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + + +#ifndef _SECP256K1_ECDSA_IMPL_H_ +#define _SECP256K1_ECDSA_IMPL_H_ + +#include "num.h" +#include "field.h" +#include "group.h" +#include "ecmult.h" +#include "ecmult_gen.h" +#include "ecdsa.h" + +static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) { + if (sig[0] != 0x30) return 0; + int lenr = sig[3]; + if (5+lenr >= size) return 0; + int lens = sig[lenr+5]; + if (sig[1] != lenr+lens+4) return 0; + if (lenr+lens+6 > size) return 0; + if (sig[2] != 0x02) return 0; + if (lenr == 0) return 0; + if (sig[lenr+4] != 0x02) return 0; + if (lens == 0) return 0; + secp256k1_num_set_bin(&r->r, sig+4, lenr); + secp256k1_num_set_bin(&r->s, sig+6+lenr, lens); + return 1; +} + +static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) { + int lenR = (secp256k1_num_bits(&a->r) + 7)/8; + if (lenR == 0 || secp256k1_num_get_bit(&a->r, lenR*8-1)) + lenR++; + int lenS = (secp256k1_num_bits(&a->s) + 7)/8; + if (lenS == 0 || secp256k1_num_get_bit(&a->s, lenS*8-1)) + lenS++; + if (*size < 6+lenS+lenR) + return 0; + *size = 6 + lenS + lenR; + sig[0] = 0x30; + sig[1] = 4 + lenS + lenR; + sig[2] = 0x02; + sig[3] = lenR; + secp256k1_num_get_bin(sig+4, lenR, &a->r); + sig[4+lenR] = 0x02; + sig[5+lenR] = lenS; + secp256k1_num_get_bin(sig+lenR+6, lenS, &a->s); + return 1; +} + +static int secp256k1_ecdsa_sig_recompute(secp256k1_num_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) { + const secp256k1_ge_consts_t *c = secp256k1_ge_consts; + + if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s)) + return 0; + if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s)) + return 0; + if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0) + return 0; + + int ret = 0; + secp256k1_num_t sn, u1, u2; + secp256k1_num_init(&sn); + secp256k1_num_init(&u1); + secp256k1_num_init(&u2); + secp256k1_num_mod_inverse(&sn, &sig->s, &c->order); + secp256k1_num_mod_mul(&u1, &sn, message, &c->order); + secp256k1_num_mod_mul(&u2, &sn, &sig->r, &c->order); + secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey); + secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1); + if (!secp256k1_gej_is_infinity(&pr)) { + secp256k1_fe_t xr; secp256k1_gej_get_x_var(&xr, &pr); + secp256k1_fe_normalize(&xr); + unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr); + secp256k1_num_set_bin(r2, xrb, 32); + secp256k1_num_mod(r2, &c->order); + ret = 1; + } + secp256k1_num_free(&sn); + secp256k1_num_free(&u1); + secp256k1_num_free(&u2); + return ret; +} + +static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid) { + const secp256k1_ge_consts_t *c = secp256k1_ge_consts; + + if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s)) + return 0; + if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s)) + return 0; + if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0) + return 0; + + secp256k1_num_t rx; + secp256k1_num_init(&rx); + secp256k1_num_copy(&rx, &sig->r); + if (recid & 2) { + secp256k1_num_add(&rx, &rx, &c->order); + if (secp256k1_num_cmp(&rx, &secp256k1_fe_consts->p) >= 0) + return 0; + } + unsigned char brx[32]; + secp256k1_num_get_bin(brx, 32, &rx); + secp256k1_num_free(&rx); + secp256k1_fe_t fx; + secp256k1_fe_set_b32(&fx, brx); + secp256k1_ge_t x; + if (!secp256k1_ge_set_xo(&x, &fx, recid & 1)) + return 0; + secp256k1_gej_t xj; + secp256k1_gej_set_ge(&xj, &x); + secp256k1_num_t rn, u1, u2; + secp256k1_num_init(&rn); + secp256k1_num_init(&u1); + secp256k1_num_init(&u2); + secp256k1_num_mod_inverse(&rn, &sig->r, &c->order); + secp256k1_num_mod_mul(&u1, &rn, message, &c->order); + secp256k1_num_sub(&u1, &c->order, &u1); + secp256k1_num_mod_mul(&u2, &rn, &sig->s, &c->order); + secp256k1_gej_t qj; + secp256k1_ecmult(&qj, &xj, &u2, &u1); + secp256k1_ge_set_gej_var(pubkey, &qj); + secp256k1_num_free(&rn); + secp256k1_num_free(&u1); + secp256k1_num_free(&u2); + return !secp256k1_gej_is_infinity(&qj); +} + +static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) { + secp256k1_num_t r2; + secp256k1_num_init(&r2); + int ret = 0; + ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_num_cmp(&sig->r, &r2) == 0; + secp256k1_num_free(&r2); + return ret; +} + +static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) { + secp256k1_gej_t rp; + secp256k1_ecmult_gen(&rp, nonce); + secp256k1_ge_t r; + secp256k1_ge_set_gej(&r, &rp); + unsigned char b[32]; + secp256k1_fe_normalize(&r.x); + secp256k1_fe_normalize(&r.y); + secp256k1_fe_get_b32(b, &r.x); + int overflow = 0; + secp256k1_scalar_t sigr; + secp256k1_scalar_set_b32(&sigr, b, &overflow); + if (recid) + *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); + secp256k1_scalar_t n; + secp256k1_scalar_mul(&n, &sigr, seckey); + secp256k1_scalar_add(&n, &n, message); + secp256k1_scalar_t sigs; + secp256k1_scalar_inverse(&sigs, nonce); + secp256k1_scalar_mul(&sigs, &sigs, &n); + secp256k1_scalar_clear(&n); + secp256k1_gej_clear(&rp); + secp256k1_ge_clear(&r); + if (secp256k1_scalar_is_zero(&sigs)) + return 0; + if (secp256k1_scalar_is_high(&sigs)) { + secp256k1_scalar_negate(&sigs, &sigs); + if (recid) + *recid ^= 1; + } + secp256k1_scalar_get_num(&sig->s, &sigs); + secp256k1_scalar_get_num(&sig->r, &sigr); + return 1; +} + +static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s) { + secp256k1_num_copy(&sig->r, r); + secp256k1_num_copy(&sig->s, s); +} + +#endif diff --git a/src/secp256k1/src/eckey.h b/src/secp256k1/src/eckey.h new file mode 100644 index 0000000000..024c8b821b --- /dev/null +++ b/src/secp256k1/src/eckey.h @@ -0,0 +1,25 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECKEY_ +#define _SECP256K1_ECKEY_ + +#include "group.h" +#include "scalar.h" +#include "num.h" + +static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); +static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); + +static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen); +static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed); + +static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak); +static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak); +static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak); +static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak); + +#endif diff --git a/src/secp256k1/src/eckey_impl.h b/src/secp256k1/src/eckey_impl.h new file mode 100644 index 0000000000..290b1f0900 --- /dev/null +++ b/src/secp256k1/src/eckey_impl.h @@ -0,0 +1,200 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECKEY_IMPL_H_ +#define _SECP256K1_ECKEY_IMPL_H_ + +#include "eckey.h" + +#include "num.h" +#include "field.h" +#include "group.h" +#include "ecmult_gen.h" + +static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size) { + if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { + secp256k1_fe_t x; + secp256k1_fe_set_b32(&x, pub+1); + return secp256k1_ge_set_xo(elem, &x, pub[0] == 0x03); + } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { + secp256k1_fe_t x, y; + secp256k1_fe_set_b32(&x, pub+1); + secp256k1_fe_set_b32(&y, pub+33); + secp256k1_ge_set_xy(elem, &x, &y); + if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) + return 0; + return secp256k1_ge_is_valid(elem); + } else { + return 0; + } +} + +static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) { + if (secp256k1_ge_is_infinity(elem)) { + return 0; + } + secp256k1_fe_normalize(&elem->x); + secp256k1_fe_normalize(&elem->y); + secp256k1_fe_get_b32(&pub[1], &elem->x); + if (compressed) { + *size = 33; + pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); + } else { + *size = 65; + pub[0] = 0x04; + secp256k1_fe_get_b32(&pub[33], &elem->y); + } + return 1; +} + +static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen) { + const unsigned char *end = privkey + privkeylen; + /* sequence header */ + if (end < privkey+1 || *privkey != 0x30) + return 0; + privkey++; + /* sequence length constructor */ + int lenb = 0; + if (end < privkey+1 || !(*privkey & 0x80)) + return 0; + lenb = *privkey & ~0x80; privkey++; + if (lenb < 1 || lenb > 2) + return 0; + if (end < privkey+lenb) + return 0; + /* sequence length */ + int len = 0; + len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); + privkey += lenb; + if (end < privkey+len) + return 0; + /* sequence element 0: version number (=1) */ + if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) + return 0; + privkey += 3; + /* sequence element 1: octet string, up to 32 bytes */ + if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) + return 0; + int overflow = 0; + unsigned char c[32] = {0}; + memcpy(c + 32 - privkey[1], privkey + 2, privkey[1]); + secp256k1_scalar_set_b32(key, c, &overflow); + memset(c, 0, 32); + return !overflow; +} + +static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed) { + secp256k1_gej_t rp; + secp256k1_ecmult_gen(&rp, key); + secp256k1_ge_t r; + secp256k1_ge_set_gej(&r, &rp); + if (compressed) { + static const unsigned char begin[] = { + 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 + }; + static const unsigned char middle[] = { + 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, + 0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, + 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, + 0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, + 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 + }; + unsigned char *ptr = privkey; + memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); + secp256k1_scalar_get_b32(ptr, key); ptr += 32; + memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); + int pubkeylen = 0; + if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1)) { + return 0; + } + ptr += pubkeylen; + *privkeylen = ptr - privkey; + } else { + static const unsigned char begin[] = { + 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 + }; + static const unsigned char middle[] = { + 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, + 0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, + 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, + 0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, + 0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, + 0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, + 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 + }; + unsigned char *ptr = privkey; + memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); + secp256k1_scalar_get_b32(ptr, key); ptr += 32; + memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); + int pubkeylen = 0; + if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0)) { + return 0; + } + ptr += pubkeylen; + *privkeylen = ptr - privkey; + } + return 1; +} + +static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak) { + secp256k1_scalar_add(key, key, tweak); + if (secp256k1_scalar_is_zero(key)) + return 0; + return 1; +} + +static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak) { + if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0) + return 0; + + secp256k1_gej_t pt; + secp256k1_gej_set_ge(&pt, key); + secp256k1_num_t one; + secp256k1_num_init(&one); + secp256k1_num_set_int(&one, 1); + secp256k1_ecmult(&pt, &pt, &one, tweak); + secp256k1_num_free(&one); + + if (secp256k1_gej_is_infinity(&pt)) + return 0; + secp256k1_ge_set_gej(key, &pt); + return 1; +} + +static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak) { + if (secp256k1_scalar_is_zero(tweak)) + return 0; + + secp256k1_scalar_mul(key, key, tweak); + return 1; +} + +static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak) { + if (secp256k1_num_is_zero(tweak)) + return 0; + if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0) + return 0; + + secp256k1_num_t zero; + secp256k1_num_init(&zero); + secp256k1_num_set_int(&zero, 0); + secp256k1_gej_t pt; + secp256k1_gej_set_ge(&pt, key); + secp256k1_ecmult(&pt, &pt, tweak, &zero); + secp256k1_num_free(&zero); + secp256k1_ge_set_gej(key, &pt); + return 1; +} + +#endif diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h new file mode 100644 index 0000000000..e3cf18b680 --- /dev/null +++ b/src/secp256k1/src/ecmult.h @@ -0,0 +1,19 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_ +#define _SECP256K1_ECMULT_ + +#include "num.h" +#include "group.h" + +static void secp256k1_ecmult_start(void); +static void secp256k1_ecmult_stop(void); + +/** Double multiply: R = na*A + ng*G */ +static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng); + +#endif diff --git a/src/secp256k1/src/ecmult_gen.h b/src/secp256k1/src/ecmult_gen.h new file mode 100644 index 0000000000..42f822f9ce --- /dev/null +++ b/src/secp256k1/src/ecmult_gen.h @@ -0,0 +1,19 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_GEN_ +#define _SECP256K1_ECMULT_GEN_ + +#include "scalar.h" +#include "group.h" + +static void secp256k1_ecmult_gen_start(void); +static void secp256k1_ecmult_gen_stop(void); + +/** Multiply with the generator: R = a*G */ +static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *a); + +#endif diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h new file mode 100644 index 0000000000..07859ab04b --- /dev/null +++ b/src/secp256k1/src/ecmult_gen_impl.h @@ -0,0 +1,118 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ +#define _SECP256K1_ECMULT_GEN_IMPL_H_ + +#include "scalar.h" +#include "group.h" +#include "ecmult_gen.h" + +typedef struct { + /* For accelerating the computation of a*G: + * To harden against timing attacks, use the following mechanism: + * * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63. + * * Compute sum(n_i * 16^i * G + U_i, i=0..63), where: + * * U_i = U * 2^i (for i=0..62) + * * U_i = U * (1-2^63) (for i=63) + * where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. + * For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is + * precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). + * None of the resulting prec group elements have a known scalar, and neither do any of + * the intermediate sums while computing a*G. + * To make memory access uniform, the bytes of prec(i, n_i) are sliced per value of n_i. */ + unsigned char prec[64][sizeof(secp256k1_ge_t)][16]; /* prec[j][k][i] = k'th byte of (16^j * i * G + U_i) */ +} secp256k1_ecmult_gen_consts_t; + +static const secp256k1_ecmult_gen_consts_t *secp256k1_ecmult_gen_consts = NULL; + +static void secp256k1_ecmult_gen_start(void) { + if (secp256k1_ecmult_gen_consts != NULL) + return; + + /* Allocate the precomputation table. */ + secp256k1_ecmult_gen_consts_t *ret = (secp256k1_ecmult_gen_consts_t*)malloc(sizeof(secp256k1_ecmult_gen_consts_t)); + + /* get the generator */ + const secp256k1_ge_t *g = &secp256k1_ge_consts->g; + secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g); + + /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ + secp256k1_gej_t nums_gej; + { + static const unsigned char nums_b32[32] = "The scalar for this x is unknown"; + secp256k1_fe_t nums_x; + secp256k1_fe_set_b32(&nums_x, nums_b32); + secp256k1_ge_t nums_ge; + VERIFY_CHECK(secp256k1_ge_set_xo(&nums_ge, &nums_x, 0)); + secp256k1_gej_set_ge(&nums_gej, &nums_ge); + /* Add G to make the bits in x uniformly distributed. */ + secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, g); + } + + /* compute prec. */ + secp256k1_ge_t prec[1024]; + { + secp256k1_gej_t precj[1024]; /* Jacobian versions of prec. */ + secp256k1_gej_t gbase; gbase = gj; /* 16^j * G */ + secp256k1_gej_t numsbase; numsbase = nums_gej; /* 2^j * nums. */ + for (int j=0; j<64; j++) { + /* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ + precj[j*16] = numsbase; + for (int i=1; i<16; i++) { + secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase); + } + /* Multiply gbase by 16. */ + for (int i=0; i<4; i++) { + secp256k1_gej_double_var(&gbase, &gbase); + } + /* Multiply numbase by 2. */ + secp256k1_gej_double_var(&numsbase, &numsbase); + if (j == 62) { + /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ + secp256k1_gej_neg(&numsbase, &numsbase); + secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej); + } + } + secp256k1_ge_set_all_gej_var(1024, prec, precj); + } + for (int j=0; j<64; j++) { + for (int i=0; i<16; i++) { + const unsigned char* raw = (const unsigned char*)(&prec[j*16 + i]); + for (size_t k=0; k<sizeof(secp256k1_ge_t); k++) + ret->prec[j][k][i] = raw[k]; + } + } + + /* Set the global pointer to the precomputation table. */ + secp256k1_ecmult_gen_consts = ret; +} + +static void secp256k1_ecmult_gen_stop(void) { + if (secp256k1_ecmult_gen_consts == NULL) + return; + + secp256k1_ecmult_gen_consts_t *c = (secp256k1_ecmult_gen_consts_t*)secp256k1_ecmult_gen_consts; + secp256k1_ecmult_gen_consts = NULL; + free(c); +} + +static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *gn) { + const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts; + secp256k1_gej_set_infinity(r); + secp256k1_ge_t add; + int bits; + for (int j=0; j<64; j++) { + bits = secp256k1_scalar_get_bits(gn, j * 4, 4); + for (size_t k=0; k<sizeof(secp256k1_ge_t); k++) + ((unsigned char*)(&add))[k] = c->prec[j][k][bits]; + secp256k1_gej_add_ge(r, r, &add); + } + bits = 0; + secp256k1_ge_clear(&add); +} + +#endif diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h new file mode 100644 index 0000000000..508902564e --- /dev/null +++ b/src/secp256k1/src/ecmult_impl.h @@ -0,0 +1,222 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_IMPL_H_ +#define _SECP256K1_ECMULT_IMPL_H_ + +#include "num.h" +#include "group.h" +#include "ecmult.h" + +/* optimal for 128-bit and 256-bit exponents. */ +#define WINDOW_A 5 + +/** larger numbers may result in slightly better performance, at the cost of + exponentially larger precomputed tables. WINDOW_G == 14 results in 640 KiB. */ +#define WINDOW_G 14 + +/** Fill a table 'pre' with precomputed odd multiples of a. W determines the size of the table. + * pre will contains the values [1*a,3*a,5*a,...,(2^(w-1)-1)*a], so it needs place for + * 2^(w-2) entries. + * + * There are two versions of this function: + * - secp256k1_ecmult_precomp_wnaf_gej, which operates on group elements in jacobian notation, + * fast to precompute, but slower to use in later additions. + * - secp256k1_ecmult_precomp_wnaf_ge, which operates on group elements in affine notations, + * (much) slower to precompute, but a bit faster to use in later additions. + * To compute a*P + b*G, we use the jacobian version for P, and the affine version for G, as + * G is constant, so it only needs to be done once in advance. + */ +static void secp256k1_ecmult_table_precomp_gej_var(secp256k1_gej_t *pre, const secp256k1_gej_t *a, int w) { + pre[0] = *a; + secp256k1_gej_t d; secp256k1_gej_double_var(&d, &pre[0]); + for (int i=1; i<(1 << (w-2)); i++) + secp256k1_gej_add_var(&pre[i], &d, &pre[i-1]); +} + +static void secp256k1_ecmult_table_precomp_ge_var(secp256k1_ge_t *pre, const secp256k1_gej_t *a, int w) { + const int table_size = 1 << (w-2); + secp256k1_gej_t prej[table_size]; + prej[0] = *a; + secp256k1_gej_t d; secp256k1_gej_double_var(&d, a); + for (int i=1; i<table_size; i++) { + secp256k1_gej_add_var(&prej[i], &d, &prej[i-1]); + } + secp256k1_ge_set_all_gej_var(table_size, pre, prej); +} + +/** The number of entries a table with precomputed multiples needs to have. */ +#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) + +/** The following two macro retrieves a particular odd multiple from a table + * of precomputed multiples. */ +#define ECMULT_TABLE_GET(r,pre,n,w,neg) do { \ + VERIFY_CHECK(((n) & 1) == 1); \ + VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ + VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ + if ((n) > 0) \ + *(r) = (pre)[((n)-1)/2]; \ + else \ + (neg)((r), &(pre)[(-(n)-1)/2]); \ +} while(0) + +#define ECMULT_TABLE_GET_GEJ(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_gej_neg) +#define ECMULT_TABLE_GET_GE(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg) + +typedef struct { + /* For accelerating the computation of a*P + b*G: */ + secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of the generator */ + secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of 2^128*generator */ +} secp256k1_ecmult_consts_t; + +static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL; + +static void secp256k1_ecmult_start(void) { + if (secp256k1_ecmult_consts != NULL) + return; + + /* Allocate the precomputation table. */ + secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)malloc(sizeof(secp256k1_ecmult_consts_t)); + + /* get the generator */ + const secp256k1_ge_t *g = &secp256k1_ge_consts->g; + secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g); + + /* calculate 2^128*generator */ + secp256k1_gej_t g_128j = gj; + for (int i=0; i<128; i++) + secp256k1_gej_double_var(&g_128j, &g_128j); + + /* precompute the tables with odd multiples */ + secp256k1_ecmult_table_precomp_ge_var(ret->pre_g, &gj, WINDOW_G); + secp256k1_ecmult_table_precomp_ge_var(ret->pre_g_128, &g_128j, WINDOW_G); + + /* Set the global pointer to the precomputation table. */ + secp256k1_ecmult_consts = ret; +} + +static void secp256k1_ecmult_stop(void) { + if (secp256k1_ecmult_consts == NULL) + return; + + secp256k1_ecmult_consts_t *c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts; + secp256k1_ecmult_consts = NULL; + free(c); +} + +/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), + * with the following guarantees: + * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) + * - two non-zero entries in wnaf are separated by at least w-1 zeroes. + * - the index of the highest non-zero entry in wnaf (=return value-1) is at most bits, where + * bits is the number of bits necessary to represent the absolute value of the input. + */ +static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) { + int ret = 0; + int zeroes = 0; + secp256k1_num_t x; + secp256k1_num_copy(&x, a); + int sign = 1; + if (secp256k1_num_is_neg(&x)) { + sign = -1; + secp256k1_num_negate(&x); + } + while (!secp256k1_num_is_zero(&x)) { + while (!secp256k1_num_is_odd(&x)) { + zeroes++; + secp256k1_num_shift(&x, 1); + } + int word = secp256k1_num_shift(&x, w); + while (zeroes) { + wnaf[ret++] = 0; + zeroes--; + } + if (word & (1 << (w-1))) { + secp256k1_num_inc(&x); + wnaf[ret++] = sign * (word - (1 << w)); + } else { + wnaf[ret++] = sign * word; + } + zeroes = w-1; + } + return ret; +} + +static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) { + const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; + +#ifdef USE_ENDOMORPHISM + secp256k1_num_t na_1, na_lam; + /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ + secp256k1_gej_split_exp_var(&na_1, &na_lam, na); + + /* build wnaf representation for na_1 and na_lam. */ + int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A); + int wnaf_na_lam[129]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A); + int bits = bits_na_1; + if (bits_na_lam > bits) bits = bits_na_lam; +#else + /* build wnaf representation for na. */ + int wnaf_na[257]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A); + int bits = bits_na; +#endif + + /* calculate odd multiples of a */ + secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_ecmult_table_precomp_gej_var(pre_a, a, WINDOW_A); + +#ifdef USE_ENDOMORPHISM + secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; + for (int i=0; i<ECMULT_TABLE_SIZE(WINDOW_A); i++) + secp256k1_gej_mul_lambda(&pre_a_lam[i], &pre_a[i]); +#endif + + /* Splitted G factors. */ + secp256k1_num_t ng_1, ng_128; + + /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ + secp256k1_num_split(&ng_1, &ng_128, ng, 128); + + /* Build wnaf representation for ng_1 and ng_128 */ + int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G); + int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G); + if (bits_ng_1 > bits) bits = bits_ng_1; + if (bits_ng_128 > bits) bits = bits_ng_128; + + secp256k1_gej_set_infinity(r); + secp256k1_gej_t tmpj; + secp256k1_ge_t tmpa; + + for (int i=bits-1; i>=0; i--) { + secp256k1_gej_double_var(r, r); + int n; +#ifdef USE_ENDOMORPHISM + if (i < bits_na_1 && (n = wnaf_na_1[i])) { + ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); + secp256k1_gej_add_var(r, r, &tmpj); + } + if (i < bits_na_lam && (n = wnaf_na_lam[i])) { + ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_lam, n, WINDOW_A); + secp256k1_gej_add_var(r, r, &tmpj); + } +#else + if (i < bits_na && (n = wnaf_na[i])) { + ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); + secp256k1_gej_add_var(r, r, &tmpj); + } +#endif + if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { + ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G); + secp256k1_gej_add_ge_var(r, r, &tmpa); + } + if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { + ECMULT_TABLE_GET_GE(&tmpa, c->pre_g_128, n, WINDOW_G); + secp256k1_gej_add_ge_var(r, r, &tmpa); + } + } +} + +#endif diff --git a/src/secp256k1/src/field.h b/src/secp256k1/src/field.h new file mode 100644 index 0000000000..c7feead900 --- /dev/null +++ b/src/secp256k1/src/field.h @@ -0,0 +1,114 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_ +#define _SECP256K1_FIELD_ + +/** Field element module. + * + * Field elements can be represented in several ways, but code accessing + * it (and implementations) need to take certain properaties into account: + * - Each field element can be normalized or not. + * - Each field element has a magnitude, which represents how far away + * its representation is away from normalization. Normalized elements + * always have a magnitude of 1, but a magnitude of 1 doesn't imply + * normality. + */ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(USE_FIELD_GMP) +#include "field_gmp.h" +#elif defined(USE_FIELD_10X26) +#include "field_10x26.h" +#elif defined(USE_FIELD_5X52) +#include "field_5x52.h" +#else +#error "Please select field implementation" +#endif + +typedef struct { + secp256k1_num_t p; +} secp256k1_fe_consts_t; + +static const secp256k1_fe_consts_t *secp256k1_fe_consts = NULL; + +/** Initialize field element precomputation data. */ +static void secp256k1_fe_start(void); + +/** Unload field element precomputation data. */ +static void secp256k1_fe_stop(void); + +/** Normalize a field element. */ +static void secp256k1_fe_normalize(secp256k1_fe_t *r); + +/** Set a field element equal to a small integer. Resulting field element is normalized. */ +static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a); + +/** Verify whether a field element is zero. Requires the input to be normalized. */ +static int secp256k1_fe_is_zero(const secp256k1_fe_t *a); + +/** Check the "oddness" of a field element. Requires the input to be normalized. */ +static int secp256k1_fe_is_odd(const secp256k1_fe_t *a); + +/** Compare two field elements. Requires both inputs to be normalized */ +static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b); + +/** Set a field element equal to 32-byte big endian value. Resulting field element is normalized. */ +static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a); + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a); + +/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input + * as an argument. The magnitude of the output is one higher. */ +static void secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m); + +/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that + * small integer. */ +static void secp256k1_fe_mul_int(secp256k1_fe_t *r, int a); + +/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */ +static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a); + +/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8. + * The output magnitude is 1 (but not guaranteed to be normalized). */ +static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b); + +/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8. + * The output magnitude is 1 (but not guaranteed to be normalized). */ +static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a); + +/** Sets a field element to be the (modular) square root (if any exist) of another. Requires the + * input's magnitude to be at most 8. The output magnitude is 1 (but not guaranteed to be + * normalized). Return value indicates whether a square root was found. */ +static int secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a); + +/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be + * at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ +static void secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a); + +/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */ +static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a); + +/** Calculate the (modular) inverses of a batch of field elements. Requires the inputs' magnitudes to be + * at most 8. The output magnitudes are 1 (but not guaranteed to be normalized). The inputs and + * outputs must not overlap in memory. */ +static void secp256k1_fe_inv_all(size_t len, secp256k1_fe_t r[len], const secp256k1_fe_t a[len]); + +/** Potentially faster version of secp256k1_fe_inv_all, without constant-time guarantee. */ +static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t r[len], const secp256k1_fe_t a[len]); + + +/** Convert a field element to a hexadecimal string. */ +static void secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a); + +/** Convert a hexadecimal string to a field element. */ +static void secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen); + +#endif diff --git a/src/secp256k1/src/field_10x26.h b/src/secp256k1/src/field_10x26.h new file mode 100644 index 0000000000..66fb3f2563 --- /dev/null +++ b/src/secp256k1/src/field_10x26.h @@ -0,0 +1,21 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_ +#define _SECP256K1_FIELD_REPR_ + +#include <stdint.h> + +typedef struct { + /* X = sum(i=0..9, elem[i]*2^26) mod n */ + uint32_t n[10]; +#ifdef VERIFY + int magnitude; + int normalized; +#endif +} secp256k1_fe_t; + +#endif diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h new file mode 100644 index 0000000000..c0f1be0b2d --- /dev/null +++ b/src/secp256k1/src/field_10x26_impl.h @@ -0,0 +1,884 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ +#define _SECP256K1_FIELD_REPR_IMPL_H_ + +#include <stdio.h> +#include <string.h> +#include "util.h" +#include "num.h" +#include "field.h" + +static void secp256k1_fe_inner_start(void) {} +static void secp256k1_fe_inner_stop(void) {} + +#ifdef VERIFY +static void secp256k1_fe_verify(const secp256k1_fe_t *a) { + const uint32_t *d = a->n; + int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; + r &= (d[0] <= 0x3FFFFFFUL * m); + r &= (d[1] <= 0x3FFFFFFUL * m); + r &= (d[2] <= 0x3FFFFFFUL * m); + r &= (d[3] <= 0x3FFFFFFUL * m); + r &= (d[4] <= 0x3FFFFFFUL * m); + r &= (d[5] <= 0x3FFFFFFUL * m); + r &= (d[6] <= 0x3FFFFFFUL * m); + r &= (d[7] <= 0x3FFFFFFUL * m); + r &= (d[8] <= 0x3FFFFFFUL * m); + r &= (d[9] <= 0x03FFFFFUL * m); + r &= (a->magnitude >= 0); + if (a->normalized) { + r &= (a->magnitude <= 1); + if (r && (d[9] == 0x03FFFFFUL)) { + uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2]; + if (mid == 0x3FFFFFFUL) { + r &= ((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL); + } + } + } + VERIFY_CHECK(r == 1); +} +#else +static void secp256k1_fe_verify(const secp256k1_fe_t *a) { + (void)a; +} +#endif + +static void secp256k1_fe_normalize(secp256k1_fe_t *r) { + uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], + t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; + uint32_t m; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + /* At most a single final reduction is needed; check if the value is >= the field characteristic */ + x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) + & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); + + /* Apply the final reduction (for constant-time behaviour, we do it always) */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; + + /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ + VERIFY_CHECK(t9 >> 22 == x); + + /* Mask off the possible multiple of 2^256 from the final reduction */ + t9 &= 0x03FFFFFUL; + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; + +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { + r->n[0] = a; + r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe_t *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + const uint32_t *t = a->n; + return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0; +} + +SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe_t *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + return a->n[0] & 1; +} + +SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe_t *a) { +#ifdef VERIFY + a->magnitude = 0; + a->normalized = 1; +#endif + for (int i=0; i<10; i++) { + a->n[i] = 0; + } +} + +SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + VERIFY_CHECK(b->normalized); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); +#endif + const uint32_t *t = a->n, *u = b->n; + return ((t[0]^u[0]) | (t[1]^u[1]) | (t[2]^u[2]) | (t[3]^u[3]) | (t[4]^u[4]) + | (t[5]^u[5]) | (t[6]^u[6]) | (t[7]^u[7]) | (t[8]^u[8]) | (t[9]^u[9])) == 0; +} + +static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { + r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; + r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; + for (int i=0; i<32; i++) { + for (int j=0; j<4; j++) { + int limb = (8*i+2*j)/26; + int shift = (8*i+2*j)%26; + r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; + } + } +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + for (int i=0; i<32; i++) { + int c = 0; + for (int j=0; j<4; j++) { + int limb = (8*i+2*j)/26; + int shift = (8*i+2*j)%26; + c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); + } + r[31-i] = c; + } +} + +SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= m); + secp256k1_fe_verify(a); +#endif + r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0]; + r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1]; + r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2]; + r->n[3] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[3]; + r->n[4] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[4]; + r->n[5] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[5]; + r->n[6] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[6]; + r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7]; + r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8]; + r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9]; +#ifdef VERIFY + r->magnitude = m + 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { + r->n[0] *= a; + r->n[1] *= a; + r->n[2] *= a; + r->n[3] *= a; + r->n[4] *= a; + r->n[5] *= a; + r->n[6] *= a; + r->n[7] *= a; + r->n[8] *= a; + r->n[9] *= a; +#ifdef VERIFY + r->magnitude *= a; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { +#ifdef VERIFY + secp256k1_fe_verify(a); +#endif + r->n[0] += a->n[0]; + r->n[1] += a->n[1]; + r->n[2] += a->n[2]; + r->n[3] += a->n[3]; + r->n[4] += a->n[4]; + r->n[5] += a->n[5]; + r->n[6] += a->n[6]; + r->n[7] += a->n[7]; + r->n[8] += a->n[8]; + r->n[9] += a->n[9]; +#ifdef VERIFY + r->magnitude += a->magnitude; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +#ifdef VERIFY +#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) +#else +#define VERIFY_BITS(x, n) do { } while(0) +#endif + +SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uint32_t *b, uint32_t *r) { + VERIFY_BITS(a[0], 30); + VERIFY_BITS(a[1], 30); + VERIFY_BITS(a[2], 30); + VERIFY_BITS(a[3], 30); + VERIFY_BITS(a[4], 30); + VERIFY_BITS(a[5], 30); + VERIFY_BITS(a[6], 30); + VERIFY_BITS(a[7], 30); + VERIFY_BITS(a[8], 30); + VERIFY_BITS(a[9], 26); + VERIFY_BITS(b[0], 30); + VERIFY_BITS(b[1], 30); + VERIFY_BITS(b[2], 30); + VERIFY_BITS(b[3], 30); + VERIFY_BITS(b[4], 30); + VERIFY_BITS(b[5], 30); + VERIFY_BITS(b[6], 30); + VERIFY_BITS(b[7], 30); + VERIFY_BITS(b[8], 30); + VERIFY_BITS(b[9], 26); + + const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; + /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. + * px is a shorthand for sum(a[i]*b[x-i], i=0..x). + * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. + */ + + uint64_t c, d; + + d = (uint64_t)a[0] * b[9] + + (uint64_t)a[1] * b[8] + + (uint64_t)a[2] * b[7] + + (uint64_t)a[3] * b[6] + + (uint64_t)a[4] * b[5] + + (uint64_t)a[5] * b[4] + + (uint64_t)a[6] * b[3] + + (uint64_t)a[7] * b[2] + + (uint64_t)a[8] * b[1] + + (uint64_t)a[9] * b[0]; + /* VERIFY_BITS(d, 64); */ + /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + uint32_t t9 = d & M; d >>= 26; + VERIFY_BITS(t9, 26); + VERIFY_BITS(d, 38); + /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + + c = (uint64_t)a[0] * b[0]; + VERIFY_BITS(c, 60); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ + d += (uint64_t)a[1] * b[9] + + (uint64_t)a[2] * b[8] + + (uint64_t)a[3] * b[7] + + (uint64_t)a[4] * b[6] + + (uint64_t)a[5] * b[5] + + (uint64_t)a[6] * b[4] + + (uint64_t)a[7] * b[3] + + (uint64_t)a[8] * b[2] + + (uint64_t)a[9] * b[1]; + VERIFY_BITS(d, 63); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + uint64_t u0 = d & M; d >>= 26; c += u0 * R0; + VERIFY_BITS(u0, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 61); + /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + uint32_t t0 = c & M; c >>= 26; c += u0 * R1; + VERIFY_BITS(t0, 26); + VERIFY_BITS(c, 37); + /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + + c += (uint64_t)a[0] * b[1] + + (uint64_t)a[1] * b[0]; + VERIFY_BITS(c, 62); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ + d += (uint64_t)a[2] * b[9] + + (uint64_t)a[3] * b[8] + + (uint64_t)a[4] * b[7] + + (uint64_t)a[5] * b[6] + + (uint64_t)a[6] * b[5] + + (uint64_t)a[7] * b[4] + + (uint64_t)a[8] * b[3] + + (uint64_t)a[9] * b[2]; + VERIFY_BITS(d, 63); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + uint64_t u1 = d & M; d >>= 26; c += u1 * R0; + VERIFY_BITS(u1, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + uint32_t t1 = c & M; c >>= 26; c += u1 * R1; + VERIFY_BITS(t1, 26); + VERIFY_BITS(c, 38); + /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + + c += (uint64_t)a[0] * b[2] + + (uint64_t)a[1] * b[1] + + (uint64_t)a[2] * b[0]; + VERIFY_BITS(c, 62); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + d += (uint64_t)a[3] * b[9] + + (uint64_t)a[4] * b[8] + + (uint64_t)a[5] * b[7] + + (uint64_t)a[6] * b[6] + + (uint64_t)a[7] * b[5] + + (uint64_t)a[8] * b[4] + + (uint64_t)a[9] * b[3]; + VERIFY_BITS(d, 63); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + uint64_t u2 = d & M; d >>= 26; c += u2 * R0; + VERIFY_BITS(u2, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + uint32_t t2 = c & M; c >>= 26; c += u2 * R1; + VERIFY_BITS(t2, 26); + VERIFY_BITS(c, 38); + /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[3] + + (uint64_t)a[1] * b[2] + + (uint64_t)a[2] * b[1] + + (uint64_t)a[3] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + d += (uint64_t)a[4] * b[9] + + (uint64_t)a[5] * b[8] + + (uint64_t)a[6] * b[7] + + (uint64_t)a[7] * b[6] + + (uint64_t)a[8] * b[5] + + (uint64_t)a[9] * b[4]; + VERIFY_BITS(d, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + uint64_t u3 = d & M; d >>= 26; c += u3 * R0; + VERIFY_BITS(u3, 26); + VERIFY_BITS(d, 37); + /* VERIFY_BITS(c, 64); */ + /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + uint32_t t3 = c & M; c >>= 26; c += u3 * R1; + VERIFY_BITS(t3, 26); + VERIFY_BITS(c, 39); + /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[4] + + (uint64_t)a[1] * b[3] + + (uint64_t)a[2] * b[2] + + (uint64_t)a[3] * b[1] + + (uint64_t)a[4] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[5] * b[9] + + (uint64_t)a[6] * b[8] + + (uint64_t)a[7] * b[7] + + (uint64_t)a[8] * b[6] + + (uint64_t)a[9] * b[5]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + uint64_t u4 = d & M; d >>= 26; c += u4 * R0; + VERIFY_BITS(u4, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + uint32_t t4 = c & M; c >>= 26; c += u4 * R1; + VERIFY_BITS(t4, 26); + VERIFY_BITS(c, 39); + /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[5] + + (uint64_t)a[1] * b[4] + + (uint64_t)a[2] * b[3] + + (uint64_t)a[3] * b[2] + + (uint64_t)a[4] * b[1] + + (uint64_t)a[5] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[6] * b[9] + + (uint64_t)a[7] * b[8] + + (uint64_t)a[8] * b[7] + + (uint64_t)a[9] * b[6]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + uint64_t u5 = d & M; d >>= 26; c += u5 * R0; + VERIFY_BITS(u5, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + uint32_t t5 = c & M; c >>= 26; c += u5 * R1; + VERIFY_BITS(t5, 26); + VERIFY_BITS(c, 39); + /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[6] + + (uint64_t)a[1] * b[5] + + (uint64_t)a[2] * b[4] + + (uint64_t)a[3] * b[3] + + (uint64_t)a[4] * b[2] + + (uint64_t)a[5] * b[1] + + (uint64_t)a[6] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[7] * b[9] + + (uint64_t)a[8] * b[8] + + (uint64_t)a[9] * b[7]; + VERIFY_BITS(d, 61); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + uint64_t u6 = d & M; d >>= 26; c += u6 * R0; + VERIFY_BITS(u6, 26); + VERIFY_BITS(d, 35); + /* VERIFY_BITS(c, 64); */ + /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + uint32_t t6 = c & M; c >>= 26; c += u6 * R1; + VERIFY_BITS(t6, 26); + VERIFY_BITS(c, 39); + /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[7] + + (uint64_t)a[1] * b[6] + + (uint64_t)a[2] * b[5] + + (uint64_t)a[3] * b[4] + + (uint64_t)a[4] * b[3] + + (uint64_t)a[5] * b[2] + + (uint64_t)a[6] * b[1] + + (uint64_t)a[7] * b[0]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x8000007C00000007ULL); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[8] * b[9] + + (uint64_t)a[9] * b[8]; + VERIFY_BITS(d, 58); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + uint64_t u7 = d & M; d >>= 26; c += u7 * R0; + VERIFY_BITS(u7, 26); + VERIFY_BITS(d, 32); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); + /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + uint32_t t7 = c & M; c >>= 26; c += u7 * R1; + VERIFY_BITS(t7, 26); + VERIFY_BITS(c, 38); + /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[8] + + (uint64_t)a[1] * b[7] + + (uint64_t)a[2] * b[6] + + (uint64_t)a[3] * b[5] + + (uint64_t)a[4] * b[4] + + (uint64_t)a[5] * b[3] + + (uint64_t)a[6] * b[2] + + (uint64_t)a[7] * b[1] + + (uint64_t)a[8] * b[0]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000007B80000008ULL); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[9] * b[9]; + VERIFY_BITS(d, 57); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + uint64_t u8 = d & M; d >>= 26; c += u8 * R0; + VERIFY_BITS(u8, 26); + VERIFY_BITS(d, 31); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[3] = t3; + VERIFY_BITS(r[3], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = t4; + VERIFY_BITS(r[4], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[5] = t5; + VERIFY_BITS(r[5], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[6] = t6; + VERIFY_BITS(r[6], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[7] = t7; + VERIFY_BITS(r[7], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[8] = c & M; c >>= 26; c += u8 * R1; + VERIFY_BITS(r[8], 26); + VERIFY_BITS(c, 39); + /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += d * R0 + t9; + VERIFY_BITS(c, 45); + /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); + VERIFY_BITS(r[9], 22); + VERIFY_BITS(c, 46); + /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + d = c * (R0 >> 4) + t0; + VERIFY_BITS(d, 56); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[0] = d & M; d >>= 26; + VERIFY_BITS(r[0], 26); + VERIFY_BITS(d, 30); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += c * (R1 >> 4) + t1; + VERIFY_BITS(d, 53); + VERIFY_CHECK(d <= 0x10000003FFFFBFULL); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[1] = d & M; d >>= 26; + VERIFY_BITS(r[1], 26); + VERIFY_BITS(d, 27); + VERIFY_CHECK(d <= 0x4000000ULL); + /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += t2; + VERIFY_BITS(d, 27); + /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = d; + VERIFY_BITS(r[2], 27); + /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} + +SECP256K1_INLINE static void secp256k1_fe_sqr_inner(const uint32_t *a, uint32_t *r) { + VERIFY_BITS(a[0], 30); + VERIFY_BITS(a[1], 30); + VERIFY_BITS(a[2], 30); + VERIFY_BITS(a[3], 30); + VERIFY_BITS(a[4], 30); + VERIFY_BITS(a[5], 30); + VERIFY_BITS(a[6], 30); + VERIFY_BITS(a[7], 30); + VERIFY_BITS(a[8], 30); + VERIFY_BITS(a[9], 26); + + const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; + /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. + * px is a shorthand for sum(a[i]*a[x-i], i=0..x). + * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. + */ + + uint64_t c, d; + + d = (uint64_t)(a[0]*2) * a[9] + + (uint64_t)(a[1]*2) * a[8] + + (uint64_t)(a[2]*2) * a[7] + + (uint64_t)(a[3]*2) * a[6] + + (uint64_t)(a[4]*2) * a[5]; + /* VERIFY_BITS(d, 64); */ + /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + uint32_t t9 = d & M; d >>= 26; + VERIFY_BITS(t9, 26); + VERIFY_BITS(d, 38); + /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + + c = (uint64_t)a[0] * a[0]; + VERIFY_BITS(c, 60); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ + d += (uint64_t)(a[1]*2) * a[9] + + (uint64_t)(a[2]*2) * a[8] + + (uint64_t)(a[3]*2) * a[7] + + (uint64_t)(a[4]*2) * a[6] + + (uint64_t)a[5] * a[5]; + VERIFY_BITS(d, 63); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + uint64_t u0 = d & M; d >>= 26; c += u0 * R0; + VERIFY_BITS(u0, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 61); + /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + uint32_t t0 = c & M; c >>= 26; c += u0 * R1; + VERIFY_BITS(t0, 26); + VERIFY_BITS(c, 37); + /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + + c += (uint64_t)(a[0]*2) * a[1]; + VERIFY_BITS(c, 62); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ + d += (uint64_t)(a[2]*2) * a[9] + + (uint64_t)(a[3]*2) * a[8] + + (uint64_t)(a[4]*2) * a[7] + + (uint64_t)(a[5]*2) * a[6]; + VERIFY_BITS(d, 63); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + uint64_t u1 = d & M; d >>= 26; c += u1 * R0; + VERIFY_BITS(u1, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + uint32_t t1 = c & M; c >>= 26; c += u1 * R1; + VERIFY_BITS(t1, 26); + VERIFY_BITS(c, 38); + /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[2] + + (uint64_t)a[1] * a[1]; + VERIFY_BITS(c, 62); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + d += (uint64_t)(a[3]*2) * a[9] + + (uint64_t)(a[4]*2) * a[8] + + (uint64_t)(a[5]*2) * a[7] + + (uint64_t)a[6] * a[6]; + VERIFY_BITS(d, 63); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + uint64_t u2 = d & M; d >>= 26; c += u2 * R0; + VERIFY_BITS(u2, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + uint32_t t2 = c & M; c >>= 26; c += u2 * R1; + VERIFY_BITS(t2, 26); + VERIFY_BITS(c, 38); + /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[3] + + (uint64_t)(a[1]*2) * a[2]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + d += (uint64_t)(a[4]*2) * a[9] + + (uint64_t)(a[5]*2) * a[8] + + (uint64_t)(a[6]*2) * a[7]; + VERIFY_BITS(d, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + uint64_t u3 = d & M; d >>= 26; c += u3 * R0; + VERIFY_BITS(u3, 26); + VERIFY_BITS(d, 37); + /* VERIFY_BITS(c, 64); */ + /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + uint32_t t3 = c & M; c >>= 26; c += u3 * R1; + VERIFY_BITS(t3, 26); + VERIFY_BITS(c, 39); + /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[4] + + (uint64_t)(a[1]*2) * a[3] + + (uint64_t)a[2] * a[2]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[5]*2) * a[9] + + (uint64_t)(a[6]*2) * a[8] + + (uint64_t)a[7] * a[7]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + uint64_t u4 = d & M; d >>= 26; c += u4 * R0; + VERIFY_BITS(u4, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + uint32_t t4 = c & M; c >>= 26; c += u4 * R1; + VERIFY_BITS(t4, 26); + VERIFY_BITS(c, 39); + /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[5] + + (uint64_t)(a[1]*2) * a[4] + + (uint64_t)(a[2]*2) * a[3]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[6]*2) * a[9] + + (uint64_t)(a[7]*2) * a[8]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + uint64_t u5 = d & M; d >>= 26; c += u5 * R0; + VERIFY_BITS(u5, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + uint32_t t5 = c & M; c >>= 26; c += u5 * R1; + VERIFY_BITS(t5, 26); + VERIFY_BITS(c, 39); + /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[6] + + (uint64_t)(a[1]*2) * a[5] + + (uint64_t)(a[2]*2) * a[4] + + (uint64_t)a[3] * a[3]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[7]*2) * a[9] + + (uint64_t)a[8] * a[8]; + VERIFY_BITS(d, 61); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + uint64_t u6 = d & M; d >>= 26; c += u6 * R0; + VERIFY_BITS(u6, 26); + VERIFY_BITS(d, 35); + /* VERIFY_BITS(c, 64); */ + /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + uint32_t t6 = c & M; c >>= 26; c += u6 * R1; + VERIFY_BITS(t6, 26); + VERIFY_BITS(c, 39); + /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[7] + + (uint64_t)(a[1]*2) * a[6] + + (uint64_t)(a[2]*2) * a[5] + + (uint64_t)(a[3]*2) * a[4]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x8000007C00000007ULL); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[8]*2) * a[9]; + VERIFY_BITS(d, 58); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + uint64_t u7 = d & M; d >>= 26; c += u7 * R0; + VERIFY_BITS(u7, 26); + VERIFY_BITS(d, 32); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); + /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + uint32_t t7 = c & M; c >>= 26; c += u7 * R1; + VERIFY_BITS(t7, 26); + VERIFY_BITS(c, 38); + /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[8] + + (uint64_t)(a[1]*2) * a[7] + + (uint64_t)(a[2]*2) * a[6] + + (uint64_t)(a[3]*2) * a[5] + + (uint64_t)a[4] * a[4]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000007B80000008ULL); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[9] * a[9]; + VERIFY_BITS(d, 57); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + uint64_t u8 = d & M; d >>= 26; c += u8 * R0; + VERIFY_BITS(u8, 26); + VERIFY_BITS(d, 31); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[3] = t3; + VERIFY_BITS(r[3], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = t4; + VERIFY_BITS(r[4], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[5] = t5; + VERIFY_BITS(r[5], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[6] = t6; + VERIFY_BITS(r[6], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[7] = t7; + VERIFY_BITS(r[7], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[8] = c & M; c >>= 26; c += u8 * R1; + VERIFY_BITS(r[8], 26); + VERIFY_BITS(c, 39); + /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += d * R0 + t9; + VERIFY_BITS(c, 45); + /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); + VERIFY_BITS(r[9], 22); + VERIFY_BITS(c, 46); + /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + d = c * (R0 >> 4) + t0; + VERIFY_BITS(d, 56); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[0] = d & M; d >>= 26; + VERIFY_BITS(r[0], 26); + VERIFY_BITS(d, 30); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += c * (R1 >> 4) + t1; + VERIFY_BITS(d, 53); + VERIFY_CHECK(d <= 0x10000003FFFFBFULL); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[1] = d & M; d >>= 26; + VERIFY_BITS(r[1], 26); + VERIFY_BITS(d, 27); + VERIFY_CHECK(d <= 0x4000000ULL); + /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += t2; + VERIFY_BITS(d, 27); + /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = d; + VERIFY_BITS(r[2], 27); + /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} + + +static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + VERIFY_CHECK(b->magnitude <= 8); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); +#endif + secp256k1_fe_mul_inner(a->n, b->n, r->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + secp256k1_fe_verify(a); +#endif + secp256k1_fe_sqr_inner(a->n, r->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +#endif diff --git a/src/secp256k1/src/field_5x52.h b/src/secp256k1/src/field_5x52.h new file mode 100644 index 0000000000..aeb0a6a1e8 --- /dev/null +++ b/src/secp256k1/src/field_5x52.h @@ -0,0 +1,21 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_ +#define _SECP256K1_FIELD_REPR_ + +#include <stdint.h> + +typedef struct { + /* X = sum(i=0..4, elem[i]*2^52) mod n */ + uint64_t n[5]; +#ifdef VERIFY + int magnitude; + int normalized; +#endif +} secp256k1_fe_t; + +#endif diff --git a/src/secp256k1/src/field_5x52_asm.asm b/src/secp256k1/src/field_5x52_asm.asm new file mode 100644 index 0000000000..5e785f7630 --- /dev/null +++ b/src/secp256k1/src/field_5x52_asm.asm @@ -0,0 +1,469 @@ + ;; Added by Diederik Huys, March 2013 + ;; + ;; Provided public procedures: + ;; secp256k1_fe_mul_inner + ;; secp256k1_fe_sqr_inner + ;; + ;; Needed tools: YASM (http://yasm.tortall.net) + ;; + ;; + + BITS 64 + +%ifidn __OUTPUT_FORMAT__,macho64 +%define SYM(x) _ %+ x +%else +%define SYM(x) x +%endif + + ;; Procedure ExSetMult + ;; Register Layout: + ;; INPUT: rdi = a->n + ;; rsi = b->n + ;; rdx = r->a + ;; + ;; INTERNAL: rdx:rax = multiplication accumulator + ;; r9:r8 = c + ;; r10-r13 = t0-t3 + ;; r14 = b.n[0] / t4 + ;; r15 = b.n[1] / t5 + ;; rbx = b.n[2] / t6 + ;; rcx = b.n[3] / t7 + ;; rbp = Constant 0FFFFFFFFFFFFFh / t8 + ;; rsi = b.n / b.n[4] / t9 + + GLOBAL SYM(secp256k1_fe_mul_inner) + ALIGN 32 +SYM(secp256k1_fe_mul_inner): + push rbp + push rbx + push r12 + push r13 + push r14 + push r15 + push rdx + mov r14,[rsi+8*0] ; preload b.n[0]. This will be the case until + ; b.n[0] is no longer needed, then we reassign + ; r14 to t4 + ;; c=a.n[0] * b.n[0] + mov rax,[rdi+0*8] ; load a.n[0] + mov rbp,0FFFFFFFFFFFFFh + mul r14 ; rdx:rax=a.n[0]*b.n[0] + mov r15,[rsi+1*8] + mov r10,rbp ; load modulus into target register for t0 + mov r8,rax + and r10,rax ; only need lower qword of c + shrd r8,rdx,52 + xor r9,r9 ; c < 2^64, so we ditch the HO part + + ;; c+=a.n[0] * b.n[1] + a.n[1] * b.n[0] + mov rax,[rdi+0*8] + mul r15 + add r8,rax + adc r9,rdx + + mov rax,[rdi+1*8] + mul r14 + mov r11,rbp + mov rbx,[rsi+2*8] + add r8,rax + adc r9,rdx + and r11,r8 + shrd r8,r9,52 + xor r9,r9 + + ;; c+=a.n[0 1 2] * b.n[2 1 0] + mov rax,[rdi+0*8] + mul rbx + add r8,rax + adc r9,rdx + + mov rax,[rdi+1*8] + mul r15 + add r8,rax + adc r9,rdx + + mov rax,[rdi+2*8] + mul r14 + mov r12,rbp + mov rcx,[rsi+3*8] + add r8,rax + adc r9,rdx + and r12,r8 + shrd r8,r9,52 + xor r9,r9 + + ;; c+=a.n[0 1 2 3] * b.n[3 2 1 0] + mov rax,[rdi+0*8] + mul rcx + add r8,rax + adc r9,rdx + + mov rax,[rdi+1*8] + mul rbx + add r8,rax + adc r9,rdx + + mov rax,[rdi+2*8] + mul r15 + add r8,rax + adc r9,rdx + + mov rax,[rdi+3*8] + mul r14 + mov r13,rbp + mov rsi,[rsi+4*8] ; load b.n[4] and destroy pointer + add r8,rax + adc r9,rdx + and r13,r8 + + shrd r8,r9,52 + xor r9,r9 + + + ;; c+=a.n[0 1 2 3 4] * b.n[4 3 2 1 0] + mov rax,[rdi+0*8] + mul rsi + add r8,rax + adc r9,rdx + + mov rax,[rdi+1*8] + mul rcx + add r8,rax + adc r9,rdx + + mov rax,[rdi+2*8] + mul rbx + add r8,rax + adc r9,rdx + + mov rax,[rdi+3*8] + mul r15 + add r8,rax + adc r9,rdx + + mov rax,[rdi+4*8] + mul r14 + mov r14,rbp ; load modulus into t4 and destroy a.n[0] + add r8,rax + adc r9,rdx + and r14,r8 + shrd r8,r9,52 + xor r9,r9 + + ;; c+=a.n[1 2 3 4] * b.n[4 3 2 1] + mov rax,[rdi+1*8] + mul rsi + add r8,rax + adc r9,rdx + + mov rax,[rdi+2*8] + mul rcx + add r8,rax + adc r9,rdx + + mov rax,[rdi+3*8] + mul rbx + add r8,rax + adc r9,rdx + + mov rax,[rdi+4*8] + mul r15 + mov r15,rbp + add r8,rax + adc r9,rdx + + and r15,r8 + shrd r8,r9,52 + xor r9,r9 + + ;; c+=a.n[2 3 4] * b.n[4 3 2] + mov rax,[rdi+2*8] + mul rsi + add r8,rax + adc r9,rdx + + mov rax,[rdi+3*8] + mul rcx + add r8,rax + adc r9,rdx + + mov rax,[rdi+4*8] + mul rbx + mov rbx,rbp + add r8,rax + adc r9,rdx + + and rbx,r8 + shrd r8,r9,52 + xor r9,r9 + + ;; c+=a.n[3 4] * b.n[4 3] + mov rax,[rdi+3*8] + mul rsi + add r8,rax + adc r9,rdx + + mov rax,[rdi+4*8] + mul rcx + mov rcx,rbp + add r8,rax + adc r9,rdx + and rcx,r8 + shrd r8,r9,52 + xor r9,r9 + + ;; c+=a.n[4] * b.n[4] + mov rax,[rdi+4*8] + mul rsi + ;; mov rbp,rbp ; modulus already there! + add r8,rax + adc r9,rdx + and rbp,r8 + shrd r8,r9,52 + xor r9,r9 + + mov rsi,r8 ; load c into t9 and destroy b.n[4] + + ;; ******************************************************* +common_exit_norm: + mov rdi,01000003D10h ; load constant + + mov rax,r15 ; get t5 + mul rdi + add rax,r10 ; +t0 + adc rdx,0 + mov r10,0FFFFFFFFFFFFFh ; modulus. Sadly, we ran out of registers! + mov r8,rax ; +c + and r10,rax + shrd r8,rdx,52 + xor r9,r9 + + mov rax,rbx ; get t6 + mul rdi + add rax,r11 ; +t1 + adc rdx,0 + mov r11,0FFFFFFFFFFFFFh ; modulus + add r8,rax ; +c + adc r9,rdx + and r11,r8 + shrd r8,r9,52 + xor r9,r9 + + mov rax,rcx ; get t7 + mul rdi + add rax,r12 ; +t2 + adc rdx,0 + pop rbx ; retrieve pointer to this.n + mov r12,0FFFFFFFFFFFFFh ; modulus + add r8,rax ; +c + adc r9,rdx + and r12,r8 + mov [rbx+2*8],r12 ; mov into this.n[2] + shrd r8,r9,52 + xor r9,r9 + + mov rax,rbp ; get t8 + mul rdi + add rax,r13 ; +t3 + adc rdx,0 + mov r13,0FFFFFFFFFFFFFh ; modulus + add r8,rax ; +c + adc r9,rdx + and r13,r8 + mov [rbx+3*8],r13 ; -> this.n[3] + shrd r8,r9,52 + xor r9,r9 + + mov rax,rsi ; get t9 + mul rdi + add rax,r14 ; +t4 + adc rdx,0 + mov r14,0FFFFFFFFFFFFh ; !!! + add r8,rax ; +c + adc r9,rdx + and r14,r8 + mov [rbx+4*8],r14 ; -> this.n[4] + shrd r8,r9,48 ; !!! + xor r9,r9 + + mov rax,01000003D1h + mul r8 + add rax,r10 + adc rdx,0 + mov r10,0FFFFFFFFFFFFFh ; modulus + mov r8,rax + and rax,r10 + shrd r8,rdx,52 + mov [rbx+0*8],rax ; -> this.n[0] + add r8,r11 + mov [rbx+1*8],r8 ; -> this.n[1] + + pop r15 + pop r14 + pop r13 + pop r12 + pop rbx + pop rbp + ret + + + ;; PROC ExSetSquare + ;; Register Layout: + ;; INPUT: rdi = a.n + ;; rsi = this.a + ;; INTERNAL: rdx:rax = multiplication accumulator + ;; r9:r8 = c + ;; r10-r13 = t0-t3 + ;; r14 = a.n[0] / t4 + ;; r15 = a.n[1] / t5 + ;; rbx = a.n[2] / t6 + ;; rcx = a.n[3] / t7 + ;; rbp = 0FFFFFFFFFFFFFh / t8 + ;; rsi = a.n[4] / t9 + GLOBAL SYM(secp256k1_fe_sqr_inner) + ALIGN 32 +SYM(secp256k1_fe_sqr_inner): + push rbp + push rbx + push r12 + push r13 + push r14 + push r15 + push rsi + mov rbp,0FFFFFFFFFFFFFh + + ;; c=a.n[0] * a.n[0] + mov r14,[rdi+0*8] ; r14=a.n[0] + mov r10,rbp ; modulus + mov rax,r14 + mul rax + mov r15,[rdi+1*8] ; a.n[1] + add r14,r14 ; r14=2*a.n[0] + mov r8,rax + and r10,rax ; only need lower qword + shrd r8,rdx,52 + xor r9,r9 + + ;; c+=2*a.n[0] * a.n[1] + mov rax,r14 ; r14=2*a.n[0] + mul r15 + mov rbx,[rdi+2*8] ; rbx=a.n[2] + mov r11,rbp ; modulus + add r8,rax + adc r9,rdx + and r11,r8 + shrd r8,r9,52 + xor r9,r9 + + ;; c+=2*a.n[0]*a.n[2]+a.n[1]*a.n[1] + mov rax,r14 + mul rbx + add r8,rax + adc r9,rdx + + mov rax,r15 + mov r12,rbp ; modulus + mul rax + mov rcx,[rdi+3*8] ; rcx=a.n[3] + add r15,r15 ; r15=a.n[1]*2 + add r8,rax + adc r9,rdx + and r12,r8 ; only need lower dword + shrd r8,r9,52 + xor r9,r9 + + ;; c+=2*a.n[0]*a.n[3]+2*a.n[1]*a.n[2] + mov rax,r14 + mul rcx + add r8,rax + adc r9,rdx + + mov rax,r15 ; rax=2*a.n[1] + mov r13,rbp ; modulus + mul rbx + mov rsi,[rdi+4*8] ; rsi=a.n[4] + add r8,rax + adc r9,rdx + and r13,r8 + shrd r8,r9,52 + xor r9,r9 + + ;; c+=2*a.n[0]*a.n[4]+2*a.n[1]*a.n[3]+a.n[2]*a.n[2] + mov rax,r14 ; last time we need 2*a.n[0] + mul rsi + add r8,rax + adc r9,rdx + + mov rax,r15 + mul rcx + mov r14,rbp ; modulus + add r8,rax + adc r9,rdx + + mov rax,rbx + mul rax + add rbx,rbx ; rcx=2*a.n[2] + add r8,rax + adc r9,rdx + and r14,r8 + shrd r8,r9,52 + xor r9,r9 + + ;; c+=2*a.n[1]*a.n[4]+2*a.n[2]*a.n[3] + mov rax,r15 ; last time we need 2*a.n[1] + mul rsi + add r8,rax + adc r9,rdx + + mov rax,rbx + mul rcx + mov r15,rbp ; modulus + add r8,rax + adc r9,rdx + and r15,r8 + shrd r8,r9,52 + xor r9,r9 + + ;; c+=2*a.n[2]*a.n[4]+a.n[3]*a.n[3] + mov rax,rbx ; last time we need 2*a.n[2] + mul rsi + add r8,rax + adc r9,rdx + + mov rax,rcx ; a.n[3] + mul rax + mov rbx,rbp ; modulus + add r8,rax + adc r9,rdx + and rbx,r8 ; only need lower dword + lea rax,[2*rcx] + shrd r8,r9,52 + xor r9,r9 + + ;; c+=2*a.n[3]*a.n[4] + mul rsi + mov rcx,rbp ; modulus + add r8,rax + adc r9,rdx + and rcx,r8 ; only need lower dword + shrd r8,r9,52 + xor r9,r9 + + ;; c+=a.n[4]*a.n[4] + mov rax,rsi + mul rax + ;; mov rbp,rbp ; modulus is already there! + add r8,rax + adc r9,rdx + and rbp,r8 + shrd r8,r9,52 + xor r9,r9 + + mov rsi,r8 + + ;; ******************************************************* + jmp common_exit_norm + end + + diff --git a/src/secp256k1/src/field_5x52_asm_impl.h b/src/secp256k1/src/field_5x52_asm_impl.h new file mode 100644 index 0000000000..f29605b11b --- /dev/null +++ b/src/secp256k1/src/field_5x52_asm_impl.h @@ -0,0 +1,13 @@ +/********************************************************************** + * Copyright (c) 2013 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ + +void __attribute__ ((sysv_abi)) secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r); +void __attribute__ ((sysv_abi)) secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r); + +#endif diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h new file mode 100644 index 0000000000..d1b06d05a4 --- /dev/null +++ b/src/secp256k1/src/field_5x52_impl.h @@ -0,0 +1,260 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ +#define _SECP256K1_FIELD_REPR_IMPL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include <string.h> +#include "util.h" +#include "num.h" +#include "field.h" + +#if defined(USE_FIELD_5X52_ASM) +#include "field_5x52_asm_impl.h" +#elif defined(USE_FIELD_5X52_INT128) +#include "field_5x52_int128_impl.h" +#else +#error "Please select field_5x52 implementation" +#endif + +/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F, + * represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular, + * each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element + * is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations + * accept any input with magnitude at most M, and have different rules for propagating magnitude to their + * output. + */ + +static void secp256k1_fe_inner_start(void) {} +static void secp256k1_fe_inner_stop(void) {} + +#ifdef VERIFY +static void secp256k1_fe_verify(const secp256k1_fe_t *a) { + const uint64_t *d = a->n; + int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; + r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m); + r &= (a->magnitude >= 0); + if (a->normalized) { + r &= (a->magnitude <= 1); + if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) { + r &= (d[0] < 0xFFFFEFFFFFC2FULL); + } + } + VERIFY_CHECK(r == 1); +} +#else +static void secp256k1_fe_verify(const secp256k1_fe_t *a) { + (void)a; +} +#endif + +static void secp256k1_fe_normalize(secp256k1_fe_t *r) { + uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; + uint64_t m; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + /* At most a single final reduction is needed; check if the value is >= the field characteristic */ + x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) + & (t0 >= 0xFFFFEFFFFFC2FULL)); + + /* Apply the final reduction (for constant-time behaviour, we do it always) */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; + + /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ + VERIFY_CHECK(t4 >> 48 == x); + + /* Mask off the possible multiple of 2^256 from the final reduction */ + t4 &= 0x0FFFFFFFFFFFFULL; + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { + r->n[0] = a; + r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe_t *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + const uint64_t *t = a->n; + return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0; +} + +SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe_t *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + return a->n[0] & 1; +} + +SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe_t *a) { +#ifdef VERIFY + a->magnitude = 0; + a->normalized = 1; +#endif + for (int i=0; i<5; i++) { + a->n[i] = 0; + } +} + +SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + VERIFY_CHECK(b->normalized); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); +#endif + const uint64_t *t = a->n, *u = b->n; + return ((t[0]^u[0]) | (t[1]^u[1]) | (t[2]^u[2]) | (t[3]^u[3]) | (t[4]^u[4])) == 0; +} + +static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { + r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; + for (int i=0; i<32; i++) { + for (int j=0; j<2; j++) { + int limb = (8*i+4*j)/52; + int shift = (8*i+4*j)%52; + r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; + } + } +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + for (int i=0; i<32; i++) { + int c = 0; + for (int j=0; j<2; j++) { + int limb = (8*i+4*j)/52; + int shift = (8*i+4*j)%52; + c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); + } + r[31-i] = c; + } +} + +SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= m); + secp256k1_fe_verify(a); +#endif + r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0]; + r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1]; + r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2]; + r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3]; + r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4]; +#ifdef VERIFY + r->magnitude = m + 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { + r->n[0] *= a; + r->n[1] *= a; + r->n[2] *= a; + r->n[3] *= a; + r->n[4] *= a; +#ifdef VERIFY + r->magnitude *= a; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { +#ifdef VERIFY + secp256k1_fe_verify(a); +#endif + r->n[0] += a->n[0]; + r->n[1] += a->n[1]; + r->n[2] += a->n[2]; + r->n[3] += a->n[3]; + r->n[4] += a->n[4]; +#ifdef VERIFY + r->magnitude += a->magnitude; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + VERIFY_CHECK(b->magnitude <= 8); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); +#endif + secp256k1_fe_mul_inner(a->n, b->n, r->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + secp256k1_fe_verify(a); +#endif + secp256k1_fe_sqr_inner(a->n, r->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +#endif diff --git a/src/secp256k1/src/field_5x52_int128_impl.h b/src/secp256k1/src/field_5x52_int128_impl.h new file mode 100644 index 0000000000..c476428672 --- /dev/null +++ b/src/secp256k1/src/field_5x52_int128_impl.h @@ -0,0 +1,279 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ + +#include <stdint.h> + +#ifdef VERIFY +#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) +#else +#define VERIFY_BITS(x, n) do { } while(0) +#endif + +SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r) { + VERIFY_BITS(a[0], 56); + VERIFY_BITS(a[1], 56); + VERIFY_BITS(a[2], 56); + VERIFY_BITS(a[3], 56); + VERIFY_BITS(a[4], 52); + VERIFY_BITS(b[0], 56); + VERIFY_BITS(b[1], 56); + VERIFY_BITS(b[2], 56); + VERIFY_BITS(b[3], 56); + VERIFY_BITS(b[4], 52); + + const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; + /* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. + * px is a shorthand for sum(a[i]*b[x-i], i=0..x). + * Note that [x 0 0 0 0 0] = [x*R]. + */ + + __int128 c, d; + + d = (__int128)a[0] * b[3] + + (__int128)a[1] * b[2] + + (__int128)a[2] * b[1] + + (__int128)a[3] * b[0]; + VERIFY_BITS(d, 114); + /* [d 0 0 0] = [p3 0 0 0] */ + c = (__int128)a[4] * b[4]; + VERIFY_BITS(c, 112); + /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + d += (c & M) * R; c >>= 52; + VERIFY_BITS(d, 115); + VERIFY_BITS(c, 60); + /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + uint64_t t3 = d & M; d >>= 52; + VERIFY_BITS(t3, 52); + VERIFY_BITS(d, 63); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + + d += (__int128)a[0] * b[4] + + (__int128)a[1] * b[3] + + (__int128)a[2] * b[2] + + (__int128)a[3] * b[1] + + (__int128)a[4] * b[0]; + VERIFY_BITS(d, 115); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + d += c * R; + VERIFY_BITS(d, 116); + /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + uint64_t t4 = d & M; d >>= 52; + VERIFY_BITS(t4, 52); + VERIFY_BITS(d, 64); + /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + uint64_t tx = (t4 >> 48); t4 &= (M >> 4); + VERIFY_BITS(tx, 4); + VERIFY_BITS(t4, 48); + /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + + c = (__int128)a[0] * b[0]; + VERIFY_BITS(c, 112); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ + d += (__int128)a[1] * b[4] + + (__int128)a[2] * b[3] + + (__int128)a[3] * b[2] + + (__int128)a[4] * b[1]; + VERIFY_BITS(d, 115); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + uint64_t u0 = d & M; d >>= 52; + VERIFY_BITS(u0, 52); + VERIFY_BITS(d, 63); + /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + u0 = (u0 << 4) | tx; + VERIFY_BITS(u0, 56); + /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + c += (__int128)u0 * (R >> 4); + VERIFY_BITS(c, 115); + /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + uint64_t t0 = c & M; c >>= 52; + VERIFY_BITS(t0, 52); + VERIFY_BITS(c, 61); + /* [d 0 t4 t3 0 c t0] = [p8 0 0 p5 p4 p3 0 0 p0] */ + + c += (__int128)a[0] * b[1] + + (__int128)a[1] * b[0]; + VERIFY_BITS(c, 114); + /* [d 0 t4 t3 0 c t0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ + d += (__int128)a[2] * b[4] + + (__int128)a[3] * b[3] + + (__int128)a[4] * b[2]; + VERIFY_BITS(d, 114); + /* [d 0 t4 t3 0 c t0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 t4 t3 0 c t0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + uint64_t t1 = c & M; c >>= 52; + VERIFY_BITS(t1, 52); + VERIFY_BITS(c, 63); + /* [d 0 0 t4 t3 c t1 t0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + + c += (__int128)a[0] * b[2] + + (__int128)a[1] * b[1] + + (__int128)a[2] * b[0]; + VERIFY_BITS(c, 114); + /* [d 0 0 t4 t3 c t1 t0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (__int128)a[3] * b[4] + + (__int128)a[4] * b[3]; + VERIFY_BITS(d, 114); + /* [d 0 0 t4 t3 c t1 t0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 0 t4 t3 c t1 t0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[0] = t0; + VERIFY_BITS(r[0], 52); + /* [d 0 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[1] = t1; + VERIFY_BITS(r[1], 52); + /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = c & M; c >>= 52; + VERIFY_BITS(r[2], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += d * R + t3;; + VERIFY_BITS(c, 100); + /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[3] = c & M; c >>= 52; + VERIFY_BITS(r[3], 52); + VERIFY_BITS(c, 48); + /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += t4; + VERIFY_BITS(c, 49); + /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = c; + VERIFY_BITS(r[4], 49); + /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} + +SECP256K1_INLINE static void secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r) { + VERIFY_BITS(a[0], 56); + VERIFY_BITS(a[1], 56); + VERIFY_BITS(a[2], 56); + VERIFY_BITS(a[3], 56); + VERIFY_BITS(a[4], 52); + + const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; + /** [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. + * px is a shorthand for sum(a[i]*a[x-i], i=0..x). + * Note that [x 0 0 0 0 0] = [x*R]. + */ + + __int128 c, d; + + uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; + + d = (__int128)(a0*2) * a3 + + (__int128)(a1*2) * a2; + VERIFY_BITS(d, 114); + /* [d 0 0 0] = [p3 0 0 0] */ + c = (__int128)a4 * a4; + VERIFY_BITS(c, 112); + /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + d += (c & M) * R; c >>= 52; + VERIFY_BITS(d, 115); + VERIFY_BITS(c, 60); + /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + uint64_t t3 = d & M; d >>= 52; + VERIFY_BITS(t3, 52); + VERIFY_BITS(d, 63); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + + a4 *= 2; + d += (__int128)a0 * a4 + + (__int128)(a1*2) * a3 + + (__int128)a2 * a2; + VERIFY_BITS(d, 115); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + d += c * R; + VERIFY_BITS(d, 116); + /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + uint64_t t4 = d & M; d >>= 52; + VERIFY_BITS(t4, 52); + VERIFY_BITS(d, 64); + /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + uint64_t tx = (t4 >> 48); t4 &= (M >> 4); + VERIFY_BITS(tx, 4); + VERIFY_BITS(t4, 48); + /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + + c = (__int128)a0 * a0; + VERIFY_BITS(c, 112); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ + d += (__int128)a1 * a4 + + (__int128)(a2*2) * a3; + VERIFY_BITS(d, 114); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + uint64_t u0 = d & M; d >>= 52; + VERIFY_BITS(u0, 52); + VERIFY_BITS(d, 62); + /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + u0 = (u0 << 4) | tx; + VERIFY_BITS(u0, 56); + /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + c += (__int128)u0 * (R >> 4); + VERIFY_BITS(c, 113); + /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + r[0] = c & M; c >>= 52; + VERIFY_BITS(r[0], 52); + VERIFY_BITS(c, 61); + /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ + + a0 *= 2; + c += (__int128)a0 * a1; + VERIFY_BITS(c, 114); + /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ + d += (__int128)a2 * a4 + + (__int128)a3 * a3; + VERIFY_BITS(d, 114); + /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + r[1] = c & M; c >>= 52; + VERIFY_BITS(r[1], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + + c += (__int128)a0 * a2 + + (__int128)a1 * a1; + VERIFY_BITS(c, 114); + /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (__int128)a3 * a4; + VERIFY_BITS(d, 114); + /* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = c & M; c >>= 52; + VERIFY_BITS(r[2], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + c += d * R + t3;; + VERIFY_BITS(c, 100); + /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[3] = c & M; c >>= 52; + VERIFY_BITS(r[3], 52); + VERIFY_BITS(c, 48); + /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += t4; + VERIFY_BITS(c, 49); + /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = c; + VERIFY_BITS(r[4], 49); + /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} + +#endif diff --git a/src/secp256k1/src/field_gmp.h b/src/secp256k1/src/field_gmp.h new file mode 100644 index 0000000000..b390fd9de8 --- /dev/null +++ b/src/secp256k1/src/field_gmp.h @@ -0,0 +1,18 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_ +#define _SECP256K1_FIELD_REPR_ + +#include <gmp.h> + +#define FIELD_LIMBS ((256 + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS) + +typedef struct { + mp_limb_t n[FIELD_LIMBS+1]; +} secp256k1_fe_t; + +#endif diff --git a/src/secp256k1/src/field_gmp_impl.h b/src/secp256k1/src/field_gmp_impl.h new file mode 100644 index 0000000000..af4728e5b4 --- /dev/null +++ b/src/secp256k1/src/field_gmp_impl.h @@ -0,0 +1,163 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ +#define _SECP256K1_FIELD_REPR_IMPL_H_ + +#include <stdio.h> +#include <string.h> +#include "num.h" +#include "field.h" + +static mp_limb_t secp256k1_field_p[FIELD_LIMBS]; +static mp_limb_t secp256k1_field_pc[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS]; + +static void secp256k1_fe_inner_start(void) { + for (int i=0; i<(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; i++) + secp256k1_field_pc[i] = 0; + secp256k1_field_pc[0] += 0x3D1UL; + secp256k1_field_pc[32/GMP_NUMB_BITS] += (((mp_limb_t)1) << (32 % GMP_NUMB_BITS)); + for (int i=0; i<FIELD_LIMBS; i++) { + secp256k1_field_p[i] = 0; + } + mpn_sub(secp256k1_field_p, secp256k1_field_p, FIELD_LIMBS, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS); +} + +static void secp256k1_fe_inner_stop(void) { +} + +static void secp256k1_fe_normalize(secp256k1_fe_t *r) { + if (r->n[FIELD_LIMBS] != 0) { +#if (GMP_NUMB_BITS >= 40) + mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * r->n[FIELD_LIMBS]); + mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * carry); +#else + mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * r->n[FIELD_LIMBS]) + + mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), r->n[FIELD_LIMBS] << (32 % GMP_NUMB_BITS)); + mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * carry); + mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), carry << (32%GMP_NUMB_BITS)); +#endif + r->n[FIELD_LIMBS] = 0; + } + if (mpn_cmp(r->n, secp256k1_field_p, FIELD_LIMBS) >= 0) + mpn_sub(r->n, r->n, FIELD_LIMBS, secp256k1_field_p, FIELD_LIMBS); +} + +SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) { + r->n[0] = a; + for (int i=1; i<FIELD_LIMBS+1; i++) + r->n[i] = 0; +} + +SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe_t *r) { + for (int i=0; i<FIELD_LIMBS+1; i++) + r->n[i] = 0; +} + +SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe_t *a) { + int ret = 1; + for (int i=0; i<FIELD_LIMBS+1; i++) + ret &= (a->n[i] == 0); + return ret; +} + +SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe_t *a) { + return a->n[0] & 1; +} + +SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { + int ret = 1; + for (int i=0; i<FIELD_LIMBS+1; i++) + ret &= (a->n[i] == b->n[i]); + return ret; +} + +static void secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) { + for (int i=0; i<FIELD_LIMBS+1; i++) + r->n[i] = 0; + for (int i=0; i<256; i++) { + int limb = i/GMP_NUMB_BITS; + int shift = i%GMP_NUMB_BITS; + r->n[limb] |= (mp_limb_t)((a[31-i/8] >> (i%8)) & 0x1) << shift; + } +} + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) { + for (int i=0; i<32; i++) { + int c = 0; + for (int j=0; j<8; j++) { + int limb = (8*i+j)/GMP_NUMB_BITS; + int shift = (8*i+j)%GMP_NUMB_BITS; + c |= ((a->n[limb] >> shift) & 0x1) << j; + } + r[31-i] = c; + } +} + +SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) { + (void)m; + *r = *a; + secp256k1_fe_normalize(r); + for (int i=0; i<FIELD_LIMBS; i++) + r->n[i] = ~(r->n[i]); +#if (GMP_NUMB_BITS >= 33) + mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x1000003D0ULL); +#else + mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x3D0UL); + mpn_sub_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), 0x1UL << (32%GMP_NUMB_BITS)); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) { + mpn_mul_1(r->n, r->n, FIELD_LIMBS+1, a); +} + +SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) { + mpn_add(r->n, r->n, FIELD_LIMBS+1, a->n, FIELD_LIMBS+1); +} + +static void secp256k1_fe_reduce(secp256k1_fe_t *r, mp_limb_t *tmp) { + /** <A1 A2 A3 A4> <B1 B2 B3 B4> + * B1 B2 B3 B4 + * + C * A1 A2 A3 A4 + * + A1 A2 A3 A4 + */ + +#if (GMP_NUMB_BITS >= 33) + mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x1000003D1ULL); +#else + mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x3D1UL) + + mpn_addmul_1(tmp+(32/GMP_NUMB_BITS), tmp+FIELD_LIMBS, FIELD_LIMBS-(32/GMP_NUMB_BITS), 0x1UL << (32%GMP_NUMB_BITS)); +#endif + mp_limb_t q[1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS]; + q[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS] = mpn_mul_1(q, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS, o); +#if (GMP_NUMB_BITS <= 32) + mp_limb_t o2 = tmp[2*FIELD_LIMBS-(32/GMP_NUMB_BITS)] << (32%GMP_NUMB_BITS); + q[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS] += mpn_addmul_1(q, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS, o2); +#endif + r->n[FIELD_LIMBS] = mpn_add(r->n, tmp, FIELD_LIMBS, q, 1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS); +} + +static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) { + secp256k1_fe_t ac = *a; + secp256k1_fe_t bc = *b; + secp256k1_fe_normalize(&ac); + secp256k1_fe_normalize(&bc); + mp_limb_t tmp[2*FIELD_LIMBS]; + mpn_mul_n(tmp, ac.n, bc.n, FIELD_LIMBS); + secp256k1_fe_reduce(r, tmp); +} + +static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) { + secp256k1_fe_t ac = *a; + secp256k1_fe_normalize(&ac); + mp_limb_t tmp[2*FIELD_LIMBS]; + mpn_sqr(tmp, ac.n, FIELD_LIMBS); + secp256k1_fe_reduce(r, tmp); +} + +#endif diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h new file mode 100644 index 0000000000..3a31e1844e --- /dev/null +++ b/src/secp256k1/src/field_impl.h @@ -0,0 +1,293 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_IMPL_H_ +#define _SECP256K1_FIELD_IMPL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include "util.h" + +#if defined(USE_FIELD_GMP) +#include "field_gmp_impl.h" +#elif defined(USE_FIELD_10X26) +#include "field_10x26_impl.h" +#elif defined(USE_FIELD_5X52) +#include "field_5x52_impl.h" +#else +#error "Please select field implementation" +#endif + +static void secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a) { + if (*rlen < 65) { + *rlen = 65; + return; + } + *rlen = 65; + unsigned char tmp[32]; + secp256k1_fe_t b = *a; + secp256k1_fe_normalize(&b); + secp256k1_fe_get_b32(tmp, &b); + for (int i=0; i<32; i++) { + static const char *c = "0123456789ABCDEF"; + r[2*i] = c[(tmp[i] >> 4) & 0xF]; + r[2*i+1] = c[(tmp[i]) & 0xF]; + } + r[64] = 0x00; +} + +static void secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) { + unsigned char tmp[32] = {}; + static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0, + 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}; + for (int i=0; i<32; i++) { + if (alen > i*2) + tmp[32 - alen/2 + i] = (cvt[(unsigned char)a[2*i]] << 4) + cvt[(unsigned char)a[2*i+1]]; + } + secp256k1_fe_set_b32(r, tmp); +} + +static int secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) { + + /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in + * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: + * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] + */ + + secp256k1_fe_t x2; + secp256k1_fe_sqr(&x2, a); + secp256k1_fe_mul(&x2, &x2, a); + + secp256k1_fe_t x3; + secp256k1_fe_sqr(&x3, &x2); + secp256k1_fe_mul(&x3, &x3, a); + + secp256k1_fe_t x6 = x3; + for (int j=0; j<3; j++) secp256k1_fe_sqr(&x6, &x6); + secp256k1_fe_mul(&x6, &x6, &x3); + + secp256k1_fe_t x9 = x6; + for (int j=0; j<3; j++) secp256k1_fe_sqr(&x9, &x9); + secp256k1_fe_mul(&x9, &x9, &x3); + + secp256k1_fe_t x11 = x9; + for (int j=0; j<2; j++) secp256k1_fe_sqr(&x11, &x11); + secp256k1_fe_mul(&x11, &x11, &x2); + + secp256k1_fe_t x22 = x11; + for (int j=0; j<11; j++) secp256k1_fe_sqr(&x22, &x22); + secp256k1_fe_mul(&x22, &x22, &x11); + + secp256k1_fe_t x44 = x22; + for (int j=0; j<22; j++) secp256k1_fe_sqr(&x44, &x44); + secp256k1_fe_mul(&x44, &x44, &x22); + + secp256k1_fe_t x88 = x44; + for (int j=0; j<44; j++) secp256k1_fe_sqr(&x88, &x88); + secp256k1_fe_mul(&x88, &x88, &x44); + + secp256k1_fe_t x176 = x88; + for (int j=0; j<88; j++) secp256k1_fe_sqr(&x176, &x176); + secp256k1_fe_mul(&x176, &x176, &x88); + + secp256k1_fe_t x220 = x176; + for (int j=0; j<44; j++) secp256k1_fe_sqr(&x220, &x220); + secp256k1_fe_mul(&x220, &x220, &x44); + + secp256k1_fe_t x223 = x220; + for (int j=0; j<3; j++) secp256k1_fe_sqr(&x223, &x223); + secp256k1_fe_mul(&x223, &x223, &x3); + + /* The final result is then assembled using a sliding window over the blocks. */ + + secp256k1_fe_t t1 = x223; + for (int j=0; j<23; j++) secp256k1_fe_sqr(&t1, &t1); + secp256k1_fe_mul(&t1, &t1, &x22); + for (int j=0; j<6; j++) secp256k1_fe_sqr(&t1, &t1); + secp256k1_fe_mul(&t1, &t1, &x2); + secp256k1_fe_sqr(&t1, &t1); + secp256k1_fe_sqr(r, &t1); + + /* Check that a square root was actually calculated */ + + secp256k1_fe_sqr(&t1, r); + secp256k1_fe_negate(&t1, &t1, 1); + secp256k1_fe_add(&t1, a); + secp256k1_fe_normalize(&t1); + return secp256k1_fe_is_zero(&t1); +} + +static void secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) { + + /** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in + * { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: + * [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] + */ + + secp256k1_fe_t x2; + secp256k1_fe_sqr(&x2, a); + secp256k1_fe_mul(&x2, &x2, a); + + secp256k1_fe_t x3; + secp256k1_fe_sqr(&x3, &x2); + secp256k1_fe_mul(&x3, &x3, a); + + secp256k1_fe_t x6 = x3; + for (int j=0; j<3; j++) secp256k1_fe_sqr(&x6, &x6); + secp256k1_fe_mul(&x6, &x6, &x3); + + secp256k1_fe_t x9 = x6; + for (int j=0; j<3; j++) secp256k1_fe_sqr(&x9, &x9); + secp256k1_fe_mul(&x9, &x9, &x3); + + secp256k1_fe_t x11 = x9; + for (int j=0; j<2; j++) secp256k1_fe_sqr(&x11, &x11); + secp256k1_fe_mul(&x11, &x11, &x2); + + secp256k1_fe_t x22 = x11; + for (int j=0; j<11; j++) secp256k1_fe_sqr(&x22, &x22); + secp256k1_fe_mul(&x22, &x22, &x11); + + secp256k1_fe_t x44 = x22; + for (int j=0; j<22; j++) secp256k1_fe_sqr(&x44, &x44); + secp256k1_fe_mul(&x44, &x44, &x22); + + secp256k1_fe_t x88 = x44; + for (int j=0; j<44; j++) secp256k1_fe_sqr(&x88, &x88); + secp256k1_fe_mul(&x88, &x88, &x44); + + secp256k1_fe_t x176 = x88; + for (int j=0; j<88; j++) secp256k1_fe_sqr(&x176, &x176); + secp256k1_fe_mul(&x176, &x176, &x88); + + secp256k1_fe_t x220 = x176; + for (int j=0; j<44; j++) secp256k1_fe_sqr(&x220, &x220); + secp256k1_fe_mul(&x220, &x220, &x44); + + secp256k1_fe_t x223 = x220; + for (int j=0; j<3; j++) secp256k1_fe_sqr(&x223, &x223); + secp256k1_fe_mul(&x223, &x223, &x3); + + /* The final result is then assembled using a sliding window over the blocks. */ + + secp256k1_fe_t t1 = x223; + for (int j=0; j<23; j++) secp256k1_fe_sqr(&t1, &t1); + secp256k1_fe_mul(&t1, &t1, &x22); + for (int j=0; j<5; j++) secp256k1_fe_sqr(&t1, &t1); + secp256k1_fe_mul(&t1, &t1, a); + for (int j=0; j<3; j++) secp256k1_fe_sqr(&t1, &t1); + secp256k1_fe_mul(&t1, &t1, &x2); + for (int j=0; j<2; j++) secp256k1_fe_sqr(&t1, &t1); + secp256k1_fe_mul(r, &t1, a); +} + +static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) { +#if defined(USE_FIELD_INV_BUILTIN) + secp256k1_fe_inv(r, a); +#elif defined(USE_FIELD_INV_NUM) + unsigned char b[32]; + secp256k1_fe_t c = *a; + secp256k1_fe_normalize(&c); + secp256k1_fe_get_b32(b, &c); + secp256k1_num_t n; + secp256k1_num_set_bin(&n, b, 32); + secp256k1_num_mod_inverse(&n, &n, &secp256k1_fe_consts->p); + secp256k1_num_get_bin(b, 32, &n); + secp256k1_fe_set_b32(r, b); +#else +#error "Please select field inverse implementation" +#endif +} + +static void secp256k1_fe_inv_all(size_t len, secp256k1_fe_t r[len], const secp256k1_fe_t a[len]) { + if (len < 1) + return; + + VERIFY_CHECK((r + len <= a) || (a + len <= r)); + + r[0] = a[0]; + + size_t i = 0; + while (++i < len) { + secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]); + } + + secp256k1_fe_t u; secp256k1_fe_inv(&u, &r[--i]); + + while (i > 0) { + int j = i--; + secp256k1_fe_mul(&r[j], &r[i], &u); + secp256k1_fe_mul(&u, &u, &a[j]); + } + + r[0] = u; +} + +static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t r[len], const secp256k1_fe_t a[len]) { + if (len < 1) + return; + + VERIFY_CHECK((r + len <= a) || (a + len <= r)); + + r[0] = a[0]; + + size_t i = 0; + while (++i < len) { + secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]); + } + + secp256k1_fe_t u; secp256k1_fe_inv_var(&u, &r[--i]); + + while (i > 0) { + int j = i--; + secp256k1_fe_mul(&r[j], &r[i], &u); + secp256k1_fe_mul(&u, &u, &a[j]); + } + + r[0] = u; +} + +static void secp256k1_fe_start(void) { + static const unsigned char secp256k1_fe_consts_p[] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F + }; + if (secp256k1_fe_consts == NULL) { + secp256k1_fe_inner_start(); + secp256k1_fe_consts_t *ret = (secp256k1_fe_consts_t*)malloc(sizeof(secp256k1_fe_consts_t)); + secp256k1_num_set_bin(&ret->p, secp256k1_fe_consts_p, sizeof(secp256k1_fe_consts_p)); + secp256k1_fe_consts = ret; + } +} + +static void secp256k1_fe_stop(void) { + if (secp256k1_fe_consts != NULL) { + secp256k1_fe_consts_t *c = (secp256k1_fe_consts_t*)secp256k1_fe_consts; + free((void*)c); + secp256k1_fe_consts = NULL; + secp256k1_fe_inner_stop(); + } +} + +#endif diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h new file mode 100644 index 0000000000..ba02549821 --- /dev/null +++ b/src/secp256k1/src/group.h @@ -0,0 +1,128 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_GROUP_ +#define _SECP256K1_GROUP_ + +#include "num.h" +#include "field.h" + +/** A group element of the secp256k1 curve, in affine coordinates. */ +typedef struct { + secp256k1_fe_t x; + secp256k1_fe_t y; + int infinity; /* whether this represents the point at infinity */ +} secp256k1_ge_t; + +/** A group element of the secp256k1 curve, in jacobian coordinates. */ +typedef struct { + secp256k1_fe_t x; /* actual X: x/z^2 */ + secp256k1_fe_t y; /* actual Y: y/z^3 */ + secp256k1_fe_t z; + int infinity; /* whether this represents the point at infinity */ +} secp256k1_gej_t; + +/** Global constants related to the group */ +typedef struct { + secp256k1_num_t order; /* the order of the curve (= order of its generator) */ + secp256k1_num_t half_order; /* half the order of the curve (= order of its generator) */ + secp256k1_ge_t g; /* the generator point */ + +#ifdef USE_ENDOMORPHISM + /* constants related to secp256k1's efficiently computable endomorphism */ + secp256k1_fe_t beta; + secp256k1_num_t lambda, a1b2, b1, a2; +#endif +} secp256k1_ge_consts_t; + +static const secp256k1_ge_consts_t *secp256k1_ge_consts = NULL; + +/** Initialize the group module. */ +static void secp256k1_ge_start(void); + +/** De-initialize the group module. */ +static void secp256k1_ge_stop(void); + +/** Set a group element equal to the point at infinity */ +static void secp256k1_ge_set_infinity(secp256k1_ge_t *r); + +/** Set a group element equal to the point with given X and Y coordinates */ +static void secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y); + +/** Set a group element (affine) equal to the point with the given X coordinate, and given oddness + * for Y. Return value indicates whether the result is valid. */ +static int secp256k1_ge_set_xo(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd); + +/** Check whether a group element is the point at infinity. */ +static int secp256k1_ge_is_infinity(const secp256k1_ge_t *a); + +/** Check whether a group element is valid (i.e., on the curve). */ +static int secp256k1_ge_is_valid(const secp256k1_ge_t *a); + +static void secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a); + +/** Get a hex representation of a point. *rlen will be overwritten with the real length. */ +static void secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a); + +/** Set a group element equal to another which is given in jacobian coordinates */ +static void secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a); + +/** Set a batch of group elements equal to the inputs given in jacobian coordinates */ +static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t r[len], const secp256k1_gej_t a[len]); + + +/** Set a group element (jacobian) equal to the point at infinity. */ +static void secp256k1_gej_set_infinity(secp256k1_gej_t *r); + +/** Set a group element (jacobian) equal to the point with given X and Y coordinates. */ +static void secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y); + +/** Set a group element (jacobian) equal to another which is given in affine coordinates. */ +static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a); + +/** Get the X coordinate of a group element (jacobian). */ +static void secp256k1_gej_get_x_var(secp256k1_fe_t *r, const secp256k1_gej_t *a); + +/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ +static void secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a); + +/** Check whether a group element is the point at infinity. */ +static int secp256k1_gej_is_infinity(const secp256k1_gej_t *a); + +/** Set r equal to the double of a. */ +static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *a); + +/** Set r equal to the sum of a and b. */ +static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b); + +/** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ +static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b); + +/** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient + than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time + guarantee, and b is allowed to be infinity. */ +static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b); + +/** Get a hex representation of a point. *rlen will be overwritten with the real length. */ +static void secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a); + +#ifdef USE_ENDOMORPHISM +/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ +static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a); + +/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (given that a is + not more than 256 bits). */ +static void secp256k1_gej_split_exp_var(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a); +#endif + +/** Clear a secp256k1_gej_t to prevent leaking sensitive information. */ +static void secp256k1_gej_clear(secp256k1_gej_t *r); + +/** Clear a secp256k1_ge_t to prevent leaking sensitive information. */ +static void secp256k1_ge_clear(secp256k1_ge_t *r); + + +#endif diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h new file mode 100644 index 0000000000..1edbc6e099 --- /dev/null +++ b/src/secp256k1/src/group_impl.h @@ -0,0 +1,519 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_GROUP_IMPL_H_ +#define _SECP256K1_GROUP_IMPL_H_ + +#include <string.h> + +#include "num.h" +#include "field.h" +#include "group.h" + +static void secp256k1_ge_set_infinity(secp256k1_ge_t *r) { + r->infinity = 1; +} + +static void secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y) { + r->infinity = 0; + r->x = *x; + r->y = *y; +} + +static int secp256k1_ge_is_infinity(const secp256k1_ge_t *a) { + return a->infinity; +} + +static void secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a) { + r->infinity = a->infinity; + r->x = a->x; + r->y = a->y; + secp256k1_fe_normalize(&r->y); + secp256k1_fe_negate(&r->y, &r->y, 1); +} + +static void secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a) { + char cx[65]; int lx=65; + char cy[65]; int ly=65; + secp256k1_fe_get_hex(cx, &lx, &a->x); + secp256k1_fe_get_hex(cy, &ly, &a->y); + lx = strlen(cx); + ly = strlen(cy); + int len = lx + ly + 3 + 1; + if (*rlen < len) { + *rlen = len; + return; + } + *rlen = len; + r[0] = '('; + memcpy(r+1, cx, lx); + r[1+lx] = ','; + memcpy(r+2+lx, cy, ly); + r[2+lx+ly] = ')'; + r[3+lx+ly] = 0; +} + +static void secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a) { + r->infinity = a->infinity; + secp256k1_fe_inv(&a->z, &a->z); + secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z); + secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &a->z, &z2); + secp256k1_fe_mul(&a->x, &a->x, &z2); + secp256k1_fe_mul(&a->y, &a->y, &z3); + secp256k1_fe_set_int(&a->z, 1); + r->x = a->x; + r->y = a->y; +} + +static void secp256k1_ge_set_gej_var(secp256k1_ge_t *r, secp256k1_gej_t *a) { + r->infinity = a->infinity; + if (a->infinity) { + return; + } + secp256k1_fe_inv_var(&a->z, &a->z); + secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z); + secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &a->z, &z2); + secp256k1_fe_mul(&a->x, &a->x, &z2); + secp256k1_fe_mul(&a->y, &a->y, &z3); + secp256k1_fe_set_int(&a->z, 1); + r->x = a->x; + r->y = a->y; +} + +static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge_t r[len], const secp256k1_gej_t a[len]) { + size_t count = 0; + secp256k1_fe_t az[len]; + for (size_t i=0; i<len; i++) { + if (!a[i].infinity) { + az[count++] = a[i].z; + } + } + + secp256k1_fe_t azi[count]; + secp256k1_fe_inv_all_var(count, azi, az); + + count = 0; + for (size_t i=0; i<len; i++) { + r[i].infinity = a[i].infinity; + if (!a[i].infinity) { + secp256k1_fe_t *zi = &azi[count++]; + secp256k1_fe_t zi2; secp256k1_fe_sqr(&zi2, zi); + secp256k1_fe_t zi3; secp256k1_fe_mul(&zi3, &zi2, zi); + secp256k1_fe_mul(&r[i].x, &a[i].x, &zi2); + secp256k1_fe_mul(&r[i].y, &a[i].y, &zi3); + } + } +} + +static void secp256k1_gej_set_infinity(secp256k1_gej_t *r) { + r->infinity = 1; + secp256k1_fe_set_int(&r->x, 0); + secp256k1_fe_set_int(&r->y, 0); + secp256k1_fe_set_int(&r->z, 0); +} + +static void secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y) { + r->infinity = 0; + r->x = *x; + r->y = *y; + secp256k1_fe_set_int(&r->z, 1); +} + +static void secp256k1_gej_clear(secp256k1_gej_t *r) { + r->infinity = 0; + secp256k1_fe_clear(&r->x); + secp256k1_fe_clear(&r->y); + secp256k1_fe_clear(&r->z); +} + +static void secp256k1_ge_clear(secp256k1_ge_t *r) { + r->infinity = 0; + secp256k1_fe_clear(&r->x); + secp256k1_fe_clear(&r->y); +} + +static int secp256k1_ge_set_xo(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd) { + r->x = *x; + secp256k1_fe_t x2; secp256k1_fe_sqr(&x2, x); + secp256k1_fe_t x3; secp256k1_fe_mul(&x3, x, &x2); + r->infinity = 0; + secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7); + secp256k1_fe_add(&c, &x3); + if (!secp256k1_fe_sqrt(&r->y, &c)) + return 0; + secp256k1_fe_normalize(&r->y); + if (secp256k1_fe_is_odd(&r->y) != odd) + secp256k1_fe_negate(&r->y, &r->y, 1); + return 1; +} + +static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a) { + r->infinity = a->infinity; + r->x = a->x; + r->y = a->y; + secp256k1_fe_set_int(&r->z, 1); +} + +static void secp256k1_gej_get_x_var(secp256k1_fe_t *r, const secp256k1_gej_t *a) { + secp256k1_fe_t zi2; secp256k1_fe_inv_var(&zi2, &a->z); secp256k1_fe_sqr(&zi2, &zi2); + secp256k1_fe_mul(r, &a->x, &zi2); +} + +static void secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a) { + r->infinity = a->infinity; + r->x = a->x; + r->y = a->y; + r->z = a->z; + secp256k1_fe_normalize(&r->y); + secp256k1_fe_negate(&r->y, &r->y, 1); +} + +static int secp256k1_gej_is_infinity(const secp256k1_gej_t *a) { + return a->infinity; +} + +static int secp256k1_gej_is_valid(const secp256k1_gej_t *a) { + if (a->infinity) + return 0; + /** y^2 = x^3 + 7 + * (Y/Z^3)^2 = (X/Z^2)^3 + 7 + * Y^2 / Z^6 = X^3 / Z^6 + 7 + * Y^2 = X^3 + 7*Z^6 + */ + secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &a->y); + secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); + secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z); + secp256k1_fe_t z6; secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); + secp256k1_fe_mul_int(&z6, 7); + secp256k1_fe_add(&x3, &z6); + secp256k1_fe_normalize(&y2); + secp256k1_fe_normalize(&x3); + return secp256k1_fe_equal(&y2, &x3); +} + +static int secp256k1_ge_is_valid(const secp256k1_ge_t *a) { + if (a->infinity) + return 0; + /* y^2 = x^3 + 7 */ + secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &a->y); + secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); + secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7); + secp256k1_fe_add(&x3, &c); + secp256k1_fe_normalize(&y2); + secp256k1_fe_normalize(&x3); + return secp256k1_fe_equal(&y2, &x3); +} + +static void secp256k1_gej_double_var(secp256k1_gej_t *r, const secp256k1_gej_t *a) { + if (a->infinity) { + r->infinity = 1; + return; + } + + secp256k1_fe_t t5 = a->y; + secp256k1_fe_normalize(&t5); + if (secp256k1_fe_is_zero(&t5)) { + r->infinity = 1; + return; + } + + secp256k1_fe_t t1,t2,t3,t4; + secp256k1_fe_mul(&r->z, &t5, &a->z); + secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */ + secp256k1_fe_sqr(&t1, &a->x); + secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */ + secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */ + secp256k1_fe_sqr(&t3, &t5); + secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */ + secp256k1_fe_sqr(&t4, &t3); + secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */ + secp256k1_fe_mul(&t3, &a->x, &t3); /* T3 = 2*X*Y^2 (1) */ + r->x = t3; + secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */ + secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */ + secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */ + secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */ + secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */ + secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */ + secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ + secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ + secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ + r->infinity = 0; +} + +static void secp256k1_gej_add_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b) { + if (a->infinity) { + *r = *b; + return; + } + if (b->infinity) { + *r = *a; + return; + } + r->infinity = 0; + secp256k1_fe_t z22; secp256k1_fe_sqr(&z22, &b->z); + secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &a->z); + secp256k1_fe_t u1; secp256k1_fe_mul(&u1, &a->x, &z22); + secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12); + secp256k1_fe_t s1; secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); + secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); + secp256k1_fe_normalize(&u1); + secp256k1_fe_normalize(&u2); + if (secp256k1_fe_equal(&u1, &u2)) { + secp256k1_fe_normalize(&s1); + secp256k1_fe_normalize(&s2); + if (secp256k1_fe_equal(&s1, &s2)) { + secp256k1_gej_double_var(r, a); + } else { + r->infinity = 1; + } + return; + } + secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); + secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); + secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i); + secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h); + secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2); + secp256k1_fe_mul(&r->z, &a->z, &b->z); secp256k1_fe_mul(&r->z, &r->z, &h); + secp256k1_fe_t t; secp256k1_fe_mul(&t, &u1, &h2); + r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); + secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); + secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); + secp256k1_fe_add(&r->y, &h3); +} + +static void secp256k1_gej_add_ge_var(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) { + if (a->infinity) { + r->infinity = b->infinity; + r->x = b->x; + r->y = b->y; + secp256k1_fe_set_int(&r->z, 1); + return; + } + if (b->infinity) { + *r = *a; + return; + } + r->infinity = 0; + secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &a->z); + secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize(&u1); + secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12); + secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize(&s1); + secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); + secp256k1_fe_normalize(&u1); + secp256k1_fe_normalize(&u2); + if (secp256k1_fe_equal(&u1, &u2)) { + secp256k1_fe_normalize(&s1); + secp256k1_fe_normalize(&s2); + if (secp256k1_fe_equal(&s1, &s2)) { + secp256k1_gej_double_var(r, a); + } else { + r->infinity = 1; + } + return; + } + secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); + secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); + secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i); + secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h); + secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2); + r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); + secp256k1_fe_t t; secp256k1_fe_mul(&t, &u1, &h2); + r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); + secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); + secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); + secp256k1_fe_add(&r->y, &h3); +} + +static void secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) { + VERIFY_CHECK(!b->infinity); + VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); + + /** In: + * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. + * In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. + * we find as solution for a unified addition/doubling formula: + * lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation. + * x3 = lambda^2 - (x1 + x2) + * 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2). + * + * Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives: + * U1 = X1*Z2^2, U2 = X2*Z1^2 + * S1 = X1*Z2^3, S2 = X2*Z2^3 + * Z = Z1*Z2 + * T = U1+U2 + * M = S1+S2 + * Q = T*M^2 + * R = T^2-U1*U2 + * X3 = 4*(R^2-Q) + * Y3 = 4*(R*(3*Q-2*R^2)-M^4) + * Z3 = 2*M*Z + * (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.) + */ + + secp256k1_fe_t zz; secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ + secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize(&u1); /* u1 = U1 = X1*Z2^2 (1) */ + secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ + secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ + secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z2^2 (1) */ + secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ + secp256k1_fe_t z = a->z; /* z = Z = Z1*Z2 (8) */ + secp256k1_fe_t t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ + secp256k1_fe_t m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ + secp256k1_fe_t n; secp256k1_fe_sqr(&n, &m); /* n = M^2 (1) */ + secp256k1_fe_t q; secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*M^2 (1) */ + secp256k1_fe_sqr(&n, &n); /* n = M^4 (1) */ + secp256k1_fe_t rr; secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ + secp256k1_fe_mul(&t, &u1, &u2); secp256k1_fe_negate(&t, &t, 1); /* t = -U1*U2 (2) */ + secp256k1_fe_add(&rr, &t); /* rr = R = T^2-U1*U2 (3) */ + secp256k1_fe_sqr(&t, &rr); /* t = R^2 (1) */ + secp256k1_fe_mul(&r->z, &m, &z); /* r->z = M*Z (1) */ + secp256k1_fe_normalize(&r->z); + int infinity = secp256k1_fe_is_zero(&r->z) * (1 - a->infinity); + secp256k1_fe_mul_int(&r->z, 2 * (1 - a->infinity)); /* r->z = Z3 = 2*M*Z (2) */ + r->x = t; /* r->x = R^2 (1) */ + secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */ + secp256k1_fe_add(&r->x, &q); /* r->x = R^2-Q (3) */ + secp256k1_fe_normalize(&r->x); + secp256k1_fe_mul_int(&q, 3); /* q = -3*Q (6) */ + secp256k1_fe_mul_int(&t, 2); /* t = 2*R^2 (2) */ + secp256k1_fe_add(&t, &q); /* t = 2*R^2-3*Q (8) */ + secp256k1_fe_mul(&t, &t, &rr); /* t = R*(2*R^2-3*Q) (1) */ + secp256k1_fe_add(&t, &n); /* t = R*(2*R^2-3*Q)+M^4 (2) */ + secp256k1_fe_negate(&r->y, &t, 2); /* r->y = R*(3*Q-2*R^2)-M^4 (3) */ + secp256k1_fe_normalize(&r->y); + secp256k1_fe_mul_int(&r->x, 4 * (1 - a->infinity)); /* r->x = X3 = 4*(R^2-Q) */ + secp256k1_fe_mul_int(&r->y, 4 * (1 - a->infinity)); /* r->y = Y3 = 4*R*(3*Q-2*R^2)-4*M^4 (4) */ + + /** In case a->infinity == 1, the above code results in r->x, r->y, and r->z all equal to 0. + * Add b->x to x, b->y to y, and 1 to z in that case. + */ + t = b->x; secp256k1_fe_mul_int(&t, a->infinity); + secp256k1_fe_add(&r->x, &t); + t = b->y; secp256k1_fe_mul_int(&t, a->infinity); + secp256k1_fe_add(&r->y, &t); + secp256k1_fe_set_int(&t, a->infinity); + secp256k1_fe_add(&r->z, &t); + r->infinity = infinity; +} + + + +static void secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a) { + secp256k1_gej_t c = *a; + secp256k1_ge_t t; secp256k1_ge_set_gej(&t, &c); + secp256k1_ge_get_hex(r, rlen, &t); +} + +#ifdef USE_ENDOMORPHISM +static void secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a) { + const secp256k1_fe_t *beta = &secp256k1_ge_consts->beta; + *r = *a; + secp256k1_fe_mul(&r->x, &r->x, beta); +} + +static void secp256k1_gej_split_exp_var(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a) { + const secp256k1_ge_consts_t *c = secp256k1_ge_consts; + secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2; + + secp256k1_num_copy(&bnn2, &c->order); + secp256k1_num_shift(&bnn2, 1); + + secp256k1_num_mul(&bnc1, a, &c->a1b2); + secp256k1_num_add(&bnc1, &bnc1, &bnn2); + secp256k1_num_div(&bnc1, &bnc1, &c->order); + + secp256k1_num_mul(&bnc2, a, &c->b1); + secp256k1_num_add(&bnc2, &bnc2, &bnn2); + secp256k1_num_div(&bnc2, &bnc2, &c->order); + + secp256k1_num_mul(&bnt1, &bnc1, &c->a1b2); + secp256k1_num_mul(&bnt2, &bnc2, &c->a2); + secp256k1_num_add(&bnt1, &bnt1, &bnt2); + secp256k1_num_sub(r1, a, &bnt1); + secp256k1_num_mul(&bnt1, &bnc1, &c->b1); + secp256k1_num_mul(&bnt2, &bnc2, &c->a1b2); + secp256k1_num_sub(r2, &bnt1, &bnt2); +} +#endif + + +static void secp256k1_ge_start(void) { + static const unsigned char secp256k1_ge_consts_order[] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, + 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, + 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 + }; + static const unsigned char secp256k1_ge_consts_g_x[] = { + 0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC, + 0x55,0xA0,0x62,0x95,0xCE,0x87,0x0B,0x07, + 0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9, + 0x59,0xF2,0x81,0x5B,0x16,0xF8,0x17,0x98 + }; + static const unsigned char secp256k1_ge_consts_g_y[] = { + 0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65, + 0x5D,0xA4,0xFB,0xFC,0x0E,0x11,0x08,0xA8, + 0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19, + 0x9C,0x47,0xD0,0x8F,0xFB,0x10,0xD4,0xB8 + }; +#ifdef USE_ENDOMORPHISM + /* properties of secp256k1's efficiently computable endomorphism */ + static const unsigned char secp256k1_ge_consts_lambda[] = { + 0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0, + 0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, + 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78, + 0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72 + }; + static const unsigned char secp256k1_ge_consts_beta[] = { + 0x7a,0xe9,0x6a,0x2b,0x65,0x7c,0x07,0x10, + 0x6e,0x64,0x47,0x9e,0xac,0x34,0x34,0xe9, + 0x9c,0xf0,0x49,0x75,0x12,0xf5,0x89,0x95, + 0xc1,0x39,0x6c,0x28,0x71,0x95,0x01,0xee + }; + static const unsigned char secp256k1_ge_consts_a1b2[] = { + 0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd, + 0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15 + }; + static const unsigned char secp256k1_ge_consts_b1[] = { + 0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28, + 0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3 + }; + static const unsigned char secp256k1_ge_consts_a2[] = { + 0x01, + 0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6, + 0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8 + }; +#endif + if (secp256k1_ge_consts == NULL) { + secp256k1_ge_consts_t *ret = (secp256k1_ge_consts_t*)malloc(sizeof(secp256k1_ge_consts_t)); + secp256k1_num_set_bin(&ret->order, secp256k1_ge_consts_order, sizeof(secp256k1_ge_consts_order)); + secp256k1_num_copy(&ret->half_order, &ret->order); + secp256k1_num_shift(&ret->half_order, 1); +#ifdef USE_ENDOMORPHISM + secp256k1_num_set_bin(&ret->lambda, secp256k1_ge_consts_lambda, sizeof(secp256k1_ge_consts_lambda)); + secp256k1_num_set_bin(&ret->a1b2, secp256k1_ge_consts_a1b2, sizeof(secp256k1_ge_consts_a1b2)); + secp256k1_num_set_bin(&ret->a2, secp256k1_ge_consts_a2, sizeof(secp256k1_ge_consts_a2)); + secp256k1_num_set_bin(&ret->b1, secp256k1_ge_consts_b1, sizeof(secp256k1_ge_consts_b1)); + secp256k1_fe_set_b32(&ret->beta, secp256k1_ge_consts_beta); +#endif + secp256k1_fe_t g_x, g_y; + secp256k1_fe_set_b32(&g_x, secp256k1_ge_consts_g_x); + secp256k1_fe_set_b32(&g_y, secp256k1_ge_consts_g_y); + secp256k1_ge_set_xy(&ret->g, &g_x, &g_y); + secp256k1_ge_consts = ret; + } +} + +static void secp256k1_ge_stop(void) { + if (secp256k1_ge_consts != NULL) { + secp256k1_ge_consts_t *c = (secp256k1_ge_consts_t*)secp256k1_ge_consts; + free((void*)c); + secp256k1_ge_consts = NULL; + } +} + +#endif diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java new file mode 100644 index 0000000000..90a498eaa2 --- /dev/null +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java @@ -0,0 +1,60 @@ +package org.bitcoin; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import com.google.common.base.Preconditions; + + +/** + * This class holds native methods to handle ECDSA verification. + * You can find an example library that can be used for this at + * https://github.com/sipa/secp256k1 + */ +public class NativeSecp256k1 { + public static final boolean enabled; + static { + boolean isEnabled = true; + try { + System.loadLibrary("javasecp256k1"); + } catch (UnsatisfiedLinkError e) { + isEnabled = false; + } + enabled = isEnabled; + } + + private static ThreadLocal<ByteBuffer> nativeECDSABuffer = new ThreadLocal<ByteBuffer>(); + /** + * Verifies the given secp256k1 signature in native code. + * Calling when enabled == false is undefined (probably library not loaded) + * + * @param data The data which was signed, must be exactly 32 bytes + * @param signature The signature + * @param pub The public key which did the signing + */ + public static boolean verify(byte[] data, byte[] signature, byte[] pub) { + Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null) { + byteBuff = ByteBuffer.allocateDirect(32 + 8 + 520 + 520); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(data); + byteBuff.putInt(signature.length); + byteBuff.putInt(pub.length); + byteBuff.put(signature); + byteBuff.put(pub); + return secp256k1_ecdsa_verify(byteBuff) == 1; + } + + /** + * @param byteBuff signature format is byte[32] data, + * native-endian int signatureLength, native-endian int pubkeyLength, + * byte[signatureLength] signature, byte[pubkeyLength] pub + * @returns 1 for valid signature, anything else for invalid + */ + private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff); +} diff --git a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c new file mode 100644 index 0000000000..bb4cd70728 --- /dev/null +++ b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c @@ -0,0 +1,23 @@ +#include "org_bitcoin_NativeSecp256k1.h" +#include "include/secp256k1.h" + +JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify + (JNIEnv* env, jclass classObject, jobject byteBufferObject) +{ + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + int sigLen = *((int*)(data + 32)); + int pubLen = *((int*)(data + 32 + 4)); + + return secp256k1_ecdsa_verify(data, 32, data+32+8, sigLen, data+32+8+sigLen, pubLen); +} + +static void __javasecp256k1_attach(void) __attribute__((constructor)); +static void __javasecp256k1_detach(void) __attribute__((destructor)); + +static void __javasecp256k1_attach(void) { + secp256k1_start(SECP256K1_START_VERIFY); +} + +static void __javasecp256k1_detach(void) { + secp256k1_stop(); +} diff --git a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h new file mode 100644 index 0000000000..d7fb004fa8 --- /dev/null +++ b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class org_bitcoin_NativeSecp256k1 */ + +#ifndef _Included_org_bitcoin_NativeSecp256k1 +#define _Included_org_bitcoin_NativeSecp256k1 +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdsa_verify + * Signature: (Ljava/nio/ByteBuffer;)I + */ +JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify + (JNIEnv *, jclass, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/secp256k1/src/num.h b/src/secp256k1/src/num.h new file mode 100644 index 0000000000..c86f847858 --- /dev/null +++ b/src/secp256k1/src/num.h @@ -0,0 +1,100 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_ +#define _SECP256K1_NUM_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(USE_NUM_GMP) +#include "num_gmp.h" +#else +#error "Please select num implementation" +#endif + +/** Clear a number to prevent the leak of sensitive data. */ +static void secp256k1_num_clear(secp256k1_num_t *r); + +/** Copy a number. */ +static void secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a); + +/** Convert a number's absolute value to a binary big-endian string. + * There must be enough place. */ +static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a); + +/** Set a number to the value of a binary big-endian string. */ +static void secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen); + +/** Set a number equal to a (signed) integer. */ +static void secp256k1_num_set_int(secp256k1_num_t *r, int a); + +/** Compute a modular inverse. The input must be less than the modulus. */ +static void secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m); + +/** Multiply two numbers modulo another. */ +static void secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m); + +/** Compare the absolute value of two numbers. */ +static int secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b); + +/** Test whether two number are equal (including sign). */ +static int secp256k1_num_eq(const secp256k1_num_t *a, const secp256k1_num_t *b); + +/** Add two (signed) numbers. */ +static void secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); + +/** Subtract two (signed) numbers. */ +static void secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); + +/** Multiply two (signed) numbers. */ +static void secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); + +/** Divide two (signed) numbers. */ +static void secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b); + +/** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1, + even if r was negative. */ +static void secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m); + +/** Calculate the number of bits in (the absolute value of) a number. */ +static int secp256k1_num_bits(const secp256k1_num_t *a); + +/** Right-shift the passed number by bits bits, and return those bits. */ +static int secp256k1_num_shift(secp256k1_num_t *r, int bits); + +/** Check whether a number is zero. */ +static int secp256k1_num_is_zero(const secp256k1_num_t *a); + +/** Check whether a number is odd. */ +static int secp256k1_num_is_odd(const secp256k1_num_t *a); + +/** Check whether a number is strictly negative. */ +static int secp256k1_num_is_neg(const secp256k1_num_t *a); + +/** Check whether a particular bit is set in a number. */ +static int secp256k1_num_get_bit(const secp256k1_num_t *a, int pos); + +/** Increase a number by 1. */ +static void secp256k1_num_inc(secp256k1_num_t *r); + +/** Set a number equal to the value of a hex string (unsigned). */ +static void secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen); + +/** Convert (the absolute value of) a number to a hexadecimal string. */ +static void secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a); + +/** Split a number into a low and high part. */ +static void secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits); + +/** Change a number's sign. */ +static void secp256k1_num_negate(secp256k1_num_t *r); + +/** Get a bunch of bits from a number. */ +static int secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count); + +#endif diff --git a/src/secp256k1/src/num_gmp.h b/src/secp256k1/src/num_gmp.h new file mode 100644 index 0000000000..baa1f2bf2e --- /dev/null +++ b/src/secp256k1/src/num_gmp.h @@ -0,0 +1,20 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_REPR_ +#define _SECP256K1_NUM_REPR_ + +#include <gmp.h> + +#define NUM_LIMBS ((256+GMP_NUMB_BITS-1)/GMP_NUMB_BITS) + +typedef struct { + mp_limb_t data[2*NUM_LIMBS]; + int neg; + int limbs; +} secp256k1_num_t; + +#endif diff --git a/src/secp256k1/src/num_gmp_impl.h b/src/secp256k1/src/num_gmp_impl.h new file mode 100644 index 0000000000..e45a59e0cd --- /dev/null +++ b/src/secp256k1/src/num_gmp_impl.h @@ -0,0 +1,376 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_REPR_IMPL_H_ +#define _SECP256K1_NUM_REPR_IMPL_H_ + +#include <string.h> +#include <stdlib.h> +#include <gmp.h> + +#include "util.h" +#include "num.h" + +#ifdef VERIFY +static void secp256k1_num_sanity(const secp256k1_num_t *a) { + VERIFY_CHECK(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0)); +} +#else +#define secp256k1_num_sanity(a) do { } while(0) +#endif + +static void secp256k1_num_init(secp256k1_num_t *r) { + r->neg = 0; + r->limbs = 1; + r->data[0] = 0; +} + +static void secp256k1_num_clear(secp256k1_num_t *r) { + memset(r, 0, sizeof(*r)); +} + +static void secp256k1_num_free(secp256k1_num_t *r) { + (void)r; +} + +static void secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) { + *r = *a; +} + +static int secp256k1_num_bits(const secp256k1_num_t *a) { + int ret=(a->limbs-1)*GMP_NUMB_BITS; + mp_limb_t x=a->data[a->limbs-1]; + while (x) { + x >>= 1; + ret++; + } + return ret; +} + + +static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) { + unsigned char tmp[65]; + int len = 0; + if (a->limbs>1 || a->data[0] != 0) { + len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs); + } + int shift = 0; + while (shift < len && tmp[shift] == 0) shift++; + VERIFY_CHECK(len-shift <= (int)rlen); + memset(r, 0, rlen - len + shift); + if (len > shift) { + memcpy(r + rlen - len + shift, tmp + shift, len - shift); + } + memset(tmp, 0, sizeof(tmp)); +} + +static void secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) { + VERIFY_CHECK(alen > 0); + VERIFY_CHECK(alen <= 64); + int len = mpn_set_str(r->data, a, alen, 256); + VERIFY_CHECK(len <= NUM_LIMBS*2); + r->limbs = len; + r->neg = 0; + while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; +} + +static void secp256k1_num_set_int(secp256k1_num_t *r, int a) { + r->limbs = 1; + r->neg = (a < 0); + r->data[0] = (a < 0) ? -a : a; +} + +static void secp256k1_num_add_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { + mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs); + r->limbs = a->limbs; + if (c != 0) { + VERIFY_CHECK(r->limbs < 2*NUM_LIMBS); + r->data[r->limbs++] = c; + } +} + +static void secp256k1_num_sub_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { + mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs); + VERIFY_CHECK(c == 0); + r->limbs = a->limbs; + while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; +} + +static void secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) { + secp256k1_num_sanity(r); + secp256k1_num_sanity(m); + + if (r->limbs >= m->limbs) { + mp_limb_t t[2*NUM_LIMBS]; + mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs); + memset(t, 0, sizeof(t)); + r->limbs = m->limbs; + while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; + } + + if (r->neg && (r->limbs > 1 || r->data[0] != 0)) { + secp256k1_num_sub_abs(r, m, r); + r->neg = 0; + } +} + +static void secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) { + secp256k1_num_sanity(a); + secp256k1_num_sanity(m); + + /** mpn_gcdext computes: (G,S) = gcdext(U,V), where + * * G = gcd(U,V) + * * G = U*S + V*T + * * U has equal or more limbs than V, and V has no padding + * If we set U to be (a padded version of) a, and V = m: + * G = a*S + m*T + * G = a*S mod m + * Assuming G=1: + * S = 1/a mod m + */ + VERIFY_CHECK(m->limbs <= NUM_LIMBS); + VERIFY_CHECK(m->data[m->limbs-1] != 0); + mp_limb_t g[NUM_LIMBS+1]; + mp_limb_t u[NUM_LIMBS+1]; + mp_limb_t v[NUM_LIMBS+1]; + for (int i=0; i < m->limbs; i++) { + u[i] = (i < a->limbs) ? a->data[i] : 0; + v[i] = m->data[i]; + } + mp_size_t sn = NUM_LIMBS+1; + mp_size_t gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs); + VERIFY_CHECK(gn == 1); + VERIFY_CHECK(g[0] == 1); + r->neg = a->neg ^ m->neg; + if (sn < 0) { + mpn_sub(r->data, m->data, m->limbs, r->data, -sn); + r->limbs = m->limbs; + while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--; + } else { + r->limbs = sn; + } + memset(g, 0, sizeof(g)); + memset(u, 0, sizeof(u)); + memset(v, 0, sizeof(v)); +} + +static int secp256k1_num_is_zero(const secp256k1_num_t *a) { + return (a->limbs == 1 && a->data[0] == 0); +} + +static int secp256k1_num_is_odd(const secp256k1_num_t *a) { + return a->data[0] & 1; +} + +static int secp256k1_num_is_neg(const secp256k1_num_t *a) { + return (a->limbs > 1 || a->data[0] != 0) && a->neg; +} + +static int secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) { + if (a->limbs > b->limbs) return 1; + if (a->limbs < b->limbs) return -1; + return mpn_cmp(a->data, b->data, a->limbs); +} + +static int secp256k1_num_eq(const secp256k1_num_t *a, const secp256k1_num_t *b) { + if (a->limbs > b->limbs) return 0; + if (a->limbs < b->limbs) return 0; + if ((a->neg && !secp256k1_num_is_zero(a)) != (b->neg && !secp256k1_num_is_zero(b))) return 0; + return mpn_cmp(a->data, b->data, a->limbs) == 0; +} + +static void secp256k1_num_subadd(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, int bneg) { + if (!(b->neg ^ bneg ^ a->neg)) { /* a and b have the same sign */ + r->neg = a->neg; + if (a->limbs >= b->limbs) { + secp256k1_num_add_abs(r, a, b); + } else { + secp256k1_num_add_abs(r, b, a); + } + } else { + if (secp256k1_num_cmp(a, b) > 0) { + r->neg = a->neg; + secp256k1_num_sub_abs(r, a, b); + } else { + r->neg = b->neg ^ bneg; + secp256k1_num_sub_abs(r, b, a); + } + } +} + +static void secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + secp256k1_num_subadd(r, a, b, 0); +} + +static void secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + secp256k1_num_subadd(r, a, b, 1); +} + +static void secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + + mp_limb_t tmp[2*NUM_LIMBS+1]; + VERIFY_CHECK(a->limbs + b->limbs <= 2*NUM_LIMBS+1); + if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) { + r->limbs = 1; + r->neg = 0; + r->data[0] = 0; + return; + } + if (a->limbs >= b->limbs) + mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs); + else + mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs); + r->limbs = a->limbs + b->limbs; + if (r->limbs > 1 && tmp[r->limbs - 1]==0) r->limbs--; + VERIFY_CHECK(r->limbs <= 2*NUM_LIMBS); + mpn_copyi(r->data, tmp, r->limbs); + r->neg = a->neg ^ b->neg; + memset(tmp, 0, sizeof(tmp)); +} + +static void secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) { + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + if (b->limbs > a->limbs) { + r->limbs = 1; + r->data[0] = 0; + r->neg = 0; + return; + } + + mp_limb_t quo[2*NUM_LIMBS+1]; + mp_limb_t rem[2*NUM_LIMBS+1]; + mpn_tdiv_qr(quo, rem, 0, a->data, a->limbs, b->data, b->limbs); + mpn_copyi(r->data, quo, a->limbs - b->limbs + 1); + r->limbs = a->limbs - b->limbs + 1; + while (r->limbs > 1 && r->data[r->limbs - 1]==0) r->limbs--; + r->neg = a->neg ^ b->neg; +} + +static void secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) { + secp256k1_num_mul(r, a, b); + secp256k1_num_mod(r, m); +} + + +static int secp256k1_num_shift(secp256k1_num_t *r, int bits) { + VERIFY_CHECK(bits <= GMP_NUMB_BITS); + mp_limb_t ret = mpn_rshift(r->data, r->data, r->limbs, bits); + if (r->limbs>1 && r->data[r->limbs-1]==0) r->limbs--; + ret >>= (GMP_NUMB_BITS - bits); + return ret; +} + +static int secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) { + return (a->limbs*GMP_NUMB_BITS > pos) && ((a->data[pos/GMP_NUMB_BITS] >> (pos % GMP_NUMB_BITS)) & 1); +} + +static void secp256k1_num_inc(secp256k1_num_t *r) { + mp_limb_t ret = mpn_add_1(r->data, r->data, r->limbs, (mp_limb_t)1); + if (ret) { + VERIFY_CHECK(r->limbs < 2*NUM_LIMBS); + r->data[r->limbs++] = ret; + } +} + +static void secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) { + static const unsigned char cvt[256] = { + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0, + 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0, + 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0 + }; + unsigned char num[257] = {}; + for (int i=0; i<alen; i++) { + num[i] = cvt[(unsigned char)a[i]]; + } + r->limbs = mpn_set_str(r->data, num, alen, 16); + r->neg = 0; + while (r->limbs > 1 && r->data[r->limbs-1] == 0) r->limbs--; +} + +static void secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) { + static const unsigned char cvt[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + unsigned char *tmp = malloc(257); + mp_size_t len = mpn_get_str(tmp, 16, (mp_limb_t*)a->data, a->limbs); + VERIFY_CHECK(len <= rlen); + for (int i=0; i<len; i++) { + VERIFY_CHECK(rlen-len+i >= 0); + VERIFY_CHECK(rlen-len+i < rlen); + VERIFY_CHECK(tmp[i] < 16); + r[rlen-len+i] = cvt[tmp[i]]; + } + for (int i=0; i<rlen-len; i++) { + VERIFY_CHECK(i >= 0); + VERIFY_CHECK(i < rlen); + r[i] = cvt[0]; + } + free(tmp); +} + +static void secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) { + VERIFY_CHECK(bits > 0); + rh->neg = a->neg; + if (bits >= a->limbs * GMP_NUMB_BITS) { + *rl = *a; + rh->limbs = 1; + rh->data[0] = 0; + return; + } + rl->limbs = 0; + rl->neg = a->neg; + int left = bits; + while (left >= GMP_NUMB_BITS) { + rl->data[rl->limbs] = a->data[rl->limbs]; + rl->limbs++; + left -= GMP_NUMB_BITS; + } + if (left == 0) { + mpn_copyi(rh->data, a->data + rl->limbs, a->limbs - rl->limbs); + rh->limbs = a->limbs - rl->limbs; + } else { + mpn_rshift(rh->data, a->data + rl->limbs, a->limbs - rl->limbs, left); + rh->limbs = a->limbs - rl->limbs; + while (rh->limbs>1 && rh->data[rh->limbs-1]==0) rh->limbs--; + } + if (left > 0) { + rl->data[rl->limbs] = a->data[rl->limbs] & ((((mp_limb_t)1) << left) - 1); + rl->limbs++; + } + while (rl->limbs>1 && rl->data[rl->limbs-1]==0) rl->limbs--; +} + +static void secp256k1_num_negate(secp256k1_num_t *r) { + r->neg ^= 1; +} + +static int secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count) { + int ret = 0; + for (int i = 0; i < count; i++) { + ret |= ((a->data[(offset + i) / GMP_NUMB_BITS] >> ((offset + i) % GMP_NUMB_BITS)) & 1) << i; + } + return ret; +} + +#endif diff --git a/src/secp256k1/src/num_impl.h b/src/secp256k1/src/num_impl.h new file mode 100644 index 0000000000..f73d3ceea8 --- /dev/null +++ b/src/secp256k1/src/num_impl.h @@ -0,0 +1,22 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_IMPL_H_ +#define _SECP256K1_NUM_IMPL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include "num.h" + +#if defined(USE_NUM_GMP) +#include "num_gmp_impl.h" +#else +#error "Please select num implementation" +#endif + +#endif diff --git a/src/secp256k1/src/scalar.h b/src/secp256k1/src/scalar.h new file mode 100644 index 0000000000..3baacb3721 --- /dev/null +++ b/src/secp256k1/src/scalar.h @@ -0,0 +1,63 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_ +#define _SECP256K1_SCALAR_ + +#include "num.h" + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(USE_SCALAR_4X64) +#include "scalar_4x64.h" +#elif defined(USE_SCALAR_8X32) +#include "scalar_8x32.h" +#else +#error "Please select scalar implementation" +#endif + +/** Clear a scalar to prevent the leak of sensitive data. */ +static void secp256k1_scalar_clear(secp256k1_scalar_t *r); + +/** Access bits from a scalar. */ +static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count); + +/** Set a scalar from a big endian byte array. */ +static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *bin, int *overflow); + +/** Convert a scalar to a byte array. */ +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar_t* a); + +/** Add two scalars together (modulo the group order). */ +static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b); + +/** Multiply two scalars (modulo the group order). */ +static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b); + +/** Compute the square of a scalar (modulo the group order). */ +static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t *a); + +/** Compute the inverse of a scalar (modulo the group order). */ +static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *a); + +/** Compute the complement of a scalar (modulo the group order). */ +static void secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scalar_t *a); + +/** Check whether a scalar equals zero. */ +static int secp256k1_scalar_is_zero(const secp256k1_scalar_t *a); + +/** Check whether a scalar equals one. */ +static int secp256k1_scalar_is_one(const secp256k1_scalar_t *a); + +/** Check whether a scalar is higher than the group order divided by 2. */ +static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a); + +/** Convert a scalar to a number. */ +static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a); + +#endif diff --git a/src/secp256k1/src/scalar_4x64.h b/src/secp256k1/src/scalar_4x64.h new file mode 100644 index 0000000000..5a751c6862 --- /dev/null +++ b/src/secp256k1/src/scalar_4x64.h @@ -0,0 +1,17 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_ +#define _SECP256K1_SCALAR_REPR_ + +#include <stdint.h> + +/** A scalar modulo the group order of the secp256k1 curve. */ +typedef struct { + uint64_t d[4]; +} secp256k1_scalar_t; + +#endif diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h new file mode 100644 index 0000000000..f78718234f --- /dev/null +++ b/src/secp256k1/src/scalar_4x64_impl.h @@ -0,0 +1,359 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ +#define _SECP256K1_SCALAR_REPR_IMPL_H_ + +typedef unsigned __int128 uint128_t; + +/* Limbs of the secp256k1 order. */ +#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) +#define SECP256K1_N_1 ((uint64_t)0xBAAEDCE6AF48A03BULL) +#define SECP256K1_N_2 ((uint64_t)0xFFFFFFFFFFFFFFFEULL) +#define SECP256K1_N_3 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) + +/* Limbs of 2^256 minus the secp256k1 order. */ +#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) +#define SECP256K1_N_C_1 (~SECP256K1_N_1) +#define SECP256K1_N_C_2 (1) + +/* Limbs of half the secp256k1 order. */ +#define SECP256K1_N_H_0 ((uint64_t)0xDFE92F46681B20A0ULL) +#define SECP256K1_N_H_1 ((uint64_t)0x5D576E7357A4501DULL) +#define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) +#define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL) + +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar_t *r) { + r->d[0] = 0; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; +} + +SECP256K1_INLINE static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count) { + VERIFY_CHECK((offset + count - 1) / 64 == offset / 64); + return (a->d[offset / 64] >> (offset % 64)) & ((((uint64_t)1) << count) - 1); +} + +SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar_t *a) { + int yes = 0; + int no = 0; + no |= (a->d[3] < SECP256K1_N_3); /* No need for a > check. */ + no |= (a->d[2] < SECP256K1_N_2); + yes |= (a->d[2] > SECP256K1_N_2) & ~no; + no |= (a->d[1] < SECP256K1_N_1); + yes |= (a->d[1] > SECP256K1_N_1) & ~no; + yes |= (a->d[0] >= SECP256K1_N_0) & ~no; + return yes; +} + +SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar_t *r, unsigned int overflow) { + VERIFY_CHECK(overflow <= 1); + uint128_t t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0; + r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[1] + overflow * SECP256K1_N_C_1; + r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[2] + overflow * SECP256K1_N_C_2; + r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint64_t)r->d[3]; + r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; + return overflow; +} + +static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) { + uint128_t t = (uint128_t)a->d[0] + b->d[0]; + r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)a->d[1] + b->d[1]; + r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)a->d[2] + b->d[2]; + r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)a->d[3] + b->d[3]; + r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + secp256k1_scalar_reduce(r, t + secp256k1_scalar_check_overflow(r)); +} + +static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *b32, int *overflow) { + r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56; + r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56; + r->d[2] = (uint64_t)b32[15] | (uint64_t)b32[14] << 8 | (uint64_t)b32[13] << 16 | (uint64_t)b32[12] << 24 | (uint64_t)b32[11] << 32 | (uint64_t)b32[10] << 40 | (uint64_t)b32[9] << 48 | (uint64_t)b32[8] << 56; + r->d[3] = (uint64_t)b32[7] | (uint64_t)b32[6] << 8 | (uint64_t)b32[5] << 16 | (uint64_t)b32[4] << 24 | (uint64_t)b32[3] << 32 | (uint64_t)b32[2] << 40 | (uint64_t)b32[1] << 48 | (uint64_t)b32[0] << 56; + int over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); + if (overflow) { + *overflow = over; + } +} + +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar_t* a) { + bin[0] = a->d[3] >> 56; bin[1] = a->d[3] >> 48; bin[2] = a->d[3] >> 40; bin[3] = a->d[3] >> 32; bin[4] = a->d[3] >> 24; bin[5] = a->d[3] >> 16; bin[6] = a->d[3] >> 8; bin[7] = a->d[3]; + bin[8] = a->d[2] >> 56; bin[9] = a->d[2] >> 48; bin[10] = a->d[2] >> 40; bin[11] = a->d[2] >> 32; bin[12] = a->d[2] >> 24; bin[13] = a->d[2] >> 16; bin[14] = a->d[2] >> 8; bin[15] = a->d[2]; + bin[16] = a->d[1] >> 56; bin[17] = a->d[1] >> 48; bin[18] = a->d[1] >> 40; bin[19] = a->d[1] >> 32; bin[20] = a->d[1] >> 24; bin[21] = a->d[1] >> 16; bin[22] = a->d[1] >> 8; bin[23] = a->d[1]; + bin[24] = a->d[0] >> 56; bin[25] = a->d[0] >> 48; bin[26] = a->d[0] >> 40; bin[27] = a->d[0] >> 32; bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar_t *a) { + return (a->d[0] | a->d[1] | a->d[2] | a->d[3]) == 0; +} + +static void secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) { + uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (secp256k1_scalar_is_zero(a) == 0); + uint128_t t = (uint128_t)(~a->d[0]) + SECP256K1_N_0 + 1; + r->d[0] = t & nonzero; t >>= 64; + t += (uint128_t)(~a->d[1]) + SECP256K1_N_1; + r->d[1] = t & nonzero; t >>= 64; + t += (uint128_t)(~a->d[2]) + SECP256K1_N_2; + r->d[2] = t & nonzero; t >>= 64; + t += (uint128_t)(~a->d[3]) + SECP256K1_N_3; + r->d[3] = t & nonzero; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar_t *a) { + return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3]) == 0; +} + +static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) { + int yes = 0; + int no = 0; + no |= (a->d[3] < SECP256K1_N_H_3); + yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; + no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; /* No need for a > check. */ + no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; + yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; + yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; + return yes; +} + +/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ + +/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd(a,b) { \ + uint64_t tl, th; \ + { \ + uint128_t t = (uint128_t)a * b; \ + th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ + c1 += th; /* overflow is handled on the next line */ \ + c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ +} + +/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ +#define muladd_fast(a,b) { \ + uint64_t tl, th; \ + { \ + uint128_t t = (uint128_t)a * b; \ + th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ + c1 += th; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK(c1 >= th); \ +} + +/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd2(a,b) { \ + uint64_t tl, th; \ + { \ + uint128_t t = (uint128_t)a * b; \ + th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = t; \ + } \ + uint64_t th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \ + c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ + uint64_t tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \ + th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ + c0 += tl2; /* overflow is handled on the next line */ \ + th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \ + c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ + c1 += th2; /* overflow is handled on the next line */ \ + c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ +} + +/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define sumadd(a) { \ + c0 += (a); /* overflow is handled on the next line */ \ + unsigned int over = (c0 < (a)) ? 1 : 0; \ + c1 += over; /* overflow is handled on the next line */ \ + c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \ +} + +/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ +#define sumadd_fast(a) { \ + c0 += (a); /* overflow is handled on the next line */ \ + c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ + VERIFY_CHECK(c2 == 0); \ +} + +/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. */ +#define extract(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = c2; \ + c2 = 0; \ +} + +/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. c2 is required to be zero. */ +#define extract_fast(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = 0; \ + VERIFY_CHECK(c2 == 0); \ +} + +static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint64_t *l) { + uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7]; + + /* 160 bit accumulator. */ + uint64_t c0, c1; + uint32_t c2; + + /* Reduce 512 bits into 385. */ + /* m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C. */ + c0 = l[0]; c1 = 0; c2 = 0; + muladd_fast(n0, SECP256K1_N_C_0); + uint64_t m0; extract_fast(m0); + sumadd_fast(l[1]); + muladd(n1, SECP256K1_N_C_0); + muladd(n0, SECP256K1_N_C_1); + uint64_t m1; extract(m1); + sumadd(l[2]); + muladd(n2, SECP256K1_N_C_0); + muladd(n1, SECP256K1_N_C_1); + sumadd(n0); + uint64_t m2; extract(m2); + sumadd(l[3]); + muladd(n3, SECP256K1_N_C_0); + muladd(n2, SECP256K1_N_C_1); + sumadd(n1); + uint64_t m3; extract(m3); + muladd(n3, SECP256K1_N_C_1); + sumadd(n2); + uint64_t m4; extract(m4); + sumadd_fast(n3); + uint64_t m5; extract_fast(m5); + VERIFY_CHECK(c0 <= 1); + uint32_t m6 = c0; + + /* Reduce 385 bits into 258. */ + /* p[0..4] = m[0..3] + m[4..6] * SECP256K1_N_C. */ + c0 = m0; c1 = 0; c2 = 0; + muladd_fast(m4, SECP256K1_N_C_0); + uint64_t p0; extract_fast(p0); + sumadd_fast(m1); + muladd(m5, SECP256K1_N_C_0); + muladd(m4, SECP256K1_N_C_1); + uint64_t p1; extract(p1); + sumadd(m2); + muladd(m6, SECP256K1_N_C_0); + muladd(m5, SECP256K1_N_C_1); + sumadd(m4); + uint64_t p2; extract(p2); + sumadd_fast(m3); + muladd_fast(m6, SECP256K1_N_C_1); + sumadd_fast(m5); + uint64_t p3; extract_fast(p3); + uint32_t p4 = c0 + m6; + VERIFY_CHECK(p4 <= 2); + + /* Reduce 258 bits into 256. */ + /* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */ + uint128_t c = p0 + (uint128_t)SECP256K1_N_C_0 * p4; + r->d[0] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; + c += p1 + (uint128_t)SECP256K1_N_C_1 * p4; + r->d[1] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; + c += p2 + (uint128_t)p4; + r->d[2] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; + c += p3; + r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; + + /* Final reduction of r. */ + secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); +} + +static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) { + /* 160 bit accumulator. */ + uint64_t c0 = 0, c1 = 0; + uint32_t c2 = 0; + + uint64_t l[8]; + + /* l[0..7] = a[0..3] * b[0..3]. */ + muladd_fast(a->d[0], b->d[0]); + extract_fast(l[0]); + muladd(a->d[0], b->d[1]); + muladd(a->d[1], b->d[0]); + extract(l[1]); + muladd(a->d[0], b->d[2]); + muladd(a->d[1], b->d[1]); + muladd(a->d[2], b->d[0]); + extract(l[2]); + muladd(a->d[0], b->d[3]); + muladd(a->d[1], b->d[2]); + muladd(a->d[2], b->d[1]); + muladd(a->d[3], b->d[0]); + extract(l[3]); + muladd(a->d[1], b->d[3]); + muladd(a->d[2], b->d[2]); + muladd(a->d[3], b->d[1]); + extract(l[4]); + muladd(a->d[2], b->d[3]); + muladd(a->d[3], b->d[2]); + extract(l[5]); + muladd_fast(a->d[3], b->d[3]); + extract_fast(l[6]); + VERIFY_CHECK(c1 <= 0); + l[7] = c0; + + secp256k1_scalar_reduce_512(r, l); +} + +static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) { + /* 160 bit accumulator. */ + uint64_t c0 = 0, c1 = 0; + uint32_t c2 = 0; + + uint64_t l[8]; + + /* l[0..7] = a[0..3] * b[0..3]. */ + muladd_fast(a->d[0], a->d[0]); + extract_fast(l[0]); + muladd2(a->d[0], a->d[1]); + extract(l[1]); + muladd2(a->d[0], a->d[2]); + muladd(a->d[1], a->d[1]); + extract(l[2]); + muladd2(a->d[0], a->d[3]); + muladd2(a->d[1], a->d[2]); + extract(l[3]); + muladd2(a->d[1], a->d[3]); + muladd(a->d[2], a->d[2]); + extract(l[4]); + muladd2(a->d[2], a->d[3]); + extract(l[5]); + muladd_fast(a->d[3], a->d[3]); + extract_fast(l[6]); + VERIFY_CHECK(c1 == 0); + l[7] = c0; + + secp256k1_scalar_reduce_512(r, l); +} + +#undef sumadd +#undef sumadd_fast +#undef muladd +#undef muladd_fast +#undef muladd2 +#undef extract +#undef extract_fast + +#endif diff --git a/src/secp256k1/src/scalar_8x32.h b/src/secp256k1/src/scalar_8x32.h new file mode 100644 index 0000000000..f70328cfc9 --- /dev/null +++ b/src/secp256k1/src/scalar_8x32.h @@ -0,0 +1,17 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_ +#define _SECP256K1_SCALAR_REPR_ + +#include <stdint.h> + +/** A scalar modulo the group order of the secp256k1 curve. */ +typedef struct { + uint32_t d[8]; +} secp256k1_scalar_t; + +#endif diff --git a/src/secp256k1/src/scalar_8x32_impl.h b/src/secp256k1/src/scalar_8x32_impl.h new file mode 100644 index 0000000000..e58be1365f --- /dev/null +++ b/src/secp256k1/src/scalar_8x32_impl.h @@ -0,0 +1,572 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ +#define _SECP256K1_SCALAR_REPR_IMPL_H_ + +/* Limbs of the secp256k1 order. */ +#define SECP256K1_N_0 ((uint32_t)0xD0364141UL) +#define SECP256K1_N_1 ((uint32_t)0xBFD25E8CUL) +#define SECP256K1_N_2 ((uint32_t)0xAF48A03BUL) +#define SECP256K1_N_3 ((uint32_t)0xBAAEDCE6UL) +#define SECP256K1_N_4 ((uint32_t)0xFFFFFFFEUL) +#define SECP256K1_N_5 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_6 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_7 ((uint32_t)0xFFFFFFFFUL) + +/* Limbs of 2^256 minus the secp256k1 order. */ +#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) +#define SECP256K1_N_C_1 (~SECP256K1_N_1) +#define SECP256K1_N_C_2 (~SECP256K1_N_2) +#define SECP256K1_N_C_3 (~SECP256K1_N_3) +#define SECP256K1_N_C_4 (1) + +/* Limbs of half the secp256k1 order. */ +#define SECP256K1_N_H_0 ((uint32_t)0x681B20A0UL) +#define SECP256K1_N_H_1 ((uint32_t)0xDFE92F46UL) +#define SECP256K1_N_H_2 ((uint32_t)0x57A4501DUL) +#define SECP256K1_N_H_3 ((uint32_t)0x5D576E73UL) +#define SECP256K1_N_H_4 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_H_5 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL) + +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar_t *r) { + r->d[0] = 0; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; + r->d[4] = 0; + r->d[5] = 0; + r->d[6] = 0; + r->d[7] = 0; +} + +SECP256K1_INLINE static int secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count) { + VERIFY_CHECK((offset + count - 1) / 32 == offset / 32); + return (a->d[offset / 32] >> (offset % 32)) & ((1 << count) - 1); +} + +SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar_t *a) { + int yes = 0; + int no = 0; + no |= (a->d[7] < SECP256K1_N_7); /* No need for a > check. */ + no |= (a->d[6] < SECP256K1_N_6); /* No need for a > check. */ + no |= (a->d[5] < SECP256K1_N_5); /* No need for a > check. */ + no |= (a->d[4] < SECP256K1_N_4); + yes |= (a->d[4] > SECP256K1_N_4) & ~no; + no |= (a->d[3] < SECP256K1_N_3) & ~yes; + yes |= (a->d[3] > SECP256K1_N_3) & ~no; + no |= (a->d[2] < SECP256K1_N_2) & ~yes; + yes |= (a->d[2] > SECP256K1_N_2) & ~no; + no |= (a->d[1] < SECP256K1_N_1) & ~yes; + yes |= (a->d[1] > SECP256K1_N_1) & ~no; + yes |= (a->d[0] >= SECP256K1_N_0) & ~no; + return yes; +} + +SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar_t *r, uint32_t overflow) { + VERIFY_CHECK(overflow <= 1); + uint64_t t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0; + r->d[0] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[1] + overflow * SECP256K1_N_C_1; + r->d[1] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[2] + overflow * SECP256K1_N_C_2; + r->d[2] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[3] + overflow * SECP256K1_N_C_3; + r->d[3] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[4] + overflow * SECP256K1_N_C_4; + r->d[4] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[5]; + r->d[5] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[6]; + r->d[6] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[7]; + r->d[7] = t & 0xFFFFFFFFUL; + return overflow; +} + +static void secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) { + uint64_t t = (uint64_t)a->d[0] + b->d[0]; + r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[1] + b->d[1]; + r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[2] + b->d[2]; + r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[3] + b->d[3]; + r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[4] + b->d[4]; + r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[5] + b->d[5]; + r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[6] + b->d[6]; + r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[7] + b->d[7]; + r->d[7] = t & 0xFFFFFFFFULL; t >>= 32; + secp256k1_scalar_reduce(r, t + secp256k1_scalar_check_overflow(r)); +} + +static void secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *b32, int *overflow) { + r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24; + r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24; + r->d[2] = (uint32_t)b32[23] | (uint32_t)b32[22] << 8 | (uint32_t)b32[21] << 16 | (uint32_t)b32[20] << 24; + r->d[3] = (uint32_t)b32[19] | (uint32_t)b32[18] << 8 | (uint32_t)b32[17] << 16 | (uint32_t)b32[16] << 24; + r->d[4] = (uint32_t)b32[15] | (uint32_t)b32[14] << 8 | (uint32_t)b32[13] << 16 | (uint32_t)b32[12] << 24; + r->d[5] = (uint32_t)b32[11] | (uint32_t)b32[10] << 8 | (uint32_t)b32[9] << 16 | (uint32_t)b32[8] << 24; + r->d[6] = (uint32_t)b32[7] | (uint32_t)b32[6] << 8 | (uint32_t)b32[5] << 16 | (uint32_t)b32[4] << 24; + r->d[7] = (uint32_t)b32[3] | (uint32_t)b32[2] << 8 | (uint32_t)b32[1] << 16 | (uint32_t)b32[0] << 24; + int over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); + if (overflow) { + *overflow = over; + } +} + +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar_t* a) { + bin[0] = a->d[7] >> 24; bin[1] = a->d[7] >> 16; bin[2] = a->d[7] >> 8; bin[3] = a->d[7]; + bin[4] = a->d[6] >> 24; bin[5] = a->d[6] >> 16; bin[6] = a->d[6] >> 8; bin[7] = a->d[6]; + bin[8] = a->d[5] >> 24; bin[9] = a->d[5] >> 16; bin[10] = a->d[5] >> 8; bin[11] = a->d[5]; + bin[12] = a->d[4] >> 24; bin[13] = a->d[4] >> 16; bin[14] = a->d[4] >> 8; bin[15] = a->d[4]; + bin[16] = a->d[3] >> 24; bin[17] = a->d[3] >> 16; bin[18] = a->d[3] >> 8; bin[19] = a->d[3]; + bin[20] = a->d[2] >> 24; bin[21] = a->d[2] >> 16; bin[22] = a->d[2] >> 8; bin[23] = a->d[2]; + bin[24] = a->d[1] >> 24; bin[25] = a->d[1] >> 16; bin[26] = a->d[1] >> 8; bin[27] = a->d[1]; + bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar_t *a) { + return (a->d[0] | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; +} + +static void secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) { + uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(a) == 0); + uint64_t t = (uint64_t)(~a->d[0]) + SECP256K1_N_0 + 1; + r->d[0] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[1]) + SECP256K1_N_1; + r->d[1] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[2]) + SECP256K1_N_2; + r->d[2] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[3]) + SECP256K1_N_3; + r->d[3] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[4]) + SECP256K1_N_4; + r->d[4] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[5]) + SECP256K1_N_5; + r->d[5] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[6]) + SECP256K1_N_6; + r->d[6] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[7]) + SECP256K1_N_7; + r->d[7] = t & nonzero; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar_t *a) { + return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; +} + +static int secp256k1_scalar_is_high(const secp256k1_scalar_t *a) { + int yes = 0; + int no = 0; + no |= (a->d[7] < SECP256K1_N_H_7); + yes |= (a->d[7] > SECP256K1_N_H_7) & ~no; + no |= (a->d[6] < SECP256K1_N_H_6) & ~yes; /* No need for a > check. */ + no |= (a->d[5] < SECP256K1_N_H_5) & ~yes; /* No need for a > check. */ + no |= (a->d[4] < SECP256K1_N_H_4) & ~yes; /* No need for a > check. */ + no |= (a->d[3] < SECP256K1_N_H_3) & ~yes; + yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; + no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; + yes |= (a->d[2] > SECP256K1_N_H_2) & ~no; + no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; + yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; + yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; + return yes; +} + +/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ + +/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd(a,b) { \ + uint32_t tl, th; \ + { \ + uint64_t t = (uint64_t)a * b; \ + th = t >> 32; /* at most 0xFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ + c1 += th; /* overflow is handled on the next line */ \ + c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ +} + +/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ +#define muladd_fast(a,b) { \ + uint32_t tl, th; \ + { \ + uint64_t t = (uint64_t)a * b; \ + th = t >> 32; /* at most 0xFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ + c1 += th; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK(c1 >= th); \ +} + +/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd2(a,b) { \ + uint32_t tl, th; \ + { \ + uint64_t t = (uint64_t)a * b; \ + th = t >> 32; /* at most 0xFFFFFFFE */ \ + tl = t; \ + } \ + uint32_t th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \ + c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ + uint32_t tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \ + th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ + c0 += tl2; /* overflow is handled on the next line */ \ + th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \ + c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ + c1 += th2; /* overflow is handled on the next line */ \ + c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ +} + +/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define sumadd(a) { \ + c0 += (a); /* overflow is handled on the next line */ \ + unsigned int over = (c0 < (a)) ? 1 : 0; \ + c1 += over; /* overflow is handled on the next line */ \ + c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \ +} + +/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ +#define sumadd_fast(a) { \ + c0 += (a); /* overflow is handled on the next line */ \ + c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ + VERIFY_CHECK(c2 == 0); \ +} + +/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. */ +#define extract(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = c2; \ + c2 = 0; \ +} + +/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. c2 is required to be zero. */ +#define extract_fast(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = 0; \ + VERIFY_CHECK(c2 == 0); \ +} + +static void secp256k1_scalar_reduce_512(secp256k1_scalar_t *r, const uint32_t *l) { + uint32_t n0 = l[8], n1 = l[9], n2 = l[10], n3 = l[11], n4 = l[12], n5 = l[13], n6 = l[14], n7 = l[15]; + + /* 96 bit accumulator. */ + uint32_t c0, c1, c2; + + /* Reduce 512 bits into 385. */ + /* m[0..12] = l[0..7] + n[0..7] * SECP256K1_N_C. */ + c0 = l[0]; c1 = 0; c2 = 0; + muladd_fast(n0, SECP256K1_N_C_0); + uint32_t m0; extract_fast(m0); + sumadd_fast(l[1]); + muladd(n1, SECP256K1_N_C_0); + muladd(n0, SECP256K1_N_C_1); + uint32_t m1; extract(m1); + sumadd(l[2]); + muladd(n2, SECP256K1_N_C_0); + muladd(n1, SECP256K1_N_C_1); + muladd(n0, SECP256K1_N_C_2); + uint32_t m2; extract(m2); + sumadd(l[3]); + muladd(n3, SECP256K1_N_C_0); + muladd(n2, SECP256K1_N_C_1); + muladd(n1, SECP256K1_N_C_2); + muladd(n0, SECP256K1_N_C_3); + uint32_t m3; extract(m3); + sumadd(l[4]); + muladd(n4, SECP256K1_N_C_0); + muladd(n3, SECP256K1_N_C_1); + muladd(n2, SECP256K1_N_C_2); + muladd(n1, SECP256K1_N_C_3); + sumadd(n0); + uint32_t m4; extract(m4); + sumadd(l[5]); + muladd(n5, SECP256K1_N_C_0); + muladd(n4, SECP256K1_N_C_1); + muladd(n3, SECP256K1_N_C_2); + muladd(n2, SECP256K1_N_C_3); + sumadd(n1); + uint32_t m5; extract(m5); + sumadd(l[6]); + muladd(n6, SECP256K1_N_C_0); + muladd(n5, SECP256K1_N_C_1); + muladd(n4, SECP256K1_N_C_2); + muladd(n3, SECP256K1_N_C_3); + sumadd(n2); + uint32_t m6; extract(m6); + sumadd(l[7]); + muladd(n7, SECP256K1_N_C_0); + muladd(n6, SECP256K1_N_C_1); + muladd(n5, SECP256K1_N_C_2); + muladd(n4, SECP256K1_N_C_3); + sumadd(n3); + uint32_t m7; extract(m7); + muladd(n7, SECP256K1_N_C_1); + muladd(n6, SECP256K1_N_C_2); + muladd(n5, SECP256K1_N_C_3); + sumadd(n4); + uint32_t m8; extract(m8); + muladd(n7, SECP256K1_N_C_2); + muladd(n6, SECP256K1_N_C_3); + sumadd(n5); + uint32_t m9; extract(m9); + muladd(n7, SECP256K1_N_C_3); + sumadd(n6); + uint32_t m10; extract(m10); + sumadd_fast(n7); + uint32_t m11; extract_fast(m11); + VERIFY_CHECK(c0 <= 1); + uint32_t m12 = c0; + + /* Reduce 385 bits into 258. */ + /* p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C. */ + c0 = m0; c1 = 0; c2 = 0; + muladd_fast(m8, SECP256K1_N_C_0); + uint32_t p0; extract_fast(p0); + sumadd_fast(m1); + muladd(m9, SECP256K1_N_C_0); + muladd(m8, SECP256K1_N_C_1); + uint32_t p1; extract(p1); + sumadd(m2); + muladd(m10, SECP256K1_N_C_0); + muladd(m9, SECP256K1_N_C_1); + muladd(m8, SECP256K1_N_C_2); + uint32_t p2; extract(p2); + sumadd(m3); + muladd(m11, SECP256K1_N_C_0); + muladd(m10, SECP256K1_N_C_1); + muladd(m9, SECP256K1_N_C_2); + muladd(m8, SECP256K1_N_C_3); + uint32_t p3; extract(p3); + sumadd(m4); + muladd(m12, SECP256K1_N_C_0); + muladd(m11, SECP256K1_N_C_1); + muladd(m10, SECP256K1_N_C_2); + muladd(m9, SECP256K1_N_C_3); + sumadd(m8); + uint32_t p4; extract(p4); + sumadd(m5); + muladd(m12, SECP256K1_N_C_1); + muladd(m11, SECP256K1_N_C_2); + muladd(m10, SECP256K1_N_C_3); + sumadd(m9); + uint32_t p5; extract(p5); + sumadd(m6); + muladd(m12, SECP256K1_N_C_2); + muladd(m11, SECP256K1_N_C_3); + sumadd(m10); + uint32_t p6; extract(p6); + sumadd_fast(m7); + muladd_fast(m12, SECP256K1_N_C_3); + sumadd_fast(m11); + uint32_t p7; extract_fast(p7); + uint32_t p8 = c0 + m12; + VERIFY_CHECK(p8 <= 2); + + /* Reduce 258 bits into 256. */ + /* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */ + uint64_t c = p0 + (uint64_t)SECP256K1_N_C_0 * p8; + r->d[0] = c & 0xFFFFFFFFUL; c >>= 32; + c += p1 + (uint64_t)SECP256K1_N_C_1 * p8; + r->d[1] = c & 0xFFFFFFFFUL; c >>= 32; + c += p2 + (uint64_t)SECP256K1_N_C_2 * p8; + r->d[2] = c & 0xFFFFFFFFUL; c >>= 32; + c += p3 + (uint64_t)SECP256K1_N_C_3 * p8; + r->d[3] = c & 0xFFFFFFFFUL; c >>= 32; + c += p4 + (uint64_t)p8; + r->d[4] = c & 0xFFFFFFFFUL; c >>= 32; + c += p5; + r->d[5] = c & 0xFFFFFFFFUL; c >>= 32; + c += p6; + r->d[6] = c & 0xFFFFFFFFUL; c >>= 32; + c += p7; + r->d[7] = c & 0xFFFFFFFFUL; c >>= 32; + + /* Final reduction of r. */ + secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); +} + +static void secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) { + /* 96 bit accumulator. */ + uint32_t c0 = 0, c1 = 0, c2 = 0; + + uint32_t l[16]; + + /* l[0..15] = a[0..7] * b[0..7]. */ + muladd_fast(a->d[0], b->d[0]); + extract_fast(l[0]); + muladd(a->d[0], b->d[1]); + muladd(a->d[1], b->d[0]); + extract(l[1]); + muladd(a->d[0], b->d[2]); + muladd(a->d[1], b->d[1]); + muladd(a->d[2], b->d[0]); + extract(l[2]); + muladd(a->d[0], b->d[3]); + muladd(a->d[1], b->d[2]); + muladd(a->d[2], b->d[1]); + muladd(a->d[3], b->d[0]); + extract(l[3]); + muladd(a->d[0], b->d[4]); + muladd(a->d[1], b->d[3]); + muladd(a->d[2], b->d[2]); + muladd(a->d[3], b->d[1]); + muladd(a->d[4], b->d[0]); + extract(l[4]); + muladd(a->d[0], b->d[5]); + muladd(a->d[1], b->d[4]); + muladd(a->d[2], b->d[3]); + muladd(a->d[3], b->d[2]); + muladd(a->d[4], b->d[1]); + muladd(a->d[5], b->d[0]); + extract(l[5]); + muladd(a->d[0], b->d[6]); + muladd(a->d[1], b->d[5]); + muladd(a->d[2], b->d[4]); + muladd(a->d[3], b->d[3]); + muladd(a->d[4], b->d[2]); + muladd(a->d[5], b->d[1]); + muladd(a->d[6], b->d[0]); + extract(l[6]); + muladd(a->d[0], b->d[7]); + muladd(a->d[1], b->d[6]); + muladd(a->d[2], b->d[5]); + muladd(a->d[3], b->d[4]); + muladd(a->d[4], b->d[3]); + muladd(a->d[5], b->d[2]); + muladd(a->d[6], b->d[1]); + muladd(a->d[7], b->d[0]); + extract(l[7]); + muladd(a->d[1], b->d[7]); + muladd(a->d[2], b->d[6]); + muladd(a->d[3], b->d[5]); + muladd(a->d[4], b->d[4]); + muladd(a->d[5], b->d[3]); + muladd(a->d[6], b->d[2]); + muladd(a->d[7], b->d[1]); + extract(l[8]); + muladd(a->d[2], b->d[7]); + muladd(a->d[3], b->d[6]); + muladd(a->d[4], b->d[5]); + muladd(a->d[5], b->d[4]); + muladd(a->d[6], b->d[3]); + muladd(a->d[7], b->d[2]); + extract(l[9]); + muladd(a->d[3], b->d[7]); + muladd(a->d[4], b->d[6]); + muladd(a->d[5], b->d[5]); + muladd(a->d[6], b->d[4]); + muladd(a->d[7], b->d[3]); + extract(l[10]); + muladd(a->d[4], b->d[7]); + muladd(a->d[5], b->d[6]); + muladd(a->d[6], b->d[5]); + muladd(a->d[7], b->d[4]); + extract(l[11]); + muladd(a->d[5], b->d[7]); + muladd(a->d[6], b->d[6]); + muladd(a->d[7], b->d[5]); + extract(l[12]); + muladd(a->d[6], b->d[7]); + muladd(a->d[7], b->d[6]); + extract(l[13]); + muladd_fast(a->d[7], b->d[7]); + extract_fast(l[14]); + VERIFY_CHECK(c1 == 0); + l[15] = c0; + + secp256k1_scalar_reduce_512(r, l); +} + +static void secp256k1_scalar_sqr(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) { + /* 96 bit accumulator. */ + uint32_t c0 = 0, c1 = 0, c2 = 0; + + uint32_t l[16]; + + /* l[0..15] = a[0..7]^2. */ + muladd_fast(a->d[0], a->d[0]); + extract_fast(l[0]); + muladd2(a->d[0], a->d[1]); + extract(l[1]); + muladd2(a->d[0], a->d[2]); + muladd(a->d[1], a->d[1]); + extract(l[2]); + muladd2(a->d[0], a->d[3]); + muladd2(a->d[1], a->d[2]); + extract(l[3]); + muladd2(a->d[0], a->d[4]); + muladd2(a->d[1], a->d[3]); + muladd(a->d[2], a->d[2]); + extract(l[4]); + muladd2(a->d[0], a->d[5]); + muladd2(a->d[1], a->d[4]); + muladd2(a->d[2], a->d[3]); + extract(l[5]); + muladd2(a->d[0], a->d[6]); + muladd2(a->d[1], a->d[5]); + muladd2(a->d[2], a->d[4]); + muladd(a->d[3], a->d[3]); + extract(l[6]); + muladd2(a->d[0], a->d[7]); + muladd2(a->d[1], a->d[6]); + muladd2(a->d[2], a->d[5]); + muladd2(a->d[3], a->d[4]); + extract(l[7]); + muladd2(a->d[1], a->d[7]); + muladd2(a->d[2], a->d[6]); + muladd2(a->d[3], a->d[5]); + muladd(a->d[4], a->d[4]); + extract(l[8]); + muladd2(a->d[2], a->d[7]); + muladd2(a->d[3], a->d[6]); + muladd2(a->d[4], a->d[5]); + extract(l[9]); + muladd2(a->d[3], a->d[7]); + muladd2(a->d[4], a->d[6]); + muladd(a->d[5], a->d[5]); + extract(l[10]); + muladd2(a->d[4], a->d[7]); + muladd2(a->d[5], a->d[6]); + extract(l[11]); + muladd2(a->d[5], a->d[7]); + muladd(a->d[6], a->d[6]); + extract(l[12]); + muladd2(a->d[6], a->d[7]); + extract(l[13]); + muladd_fast(a->d[7], a->d[7]); + extract_fast(l[14]); + VERIFY_CHECK(c1 == 0); + l[15] = c0; + + secp256k1_scalar_reduce_512(r, l); +} + +#undef sumadd +#undef sumadd_fast +#undef muladd +#undef muladd_fast +#undef muladd2 +#undef extract +#undef extract_fast + +#endif diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h new file mode 100644 index 0000000000..ddc5061c76 --- /dev/null +++ b/src/secp256k1/src/scalar_impl.h @@ -0,0 +1,184 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_IMPL_H_ +#define _SECP256K1_SCALAR_IMPL_H_ + +#include <string.h> + +#include "scalar.h" + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(USE_SCALAR_4X64) +#include "scalar_4x64_impl.h" +#elif defined(USE_SCALAR_8X32) +#include "scalar_8x32_impl.h" +#else +#error "Please select scalar implementation" +#endif + +static void secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a) { + unsigned char c[32]; + secp256k1_scalar_get_b32(c, a); + secp256k1_num_set_bin(r, c, 32); +} + + +static void secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *x) { + /* First compute x ^ (2^N - 1) for some values of N. */ + secp256k1_scalar_t x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127; + + secp256k1_scalar_sqr(&x2, x); + secp256k1_scalar_mul(&x2, &x2, x); + + secp256k1_scalar_sqr(&x3, &x2); + secp256k1_scalar_mul(&x3, &x3, x); + + secp256k1_scalar_sqr(&x4, &x3); + secp256k1_scalar_mul(&x4, &x4, x); + + secp256k1_scalar_sqr(&x6, &x4); + secp256k1_scalar_sqr(&x6, &x6); + secp256k1_scalar_mul(&x6, &x6, &x2); + + secp256k1_scalar_sqr(&x7, &x6); + secp256k1_scalar_mul(&x7, &x7, x); + + secp256k1_scalar_sqr(&x8, &x7); + secp256k1_scalar_mul(&x8, &x8, x); + + secp256k1_scalar_sqr(&x15, &x8); + for (int i=0; i<6; i++) + secp256k1_scalar_sqr(&x15, &x15); + secp256k1_scalar_mul(&x15, &x15, &x7); + + secp256k1_scalar_sqr(&x30, &x15); + for (int i=0; i<14; i++) + secp256k1_scalar_sqr(&x30, &x30); + secp256k1_scalar_mul(&x30, &x30, &x15); + + secp256k1_scalar_sqr(&x60, &x30); + for (int i=0; i<29; i++) + secp256k1_scalar_sqr(&x60, &x60); + secp256k1_scalar_mul(&x60, &x60, &x30); + + secp256k1_scalar_sqr(&x120, &x60); + for (int i=0; i<59; i++) + secp256k1_scalar_sqr(&x120, &x120); + secp256k1_scalar_mul(&x120, &x120, &x60); + + secp256k1_scalar_sqr(&x127, &x120); + for (int i=0; i<6; i++) + secp256k1_scalar_sqr(&x127, &x127); + secp256k1_scalar_mul(&x127, &x127, &x7); + + /* Then accumulate the final result (t starts at x127). */ + secp256k1_scalar_t *t = &x127; + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<4; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<4; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (int i=0; i<3; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (int i=0; i<4; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (int i=0; i<5; i++) /* 00 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (int i=0; i<4; i++) /* 00 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<5; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x4); /* 1111 */ + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<3; i++) /* 00 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<4; i++) /* 000 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<10; i++) /* 0000000 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (int i=0; i<4; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (int i=0; i<9; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x8); /* 11111111 */ + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<3; i++) /* 00 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<3; i++) /* 00 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<5; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x4); /* 1111 */ + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<5; i++) /* 000 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (int i=0; i<4; i++) /* 00 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (int i=0; i<2; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<8; i++) /* 000000 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (int i=0; i<3; i++) /* 0 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (int i=0; i<3; i++) /* 00 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<6; i++) /* 00000 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (int i=0; i<8; i++) /* 00 */ + secp256k1_scalar_sqr(t, t); + secp256k1_scalar_mul(r, t, &x6); /* 111111 */ +} + +#endif diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c new file mode 100644 index 0000000000..1ab5b3722c --- /dev/null +++ b/src/secp256k1/src/secp256k1.c @@ -0,0 +1,305 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#define SECP256K1_BUILD (1) + +#include "include/secp256k1.h" + +#include "util.h" +#include "num_impl.h" +#include "field_impl.h" +#include "scalar_impl.h" +#include "group_impl.h" +#include "ecmult_impl.h" +#include "ecmult_gen_impl.h" +#include "ecdsa_impl.h" +#include "eckey_impl.h" + +void secp256k1_start(unsigned int flags) { + secp256k1_fe_start(); + secp256k1_ge_start(); + if (flags & SECP256K1_START_SIGN) { + secp256k1_ecmult_gen_start(); + } + if (flags & SECP256K1_START_VERIFY) { + secp256k1_ecmult_start(); + } +} + +void secp256k1_stop(void) { + secp256k1_ecmult_stop(); + secp256k1_ecmult_gen_stop(); + secp256k1_ge_stop(); + secp256k1_fe_stop(); +} + +int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) { + DEBUG_CHECK(secp256k1_ecmult_consts != NULL); + DEBUG_CHECK(msg != NULL); + DEBUG_CHECK(msglen <= 32); + DEBUG_CHECK(sig != NULL); + DEBUG_CHECK(pubkey != NULL); + + int ret = -3; + secp256k1_num_t m; + secp256k1_ecdsa_sig_t s; + secp256k1_ge_t q; + secp256k1_num_set_bin(&m, msg, msglen); + + if (!secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) { + ret = -1; + goto end; + } + if (!secp256k1_ecdsa_sig_parse(&s, sig, siglen)) { + ret = -2; + goto end; + } + if (!secp256k1_ecdsa_sig_verify(&s, &q, &m)) { + ret = 0; + goto end; + } + ret = 1; +end: + return ret; +} + +int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned char *signature, int *signaturelen, const unsigned char *seckey, const unsigned char *nonce) { + DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL); + DEBUG_CHECK(message != NULL); + DEBUG_CHECK(messagelen <= 32); + DEBUG_CHECK(signature != NULL); + DEBUG_CHECK(signaturelen != NULL); + DEBUG_CHECK(seckey != NULL); + DEBUG_CHECK(nonce != NULL); + + secp256k1_scalar_t sec, non, msg; + secp256k1_scalar_set_b32(&sec, seckey, NULL); + int overflow = 0; + secp256k1_scalar_set_b32(&non, nonce, &overflow); + { + unsigned char c[32] = {0}; + memcpy(c + 32 - messagelen, message, messagelen); + secp256k1_scalar_set_b32(&msg, c, NULL); + memset(c, 0, 32); + } + int ret = !secp256k1_scalar_is_zero(&non) && !overflow; + secp256k1_ecdsa_sig_t sig; + if (ret) { + ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL); + } + if (ret) { + secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig); + } + secp256k1_scalar_clear(&msg); + secp256k1_scalar_clear(&non); + secp256k1_scalar_clear(&sec); + return ret; +} + +int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) { + DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL); + DEBUG_CHECK(message != NULL); + DEBUG_CHECK(messagelen <= 32); + DEBUG_CHECK(sig64 != NULL); + DEBUG_CHECK(seckey != NULL); + DEBUG_CHECK(nonce != NULL); + + secp256k1_scalar_t sec, non, msg; + secp256k1_scalar_set_b32(&sec, seckey, NULL); + int overflow = 0; + secp256k1_scalar_set_b32(&non, nonce, &overflow); + { + unsigned char c[32] = {0}; + memcpy(c + 32 - messagelen, message, messagelen); + secp256k1_scalar_set_b32(&msg, c, NULL); + memset(c, 0, 32); + } + int ret = !secp256k1_scalar_is_zero(&non) && !overflow; + secp256k1_ecdsa_sig_t sig; + if (ret) { + ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid); + } + if (ret) { + secp256k1_num_get_bin(sig64, 32, &sig.r); + secp256k1_num_get_bin(sig64 + 32, 32, &sig.s); + } + secp256k1_scalar_clear(&msg); + secp256k1_scalar_clear(&non); + secp256k1_scalar_clear(&sec); + return ret; +} + +int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) { + DEBUG_CHECK(secp256k1_ecmult_consts != NULL); + DEBUG_CHECK(msg != NULL); + DEBUG_CHECK(msglen <= 32); + DEBUG_CHECK(sig64 != NULL); + DEBUG_CHECK(pubkey != NULL); + DEBUG_CHECK(pubkeylen != NULL); + DEBUG_CHECK(recid >= 0 && recid <= 3); + + int ret = 0; + secp256k1_num_t m; + secp256k1_ecdsa_sig_t sig; + secp256k1_num_set_bin(&sig.r, sig64, 32); + secp256k1_num_set_bin(&sig.s, sig64 + 32, 32); + secp256k1_num_set_bin(&m, msg, msglen); + + secp256k1_ge_t q; + if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) { + ret = secp256k1_eckey_pubkey_serialize(&q, pubkey, pubkeylen, compressed); + } + return ret; +} + +int secp256k1_ec_seckey_verify(const unsigned char *seckey) { + DEBUG_CHECK(seckey != NULL); + + secp256k1_scalar_t sec; + int overflow; + secp256k1_scalar_set_b32(&sec, seckey, &overflow); + int ret = !secp256k1_scalar_is_zero(&sec) && !overflow; + secp256k1_scalar_clear(&sec); + return ret; +} + +int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) { + DEBUG_CHECK(pubkey != NULL); + + secp256k1_ge_t q; + return secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen); +} + +int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { + DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL); + DEBUG_CHECK(pubkey != NULL); + DEBUG_CHECK(pubkeylen != NULL); + DEBUG_CHECK(seckey != NULL); + + secp256k1_scalar_t sec; + secp256k1_scalar_set_b32(&sec, seckey, NULL); + secp256k1_gej_t pj; + secp256k1_ecmult_gen(&pj, &sec); + secp256k1_scalar_clear(&sec); + secp256k1_ge_t p; + secp256k1_ge_set_gej(&p, &pj); + return secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, compressed); +} + +int secp256k1_ec_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { + DEBUG_CHECK(pubkey != NULL); + DEBUG_CHECK(pubkeylen != NULL); + + secp256k1_ge_t p; + if (!secp256k1_eckey_pubkey_parse(&p, pubkey, *pubkeylen)) + return 0; + return secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, 0); +} + +int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) { + DEBUG_CHECK(seckey != NULL); + DEBUG_CHECK(tweak != NULL); + + secp256k1_scalar_t term; + int overflow = 0; + secp256k1_scalar_set_b32(&term, tweak, &overflow); + secp256k1_scalar_t sec; + secp256k1_scalar_set_b32(&sec, seckey, NULL); + + int ret = secp256k1_eckey_privkey_tweak_add(&sec, &term) && !overflow; + if (ret) { + secp256k1_scalar_get_b32(seckey, &sec); + } + + secp256k1_scalar_clear(&sec); + secp256k1_scalar_clear(&term); + return ret; +} + +int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { + DEBUG_CHECK(secp256k1_ecmult_consts != NULL); + DEBUG_CHECK(pubkey != NULL); + DEBUG_CHECK(tweak != NULL); + + secp256k1_num_t term; + secp256k1_num_set_bin(&term, tweak, 32); + secp256k1_ge_t p; + int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen); + if (ret) { + ret = secp256k1_eckey_pubkey_tweak_add(&p, &term); + } + if (ret) { + int oldlen = pubkeylen; + ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); + VERIFY_CHECK(pubkeylen == oldlen); + } + + return ret; +} + +int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) { + DEBUG_CHECK(seckey != NULL); + DEBUG_CHECK(tweak != NULL); + + secp256k1_scalar_t factor; + int overflow = 0; + secp256k1_scalar_set_b32(&factor, tweak, &overflow); + secp256k1_scalar_t sec; + secp256k1_scalar_set_b32(&sec, seckey, NULL); + int ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor) && !overflow; + if (ret) { + secp256k1_scalar_get_b32(seckey, &sec); + } + + secp256k1_scalar_clear(&sec); + secp256k1_scalar_clear(&factor); + return ret; +} + +int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { + DEBUG_CHECK(secp256k1_ecmult_consts != NULL); + DEBUG_CHECK(pubkey != NULL); + DEBUG_CHECK(tweak != NULL); + + secp256k1_num_t factor; + secp256k1_num_set_bin(&factor, tweak, 32); + secp256k1_ge_t p; + int ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen); + if (ret) { + ret = secp256k1_eckey_pubkey_tweak_mul(&p, &factor); + } + if (ret) { + int oldlen = pubkeylen; + ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); + VERIFY_CHECK(pubkeylen == oldlen); + } + + return ret; +} + +int secp256k1_ec_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) { + DEBUG_CHECK(seckey != NULL); + DEBUG_CHECK(privkey != NULL); + DEBUG_CHECK(privkeylen != NULL); + + secp256k1_scalar_t key; + secp256k1_scalar_set_b32(&key, seckey, NULL); + int ret = secp256k1_eckey_privkey_serialize(privkey, privkeylen, &key, compressed); + secp256k1_scalar_clear(&key); + return ret; +} + +int secp256k1_ec_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) { + DEBUG_CHECK(seckey != NULL); + DEBUG_CHECK(privkey != NULL); + + secp256k1_scalar_t key; + int ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen); + if (ret) + secp256k1_scalar_get_b32(seckey, &key); + secp256k1_scalar_clear(&key); + return ret; +} diff --git a/src/secp256k1/src/testrand.h b/src/secp256k1/src/testrand.h new file mode 100644 index 0000000000..018b65cd53 --- /dev/null +++ b/src/secp256k1/src/testrand.h @@ -0,0 +1,26 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_TESTRAND_H_ +#define _SECP256K1_TESTRAND_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +/** Seed the pseudorandom number generator. */ +SECP256K1_INLINE static void secp256k1_rand_seed(uint64_t v); + +/** Generate a pseudorandom 32-bit number. */ +static uint32_t secp256k1_rand32(void); + +/** Generate a pseudorandom 32-byte array. */ +static void secp256k1_rand256(unsigned char *b32); + +/** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ +static void secp256k1_rand256_test(unsigned char *b32); + +#endif diff --git a/src/secp256k1/src/testrand_impl.h b/src/secp256k1/src/testrand_impl.h new file mode 100644 index 0000000000..677c4b9a0e --- /dev/null +++ b/src/secp256k1/src/testrand_impl.h @@ -0,0 +1,60 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_TESTRAND_IMPL_H_ +#define _SECP256K1_TESTRAND_IMPL_H_ + +#include <stdint.h> +#include <string.h> + +#include "testrand.h" + +static uint32_t secp256k1_Rz = 11, secp256k1_Rw = 11; + +SECP256K1_INLINE static void secp256k1_rand_seed(uint64_t v) { + secp256k1_Rz = v >> 32; + secp256k1_Rw = v; + + if (secp256k1_Rz == 0 || secp256k1_Rz == 0x9068ffffU) { + secp256k1_Rz = 111; + } + if (secp256k1_Rw == 0 || secp256k1_Rw == 0x464fffffU) { + secp256k1_Rw = 111; + } +} + +SECP256K1_INLINE static uint32_t secp256k1_rand32(void) { + secp256k1_Rz = 36969 * (secp256k1_Rz & 0xFFFF) + (secp256k1_Rz >> 16); + secp256k1_Rw = 18000 * (secp256k1_Rw & 0xFFFF) + (secp256k1_Rw >> 16); + return (secp256k1_Rw << 16) + (secp256k1_Rw >> 16) + secp256k1_Rz; +} + +static void secp256k1_rand256(unsigned char *b32) { + for (int i=0; i<8; i++) { + uint32_t r = secp256k1_rand32(); + b32[i*4 + 0] = (r >> 0) & 0xFF; + b32[i*4 + 1] = (r >> 8) & 0xFF; + b32[i*4 + 2] = (r >> 16) & 0xFF; + b32[i*4 + 3] = (r >> 24) & 0xFF; + } +} + +static void secp256k1_rand256_test(unsigned char *b32) { + int bits=0; + memset(b32, 0, 32); + while (bits < 256) { + uint32_t ent = secp256k1_rand32(); + int now = 1 + ((ent % 64)*((ent >> 6) % 32)+16)/31; + uint32_t val = 1 & (ent >> 11); + while (now > 0 && bits < 256) { + b32[bits / 8] |= val << (bits % 8); + now--; + bits++; + } + } +} + +#endif diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c new file mode 100644 index 0000000000..5d9b8344d9 --- /dev/null +++ b/src/secp256k1/src/tests.c @@ -0,0 +1,1080 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> + +#include "secp256k1.c" +#include "testrand_impl.h" + +#ifdef ENABLE_OPENSSL_TESTS +#include "openssl/bn.h" +#include "openssl/ec.h" +#include "openssl/ecdsa.h" +#include "openssl/obj_mac.h" +#endif + +static int count = 64; + +/***** NUM TESTS *****/ + +void random_num_negate(secp256k1_num_t *num) { + if (secp256k1_rand32() & 1) + secp256k1_num_negate(num); +} + +void random_field_element_test(secp256k1_fe_t *fe) { + do { + unsigned char b32[32]; + secp256k1_rand256_test(b32); + secp256k1_num_t num; + secp256k1_num_set_bin(&num, b32, 32); + if (secp256k1_num_cmp(&num, &secp256k1_fe_consts->p) >= 0) + continue; + secp256k1_fe_set_b32(fe, b32); + break; + } while(1); +} + +void random_field_element_magnitude(secp256k1_fe_t *fe) { + secp256k1_fe_normalize(fe); + int n = secp256k1_rand32() % 4; + for (int i = 0; i < n; i++) { + secp256k1_fe_negate(fe, fe, 1 + 2*i); + secp256k1_fe_negate(fe, fe, 2 + 2*i); + } +} + +void random_group_element_test(secp256k1_ge_t *ge) { + secp256k1_fe_t fe; + do { + random_field_element_test(&fe); + if (secp256k1_ge_set_xo(ge, &fe, secp256k1_rand32() & 1)) + break; + } while(1); +} + +void random_group_element_jacobian_test(secp256k1_gej_t *gej, const secp256k1_ge_t *ge) { + do { + random_field_element_test(&gej->z); + if (!secp256k1_fe_is_zero(&gej->z)) { + break; + } + } while(1); + secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &gej->z); + secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &z2, &gej->z); + secp256k1_fe_mul(&gej->x, &ge->x, &z2); + secp256k1_fe_mul(&gej->y, &ge->y, &z3); + gej->infinity = ge->infinity; +} + +void random_num_order_test(secp256k1_num_t *num) { + do { + unsigned char b32[32]; + secp256k1_rand256_test(b32); + secp256k1_num_set_bin(num, b32, 32); + if (secp256k1_num_is_zero(num)) + continue; + if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0) + continue; + break; + } while(1); +} + +void random_scalar_order_test(secp256k1_scalar_t *num) { + do { + unsigned char b32[32]; + secp256k1_rand256_test(b32); + int overflow = 0; + secp256k1_scalar_set_b32(num, b32, &overflow); + if (overflow || secp256k1_scalar_is_zero(num)) + continue; + break; + } while(1); +} + +void random_num_order(secp256k1_num_t *num) { + do { + unsigned char b32[32]; + secp256k1_rand256(b32); + secp256k1_num_set_bin(num, b32, 32); + if (secp256k1_num_is_zero(num)) + continue; + if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0) + continue; + break; + } while(1); +} + +void test_num_copy_inc_cmp(void) { + secp256k1_num_t n1,n2; + random_num_order(&n1); + secp256k1_num_copy(&n2, &n1); + CHECK(secp256k1_num_eq(&n1, &n2)); + CHECK(secp256k1_num_eq(&n2, &n1)); + secp256k1_num_inc(&n2); + CHECK(!secp256k1_num_eq(&n1, &n2)); + CHECK(!secp256k1_num_eq(&n2, &n1)); +} + + +void test_num_get_set_hex(void) { + secp256k1_num_t n1,n2; + random_num_order_test(&n1); + char c[64]; + secp256k1_num_get_hex(c, 64, &n1); + secp256k1_num_set_hex(&n2, c, 64); + CHECK(secp256k1_num_eq(&n1, &n2)); + for (int i=0; i<64; i++) { + /* check whether the lower 4 bits correspond to the last hex character */ + int low1 = secp256k1_num_shift(&n1, 4); + int lowh = c[63]; + int low2 = ((lowh>>6)*9+(lowh-'0'))&15; + CHECK(low1 == low2); + /* shift bits off the hex representation, and compare */ + memmove(c+1, c, 63); + c[0] = '0'; + secp256k1_num_set_hex(&n2, c, 64); + CHECK(secp256k1_num_eq(&n1, &n2)); + } +} + +void test_num_get_set_bin(void) { + secp256k1_num_t n1,n2; + random_num_order_test(&n1); + unsigned char c[32]; + secp256k1_num_get_bin(c, 32, &n1); + secp256k1_num_set_bin(&n2, c, 32); + CHECK(secp256k1_num_eq(&n1, &n2)); + for (int i=0; i<32; i++) { + /* check whether the lower 8 bits correspond to the last byte */ + int low1 = secp256k1_num_shift(&n1, 8); + int low2 = c[31]; + CHECK(low1 == low2); + /* shift bits off the byte representation, and compare */ + memmove(c+1, c, 31); + c[0] = 0; + secp256k1_num_set_bin(&n2, c, 32); + CHECK(secp256k1_num_eq(&n1, &n2)); + } +} + +void run_num_int(void) { + secp256k1_num_t n1; + for (int i=-255; i<256; i++) { + unsigned char c1[3] = {}; + c1[2] = abs(i); + unsigned char c2[3] = {0x11,0x22,0x33}; + secp256k1_num_set_int(&n1, i); + secp256k1_num_get_bin(c2, 3, &n1); + CHECK(memcmp(c1, c2, 3) == 0); + } +} + +void test_num_negate(void) { + secp256k1_num_t n1; + secp256k1_num_t n2; + random_num_order_test(&n1); /* n1 = R */ + random_num_negate(&n1); + secp256k1_num_copy(&n2, &n1); /* n2 = R */ + secp256k1_num_sub(&n1, &n2, &n1); /* n1 = n2-n1 = 0 */ + CHECK(secp256k1_num_is_zero(&n1)); + secp256k1_num_copy(&n1, &n2); /* n1 = R */ + secp256k1_num_negate(&n1); /* n1 = -R */ + CHECK(!secp256k1_num_is_zero(&n1)); + secp256k1_num_add(&n1, &n2, &n1); /* n1 = n2+n1 = 0 */ + CHECK(secp256k1_num_is_zero(&n1)); + secp256k1_num_copy(&n1, &n2); /* n1 = R */ + secp256k1_num_negate(&n1); /* n1 = -R */ + CHECK(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2)); + secp256k1_num_negate(&n1); /* n1 = R */ + CHECK(secp256k1_num_eq(&n1, &n2)); +} + +void test_num_add_sub(void) { + int r = secp256k1_rand32(); + secp256k1_num_t n1; + secp256k1_num_t n2; + random_num_order_test(&n1); /* n1 = R1 */ + if (r & 1) { + random_num_negate(&n1); + } + random_num_order_test(&n2); /* n2 = R2 */ + if (r & 2) { + random_num_negate(&n2); + } + secp256k1_num_t n1p2, n2p1, n1m2, n2m1; + secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */ + secp256k1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */ + secp256k1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */ + secp256k1_num_sub(&n2m1, &n2, &n1); /* n2m1 = R2 - R1 */ + CHECK(secp256k1_num_eq(&n1p2, &n2p1)); + CHECK(!secp256k1_num_eq(&n1p2, &n1m2)); + secp256k1_num_negate(&n2m1); /* n2m1 = -R2 + R1 */ + CHECK(secp256k1_num_eq(&n2m1, &n1m2)); + CHECK(!secp256k1_num_eq(&n2m1, &n1)); + secp256k1_num_add(&n2m1, &n2m1, &n2); /* n2m1 = -R2 + R1 + R2 = R1 */ + CHECK(secp256k1_num_eq(&n2m1, &n1)); + CHECK(!secp256k1_num_eq(&n2p1, &n1)); + secp256k1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */ + CHECK(secp256k1_num_eq(&n2p1, &n1)); +} + +void run_num_smalltests(void) { + for (int i=0; i<100*count; i++) { + test_num_copy_inc_cmp(); + test_num_get_set_hex(); + test_num_get_set_bin(); + test_num_negate(); + test_num_add_sub(); + } + run_num_int(); +} + +/***** SCALAR TESTS *****/ + +int secp256k1_scalar_eq(const secp256k1_scalar_t *s1, const secp256k1_scalar_t *s2) { + secp256k1_scalar_t t; + secp256k1_scalar_negate(&t, s2); + secp256k1_scalar_add(&t, &t, s1); + int ret = secp256k1_scalar_is_zero(&t); + return ret; +} + +void scalar_test(void) { + unsigned char c[32]; + + /* Set 's' to a random scalar, with value 'snum'. */ + secp256k1_rand256_test(c); + secp256k1_scalar_t s; + secp256k1_scalar_set_b32(&s, c, NULL); + secp256k1_num_t snum; + secp256k1_num_set_bin(&snum, c, 32); + secp256k1_num_mod(&snum, &secp256k1_ge_consts->order); + + /* Set 's1' to a random scalar, with value 's1num'. */ + secp256k1_rand256_test(c); + secp256k1_scalar_t s1; + secp256k1_scalar_set_b32(&s1, c, NULL); + secp256k1_num_t s1num; + secp256k1_num_set_bin(&s1num, c, 32); + secp256k1_num_mod(&s1num, &secp256k1_ge_consts->order); + + /* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */ + secp256k1_rand256_test(c); + secp256k1_scalar_t s2; + int overflow = 0; + secp256k1_scalar_set_b32(&s2, c, &overflow); + secp256k1_num_t s2num; + secp256k1_num_set_bin(&s2num, c, 32); + secp256k1_num_mod(&s2num, &secp256k1_ge_consts->order); + + { + /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ + secp256k1_num_t n, t, m; + secp256k1_num_set_int(&n, 0); + secp256k1_num_set_int(&m, 16); + for (int i = 0; i < 256; i += 4) { + secp256k1_num_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); + secp256k1_num_mul(&n, &n, &m); + secp256k1_num_add(&n, &n, &t); + } + CHECK(secp256k1_num_eq(&n, &snum)); + } + + { + /* Test that get_b32 returns the same as get_bin on the number. */ + unsigned char r1[32]; + secp256k1_scalar_get_b32(r1, &s2); + unsigned char r2[32]; + secp256k1_num_get_bin(r2, 32, &s2num); + CHECK(memcmp(r1, r2, 32) == 0); + /* If no overflow occurred when assigning, it should also be equal to the original byte array. */ + CHECK((memcmp(r1, c, 32) == 0) == (overflow == 0)); + } + + { + /* Test that adding the scalars together is equal to adding their numbers together modulo the order. */ + secp256k1_num_t rnum; + secp256k1_num_add(&rnum, &snum, &s2num); + secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order); + secp256k1_scalar_t r; + secp256k1_scalar_add(&r, &s, &s2); + secp256k1_num_t r2num; + secp256k1_scalar_get_num(&r2num, &r); + CHECK(secp256k1_num_eq(&rnum, &r2num)); + } + + { + /* Test that multipying the scalars is equal to multiplying their numbers modulo the order. */ + secp256k1_num_t rnum; + secp256k1_num_mul(&rnum, &snum, &s2num); + secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order); + secp256k1_scalar_t r; + secp256k1_scalar_mul(&r, &s, &s2); + secp256k1_num_t r2num; + secp256k1_scalar_get_num(&r2num, &r); + CHECK(secp256k1_num_eq(&rnum, &r2num)); + /* The result can only be zero if at least one of the factors was zero. */ + CHECK(secp256k1_scalar_is_zero(&r) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_zero(&s2))); + /* The results can only be equal to one of the factors if that factor was zero, or the other factor was one. */ + CHECK(secp256k1_num_eq(&rnum, &snum) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_one(&s2))); + CHECK(secp256k1_num_eq(&rnum, &s2num) == (secp256k1_scalar_is_zero(&s2) || secp256k1_scalar_is_one(&s))); + } + + { + /* Check that comparison with zero matches comparison with zero on the number. */ + CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s)); + /* Check that comparison with the half order is equal to testing for high scalar. */ + CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &secp256k1_ge_consts->half_order) > 0)); + secp256k1_scalar_t neg; + secp256k1_scalar_negate(&neg, &s); + secp256k1_num_t negnum; + secp256k1_num_sub(&negnum, &secp256k1_ge_consts->order, &snum); + secp256k1_num_mod(&negnum, &secp256k1_ge_consts->order); + /* Check that comparison with the half order is equal to testing for high scalar after negation. */ + CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &secp256k1_ge_consts->half_order) > 0)); + /* Negating should change the high property, unless the value was already zero. */ + CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s)); + secp256k1_num_t negnum2; + secp256k1_scalar_get_num(&negnum2, &neg); + /* Negating a scalar should be equal to (order - n) mod order on the number. */ + CHECK(secp256k1_num_eq(&negnum, &negnum2)); + secp256k1_scalar_add(&neg, &neg, &s); + /* Adding a number to its negation should result in zero. */ + CHECK(secp256k1_scalar_is_zero(&neg)); + secp256k1_scalar_negate(&neg, &neg); + /* Negating zero should still result in zero. */ + CHECK(secp256k1_scalar_is_zero(&neg)); + } + + { + /* Test that scalar inverses are equal to the inverse of their number modulo the order. */ + if (!secp256k1_scalar_is_zero(&s)) { + secp256k1_scalar_t inv; + secp256k1_scalar_inverse(&inv, &s); + secp256k1_num_t invnum; + secp256k1_num_mod_inverse(&invnum, &snum, &secp256k1_ge_consts->order); + secp256k1_num_t invnum2; + secp256k1_scalar_get_num(&invnum2, &inv); + CHECK(secp256k1_num_eq(&invnum, &invnum2)); + secp256k1_scalar_mul(&inv, &inv, &s); + /* Multiplying a scalar with its inverse must result in one. */ + CHECK(secp256k1_scalar_is_one(&inv)); + secp256k1_scalar_inverse(&inv, &inv); + /* Inverting one must result in one. */ + CHECK(secp256k1_scalar_is_one(&inv)); + } + } + + { + /* Test commutativity of add. */ + secp256k1_scalar_t r1, r2; + secp256k1_scalar_add(&r1, &s1, &s2); + secp256k1_scalar_add(&r2, &s2, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test commutativity of mul. */ + secp256k1_scalar_t r1, r2; + secp256k1_scalar_mul(&r1, &s1, &s2); + secp256k1_scalar_mul(&r2, &s2, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test associativity of add. */ + secp256k1_scalar_t r1, r2; + secp256k1_scalar_add(&r1, &s1, &s2); + secp256k1_scalar_add(&r1, &r1, &s); + secp256k1_scalar_add(&r2, &s2, &s); + secp256k1_scalar_add(&r2, &s1, &r2); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test associativity of mul. */ + secp256k1_scalar_t r1, r2; + secp256k1_scalar_mul(&r1, &s1, &s2); + secp256k1_scalar_mul(&r1, &r1, &s); + secp256k1_scalar_mul(&r2, &s2, &s); + secp256k1_scalar_mul(&r2, &s1, &r2); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test distributitivity of mul over add. */ + secp256k1_scalar_t r1, r2, t; + secp256k1_scalar_add(&r1, &s1, &s2); + secp256k1_scalar_mul(&r1, &r1, &s); + secp256k1_scalar_mul(&r2, &s1, &s); + secp256k1_scalar_mul(&t, &s2, &s); + secp256k1_scalar_add(&r2, &r2, &t); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test square. */ + secp256k1_scalar_t r1, r2; + secp256k1_scalar_sqr(&r1, &s1); + secp256k1_scalar_mul(&r2, &s1, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } +} + +void run_scalar_tests(void) { + for (int i = 0; i < 128 * count; i++) { + scalar_test(); + } +} + +/***** FIELD TESTS *****/ + +void random_fe(secp256k1_fe_t *x) { + unsigned char bin[32]; + secp256k1_rand256(bin); + secp256k1_fe_set_b32(x, bin); +} + +void random_fe_non_zero(secp256k1_fe_t *nz) { + int tries = 10; + while (--tries >= 0) { + random_fe(nz); + secp256k1_fe_normalize(nz); + if (!secp256k1_fe_is_zero(nz)) + break; + } + /* Infinitesimal probability of spurious failure here */ + CHECK(tries >= 0); +} + +void random_fe_non_square(secp256k1_fe_t *ns) { + random_fe_non_zero(ns); + secp256k1_fe_t r; + if (secp256k1_fe_sqrt(&r, ns)) { + secp256k1_fe_negate(ns, ns, 1); + } +} + +int check_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { + secp256k1_fe_t an = *a; secp256k1_fe_normalize(&an); + secp256k1_fe_t bn = *b; secp256k1_fe_normalize(&bn); + return secp256k1_fe_equal(&an, &bn); +} + +int check_fe_inverse(const secp256k1_fe_t *a, const secp256k1_fe_t *ai) { + secp256k1_fe_t x; secp256k1_fe_mul(&x, a, ai); + secp256k1_fe_t one; secp256k1_fe_set_int(&one, 1); + return check_fe_equal(&x, &one); +} + +void run_field_inv(void) { + secp256k1_fe_t x, xi, xii; + for (int i=0; i<10*count; i++) { + random_fe_non_zero(&x); + secp256k1_fe_inv(&xi, &x); + CHECK(check_fe_inverse(&x, &xi)); + secp256k1_fe_inv(&xii, &xi); + CHECK(check_fe_equal(&x, &xii)); + } +} + +void run_field_inv_var(void) { + secp256k1_fe_t x, xi, xii; + for (int i=0; i<10*count; i++) { + random_fe_non_zero(&x); + secp256k1_fe_inv_var(&xi, &x); + CHECK(check_fe_inverse(&x, &xi)); + secp256k1_fe_inv_var(&xii, &xi); + CHECK(check_fe_equal(&x, &xii)); + } +} + +void run_field_inv_all(void) { + secp256k1_fe_t x[16], xi[16], xii[16]; + /* Check it's safe to call for 0 elements */ + secp256k1_fe_inv_all(0, xi, x); + for (int i=0; i<count; i++) { + size_t len = (secp256k1_rand32() & 15) + 1; + for (size_t j=0; j<len; j++) + random_fe_non_zero(&x[j]); + secp256k1_fe_inv_all(len, xi, x); + for (size_t j=0; j<len; j++) + CHECK(check_fe_inverse(&x[j], &xi[j])); + secp256k1_fe_inv_all(len, xii, xi); + for (size_t j=0; j<len; j++) + CHECK(check_fe_equal(&x[j], &xii[j])); + } +} + +void run_field_inv_all_var(void) { + secp256k1_fe_t x[16], xi[16], xii[16]; + /* Check it's safe to call for 0 elements */ + secp256k1_fe_inv_all_var(0, xi, x); + for (int i=0; i<count; i++) { + size_t len = (secp256k1_rand32() & 15) + 1; + for (size_t j=0; j<len; j++) + random_fe_non_zero(&x[j]); + secp256k1_fe_inv_all_var(len, xi, x); + for (size_t j=0; j<len; j++) + CHECK(check_fe_inverse(&x[j], &xi[j])); + secp256k1_fe_inv_all_var(len, xii, xi); + for (size_t j=0; j<len; j++) + CHECK(check_fe_equal(&x[j], &xii[j])); + } +} + +void run_sqr(void) { + secp256k1_fe_t x, s; + + { + secp256k1_fe_set_int(&x, 1); + secp256k1_fe_negate(&x, &x, 1); + + for (int i=1; i<=512; ++i) { + secp256k1_fe_mul_int(&x, 2); + secp256k1_fe_normalize(&x); + secp256k1_fe_sqr(&s, &x); + } + } +} + +void test_sqrt(const secp256k1_fe_t *a, const secp256k1_fe_t *k) { + secp256k1_fe_t r1, r2; + int v = secp256k1_fe_sqrt(&r1, a); + CHECK((v == 0) == (k == NULL)); + + if (k != NULL) { + /* Check that the returned root is +/- the given known answer */ + secp256k1_fe_negate(&r2, &r1, 1); + secp256k1_fe_add(&r1, k); secp256k1_fe_add(&r2, k); + secp256k1_fe_normalize(&r1); secp256k1_fe_normalize(&r2); + CHECK(secp256k1_fe_is_zero(&r1) || secp256k1_fe_is_zero(&r2)); + } +} + +void run_sqrt(void) { + secp256k1_fe_t ns, x, s, t; + + /* Check sqrt(0) is 0 */ + secp256k1_fe_set_int(&x, 0); + secp256k1_fe_sqr(&s, &x); + test_sqrt(&s, &x); + + /* Check sqrt of small squares (and their negatives) */ + for (int i=1; i<=100; i++) { + secp256k1_fe_set_int(&x, i); + secp256k1_fe_sqr(&s, &x); + test_sqrt(&s, &x); + secp256k1_fe_negate(&t, &s, 1); + test_sqrt(&t, NULL); + } + + /* Consistency checks for large random values */ + for (int i=0; i<10; i++) { + random_fe_non_square(&ns); + for (int j=0; j<count; j++) { + random_fe(&x); + secp256k1_fe_sqr(&s, &x); + test_sqrt(&s, &x); + secp256k1_fe_negate(&t, &s, 1); + test_sqrt(&t, NULL); + secp256k1_fe_mul(&t, &s, &ns); + test_sqrt(&t, NULL); + } + } +} + +/***** GROUP TESTS *****/ + +int ge_equals_ge(const secp256k1_ge_t *a, const secp256k1_ge_t *b) { + if (a->infinity && b->infinity) + return 1; + return check_fe_equal(&a->x, &b->x) && check_fe_equal(&a->y, &b->y); +} + +void ge_equals_gej(const secp256k1_ge_t *a, const secp256k1_gej_t *b) { + secp256k1_ge_t bb; + secp256k1_gej_t bj = *b; + secp256k1_ge_set_gej_var(&bb, &bj); + CHECK(ge_equals_ge(a, &bb)); +} + +void gej_equals_gej(const secp256k1_gej_t *a, const secp256k1_gej_t *b) { + secp256k1_ge_t aa, bb; + secp256k1_gej_t aj = *a, bj = *b; + secp256k1_ge_set_gej_var(&aa, &aj); + secp256k1_ge_set_gej_var(&bb, &bj); + CHECK(ge_equals_ge(&aa, &bb)); +} + +void test_ge(void) { + secp256k1_ge_t a, b, i, n; + random_group_element_test(&a); + random_group_element_test(&b); + n = a; + secp256k1_fe_normalize(&a.y); + secp256k1_fe_negate(&n.y, &a.y, 1); + secp256k1_ge_set_infinity(&i); + random_field_element_magnitude(&a.x); + random_field_element_magnitude(&a.y); + random_field_element_magnitude(&b.x); + random_field_element_magnitude(&b.y); + random_field_element_magnitude(&n.x); + random_field_element_magnitude(&n.y); + + secp256k1_gej_t aj, bj, ij, nj; + random_group_element_jacobian_test(&aj, &a); + random_group_element_jacobian_test(&bj, &b); + secp256k1_gej_set_infinity(&ij); + random_group_element_jacobian_test(&nj, &n); + random_field_element_magnitude(&aj.x); + random_field_element_magnitude(&aj.y); + random_field_element_magnitude(&aj.z); + random_field_element_magnitude(&bj.x); + random_field_element_magnitude(&bj.y); + random_field_element_magnitude(&bj.z); + random_field_element_magnitude(&nj.x); + random_field_element_magnitude(&nj.y); + random_field_element_magnitude(&nj.z); + + /* gej + gej adds */ + secp256k1_gej_t aaj; secp256k1_gej_add_var(&aaj, &aj, &aj); + secp256k1_gej_t abj; secp256k1_gej_add_var(&abj, &aj, &bj); + secp256k1_gej_t aij; secp256k1_gej_add_var(&aij, &aj, &ij); + secp256k1_gej_t anj; secp256k1_gej_add_var(&anj, &aj, &nj); + secp256k1_gej_t iaj; secp256k1_gej_add_var(&iaj, &ij, &aj); + secp256k1_gej_t iij; secp256k1_gej_add_var(&iij, &ij, &ij); + + /* gej + ge adds */ + secp256k1_gej_t aa; secp256k1_gej_add_ge_var(&aa, &aj, &a); + secp256k1_gej_t ab; secp256k1_gej_add_ge_var(&ab, &aj, &b); + secp256k1_gej_t ai; secp256k1_gej_add_ge_var(&ai, &aj, &i); + secp256k1_gej_t an; secp256k1_gej_add_ge_var(&an, &aj, &n); + secp256k1_gej_t ia; secp256k1_gej_add_ge_var(&ia, &ij, &a); + secp256k1_gej_t ii; secp256k1_gej_add_ge_var(&ii, &ij, &i); + + /* const gej + ge adds */ + secp256k1_gej_t aac; secp256k1_gej_add_ge(&aac, &aj, &a); + secp256k1_gej_t abc; secp256k1_gej_add_ge(&abc, &aj, &b); + secp256k1_gej_t anc; secp256k1_gej_add_ge(&anc, &aj, &n); + secp256k1_gej_t iac; secp256k1_gej_add_ge(&iac, &ij, &a); + + CHECK(secp256k1_gej_is_infinity(&an)); + CHECK(secp256k1_gej_is_infinity(&anj)); + CHECK(secp256k1_gej_is_infinity(&anc)); + gej_equals_gej(&aa, &aaj); + gej_equals_gej(&aa, &aac); + gej_equals_gej(&ab, &abj); + gej_equals_gej(&ab, &abc); + gej_equals_gej(&an, &anj); + gej_equals_gej(&an, &anc); + gej_equals_gej(&ia, &iaj); + gej_equals_gej(&ai, &aij); + gej_equals_gej(&ii, &iij); + ge_equals_gej(&a, &ai); + ge_equals_gej(&a, &ai); + ge_equals_gej(&a, &iaj); + ge_equals_gej(&a, &iaj); + ge_equals_gej(&a, &iac); +} + +void run_ge(void) { + for (int i = 0; i < 2000*count; i++) { + test_ge(); + } +} + +/***** ECMULT TESTS *****/ + +void run_ecmult_chain(void) { + /* random starting point A (on the curve) */ + secp256k1_fe_t ax; secp256k1_fe_set_hex(&ax, "8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004", 64); + secp256k1_fe_t ay; secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64); + secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay); + /* two random initial factors xn and gn */ + secp256k1_num_t xn; + secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64); + secp256k1_num_t gn; + secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64); + /* two small multipliers to be applied to xn and gn in every iteration: */ + secp256k1_num_t xf; + secp256k1_num_set_hex(&xf, "1337", 4); + secp256k1_num_t gf; + secp256k1_num_set_hex(&gf, "7113", 4); + /* accumulators with the resulting coefficients to A and G */ + secp256k1_num_t ae; + secp256k1_num_set_int(&ae, 1); + secp256k1_num_t ge; + secp256k1_num_set_int(&ge, 0); + /* the point being computed */ + secp256k1_gej_t x = a; + const secp256k1_num_t *order = &secp256k1_ge_consts->order; + for (int i=0; i<200*count; i++) { + /* in each iteration, compute X = xn*X + gn*G; */ + secp256k1_ecmult(&x, &x, &xn, &gn); + /* also compute ae and ge: the actual accumulated factors for A and G */ + /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ + secp256k1_num_mod_mul(&ae, &ae, &xn, order); + secp256k1_num_mod_mul(&ge, &ge, &xn, order); + secp256k1_num_add(&ge, &ge, &gn); + secp256k1_num_mod(&ge, order); + /* modify xn and gn */ + secp256k1_num_mod_mul(&xn, &xn, &xf, order); + secp256k1_num_mod_mul(&gn, &gn, &gf, order); + + /* verify */ + if (i == 19999) { + char res[132]; int resl = 132; + secp256k1_gej_get_hex(res, &resl, &x); + CHECK(strcmp(res, "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)") == 0); + } + } + /* redo the computation, but directly with the resulting ae and ge coefficients: */ + secp256k1_gej_t x2; secp256k1_ecmult(&x2, &a, &ae, &ge); + char res[132]; int resl = 132; + char res2[132]; int resl2 = 132; + secp256k1_gej_get_hex(res, &resl, &x); + secp256k1_gej_get_hex(res2, &resl2, &x2); + CHECK(strcmp(res, res2) == 0); + CHECK(strlen(res) == 131); +} + +void test_point_times_order(const secp256k1_gej_t *point) { + /* multiplying a point by the order results in O */ + const secp256k1_num_t *order = &secp256k1_ge_consts->order; + secp256k1_num_t zero; + secp256k1_num_set_int(&zero, 0); + secp256k1_gej_t res; + secp256k1_ecmult(&res, point, order, order); /* calc res = order * point + order * G; */ + CHECK(secp256k1_gej_is_infinity(&res)); +} + +void run_point_times_order(void) { + secp256k1_fe_t x; secp256k1_fe_set_hex(&x, "02", 2); + for (int i=0; i<500; i++) { + secp256k1_ge_t p; + if (secp256k1_ge_set_xo(&p, &x, 1)) { + CHECK(secp256k1_ge_is_valid(&p)); + secp256k1_gej_t j; + secp256k1_gej_set_ge(&j, &p); + CHECK(secp256k1_gej_is_valid(&j)); + test_point_times_order(&j); + } + secp256k1_fe_sqr(&x, &x); + } + char c[65]; int cl=65; + secp256k1_fe_get_hex(c, &cl, &x); + CHECK(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0); +} + +void test_wnaf(const secp256k1_num_t *number, int w) { + secp256k1_num_t x, two, t; + secp256k1_num_set_int(&x, 0); + secp256k1_num_set_int(&two, 2); + int wnaf[257]; + int bits = secp256k1_ecmult_wnaf(wnaf, number, w); + int zeroes = -1; + for (int i=bits-1; i>=0; i--) { + secp256k1_num_mul(&x, &x, &two); + int v = wnaf[i]; + if (v) { + CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ + zeroes=0; + CHECK((v & 1) == 1); /* check non-zero elements are odd */ + CHECK(v <= (1 << (w-1)) - 1); /* check range below */ + CHECK(v >= -(1 << (w-1)) - 1); /* check range above */ + } else { + CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */ + zeroes++; + } + secp256k1_num_set_int(&t, v); + secp256k1_num_add(&x, &x, &t); + } + CHECK(secp256k1_num_eq(&x, number)); /* check that wnaf represents number */ +} + +void run_wnaf(void) { + secp256k1_num_t n; + for (int i=0; i<count; i++) { + random_num_order(&n); + if (i % 1) + secp256k1_num_negate(&n); + test_wnaf(&n, 4+(i%10)); + } +} + +void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *key, const secp256k1_scalar_t *msg, int *recid) { + secp256k1_scalar_t nonce; + do { + random_scalar_order_test(&nonce); + } while(!secp256k1_ecdsa_sig_sign(sig, key, msg, &nonce, recid)); +} + +void test_ecdsa_sign_verify(void) { + secp256k1_scalar_t msg, key; + random_scalar_order_test(&msg); + random_scalar_order_test(&key); + secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key); + secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj); + secp256k1_ecdsa_sig_t sig; + random_sign(&sig, &key, &msg, NULL); + secp256k1_num_t msg_num; + secp256k1_scalar_get_num(&msg_num, &msg); + CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num)); + secp256k1_num_inc(&msg_num); + CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num)); +} + +void run_ecdsa_sign_verify(void) { + for (int i=0; i<10*count; i++) { + test_ecdsa_sign_verify(); + } +} + +void test_ecdsa_end_to_end(void) { + unsigned char privkey[32]; + unsigned char message[32]; + + /* Generate a random key and message. */ + { + secp256k1_num_t msg, key; + random_num_order_test(&msg); + random_num_order_test(&key); + secp256k1_num_get_bin(privkey, 32, &key); + secp256k1_num_get_bin(message, 32, &msg); + } + + /* Construct and verify corresponding public key. */ + CHECK(secp256k1_ec_seckey_verify(privkey) == 1); + unsigned char pubkey[65]; int pubkeylen = 65; + CHECK(secp256k1_ec_pubkey_create(pubkey, &pubkeylen, privkey, secp256k1_rand32() % 2) == 1); + CHECK(secp256k1_ec_pubkey_verify(pubkey, pubkeylen)); + + /* Verify private key import and export. */ + unsigned char seckey[300]; int seckeylen = 300; + CHECK(secp256k1_ec_privkey_export(privkey, seckey, &seckeylen, secp256k1_rand32() % 2) == 1); + unsigned char privkey2[32]; + CHECK(secp256k1_ec_privkey_import(privkey2, seckey, seckeylen) == 1); + CHECK(memcmp(privkey, privkey2, 32) == 0); + + /* Optionally tweak the keys using addition. */ + if (secp256k1_rand32() % 3 == 0) { + unsigned char rnd[32]; + secp256k1_rand256_test(rnd); + int ret1 = secp256k1_ec_privkey_tweak_add(privkey, rnd); + int ret2 = secp256k1_ec_pubkey_tweak_add(pubkey, pubkeylen, rnd); + CHECK(ret1 == ret2); + if (ret1 == 0) return; + unsigned char pubkey2[65]; int pubkeylen2 = 65; + CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); + CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); + } + + /* Optionally tweak the keys using multiplication. */ + if (secp256k1_rand32() % 3 == 0) { + unsigned char rnd[32]; + secp256k1_rand256_test(rnd); + int ret1 = secp256k1_ec_privkey_tweak_mul(privkey, rnd); + int ret2 = secp256k1_ec_pubkey_tweak_mul(pubkey, pubkeylen, rnd); + CHECK(ret1 == ret2); + if (ret1 == 0) return; + unsigned char pubkey2[65]; int pubkeylen2 = 65; + CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); + CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); + } + + /* Sign. */ + unsigned char signature[72]; int signaturelen = 72; + while(1) { + unsigned char rnd[32]; + secp256k1_rand256_test(rnd); + if (secp256k1_ecdsa_sign(message, 32, signature, &signaturelen, privkey, rnd) == 1) { + break; + } + } + /* Verify. */ + CHECK(secp256k1_ecdsa_verify(message, 32, signature, signaturelen, pubkey, pubkeylen) == 1); + /* Destroy signature and verify again. */ + signature[signaturelen - 1 - secp256k1_rand32() % 20] += 1 + (secp256k1_rand32() % 255); + CHECK(secp256k1_ecdsa_verify(message, 32, signature, signaturelen, pubkey, pubkeylen) != 1); + + /* Compact sign. */ + unsigned char csignature[64]; int recid = 0; + while(1) { + unsigned char rnd[32]; + secp256k1_rand256_test(rnd); + if (secp256k1_ecdsa_sign_compact(message, 32, csignature, privkey, rnd, &recid) == 1) { + break; + } + } + /* Recover. */ + unsigned char recpubkey[65]; int recpubkeylen = 0; + CHECK(secp256k1_ecdsa_recover_compact(message, 32, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1); + CHECK(recpubkeylen == pubkeylen); + CHECK(memcmp(pubkey, recpubkey, pubkeylen) == 0); + /* Destroy signature and verify again. */ + csignature[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255); + CHECK(secp256k1_ecdsa_recover_compact(message, 32, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) != 1 || + memcmp(pubkey, recpubkey, pubkeylen) != 0); + CHECK(recpubkeylen == pubkeylen); + +} + +void run_ecdsa_end_to_end(void) { + for (int i=0; i<64*count; i++) { + test_ecdsa_end_to_end(); + } +} + +void test_ecdsa_infinity(void) { + const unsigned char msg32[32] = { + 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', + 'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', + 'e', 'c', 'r', 'e', 't', ' ', 'm', 'e', + 's', 's', 'a', 'g', 'e', '.', '.', '.' + }; + const unsigned char sig64[64] = { + // Generated by signing the above message with nonce 'This is the nonce we will use...' + // and secret key 0 (which is not valid), resulting in recid 0. + 0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8, + 0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96, + 0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63, + 0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32, + 0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E, + 0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD, + 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, + 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 + }; + unsigned char pubkey[65]; + int pubkeylen = 65; + CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 0)); + CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 1)); + CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 2)); + CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 3)); +} + +void run_ecdsa_infinity(void) { + test_ecdsa_infinity(); +} + +#ifdef ENABLE_OPENSSL_TESTS +EC_KEY *get_openssl_key(const secp256k1_scalar_t *key) { + unsigned char privkey[300]; + int privkeylen; + int compr = secp256k1_rand32() & 1; + const unsigned char* pbegin = privkey; + EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); + CHECK(secp256k1_eckey_privkey_serialize(privkey, &privkeylen, key, compr)); + CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); + CHECK(EC_KEY_check_key(ec_key)); + return ec_key; +} + +void test_ecdsa_openssl(void) { + secp256k1_scalar_t key, msg; + unsigned char message[32]; + secp256k1_rand256_test(message); + secp256k1_scalar_set_b32(&msg, message, NULL); + random_scalar_order_test(&key); + secp256k1_gej_t qj; + secp256k1_ecmult_gen(&qj, &key); + secp256k1_ge_t q; + secp256k1_ge_set_gej(&q, &qj); + EC_KEY *ec_key = get_openssl_key(&key); + CHECK(ec_key); + unsigned char signature[80]; + unsigned int sigsize = 80; + CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); + secp256k1_ecdsa_sig_t sig; + CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize)); + secp256k1_num_t msg_num; + secp256k1_scalar_get_num(&msg_num, &msg); + CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num)); + secp256k1_num_inc(&sig.r); + CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num)); + + random_sign(&sig, &key, &msg, NULL); + int secp_sigsize = 80; + CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sig)); + CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1); + + EC_KEY_free(ec_key); +} + +void run_ecdsa_openssl(void) { + for (int i=0; i<10*count; i++) { + test_ecdsa_openssl(); + } +} +#endif + +int main(int argc, char **argv) { + /* find iteration count */ + if (argc > 1) { + count = strtol(argv[1], NULL, 0); + } + + /* find random seed */ + uint64_t seed; + if (argc > 2) { + seed = strtoull(argv[2], NULL, 0); + } else { + FILE *frand = fopen("/dev/urandom", "r"); + if (!frand || !fread(&seed, sizeof(seed), 1, frand)) { + seed = time(NULL) * 1337; + } + fclose(frand); + } + secp256k1_rand_seed(seed); + + printf("test count = %i\n", count); + printf("random seed = %llu\n", (unsigned long long)seed); + + /* initialize */ + secp256k1_start(SECP256K1_START_SIGN | SECP256K1_START_VERIFY); + + /* num tests */ + run_num_smalltests(); + + /* scalar tests */ + run_scalar_tests(); + + /* field tests */ + run_field_inv(); + run_field_inv_var(); + run_field_inv_all(); + run_field_inv_all_var(); + run_sqr(); + run_sqrt(); + + /* group tests */ + run_ge(); + + /* ecmult tests */ + run_wnaf(); + run_point_times_order(); + run_ecmult_chain(); + + /* ecdsa tests */ + run_ecdsa_sign_verify(); + run_ecdsa_end_to_end(); + run_ecdsa_infinity(); +#ifdef ENABLE_OPENSSL_TESTS + run_ecdsa_openssl(); +#endif + + printf("random run = %llu\n", (unsigned long long)secp256k1_rand32() + ((unsigned long long)secp256k1_rand32() << 32)); + + /* shutdown */ + secp256k1_stop(); + return 0; +} diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h new file mode 100644 index 0000000000..96b47057c0 --- /dev/null +++ b/src/secp256k1/src/util.h @@ -0,0 +1,64 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_UTIL_H_ +#define _SECP256K1_UTIL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> + +#ifdef DETERMINISTIC +#define TEST_FAILURE(msg) do { \ + fprintf(stderr, "%s\n", msg); \ + abort(); \ +} while(0); +#else +#define TEST_FAILURE(msg) do { \ + fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \ + abort(); \ +} while(0) +#endif + +#ifndef HAVE_BUILTIN_EXPECT +#define EXPECT(x,c) __builtin_expect((x),(c)) +#else +#define EXPECT(x,c) (x) +#endif + +#ifdef DETERMINISTIC +#define CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + TEST_FAILURE("test condition failed"); \ + } \ +} while(0) +#else +#define CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + TEST_FAILURE("test condition failed: " #cond); \ + } \ +} while(0) +#endif + +/* Like assert(), but safe to use on expressions with side effects. */ +#ifndef NDEBUG +#define DEBUG_CHECK CHECK +#else +#define DEBUG_CHECK(cond) do { (void)(cond); } while(0) +#endif + +/* Like DEBUG_CHECK(), but when VERIFY is defined instead of NDEBUG not defined. */ +#ifdef VERIFY +#define VERIFY_CHECK CHECK +#else +#define VERIFY_CHECK(cond) do { (void)(cond); } while(0) +#endif + +#endif diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 68232a2ff1..26708f5071 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -2,14 +2,19 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "crypto/rfc6979_hmac_sha256.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" -#include "crypto/sha2.h" +#include "crypto/sha256.h" +#include "crypto/sha512.h" +#include "crypto/hmac_sha256.h" +#include "crypto/hmac_sha512.h" #include "random.h" #include "utilstrencodings.h" #include <vector> +#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> BOOST_AUTO_TEST_SUITE(crypto_tests) @@ -48,6 +53,11 @@ void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(C void TestSHA512(const std::string &in, const std::string &hexout) { TestVector(CSHA512(), in, ParseHex(hexout));} void TestRIPEMD160(const std::string &in, const std::string &hexout) { TestVector(CRIPEMD160(), in, ParseHex(hexout));} +void TestHMACSHA256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) { + std::vector<unsigned char> key = ParseHex(hexkey); + TestVector(CHMAC_SHA256(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout)); +} + void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const std::string &hexout) { std::vector<unsigned char> key = ParseHex(hexkey); TestVector(CHMAC_SHA512(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout)); @@ -158,6 +168,43 @@ BOOST_AUTO_TEST_CASE(sha512_testvectors) { "37de8c3ef5459d76a52cedc02dc499a3c9ed9dedbfb3281afd9653b8a112fafc"); } +BOOST_AUTO_TEST_CASE(hmac_sha256_testvectors) { + // test cases 1, 2, 3, 4, 6 and 7 of RFC 4231 + TestHMACSHA256("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "4869205468657265", + "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"); + TestHMACSHA256("4a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"); + TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" + "dddddddddddddddddddddddddddddddddddd", + "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"); + TestHMACSHA256("0102030405060708090a0b0c0d0e0f10111213141516171819", + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", + "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"); + TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaa", + "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" + "65204b6579202d2048617368204b6579204669727374", + "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"); + TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaa", + "5468697320697320612074657374207573696e672061206c6172676572207468" + "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" + "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" + "647320746f20626520686173686564206265666f7265206265696e6720757365" + "642062792074686520484d414320616c676f726974686d2e", + "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"); +} + BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { // test cases 1, 2, 3, 4, 6 and 7 of RFC 4231 TestHMACSHA512("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", @@ -201,4 +248,38 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"); } +void TestRFC6979(const std::string& hexkey, const std::string& hexmsg, const std::vector<std::string>& hexout) +{ + std::vector<unsigned char> key = ParseHex(hexkey); + std::vector<unsigned char> msg = ParseHex(hexmsg); + RFC6979_HMAC_SHA256 rng(&key[0], key.size(), &msg[0], msg.size()); + + for (unsigned int i = 0; i < hexout.size(); i++) { + std::vector<unsigned char> out = ParseHex(hexout[i]); + std::vector<unsigned char> gen; + gen.resize(out.size()); + rng.Generate(&gen[0], gen.size()); + BOOST_CHECK(out == gen); + } +} + +BOOST_AUTO_TEST_CASE(rfc6979_hmac_sha256) +{ + TestRFC6979( + "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f00", + "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a", + boost::assign::list_of + ("4fe29525b2086809159acdf0506efb86b0ec932c7ba44256ab321e421e67e9fb") + ("2bf0fff1d3c378a22dc5de1d856522325c65b504491a0cbd01cb8f3aa67ffd4a") + ("f528b410cb541f77000d7afb6c5b53c5c471eab43e466d9ac5190c39c82fd82e")); + + TestRFC6979( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + boost::assign::list_of + ("9c236c165b82ae0cd590659e100b6bab3036e7ba8b06749baf6981e16f1a2b95") + ("df471061625bc0ea14b682feee2c9c02f235da04204c1d62a1536c6e17aed7a9") + ("7597887cbd76321f32e30440679a22cf7f8d9d2eac390e581fea091ce202ba94")); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json index 6f451a36ee..c454b52976 100644 --- a/src/test/data/script_invalid.json +++ b/src/test/data/script_invalid.json @@ -163,6 +163,23 @@ nSequences are max. ["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC"], ["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC"], +["Ensure 100% coverage of discouraged NOPS"], +["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP2", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP8", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP9", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], +["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"], + +["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig"], + +["1 0x01 0xb9", "HASH160 0x14 0x15727299b05b45fdaf9ac9ecf7565cfe27c3e567 EQUAL", + "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"], + ["0x50","1", "P2SH,STRICTENC", "opcode 0x50 is reserved"], ["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"], ["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"], @@ -479,140 +496,177 @@ nSequences are max. ["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA"], +[" +Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of +pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded +signatures and pubkeys. +"], +[ + "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", + "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT", + "STRICTENC", + "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded." +], +[ + "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0", + "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", + "STRICTENC", + "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid." +], + +["Automatically generated test cases"], [ - "0x47 0x30440220304eff7556bba9560df47873275e64db45f3cd735998ce3f00d2e57b1bb5f31302205c0c9d14b8b80d43e2ac9b87532f1af6d8a3271262bc694ec4e14068392bb0a001", + "0x47 0x3044022053205076a7bb12d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "P2PK, bad sig" ], [ - "0x47 0x3044022037fcdb8e08f41e27588de8bc036d2c4b16eb3d09c1ba53b8f47a0a9c27722a39022058664b7a53b507e71dfafb77193e3786c3f0c119d78ce9104480ee7ece04f09301 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", + "0x47 0x30440220151ea78fa148b59f399b23731b634645ebc142f299ee9838d46fb78cf7e0bc0102200d62327dcd54ac6bcfb1516b035b1bf8eaea438c52c62d3450d1f3a8f030e0de01 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG", "", "P2PKH, bad pubkey" ], [ - "0x47 0x3044022035e5b6742d299861c84cebaf2ea64145ee427a95facab39e2594d6deebb0c1d602200acb16778faa2e467a59006f342f2535b1418d55ba63a8605b387b7f9ac86d9a01", + "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "P2PK anyonecanpay marked with normal hashtype" ], [ - "0x47 0x3044022029b2b8765ca950cf75a69e80b73b7ddfcaa8b27080c2db4c23b36aae60688e790220598ff368e17872ee065aa54d7d3a590682ca5204325b23b31d7da3c4a21ae67901 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", + "0x47 0x304402202166fcd5e607de452d3c6f15e059505cf21654346592f9650ba906b9e8be88fa022005d976d28eb8de477102feba28807b3ad361e7fa24796d259c9d61452f7c318c01 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", "P2SH", "P2SH(P2PK), bad redeemscript" ], [ - "0x47 0x30440220647f906e63890df5ef1d3fed47ba892b31976c634281079e2bd38504fb54a1fb022021e8811f38fbe90efb6b74cb78da01d9badbac3bafdf70a861d7538a220d0b2601 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", + "0x47 0x3044022064cc90ca89ad721384b231653b945579359a24b928ef8539b331172628c9cc6102203e238869ab5dac3fc293db53c12e7dd3079e86cfde9024b689efc7227e4d671001 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", "P2SH", "P2SH(P2PKH), bad sig" ], [ - "0 0x47 0x304402203ef170402f8887f2ac183f31b1f503b0bc60bfc968dd469b097ea6124aefac5002200612febadc4e4cacc086982cb85830a17af3680c1b6a3cf77c1708af7621cf1301 0 0x47 0x304402207821838251a24a2234844f68e7169e6d11945cdf052ea12bd3e4e37457aceb4402200b6b46c81361e314c740ae5133c072af5fa5c209d65d2db1679e1716f19a538101", + "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "3-of-3, 2 sigs" ], [ - "0 0 0x47 0x304402204661f7795e8db7be3132e8974e9a76d1d24b31f23df94c6fbcea07d1c205789102203f5e45a1c0b085279b58d11b36d5fea5449c3cf16f844ad10124e9b65e8777d201 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", + "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH", "P2SH(2-of-3), 1 sig" ], [ - "0x47 0x304402200052bc1600ca45c71f3538720fe62a5e8548dffd137af04467598c98466e9c0a0220789318ddbc9991ee477974089220a2feb6a6298a7c93d5ff6c25a92a2f4b48d501", + "0x47 0x30440220001d6702bfa4f49c3a2542af9b1c2844a2eaac55f86f310f42d26a5dd17d6a8002202cdadbe608c00b50dd951c6ba0877d5b07a970f3e265c18697bc413a0a86f69901", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "STRICTENC", + "DERSIG", "P2PK with too much R padding" ], [ - "0x48 0x304502206eb7b92628bfb3c4d2a04b65b986987bcbb1af4fceedb144d5a0437b7ee410590221005f57a52df4aa26366742eed0db182fce51fbcd7159011b0644a7c05943eb228901", + "0x48 0x304502207d2b258e959605e2ea50b46fea1325b7391ffb0c14a5b58ef8ad3851da3644380221007e75136df5f2e38216c4338b31c97e8307102edb97d611e06914e1f8fba68ead01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "STRICTENC", + "DERSIG", "P2PK with too much S padding" ], [ - "0x47 0x30440220d8ad1efd55a3d2b8896495c38aba72056e1b3ca4a6ca15760e843eb1a9b9907602203eb0e8f3d6bec998262dfd03eaeb0f31c4e5105965436dec77550724b3771f3201", + "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "STRICTENC", + "DERSIG", "P2PK with too little R padding" ], [ - "0x47 0x30440220001d0f82c127470cb38316c96b1719b33382353687a1146a776dee8259606905022062cd1fc8eacef819d68f0f41cc9ae9fdc2e29b70c3c7ad2c6c18f39b4e35c42701", + "0x47 0x30440220003040725f724b0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "DERSIG", "P2PK NOT with bad sig with too much R padding" ], [ - "0x47 0x30440220005d727e2a82d6e8a98a6da6fbc281325644d1a40455e386fdb17883a8e6bc4d02202d15cca42ce136047a980d288e60c679d7e84cce18c3ceffb6bc81b9e9ba517801", + "0x47 0x30440220003040725f724a0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "", "P2PK NOT with too much R padding but no DERSIG" ], [ - "0x47 0x30440220006e8bc4f82032b12bd594847c16d8b2986de734aa3b0528bd89d664d41e6d1c02200cfd582694891bcfa2e630e899bda257486eba00a007222fae71144dba07dc2901", + "0x47 0x30440220003040725f724a0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "DERSIG", "P2PK NOT with too much R padding" ], [ - "0x48 0x304502206c43e065c8a8db3bbe69015afb86a51fb2fc8870defd41d436da2a197d9d6c12022100fcec35816ee2d84ec271ad159fcabf5dd712157051169e48ac328a7818cdb51e01", + "0x49 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef05101", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", - "LOW_S,STRICTENC", + "LOW_S", "P2PK with high S" ], [ - "0x47 0x304402203aab50cd7c30cc1e1475dee615b295bcee6ccf8aa8a7f6cda6b696c70d79cbb40220558e43fe7596c31146e2d077698d5a9c38351d8ba567549a2ae43ca97231c39501", + "0x47 0x30440220745d63eb70d45652128b450aa5ca7d9b513439963f261cb1c40a60f0785e7ee402204877785b38945ca9dbec78e1c1d4dd12148cc25c868bd27480023b49ae0f310501", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "STRICTENC", "P2PK with hybrid pubkey" ], [ - "0x47 0x304402205745e8f846110c185ee1185c01843a108588b81463d2c34d4a3f2445529f12fe02206ee6a2657bbc4e2bb74bfc44c3a5c4f410ed6356ca68982465de6ca807c807c201", + "0x47 0x30440220606f6f9f6cebc94ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "", "P2PK NOT with hybrid pubkey but no STRICTENC" ], [ - "0x47 0x304402201f82b99a813c9c48c8dee8d2c43b8f637b72353fe9bdcc084537bc17e2ab770402200c43b96a5f7e115f0114eabda32e068145965cb6c7b5ef64833bb4fcf9fc1b3b05", + "0x47 0x30440220606f6f9f6cebc94ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", + "STRICTENC", + "P2PK NOT with hybrid pubkey" +], +[ + "0x47 0x30440220606f6f9f6cebc84ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", + "STRICTENC", + "P2PK NOT with invalid hybrid pubkey" +], +[ + "0 0x47 0x304402203cdcf66792fe97e3955655ede5dad004950e58b369831ffa7743132c507b272c022031fbcfb4a72b3e00217abf2f5557585f1f9891f12827d2f0a2ae2978e7f9f11001", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG", + "STRICTENC", + "1-of-2 with the first 1 hybrid pubkey" +], +[ + "0x47 0x304402201c215cb13e4954e60ce4f6de74941904c771f998de7b1d9627e82a1949fde517022031c2197455f3dbecbb78321201308d7b039424e38d480772d7cd4eb465a083f405", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "STRICTENC", "P2PK with undefined hashtype" ], [ - "0x47 0x30440220166848cd5b82a32b5944d90de3c35249354b43773c2ece1844ee8d1103e2f6c602203b6b046da4243c77adef80ada9201b27bbfdf7f9d5428f40434b060432afd62005", + "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", "STRICTENC", "P2PK NOT with invalid sig and undefined hashtype" ], [ - "0x01 0x01 0x47 0x304402200e48ba1cf4d7182db94ffb57bd72ea31b5545dc0d1c512e665779b4fb2badc52022054b8388dfc074c708a75b62359b7be46402751ee40c0a111aef38a837b6ed09801 0x47 0x304402201c9820f59c49107bb30e6175cfc9ec95f897b03beb628b4bc854d2b80392aa0602200235d986ae418bcd111b8814f4c26a0ab5f475fb542a44884fc14912a97a252301 0x47 0x304402204cd7894c6f10a871f5b0c1f9c13228f8cdd4050248f0d0f498ee86be69ee3080022051bd2932c7d585eb600c7194235c74da820935f0d67972fd9545673aa1fd023301", + "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "NULLDUMMY", "3-of-3 with nonzero dummy" ], [ - "0x01 0x01 0x47 0x304402201847fc3b8f7597768e7f543c58da1fca6e8e35eb28979431e6b637572ce6eaa4022048dd58608e040841d0bf52a70cfb70e1a9c8d2826fad068f4e9d2bf5c87766a501 0x47 0x30440220711311a72516affed73363763983d05c3d6a06a2eadf5d76b90b4354162ba94302204841a69e5955a7dc8e4ab3105fd0c86040c1dac6016297a51ddbf5079c28756801 0x47 0x30440220267e331a378191e7282fd10d61c97bf74bc97c233c5833d677936424ac08dee502201eee83d88b91988e1c4d9b979df2404aa190e0987a8ca09c4e5cd61da1d48ecc01", + "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", "NULLDUMMY", "3-of-3 NOT with invalid sig with nonzero dummy" ], [ - "0 0x47 0x3044022035341cc377b19138f944f90c45772cb06338c6d56a4c0c31a65bf1a8a105fadc022046dd232850b6bacb25879c9da82a7a628982aa19d055f1753468f68047662e0301 DUP", + "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 DUP", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "SIGPUSHONLY", "2-of-2 with two identical keys and sigs pushed using OP_DUP" ], [ - "0x47 0x304402204d8b99eea2f53382fd67e0dbc8ed0596bd614aa0dad6bc6843c7860c79b901c3022062f022a71993013e3d9b22302a8e4b40109d7bb057aeb250b9aab2197b3e96b801 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "", "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY" ], [ - "0x47 0x30440220078c887c33abc67fbbd827ceb3f661c1c459e78218161b652f23e3ca76cfabbd022047df245eacb8a88d8c5ca7b5228e3b4d070c102d2f542433362d3f443cd24eda01 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "SIGPUSHONLY", "P2SH(P2PK) with non-push scriptSig" diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json index 439c82ef32..af0f6939c6 100644 --- a/src/test/data/script_valid.json +++ b/src/test/data/script_valid.json @@ -235,6 +235,11 @@ nSequences are max. ["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC"], ["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC"], +["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "Discourage NOPx flag allows OP_NOP"], + +["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", + "Discouraged NOPs are allowed if not executed"], + ["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"], ["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"], ["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC"], @@ -659,135 +664,158 @@ nSequences are max. ["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", ""], ["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", ""], +[" +CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and +pubkeys in a specific order, and will exit early if the number of signatures +left to check is greater than the number of keys left. As STRICTENC fails the +script when it reaches an invalidly encoded signature or pubkey, we can use it +to test the exact order in which signatures and pubkeys are evaluated by +distinguishing CHECKMULTISIG returning false on the stack and the script as a +whole failing. +See also the corresponding inverted versions of these tests in script_invalid.json +"], +[ + "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", + "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", + "STRICTENC", + "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey." +], +[ + "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", + "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", + "STRICTENC", + "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature." +], +["Automatically generated test cases"], [ - "0x47 0x3044022007415aa37ce7eaa6146001ac8bdefca0ddcba0e37c5dc08c4ac99392124ebac802207d382307fd53f65778b07b9c63b6e196edeadf0be719130c5db21ff1e700d67501", + "0x47 0x3044022053205076a7bb13d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "P2PK" ], [ - "0x47 0x3044022069d40999786aeb2fd874f9eb2636461a062dc963471627ed8390a3a5f9556f640220350132a52415ce622f2aadd07f791c591500917ec1f8c5edbc5381ef7942534d01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", + "0x47 0x304402206e05a6fe23c59196ffe176c9ddc31e73a9885638f9d1328d47c0c703863b8876022076feb53811aa5b04e0e79f938eb19906cc5e67548bc555a8e8b8b0fc603d840c01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG", "", "P2PKH" ], [ - "0x47 0x30440220519f2a6632ffa134c7811ea2819e9dcc951f0c7baf461f2dffdd09133f3b080a02203ec6bab5eb6619ed7f41b8701d7c6d70cfc83bb26c5c97f54b2ca6e304fc2bb581", + "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "P2PK anyonecanpay" ], [ - "0x47 0x30440220279dad2170ffb5639f0a1ea71fc462ee37d75d420d86f84c978bac523c09b7f20220683b2789f5c5528a9e0a0d78f6e40db3f616cf1adb5a5fdef117d5974795cfe201 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", + "0x47 0x304402202166fcd5e607de452d3c6f15e059505cf21654346592f9650ba906b9e8be88fa022005d976d28eb8de477102feba28807b3ad361e7fa24796d259c9d61452f7c318c01 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", "P2SH", "P2SH(P2PK)" ], [ - "0x47 0x3044022066acbfb5ac96b7cbf3f05a2aaf358c32438c45d1d7359dee9fc1ee636940735f02205606a03fd8cbf6a6fcbcba60c8abb1e385c0b5753cb57a97538159106fd3684e01 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", + "0x47 0x3044022064cc90ca89ad721384b231653b945579359a24b928ef8539b331172628c9cc6102203e238869ab5dac3fc293db53c12e7dd3079e86cfde9024b689efc7227e4d671001 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", "", "P2SH(P2PKH), bad sig but no VERIFY_P2SH" ], [ - "0 0x47 0x3044022004e791dd30a64c70e55e84e150c002af9feb3ce0ab1f20e86c53d1209003927502205a60453987fcd72aebaaacebc8ce4b15449cdd79e54cc82cefb83e69dbcfeabf01 0x47 0x304402201d021808ce93dd8574cc4f99ae4f11b44305528b0aecbd9f156f08315173643802200944a0ea5c884bd86180aef76d8b1e444860776b251e47d2d6c651a1c6f9930801 0x47 0x30440220446336d7b7de05ebb5683b82b05248ec7d78e88ae8d6125985f5776c887a4cf90220674ab2b2c2f954ba1cf35457d273c90d0c0c1c224d0ae128628740e81129486801", + "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "3-of-3" ], [ - "0 0x47 0x30440220288b06d057cf0eac434ed0c3be9257cc0ca144dd99c11cc8f1a49467a37d8e8002203c496c72253c528e6bc81c42e683aba974d46041a96ef7b00915c863eb2a702901 0x47 0x304402207ffb4da33f40cac839a43000a187bd76a1ee5bf95e46dc1534b38bb7bd0321db022038c078f29d1831f8eb68ffdc2634c654fb01c3467b6457b98ad220653bb2478501 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", + "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x304402204511cf05e85c2be07c6c176c5338a08ed3cb34212667f39613340881169986c002207cc48b27aa3691a20706a5773ec9923cadd20fedffd00c24457d85f83f0b51fe01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH", "P2SH(2-of-3)" ], [ - "0x47 0x30440220001fff8863c84c0efc8eea5bffb7f388313f966f23a00ad3c0acc30ff5339684022016e6d78f51a3a1c362745931ca40b24f71cba2903dbfe5a6d392a9189127d83701", + "0x47 0x30440220001d6702bfa4f49c3a2542af9b1c2844a2eaac55f86f310f42d26a5dd17d6a8002202cdadbe608c00b50dd951c6ba0877d5b07a970f3e265c18697bc413a0a86f69901", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "P2PK with too much R padding but no DERSIG" ], [ - "0x48 0x304502202323d56f293842b544cacedd06baafb999196dfa1c2975314848c158ac606655022100514bd98186b8a3a1cc87f4aff76aed797781389f13f50d87bf95b2df6e488fcc01", + "0x48 0x304502207d2b258e959605e2ea50b46fea1325b7391ffb0c14a5b58ef8ad3851da3644380221007e75136df5f2e38216c4338b31c97e8307102edb97d611e06914e1f8fba68ead01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "P2PK with too much S padding but no DERSIG" ], [ - "0x47 0x30440220d31c24bb6c08a496e7698a08fd41975115d7b55bfaa31cb2d573e09481e59a6702206a691239996434076b78a4e1cf46fc8e993b468a9c77fb1832186aa8040a61a201", + "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "P2PK with too little R padding but no DERSIG" ], [ - "0x47 0x30440220007c2cc7aef1801c2937447703c87ef2a3744209ad98da2abadd4ba8bb2e3ea00220503a275582c9f9e9ff30260c81b7f64b8b696f22105605cc8241fb76a797316201", + "0x47 0x30440220003040725f724b0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "", "P2PK NOT with bad sig with too much R padding but no DERSIG" ], [ - "0x48 0x3045022021bf9184d94f208ac9f4757ebca9b1cbebf008cfc244fe5be1360b1b9aba0e92022100e55074f72f3a1bfddf2ea4ea7ba984f78822e136fe04c8f9c1363238e0233bd801", + "0x49 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef05101", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", - "STRICTENC", + "", "P2PK with high S but no LOW_S" ], [ - "0x47 0x304402202163bc732c21b7de0251297d3c6c2ece182782e85fc5e19d6036f1130a79051e022033827811634924ebba68767537d78dd7bd9109ae2a89a60587927abdc25eb06401", + "0x47 0x30440220745d63eb70d45652128b450aa5ca7d9b513439963f261cb1c40a60f0785e7ee402204877785b38945ca9dbec78e1c1d4dd12148cc25c868bd27480023b49ae0f310501", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "P2PK with hybrid pubkey but no STRICTENC" ], [ - "0x47 0x3044022078033e4227aa05ded69d8da579966578e230d8a7fb44d5f1a0620c3853c24f78022006a2e3f4d872ac8dfdc529110aa37301d65a76255a4b6cce2992adacd4d2c4e201", + "0x47 0x30440220606f6f9f6cebc84ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", - "STRICTENC", - "P2PK NOT with hybrid pubkey" + "", + "P2PK NOT with invalid hybrid pubkey but no STRICTENC" ], [ - "0x47 0x3044022078d6c447887e88dcbe1bc5b613645280df6f4e5935648bc226e9d91da71b3216022047d6b7ef0949b228fc1b359afb8d50500268711354298217b983c26970790c7601", - "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", + "0 0x47 0x304402203a5ee39032637c431af0a3ac42e32e0627390bd44f6f98c9c04e6d714635ad0202207b42fcd889c3ae8a1b515608f38535f1f9be815176ee8d1b65a27c767cf37aed01", + "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "", - "P2PK NOT with invalid hybrid pubkey but no STRICTENC" + "1-of-2 with the second 1 hybrid pubkey and no STRICTENC" ], [ - "0x47 0x304402207592427de20e315d644839754f2a5cca5b978b983a15e6da82109ede01722baa022032ceaf78590faa3f7743821e1b47b897ed1a57f6ee1c8a7519d23774d8de3c4401", - "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", + "0 0x47 0x304402203a5ee39032637c431af0a3ac42e32e0627390bd44f6f98c9c04e6d714635ad0202207b42fcd889c3ae8a1b515608f38535f1f9be815176ee8d1b65a27c767cf37aed01", + "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "STRICTENC", - "P2PK NOT with invalid hybrid pubkey" + "1-of-2 with the second 1 hybrid pubkey" ], [ - "0x47 0x304402204649e9517ef0377a8f8270bd423053fd98ddff62d74ea553e9579558abbb75e4022044a2b2344469c12e35ed898987711272b634733dd0f5e051288eceb04bd4669e05", + "0x47 0x304402201c215cb13e4954e60ce4f6de74941904c771f998de7b1d9627e82a1949fde517022031c2197455f3dbecbb78321201308d7b039424e38d480772d7cd4eb465a083f405", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "P2PK with undefined hashtype but no STRICTENC" ], [ - "0x47 0x304402207f1cf1866a2df0bb4b8d84d0ade72aa3abb6aaab0639d608b23d9e10ead0c48202203caa97f22c3439443eea4b89f7f6729854df0f567a8184d6ecc6e8b6c68c3e9d05", + "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", "", "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC" ], [ - "1 0x47 0x3044022046ce33d1771b0127dd4c4cef8fdc3218ebdfa60e3793ed700292d8ebd93fb1f402201029d47a414db83e96e31443c2d8b552f971469c4800f5eff7df2f0648521aed01 0x47 0x304402205c53911ad55b054920043962bbda98cf6e57e2db1cd5611138251490baabaa8702201dc80dfceae6007e7772dc13ff6e7ca66a983cb017fe5d46d30118462d83bcf801 0x47 0x304402201937e44a4ec12364f9d32f9d25e7ecbc68aee9ef90069af80efef4c05f6ace9602206c515101c00c75710b32ff7ff8dbaf7c9a0be6e86ed14a0755b47626604f31fd01", + "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "3-of-3 with nonzero dummy but no NULLDUMMY" ], [ - "1 0x47 0x30440220195038dbc6b2ae1199f86a6777824f7c5149789d85f655a3534a4422b8fba38c02204df9db87d2eb9fe06edc66870d9ac4c9ce673459f9d43cee0347ce4ffb02ee5a01 0x47 0x3044022010a45f30c6fa97a186eba9e6b595ab87d3dfcbf05dcaf1f1b8e3e7bf39515bb802203474e78d3d372e5f5c0f8c257ce8300c4bb8f37c51d4a894e11a91b5817da6ed01 0x47 0x30440220039cffd8e39850f95112662b1220b14b3c0d3d8a2772e13c947bfbf96345a64e02204154bfa77e2c0134d5434353bed82141e5da1cc479954aa288d5f0671480a04b01", + "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", "", "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY" ], [ - "0 0x47 0x3044022002a27769ee33db258bdf7a3792e7da4143ec4001b551f73e6a190b8d1bde449d02206742c56ccd94a7a2e16ca52fc1ae4a0aa122b0014a867a80de104f9cb18e472c01 DUP", + "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 DUP", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "", "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY" ], [ - "0 0x47 0x304402203acf75dd59bbef171aeeedae4f1020b824195820db82575c2b323b8899f95de9022067df297d3a5fad049ba0bb81255d0e495643cbcf9abae9e396988618bc0c6dfe01 0x47 0x304402205f8b859230c1cab7d4e8de38ff244d2ebe046b64e8d3f4219b01e483c203490a022071bdc488e31b557f7d9e5c8a8bec90dc92289ca70fa317685f4f140e38b30c4601", + "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "SIGPUSHONLY", "2-of-2 with two identical keys and sigs pushed" diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index b32f3774fe..43b18ce61e 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -8,6 +8,7 @@ #include "script/script.h" #include "uint256.h" #include "util.h" +#include "utilstrencodings.h" #include <string> #include <vector> @@ -82,6 +83,26 @@ BOOST_AUTO_TEST_CASE(key_test1) CPubKey pubkey1C = key1C.GetPubKey(); CPubKey pubkey2C = key2C.GetPubKey(); + BOOST_CHECK(key1.VerifyPubKey(pubkey1)); + BOOST_CHECK(!key1.VerifyPubKey(pubkey1C)); + BOOST_CHECK(!key1.VerifyPubKey(pubkey2)); + BOOST_CHECK(!key1.VerifyPubKey(pubkey2C)); + + BOOST_CHECK(!key1C.VerifyPubKey(pubkey1)); + BOOST_CHECK(key1C.VerifyPubKey(pubkey1C)); + BOOST_CHECK(!key1C.VerifyPubKey(pubkey2)); + BOOST_CHECK(!key1C.VerifyPubKey(pubkey2C)); + + BOOST_CHECK(!key2.VerifyPubKey(pubkey1)); + BOOST_CHECK(!key2.VerifyPubKey(pubkey1C)); + BOOST_CHECK(key2.VerifyPubKey(pubkey2)); + BOOST_CHECK(!key2.VerifyPubKey(pubkey2C)); + + BOOST_CHECK(!key2C.VerifyPubKey(pubkey1)); + BOOST_CHECK(!key2C.VerifyPubKey(pubkey1C)); + BOOST_CHECK(!key2C.VerifyPubKey(pubkey2)); + BOOST_CHECK(key2C.VerifyPubKey(pubkey2C)); + BOOST_CHECK(addr1.Get() == CTxDestination(pubkey1.GetID())); BOOST_CHECK(addr2.Get() == CTxDestination(pubkey2.GetID())); BOOST_CHECK(addr1C.Get() == CTxDestination(pubkey1C.GetID())); @@ -142,6 +163,28 @@ BOOST_AUTO_TEST_CASE(key_test1) BOOST_CHECK(rkey1C == pubkey1C); BOOST_CHECK(rkey2C == pubkey2C); } + + // test deterministic signing + + std::vector<unsigned char> detsig, detsigc; + string strMsg = "Very deterministic message"; + uint256 hashMsg = Hash(strMsg.begin(), strMsg.end()); + BOOST_CHECK(key1.Sign(hashMsg, detsig)); + BOOST_CHECK(key1C.Sign(hashMsg, detsigc)); + BOOST_CHECK(detsig == detsigc); + BOOST_CHECK(detsig == ParseHex("304402205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d022014ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6")); + BOOST_CHECK(key2.Sign(hashMsg, detsig)); + BOOST_CHECK(key2C.Sign(hashMsg, detsigc)); + BOOST_CHECK(detsig == detsigc); + BOOST_CHECK(detsig == ParseHex("3044022052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd5022061d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d")); + BOOST_CHECK(key1.SignCompact(hashMsg, detsig)); + BOOST_CHECK(key1C.SignCompact(hashMsg, detsigc)); + BOOST_CHECK(detsig == ParseHex("1c5dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6")); + BOOST_CHECK(detsigc == ParseHex("205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6")); + BOOST_CHECK(key2.SignCompact(hashMsg, detsig)); + BOOST_CHECK(key2C.SignCompact(hashMsg, detsigc)); + BOOST_CHECK(detsig == ParseHex("1c52d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d")); + BOOST_CHECK(detsigc == ParseHex("2052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d")); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index 78c4181409..bf57dd81d9 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "core/transaction.h" +#include "primitives/transaction.h" #include "main.h" #include <boost/test/unit_test.hpp> diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 9a31bdf5fd..53c2e7b261 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -57,6 +57,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) uint256 hash; LOCK(cs_main); + Checkpoints::fEnabled = false; // Simple block creation, nothing special yet: BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); @@ -259,6 +260,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) BOOST_FOREACH(CTransaction *tx, txFirst) delete tx; + Checkpoints::fEnabled = true; } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index ede13b23c2..4d2a9aff45 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -14,6 +14,10 @@ #include "script/sign.h" #include "util.h" +#if defined(HAVE_CONSENSUS_LIB) +#include "script/bitcoinconsensus.h" +#endif + #include <fstream> #include <stdint.h> #include <string> @@ -94,8 +98,15 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMu void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bool expect, const std::string& message) { ScriptError err; - BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, SignatureChecker(BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)), 0), &err) == expect, message); + CMutableTransaction tx = BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)); + CMutableTransaction tx2 = tx; + BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, SignatureChecker(tx, 0), &err) == expect, message); BOOST_CHECK_MESSAGE(expect == (err == SCRIPT_ERR_OK), std::string(ScriptErrorString(err)) + ": " + message); +#if defined(HAVE_CONSENSUS_LIB) + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << tx2; + BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(begin_ptr(scriptPubKey), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect,message); +#endif } void static NegateSignatureS(std::vector<unsigned char>& vchSig) { @@ -175,7 +186,6 @@ struct KeyData } }; -const KeyData keys; class TestBuilder { @@ -238,8 +248,9 @@ public: { uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType); std::vector<unsigned char> vchSig, r, s; + uint32_t iter = 0; do { - key.Sign(hash, vchSig); + key.Sign(hash, vchSig, iter++); if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) { NegateSignatureS(vchSig); } @@ -317,6 +328,8 @@ public: BOOST_AUTO_TEST_CASE(script_build) { + const KeyData keys; + std::vector<TestBuilder> good; std::vector<TestBuilder> bad; @@ -416,15 +429,24 @@ BOOST_AUTO_TEST_CASE(script_build) bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, "P2PK NOT with hybrid pubkey but no STRICTENC", 0 ).PushSig(keys.key0, SIGHASH_ALL)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with hybrid pubkey", SCRIPT_VERIFY_STRICTENC - ).PushSig(keys.key0, SIGHASH_ALL)); + bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with hybrid pubkey", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key0, SIGHASH_ALL)); good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, "P2PK NOT with invalid hybrid pubkey but no STRICTENC", 0 ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10)); - good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, - "P2PK NOT with invalid hybrid pubkey", SCRIPT_VERIFY_STRICTENC - ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10)); + bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, + "P2PK NOT with invalid hybrid pubkey", SCRIPT_VERIFY_STRICTENC + ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10)); + good.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, + "1-of-2 with the second 1 hybrid pubkey and no STRICTENC", 0 + ).Num(0).PushSig(keys.key1, SIGHASH_ALL)); + good.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG, + "1-of-2 with the second 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC + ).Num(0).PushSig(keys.key1, SIGHASH_ALL)); + bad.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0H) << OP_2 << OP_CHECKMULTISIG, + "1-of-2 with the first 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC + ).Num(0).PushSig(keys.key1, SIGHASH_ALL)); good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, "P2PK with undefined hashtype but no STRICTENC", 0 @@ -469,24 +491,18 @@ BOOST_AUTO_TEST_CASE(script_build) ).Num(0).PushSig(keys.key1).PushSig(keys.key1)); - std::map<std::string, Array> tests_good; - std::map<std::string, Array> tests_bad; + std::set<std::string> tests_good; + std::set<std::string> tests_bad; { Array json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); Array json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid))); BOOST_FOREACH(Value& tv, json_good) { - Array test = tv.get_array(); - if (test.size() >= 4) { - tests_good[test[3].get_str()] = test; - } + tests_good.insert(write_string(Value(tv.get_array()), true)); } BOOST_FOREACH(Value& tv, json_bad) { - Array test = tv.get_array(); - if (test.size() >= 4) { - tests_bad[test[3].get_str()] = test; - } + tests_bad.insert(write_string(Value(tv.get_array()), true)); } } @@ -495,27 +511,23 @@ BOOST_AUTO_TEST_CASE(script_build) BOOST_FOREACH(TestBuilder& test, good) { test.Test(true); - if (tests_good.count(test.GetComment()) == 0) { + std::string str = write_string(Value(test.GetJSON()), true); #ifndef UPDATE_JSON_TESTS + if (tests_good.count(str) == 0) { BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment()); -#endif - strGood += write_string(Value(test.GetJSON()), true) + ",\n"; - } else { - BOOST_CHECK_MESSAGE(ParseScript(tests_good[test.GetComment()][1].get_str()) == test.GetScriptPubKey(), "ScriptPubKey mismatch in auto script_valid test: " + test.GetComment()); - strGood += write_string(Value(tests_good[test.GetComment()]), true) + ",\n"; } +#endif + strGood += str + ",\n"; } BOOST_FOREACH(TestBuilder& test, bad) { test.Test(false); - if (tests_bad.count(test.GetComment()) == 0) { + std::string str = write_string(Value(test.GetJSON()), true); #ifndef UPDATE_JSON_TESTS + if (tests_bad.count(str) == 0) { BOOST_CHECK_MESSAGE(false, "Missing auto script_invalid test: " + test.GetComment()); -#endif - strBad += write_string(Value(test.GetJSON()), true) + ",\n"; - } else { - BOOST_CHECK_MESSAGE(ParseScript(tests_bad[test.GetComment()][1].get_str()) == test.GetScriptPubKey(), "ScriptPubKey mismatch in auto script_invalid test: " + test.GetComment()); - strBad += write_string(Value(tests_bad[test.GetComment()]), true) + ",\n"; } +#endif + strBad += str + ",\n"; } #ifdef UPDATE_JSON_TESTS diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index bf3a60c04f..e939e89972 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -37,7 +37,8 @@ static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of (string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S) (string("SIGPUSHONLY"), (unsigned int)SCRIPT_VERIFY_SIGPUSHONLY) (string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA) - (string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY); + (string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY) + (string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS); unsigned int ParseScriptFlags(string strFlags) { diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 67d50fccf4..10f77e3a5b 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -5,7 +5,7 @@ #include "util.h" #include "clientversion.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "random.h" #include "sync.h" #include "utilstrencodings.h" diff --git a/src/timedata.cpp b/src/timedata.cpp index 40cdb33f7a..59f7778db1 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "timedata.h" @@ -17,14 +17,13 @@ using namespace std; static CCriticalSection cs_nTimeOffset; static int64_t nTimeOffset = 0; -// -// "Never go to sea with two chronometers; take one or three." -// Our three time sources are: -// - System clock -// - Median of other nodes clocks -// - The user (asking the user to fix the system clock if the first two disagree) -// -// +/** + * "Never go to sea with two chronometers; take one or three." + * Our three time sources are: + * - System clock + * - Median of other nodes clocks + * - The user (asking the user to fix the system clock if the first two disagree) + */ int64_t GetTimeOffset() { LOCK(cs_nTimeOffset); diff --git a/src/timedata.h b/src/timedata.h index 2c20f4efd5..64595ffc37 100644 --- a/src/timedata.h +++ b/src/timedata.h @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_TIMEDATA_H @@ -12,7 +12,8 @@ class CNetAddr; -/** Median filter over a stream of values. +/** + * Median filter over a stream of values. * Returns the median of the last N numbers */ template <typename T> @@ -67,7 +68,7 @@ public: } }; -/* Functions to keep track of adjusted P2P time */ +/** Functions to keep track of adjusted P2P time */ int64_t GetTimeOffset(); int64_t GetAdjustedTime(); void AddTimeData(const CNetAddr& ip, int64_t nTime); diff --git a/src/txdb.h b/src/txdb.h index 147c186990..9a98fcc41b 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_TXDB_H @@ -17,11 +17,11 @@ class CCoins; class uint256; -// -dbcache default (MiB) +//! -dbcache default (MiB) static const int64_t nDefaultDbCache = 100; -// max. -dbcache in (MiB) +//! max. -dbcache in (MiB) static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 4096 : 1024; -// min. -dbcache in (MiB) +//! min. -dbcache in (MiB) static const int64_t nMinDbCache = 4; /** CCoinsView backed by the LevelDB coin database (chainstate/) */ diff --git a/src/txmempool.h b/src/txmempool.h index 0d3c8bba6a..d00bdd0616 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -10,16 +10,21 @@ #include "amount.h" #include "coins.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "sync.h" class CAutoFile; +inline double AllowFreeThreshold() +{ + return COIN * 144 / 250; +} + inline bool AllowFree(double dPriority) { // Large (in bytes) low-priority (new, small-coin) transactions // need a fee. - return dPriority > COIN * 144 / 250; + return dPriority > AllowFreeThreshold(); } /** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */ diff --git a/src/uint256.h b/src/uint256.h index 28de540226..56f7f44a16 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_UINT256_H @@ -255,8 +255,10 @@ public: return sizeof(pn); } - // Returns the position of the highest bit set plus one, or zero if the - // value is zero. + /** + * Returns the position of the highest bit set plus one, or zero if the + * value is zero. + */ unsigned int bits() const; uint64_t GetLow64() const @@ -301,26 +303,27 @@ public: uint256(uint64_t b) : base_uint<256>(b) {} explicit uint256(const std::string& str) : base_uint<256>(str) {} explicit uint256(const std::vector<unsigned char>& vch) : base_uint<256>(vch) {} - - // The "compact" format is a representation of a whole - // number N using an unsigned 32bit number similar to a - // floating point format. - // The most significant 8 bits are the unsigned exponent of base 256. - // This exponent can be thought of as "number of bytes of N". - // The lower 23 bits are the mantissa. - // Bit number 24 (0x800000) represents the sign of N. - // N = (-1^sign) * mantissa * 256^(exponent-3) - // - // Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). - // MPI uses the most significant bit of the first byte as sign. - // Thus 0x1234560000 is compact (0x05123456) - // and 0xc0de000000 is compact (0x0600c0de) - // (0x05c0de00) would be -0x40de000000 - // - // Bitcoin only uses this "compact" format for encoding difficulty - // targets, which are unsigned 256bit quantities. Thus, all the - // complexities of the sign bit and using base 256 are probably an - // implementation accident. + + /** + * The "compact" format is a representation of a whole + * number N using an unsigned 32bit number similar to a + * floating point format. + * The most significant 8 bits are the unsigned exponent of base 256. + * This exponent can be thought of as "number of bytes of N". + * The lower 23 bits are the mantissa. + * Bit number 24 (0x800000) represents the sign of N. + * N = (-1^sign) * mantissa * 256^(exponent-3) + * + * Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). + * MPI uses the most significant bit of the first byte as sign. + * Thus 0x1234560000 is compact (0x05123456) + * and 0xc0de000000 is compact (0x0600c0de) + * + * Bitcoin only uses this "compact" format for encoding difficulty + * targets, which are unsigned 256bit quantities. Thus, all the + * complexities of the sign bit and using base 256 are probably an + * implementation accident. + */ uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL); uint32_t GetCompact(bool fNegative = false) const; diff --git a/src/undo.h b/src/undo.h index 4f5f4047dd..2301bd8b43 100644 --- a/src/undo.h +++ b/src/undo.h @@ -7,7 +7,7 @@ #define BITCOIN_UNDO_H #include "compressor.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "serialize.h" /** Undo information for a CTxIn diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp index 085adae85e..3e076a0266 100644 --- a/src/utilmoneystr.cpp +++ b/src/utilmoneystr.cpp @@ -5,7 +5,7 @@ #include "utilmoneystr.h" -#include "core/transaction.h" +#include "primitives/transaction.h" #include "tinyformat.h" #include "utilstrencodings.h" diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index a961b3c5cd..d0062d4544 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -14,13 +14,13 @@ using namespace std; -/** - * safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything - * even possibly remotely dangerous like & or > - */ -static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@()"); string SanitizeString(const string& str) { + /** + * safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything + * even possibly remotely dangerous like & or > + */ + static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@()"); string strResult; for (std::string::size_type i = 0; i < str.size(); i++) { diff --git a/src/wallet.cpp b/src/wallet.cpp index ec439c5aad..27dbf61c2b 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -28,12 +28,14 @@ using namespace std; CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = 1; bool bSpendZeroConfChange = true; +bool fSendFreeTransactions = false; +bool fPayAtLeastCustomFee = true; /** * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) * Override with -mintxfee */ -CFeeRate CWallet::minTxFee = CFeeRate(10000); +CFeeRate CWallet::minTxFee = CFeeRate(1000); /** @defgroup mapWallet * @@ -77,6 +79,7 @@ CPubKey CWallet::GenerateNewKey() SetMinVersion(FEATURE_COMPRPUBKEY); CPubKey pubkey = secret.GetPubKey(); + assert(secret.VerifyPubKey(pubkey)); // Create new metadata int64_t nCreationTime = GetTime(); @@ -1382,7 +1385,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend, { LOCK2(cs_main, cs_wallet); { - nFeeRet = payTxFee.GetFeePerK(); + nFeeRet = 0; while (true) { txNew.vin.clear(); @@ -1502,7 +1505,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend, break; // Done, enough fee included. // Too big to send for free? Include more fee and try again: - if (nBytes > MAX_FREE_TRANSACTION_CREATE_SIZE) + if (!fSendFreeTransactions || nBytes > MAX_FREE_TRANSACTION_CREATE_SIZE) { nFeeRet = nFeeNeeded; continue; @@ -1628,6 +1631,12 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge { // payTxFee is user-set "I want to pay this much" CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes); + // prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee + if (nFeeNeeded > 0 && nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes)) + nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes); + // user selected total at least (default=true) + if (fPayAtLeastCustomFee && nFeeNeeded > 0 && nFeeNeeded < payTxFee.GetFeePerK()) + nFeeNeeded = payTxFee.GetFeePerK(); // User didn't set: use -txconfirmtarget to estimate... if (nFeeNeeded == 0) nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes); @@ -2021,7 +2030,7 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings() set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const { - AssertLockHeld(cs_wallet); // mapWallet + LOCK(cs_wallet); set<CTxDestination> result; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook) { diff --git a/src/wallet.h b/src/wallet.h index b692ad056b..70d274c2d5 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -7,8 +7,8 @@ #define BITCOIN_WALLET_H #include "amount.h" -#include "core/block.h" -#include "core/transaction.h" +#include "primitives/block.h" +#include "primitives/transaction.h" #include "crypter.h" #include "key.h" #include "keystore.h" @@ -32,6 +32,8 @@ extern CFeeRate payTxFee; extern unsigned int nTxConfirmTarget; extern bool bSpendZeroConfChange; +extern bool fSendFreeTransactions; +extern bool fPayAtLeastCustomFee; //! -paytxfee default static const CAmount DEFAULT_TRANSACTION_FEE = 0; |