From b150b09edcd3b6b7ca5f26ca6ebee92bbad97089 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 6 Jun 2014 10:23:34 -0400 Subject: [PATCH 1/3] secp256k1: add libtool as a dependency --- autogen.sh | 3 +++ configure.ac | 1 + contrib/debian/control | 1 + contrib/gitian-descriptors/gitian-osx-bitcoin.yml | 1 + doc/build-osx.md | 4 ++-- 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/autogen.sh b/autogen.sh index 5b883a6a4..50b85bcba 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,4 +2,7 @@ set -e srcdir="$(dirname $0)" cd "$srcdir" +if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="`which glibtoolize 2>/dev/null`"; then + export LIBTOOLIZE="${GLIBTOOLIZE}" +fi autoreconf --install --force diff --git a/configure.ac b/configure.ac index 811ef1dd8..925ac41ad 100644 --- a/configure.ac +++ b/configure.ac @@ -9,6 +9,7 @@ define(_COPYRIGHT_YEAR, 2014) AC_INIT([Bitcoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@bitcoin.org],[bitcoin]) AC_CONFIG_AUX_DIR([src/build-aux]) AC_CONFIG_MACRO_DIR([src/m4]) +LT_INIT([disable-shared]) AC_CANONICAL_HOST AH_TOP([#ifndef BITCOIN_CONFIG_H]) AH_TOP([#define BITCOIN_CONFIG_H]) diff --git a/contrib/debian/control b/contrib/debian/control index 9e006a707..a04e88d4e 100644 --- a/contrib/debian/control +++ b/contrib/debian/control @@ -6,6 +6,7 @@ Uploaders: Micah Anderson Build-Depends: debhelper, devscripts, automake, + libtool, bash-completion, libboost-system-dev (>> 1.35) | libboost-system1.35-dev, libdb4.8++-dev, diff --git a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml index 44b5de9be..bc3d561c3 100644 --- a/contrib/gitian-descriptors/gitian-osx-bitcoin.yml +++ b/contrib/gitian-descriptors/gitian-osx-bitcoin.yml @@ -11,6 +11,7 @@ packages: - "bsdmainutils" - "pkg-config" - "p7zip-full" +- "libtool" reference_datetime: "2013-06-01 00:00:00" remotes: diff --git a/doc/build-osx.md b/doc/build-osx.md index 1e38326d8..bc42723b1 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -41,7 +41,7 @@ Instructions: MacPorts ### Install dependencies - sudo port install boost db48@+no_java openssl miniupnpc autoconf pkgconfig automake + sudo port install boost db48@+no_java openssl miniupnpc autoconf pkgconfig automake libtool Optional: install Qt4 @@ -69,7 +69,7 @@ Instructions: Homebrew #### Install dependencies using Homebrew - brew install autoconf automake berkeley-db4 boost miniupnpc openssl pkg-config protobuf qt + brew install autoconf automake libtool berkeley-db4 boost miniupnpc openssl pkg-config protobuf qt Note: After you have installed the dependencies, you should check that the Homebrew installed version of OpenSSL is the one available for compilation. You can check this by typing From 556682663547f9a9ede69fc4f924b50c531d92b3 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 6 Jun 2014 10:57:28 -0400 Subject: [PATCH 2/3] secp256k1: Add build-side changes for libsecp256k1 Note: This is added to our existing automake targets rather than as a libtool-style lib. The switch to libtool-style targets can come later if it proves to not add any complications. --- Makefile.am | 1 + configure.ac | 1 + src/Makefile.am | 20 +++++++++++++++++++- src/Makefile.qt.include | 3 +++ src/Makefile.qttest.include | 3 +++ src/Makefile.test.include | 5 +++++ src/secp256k1/.empty | 0 7 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/secp256k1/.empty diff --git a/Makefile.am b/Makefile.am index 719af42ac..3a6a6b6d8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,6 +35,7 @@ COVERAGE_INFO = baseline_filtered_combined.info baseline.info block_test.info \ dist-hook: -$(MAKE) -C $(top_distdir)/src/leveldb clean + -$(MAKE) -C $(top_distdir)/src/secp256k1 distclean -$(GIT) archive --format=tar HEAD -- src/version.cpp | $(AMTAR) -C $(top_distdir) -xf - distcheck-hook: diff --git a/configure.ac b/configure.ac index 925ac41ad..2a4636e36 100644 --- a/configure.ac +++ b/configure.ac @@ -680,6 +680,7 @@ AM_CONDITIONAL([USE_LCOV],[test x$use_lcov == xyes]) AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno]) AM_CONDITIONAL([USE_COMPARISON_TOOL_REORG_TESTS],[test x$use_comparison_tool_reorg_test != xno]) AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) +AM_CONDITIONAL([USE_LIBSECP256K1],[test x$use_libsecp256k1 = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) diff --git a/src/Makefile.am b/src/Makefile.am index 9c7b294d3..e2a62c969 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,10 @@ AM_CPPFLAGS = $(INCLUDES) AM_LDFLAGS = $(PTHREAD_CFLAGS) +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 @@ -20,6 +24,10 @@ endif BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) +if USE_LIBSECP256K1 +BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include +endif + LIBBITCOIN_SERVER=libbitcoin_server.a LIBBITCOIN_WALLET=libbitcoin_wallet.a LIBBITCOIN_COMMON=libbitcoin_common.a @@ -220,6 +228,11 @@ bitcoind_LDADD = \ $(LIBBITCOIN_CRYPTO) \ $(LIBLEVELDB) \ $(LIBMEMENV) + +if USE_LIBSECP256K1 + bitcoind_LDADD += secp256k1/libsecp256k1.la +endif + if ENABLE_WALLET bitcoind_LDADD += libbitcoin_wallet.a endif @@ -242,6 +255,10 @@ bitcoin_cli_LDADD = \ $(BOOST_LIBS) bitcoin_cli_SOURCES = \ bitcoin-cli.cpp + +if USE_LIBSECP256K1 + bitcoin_cli_LDADD += secp256k1/libsecp256k1.la +endif bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES) # @@ -253,10 +270,11 @@ CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno DISTCLEANFILES = obj/build.h -EXTRA_DIST = leveldb +EXTRA_DIST = leveldb secp256k1 clean-local: -$(MAKE) -C leveldb clean + -$(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 9df0779ba..4563bb356 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -357,6 +357,9 @@ qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) $(LIBMEMENV) \ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) +if USE_LIBSECP256K1 + qt_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la +endif qt_bitcoin_qt_LDFLAGS = $(QT_LDFLAGS) #locale/foo.ts -> locale/foo.qm diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index a509f2375..7e10ce5a9 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -33,6 +33,9 @@ endif qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBLEVELDB) \ $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) +if USE_LIBSECP256K1 + qt_test_test_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la +endif qt_test_test_bitcoin_qt_LDFLAGS = $(QT_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 8685452c7..12b90adca 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -69,6 +69,11 @@ test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_CO 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) nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) diff --git a/src/secp256k1/.empty b/src/secp256k1/.empty new file mode 100644 index 000000000..e69de29bb From fda3fed18aedc4bfc8ccffe89d8d2cabb12677ab Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 6 Jun 2014 01:26:27 +0200 Subject: [PATCH 3/3] libsecp256k1 integration --- src/key.cpp | 130 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 119 insertions(+), 11 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 784085da3..3c4fa77e7 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -5,15 +5,34 @@ #include "key.h" #include "crypto/sha2.h" +#include +#ifdef USE_SECP256K1 +#include +#else #include #include #include -#include +#endif // anonymous namespace with local implementation code (OpenSSL interaction) namespace { +#ifdef USE_SECP256K1 +#include +class CSecp256k1Init { +public: + CSecp256k1Init() { + secp256k1_start(); + } + ~CSecp256k1Init() { + secp256k1_stop(); + } +}; +static CSecp256k1Init instance_of_csecp256k1; + +#else + // Generate a private key from just the secret parameter int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key) { @@ -334,6 +353,8 @@ public: } }; +#endif + int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) { while (c1len > c2len) { if (*c1) @@ -398,10 +419,15 @@ 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)) return false; key.GetSecretBytes(vch); +#endif fCompressed = fCompressedIn; fValid = true; return true; @@ -409,99 +435,167 @@ bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) { CPrivKey CKey::GetPrivKey() const { assert(fValid); + CPrivKey privkey; +#ifdef USE_SECP256K1 + privkey.resize(279); + int privkeylen = 279; + int ret = secp256k1_ecdsa_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed); + assert(ret); + privkey.resize(privkeylen); +#else CECKey key; key.SetSecretBytes(vch); - CPrivKey privkey; key.GetPrivKey(privkey, fCompressed); +#endif return privkey; } CPubKey CKey::GetPubKey() const { assert(fValid); + CPubKey pubkey; +#ifdef USE_SECP256K1 + int clen = 65; + int ret = secp256k1_ecdsa_pubkey_create((unsigned char*)pubkey.begin(), &clen, begin(), fCompressed); + assert(ret); + assert(pubkey.IsValid()); + assert((int)pubkey.size() == clen); +#else CECKey key; key.SetSecretBytes(vch); - CPubKey pubkey; key.GetPubKey(pubkey, fCompressed); +#endif return pubkey; } bool CKey::Sign(const uint256 &hash, std::vector& vchSig) const { if (!fValid) return false; +#ifdef USE_SECP256K1 + vchSig.resize(72); + int nSigLen = 72; + CKey nonce; + do { + nonce.MakeNewKey(true); + if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin())) + break; + } while(true); + vchSig.resize(nSigLen); + return true; +#else CECKey key; key.SetSecretBytes(vch); return key.Sign(hash, vchSig); +#endif } bool CKey::SignCompact(const uint256 &hash, std::vector& vchSig) const { if (!fValid) return false; - CECKey key; - key.SetSecretBytes(vch); vchSig.resize(65); int rec = -1; +#ifdef USE_SECP256K1 + CKey nonce; + do { + nonce.MakeNewKey(true); + if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec)) + 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())) + return false; +#else CECKey key; if (!key.SetPrivKey(privkey, fSkipCheck)) return false; - key.GetSecretBytes(vch); +#endif fCompressed = vchPubKey.IsCompressed(); fValid = true; - + if (fSkipCheck) return true; - + if (GetPubKey() != vchPubKey) return false; - + return true; } bool CPubKey::Verify(const uint256 &hash, const std::vector& vchSig) const { if (!IsValid()) return false; +#ifdef USE_SECP256K1 + if (secp256k1_ecdsa_verify((const unsigned char*)&hash, 32, &vchSig[0], vchSig.size(), begin(), size()) != 1) + return false; +#else CECKey key; if (!key.SetPubKey(*this)) return false; if (!key.Verify(hash, vchSig)) return false; +#endif return true; } bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector& vchSig) { if (vchSig.size() != 65) return false; + int recid = (vchSig[0] - 27) & 3; + bool fComp = (vchSig[0] - 27) & 4; +#ifdef USE_SECP256K1 + int pubkeylen = 65; + if (!secp256k1_ecdsa_recover_compact((const unsigned char*)&hash, 32, &vchSig[1], (unsigned char*)begin(), &pubkeylen, fComp, recid)) + return false; + assert((int)size() == pubkeylen); +#else CECKey key; - if (!key.Recover(hash, &vchSig[1], (vchSig[0] - 27) & ~4)) + if (!key.Recover(hash, &vchSig[1], recid)) return false; - key.GetPubKey(*this, (vchSig[0] - 27) & 4); + key.GetPubKey(*this, fComp); +#endif return true; } bool CPubKey::IsFullyValid() const { if (!IsValid()) return false; +#ifdef USE_SECP256K1 + if (!secp256k1_ecdsa_pubkey_verify(begin(), size())) + return false; +#else CECKey key; if (!key.SetPubKey(*this)) return false; +#endif return true; } bool CPubKey::Decompress() { if (!IsValid()) return false; +#ifdef USE_SECP256K1 + int clen = size(); + int ret = secp256k1_ecdsa_pubkey_decompress((unsigned char*)begin(), &clen); + assert(ret); + assert(clen == (int)size()); +#else CECKey key; if (!key.SetPubKey(*this)) return false; key.GetPubKey(*this, false); +#endif return true; } @@ -531,7 +625,12 @@ 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 UnlockObject(out); keyChild.fCompressed = true; keyChild.fValid = ret; @@ -545,10 +644,15 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned i unsigned char out[64]; BIP32Hash(cc, nChild, *begin(), begin()+1, out); memcpy(ccChild, out+32, 32); +#ifdef USE_SECP256K1 + pubkeyChild = *this; + bool ret = secp256k1_ecdsa_pubkey_tweak_add((unsigned char*)pubkeyChild.begin(), pubkeyChild.size(), out); +#else CECKey key; bool ret = key.SetPubKey(*this); ret &= key.TweakPublic(out); key.GetPubKey(pubkeyChild, true); +#endif return ret; } @@ -629,6 +733,9 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { } bool ECC_InitSanityCheck() { +#ifdef USE_SECP256K1 + return true; +#else EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if(pkey == NULL) return false; @@ -636,6 +743,7 @@ bool ECC_InitSanityCheck() { // TODO Is there more EC functionality that could be missing? return true; +#endif }