aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am97
-rw-r--r--src/Makefile.qt.include7
-rw-r--r--src/Makefile.qttest.include7
-rw-r--r--src/Makefile.test.include21
-rw-r--r--src/addrman.h6
-rw-r--r--src/alert.cpp7
-rw-r--r--src/alert.h6
-rw-r--r--src/base58.cpp4
-rw-r--r--src/base58.h25
-rw-r--r--src/bitcoin-cli.cpp114
-rw-r--r--src/bitcoind.cpp53
-rw-r--r--src/bloom.cpp21
-rw-r--r--src/bloom.h36
-rw-r--r--src/chain.h11
-rw-r--r--src/chainparams.cpp6
-rw-r--r--src/chainparams.h6
-rw-r--r--src/chainparamsbase.h6
-rw-r--r--src/chainparamsseeds.h11
-rw-r--r--src/checkpoints.cpp16
-rw-r--r--src/checkpoints.h19
-rw-r--r--src/checkqueue.h56
-rw-r--r--src/clientversion.h6
-rw-r--r--src/coincontrol.h10
-rw-r--r--src/coins.cpp14
-rw-r--r--src/coins.h115
-rw-r--r--src/compat.h14
-rw-r--r--src/compat/sanity.h6
-rw-r--r--src/compat/strnlen.cpp18
-rw-r--r--src/compressor.cpp2
-rw-r--r--src/compressor.h28
-rw-r--r--src/core/block.h6
-rw-r--r--src/core/transaction.h6
-rw-r--r--src/core_io.h8
-rw-r--r--src/core_read.cpp18
-rw-r--r--src/crypter.h59
-rw-r--r--src/crypto/ripemd160.h6
-rw-r--r--src/crypto/sha1.h6
-rw-r--r--src/crypto/sha2.h6
-rw-r--r--src/db.h8
-rw-r--r--src/eccryptoverify.cpp68
-rw-r--r--src/eccryptoverify.h21
-rw-r--r--src/ecwrapper.cpp174
-rw-r--r--src/ecwrapper.h28
-rw-r--r--src/hash.cpp17
-rw-r--r--src/hash.h4
-rw-r--r--src/init.cpp44
-rw-r--r--src/key.cpp283
-rw-r--r--src/key.h194
-rw-r--r--src/keystore.h1
-rw-r--r--src/leveldbwrapper.cpp3
-rw-r--r--src/leveldbwrapper.h20
-rw-r--r--src/main.cpp374
-rw-r--r--src/main.h42
-rw-r--r--src/miner.cpp33
-rw-r--r--src/miner.h2
-rw-r--r--src/net.cpp161
-rw-r--r--src/net.h4
-rw-r--r--src/pow.cpp16
-rw-r--r--src/pow.h5
-rw-r--r--src/protocol.h6
-rw-r--r--src/pubkey.cpp131
-rw-r--r--src/pubkey.h206
-rw-r--r--src/qt/addressbookpage.h6
-rw-r--r--src/qt/addresstablemodel.h6
-rw-r--r--src/qt/askpassphrasedialog.cpp7
-rw-r--r--src/qt/askpassphrasedialog.h6
-rw-r--r--src/qt/bitcoinaddressvalidator.h6
-rw-r--r--src/qt/bitcoinamountfield.cpp7
-rw-r--r--src/qt/bitcoinamountfield.h9
-rw-r--r--src/qt/bitcoingui.cpp8
-rw-r--r--src/qt/bitcoingui.h7
-rw-r--r--src/qt/bitcoinstrings.cpp10
-rw-r--r--src/qt/bitcoinunits.h6
-rw-r--r--src/qt/clientmodel.h6
-rw-r--r--src/qt/coincontroldialog.cpp95
-rw-r--r--src/qt/coincontroldialog.h8
-rw-r--r--src/qt/coincontroltreewidget.h6
-rw-r--r--src/qt/csvmodelwriter.h6
-rw-r--r--src/qt/editaddressdialog.h6
-rw-r--r--src/qt/forms/askpassphrasedialog.ui11
-rw-r--r--src/qt/forms/coincontroldialog.ui12
-rw-r--r--src/qt/forms/optionsdialog.ui82
-rw-r--r--src/qt/forms/rpcconsole.ui2
-rw-r--r--src/qt/forms/sendcoinsdialog.ui600
-rw-r--r--src/qt/guiconstants.h6
-rw-r--r--src/qt/guiutil.h23
-rw-r--r--src/qt/intro.h6
-rw-r--r--src/qt/locale/bitcoin_en.ts356
-rw-r--r--src/qt/macdockiconhandler.h6
-rw-r--r--src/qt/macnotificationhandler.h6
-rw-r--r--src/qt/macnotificationhandler.mm24
-rw-r--r--src/qt/networkstyle.h6
-rw-r--r--src/qt/notificator.h6
-rw-r--r--src/qt/openuridialog.h6
-rw-r--r--src/qt/optionsdialog.cpp25
-rw-r--r--src/qt/optionsdialog.h14
-rw-r--r--src/qt/optionsmodel.cpp24
-rw-r--r--src/qt/optionsmodel.h8
-rw-r--r--src/qt/overviewpage.h6
-rw-r--r--src/qt/paymentrequestplus.h7
-rw-r--r--src/qt/paymentserver.h7
-rw-r--r--src/qt/peertablemodel.h6
-rw-r--r--src/qt/qvalidatedlineedit.h6
-rw-r--r--src/qt/qvaluecombobox.h6
-rw-r--r--src/qt/receivecoinsdialog.h6
-rw-r--r--src/qt/receiverequestdialog.h6
-rw-r--r--src/qt/recentrequeststablemodel.h6
-rw-r--r--src/qt/rpcconsole.h6
-rw-r--r--src/qt/sendcoinsdialog.cpp206
-rw-r--r--src/qt/sendcoinsdialog.h19
-rw-r--r--src/qt/sendcoinsentry.h6
-rw-r--r--src/qt/signverifymessagedialog.h6
-rw-r--r--src/qt/splashscreen.h6
-rw-r--r--src/qt/test/paymentservertests.h6
-rw-r--r--src/qt/test/uritests.h6
-rw-r--r--src/qt/trafficgraphwidget.cpp8
-rw-r--r--src/qt/trafficgraphwidget.h6
-rw-r--r--src/qt/transactiondesc.h6
-rw-r--r--src/qt/transactiondescdialog.h6
-rw-r--r--src/qt/transactionfilterproxy.h6
-rw-r--r--src/qt/transactionrecord.h6
-rw-r--r--src/qt/transactiontablemodel.h6
-rw-r--r--src/qt/transactionview.h6
-rw-r--r--src/qt/utilitydialog.h6
-rw-r--r--src/qt/walletframe.h6
-rw-r--r--src/qt/walletmodel.cpp4
-rw-r--r--src/qt/walletmodel.h9
-rw-r--r--src/qt/walletmodeltransaction.cpp5
-rw-r--r--src/qt/walletmodeltransaction.h7
-rw-r--r--src/qt/walletview.cpp1
-rw-r--r--src/qt/walletview.h6
-rw-r--r--src/qt/winshutdownmonitor.h6
-rw-r--r--src/random.cpp5
-rw-r--r--src/random.h2
-rw-r--r--src/rest.cpp206
-rw-r--r--src/rpcblockchain.cpp10
-rw-r--r--src/rpcclient.cpp11
-rw-r--r--src/rpcclient.h10
-rw-r--r--src/rpcdump.cpp4
-rw-r--r--src/rpcmining.cpp153
-rw-r--r--src/rpcmisc.cpp30
-rw-r--r--src/rpcnet.cpp2
-rw-r--r--src/rpcprotocol.cpp34
-rw-r--r--src/rpcprotocol.h80
-rw-r--r--src/rpcrawtransaction.cpp2
-rw-r--r--src/rpcserver.cpp40
-rw-r--r--src/rpcserver.h27
-rw-r--r--src/rpcwallet.cpp6
-rw-r--r--src/script/bitcoinconsensus.cpp91
-rw-r--r--src/script/bitcoinconsensus.h67
-rw-r--r--src/script/interpreter.cpp376
-rw-r--r--src/script/interpreter.h29
-rw-r--r--src/script/script.h50
-rw-r--r--src/script/script_error.cpp71
-rw-r--r--src/script/script_error.h57
-rw-r--r--src/script/sigcache.cpp12
-rw-r--r--src/script/sigcache.h6
-rw-r--r--src/script/sign.cpp20
-rw-r--r--src/script/sign.h14
-rw-r--r--src/script/standard.cpp7
-rw-r--r--src/script/standard.h44
-rw-r--r--src/secp256k1/.gitignore35
-rw-r--r--src/secp256k1/.travis.yml25
-rw-r--r--src/secp256k1/COPYING19
-rw-r--r--src/secp256k1/Makefile.am88
-rw-r--r--src/secp256k1/README.md55
-rw-r--r--src/secp256k1/TODO3
-rwxr-xr-xsrc/secp256k1/autogen.sh3
-rw-r--r--src/secp256k1/build-aux/m4/bitcoin_secp.m490
-rw-r--r--src/secp256k1/configure.ac259
-rw-r--r--src/secp256k1/include/secp256k1.h252
-rw-r--r--src/secp256k1/libsecp256k1.pc.in13
-rwxr-xr-xsrc/secp256k1/nasm_lt.sh57
-rw-r--r--src/secp256k1/obj/.gitignore (renamed from src/secp256k1/.empty)0
-rw-r--r--src/secp256k1/src/bench_inv.c41
-rw-r--r--src/secp256k1/src/bench_sign.c49
-rw-r--r--src/secp256k1/src/bench_verify.c44
-rw-r--r--src/secp256k1/src/ecdsa.h23
-rw-r--r--src/secp256k1/src/ecdsa_impl.h183
-rw-r--r--src/secp256k1/src/eckey.h25
-rw-r--r--src/secp256k1/src/eckey_impl.h200
-rw-r--r--src/secp256k1/src/ecmult.h19
-rw-r--r--src/secp256k1/src/ecmult_gen.h19
-rw-r--r--src/secp256k1/src/ecmult_gen_impl.h118
-rw-r--r--src/secp256k1/src/ecmult_impl.h222
-rw-r--r--src/secp256k1/src/field.h114
-rw-r--r--src/secp256k1/src/field_10x26.h21
-rw-r--r--src/secp256k1/src/field_10x26_impl.h884
-rw-r--r--src/secp256k1/src/field_5x52.h21
-rw-r--r--src/secp256k1/src/field_5x52_asm.asm469
-rw-r--r--src/secp256k1/src/field_5x52_asm_impl.h13
-rw-r--r--src/secp256k1/src/field_5x52_impl.h260
-rw-r--r--src/secp256k1/src/field_5x52_int128_impl.h279
-rw-r--r--src/secp256k1/src/field_gmp.h18
-rw-r--r--src/secp256k1/src/field_gmp_impl.h163
-rw-r--r--src/secp256k1/src/field_impl.h293
-rw-r--r--src/secp256k1/src/group.h128
-rw-r--r--src/secp256k1/src/group_impl.h519
-rw-r--r--src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java60
-rw-r--r--src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c23
-rw-r--r--src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h21
-rw-r--r--src/secp256k1/src/num.h100
-rw-r--r--src/secp256k1/src/num_gmp.h20
-rw-r--r--src/secp256k1/src/num_gmp_impl.h376
-rw-r--r--src/secp256k1/src/num_impl.h22
-rw-r--r--src/secp256k1/src/scalar.h63
-rw-r--r--src/secp256k1/src/scalar_4x64.h17
-rw-r--r--src/secp256k1/src/scalar_4x64_impl.h359
-rw-r--r--src/secp256k1/src/scalar_8x32.h17
-rw-r--r--src/secp256k1/src/scalar_8x32_impl.h572
-rw-r--r--src/secp256k1/src/scalar_impl.h184
-rw-r--r--src/secp256k1/src/secp256k1.c305
-rw-r--r--src/secp256k1/src/testrand.h26
-rw-r--r--src/secp256k1/src/testrand_impl.h60
-rw-r--r--src/secp256k1/src/tests.c1080
-rw-r--r--src/secp256k1/src/util.h64
-rw-r--r--src/serialize.h178
-rw-r--r--src/test/alert_tests.cpp16
-rw-r--r--src/test/bignum.h6
-rw-r--r--src/test/data/script_invalid.json54
-rw-r--r--src/test/data/script_valid.json48
-rw-r--r--src/test/key_tests.cpp20
-rw-r--r--src/test/miner_tests.cpp5
-rw-r--r--src/test/multisig_tests.cpp37
-rw-r--r--src/test/script_P2SH_tests.cpp19
-rw-r--r--src/test/script_tests.cpp148
-rw-r--r--src/test/sigopcount_tests.cpp1
-rw-r--r--src/test/transaction_tests.cpp13
-rw-r--r--src/timedata.cpp17
-rw-r--r--src/timedata.h7
-rw-r--r--src/txdb.h16
-rw-r--r--src/txmempool.cpp42
-rw-r--r--src/txmempool.h51
-rw-r--r--src/uint256.h49
-rw-r--r--src/undo.h6
-rw-r--r--src/univalue/gen.cpp6
-rw-r--r--src/univalue/univalue.h6
-rw-r--r--src/univalue/univalue_escapes.h6
-rw-r--r--src/util.cpp48
-rw-r--r--src/util.h37
-rw-r--r--src/utilmoneystr.cpp2
-rw-r--r--src/utilmoneystr.h2
-rw-r--r--src/utilstrencodings.cpp14
-rw-r--r--src/utilstrencodings.h9
-rw-r--r--src/utiltime.cpp13
-rw-r--r--src/utiltime.h2
-rw-r--r--src/wallet.cpp21
-rw-r--r--src/wallet.h2
-rw-r--r--src/wallet_ismine.cpp1
-rw-r--r--src/wallet_ismine.h6
250 files changed, 12878 insertions, 2442 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8253c4ab14..3ec9e2f85d 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 =
@@ -86,6 +92,7 @@ BITCOIN_CORE_H = \
core_io.h \
crypter.h \
db.h \
+ eccryptoverify.h \
ecwrapper.h \
hash.h \
init.h \
@@ -101,6 +108,7 @@ BITCOIN_CORE_H = \
noui.h \
pow.h \
protocol.h \
+ pubkey.h \
random.h \
rpcclient.h \
rpcprotocol.h \
@@ -110,6 +118,7 @@ BITCOIN_CORE_H = \
script/sigcache.h \
script/sign.h \
script/standard.h \
+ script/script_error.h \
serialize.h \
streams.h \
sync.h \
@@ -163,12 +172,14 @@ libbitcoin_server_a_SOURCES = \
net.cpp \
noui.cpp \
pow.cpp \
+ rest.cpp \
rpcblockchain.cpp \
rpcmining.cpp \
rpcmisc.cpp \
rpcnet.cpp \
rpcrawtransaction.cpp \
rpcserver.cpp \
+ script/sigcache.cpp \
timedata.cpp \
txdb.cpp \
txmempool.cpp \
@@ -220,17 +231,19 @@ libbitcoin_common_a_SOURCES = \
core/transaction.cpp \
core_read.cpp \
core_write.cpp \
+ eccryptoverify.cpp \
ecwrapper.cpp \
hash.cpp \
key.cpp \
keystore.cpp \
netbase.cpp \
protocol.cpp \
+ pubkey.cpp \
script/interpreter.cpp \
script/script.cpp \
- script/sigcache.cpp \
script/sign.cpp \
script/standard.cpp \
+ script/script_error.cpp \
$(BITCOIN_CORE_H)
# util: shared between all executables.
@@ -238,6 +251,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 \
@@ -274,11 +288,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
@@ -292,25 +303,19 @@ 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 = \
$(LIBBITCOIN_CLI) \
- $(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
- $(LIBBITCOIN_CRYPTO) \
$(BOOST_LIBS) \
$(SSL_LIBS) \
- $(CRYPTO_LIBS) \
- $(MINIUPNPC_LIBS)
+ $(CRYPTO_LIBS)
bitcoin_cli_SOURCES = \
bitcoin-cli.cpp
-if USE_LIBSECP256K1
- bitcoin_cli_LDADD += secp256k1/libsecp256k1.la
-endif
bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES)
#
@@ -319,36 +324,60 @@ 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) \
- $(SSL_LIBS) \
- $(CRYPTO_LIBS) \
- $(MINIUPNPC_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 = \
+ core/transaction.cpp \
+ crypto/sha1.cpp \
+ crypto/sha2.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 340eb9f1a7..9e9f478d8f 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -42,8 +42,8 @@ BITCOIN_TESTS =\
test/bloom_tests.cpp \
test/checkblock_tests.cpp \
test/Checkpoints_tests.cpp \
- test/compress_tests.cpp \
test/coins_tests.cpp \
+ test/compress_tests.cpp \
test/crypto_tests.cpp \
test/DoS_tests.cpp \
test/getarg_tests.cpp \
@@ -58,7 +58,9 @@ BITCOIN_TESTS =\
test/rpc_tests.cpp \
test/script_P2SH_tests.cpp \
test/script_tests.cpp \
+ test/scriptnum_tests.cpp \
test/serialize_tests.cpp \
+ test/sighash_tests.cpp \
test/sigopcount_tests.cpp \
test/skiplist_tests.cpp \
test/test_bitcoin.cpp \
@@ -66,9 +68,7 @@ BITCOIN_TESTS =\
test/transaction_tests.cpp \
test/uint256_tests.cpp \
test/univalue_tests.cpp \
- test/util_tests.cpp \
- test/scriptnum_tests.cpp \
- test/sighash_tests.cpp
+ test/util_tests.cpp
if ENABLE_WALLET
BITCOIN_TESTS += \
@@ -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/addrman.h b/src/addrman.h
index 914086fc76..d47217683c 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef _BITCOIN_ADDRMAN
-#define _BITCOIN_ADDRMAN
+#ifndef BITCOIN_ADDRMAN_H
+#define BITCOIN_ADDRMAN_H
#include "netbase.h"
#include "protocol.h"
@@ -514,4 +514,4 @@ public:
}
};
-#endif // _BITCOIN_ADDRMAN
+#endif // BITCOIN_ADDRMAN_H
diff --git a/src/alert.cpp b/src/alert.cpp
index f16898dc38..64399a4260 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -1,14 +1,14 @@
// 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 "alert.h"
#include "chainparams.h"
#include "clientversion.h"
-#include "key.h"
#include "net.h"
+#include "pubkey.h"
#include "timedata.h"
#include "ui_interface.h"
#include "util.h"
@@ -128,6 +128,9 @@ bool CAlert::RelayTo(CNode* pnode) const
{
if (!IsInEffect())
return false;
+ // don't relay to nodes which haven't sent their version message
+ if (pnode->nVersion == 0)
+ return false;
// returns true if wasn't already contained in the set
if (pnode->setKnown.insert(GetHash()).second)
{
diff --git a/src/alert.h b/src/alert.h
index ba3235858d..96c203b557 100644
--- a/src/alert.h
+++ b/src/alert.h
@@ -3,8 +3,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef _BITCOINALERT_H_
-#define _BITCOINALERT_H_
+#ifndef BITCOIN_ALERT_H
+#define BITCOIN_ALERT_H
#include "serialize.h"
#include "sync.h"
@@ -110,4 +110,4 @@ public:
static CAlert getAlertByHash(const uint256 &hash);
};
-#endif // _BITCOINALERT_H_
+#endif // BITCOIN_ALERT_H
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 c5e230c72e..c4cb96814c 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -1,21 +1,22 @@
// 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
#include "chainparams.h"
#include "key.h"
+#include "pubkey.h"
#include "script/script.h"
#include "script/standard.h"
@@ -69,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 38fbc29faf..1b638e99e9 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -5,7 +5,6 @@
#include "chainparamsbase.h"
#include "clientversion.h"
-#include "init.h"
#include "rpcclient.h"
#include "rpcprotocol.h"
#include "util.h"
@@ -46,12 +45,41 @@ std::string HelpMessageCli()
//
// Start
//
+
+//
+// Exception thrown on connection error. This error is used to determine
+// when to wait if -rpcwait is given.
+//
+class CConnectionFailed : public std::runtime_error
+{
+public:
+
+ explicit inline CConnectionFailed(const std::string& msg) :
+ std::runtime_error(msg)
+ {}
+
+};
+
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;
@@ -67,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;
}
@@ -101,15 +115,9 @@ Object CallRPC(const string& strMethod, const Array& params)
SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
- bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started
- do {
- bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort())));
- if (fConnected) break;
- if (fWait)
- MilliSleep(1000);
- else
- throw runtime_error("couldn't connect to server");
- } while (fWait);
+ const bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort())));
+ if (!fConnected)
+ throw CConnectionFailed("couldn't connect to server");
// HTTP basic authentication
string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
@@ -168,27 +176,43 @@ int CommandLineRPC(int argc, char *argv[])
std::vector<std::string> strParams(&argv[2], &argv[argc]);
Array params = RPCConvertValues(strMethod, strParams);
- // Execute
- Object reply = CallRPC(strMethod, params);
-
- // Parse reply
- const Value& result = find_value(reply, "result");
- const Value& error = find_value(reply, "error");
-
- if (error.type() != null_type) {
- // Error
- strPrint = "error: " + write_string(error, false);
- int code = find_value(error.get_obj(), "code").get_int();
- nRet = abs(code);
- } else {
- // Result
- if (result.type() == null_type)
- strPrint = "";
- else if (result.type() == str_type)
- strPrint = result.get_str();
- else
- strPrint = write_string(result, true);
- }
+ // Execute and handle connection failures with -rpcwait
+ const bool fWait = GetBoolArg("-rpcwait", false);
+ do {
+ try {
+ const Object reply = CallRPC(strMethod, params);
+
+ // Parse reply
+ const Value& result = find_value(reply, "result");
+ const Value& error = find_value(reply, "error");
+
+ if (error.type() != null_type) {
+ // Error
+ const int code = find_value(error.get_obj(), "code").get_int();
+ if (fWait && code == RPC_IN_WARMUP)
+ throw CConnectionFailed("server in warmup");
+ strPrint = "error: " + write_string(error, false);
+ nRet = abs(code);
+ } else {
+ // Result
+ if (result.type() == null_type)
+ strPrint = "";
+ else if (result.type() == str_type)
+ strPrint = result.get_str();
+ else
+ strPrint = write_string(result, true);
+ }
+
+ // Connection succeeded, no need to retry.
+ break;
+ }
+ catch (const CConnectionFailed& e) {
+ if (fWait)
+ MilliSleep(1000);
+ else
+ throw;
+ }
+ } while (fWait);
}
catch (boost::thread_interrupted) {
throw;
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 c1e7aeb3bf..07b8f2c0ae 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -1,10 +1,11 @@
-// 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 "hash.h"
#include "script/script.h"
#include "script/standard.h"
#include "streams.h"
@@ -20,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 7c5603dafc..c01240665d 100644
--- a/src/chain.h
+++ b/src/chain.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 H_BITCOIN_CHAIN
-#define H_BITCOIN_CHAIN
+#ifndef BITCOIN_CHAIN_H
+#define BITCOIN_CHAIN_H
#include "core/block.h"
#include "pow.h"
@@ -220,11 +220,6 @@ public:
return (int64_t)nTime;
}
- uint256 GetBlockWork() const
- {
- return GetProofIncrement(nBits);
- }
-
enum { nMedianTimeSpan=11 };
int64_t GetMedianTimePast() const
@@ -409,4 +404,4 @@ public:
const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
};
-#endif // H_BITCOIN_CHAIN
+#endif // BITCOIN_CHAIN_H
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 9ffc369b40..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;
@@ -369,7 +364,6 @@ bool SelectParamsFromCommandLine()
if (network == CBaseChainParams::MAX_NETWORK_TYPES)
return false;
- SelectBaseParams(network);
SelectParams(network);
return true;
}
diff --git a/src/chainparams.h b/src/chainparams.h
index 9279edd6c0..9f24b70a26 100644
--- a/src/chainparams.h
+++ b/src/chainparams.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_CHAIN_PARAMS_H
-#define BITCOIN_CHAIN_PARAMS_H
+#ifndef BITCOIN_CHAINPARAMS_H
+#define BITCOIN_CHAINPARAMS_H
#include "chainparamsbase.h"
#include "checkpoints.h"
@@ -151,4 +151,4 @@ void SelectParams(CBaseChainParams::Network network);
*/
bool SelectParamsFromCommandLine();
-#endif // BITCOIN_CHAIN_PARAMS_H
+#endif // BITCOIN_CHAINPARAMS_H
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index 4042b8c879..eaf3fea1b6 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_CHAIN_PARAMS_BASE_H
-#define BITCOIN_CHAIN_PARAMS_BASE_H
+#ifndef BITCOIN_CHAINPARAMSBASE_H
+#define BITCOIN_CHAINPARAMSBASE_H
#include <string>
#include <vector>
@@ -62,4 +62,4 @@ bool SelectBaseParamsFromCommandLine();
*/
bool AreBaseParamsConfigured();
-#endif // BITCOIN_CHAIN_PARAMS_BASE_H
+#endif // BITCOIN_CHAINPARAMSBASE_H
diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h
index c3323c48bd..575e129334 100644
--- a/src/chainparamsseeds.h
+++ b/src/chainparamsseeds.h
@@ -1,10 +1,9 @@
-#ifndef H_CHAINPARAMSSEEDS
-#define H_CHAINPARAMSSEEDS
-
+#ifndef BITCOIN_CHAINPARAMSSEEDS_H
+#define BITCOIN_CHAINPARAMSSEEDS_H
/**
* List of fixed seed nodes for the bitcoin network
- * AUTOGENERATED by contrib/devtools/generate-seeds.py
- *
+ * AUTOGENERATED by share/seeds/generate-seeds.py
+ *
* Each line contains a 16-byte IPv6 address and a port.
* IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly.
*/
@@ -638,4 +637,4 @@ static SeedSpec6 pnSeed6_test[] = {
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xcb,0x26,0x31,0xba,0x48,0x51,0x31,0x39,0x0d}, 18333},
{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x44,0xf4,0xf4,0xf0,0xbf,0xf7,0x7e,0x6d,0xc4,0xe8}, 18333}
};
-#endif
+#endif // BITCOIN_CHAINPARAMSSEEDS_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 b5b620fa6b..65c5165f0f 100644
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -1,9 +1,9 @@
-// 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_CHECKPOINT_H
-#define BITCOIN_CHECKPOINT_H
+#ifndef BITCOIN_CHECKPOINTS_H
+#define BITCOIN_CHECKPOINTS_H
#include "uint256.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);
@@ -40,4 +41,4 @@ extern bool fEnabled;
} //namespace Checkpoints
-#endif // BITCOIN_CHECKPOINT_H
+#endif // BITCOIN_CHECKPOINTS_H
diff --git a/src/checkqueue.h b/src/checkqueue.h
index b2a713e646..2ee46a1210 100644
--- a/src/checkqueue.h
+++ b/src/checkqueue.h
@@ -1,9 +1,9 @@
-// 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 CHECKQUEUE_H
-#define CHECKQUEUE_H
+#ifndef BITCOIN_CHECKQUEUE_H
+#define BITCOIN_CHECKQUEUE_H
#include <algorithm>
#include <vector>
@@ -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
@@ -204,4 +208,4 @@ public:
}
};
-#endif // CHECKQUEUE_H
+#endif // BITCOIN_CHECKQUEUE_H
diff --git a/src/clientversion.h b/src/clientversion.h
index a187e185c1..0a36eb8012 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef CLIENTVERSION_H
-#define CLIENTVERSION_H
+#ifndef BITCOIN_CLIENTVERSION_H
+#define BITCOIN_CLIENTVERSION_H
#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
@@ -67,4 +67,4 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const
#endif // WINDRES_PREPROC
-#endif // CLIENTVERSION_H
+#endif // BITCOIN_CLIENTVERSION_H
diff --git a/src/coincontrol.h b/src/coincontrol.h
index c8f12d92de..c8bdd3b39d 100644
--- a/src/coincontrol.h
+++ b/src/coincontrol.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef COINCONTROL_H
-#define COINCONTROL_H
+#ifndef BITCOIN_COINCONTROL_H
+#define BITCOIN_COINCONTROL_H
#include "core/transaction.h"
@@ -35,12 +35,12 @@ public:
return (setSelected.count(outpt) > 0);
}
- void Select(COutPoint& output)
+ void Select(const COutPoint& output)
{
setSelected.insert(output);
}
- void UnSelect(COutPoint& output)
+ void UnSelect(const COutPoint& output)
{
setSelected.erase(output);
}
@@ -59,4 +59,4 @@ private:
std::set<COutPoint> setSelected;
};
-#endif // COINCONTROL_H
+#endif // BITCOIN_COINCONTROL_H
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 4fc28a36e0..dffd4ecf52 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -3,8 +3,12 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef _BITCOIN_COMPAT_H
-#define _BITCOIN_COMPAT_H
+#ifndef BITCOIN_COMPAT_H
+#define BITCOIN_COMPAT_H
+
+#if defined(HAVE_CONFIG_H)
+#include "config/bitcoin-config.h"
+#endif
#ifdef WIN32
#ifdef _WIN32_WINNT
@@ -84,4 +88,8 @@ typedef u_int SOCKET;
#define THREAD_PRIORITY_ABOVE_NORMAL (-2)
#endif
-#endif // _BITCOIN_COMPAT_H
+#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/sanity.h b/src/compat/sanity.h
index 7016ac0ab7..7f5bc1a4fb 100644
--- a/src/compat/sanity.h
+++ b/src/compat/sanity.h
@@ -2,10 +2,10 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCON_COMPAT_SANITY_H
-#define BITCON_COMPAT_SANITY_H
+#ifndef BITCOIN_COMPAT_SANITY_H
+#define BITCOIN_COMPAT_SANITY_H
bool glibc_sanity_test();
bool glibcxx_sanity_test();
-#endif // BITCON_COMPAT_SANITY_H
+#endif // BITCOIN_COMPAT_SANITY_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.cpp b/src/compressor.cpp
index 806175dd3e..c47a0f6f8c 100644
--- a/src/compressor.cpp
+++ b/src/compressor.cpp
@@ -6,7 +6,7 @@
#include "compressor.h"
#include "hash.h"
-#include "key.h"
+#include "pubkey.h"
#include "script/standard.h"
bool CScriptCompressor::IsToKeyID(CKeyID &hash) const
diff --git a/src/compressor.h b/src/compressor.h
index a612c3a883..d9cde5de7a 100644
--- a/src/compressor.h
+++ b/src/compressor.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 H_BITCOIN_COMPRESSOR
-#define H_BITCOIN_COMPRESSOR
+#ifndef BITCOIN_COMPRESSOR_H
+#define BITCOIN_COMPRESSOR_H
#include "core/transaction.h"
#include "script/script.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;
@@ -116,4 +120,4 @@ public:
}
};
-#endif // H_BITCOIN_COMPRESSOR
+#endif // BITCOIN_COMPRESSOR_H
diff --git a/src/core/block.h b/src/core/block.h
index f1eb7a844f..6e119c3699 100644
--- a/src/core/block.h
+++ b/src/core/block.h
@@ -3,8 +3,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef H_BITCOIN_CORE_BLOCK
-#define H_BITCOIN_CORE_BLOCK
+#ifndef BITCOIN_CORE_BLOCK_H
+#define BITCOIN_CORE_BLOCK_H
#include "core/transaction.h"
#include "serialize.h"
@@ -165,4 +165,4 @@ struct CBlockLocator
}
};
-#endif // H_BITCOIN_CORE_BLOCK
+#endif // BITCOIN_CORE_BLOCK_H
diff --git a/src/core/transaction.h b/src/core/transaction.h
index c21558cfeb..724348020a 100644
--- a/src/core/transaction.h
+++ b/src/core/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 H_BITCOIN_CORE_TRANSACTION
-#define H_BITCOIN_CORE_TRANSACTION
+#ifndef BITCOIN_CORE_TRANSACTION_H
+#define BITCOIN_CORE_TRANSACTION_H
#include "amount.h"
#include "script/script.h"
@@ -273,4 +273,4 @@ struct CMutableTransaction
uint256 GetHash() const;
};
-#endif // H_BITCOIN_CORE_TRANSACTION
+#endif // BITCOIN_CORE_TRANSACTION_H
diff --git a/src/core_io.h b/src/core_io.h
index 94848f1c3d..aba1928a36 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -2,12 +2,13 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef __BITCOIN_CORE_IO_H__
-#define __BITCOIN_CORE_IO_H__
+#ifndef BITCOIN_CORE_IO_H
+#define BITCOIN_CORE_IO_H
#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);
@@ -26,4 +28,4 @@ extern void ScriptPubKeyToUniv(const CScript& scriptPubKey,
UniValue& out, bool fIncludeHex);
extern void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry);
-#endif // __BITCOIN_CORE_IO_H__
+#endif // BITCOIN_CORE_IO_H
diff --git a/src/core_read.cpp b/src/core_read.cpp
index d39bc9a780..42e2f8d200 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -4,6 +4,7 @@
#include "core_io.h"
+#include "core/block.h"
#include "core/transaction.h"
#include "script/script.h"
#include "serialize.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/crypter.h b/src/crypter.h
index c7424c9b20..f7018cfdbe 100644
--- a/src/crypter.h
+++ b/src/crypter.h
@@ -1,33 +1,33 @@
-// 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 __CRYPTER_H__
-#define __CRYPTER_H__
+#ifndef BITCOIN_CRYPTER_H
+#define BITCOIN_CRYPTER_H
#include "allocators.h"
-#include "serialize.h"
#include "keystore.h"
+#include "serialize.h"
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,10 +189,11 @@ public:
}
}
- /* Wallet status (encrypted, locked) changed.
+ /**
+ * Wallet status (encrypted, locked) changed.
* Note: Called without locks held.
*/
boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
};
-#endif // __CRYPTER_H__
+#endif // BITCOIN_CRYPTER_H
diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h
index 902e7ca83f..f468ec6722 100644
--- a/src/crypto/ripemd160.h
+++ b/src/crypto/ripemd160.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_RIPEMD160_H
-#define BITCOIN_RIPEMD160_H
+#ifndef BITCOIN_CRYPTO_RIPEMD160_H
+#define BITCOIN_CRYPTO_RIPEMD160_H
#include <stdint.h>
#include <stdlib.h>
@@ -25,4 +25,4 @@ public:
CRIPEMD160& Reset();
};
-#endif // BITCOIN_RIPEMD160_H
+#endif // BITCOIN_CRYPTO_RIPEMD160_H
diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h
index 68bd7ced9f..e28f98decd 100644
--- a/src/crypto/sha1.h
+++ b/src/crypto/sha1.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_SHA1_H
-#define BITCOIN_SHA1_H
+#ifndef BITCOIN_CRYPTO_SHA1_H
+#define BITCOIN_CRYPTO_SHA1_H
#include <stdint.h>
#include <stdlib.h>
@@ -25,4 +25,4 @@ public:
CSHA1& Reset();
};
-#endif // BITCOIN_SHA1_H
+#endif // BITCOIN_CRYPTO_SHA1_H
diff --git a/src/crypto/sha2.h b/src/crypto/sha2.h
index a6cbe58554..329c6675ab 100644
--- a/src/crypto/sha2.h
+++ b/src/crypto/sha2.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_SHA2_H
-#define BITCOIN_SHA2_H
+#ifndef BITCOIN_CRYPTO_SHA2_H
+#define BITCOIN_CRYPTO_SHA2_H
#include <stdint.h>
#include <stdlib.h>
@@ -61,4 +61,4 @@ public:
void Finalize(unsigned char hash[OUTPUT_SIZE]);
};
-#endif // BITCOIN_SHA2_H
+#endif // BITCOIN_CRYPTO_SHA2_H
diff --git a/src/db.h b/src/db.h
index 85ffbae1cb..1c572d8970 100644
--- a/src/db.h
+++ b/src/db.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/eccryptoverify.cpp b/src/eccryptoverify.cpp
new file mode 100644
index 0000000000..435154d608
--- /dev/null
+++ b/src/eccryptoverify.cpp
@@ -0,0 +1,68 @@
+// 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 "eccryptoverify.h"
+
+namespace {
+
+int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) {
+ while (c1len > c2len) {
+ if (*c1)
+ return 1;
+ c1++;
+ c1len--;
+ }
+ while (c2len > c1len) {
+ if (*c2)
+ return -1;
+ c2++;
+ c2len--;
+ }
+ while (c1len > 0) {
+ if (*c1 > *c2)
+ return 1;
+ if (*c2 > *c1)
+ return -1;
+ c1++;
+ c2++;
+ c1len--;
+ }
+ return 0;
+}
+
+/** Order of secp256k1's generator minus 1. */
+const unsigned char vchMaxModOrder[32] = {
+ 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,0x40
+};
+
+/** Half of the order of secp256k1's generator minus 1. */
+const unsigned char vchMaxModHalfOrder[32] = {
+ 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D,
+ 0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0
+};
+
+const unsigned char vchZero[1] = {0};
+} // anon namespace
+
+namespace eccrypto {
+
+bool Check(const unsigned char *vch) {
+ return vch &&
+ CompareBigEndian(vch, 32, vchZero, 0) > 0 &&
+ CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0;
+}
+
+bool CheckSignatureElement(const unsigned char *vch, int len, bool half) {
+ return vch &&
+ CompareBigEndian(vch, len, vchZero, 0) > 0 &&
+ CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0;
+}
+
+} // namespace eccrypto
diff --git a/src/eccryptoverify.h b/src/eccryptoverify.h
new file mode 100644
index 0000000000..da7e80c7c3
--- /dev/null
+++ b/src/eccryptoverify.h
@@ -0,0 +1,21 @@
+// 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_ECCRYPTOVERIFY_H
+#define BITCOIN_ECCRYPTOVERIFY_H
+
+#include <vector>
+#include <cstdlib>
+
+class uint256;
+
+namespace eccrypto {
+
+bool Check(const unsigned char *vch);
+bool CheckSignatureElement(const unsigned char *vch, int len, bool half);
+
+} // eccrypto namespace
+
+#endif // BITCOIN_ECCRYPTOVERIFY_H
diff --git a/src/ecwrapper.cpp b/src/ecwrapper.cpp
index e5db670927..5ce7e61294 100644
--- a/src/ecwrapper.cpp
+++ b/src/ecwrapper.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 "ecwrapper.h"
@@ -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, bool lowS) {
- 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 (lowS && 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 072da4a942..4efde51650 100644
--- a/src/ecwrapper.h
+++ b/src/ecwrapper.h
@@ -1,9 +1,9 @@
// 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_EC_WRAPPER_H
-#define BITCOIN_EC_WRAPPER_H
+#ifndef BITCOIN_ECWRAPPER_H
+#define BITCOIN_ECWRAPPER_H
#include <cstddef>
#include <vector>
@@ -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,26 +21,20 @@ 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 lowS);
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();
};
-#endif
+#endif // BITCOIN_ECWRAPPER_H
diff --git a/src/hash.cpp b/src/hash.cpp
index 218607a6fd..2cca06ae23 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -1,3 +1,7 @@
+// Copyright (c) 2013-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 "hash.h"
inline uint32_t ROTL32(uint32_t x, int8_t r)
@@ -63,3 +67,16 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char
return h1;
}
+
+void BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64])
+{
+ unsigned char num[4];
+ num[0] = (nChild >> 24) & 0xFF;
+ num[1] = (nChild >> 16) & 0xFF;
+ num[2] = (nChild >> 8) & 0xFF;
+ num[3] = (nChild >> 0) & 0xFF;
+ CHMAC_SHA512(chainCode, 32).Write(&header, 1)
+ .Write(data, 32)
+ .Write(num, 4)
+ .Finalize(output);
+}
diff --git a/src/hash.h b/src/hash.h
index bdcd4afb47..75695160e6 100644
--- a/src/hash.h
+++ b/src/hash.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
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_HASH_H
@@ -159,4 +159,6 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
+void BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
+
#endif // BITCOIN_HASH_H
diff --git a/src/init.cpp b/src/init.cpp
index d622af69ef..b73c6e8722 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -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;
@@ -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";
@@ -320,7 +316,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += ".\n";
#ifdef ENABLE_WALLET
strUsage += " -gen " + strprintf(_("Generate coins (default: %u)"), 0) + "\n";
- strUsage += " -genproclimit=<n> " + strprintf(_("Set the processor limit for when generation is on (-1 = unlimited, default: %d)"), -1) + "\n";
+ strUsage += " -genproclimit=<n> " + strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1) + "\n";
#endif
strUsage += " -help-debug " + _("Show all debugging options (usage: --help -help-debug)") + "\n";
strUsage += " -logips " + strprintf(_("Include IP addresses in debug output (default: %u)"), 0) + "\n";
@@ -378,7 +374,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";
@@ -574,6 +570,9 @@ bool AppInit2(boost::thread_group& threadGroup)
// to protect privacy, do not listen by default if a default proxy server is specified
if (SoftSetBoolArg("-listen", false))
LogPrintf("AppInit2 : parameter interaction: -proxy set -> setting -listen=0\n");
+ // to protect privacy, do not discover addresses by default
+ if (SoftSetBoolArg("-discover", false))
+ LogPrintf("AppInit2 : parameter interaction: -proxy set -> setting -discover=0\n");
}
if (!GetBoolArg("-listen", true)) {
@@ -701,6 +700,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
@@ -746,12 +746,23 @@ bool AppInit2(boost::thread_group& threadGroup)
LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
std::ostringstream strErrors;
+ LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
if (nScriptCheckThreads) {
- LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
for (int i=0; i<nScriptCheckThreads-1; i++)
threadGroup.create_thread(&ThreadScriptCheck);
}
+ /* Start the RPC server already. It will be started in "warmup" mode
+ * and not really process calls already (but it will signify connections
+ * that the server is there and will be ready later). Warmup mode will
+ * be disabled when initialisation is finished.
+ */
+ if (fServer)
+ {
+ uiInterface.InitMessage.connect(SetRPCWarmupStatus);
+ StartRPCThreads();
+ }
+
int64_t nStart;
// ********************************************************* Step 5: verify wallet database integrity
@@ -838,10 +849,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;
}
@@ -1248,17 +1257,16 @@ bool AppInit2(boost::thread_group& threadGroup)
#endif
StartNode(threadGroup);
- if (fServer)
- StartRPCThreads();
#ifdef ENABLE_WALLET
// Generate coins in the background
if (pwalletMain)
- GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", -1));
+ GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1));
#endif
// ********************************************************* Step 11: finished
+ SetRPCWarmupFinished();
uiInterface.InitMessage(_("Done loading"));
#ifdef ENABLE_WALLET
diff --git a/src/key.cpp b/src/key.cpp
index c466e84f26..a91ed1cc1d 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -5,23 +5,20 @@
#include "key.h"
#include "crypto/sha2.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();
@@ -29,61 +26,10 @@ public:
};
static CSecp256k1Init instance_of_csecp256k1;
-#endif
-
-int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) {
- while (c1len > c2len) {
- if (*c1)
- return 1;
- c1++;
- c1len--;
- }
- while (c2len > c1len) {
- if (*c2)
- return -1;
- c2++;
- c2len--;
- }
- while (c1len > 0) {
- if (*c1 > *c2)
- return 1;
- if (*c2 > *c1)
- return -1;
- c1++;
- c2++;
- c1len--;
- }
- return 0;
-}
-
-/** Order of secp256k1's generator minus 1. */
-const unsigned char vchMaxModOrder[32] = {
- 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,0x40
-};
-
-/** Half of the order of secp256k1's generator minus 1. */
-const unsigned char vchMaxModHalfOrder[32] = {
- 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D,
- 0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0
-};
-
-const unsigned char vchZero[1] = {0};
-
} // anon namespace
bool CKey::Check(const unsigned char *vch) {
- return CompareBigEndian(vch, 32, vchZero, 0) > 0 &&
- CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0;
-}
-
-bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) {
- return CompareBigEndian(vch, len, vchZero, 0) > 0 &&
- CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0;
+ return eccrypto::Check(vch);
}
void CKey::MakeNewKey(bool fCompressedIn) {
@@ -95,15 +41,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;
@@ -113,47 +52,28 @@ 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, bool lowS) const {
+bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
if (!fValid)
return false;
-#ifdef USE_SECP256K1
vchSig.resize(72);
int nSigLen = 72;
CKey nonce;
@@ -164,11 +84,20 @@ bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, bool lo
} while(true);
vchSig.resize(nSigLen);
return true;
-#else
- CECKey key;
- key.SetSecretBytes(vch);
- return key.Sign(hash, vchSig, lowS);
-#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 {
@@ -176,126 +105,27 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
return false;
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[0], privkey.size(), fSkipCheck))
+ if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
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<unsigned char>& 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(begin(), size()))
- return false;
- if (!key.Verify(hash, vchSig))
- return false;
-#endif
- return true;
-}
-
-bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
- if (vchSig.size() != 65)
- return false;
- int recid = (vchSig[0] - 27) & 3;
- bool fComp = ((vchSig[0] - 27) & 4) != 0;
-#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], recid))
- return false;
- std::vector<unsigned char> pubkey;
- key.GetPubKey(pubkey, fComp);
- Set(pubkey.begin(), pubkey.end());
-#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(begin(), size()))
- 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(begin(), size()))
- return false;
- std::vector<unsigned char> pubkey;
- key.GetPubKey(pubkey, false);
- Set(pubkey.begin(), pubkey.end());
-#endif
- return true;
-}
-
-void static BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]) {
- unsigned char num[4];
- num[0] = (nChild >> 24) & 0xFF;
- num[1] = (nChild >> 16) & 0xFF;
- num[2] = (nChild >> 8) & 0xFF;
- num[3] = (nChild >> 0) & 0xFF;
- CHMAC_SHA512(chainCode, 32).Write(&header, 1)
- .Write(data, 32)
- .Write(num, 4)
- .Finalize(output);
+ return VerifyPubKey(vchPubKey);
}
bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
@@ -312,39 +142,14 @@ 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;
return ret;
}
-bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
- assert(IsValid());
- assert((nChild >> 31) == 0);
- assert(begin() + 33 == end());
- 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(begin(), size());
- ret &= key.TweakPublic(out);
- std::vector<unsigned char> pubkey;
- key.GetPubKey(pubkey, true);
- pubkeyChild.Set(pubkey.begin(), pubkey.end());
-#endif
- return ret;
-}
-
bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const {
out.nDepth = nDepth + 1;
CKeyID id = key.GetPubKey().GetID();
@@ -395,36 +200,14 @@ void CExtKey::Decode(const unsigned char code[74]) {
key.Set(code+42, code+74, true);
}
-void CExtPubKey::Encode(unsigned char code[74]) const {
- code[0] = nDepth;
- memcpy(code+1, vchFingerprint, 4);
- code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
- code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF;
- memcpy(code+9, vchChainCode, 32);
- assert(pubkey.size() == 33);
- memcpy(code+41, pubkey.begin(), 33);
-}
-
-void CExtPubKey::Decode(const unsigned char code[74]) {
- nDepth = code[0];
- memcpy(vchFingerprint, code+1, 4);
- nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
- memcpy(vchChainCode, code+9, 32);
- pubkey.Set(code+41, code+74);
-}
-
-bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
- out.nDepth = nDepth + 1;
- CKeyID id = pubkey.GetID();
- memcpy(&out.vchFingerprint[0], &id, 4);
- out.nChild = nChild;
- return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode);
-}
-
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);
}
diff --git a/src/key.h b/src/key.h
index b4cb647681..228cc42449 100644
--- a/src/key.h
+++ b/src/key.h
@@ -7,13 +7,16 @@
#define BITCOIN_KEY_H
#include "allocators.h"
-#include "hash.h"
#include "serialize.h"
#include "uint256.h"
#include <stdexcept>
#include <vector>
+class CPubKey;
+
+struct CExtPubKey;
+
/**
* secp256k1:
* const unsigned int PRIVATE_KEY_SIZE = 279;
@@ -24,169 +27,6 @@
* script supports up to 75 for single byte push
*/
-/** A reference to a CKey: the Hash160 of its serialized public key */
-class CKeyID : public uint160
-{
-public:
- CKeyID() : uint160(0) {}
- CKeyID(const uint160& in) : uint160(in) {}
-};
-
-/** An encapsulated public key. */
-class CPubKey
-{
-private:
-
- /**
- * Just store the serialized data.
- * Its length can very cheaply be computed from the first byte.
- */
- unsigned char vch[65];
-
- //! Compute the length of a pubkey with a given first byte.
- unsigned int static GetLen(unsigned char chHeader)
- {
- if (chHeader == 2 || chHeader == 3)
- return 33;
- if (chHeader == 4 || chHeader == 6 || chHeader == 7)
- return 65;
- return 0;
- }
-
- //! Set this key data to be invalid
- void Invalidate()
- {
- vch[0] = 0xFF;
- }
-
-public:
- //! Construct an invalid public key.
- CPubKey()
- {
- Invalidate();
- }
-
- //! Initialize a public key using begin/end iterators to byte data.
- template <typename T>
- void Set(const T pbegin, const T pend)
- {
- int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
- if (len && len == (pend - pbegin))
- memcpy(vch, (unsigned char*)&pbegin[0], len);
- else
- Invalidate();
- }
-
- //! Construct a public key using begin/end iterators to byte data.
- template <typename T>
- CPubKey(const T pbegin, const T pend)
- {
- Set(pbegin, pend);
- }
-
- //! Construct a public key from a byte vector.
- CPubKey(const std::vector<unsigned char>& vch)
- {
- Set(vch.begin(), vch.end());
- }
-
- //! Simple read-only vector-like interface to the pubkey data.
- unsigned int size() const { return GetLen(vch[0]); }
- const unsigned char* begin() const { return vch; }
- const unsigned char* end() const { return vch + size(); }
- const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
-
- //! Comparator implementation.
- friend bool operator==(const CPubKey& a, const CPubKey& b)
- {
- return a.vch[0] == b.vch[0] &&
- memcmp(a.vch, b.vch, a.size()) == 0;
- }
- friend bool operator!=(const CPubKey& a, const CPubKey& b)
- {
- return !(a == b);
- }
- friend bool operator<(const CPubKey& a, const CPubKey& b)
- {
- return a.vch[0] < b.vch[0] ||
- (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
- }
-
- //! Implement serialization, as if this was a byte vector.
- unsigned int GetSerializeSize(int nType, int nVersion) const
- {
- return size() + 1;
- }
- template <typename Stream>
- void Serialize(Stream& s, int nType, int nVersion) const
- {
- unsigned int len = size();
- ::WriteCompactSize(s, len);
- s.write((char*)vch, len);
- }
- template <typename Stream>
- void Unserialize(Stream& s, int nType, int nVersion)
- {
- unsigned int len = ::ReadCompactSize(s);
- if (len <= 65) {
- s.read((char*)vch, len);
- } else {
- // invalid pubkey, skip available data
- char dummy;
- while (len--)
- s.read(&dummy, 1);
- Invalidate();
- }
- }
-
- //! Get the KeyID of this public key (hash of its serialization)
- CKeyID GetID() const
- {
- return CKeyID(Hash160(vch, vch + size()));
- }
-
- //! Get the 256-bit hash of this public key.
- uint256 GetHash() const
- {
- return Hash(vch, vch + size());
- }
-
- /*
- * Check syntactic correctness.
- *
- * Note that this is consensus critical as CheckSig() calls it!
- */
- bool IsValid() const
- {
- return size() > 0;
- }
-
- //! fully validate whether this is a valid public key (more expensive than IsValid())
- bool IsFullyValid() const;
-
- //! Check whether this is a compressed public key.
- bool IsCompressed() const
- {
- return size() == 33;
- }
-
- /**
- * Verify a DER signature (~72 bytes).
- * If this public key is not fully valid, the return value will be false.
- */
- bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
-
- //! Recover a public key from a compact signature.
- bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
-
- //! Turn this public key into an uncompressed public key.
- bool Decompress();
-
- //! Derive BIP32 child pubkey.
- bool Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
-};
-
-
/**
* secure_allocator is defined in allocators.h
* CPrivKey is a serialized private key, with all parameters included (279 bytes)
@@ -283,7 +123,7 @@ public:
CPubKey GetPubKey() const;
//! Create a DER-serialized signature.
- bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, bool lowS = true) const;
+ bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig) const;
/**
* Create a compact signature (65 bytes), which allows reconstructing the used public key.
@@ -297,6 +137,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);
@@ -304,24 +150,6 @@ public:
static bool CheckSignatureElement(const unsigned char* vch, int len, bool half);
};
-struct CExtPubKey {
- unsigned char nDepth;
- unsigned char vchFingerprint[4];
- unsigned int nChild;
- unsigned char vchChainCode[32];
- CPubKey pubkey;
-
- friend bool operator==(const CExtPubKey& a, const CExtPubKey& b)
- {
- return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild &&
- memcmp(&a.vchChainCode[0], &b.vchChainCode[0], 32) == 0 && a.pubkey == b.pubkey;
- }
-
- void Encode(unsigned char code[74]) const;
- void Decode(const unsigned char code[74]);
- bool Derive(CExtPubKey& out, unsigned int nChild) const;
-};
-
struct CExtKey {
unsigned char nDepth;
unsigned char vchFingerprint[4];
diff --git a/src/keystore.h b/src/keystore.h
index 66f8771d4a..60502e9a29 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -7,6 +7,7 @@
#define BITCOIN_KEYSTORE_H
#include "key.h"
+#include "pubkey.h"
#include "sync.h"
#include <boost/signals2/signal.hpp>
diff --git a/src/leveldbwrapper.cpp b/src/leveldbwrapper.cpp
index 8ce3e7b470..70980fede5 100644
--- a/src/leveldbwrapper.cpp
+++ b/src/leveldbwrapper.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2012-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 "leveldbwrapper.h"
@@ -7,6 +7,7 @@
#include "util.h"
#include <boost/filesystem.hpp>
+
#include <leveldb/cache.h>
#include <leveldb/env.h>
#include <leveldb/filter_policy.h>
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 ac65a4ac2f..bda2ee7f7b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -128,6 +128,14 @@ namespace {
};
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
+ // Number of preferrable block download peers.
+ int nPreferredDownload = 0;
+
+ // Dirty block index entries.
+ set<CBlockIndex*> setDirtyBlockIndex;
+
+ // Dirty block file entries.
+ set<int> setDirtyFileInfo;
} // anon namespace
//////////////////////////////////////////////////////////////////////////////
@@ -152,6 +160,8 @@ struct CMainSignals {
boost::signals2::signal<void (const uint256 &)> Inventory;
// Tells listeners to broadcast their data.
boost::signals2::signal<void ()> Broadcast;
+ // Notifies listeners of a block validation result
+ boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
} g_signals;
} // anon namespace
@@ -163,9 +173,11 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn));
+ g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
}
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
+ g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn));
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
@@ -175,6 +187,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
}
void UnregisterAllValidationInterfaces() {
+ g_signals.BlockChecked.disconnect_all_slots();
g_signals.Broadcast.disconnect_all_slots();
g_signals.Inventory.disconnect_all_slots();
g_signals.SetBestChain.disconnect_all_slots();
@@ -225,6 +238,8 @@ struct CNodeState {
int64_t nStallingSince;
list<QueuedBlock> vBlocksInFlight;
int nBlocksInFlight;
+ // Whether we consider this a preferred download peer.
+ bool fPreferredDownload;
CNodeState() {
nMisbehavior = 0;
@@ -235,6 +250,7 @@ struct CNodeState {
fSyncStarted = false;
nStallingSince = 0;
nBlocksInFlight = 0;
+ fPreferredDownload = false;
}
};
@@ -255,6 +271,16 @@ int GetHeight()
return chainActive.Height();
}
+void UpdatePreferredDownload(CNode* node, CNodeState* state)
+{
+ nPreferredDownload -= state->fPreferredDownload;
+
+ // Whether this node should be marked as a preferred download node.
+ state->fPreferredDownload = (!node->fInbound || node->fWhitelisted) && !node->fOneShot && !node->fClient;
+
+ nPreferredDownload += state->fPreferredDownload;
+}
+
void InitializeNode(NodeId nodeid, const CNode *pnode) {
LOCK(cs_main);
CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
@@ -271,6 +297,7 @@ void FinalizeNode(NodeId nodeid) {
BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight)
mapBlocksInFlight.erase(entry.hash);
EraseOrphansFor(nodeid);
+ nPreferredDownload -= state->fPreferredDownload;
mapNodeState.erase(nodeid);
}
@@ -1116,11 +1143,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;
}
@@ -1205,15 +1227,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(),
@@ -1256,7 +1278,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;
@@ -1314,7 +1336,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);
}
@@ -1572,7 +1594,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
@@ -1711,10 +1733,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)
@@ -1738,10 +1757,23 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
return true;
}
-// Update the on-disk chain state.
-bool static WriteChainState(CValidationState &state) {
+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 (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
@@ -1749,15 +1781,44 @@ bool static WriteChainState(CValidationState &state) {
// 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;
}
+void FlushStateToDisk() {
+ CValidationState state;
+ FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
+}
+
// Update chainActive and related internal data structures.
void static UpdateTip(CBlockIndex *pindexNew) {
chainActive.SetTip(pindexNew);
@@ -1816,7 +1877,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) {
@@ -1864,7 +1925,9 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
{
CCoinsViewCache view(pcoinsTip);
CInv inv(MSG_BLOCK, pindexNew->GetBlockHash());
- if (!ConnectBlock(*pblock, state, pindexNew, view)) {
+ bool rv = ConnectBlock(*pblock, state, pindexNew, view);
+ g_signals.BlockChecked(*pblock, state);
+ if (!rv) {
if (state.IsInvalid())
InvalidBlockFound(pindexNew, state);
return error("ConnectTip() : ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
@@ -1877,7 +1940,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);
@@ -1896,10 +1959,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);
@@ -2024,9 +2083,6 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
else
CheckForkWarningConditions();
- if (!pblocktree->Flush())
- return state.Abort("Failed to sync block index");
-
return true;
}
@@ -2067,11 +2123,16 @@ 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;
}
@@ -2099,13 +2160,12 @@ 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;
}
@@ -2124,6 +2184,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.
@@ -2143,15 +2204,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;
@@ -2159,8 +2216,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;
@@ -2176,7 +2231,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;
@@ -2203,11 +2257,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;
}
@@ -2220,9 +2270,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;
@@ -2261,6 +2309,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;
@@ -2315,6 +2365,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);
@@ -2332,46 +2449,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);
@@ -2396,36 +2488,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);
@@ -2508,7 +2580,7 @@ void CBlockIndex::BuildSkip()
pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
}
-bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
+bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
{
// Preliminary checks
bool checked = CheckBlock(*pblock, state);
@@ -2517,7 +2589,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
LOCK(cs_main);
MarkBlockAsReceived(pblock->GetHash());
if (!checked) {
- return error("ProcessBlock() : CheckBlock FAILED");
+ return error("%s : CheckBlock FAILED", __func__);
}
// Store to disk
@@ -2527,11 +2599,35 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
}
if (!ret)
- return error("ProcessBlock() : AcceptBlock FAILED");
+ return error("%s : AcceptBlock FAILED", __func__);
}
if (!ActivateBestChain(state, pblock))
- return error("ProcessBlock() : ActivateBestChain failed");
+ return error("%s : ActivateBestChain failed", __func__);
+
+ 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;
}
@@ -2792,7 +2888,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) {
@@ -3006,6 +3102,8 @@ bool InitBlockIndex() {
return error("LoadBlockIndex() : genesis block not accepted");
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 FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
} catch(std::runtime_error &e) {
return error("LoadBlockIndex() : failed to initialize block database: %s", e.what());
}
@@ -3141,12 +3239,14 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
}
// process in case the block isn't known yet
- if (mapBlockIndex.count(hash) == 0) {
+ if (mapBlockIndex.count(hash) == 0 || (mapBlockIndex[hash]->nStatus & BLOCK_HAVE_DATA) == 0) {
CValidationState state;
- if (ProcessBlock(state, NULL, &block, dbp))
+ if (ProcessNewBlock(state, NULL, &block, dbp))
nLoaded++;
if (state.IsError())
break;
+ } else if (hash != Params().HashGenesisBlock() && mapBlockIndex[hash]->nHeight % 1000 == 0) {
+ LogPrintf("Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight);
}
// Recursively process earlier encountered successors of this block
@@ -3163,7 +3263,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(),
head.ToString());
CValidationState dummy;
- if (ProcessBlock(dummy, NULL, &block, &it->second))
+ if (ProcessNewBlock(dummy, NULL, &block, &it->second))
{
nLoaded++;
queue.push_back(block.GetHash());
@@ -3196,12 +3296,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 != "")
{
@@ -3458,12 +3558,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else
pfrom->fRelayTxes = true;
- if (pfrom->fInbound && addrMe.IsRoutable())
- {
- pfrom->addrLocal = addrMe;
- SeenLocal(addrMe);
- }
-
// Disconnect if we connected to ourself
if (nNonce == nLocalHostNonce && nNonce > 1)
{
@@ -3472,12 +3566,20 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true;
}
+ pfrom->addrLocal = addrMe;
+ if (pfrom->fInbound && addrMe.IsRoutable())
+ {
+ SeenLocal(addrMe);
+ }
+
// Be shy and don't send version until we hear
if (pfrom->fInbound)
pfrom->PushVersion();
pfrom->fClient = !(pfrom->nServices & NODE_NETWORK);
+ // Potentially mark this peer as a preferred download peer.
+ UpdatePreferredDownload(pfrom, State(pfrom->GetId()));
// Change version
pfrom->PushMessage("verack");
@@ -3490,7 +3592,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
{
CAddress addr = GetLocalAddress(&pfrom->addr);
if (addr.IsRoutable())
+ {
pfrom->PushAddress(addr);
+ } else if (IsPeerAddrLocalGood(pfrom)) {
+ addr.SetIP(pfrom->addrLocal);
+ pfrom->PushAddress(addr);
+ }
}
// Get recent addresses
@@ -3941,7 +4048,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->AddInventoryKnown(inv);
CValidationState state;
- ProcessBlock(state, pfrom, &block);
+ ProcessNewBlock(state, pfrom, &block);
int nDoS;
if (state.IsInvalid(nDoS)) {
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
@@ -4353,24 +4460,18 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
static int64_t nLastRebroadcast;
if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
{
+ LOCK(cs_vNodes);
+ BOOST_FOREACH(CNode* pnode, vNodes)
{
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
- {
- // Periodically clear setAddrKnown to allow refresh broadcasts
- if (nLastRebroadcast)
- pnode->setAddrKnown.clear();
+ // Periodically clear setAddrKnown to allow refresh broadcasts
+ if (nLastRebroadcast)
+ pnode->setAddrKnown.clear();
- // Rebroadcast our address
- if (fListen)
- {
- CAddress addr = GetLocalAddress(&pnode->addr);
- if (addr.IsRoutable())
- pnode->PushAddress(addr);
- }
- }
+ // Rebroadcast our address
+ AdvertizeLocal(pnode);
}
- nLastRebroadcast = GetTime();
+ if (!vNodes.empty())
+ nLastRebroadcast = GetTime();
}
//
@@ -4422,7 +4523,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// Start block sync
if (pindexBestHeader == NULL)
pindexBestHeader = chainActive.Tip();
- bool fFetch = !pto->fInbound || (pindexBestHeader && (state.pindexLastCommonBlock ? state.pindexLastCommonBlock->nHeight : 0) + 144 > pindexBestHeader->nHeight);
+ bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->fOneShot); // Download if this is a nice peer, or we have no nice peers and this one might do.
if (!state.fSyncStarted && !pto->fClient && fFetch && !fImporting && !fReindex) {
// Only actively request headers from a single peer, unless we're close to today.
if (nSyncStarted == 0 || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) {
@@ -4573,11 +4674,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 1941ca7059..c0d6412528 100644
--- a/src/main.h
+++ b/src/main.h
@@ -39,8 +39,15 @@
#include <boost/unordered_map.hpp>
class CBlockIndex;
+class CBlockTreeDB;
class CBloomFilter;
class CInv;
+class CScriptCheck;
+class CValidationInterface;
+class CValidationState;
+
+struct CBlockTemplate;
+struct CNodeStateStats;
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static const unsigned int MAX_BLOCK_SIZE = 1000000;
@@ -87,6 +94,8 @@ 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;
/** "reject" message codes **/
static const unsigned char REJECT_MALFORMED = 0x01;
@@ -128,15 +137,6 @@ extern CBlockIndex *pindexBestHeader;
// Minimum disk space required - used in CheckDiskSpace()
static const uint64_t nMinDiskSpace = 52428800;
-
-class CBlockTreeDB;
-class CScriptCheck;
-class CValidationState;
-class CValidationInterface;
-struct CNodeStateStats;
-
-struct CBlockTemplate;
-
/** Register a wallet to receive updates from core */
void RegisterValidationInterface(CValidationInterface* pwalletIn);
/** Unregister a wallet from core */
@@ -151,8 +151,16 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
/** Unregister a network node */
void UnregisterNodeSignals(CNodeSignals& nodeSignals);
-/** Process an incoming block */
-bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
+/** 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()
+*/
+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);
/** Open a block file (blk?????.dat) */
@@ -195,6 +203,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 **/
@@ -451,12 +461,19 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
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);
+bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);
// 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);
+// 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);
@@ -651,6 +668,7 @@ protected:
virtual void UpdatedTransaction(const uint256 &hash) {};
virtual void Inventory(const uint256 &hash) {};
virtual void ResendWalletTransactions() {};
+ virtual void BlockChecked(const CBlock&, const CValidationState&) {};
friend void ::RegisterValidationInterface(CValidationInterface*);
friend void ::UnregisterValidationInterface(CValidationInterface*);
friend void ::UnregisterAllValidationInterfaces();
diff --git a/src/miner.cpp b/src/miner.cpp
index 0235de3ab3..660173f35b 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -12,6 +12,7 @@
#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();
@@ -428,8 +435,8 @@ bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
// Process this block the same as if we had received it from another node
CValidationState state;
- if (!ProcessBlock(state, NULL, pblock))
- return error("BitcoinMiner : ProcessBlock, block not accepted");
+ if (!ProcessNewBlock(state, NULL, pblock))
+ return error("BitcoinMiner : ProcessNewBlock, block not accepted");
return true;
}
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 5ceb82cf8b..a66875a894 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -142,16 +142,19 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
}
// get best local address for a particular peer as a CAddress
+// Otherwise, return the unroutable 0.0.0.0 but filled in with
+// the normal parameters, since the IP may be changed to a useful
+// one by discovery.
CAddress GetLocalAddress(const CNetAddr *paddrPeer)
{
- CAddress ret(CService("0.0.0.0",0),0);
+ CAddress ret(CService("0.0.0.0",GetListenPort()),0);
CService addr;
if (GetLocal(addr, paddrPeer))
{
ret = CAddress(addr);
- ret.nServices = nLocalServices;
- ret.nTime = GetAdjustedTime();
}
+ ret.nServices = nLocalServices;
+ ret.nTime = GetAdjustedTime();
return ret;
}
@@ -205,21 +208,38 @@ bool RecvLine(SOCKET hSocket, string& strLine)
}
}
-// used when scores of local addresses may have changed
-// pushes better local address to peers
-void static AdvertizeLocal()
+int GetnScore(const CService& addr)
{
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
+ LOCK(cs_mapLocalHost);
+ if (mapLocalHost.count(addr) == LOCAL_NONE)
+ return 0;
+ return mapLocalHost[addr].nScore;
+}
+
+// Is our peer's addrLocal potentially useful as an external IP source?
+bool IsPeerAddrLocalGood(CNode *pnode)
+{
+ return fDiscover && pnode->addr.IsRoutable() && pnode->addrLocal.IsRoutable() &&
+ !IsLimited(pnode->addrLocal.GetNetwork());
+}
+
+// pushes our own address to a peer
+void AdvertizeLocal(CNode *pnode)
+{
+ if (fListen && pnode->fSuccessfullyConnected)
{
- if (pnode->fSuccessfullyConnected)
+ CAddress addrLocal = GetLocalAddress(&pnode->addr);
+ // If discovery is enabled, sometimes give our peer the address it
+ // tells us that it sees us as in case it has a better idea of our
+ // address than we do.
+ if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
+ GetRand((GetnScore(addrLocal) > LOCAL_MANUAL) ? 8:2) == 0))
{
- CAddress addrLocal = GetLocalAddress(&pnode->addr);
- if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal)
- {
- pnode->PushAddress(addrLocal);
- pnode->addrLocal = addrLocal;
- }
+ addrLocal.SetIP(pnode->addrLocal);
+ }
+ if (addrLocal.IsRoutable())
+ {
+ pnode->PushAddress(addrLocal);
}
}
}
@@ -257,8 +277,6 @@ bool AddLocal(const CService& addr, int nScore)
SetReachable(addr.GetNetwork());
}
- AdvertizeLocal();
-
return true;
}
@@ -296,12 +314,10 @@ bool SeenLocal(const CService& addr)
return false;
mapLocalHost[addr].nScore++;
}
-
- AdvertizeLocal();
-
return true;
}
+
/** check whether a given address is potentially local */
bool IsLocal(const CService& addr)
{
@@ -323,114 +339,12 @@ bool IsReachable(const CNetAddr& addr)
return IsReachable(net);
}
-bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet)
-{
- SOCKET hSocket;
- if (!ConnectSocket(addrConnect, hSocket))
- return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString());
-
- send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
-
- string strLine;
- while (RecvLine(hSocket, strLine))
- {
- if (strLine.empty()) // HTTP response is separated from headers by blank line
- {
- while (true)
- {
- if (!RecvLine(hSocket, strLine))
- {
- CloseSocket(hSocket);
- return false;
- }
- if (pszKeyword == NULL)
- break;
- if (strLine.find(pszKeyword) != string::npos)
- {
- strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
- break;
- }
- }
- CloseSocket(hSocket);
- if (strLine.find("<") != string::npos)
- strLine = strLine.substr(0, strLine.find("<"));
- strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
- while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
- strLine.resize(strLine.size()-1);
- CService addr(strLine,0,true);
- LogPrintf("GetMyExternalIP() received [%s] %s\n", strLine, addr.ToString());
- if (!addr.IsValid() || !addr.IsRoutable())
- return false;
- ipRet.SetIP(addr);
- return true;
- }
- }
- CloseSocket(hSocket);
- return error("GetMyExternalIP() : connection closed");
-}
-
-bool GetMyExternalIP(CNetAddr& ipRet)
-{
- CService addrConnect;
- const char* pszGet;
- const char* pszKeyword;
-
- for (int nLookup = 0; nLookup <= 1; nLookup++)
- for (int nHost = 1; nHost <= 1; nHost++)
- {
- // We should be phasing out our use of sites like these. If we need
- // replacements, we should ask for volunteers to put this simple
- // php file on their web server that prints the client IP:
- // <?php echo $_SERVER["REMOTE_ADDR"]; ?>
- if (nHost == 1)
- {
- addrConnect = CService("91.198.22.70", 80); // checkip.dyndns.org
-
- if (nLookup == 1)
- {
- CService addrIP("checkip.dyndns.org", 80, true);
- if (addrIP.IsValid())
- addrConnect = addrIP;
- }
-
- pszGet = "GET / HTTP/1.1\r\n"
- "Host: checkip.dyndns.org\r\n"
- "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
- "Connection: close\r\n"
- "\r\n";
-
- pszKeyword = "Address:";
- }
-
- if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
- return true;
- }
-
- return false;
-}
-
-void ThreadGetMyExternalIP()
-{
- CNetAddr addrLocalHost;
- if (GetMyExternalIP(addrLocalHost))
- {
- LogPrintf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP());
- AddLocal(addrLocalHost, LOCAL_HTTP);
- }
-}
-
-
-
-
-
void AddressCurrentlyConnected(const CService& addr)
{
addrman.Connected(addr);
}
-
-
uint64_t CNode::nTotalBytesRecv = 0;
uint64_t CNode::nTotalBytesSent = 0;
CCriticalSection CNode::cs_totalBytesRecv;
@@ -1687,9 +1601,6 @@ void static Discover(boost::thread_group& threadGroup)
}
#endif
- // Don't use external IPv4 discovery, when -onlynet="IPv6"
- if (!IsLimited(NET_IPV4))
- threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "ext-ip", &ThreadGetMyExternalIP));
}
void StartNode(boost::thread_group& threadGroup)
diff --git a/src/net.h b/src/net.h
index 340158512d..e48acf5644 100644
--- a/src/net.h
+++ b/src/net.h
@@ -60,7 +60,6 @@ unsigned int SendBufferSize();
void AddOneShot(std::string strDest);
bool RecvLine(SOCKET hSocket, std::string& strLine);
-bool GetMyExternalIP(CNetAddr& ipRet);
void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const std::string& addrName);
@@ -96,12 +95,13 @@ enum
LOCAL_IF, // address a local interface listens on
LOCAL_BIND, // address explicit bound to
LOCAL_UPNP, // address reported by UPnP
- LOCAL_HTTP, // address reported by whatismyip.com and similar
LOCAL_MANUAL, // address explicitly specified (-externalip=)
LOCAL_MAX
};
+bool IsPeerAddrLocalGood(CNode *pnode);
+void AdvertizeLocal(CNode *pnode);
void SetLimited(enum Network net, bool fLimited = true);
bool IsLimited(enum Network net);
bool IsLimited(const CNetAddr& addr);
diff --git a/src/pow.cpp b/src/pow.cpp
index af7fc488ef..e07e7ff770 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 "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
diff --git a/src/pow.h b/src/pow.h
index 233d1f3795..cf28656bd8 100644
--- a/src/pow.h
+++ b/src/pow.h
@@ -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/protocol.h b/src/protocol.h
index b73041a9fd..2ac8f3d8f7 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -7,8 +7,8 @@
#error This header can only be compiled as C++.
#endif
-#ifndef __INCLUDED_PROTOCOL_H__
-#define __INCLUDED_PROTOCOL_H__
+#ifndef BITCOIN_PROTOCOL_H
+#define BITCOIN_PROTOCOL_H
#include "netbase.h"
#include "serialize.h"
@@ -149,4 +149,4 @@ enum {
MSG_FILTERED_BLOCK,
};
-#endif // __INCLUDED_PROTOCOL_H__
+#endif // BITCOIN_PROTOCOL_H
diff --git a/src/pubkey.cpp b/src/pubkey.cpp
new file mode 100644
index 0000000000..9c6f536f21
--- /dev/null
+++ b/src/pubkey.cpp
@@ -0,0 +1,131 @@
+// 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 "pubkey.h"
+
+#include "crypto/sha2.h"
+#include "eccryptoverify.h"
+
+#ifdef USE_SECP256K1
+#include <secp256k1.h>
+#else
+#include "ecwrapper.h"
+#endif
+
+bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& 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(begin(), size()))
+ return false;
+ if (!key.Verify(hash, vchSig))
+ return false;
+#endif
+ return true;
+}
+
+bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
+ if (vchSig.size() != 65)
+ return false;
+ int recid = (vchSig[0] - 27) & 3;
+ bool fComp = ((vchSig[0] - 27) & 4) != 0;
+#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], recid))
+ return false;
+ std::vector<unsigned char> pubkey;
+ key.GetPubKey(pubkey, fComp);
+ Set(pubkey.begin(), pubkey.end());
+#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(begin(), size()))
+ 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(begin(), size()))
+ return false;
+ std::vector<unsigned char> pubkey;
+ key.GetPubKey(pubkey, false);
+ Set(pubkey.begin(), pubkey.end());
+#endif
+ return true;
+}
+
+bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
+ assert(IsValid());
+ assert((nChild >> 31) == 0);
+ assert(begin() + 33 == end());
+ 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(begin(), size());
+ ret &= key.TweakPublic(out);
+ std::vector<unsigned char> pubkey;
+ key.GetPubKey(pubkey, true);
+ pubkeyChild.Set(pubkey.begin(), pubkey.end());
+#endif
+ return ret;
+}
+
+void CExtPubKey::Encode(unsigned char code[74]) const {
+ code[0] = nDepth;
+ memcpy(code+1, vchFingerprint, 4);
+ code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
+ code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF;
+ memcpy(code+9, vchChainCode, 32);
+ assert(pubkey.size() == 33);
+ memcpy(code+41, pubkey.begin(), 33);
+}
+
+void CExtPubKey::Decode(const unsigned char code[74]) {
+ nDepth = code[0];
+ memcpy(vchFingerprint, code+1, 4);
+ nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
+ memcpy(vchChainCode, code+9, 32);
+ pubkey.Set(code+41, code+74);
+}
+
+bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
+ out.nDepth = nDepth + 1;
+ CKeyID id = pubkey.GetID();
+ memcpy(&out.vchFingerprint[0], &id, 4);
+ out.nChild = nChild;
+ return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode);
+}
diff --git a/src/pubkey.h b/src/pubkey.h
new file mode 100644
index 0000000000..37351cff0e
--- /dev/null
+++ b/src/pubkey.h
@@ -0,0 +1,206 @@
+// 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_PUBKEY_H
+#define BITCOIN_PUBKEY_H
+
+#include "hash.h"
+#include "serialize.h"
+#include "uint256.h"
+
+#include <stdexcept>
+#include <vector>
+
+/**
+ * secp256k1:
+ * const unsigned int PRIVATE_KEY_SIZE = 279;
+ * const unsigned int PUBLIC_KEY_SIZE = 65;
+ * const unsigned int SIGNATURE_SIZE = 72;
+ *
+ * see www.keylength.com
+ * script supports up to 75 for single byte push
+ */
+
+/** A reference to a CKey: the Hash160 of its serialized public key */
+class CKeyID : public uint160
+{
+public:
+ CKeyID() : uint160(0) {}
+ CKeyID(const uint160& in) : uint160(in) {}
+};
+
+/** An encapsulated public key. */
+class CPubKey
+{
+private:
+
+ /**
+ * Just store the serialized data.
+ * Its length can very cheaply be computed from the first byte.
+ */
+ unsigned char vch[65];
+
+ //! Compute the length of a pubkey with a given first byte.
+ unsigned int static GetLen(unsigned char chHeader)
+ {
+ if (chHeader == 2 || chHeader == 3)
+ return 33;
+ if (chHeader == 4 || chHeader == 6 || chHeader == 7)
+ return 65;
+ return 0;
+ }
+
+ //! Set this key data to be invalid
+ void Invalidate()
+ {
+ vch[0] = 0xFF;
+ }
+
+public:
+ //! Construct an invalid public key.
+ CPubKey()
+ {
+ Invalidate();
+ }
+
+ //! Initialize a public key using begin/end iterators to byte data.
+ template <typename T>
+ void Set(const T pbegin, const T pend)
+ {
+ int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
+ if (len && len == (pend - pbegin))
+ memcpy(vch, (unsigned char*)&pbegin[0], len);
+ else
+ Invalidate();
+ }
+
+ //! Construct a public key using begin/end iterators to byte data.
+ template <typename T>
+ CPubKey(const T pbegin, const T pend)
+ {
+ Set(pbegin, pend);
+ }
+
+ //! Construct a public key from a byte vector.
+ CPubKey(const std::vector<unsigned char>& vch)
+ {
+ Set(vch.begin(), vch.end());
+ }
+
+ //! Simple read-only vector-like interface to the pubkey data.
+ unsigned int size() const { return GetLen(vch[0]); }
+ const unsigned char* begin() const { return vch; }
+ const unsigned char* end() const { return vch + size(); }
+ const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
+
+ //! Comparator implementation.
+ friend bool operator==(const CPubKey& a, const CPubKey& b)
+ {
+ return a.vch[0] == b.vch[0] &&
+ memcmp(a.vch, b.vch, a.size()) == 0;
+ }
+ friend bool operator!=(const CPubKey& a, const CPubKey& b)
+ {
+ return !(a == b);
+ }
+ friend bool operator<(const CPubKey& a, const CPubKey& b)
+ {
+ return a.vch[0] < b.vch[0] ||
+ (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
+ }
+
+ //! Implement serialization, as if this was a byte vector.
+ unsigned int GetSerializeSize(int nType, int nVersion) const
+ {
+ return size() + 1;
+ }
+ template <typename Stream>
+ void Serialize(Stream& s, int nType, int nVersion) const
+ {
+ unsigned int len = size();
+ ::WriteCompactSize(s, len);
+ s.write((char*)vch, len);
+ }
+ template <typename Stream>
+ void Unserialize(Stream& s, int nType, int nVersion)
+ {
+ unsigned int len = ::ReadCompactSize(s);
+ if (len <= 65) {
+ s.read((char*)vch, len);
+ } else {
+ // invalid pubkey, skip available data
+ char dummy;
+ while (len--)
+ s.read(&dummy, 1);
+ Invalidate();
+ }
+ }
+
+ //! Get the KeyID of this public key (hash of its serialization)
+ CKeyID GetID() const
+ {
+ return CKeyID(Hash160(vch, vch + size()));
+ }
+
+ //! Get the 256-bit hash of this public key.
+ uint256 GetHash() const
+ {
+ return Hash(vch, vch + size());
+ }
+
+ /*
+ * Check syntactic correctness.
+ *
+ * Note that this is consensus critical as CheckSig() calls it!
+ */
+ bool IsValid() const
+ {
+ return size() > 0;
+ }
+
+ //! fully validate whether this is a valid public key (more expensive than IsValid())
+ bool IsFullyValid() const;
+
+ //! Check whether this is a compressed public key.
+ bool IsCompressed() const
+ {
+ return size() == 33;
+ }
+
+ /**
+ * Verify a DER signature (~72 bytes).
+ * If this public key is not fully valid, the return value will be false.
+ */
+ bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
+
+ //! Recover a public key from a compact signature.
+ bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
+
+ //! Turn this public key into an uncompressed public key.
+ bool Decompress();
+
+ //! Derive BIP32 child pubkey.
+ bool Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
+};
+
+struct CExtPubKey {
+ unsigned char nDepth;
+ unsigned char vchFingerprint[4];
+ unsigned int nChild;
+ unsigned char vchChainCode[32];
+ CPubKey pubkey;
+
+ friend bool operator==(const CExtPubKey& a, const CExtPubKey& b)
+ {
+ return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild &&
+ memcmp(&a.vchChainCode[0], &b.vchChainCode[0], 32) == 0 && a.pubkey == b.pubkey;
+ }
+
+ void Encode(unsigned char code[74]) const;
+ void Decode(const unsigned char code[74]);
+ bool Derive(CExtPubKey& out, unsigned int nChild) const;
+};
+
+#endif // BITCOIN_PUBKEY_H
diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h
index 20beb51ec4..031c424785 100644
--- a/src/qt/addressbookpage.h
+++ b/src/qt/addressbookpage.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef ADDRESSBOOKPAGE_H
-#define ADDRESSBOOKPAGE_H
+#ifndef BITCOIN_QT_ADDRESSBOOKPAGE_H
+#define BITCOIN_QT_ADDRESSBOOKPAGE_H
#include <QDialog>
@@ -84,4 +84,4 @@ signals:
void sendCoins(QString addr);
};
-#endif // ADDRESSBOOKPAGE_H
+#endif // BITCOIN_QT_ADDRESSBOOKPAGE_H
diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h
index 71691f5a26..310647d7c3 100644
--- a/src/qt/addresstablemodel.h
+++ b/src/qt/addresstablemodel.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef ADDRESSTABLEMODEL_H
-#define ADDRESSTABLEMODEL_H
+#ifndef BITCOIN_QT_ADDRESSTABLEMODEL_H
+#define BITCOIN_QT_ADDRESSTABLEMODEL_H
#include <QAbstractTableModel>
#include <QStringList>
@@ -92,4 +92,4 @@ public slots:
friend class AddressTablePriv;
};
-#endif // ADDRESSTABLEMODEL_H
+#endif // BITCOIN_QT_ADDRESSTABLEMODEL_H
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/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h
index 1119e0861f..6605086060 100644
--- a/src/qt/askpassphrasedialog.h
+++ b/src/qt/askpassphrasedialog.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef ASKPASSPHRASEDIALOG_H
-#define ASKPASSPHRASEDIALOG_H
+#ifndef BITCOIN_QT_ASKPASSPHRASEDIALOG_H
+#define BITCOIN_QT_ASKPASSPHRASEDIALOG_H
#include <QDialog>
@@ -48,4 +48,4 @@ protected:
bool eventFilter(QObject *object, QEvent *event);
};
-#endif // ASKPASSPHRASEDIALOG_H
+#endif // BITCOIN_QT_ASKPASSPHRASEDIALOG_H
diff --git a/src/qt/bitcoinaddressvalidator.h b/src/qt/bitcoinaddressvalidator.h
index 0fb779f7d8..15a6245da4 100644
--- a/src/qt/bitcoinaddressvalidator.h
+++ b/src/qt/bitcoinaddressvalidator.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOINADDRESSVALIDATOR_H
-#define BITCOINADDRESSVALIDATOR_H
+#ifndef BITCOIN_QT_BITCOINADDRESSVALIDATOR_H
+#define BITCOIN_QT_BITCOINADDRESSVALIDATOR_H
#include <QValidator>
@@ -32,4 +32,4 @@ public:
State validate(QString &input, int &pos) const;
};
-#endif // BITCOINADDRESSVALIDATOR_H
+#endif // BITCOIN_QT_BITCOINADDRESSVALIDATOR_H
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index 6e35bf17b3..5b8ab23b26 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -130,6 +130,7 @@ public:
extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &opt,
QStyle::SC_SpinBoxEditField, this).size();
hint += extra;
+ hint.setHeight(h);
opt.rect = rect();
@@ -220,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 040a234177..1bad8ce1b8 100644
--- a/src/qt/bitcoinamountfield.h
+++ b/src/qt/bitcoinamountfield.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOINAMOUNTFIELD_H
-#define BITCOINAMOUNTFIELD_H
+#ifndef BITCOIN_QT_BITCOINAMOUNTFIELD_H
+#define BITCOIN_QT_BITCOINAMOUNTFIELD_H
#include "amount.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.
*/
@@ -69,4 +72,4 @@ private slots:
};
-#endif // BITCOINAMOUNTFIELD_H
+#endif // BITCOIN_QT_BITCOINAMOUNTFIELD_H
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 77cfdceef0..6a457d361f 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -103,9 +103,9 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle *networkStyle, QWidget *parent) :
QString windowTitle = tr("Bitcoin Core") + " - ";
#ifdef ENABLE_WALLET
/* if compiled with wallet support, -disablewallet can still disable the wallet */
- bool enableWallet = !GetBoolArg("-disablewallet", false);
+ enableWallet = !GetBoolArg("-disablewallet", false);
#else
- bool enableWallet = false;
+ enableWallet = false;
#endif // ENABLE_WALLET
if(enableWallet)
{
@@ -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);
@@ -554,7 +554,7 @@ void BitcoinGUI::optionsClicked()
if(!clientModel || !clientModel->getOptionsModel())
return;
- OptionsDialog dlg(this);
+ OptionsDialog dlg(this, enableWallet);
dlg.setModel(clientModel->getOptionsModel());
dlg.exec();
}
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 0ef4101127..662ef9d9e8 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOINGUI_H
-#define BITCOINGUI_H
+#ifndef BITCOIN_QT_BITCOINGUI_H
+#define BITCOIN_QT_BITCOINGUI_H
#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
@@ -64,6 +64,7 @@ public:
bool setCurrentWallet(const QString& name);
void removeAllWallets();
#endif // ENABLE_WALLET
+ bool enableWallet;
protected:
void changeEvent(QEvent *e);
@@ -236,4 +237,4 @@ private slots:
void onMenuSelection(QAction* action);
};
-#endif // BITCOINGUI_H
+#endif // BITCOIN_QT_BITCOINGUI_H
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.h b/src/qt/bitcoinunits.h
index a392c42b9b..7a4f38274d 100644
--- a/src/qt/bitcoinunits.h
+++ b/src/qt/bitcoinunits.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOINUNITS_H
-#define BITCOINUNITS_H
+#ifndef BITCOIN_QT_BITCOINUNITS_H
+#define BITCOIN_QT_BITCOINUNITS_H
#include "amount.h"
@@ -126,4 +126,4 @@ private:
};
typedef BitcoinUnits::Unit BitcoinUnit;
-#endif // BITCOINUNITS_H
+#endif // BITCOIN_QT_BITCOINUNITS_H
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index c7bd60bd41..c7a05e287d 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef CLIENTMODEL_H
-#define CLIENTMODEL_H
+#ifndef BITCOIN_QT_CLIENTMODEL_H
+#define BITCOIN_QT_CLIENTMODEL_H
#include <QObject>
@@ -102,4 +102,4 @@ public slots:
void updateAlert(const QString &hash, int status);
};
-#endif // CLIENTMODEL_H
+#endif // BITCOIN_QT_CLIENTMODEL_H
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 9eaa8eb41d..bd4f5d7f1e 100644
--- a/src/qt/coincontroldialog.h
+++ b/src/qt/coincontroldialog.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef COINCONTROLDIALOG_H
-#define COINCONTROLDIALOG_H
+#ifndef BITCOIN_QT_COINCONTROLDIALOG_H
+#define BITCOIN_QT_COINCONTROLDIALOG_H
#include "amount.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;
@@ -124,4 +124,4 @@ private slots:
void updateLabelLocked();
};
-#endif // COINCONTROLDIALOG_H
+#endif // BITCOIN_QT_COINCONTROLDIALOG_H
diff --git a/src/qt/coincontroltreewidget.h b/src/qt/coincontroltreewidget.h
index a2cd34eb88..643eaf0c70 100644
--- a/src/qt/coincontroltreewidget.h
+++ b/src/qt/coincontroltreewidget.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef COINCONTROLTREEWIDGET_H
-#define COINCONTROLTREEWIDGET_H
+#ifndef BITCOIN_QT_COINCONTROLTREEWIDGET_H
+#define BITCOIN_QT_COINCONTROLTREEWIDGET_H
#include <QKeyEvent>
#include <QTreeWidget>
@@ -19,4 +19,4 @@ protected:
virtual void keyPressEvent(QKeyEvent *event);
};
-#endif // COINCONTROLTREEWIDGET_H \ No newline at end of file
+#endif // BITCOIN_QT_COINCONTROLTREEWIDGET_H
diff --git a/src/qt/csvmodelwriter.h b/src/qt/csvmodelwriter.h
index 29de251efe..c613ce73eb 100644
--- a/src/qt/csvmodelwriter.h
+++ b/src/qt/csvmodelwriter.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef CSVMODELWRITER_H
-#define CSVMODELWRITER_H
+#ifndef BITCOIN_QT_CSVMODELWRITER_H
+#define BITCOIN_QT_CSVMODELWRITER_H
#include <QList>
#include <QObject>
@@ -43,4 +43,4 @@ private:
QList<Column> columns;
};
-#endif // CSVMODELWRITER_H
+#endif // BITCOIN_QT_CSVMODELWRITER_H
diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h
index 6910c667cd..aa1103a2f5 100644
--- a/src/qt/editaddressdialog.h
+++ b/src/qt/editaddressdialog.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef EDITADDRESSDIALOG_H
-#define EDITADDRESSDIALOG_H
+#ifndef BITCOIN_QT_EDITADDRESSDIALOG_H
+#define BITCOIN_QT_EDITADDRESSDIALOG_H
#include <QDialog>
@@ -54,4 +54,4 @@ private:
QString address;
};
-#endif // EDITADDRESSDIALOG_H
+#endif // BITCOIN_QT_EDITADDRESSDIALOG_H
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/coincontroldialog.ui b/src/qt/forms/coincontroldialog.ui
index cbe58fec65..c1fef6b9b1 100644
--- a/src/qt/forms/coincontroldialog.ui
+++ b/src/qt/forms/coincontroldialog.ui
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
- <string>Coin Control Address Selection</string>
+ <string>Coin Selection</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
@@ -379,9 +379,6 @@
<property name="text">
<string>Tree mode</string>
</property>
- <property name="checked">
- <bool>true</bool>
- </property>
</widget>
</item>
<item>
@@ -395,6 +392,9 @@
<property name="text">
<string>List mode</string>
</property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item>
@@ -451,12 +451,12 @@
</column>
<column>
<property name="text">
- <string notr="true">Label</string>
+ <string>Received with label</string>
</property>
</column>
<column>
<property name="text">
- <string>Address</string>
+ <string>Received with address</string>
</property>
</column>
<column>
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 &amp;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>&amp;Connect through SOCKS proxy (default proxy):</string>
+ <string>&amp;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/rpcconsole.ui b/src/qt/forms/rpcconsole.ui
index 898df2b080..c5ac371619 100644
--- a/src/qt/forms/rpcconsole.ui
+++ b/src/qt/forms/rpcconsole.ui
@@ -689,7 +689,7 @@
<item row="0" column="0" rowspan="2">
<widget class="QTableView" name="peerWidget">
<property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOff</enum>
+ <enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
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 &quot;per kilobyte&quot; only pays 250 satoshis in fee, while &quot;at least&quot; 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 &quot;per kilobyte&quot; only pays 250 satoshis in fee, while &quot;total at least&quot; 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/guiconstants.h b/src/qt/guiconstants.h
index 4c8a67b663..f23175049a 100644
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef GUICONSTANTS_H
-#define GUICONSTANTS_H
+#ifndef BITCOIN_QT_GUICONSTANTS_H
+#define BITCOIN_QT_GUICONSTANTS_H
/* Milliseconds between model updates */
static const int MODEL_UPDATE_DELAY = 250;
@@ -52,4 +52,4 @@ static const int MAX_PAYMENT_REQUEST_SIZE = 50000; // bytes
#define QAPP_APP_NAME_DEFAULT "Bitcoin-Qt"
#define QAPP_APP_NAME_TESTNET "Bitcoin-Qt-testnet"
-#endif // GUICONSTANTS_H
+#endif // BITCOIN_QT_GUICONSTANTS_H
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 0939c78f64..09c79db2d9 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -2,14 +2,16 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef GUIUTIL_H
-#define GUIUTIL_H
+#ifndef BITCOIN_QT_GUIUTIL_H
+#define BITCOIN_QT_GUIUTIL_H
#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 // GUIUTIL_H
+#endif // BITCOIN_QT_GUIUTIL_H
diff --git a/src/qt/intro.h b/src/qt/intro.h
index e3e396d369..c9c0d448fa 100644
--- a/src/qt/intro.h
+++ b/src/qt/intro.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef INTRO_H
-#define INTRO_H
+#ifndef BITCOIN_QT_INTRO_H
+#define BITCOIN_QT_INTRO_H
#include <QDialog>
#include <QMutex>
@@ -70,4 +70,4 @@ private:
friend class FreespaceChecker;
};
-#endif // INTRO_H
+#endif // BITCOIN_QT_INTRO_H
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.&lt;br/&gt;Please use a passphrase of &lt;b&gt;ten or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</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 &amp;message...</source>
<translation>Sign &amp;message...</translation>
</message>
@@ -296,7 +296,7 @@
<translation>Synchronizing with network...</translation>
</message>
<message>
- <location line="-405"/>
+ <location line="-407"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
@@ -321,7 +321,7 @@
<translation>Browse transaction history</translation>
</message>
<message>
- <location line="+17"/>
+ <location line="+19"/>
<source>E&amp;xit</source>
<translation>E&amp;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>&amp;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>&amp;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>&amp;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 &amp;fee</source>
- <translation>Pay transaction &amp;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>&amp;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>&amp;Network</translation>
</message>
<message>
- <location line="-131"/>
+ <location line="-85"/>
<source>(0 = auto, &lt;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 &amp;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>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+9"/>
<source>Proxy &amp;IP:</source>
<translation>Proxy &amp;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>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1435,17 +1429,17 @@ Address: %4
<translation>&amp;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 &quot;per kilobyte&quot; only pays 250 satoshis in fee, while &quot;at least&quot; 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 &quot;per kilobyte&quot; only pays 250 satoshis in fee, while &quot;total at least&quot; 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 &amp;All</source>
<translation>Clear &amp;All</translation>
</message>
@@ -2417,12 +2502,12 @@ Address: %4
<translation>S&amp;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 &quot;Bitcoin Alert&quot; 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 &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</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 &quot;Bitcoin Alert&quot; 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, &lt;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 &quot;Bitcoin Alert&quot; 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 &quot;Bitcoin Alert&quot; 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 &lt;ip&gt; 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 &quot;Bitcoin Alert&quot; 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 &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</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 &quot;Bitcoin Alert&quot; 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 &quot;Bitcoin Alert&quot; 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 &lt;https://www.openssl.org/&gt; 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 &quot;Bitcoin Alert&quot; 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 &quot;Bitcoin Alert&quot; 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 &quot;Bitcoin Alert&quot; 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 &quot;Bitcoin Alert&quot; 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 &quot;Bitcoin Alert&quot; 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 &quot;Bitcoin Alert&quot; 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 &quot;Bitcoin Alert&quot; 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 &quot;Bitcoin Alert&quot; admin@foo.
<translation>Unknown network specified in -onlynet: &apos;%s&apos;</translation>
</message>
<message>
- <location line="-111"/>
+ <location line="-112"/>
<source>Cannot resolve -bind address: &apos;%s&apos;</source>
<translation>Cannot resolve -bind address: &apos;%s&apos;</translation>
</message>
@@ -4424,12 +4534,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; 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/macdockiconhandler.h b/src/qt/macdockiconhandler.h
index b21a61cb07..1ffab75c9a 100644
--- a/src/qt/macdockiconhandler.h
+++ b/src/qt/macdockiconhandler.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef MACDOCKICONHANDLER_H
-#define MACDOCKICONHANDLER_H
+#ifndef BITCOIN_QT_MACDOCKICONHANDLER_H
+#define BITCOIN_QT_MACDOCKICONHANDLER_H
#include <QMainWindow>
#include <QObject>
@@ -48,4 +48,4 @@ private:
QMainWindow *mainWindow;
};
-#endif // MACDOCKICONCLICKHANDLER_H
+#endif // BITCOIN_QT_MACDOCKICONHANDLER_H
diff --git a/src/qt/macnotificationhandler.h b/src/qt/macnotificationhandler.h
index bc335edede..f7a4cb7f5b 100644
--- a/src/qt/macnotificationhandler.h
+++ b/src/qt/macnotificationhandler.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef MACNOTIFICATIONHANDLER_H
-#define MACNOTIFICATIONHANDLER_H
+#ifndef BITCOIN_QT_MACNOTIFICATIONHANDLER_H
+#define BITCOIN_QT_MACNOTIFICATIONHANDLER_H
#include <QObject>
@@ -27,4 +27,4 @@ public:
};
-#endif // MACNOTIFICATIONHANDLER_H
+#endif // BITCOIN_QT_MACNOTIFICATIONHANDLER_H
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/networkstyle.h b/src/qt/networkstyle.h
index 99304d61a3..e49b86c950 100644
--- a/src/qt/networkstyle.h
+++ b/src/qt/networkstyle.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef H_NETWORKSTYLE
-#define H_NETWORKSTYLE
+#ifndef BITCOIN_QT_NETWORKSTYLE_H
+#define BITCOIN_QT_NETWORKSTYLE_H
#include <QIcon>
#include <QPixmap>
@@ -30,4 +30,4 @@ private:
QPixmap splashImage;
};
-#endif // H_NETWORKSTYLE
+#endif // BITCOIN_QT_NETWORKSTYLE_H
diff --git a/src/qt/notificator.h b/src/qt/notificator.h
index 3395e64350..61c27e7ff8 100644
--- a/src/qt/notificator.h
+++ b/src/qt/notificator.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef NOTIFICATOR_H
-#define NOTIFICATOR_H
+#ifndef BITCOIN_QT_NOTIFICATOR_H
+#define BITCOIN_QT_NOTIFICATOR_H
#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
@@ -77,4 +77,4 @@ private:
#endif
};
-#endif // NOTIFICATOR_H
+#endif // BITCOIN_QT_NOTIFICATOR_H
diff --git a/src/qt/openuridialog.h b/src/qt/openuridialog.h
index 67a5f167d1..f04ec71b32 100644
--- a/src/qt/openuridialog.h
+++ b/src/qt/openuridialog.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef OPENURIDIALOG_H
-#define OPENURIDIALOG_H
+#ifndef BITCOIN_QT_OPENURIDIALOG_H
+#define BITCOIN_QT_OPENURIDIALOG_H
#include <QDialog>
@@ -31,4 +31,4 @@ private:
Ui::OpenURIDialog *ui;
};
-#endif // OPENURIDIALOG_H
+#endif // BITCOIN_QT_OPENURIDIALOG_H
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 67be174d55..069080219e 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -30,7 +30,7 @@
#include <QMessageBox>
#include <QTimer>
-OptionsDialog::OptionsDialog(QWidget *parent) :
+OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
QDialog(parent),
ui(new Ui::OptionsDialog),
model(0),
@@ -66,6 +66,11 @@ OptionsDialog::OptionsDialog(QWidget *parent) :
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWindow));
#endif
+ /* remove Wallet tab in case of -disablewallet */
+ if (!enableWallet) {
+ ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWallet));
+ }
+
/* Display elements init */
QDir translations(":translations");
ui->lang->addItem(QString("(") + tr("default") + QString(")"), QVariant(""));
@@ -100,9 +105,6 @@ OptionsDialog::OptionsDialog(QWidget *parent) :
#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);
@@ -134,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 */
@@ -167,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);
@@ -259,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 39c53f4391..511719f53c 100644
--- a/src/qt/optionsdialog.h
+++ b/src/qt/optionsdialog.h
@@ -2,15 +2,18 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef OPTIONSDIALOG_H
-#define OPTIONSDIALOG_H
+#ifndef BITCOIN_QT_OPTIONSDIALOG_H
+#define BITCOIN_QT_OPTIONSDIALOG_H
#include <QDialog>
-class QDataWidgetMapper;
class OptionsModel;
class QValidatedLineEdit;
+QT_BEGIN_NAMESPACE
+class QDataWidgetMapper;
+QT_END_NAMESPACE
+
namespace Ui {
class OptionsDialog;
}
@@ -21,7 +24,7 @@ class OptionsDialog : public QDialog
Q_OBJECT
public:
- explicit OptionsDialog(QWidget *parent);
+ explicit OptionsDialog(QWidget *parent, bool enableWallet);
~OptionsDialog();
void setModel(OptionsModel *model);
@@ -43,7 +46,6 @@ private slots:
void showRestartWarning(bool fPersistent = false);
void clearStatusLabel();
- void updateDisplayUnit();
void doProxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort);
signals:
@@ -56,4 +58,4 @@ private:
bool fProxyIpValid;
};
-#endif // OPTIONSDIALOG_H
+#endif // BITCOIN_QT_OPTIONSDIALOG_H
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 42ea3bf8e5..84fd49a7b8 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef OPTIONSMODEL_H
-#define OPTIONSMODEL_H
+#ifndef BITCOIN_QT_OPTIONSMODEL_H
+#define BITCOIN_QT_OPTIONSMODEL_H
#include "amount.h"
@@ -34,7 +34,6 @@ public:
ProxyUse, // bool
ProxyIP, // QString
ProxyPort, // int
- Fee, // qint64
DisplayUnit, // BitcoinUnits::Unit
ThirdPartyTxUrls, // QString
Language, // QString
@@ -84,8 +83,7 @@ private:
signals:
void displayUnitChanged(int unit);
- void transactionFeeChanged(const CAmount&);
void coinControlFeaturesChanged(bool);
};
-#endif // OPTIONSMODEL_H
+#endif // BITCOIN_QT_OPTIONSMODEL_H
diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h
index 03f239008f..e889eae8be 100644
--- a/src/qt/overviewpage.h
+++ b/src/qt/overviewpage.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef OVERVIEWPAGE_H
-#define OVERVIEWPAGE_H
+#ifndef BITCOIN_QT_OVERVIEWPAGE_H
+#define BITCOIN_QT_OVERVIEWPAGE_H
#include "amount.h"
@@ -63,4 +63,4 @@ private slots:
void updateWatchOnlyLabels(bool showWatchOnly);
};
-#endif // OVERVIEWPAGE_H
+#endif // BITCOIN_QT_OVERVIEWPAGE_H
diff --git a/src/qt/paymentrequestplus.h b/src/qt/paymentrequestplus.h
index 3d94d93269..91c704c520 100644
--- a/src/qt/paymentrequestplus.h
+++ b/src/qt/paymentrequestplus.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef PAYMENTREQUESTPLUS_H
-#define PAYMENTREQUESTPLUS_H
+#ifndef BITCOIN_QT_PAYMENTREQUESTPLUS_H
+#define BITCOIN_QT_PAYMENTREQUESTPLUS_H
#include "paymentrequest.pb.h"
@@ -42,5 +42,4 @@ private:
payments::PaymentDetails details;
};
-#endif // PAYMENTREQUESTPLUS_H
-
+#endif // BITCOIN_QT_PAYMENTREQUESTPLUS_H
diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h
index d84d09c57d..25b08cde49 100644
--- a/src/qt/paymentserver.h
+++ b/src/qt/paymentserver.h
@@ -2,8 +2,9 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef PAYMENTSERVER_H
-#define PAYMENTSERVER_H
+#ifndef BITCOIN_QT_PAYMENTSERVER_H
+#define BITCOIN_QT_PAYMENTSERVER_H
+
// This class handles payment requests from clicking on
// bitcoin: URIs
//
@@ -135,4 +136,4 @@ private:
OptionsModel *optionsModel;
};
-#endif // PAYMENTSERVER_H
+#endif // BITCOIN_QT_PAYMENTSERVER_H
diff --git a/src/qt/peertablemodel.h b/src/qt/peertablemodel.h
index 38f2662f89..23e71fc685 100644
--- a/src/qt/peertablemodel.h
+++ b/src/qt/peertablemodel.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef PEERTABLEMODEL_H
-#define PEERTABLEMODEL_H
+#ifndef BITCOIN_QT_PEERTABLEMODEL_H
+#define BITCOIN_QT_PEERTABLEMODEL_H
#include "main.h"
#include "net.h"
@@ -78,4 +78,4 @@ private:
QTimer *timer;
};
-#endif // PEERTABLEMODEL_H
+#endif // BITCOIN_QT_PEERTABLEMODEL_H
diff --git a/src/qt/qvalidatedlineedit.h b/src/qt/qvalidatedlineedit.h
index c2a4817e65..0996164b0f 100644
--- a/src/qt/qvalidatedlineedit.h
+++ b/src/qt/qvalidatedlineedit.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef QVALIDATEDLINEEDIT_H
-#define QVALIDATEDLINEEDIT_H
+#ifndef BITCOIN_QT_QVALIDATEDLINEEDIT_H
+#define BITCOIN_QT_QVALIDATEDLINEEDIT_H
#include <QLineEdit>
@@ -36,4 +36,4 @@ private slots:
void checkValidity();
};
-#endif // QVALIDATEDLINEEDIT_H
+#endif // BITCOIN_QT_QVALIDATEDLINEEDIT_H
diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h
index 5f2182913c..821f41716b 100644
--- a/src/qt/qvaluecombobox.h
+++ b/src/qt/qvaluecombobox.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef QVALUECOMBOBOX_H
-#define QVALUECOMBOBOX_H
+#ifndef BITCOIN_QT_QVALUECOMBOBOX_H
+#define BITCOIN_QT_QVALUECOMBOBOX_H
#include <QComboBox>
#include <QVariant>
@@ -34,4 +34,4 @@ private slots:
void handleSelectionChanged(int idx);
};
-#endif // QVALUECOMBOBOX_H
+#endif // BITCOIN_QT_QVALUECOMBOBOX_H
diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h
index 7a7e38e25e..220fb5c7a8 100644
--- a/src/qt/receivecoinsdialog.h
+++ b/src/qt/receivecoinsdialog.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef RECEIVECOINSDIALOG_H
-#define RECEIVECOINSDIALOG_H
+#ifndef BITCOIN_QT_RECEIVECOINSDIALOG_H
+#define BITCOIN_QT_RECEIVECOINSDIALOG_H
#include "guiutil.h"
@@ -73,4 +73,4 @@ private slots:
void copyAmount();
};
-#endif // RECEIVECOINSDIALOG_H
+#endif // BITCOIN_QT_RECEIVECOINSDIALOG_H
diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h
index 9b78e495c3..6f3b9838e2 100644
--- a/src/qt/receiverequestdialog.h
+++ b/src/qt/receiverequestdialog.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef QRCODEDIALOG_H
-#define QRCODEDIALOG_H
+#ifndef BITCOIN_QT_RECEIVEREQUESTDIALOG_H
+#define BITCOIN_QT_RECEIVEREQUESTDIALOG_H
#include "walletmodel.h"
@@ -67,4 +67,4 @@ private:
SendCoinsRecipient info;
};
-#endif // QRCODEDIALOG_H
+#endif // BITCOIN_QT_RECEIVEREQUESTDIALOG_H
diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h
index 3df5971823..ec6a49070d 100644
--- a/src/qt/recentrequeststablemodel.h
+++ b/src/qt/recentrequeststablemodel.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef RECENTREQUESTSTABLEMODEL_H
-#define RECENTREQUESTSTABLEMODEL_H
+#ifndef BITCOIN_QT_RECENTREQUESTSTABLEMODEL_H
+#define BITCOIN_QT_RECENTREQUESTSTABLEMODEL_H
#include "walletmodel.h"
@@ -105,4 +105,4 @@ private:
QString getAmountTitle();
};
-#endif
+#endif // BITCOIN_QT_RECENTREQUESTSTABLEMODEL_H
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 1ffff92758..4bb9b62e93 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef RPCCONSOLE_H
-#define RPCCONSOLE_H
+#ifndef BITCOIN_QT_RPCCONSOLE_H
+#define BITCOIN_QT_RPCCONSOLE_H
#include "guiutil.h"
#include "peertablemodel.h"
@@ -100,4 +100,4 @@ private:
NodeId cachedNodeid;
};
-#endif // RPCCONSOLE_H
+#endif // BITCOIN_QT_RPCCONSOLE_H
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 74cc4bde56..15d39782a1 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -2,14 +2,15 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef SENDCOINSDIALOG_H
-#define SENDCOINSDIALOG_H
+#ifndef BITCOIN_QT_SENDCOINSDIALOG_H
+#define BITCOIN_QT_SENDCOINSDIALOG_H
#include "walletmodel.h"
#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,10 +85,15 @@ 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
void message(const QString &title, const QString &message, unsigned int style);
};
-#endif // SENDCOINSDIALOG_H
+#endif // BITCOIN_QT_SENDCOINSDIALOG_H
diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h
index 2b696c77fb..69ad1032df 100644
--- a/src/qt/sendcoinsentry.h
+++ b/src/qt/sendcoinsentry.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef SENDCOINSENTRY_H
-#define SENDCOINSENTRY_H
+#ifndef BITCOIN_QT_SENDCOINSENTRY_H
+#define BITCOIN_QT_SENDCOINSENTRY_H
#include "walletmodel.h"
@@ -67,4 +67,4 @@ private:
bool updateLabel(const QString &address);
};
-#endif // SENDCOINSENTRY_H
+#endif // BITCOIN_QT_SENDCOINSENTRY_H
diff --git a/src/qt/signverifymessagedialog.h b/src/qt/signverifymessagedialog.h
index bba861649a..36550edc8d 100644
--- a/src/qt/signverifymessagedialog.h
+++ b/src/qt/signverifymessagedialog.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef SIGNVERIFYMESSAGEDIALOG_H
-#define SIGNVERIFYMESSAGEDIALOG_H
+#ifndef BITCOIN_QT_SIGNVERIFYMESSAGEDIALOG_H
+#define BITCOIN_QT_SIGNVERIFYMESSAGEDIALOG_H
#include <QDialog>
@@ -48,4 +48,4 @@ private slots:
void on_clearButton_VM_clicked();
};
-#endif // SIGNVERIFYMESSAGEDIALOG_H
+#endif // BITCOIN_QT_SIGNVERIFYMESSAGEDIALOG_H
diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h
index 128edadbee..4d9651f022 100644
--- a/src/qt/splashscreen.h
+++ b/src/qt/splashscreen.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef SPLASHSCREEN_H
-#define SPLASHSCREEN_H
+#ifndef BITCOIN_QT_SPLASHSCREEN_H
+#define BITCOIN_QT_SPLASHSCREEN_H
#include <QSplashScreen>
@@ -46,4 +46,4 @@ private:
int curAlignment;
};
-#endif // SPLASHSCREEN_H
+#endif // BITCOIN_QT_SPLASHSCREEN_H
diff --git a/src/qt/test/paymentservertests.h b/src/qt/test/paymentservertests.h
index 9b6400b0d5..0717111f66 100644
--- a/src/qt/test/paymentservertests.h
+++ b/src/qt/test/paymentservertests.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef PAYMENTSERVERTESTS_H
-#define PAYMENTSERVERTESTS_H
+#ifndef BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H
+#define BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H
#include "../paymentserver.h"
@@ -32,4 +32,4 @@ public:
SendCoinsRecipient recipient;
};
-#endif // PAYMENTSERVERTESTS_H
+#endif // BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H
diff --git a/src/qt/test/uritests.h b/src/qt/test/uritests.h
index 1ea6d9f075..ed30a9f4a7 100644
--- a/src/qt/test/uritests.h
+++ b/src/qt/test/uritests.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef URITESTS_H
-#define URITESTS_H
+#ifndef BITCOIN_QT_TEST_URITESTS_H
+#define BITCOIN_QT_TEST_URITESTS_H
#include <QObject>
#include <QTest>
@@ -16,4 +16,4 @@ private slots:
void uriTests();
};
-#endif // URITESTS_H
+#endif // BITCOIN_QT_TEST_URITESTS_H
diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp
index 74565bb6d0..5f14b80797 100644
--- a/src/qt/trafficgraphwidget.cpp
+++ b/src/qt/trafficgraphwidget.cpp
@@ -76,10 +76,12 @@ void TrafficGraphWidget::paintEvent(QPaintEvent *)
int base = floor(log10(fMax));
float val = pow(10.0f, base);
- const QString units = tr("KB/s");
+ const QString units = tr("KB/s");
+ const float yMarginText = 2.0;
+
// draw lines
painter.setPen(axisCol);
- painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 %2").arg(val).arg(units));
+ painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
for(float y = val; y < fMax; y += val) {
int yy = YMARGIN + h - h * y / fMax;
painter.drawLine(XMARGIN, yy, width() - XMARGIN, yy);
@@ -89,7 +91,7 @@ void TrafficGraphWidget::paintEvent(QPaintEvent *)
axisCol = axisCol.darker();
val = pow(10.0f, base - 1);
painter.setPen(axisCol);
- painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax, QString("%1 %2").arg(val).arg(units));
+ painter.drawText(XMARGIN, YMARGIN + h - h * val / fMax-yMarginText, QString("%1 %2").arg(val).arg(units));
int count = 1;
for(float y = val; y < fMax; y += val, count++) {
// don't overwrite lines drawn above
diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h
index efab6e7fc5..50571e0b2d 100644
--- a/src/qt/trafficgraphwidget.h
+++ b/src/qt/trafficgraphwidget.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef TRAFFICGRAPHWIDGET_H
-#define TRAFFICGRAPHWIDGET_H
+#ifndef BITCOIN_QT_TRAFFICGRAPHWIDGET_H
+#define BITCOIN_QT_TRAFFICGRAPHWIDGET_H
#include <QWidget>
#include <QQueue>
@@ -45,4 +45,4 @@ private:
ClientModel *clientModel;
};
-#endif // TRAFFICGRAPHWIDGET_H
+#endif // BITCOIN_QT_TRAFFICGRAPHWIDGET_H
diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h
index 4bd4293210..fc958a097c 100644
--- a/src/qt/transactiondesc.h
+++ b/src/qt/transactiondesc.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef TRANSACTIONDESC_H
-#define TRANSACTIONDESC_H
+#ifndef BITCOIN_QT_TRANSACTIONDESC_H
+#define BITCOIN_QT_TRANSACTIONDESC_H
#include <QObject>
#include <QString>
@@ -28,4 +28,4 @@ private:
static QString FormatTxStatus(const CWalletTx& wtx);
};
-#endif // TRANSACTIONDESC_H
+#endif // BITCOIN_QT_TRANSACTIONDESC_H
diff --git a/src/qt/transactiondescdialog.h b/src/qt/transactiondescdialog.h
index d4719975b2..c12c18e824 100644
--- a/src/qt/transactiondescdialog.h
+++ b/src/qt/transactiondescdialog.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef TRANSACTIONDESCDIALOG_H
-#define TRANSACTIONDESCDIALOG_H
+#ifndef BITCOIN_QT_TRANSACTIONDESCDIALOG_H
+#define BITCOIN_QT_TRANSACTIONDESCDIALOG_H
#include <QDialog>
@@ -28,4 +28,4 @@ private:
Ui::TransactionDescDialog *ui;
};
-#endif // TRANSACTIONDESCDIALOG_H
+#endif // BITCOIN_QT_TRANSACTIONDESCDIALOG_H
diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h
index ca31ee8f87..5836b114ab 100644
--- a/src/qt/transactionfilterproxy.h
+++ b/src/qt/transactionfilterproxy.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef TRANSACTIONFILTERPROXY_H
-#define TRANSACTIONFILTERPROXY_H
+#ifndef BITCOIN_QT_TRANSACTIONFILTERPROXY_H
+#define BITCOIN_QT_TRANSACTIONFILTERPROXY_H
#include "amount.h"
@@ -65,4 +65,4 @@ private:
bool showInactive;
};
-#endif // TRANSACTIONFILTERPROXY_H
+#endif // BITCOIN_QT_TRANSACTIONFILTERPROXY_H
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index 9276c9f0af..e26453cda4 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef TRANSACTIONRECORD_H
-#define TRANSACTIONRECORD_H
+#ifndef BITCOIN_QT_TRANSACTIONRECORD_H
+#define BITCOIN_QT_TRANSACTIONRECORD_H
#include "amount.h"
#include "uint256.h"
@@ -140,4 +140,4 @@ public:
bool statusUpdateNeeded();
};
-#endif // TRANSACTIONRECORD_H
+#endif // BITCOIN_QT_TRANSACTIONRECORD_H
diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h
index bb517a969c..cfefe4cf19 100644
--- a/src/qt/transactiontablemodel.h
+++ b/src/qt/transactiontablemodel.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef TRANSACTIONTABLEMODEL_H
-#define TRANSACTIONTABLEMODEL_H
+#ifndef BITCOIN_QT_TRANSACTIONTABLEMODEL_H
+#define BITCOIN_QT_TRANSACTIONTABLEMODEL_H
#include "bitcoinunits.h"
@@ -109,4 +109,4 @@ public slots:
friend class TransactionTablePriv;
};
-#endif // TRANSACTIONTABLEMODEL_H
+#endif // BITCOIN_QT_TRANSACTIONTABLEMODEL_H
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index b249e00411..be6989adee 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef TRANSACTIONVIEW_H
-#define TRANSACTIONVIEW_H
+#ifndef BITCOIN_QT_TRANSACTIONVIEW_H
+#define BITCOIN_QT_TRANSACTIONVIEW_H
#include "guiutil.h"
@@ -112,4 +112,4 @@ public slots:
};
-#endif // TRANSACTIONVIEW_H
+#endif // BITCOIN_QT_TRANSACTIONVIEW_H
diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h
index ae5045cca9..e10b4dc8af 100644
--- a/src/qt/utilitydialog.h
+++ b/src/qt/utilitydialog.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef UTILITYDIALOG_H
-#define UTILITYDIALOG_H
+#ifndef BITCOIN_QT_UTILITYDIALOG_H
+#define BITCOIN_QT_UTILITYDIALOG_H
#include <QDialog>
#include <QObject>
@@ -49,4 +49,4 @@ protected:
void closeEvent(QCloseEvent *event);
};
-#endif // UTILITYDIALOG_H
+#endif // BITCOIN_QT_UTILITYDIALOG_H
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
index f1830a0d6b..ae8592840d 100644
--- a/src/qt/walletframe.h
+++ b/src/qt/walletframe.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef WALLETFRAME_H
-#define WALLETFRAME_H
+#ifndef BITCOIN_QT_WALLETFRAME_H
+#define BITCOIN_QT_WALLETFRAME_H
#include <QFrame>
#include <QMap>
@@ -77,4 +77,4 @@ public slots:
void usedReceivingAddresses();
};
-#endif // WALLETFRAME_H
+#endif // BITCOIN_QT_WALLETFRAME_H
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 fe91e9d9fa..d7e391f8d1 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef WALLETMODEL_H
-#define WALLETMODEL_H
+#ifndef BITCOIN_QT_WALLETMODEL_H
+#define BITCOIN_QT_WALLETMODEL_H
#include "paymentrequestplus.h"
#include "walletmodeltransaction.h"
@@ -110,7 +110,8 @@ public:
AmountWithFeeExceedsBalance,
DuplicateAddress,
TransactionCreationFailed, // Error returned when wallet is still locked
- TransactionCommitFailed
+ TransactionCommitFailed,
+ InsaneFee
};
enum EncryptionStatus
@@ -261,4 +262,4 @@ public slots:
void pollBalanceChanged();
};
-#endif // WALLETMODEL_H
+#endif // BITCOIN_QT_WALLETMODEL_H
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 4eadfbe4d1..4272529abe 100644
--- a/src/qt/walletmodeltransaction.h
+++ b/src/qt/walletmodeltransaction.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef WALLETMODELTRANSACTION_H
-#define WALLETMODELTRANSACTION_H
+#ifndef BITCOIN_QT_WALLETMODELTRANSACTION_H
+#define BITCOIN_QT_WALLETMODELTRANSACTION_H
#include "walletmodel.h"
@@ -25,6 +25,7 @@ public:
QList<SendCoinsRecipient> getRecipients();
CWalletTx *getTransaction();
+ unsigned int getTransactionSize();
void setTransactionFee(const CAmount& newFee);
CAmount getTransactionFee();
@@ -41,4 +42,4 @@ private:
CAmount fee;
};
-#endif // WALLETMODELTRANSACTION_H
+#endif // BITCOIN_QT_WALLETMODELTRANSACTION_H
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/qt/walletview.h b/src/qt/walletview.h
index cafba517fd..95890ccd67 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef WALLETVIEW_H
-#define WALLETVIEW_H
+#ifndef BITCOIN_QT_WALLETVIEW_H
+#define BITCOIN_QT_WALLETVIEW_H
#include "amount.h"
@@ -116,4 +116,4 @@ signals:
void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address);
};
-#endif // WALLETVIEW_H
+#endif // BITCOIN_QT_WALLETVIEW_H
diff --git a/src/qt/winshutdownmonitor.h b/src/qt/winshutdownmonitor.h
index 4c76d2c816..26f5d80361 100644
--- a/src/qt/winshutdownmonitor.h
+++ b/src/qt/winshutdownmonitor.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef WINSHUTDOWNMONITOR_H
-#define WINSHUTDOWNMONITOR_H
+#ifndef BITCOIN_QT_WINSHUTDOWNMONITOR_H
+#define BITCOIN_QT_WINSHUTDOWNMONITOR_H
#ifdef WIN32
#include <QByteArray>
@@ -26,4 +26,4 @@ public:
#endif
#endif
-#endif // WINSHUTDOWNMONITOR_H
+#endif // BITCOIN_QT_WINSHUTDOWNMONITOR_H
diff --git a/src/random.cpp b/src/random.cpp
index 998e7dfb08..fc9505ae73 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -82,13 +82,12 @@ void RandAddSeedPerfmon()
#endif
}
-bool GetRandBytes(unsigned char* buf, int num)
+void GetRandBytes(unsigned char* buf, int num)
{
if (RAND_bytes(buf, num) != 1) {
LogPrintf("%s: OpenSSL RAND_bytes() failed with error: %s\n", __func__, ERR_error_string(ERR_get_error(), NULL));
- return false;
+ assert(false);
}
- return true;
}
uint64_t GetRand(uint64_t nMax)
diff --git a/src/random.h b/src/random.h
index 161ebe8986..ec73d910c4 100644
--- a/src/random.h
+++ b/src/random.h
@@ -19,7 +19,7 @@ void RandAddSeedPerfmon();
/**
* Functions to gather random data via the OpenSSL PRNG
*/
-bool GetRandBytes(unsigned char* buf, int num);
+void GetRandBytes(unsigned char* buf, int num);
uint64_t GetRand(uint64_t nMax);
int GetRandInt(int nMax);
uint256 GetRandHash();
diff --git a/src/rest.cpp b/src/rest.cpp
new file mode 100644
index 0000000000..122b361719
--- /dev/null
+++ b/src/rest.cpp
@@ -0,0 +1,206 @@
+// 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 "core/block.h"
+#include "core/transaction.h"
+#include "main.h"
+#include "rpcserver.h"
+#include "streams.h"
+#include "sync.h"
+#include "utilstrencodings.h"
+#include "version.h"
+
+#include <boost/algorithm/string.hpp>
+
+using namespace std;
+using namespace json_spirit;
+
+enum RetFormat {
+ RF_BINARY,
+ RF_HEX,
+ RF_JSON,
+};
+
+static const struct {
+ enum RetFormat rf;
+ const char *name;
+} rf_names[] = {
+ { RF_BINARY, "binary" }, // default, if match not found
+ { RF_HEX, "hex" },
+ { RF_JSON, "json" },
+};
+
+class RestErr {
+public:
+ enum HTTPStatusCode status;
+ string message;
+};
+
+extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
+extern Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex);
+
+static RestErr RESTERR(enum HTTPStatusCode status, string message)
+{
+ RestErr re;
+ re.status = status;
+ re.message = message;
+ return re;
+}
+
+static enum RetFormat ParseDataFormat(const string& format)
+{
+ for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++)
+ if (format == rf_names[i].name)
+ return rf_names[i].rf;
+
+ return rf_names[0].rf;
+}
+
+static bool ParseHashStr(const string& strReq, uint256& v)
+{
+ if (!IsHex(strReq) || (strReq.size() != 64))
+ return false;
+
+ v.SetHex(strReq);
+ return true;
+}
+
+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(""));
+
+ string hashStr = params[0];
+ uint256 hash;
+ if (!ParseHashStr(hashStr, hash))
+ throw RESTERR(HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
+
+ CBlock block;
+ CBlockIndex* pblockindex = NULL;
+ {
+ LOCK(cs_main);
+ if (mapBlockIndex.count(hash) == 0)
+ throw RESTERR(HTTP_NOT_FOUND, hashStr + " not found");
+
+ pblockindex = mapBlockIndex[hash];
+ if (!ReadBlockFromDisk(block, pblockindex))
+ throw RESTERR(HTTP_NOT_FOUND, hashStr + " not found");
+ }
+
+ CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
+ ssBlock << block;
+
+ switch (rf) {
+ case RF_BINARY: {
+ string binaryBlock = ssBlock.str();
+ conn->stream() << HTTPReply(HTTP_OK, binaryBlock, fRun, true, "application/octet-stream") << binaryBlock << std::flush;
+ return true;
+ }
+
+ case RF_HEX: {
+ string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";;
+ conn->stream() << HTTPReply(HTTP_OK, strHex, fRun, false, "text/plain") << std::flush;
+ return true;
+ }
+
+ case RF_JSON: {
+ Object objBlock = blockToJSON(block, pblockindex);
+ string strJSON = write_string(Value(objBlock), false) + "\n";
+ conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
+ return true;
+ }
+ }
+
+ // not reached
+ return true; // continue to process further HTTP reqs on this cxn
+}
+
+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(""));
+
+ string hashStr = params[0];
+ uint256 hash;
+ if (!ParseHashStr(hashStr, hash))
+ throw RESTERR(HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
+
+ CTransaction tx;
+ uint256 hashBlock = 0;
+ if (!GetTransaction(hash, tx, hashBlock, true))
+ throw RESTERR(HTTP_NOT_FOUND, hashStr + " not found");
+
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ ssTx << tx;
+
+ switch (rf) {
+ case RF_BINARY: {
+ string binaryTx = ssTx.str();
+ conn->stream() << HTTPReply(HTTP_OK, binaryTx, fRun, true, "application/octet-stream") << binaryTx << std::flush;
+ return true;
+ }
+
+ case RF_HEX: {
+ string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";;
+ conn->stream() << HTTPReply(HTTP_OK, strHex, fRun, false, "text/plain") << std::flush;
+ return true;
+ }
+
+ case RF_JSON: {
+ Object objTx;
+ TxToJSON(tx, hashBlock, objTx);
+ string strJSON = write_string(Value(objTx), false) + "\n";
+ conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
+ return true;
+ }
+ }
+
+ // not reached
+ return true; // continue to process further HTTP reqs on this cxn
+}
+
+static const struct {
+ 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 },
+};
+
+bool HTTPReq_REST(AcceptedConnection *conn,
+ string& strURI,
+ map<string, string>& mapHeaders,
+ bool fRun)
+{
+ try {
+ 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) {
+ string strReq = strURI.substr(plen);
+ return uri_prefixes[i].handler(conn, strReq, mapHeaders, fRun);
+ }
+ }
+ }
+ catch (RestErr& re) {
+ conn->stream() << HTTPReply(re.status, re.message + "\r\n", false, false, "text/plain") << std::flush;
+ return false;
+ }
+
+ conn->stream() << HTTPError(HTTP_NOT_FOUND, false) << std::flush;
+ return false;
+}
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 78f5569895..e8b0f62a83 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,13 +468,13 @@ 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
{
/* Make sure that unequal blocks with the same height do not compare
- equal. Use the pointers themselves to make a distinction. */
+ equal. Use the pointers themselves to make a distinction. */
if (a->nHeight != b->nHeight)
return (a->nHeight > b->nHeight);
diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp
index a9c491cede..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,13 +18,14 @@ 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[] =
{
{ "stop", 0 },
+ { "setmocktime", 0 },
{ "getaddednodeinfo", 0 },
{ "setgenerate", 0 },
{ "setgenerate", 1 },
@@ -115,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 307aa2aab8..a91c2eb033 100644
--- a/src/rpcclient.h
+++ b/src/rpcclient.h
@@ -1,10 +1,10 @@
// 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 _BITCOINRPC_CLIENT_H_
-#define _BITCOINRPC_CLIENT_H_
+#ifndef BITCOIN_RPCCLIENT_H
+#define BITCOIN_RPCCLIENT_H
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
@@ -12,4 +12,4 @@
json_spirit::Array RPCConvertValues(const std::string& strMethod, const std::vector<std::string>& strParams);
-#endif // _BITCOINRPC_CLIENT_H_
+#endif // 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 8af3c46348..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();
@@ -121,6 +123,8 @@ Value setgenerate(const Array& params, bool fHelp)
"1. generate (boolean, required) Set to true to turn on generation, off to turn off.\n"
"2. genproclimit (numeric, optional) Set the processor limit for when generation is on. Can be -1 for unlimited.\n"
" Note: in -regtest mode, genproclimit controls how many blocks are generated immediately.\n"
+ "\nResult\n"
+ "[ blockhashes ] (array, -regtest only) hashes of blocks generated\n"
"\nExamples:\n"
"\nSet the generation on with a limit of one processor\n"
+ HelpExampleCli("setgenerate", "true 1") +
@@ -154,26 +158,38 @@ Value setgenerate(const Array& params, bool fHelp)
int nHeightEnd = 0;
int nHeight = 0;
int nGenerate = (nGenProcLimit > 0 ? nGenProcLimit : 1);
+ CReserveKey reservekey(pwalletMain);
+
{ // Don't keep cs_main locked
LOCK(cs_main);
nHeightStart = chainActive.Height();
nHeight = nHeightStart;
nHeightEnd = nHeightStart+nGenerate;
}
- int nHeightLast = -1;
+ unsigned int nExtraNonce = 0;
+ Array blockHashes;
while (nHeight < nHeightEnd)
{
- if (nHeightLast != nHeight)
+ auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
+ if (!pblocktemplate.get())
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
+ CBlock *pblock = &pblocktemplate->block;
{
- nHeightLast = nHeight;
- GenerateBitcoins(fGenerate, pwalletMain, 1);
- }
- MilliSleep(1);
- { // Don't keep cs_main locked
LOCK(cs_main);
- nHeight = chainActive.Height();
+ IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
+ }
+ while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits)) {
+ // Yes, there is a chance every nonce could fail to satisfy the -regtest
+ // target -- 1 in 2^(2^32). That ain't gonna happen.
+ ++pblock->nNonce;
}
+ CValidationState state;
+ if (!ProcessNewBlock(state, NULL, pblock))
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
+ ++nHeight;
+ blockHashes.push_back(pblock->GetHash().GetHex());
}
+ return blockHashes;
}
else // Not -regtest: start generate thread, return immediately
{
@@ -283,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)
@@ -360,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")
@@ -462,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;
@@ -508,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));
@@ -527,6 +595,24 @@ Value getblocktemplate(const Array& params, bool fHelp)
return result;
}
+class submitblock_StateCatcher : public CValidationInterface
+{
+public:
+ uint256 hash;
+ bool found;
+ CValidationState state;
+
+ submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
+
+protected:
+ virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
+ if (block.GetHash() != hash)
+ return;
+ found = true;
+ state = stateIn;
+ };
+};
+
Value submitblock(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
@@ -548,22 +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;
- bool fAccepted = ProcessBlock(state, NULL, &pblock);
- if (!fAccepted)
- return "rejected"; // TODO: report validation state
-
- return Value::null;
+ submitblock_StateCatcher sc(block.GetHash());
+ RegisterValidationInterface(&sc);
+ 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;
+ }
+ return BIP22ValidationResult(state);
}
Value estimatefee(const Array& params, bool fHelp)
diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp
index 08e956c961..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();
@@ -354,3 +354,23 @@ Value verifymessage(const Array& params, bool fHelp)
return (pubkey.GetID() == keyID);
}
+
+Value setmocktime(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "setmocktime timestamp\n"
+ "\nSet the local time to given timestamp (-regtest only)\n"
+ "\nArguments:\n"
+ "1. timestamp (integer, required) Unix seconds-since-epoch timestamp\n"
+ " Pass 0 to go back to using the system time."
+ );
+
+ if (!Params().MineBlocksOnDemand())
+ throw runtime_error("setmocktime for regression testing (-regtest mode) only");
+
+ RPCTypeCheck(params, boost::assign::list_of(int_type));
+ SetMockTime(params[0].get_int64());
+
+ return Value::null;
+}
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 a9adb58803..a321338176 100644
--- a/src/rpcprotocol.h
+++ b/src/rpcprotocol.h
@@ -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.
-#ifndef _BITCOINRPC_PROTOCOL_H_
-#define _BITCOINRPC_PROTOCOL_H_
+#ifndef BITCOIN_RPCPROTOCOL_H
+#define BITCOIN_RPCPROTOCOL_H
#include <list>
#include <map>
@@ -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,
@@ -30,50 +30,56 @@ enum HTTPStatusCode
HTTP_INTERNAL_SERVER_ERROR = 500,
};
-// 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_TRANSACTION_ERROR = -25, // General error during transaction submission
- RPC_TRANSACTION_REJECTED = -26, // Transaction was rejected by network rules
- RPC_TRANSACTION_ALREADY_IN_CHAIN= -27, // Transaction already in chain
+ //! 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
- // 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
+ //! 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,
- // 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
+ //! 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
};
-//
-// 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:
@@ -159,4 +165,4 @@ json_spirit::Object JSONRPCReplyObj(const json_spirit::Value& result, const json
std::string JSONRPCReply(const json_spirit::Value& result, const json_spirit::Value& error, const json_spirit::Value& id);
json_spirit::Object JSONRPCError(int code, const std::string& message);
-#endif // _BITCOINRPC_PROTOCOL_H_
+#endif // BITCOIN_RPCPROTOCOL_H
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index d3ce3b3191..25734f4930 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.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"
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 08ed73f6de..7022c50375 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -34,6 +34,10 @@ using namespace std;
static std::string strRPCUserColonPass;
static bool fRPCRunning = false;
+static bool fRPCInWarmup = true;
+static std::string rpcWarmupStatus("RPC server started");
+static CCriticalSection cs_rpcWarmup;
+
//! These are created by StartRPCThreads, destroyed in StopRPCThreads
static asio::io_service* rpc_io_service = NULL;
static map<string, boost::shared_ptr<deadline_timer> > deadlineTimers;
@@ -242,6 +246,7 @@ 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 },
@@ -560,13 +565,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"
@@ -576,7 +576,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);
@@ -744,6 +743,19 @@ bool IsRPCRunning()
return fRPCRunning;
}
+void SetRPCWarmupStatus(const std::string& newStatus)
+{
+ LOCK(cs_rpcWarmup);
+ rpcWarmupStatus = newStatus;
+}
+
+void SetRPCWarmupFinished()
+{
+ LOCK(cs_rpcWarmup);
+ assert(fRPCInWarmup);
+ fRPCInWarmup = false;
+}
+
void RPCRunHandler(const boost::system::error_code& err, boost::function<void(void)> func)
{
if (!err)
@@ -870,6 +882,13 @@ static bool HTTPReq_JSONRPC(AcceptedConnection *conn,
if (!read_string(strRequest, valRequest))
throw JSONRPCError(RPC_PARSE_ERROR, "Parse error");
+ // Return immediately if in warmup
+ {
+ LOCK(cs_rpcWarmup);
+ if (fRPCInWarmup)
+ throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus);
+ }
+
string strReply;
// singleton request
@@ -922,9 +941,16 @@ void ServiceConnection(AcceptedConnection *conn)
if (mapHeaders["connection"] == "close")
fRun = false;
+ // Process via JSON-RPC API
if (strURI == "/") {
if (!HTTPReq_JSONRPC(conn, strRequest, mapHeaders, fRun))
break;
+
+ // Process via HTTP REST API
+ } else if (strURI.substr(0, 6) == "/rest/") {
+ if (!HTTPReq_REST(conn, strURI, mapHeaders, fRun))
+ break;
+
} else {
conn->stream() << HTTPError(HTTP_NOT_FOUND, false) << std::flush;
break;
diff --git a/src/rpcserver.h b/src/rpcserver.h
index cc444cef1f..7395fc23c6 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -3,12 +3,12 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef _BITCOINRPC_SERVER_H_
-#define _BITCOINRPC_SERVER_H_
+#ifndef BITCOIN_RPCSERVER_H
+#define BITCOIN_RPCSERVER_H
#include "amount.h"
-#include "uint256.h"
#include "rpcprotocol.h"
+#include "uint256.h"
#include <list>
#include <map>
@@ -40,11 +40,19 @@ 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
+ * 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();
+
/**
* 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.
@@ -187,6 +195,7 @@ extern json_spirit::Value getinfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getwalletinfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getblockchaininfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getnetworkinfo(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value setmocktime(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp
extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp);
@@ -211,4 +220,10 @@ 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);
-#endif // _BITCOINRPC_SERVER_H_
+// in rest.cpp
+extern bool HTTPReq_REST(AcceptedConnection *conn,
+ std::string& strURI,
+ std::map<std::string, std::string>& mapHeaders,
+ bool fRun);
+
+#endif // BITCOIN_RPCSERVER_H
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index f2b5e2061e..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"
@@ -1067,7 +1067,7 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
"\nList balances by receiving address.\n"
"\nArguments:\n"
"1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
- "2. includeempty (numeric, optional, dafault=false) Whether to include addresses that haven't received any payments.\n"
+ "2. includeempty (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
"3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
"\nResult:\n"
@@ -1335,7 +1335,7 @@ Value listaccounts(const Array& params, bool fHelp)
"listaccounts ( minconf includeWatchonly)\n"
"\nReturns Object that has account names as keys, account balances as values.\n"
"\nArguments:\n"
- "1. minconf (numeric, optional, default=1) Only onclude transactions with at least this many confirmations\n"
+ "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
"2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n"
"\nResult:\n"
"{ (json object where keys are account names, and values are numeric balances\n"
diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
new file mode 100644
index 0000000000..4faa760ad7
--- /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 "core/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 3625972ebf..a10cefcc0b 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -9,21 +9,32 @@
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha2.h"
-#include "key.h"
+#include "eccryptoverify.h"
+#include "pubkey.h"
#include "script/script.h"
#include "uint256.h"
-#include "util.h"
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 {
+
+inline bool set_success(ScriptError* ret)
+{
+ if (ret)
+ *ret = SCRIPT_ERR_OK;
+ return true;
+}
+
+inline bool set_error(ScriptError* ret, const ScriptError serror)
+{
+ if (ret)
+ *ret = serror;
+ return false;
+}
+
+} // anon namespace
bool CastToBool(const valtype& vch)
{
@@ -40,10 +51,10 @@ bool CastToBool(const valtype& vch)
return false;
}
-//
-// Script is a stack machine (like Forth) that evaluates a predicate
-// returning a bool indicating valid or not. There are no loops.
-//
+/**
+ * Script is a stack machine (like Forth) that evaluates a predicate
+ * returning a bool indicating valid or not. There are no loops.
+ */
#define stacktop(i) (stack.at(stack.size()+(i)))
#define altstacktop(i) (altstack.at(altstack.size()+(i)))
static inline void popstack(vector<valtype>& stack)
@@ -54,67 +65,105 @@ static inline void popstack(vector<valtype>& stack)
}
bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) {
- if (vchPubKey.size() < 33)
- return error("Non-canonical public key: too short");
+ if (vchPubKey.size() < 33) {
+ // Non-canonical public key: too short
+ return false;
+ }
if (vchPubKey[0] == 0x04) {
- if (vchPubKey.size() != 65)
- return error("Non-canonical public key: invalid length for uncompressed key");
+ if (vchPubKey.size() != 65) {
+ // Non-canonical public key: invalid length for uncompressed key
+ return false;
+ }
} else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) {
- if (vchPubKey.size() != 33)
- return error("Non-canonical public key: invalid length for compressed key");
+ if (vchPubKey.size() != 33) {
+ // Non-canonical public key: invalid length for compressed key
+ return false;
+ }
} else {
- return error("Non-canonical public key: neither compressed nor uncompressed");
+ // Non-canonical public key: neither compressed nor uncompressed
+ return false;
}
return true;
}
+/**
+ * A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype>
+ * Where R and S are not negative (their first byte has its highest bit not set), and not
+ * excessively padded (do not start with a 0 byte, unless an otherwise negative number follows,
+ * in which case a single 0 byte is necessary and even required).
+ *
+ * See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
+ */
bool static IsDERSignature(const valtype &vchSig) {
- // See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
- // A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype>
- // Where R and S are not negative (their first byte has its highest bit not set), and not
- // excessively padded (do not start with a 0 byte, unless an otherwise negative number follows,
- // in which case a single 0 byte is necessary and even required).
- if (vchSig.size() < 9)
- return error("Non-canonical signature: too short");
- if (vchSig.size() > 73)
- return error("Non-canonical signature: too long");
- if (vchSig[0] != 0x30)
- return error("Non-canonical signature: wrong type");
- if (vchSig[1] != vchSig.size()-3)
- return error("Non-canonical signature: wrong length marker");
+
+ if (vchSig.size() < 9) {
+ // Non-canonical signature: too short
+ return false;
+ }
+ if (vchSig.size() > 73) {
+ // Non-canonical signature: too long
+ return false;
+ }
+ if (vchSig[0] != 0x30) {
+ // Non-canonical signature: wrong type
+ return false;
+ }
+ if (vchSig[1] != vchSig.size()-3) {
+ // Non-canonical signature: wrong length marker
+ return false;
+ }
unsigned int nLenR = vchSig[3];
- if (5 + nLenR >= vchSig.size())
- return error("Non-canonical signature: S length misplaced");
+ if (5 + nLenR >= vchSig.size()) {
+ // Non-canonical signature: S length misplaced
+ return false;
+ }
unsigned int nLenS = vchSig[5+nLenR];
- if ((unsigned long)(nLenR+nLenS+7) != vchSig.size())
- return error("Non-canonical signature: R+S length mismatch");
+ if ((unsigned long)(nLenR+nLenS+7) != vchSig.size()) {
+ // Non-canonical signature: R+S length mismatch
+ return false;
+ }
const unsigned char *R = &vchSig[4];
- if (R[-2] != 0x02)
- return error("Non-canonical signature: R value type mismatch");
- if (nLenR == 0)
- return error("Non-canonical signature: R length is zero");
- if (R[0] & 0x80)
- return error("Non-canonical signature: R value negative");
- if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80))
- return error("Non-canonical signature: R value excessively padded");
+ if (R[-2] != 0x02) {
+ // Non-canonical signature: R value type mismatch
+ return false;
+ }
+ if (nLenR == 0) {
+ // Non-canonical signature: R length is zero
+ return false;
+ }
+ if (R[0] & 0x80) {
+ // Non-canonical signature: R value negative
+ return false;
+ }
+ if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80)) {
+ // Non-canonical signature: R value excessively padded
+ return false;
+ }
const unsigned char *S = &vchSig[6+nLenR];
- if (S[-2] != 0x02)
- return error("Non-canonical signature: S value type mismatch");
- if (nLenS == 0)
- return error("Non-canonical signature: S length is zero");
- if (S[0] & 0x80)
- return error("Non-canonical signature: S value negative");
- if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80))
- return error("Non-canonical signature: S value excessively padded");
-
+ if (S[-2] != 0x02) {
+ // Non-canonical signature: S value type mismatch
+ return false;
+ }
+ if (nLenS == 0) {
+ // Non-canonical signature: S length is zero
+ return false;
+ }
+ if (S[0] & 0x80) {
+ // Non-canonical signature: S value negative
+ return false;
+ }
+ if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) {
+ // Non-canonical signature: S value excessively padded
+ return false;
+ }
return true;
}
-bool static IsLowDERSignature(const valtype &vchSig) {
+bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) {
if (!IsDERSignature(vchSig)) {
- return false;
+ return set_error(serror, SCRIPT_ERR_SIG_DER);
}
unsigned int nLenR = vchSig[3];
unsigned int nLenS = vchSig[5+nLenR];
@@ -122,8 +171,8 @@ bool static IsLowDERSignature(const valtype &vchSig) {
// If the S value is above the order of the curve divided by two, its
// complement modulo the order could have been used instead, which is
// one byte shorter when encoded correctly.
- if (!CKey::CheckSignatureElement(S, nLenS, true))
- return error("Non-canonical signature: S value is unnecessarily high");
+ if (!eccrypto::CheckSignatureElement(S, nLenS, true))
+ return set_error(serror, SCRIPT_ERR_SIG_HIGH_S);
return true;
}
@@ -134,25 +183,26 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
}
unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY));
if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE)
- return error("Non-canonical signature: unknown hashtype byte");
+ return false;
return true;
}
-bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags) {
+bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsDERSignature(vchSig)) {
- return false;
- } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig)) {
+ return set_error(serror, SCRIPT_ERR_SIG_DER);
+ } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig, serror)) {
+ // serror is set
return false;
} else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsDefinedHashtypeSignature(vchSig)) {
- return false;
+ return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE);
}
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;
}
@@ -180,8 +230,16 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
return true;
}
-bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker)
+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();
@@ -189,8 +247,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
valtype vchPushValue;
vector<bool> vfExec;
vector<valtype> altstack;
+ set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
if (script.size() > 10000)
- return false;
+ return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE);
int nOpCount = 0;
bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0;
@@ -204,13 +263,13 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// Read instruction
//
if (!script.GetOp(pc, opcode, vchPushValue))
- return false;
+ return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE)
- return false;
+ return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
// Note how OP_RESERVED does not count towards the opcode limit.
if (opcode > OP_16 && ++nOpCount > 201)
- return false;
+ return set_error(serror, SCRIPT_ERR_OP_COUNT);
if (opcode == OP_CAT ||
opcode == OP_SUBSTR ||
@@ -227,11 +286,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
opcode == OP_MOD ||
opcode == OP_LSHIFT ||
opcode == OP_RSHIFT)
- return false; // Disabled opcodes.
+ return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes.
if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) {
if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) {
- return false;
+ return set_error(serror, SCRIPT_ERR_MINIMALDATA);
}
stack.push_back(vchPushValue);
} else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
@@ -271,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:
@@ -283,7 +348,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (fExec)
{
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
valtype& vch = stacktop(-1);
fValue = CastToBool(vch);
if (opcode == OP_NOTIF)
@@ -297,7 +362,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
case OP_ELSE:
{
if (vfExec.empty())
- return false;
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
vfExec.back() = !vfExec.back();
}
break;
@@ -305,7 +370,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
case OP_ENDIF:
{
if (vfExec.empty())
- return false;
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
vfExec.pop_back();
}
break;
@@ -315,18 +380,18 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// (true -- ) or
// (false -- false) and return
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
bool fValue = CastToBool(stacktop(-1));
if (fValue)
popstack(stack);
else
- return false;
+ return set_error(serror, SCRIPT_ERR_VERIFY);
}
break;
case OP_RETURN:
{
- return false;
+ return set_error(serror, SCRIPT_ERR_OP_RETURN);
}
break;
@@ -337,7 +402,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
case OP_TOALTSTACK:
{
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
altstack.push_back(stacktop(-1));
popstack(stack);
}
@@ -346,7 +411,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
case OP_FROMALTSTACK:
{
if (altstack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION);
stack.push_back(altstacktop(-1));
popstack(altstack);
}
@@ -356,7 +421,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- )
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
popstack(stack);
popstack(stack);
}
@@ -366,7 +431,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- x1 x2 x1 x2)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch1 = stacktop(-2);
valtype vch2 = stacktop(-1);
stack.push_back(vch1);
@@ -378,7 +443,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
if (stack.size() < 3)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch1 = stacktop(-3);
valtype vch2 = stacktop(-2);
valtype vch3 = stacktop(-1);
@@ -392,7 +457,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
if (stack.size() < 4)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch1 = stacktop(-4);
valtype vch2 = stacktop(-3);
stack.push_back(vch1);
@@ -404,7 +469,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
if (stack.size() < 6)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch1 = stacktop(-6);
valtype vch2 = stacktop(-5);
stack.erase(stack.end()-6, stack.end()-4);
@@ -417,7 +482,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 x3 x4 -- x3 x4 x1 x2)
if (stack.size() < 4)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
swap(stacktop(-4), stacktop(-2));
swap(stacktop(-3), stacktop(-1));
}
@@ -427,7 +492,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x - 0 | x x)
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch = stacktop(-1);
if (CastToBool(vch))
stack.push_back(vch);
@@ -446,7 +511,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x -- )
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
popstack(stack);
}
break;
@@ -455,7 +520,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x -- x x)
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch = stacktop(-1);
stack.push_back(vch);
}
@@ -465,7 +530,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- x2)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
stack.erase(stack.end() - 2);
}
break;
@@ -474,7 +539,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- x1 x2 x1)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch = stacktop(-2);
stack.push_back(vch);
}
@@ -486,11 +551,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
// (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
int n = CScriptNum(stacktop(-1), fRequireMinimal).getint();
popstack(stack);
if (n < 0 || n >= (int)stack.size())
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch = stacktop(-n-1);
if (opcode == OP_ROLL)
stack.erase(stack.end()-n-1);
@@ -504,7 +569,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// x2 x1 x3 after first swap
// x2 x3 x1 after second swap
if (stack.size() < 3)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
swap(stacktop(-3), stacktop(-2));
swap(stacktop(-2), stacktop(-1));
}
@@ -514,7 +579,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- x2 x1)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
swap(stacktop(-2), stacktop(-1));
}
break;
@@ -523,7 +588,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- x2 x1 x2)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype vch = stacktop(-1);
stack.insert(stack.end()-2, vch);
}
@@ -534,7 +599,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (in -- in size)
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
CScriptNum bn(stacktop(-1).size());
stack.push_back(bn.getvch());
}
@@ -550,7 +615,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 - bool)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype& vch1 = stacktop(-2);
valtype& vch2 = stacktop(-1);
bool fEqual = (vch1 == vch2);
@@ -567,7 +632,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (fEqual)
popstack(stack);
else
- return false;
+ return set_error(serror, SCRIPT_ERR_EQUALVERIFY);
}
}
break;
@@ -585,7 +650,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (in -- out)
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
CScriptNum bn(stacktop(-1), fRequireMinimal);
switch (opcode)
{
@@ -618,7 +683,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x1 x2 -- out)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
CScriptNum bn1(stacktop(-2), fRequireMinimal);
CScriptNum bn2(stacktop(-1), fRequireMinimal);
CScriptNum bn(0);
@@ -654,7 +719,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (CastToBool(stacktop(-1)))
popstack(stack);
else
- return false;
+ return set_error(serror, SCRIPT_ERR_NUMEQUALVERIFY);
}
}
break;
@@ -663,7 +728,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (x min max -- out)
if (stack.size() < 3)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
CScriptNum bn1(stacktop(-3), fRequireMinimal);
CScriptNum bn2(stacktop(-2), fRequireMinimal);
CScriptNum bn3(stacktop(-1), fRequireMinimal);
@@ -687,7 +752,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (in -- hash)
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype& vch = stacktop(-1);
valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32);
if (opcode == OP_RIPEMD160)
@@ -717,7 +782,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
{
// (sig pubkey -- bool)
if (stack.size() < 2)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
valtype& vchSig = stacktop(-2);
valtype& vchPubKey = stacktop(-1);
@@ -728,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)) {
+ 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);
@@ -742,7 +807,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (fSuccess)
popstack(stack);
else
- return false;
+ return set_error(serror, SCRIPT_ERR_CHECKSIGVERIFY);
}
}
break;
@@ -754,26 +819,26 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
int i = 1;
if ((int)stack.size() < i)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
if (nKeysCount < 0 || nKeysCount > 20)
- return false;
+ return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT);
nOpCount += nKeysCount;
if (nOpCount > 201)
- return false;
+ return set_error(serror, SCRIPT_ERR_OP_COUNT);
int ikey = ++i;
i += nKeysCount;
if ((int)stack.size() < i)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
int nSigsCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
if (nSigsCount < 0 || nSigsCount > nKeysCount)
- return false;
+ return set_error(serror, SCRIPT_ERR_SIG_COUNT);
int isig = ++i;
i += nSigsCount;
if ((int)stack.size() < i)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
// Subset of script starting at the most recent codeseparator
CScript scriptCode(pbegincodehash, pend);
@@ -791,12 +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)) {
+ // 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++;
@@ -806,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;
}
@@ -822,9 +892,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
// so optionally verify it is exactly equal to zero prior
// to removing it from the stack.
if (stack.size() < 1)
- return false;
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
if ((flags & SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).size())
- return error("CHECKMULTISIG dummy argument not null");
+ return set_error(serror, SCRIPT_ERR_SIG_NULLDUMMY);
popstack(stack);
stack.push_back(fSuccess ? vchTrue : vchFalse);
@@ -834,44 +904,45 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
if (fSuccess)
popstack(stack);
else
- return false;
+ return set_error(serror, SCRIPT_ERR_CHECKMULTISIGVERIFY);
}
}
break;
default:
- return false;
+ return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
}
// Size limits
if (stack.size() + altstack.size() > 1000)
- return false;
+ return set_error(serror, SCRIPT_ERR_STACK_SIZE);
}
}
catch (...)
{
- return false;
+ return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
}
if (!vfExec.empty())
- return false;
+ return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
- return true;
+ return set_success(serror);
}
namespace {
-/** Wrapper that serializes like CTransaction, but with the modifications
+/**
+ * Wrapper that serializes like CTransaction, but with the modifications
* required for the signature hash done in-place
*/
class CTransactionSignatureSerializer {
private:
- const CTransaction &txTo; // reference to the spending transaction (the one being serialized)
- const CScript &scriptCode; // output script being consumed
- const unsigned int nIn; // input index of txTo being signed
- const bool fAnyoneCanPay; // whether the hashtype has the SIGHASH_ANYONECANPAY flag set
- const bool fHashSingle; // whether the hashtype is SIGHASH_SINGLE
- const bool fHashNone; // whether the hashtype is SIGHASH_NONE
+ const CTransaction &txTo; //! reference to the spending transaction (the one being serialized)
+ const CScript &scriptCode; //! output script being consumed
+ const unsigned int nIn; //! input index of txTo being signed
+ const bool fAnyoneCanPay; //! whether the hashtype has the SIGHASH_ANYONECANPAY flag set
+ const bool fHashSingle; //! whether the hashtype is SIGHASH_SINGLE
+ const bool fHashNone; //! whether the hashtype is SIGHASH_NONE
public:
CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
@@ -950,7 +1021,7 @@ public:
::WriteCompactSize(s, nOutputs);
for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++)
SerializeOutput(s, nOutput, nType, nVersion);
- // Serialie nLockTime
+ // Serialize nLockTime
::Serialize(s, txTo.nLockTime, nType, nVersion);
}
};
@@ -960,14 +1031,14 @@ public:
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
if (nIn >= txTo.vin.size()) {
- LogPrintf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
+ // nIn out of range
return 1;
}
// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
- LogPrintf("ERROR: SignatureHash() : nOut=%d out of range\n", nIn);
+ // nOut out of range
return 1;
}
}
@@ -1007,30 +1078,35 @@ bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vec
return true;
}
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker)
+bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
+ set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
+
if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) {
- return false;
+ return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
}
vector<vector<unsigned char> > stack, stackCopy;
- if (!EvalScript(stack, scriptSig, flags, checker))
+ if (!EvalScript(stack, scriptSig, flags, checker, serror))
+ // serror is set
return false;
if (flags & SCRIPT_VERIFY_P2SH)
stackCopy = stack;
- if (!EvalScript(stack, scriptPubKey, flags, checker))
+ if (!EvalScript(stack, scriptPubKey, flags, checker, serror))
+ // serror is set
return false;
if (stack.empty())
- return false;
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
if (CastToBool(stack.back()) == false)
- return false;
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
// Additional validation for spend-to-script-hash transactions:
if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash())
{
- if (!scriptSig.IsPushOnly()) // scriptSig must be literals-only
- return false; // or validation fails
+ // scriptSig must be literals-only or validation fails
+ if (!scriptSig.IsPushOnly())
+ return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
// stackCopy cannot be empty here, because if it was the
// P2SH HASH <> EQUAL scriptPubKey would be evaluated with
@@ -1041,12 +1117,16 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
popstack(stackCopy);
- if (!EvalScript(stackCopy, pubKey2, flags, checker))
+ if (!EvalScript(stackCopy, pubKey2, flags, checker, serror))
+ // serror is set
return false;
if (stackCopy.empty())
- return false;
- return CastToBool(stackCopy.back());
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ if (!CastToBool(stackCopy.back()))
+ return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ else
+ return set_success(serror);
}
- return true;
+ return set_success(serror);
}
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 5133c80aab..35b2f6c65a 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -3,8 +3,10 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef H_BITCOIN_SCRIPT_INTERPRETER
-#define H_BITCOIN_SCRIPT_INTERPRETER
+#ifndef BITCOIN_SCRIPT_INTERPRETER_H
+#define BITCOIN_SCRIPT_INTERPRETER_H
+
+#include "script_error.h"
#include <vector>
#include <stdint.h>
@@ -33,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)
@@ -55,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);
@@ -85,7 +98,7 @@ public:
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const;
};
-bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker);
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker);
+bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
+bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* error = NULL);
-#endif // H_BITCOIN_SCRIPT_INTERPRETER
+#endif // BITCOIN_SCRIPT_INTERPRETER_H
diff --git a/src/script/script.h b/src/script/script.h
index 05f2e7e3a9..9c22cb908c 100644
--- a/src/script/script.h
+++ b/src/script/script.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 H_BITCOIN_SCRIPT
-#define H_BITCOIN_SCRIPT
+#ifndef BITCOIN_SCRIPT_SCRIPT_H
+#define BITCOIN_SCRIPT_SCRIPT_H
#include <assert.h>
#include <climits>
@@ -179,12 +179,14 @@ public:
class CScriptNum
{
-// Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers.
-// The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1],
-// but results may overflow (and are valid as long as they are not used in a subsequent
-// numeric operation). CScriptNum enforces those semantics by storing results as
-// an int64 and allowing out-of-range values to be returned as a vector of bytes but
-// throwing an exception if arithmetic is done or the result is interpreted as an integer.
+/**
+ * Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers.
+ * The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1],
+ * but results may overflow (and are valid as long as they are not used in a subsequent
+ * numeric operation). CScriptNum enforces those semantics by storing results as
+ * an int64 and allowing out-of-range values to be returned as a vector of bytes but
+ * throwing an exception if arithmetic is done or the result is interpreted as an integer.
+ */
public:
explicit CScriptNum(const int64_t& n)
@@ -516,7 +518,7 @@ public:
return true;
}
- // Encode/decode small integers:
+ /** Encode/decode small integers: */
static int DecodeOP_N(opcodetype opcode)
{
if (opcode == OP_0)
@@ -560,25 +562,31 @@ public:
return nFound;
}
- // Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
- // as 20 sigops. With pay-to-script-hash, that changed:
- // CHECKMULTISIGs serialized in scriptSigs are
- // counted more accurately, assuming they are of the form
- // ... OP_N CHECKMULTISIG ...
+ /**
+ * Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
+ * as 20 sigops. With pay-to-script-hash, that changed:
+ * CHECKMULTISIGs serialized in scriptSigs are
+ * counted more accurately, assuming they are of the form
+ * ... OP_N CHECKMULTISIG ...
+ */
unsigned int GetSigOpCount(bool fAccurate) const;
- // Accurately count sigOps, including sigOps in
- // pay-to-script-hash transactions:
+ /**
+ * Accurately count sigOps, including sigOps in
+ * pay-to-script-hash transactions:
+ */
unsigned int GetSigOpCount(const CScript& scriptSig) const;
bool IsPayToScriptHash() const;
- // Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical).
+ /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */
bool IsPushOnly() const;
- // Returns whether the script is guaranteed to fail at execution,
- // regardless of the initial stack. This allows outputs to be pruned
- // instantly when entering the UTXO set.
+ /**
+ * Returns whether the script is guaranteed to fail at execution,
+ * regardless of the initial stack. This allows outputs to be pruned
+ * instantly when entering the UTXO set.
+ */
bool IsUnspendable() const
{
return (size() > 0 && *begin() == OP_RETURN);
@@ -592,4 +600,4 @@ public:
}
};
-#endif // H_BITCOIN_SCRIPT
+#endif // BITCOIN_SCRIPT_SCRIPT_H
diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp
new file mode 100644
index 0000000000..5d24ed98ba
--- /dev/null
+++ b/src/script/script_error.cpp
@@ -0,0 +1,71 @@
+// 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 "script_error.h"
+
+const char* ScriptErrorString(const ScriptError serror)
+{
+ switch (serror)
+ {
+ case SCRIPT_ERR_OK:
+ return "No error";
+ case SCRIPT_ERR_EVAL_FALSE:
+ return "Script evaluated without error but finished with a false/empty top stack element";
+ case SCRIPT_ERR_VERIFY:
+ return "Script failed an OP_VERIFY operation";
+ case SCRIPT_ERR_EQUALVERIFY:
+ return "Script failed an OP_EQUALVERIFY operation";
+ case SCRIPT_ERR_CHECKMULTISIGVERIFY:
+ return "Script failed an OP_CHECKMULTISIGVERIFY operation";
+ case SCRIPT_ERR_CHECKSIGVERIFY:
+ return "Script failed an OP_CHECKSIGVERIFY operation";
+ case SCRIPT_ERR_NUMEQUALVERIFY:
+ return "Script failed an OP_NUMEQUALVERIFY operation";
+ case SCRIPT_ERR_SCRIPT_SIZE:
+ return "Script is too big";
+ case SCRIPT_ERR_PUSH_SIZE:
+ return "Push value size limit exceeded";
+ case SCRIPT_ERR_OP_COUNT:
+ return "Operation limit exceeded";
+ case SCRIPT_ERR_STACK_SIZE:
+ return "Stack size limit exceeded";
+ case SCRIPT_ERR_SIG_COUNT:
+ return "Signature count negative or greater than pubkey count";
+ case SCRIPT_ERR_PUBKEY_COUNT:
+ return "Pubkey count negative or limit exceeded";
+ case SCRIPT_ERR_BAD_OPCODE:
+ return "Opcode missing or not understood";
+ case SCRIPT_ERR_DISABLED_OPCODE:
+ return "Attempted to use a disabled opcode";
+ case SCRIPT_ERR_INVALID_STACK_OPERATION:
+ return "Operation not valid with the current stack size";
+ case SCRIPT_ERR_INVALID_ALTSTACK_OPERATION:
+ return "Operation not valid with the current altstack size";
+ case SCRIPT_ERR_OP_RETURN:
+ return "OP_RETURN was encountered";
+ case SCRIPT_ERR_UNBALANCED_CONDITIONAL:
+ return "Invalid OP_IF construction";
+ case SCRIPT_ERR_SIG_HASHTYPE:
+ return "Signature hash type missing or not understood";
+ case SCRIPT_ERR_SIG_DER:
+ return "Non-canonical DER signature";
+ case SCRIPT_ERR_MINIMALDATA:
+ return "Data push larger than necessary";
+ case SCRIPT_ERR_SIG_PUSHONLY:
+ return "Only non-push operators allowed in signatures";
+ case SCRIPT_ERR_SIG_HIGH_S:
+ 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;
+ }
+ return "unknown error";
+}
diff --git a/src/script/script_error.h b/src/script/script_error.h
new file mode 100644
index 0000000000..ac1f2deae5
--- /dev/null
+++ b/src/script/script_error.h
@@ -0,0 +1,57 @@
+// 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_SCRIPT_ERROR_H
+#define BITCOIN_SCRIPT_ERROR_H
+
+typedef enum ScriptError_t
+{
+ SCRIPT_ERR_OK = 0,
+ SCRIPT_ERR_UNKNOWN_ERROR,
+ SCRIPT_ERR_EVAL_FALSE,
+ SCRIPT_ERR_OP_RETURN,
+
+ /* Max sizes */
+ SCRIPT_ERR_SCRIPT_SIZE,
+ SCRIPT_ERR_PUSH_SIZE,
+ SCRIPT_ERR_OP_COUNT,
+ SCRIPT_ERR_STACK_SIZE,
+ SCRIPT_ERR_SIG_COUNT,
+ SCRIPT_ERR_PUBKEY_COUNT,
+
+ /* Failed verify operations */
+ SCRIPT_ERR_VERIFY,
+ SCRIPT_ERR_EQUALVERIFY,
+ SCRIPT_ERR_CHECKMULTISIGVERIFY,
+ SCRIPT_ERR_CHECKSIGVERIFY,
+ SCRIPT_ERR_NUMEQUALVERIFY,
+
+ /* Logical/Format/Canonical errors */
+ SCRIPT_ERR_BAD_OPCODE,
+ SCRIPT_ERR_DISABLED_OPCODE,
+ SCRIPT_ERR_INVALID_STACK_OPERATION,
+ SCRIPT_ERR_INVALID_ALTSTACK_OPERATION,
+ SCRIPT_ERR_UNBALANCED_CONDITIONAL,
+
+ /* BIP62 */
+ SCRIPT_ERR_SIG_HASHTYPE,
+ SCRIPT_ERR_SIG_DER,
+ SCRIPT_ERR_MINIMALDATA,
+ 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;
+
+#define SCRIPT_ERR_LAST SCRIPT_ERR_ERROR_COUNT
+
+const char* ScriptErrorString(const ScriptError error);
+
+#endif // BITCOIN_SCRIPT_ERROR_H
diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp
index ab366898d8..5580a5933e 100644
--- a/src/script/sigcache.cpp
+++ b/src/script/sigcache.cpp
@@ -5,7 +5,7 @@
#include "sigcache.h"
-#include "key.h"
+#include "pubkey.h"
#include "random.h"
#include "uint256.h"
#include "util.h"
@@ -15,13 +15,15 @@
namespace {
-// Valid signature cache, to avoid doing expensive ECDSA signature checking
-// twice for every transaction (once when accepted into memory pool, and
-// again when accepted into the block chain)
+/**
+ * Valid signature cache, to avoid doing expensive ECDSA signature checking
+ * twice for every transaction (once when accepted into memory pool, and
+ * again when accepted into the block chain)
+ */
class CSignatureCache
{
private:
- // sigdata_type is (signature hash, signature, public key):
+ //! sigdata_type is (signature hash, signature, public key):
typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type;
std::set< sigdata_type> setValid;
boost::shared_mutex cs_sigcache;
diff --git a/src/script/sigcache.h b/src/script/sigcache.h
index 46b8f4d335..df2a2ea13c 100644
--- a/src/script/sigcache.h
+++ b/src/script/sigcache.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 H_BITCOIN_SCRIPT_SIGCACHE
-#define H_BITCOIN_SCRIPT_SIGCACHE
+#ifndef BITCOIN_SCRIPT_SIGCACHE_H
+#define BITCOIN_SCRIPT_SIGCACHE_H
#include "script/interpreter.h"
@@ -23,4 +23,4 @@ public:
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
};
-#endif // H_BITCOIN_SCRIPT_SIGCACHE
+#endif // BITCOIN_SCRIPT_SIGCACHE_H
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 0eab0626e5..7dfed751b6 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -46,12 +46,12 @@ bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint2
return nSigned==nRequired;
}
-//
-// Sign scriptPubKey with private keys stored in keystore, given transaction hash and hash type.
-// Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
-// unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
-// Returns false if scriptPubKey could not be completely satisfied.
-//
+/**
+ * Sign scriptPubKey with private keys stored in keystore, given transaction hash and hash type.
+ * Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
+ * unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
+ * Returns false if scriptPubKey could not be completely satisfied.
+ */
bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType,
CScript& scriptSigRet, txnouttype& whichTypeRet)
{
@@ -144,9 +144,9 @@ static CScript PushAll(const vector<valtype>& values)
return result;
}
-static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction& txTo, unsigned int nIn,
+static CScript CombineMultisig(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
const vector<valtype>& vSolutions,
- vector<valtype>& sigs1, vector<valtype>& sigs2)
+ const vector<valtype>& sigs1, const vector<valtype>& sigs2)
{
// Combine all the signatures we've got:
set<valtype> allsigs;
@@ -199,7 +199,7 @@ static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction&
return result;
}
-static CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
+static CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
const txnouttype txType, const vector<valtype>& vSolutions,
vector<valtype>& sigs1, vector<valtype>& sigs2)
{
@@ -244,7 +244,7 @@ static CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo,
return CScript();
}
-CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
+CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
const CScript& scriptSig1, const CScript& scriptSig2)
{
txnouttype txType;
diff --git a/src/script/sign.h b/src/script/sign.h
index f218a64562..45a5e0dea3 100644
--- a/src/script/sign.h
+++ b/src/script/sign.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 H_BITCOIN_SCRIPT_SIGN
-#define H_BITCOIN_SCRIPT_SIGN
+#ifndef BITCOIN_SCRIPT_SIGN_H
+#define BITCOIN_SCRIPT_SIGN_H
#include "script/interpreter.h"
@@ -17,8 +17,10 @@ struct CMutableTransaction;
bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
-// Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders,
-// combine them intelligently and return the result.
-CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2);
+/**
+ * Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders,
+ * combine them intelligently and return the result.
+ */
+CScript CombineSignatures(const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2);
-#endif // H_BITCOIN_SCRIPT_SIGN
+#endif // BITCOIN_SCRIPT_SIGN_H
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 7356e541a6..ab6e6cde0d 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -5,6 +5,7 @@
#include "script/standard.h"
+#include "pubkey.h"
#include "script/script.h"
#include "util.h"
#include "utilstrencodings.h"
@@ -33,9 +34,9 @@ const char* GetTxnOutputType(txnouttype t)
return NULL;
}
-//
-// Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
-//
+/**
+ * Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
+ */
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet)
{
// Templates
diff --git a/src/script/standard.h b/src/script/standard.h
index 504d98c686..c4b82b4c45 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -3,17 +3,17 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef H_BITCOIN_SCRIPT_STANDARD
-#define H_BITCOIN_SCRIPT_STANDARD
+#ifndef BITCOIN_SCRIPT_STANDARD_H
+#define BITCOIN_SCRIPT_STANDARD_H
-#include "key.h"
-#include "script/script.h"
#include "script/interpreter.h"
+#include "uint256.h"
#include <boost/variant.hpp>
#include <stdint.h>
+class CKeyID;
class CScript;
/** A reference to a CScript: the Hash160 of its serialization (see script.h) */
@@ -25,27 +25,32 @@ public:
CScriptID(const uint160& in) : uint160(in) {}
};
-static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
+static const unsigned int MAX_OP_RETURN_RELAY = 40; //! bytes
extern unsigned nMaxDatacarrierBytes;
-// Mandatory script verification flags that all new blocks must comply with for
-// them to be valid. (but old blocks may not comply with) Currently just P2SH,
-// but in the future other flags may be added, such as a soft-fork to enforce
-// strict DER encoding.
-//
-// Failing one of these tests may trigger a DoS ban - see CheckInputs() for
-// details.
+/**
+ * Mandatory script verification flags that all new blocks must comply with for
+ * them to be valid. (but old blocks may not comply with) Currently just P2SH,
+ * but in the future other flags may be added, such as a soft-fork to enforce
+ * strict DER encoding.
+ *
+ * Failing one of these tests may trigger a DoS ban - see CheckInputs() for
+ * details.
+ */
static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH;
-// Standard script verification flags that standard transactions will comply
-// with. However scripts violating these flags may still be present in valid
-// blocks and we must accept those blocks.
+/**
+ * Standard script verification flags that standard transactions will comply
+ * with. However scripts violating these flags may still be present in valid
+ * blocks and we must accept those blocks.
+ */
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.
+/** 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;
enum txnouttype
@@ -65,7 +70,8 @@ public:
friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; }
};
-/** A txout script template with a specific destination. It is either:
+/**
+ * A txout script template with a specific destination. It is either:
* * CNoDestination: no destination set
* * CKeyID: TX_PUBKEYHASH destination
* * CScriptID: TX_SCRIPTHASH destination
@@ -84,4 +90,4 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::
CScript GetScriptForDestination(const CTxDestination& dest);
CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys);
-#endif // H_BITCOIN_SCRIPT_STANDARD
+#endif // BITCOIN_SCRIPT_STANDARD_H
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/serialize.h b/src/serialize.h
index 877ef8640a..ad38a3fa22 100644
--- a/src/serialize.h
+++ b/src/serialize.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_SERIALIZE_H
@@ -22,23 +22,28 @@ class CScript;
static const unsigned int MAX_SIZE = 0x02000000;
-// Used to bypass the rule against non-const reference to temporary
-// where it makes sense with wrappers such as CFlatData or CTxDB
+/**
+ * Used to bypass the rule against non-const reference to temporary
+ * where it makes sense with wrappers such as CFlatData or CTxDB
+ */
template<typename T>
inline T& REF(const T& val)
{
return const_cast<T&>(val);
}
-// Used to acquire a non-const pointer "this" to generate bodies
-// of const serialization operations from a template
+/**
+ * Used to acquire a non-const pointer "this" to generate bodies
+ * of const serialization operations from a template
+ */
template<typename T>
inline T* NCONST_PTR(const T* val)
{
return const_cast<T*>(val);
}
-/** Get begin pointer of vector (non-const version).
+/**
+ * Get begin pointer of vector (non-const version).
* @note These functions avoid the undefined case of indexing into an empty
* vector, as well as that of indexing after the end of the vector.
*/
@@ -82,10 +87,12 @@ enum
#define READWRITE(obj) (::SerReadWrite(s, (obj), nType, nVersion, ser_action))
-/* Implement three methods for serializable objects. These are actually wrappers over
+/**
+ * Implement three methods for serializable objects. These are actually wrappers over
* "SerializationOp" template, which implements the body of each class' serialization
* code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be
- * added as members. */
+ * added as members.
+ */
#define ADD_SERIALIZE_METHODS \
size_t GetSerializeSize(int nType, int nVersion) const { \
CSizeComputer s(nType, nVersion); \
@@ -103,9 +110,9 @@ enum
-//
-// Basic types
-//
+/*
+ * Basic Types
+ */
#define WRITEDATA(s, obj) s.write((char*)&(obj), sizeof(obj))
#define READDATA(s, obj) s.read((char*)&(obj), sizeof(obj))
@@ -160,13 +167,13 @@ template<typename Stream> inline void Unserialize(Stream& s, bool& a, int, int=0
-//
-// Compact size
-// size < 253 -- 1 byte
-// size <= USHRT_MAX -- 3 bytes (253 + 2 bytes)
-// size <= UINT_MAX -- 5 bytes (254 + 4 bytes)
-// size > UINT_MAX -- 9 bytes (255 + 8 bytes)
-//
+/**
+ * Compact Size
+ * size < 253 -- 1 byte
+ * size <= USHRT_MAX -- 3 bytes (253 + 2 bytes)
+ * size <= UINT_MAX -- 5 bytes (254 + 4 bytes)
+ * size > UINT_MAX -- 9 bytes (255 + 8 bytes)
+ */
inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
{
if (nSize < 253) return sizeof(unsigned char);
@@ -246,27 +253,29 @@ uint64_t ReadCompactSize(Stream& is)
return nSizeRet;
}
-// Variable-length integers: bytes are a MSB base-128 encoding of the number.
-// The high bit in each byte signifies whether another digit follows. To make
-// the encoding is one-to-one, one is subtracted from all but the last digit.
-// Thus, the byte sequence a[] with length len, where all but the last byte
-// has bit 128 set, encodes the number:
-//
-// (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
-//
-// Properties:
-// * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
-// * Every integer has exactly one encoding
-// * Encoding does not depend on size of original integer type
-// * No redundancy: every (infinite) byte sequence corresponds to a list
-// of encoded integers.
-//
-// 0: [0x00] 256: [0x81 0x00]
-// 1: [0x01] 16383: [0xFE 0x7F]
-// 127: [0x7F] 16384: [0xFF 0x00]
-// 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F]
-// 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F]
-// 2^32: [0x8E 0xFE 0xFE 0xFF 0x00]
+/**
+ * Variable-length integers: bytes are a MSB base-128 encoding of the number.
+ * The high bit in each byte signifies whether another digit follows. To make
+ * sure the encoding is one-to-one, one is subtracted from all but the last digit.
+ * Thus, the byte sequence a[] with length len, where all but the last byte
+ * has bit 128 set, encodes the number:
+ *
+ * (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
+ *
+ * Properties:
+ * * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
+ * * Every integer has exactly one encoding
+ * * Encoding does not depend on size of original integer type
+ * * No redundancy: every (infinite) byte sequence corresponds to a list
+ * of encoded integers.
+ *
+ * 0: [0x00] 256: [0x81 0x00]
+ * 1: [0x01] 16383: [0xFE 0x7F]
+ * 127: [0x7F] 16384: [0xFF 0x00]
+ * 128: [0x80 0x00] 16511: [0x80 0xFF 0x7F]
+ * 255: [0x80 0x7F] 65535: [0x82 0xFD 0x7F]
+ * 2^32: [0x8E 0xFE 0xFE 0xFF 0x00]
+ */
template<typename I>
inline unsigned int GetSizeOfVarInt(I n)
@@ -317,7 +326,8 @@ I ReadVarInt(Stream& is)
#define VARINT(obj) REF(WrapVarInt(REF(obj)))
#define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj)))
-/** Wrapper for serializing arrays and POD.
+/**
+ * Wrapper for serializing arrays and POD.
*/
class CFlatData
{
@@ -415,17 +425,21 @@ public:
template<typename I>
CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
-//
-// Forward declarations
-//
+/**
+ * Forward declarations
+ */
-// string
+/**
+ * string
+ */
template<typename C> unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int=0);
template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str, int, int=0);
template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str, int, int=0);
-// vector
-// vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
+/**
+ * vector
+ * vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
+ */
template<typename T, typename A> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&);
template<typename T, typename A, typename V> unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const V&);
template<typename T, typename A> inline unsigned int GetSerializeSize(const std::vector<T, A>& v, int nType, int nVersion);
@@ -436,22 +450,30 @@ template<typename Stream, typename T, typename A> void Unserialize_impl(Stream&
template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion, const V&);
template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersion);
-// others derived from vector
+/**
+ * others derived from vector
+ */
extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion);
template<typename Stream> void Serialize(Stream& os, const CScript& v, int nType, int nVersion);
template<typename Stream> void Unserialize(Stream& is, CScript& v, int nType, int nVersion);
-// pair
+/**
+ * pair
+ */
template<typename K, typename T> unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion);
template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item, int nType, int nVersion);
template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion);
-// map
+/**
+ * map
+ */
template<typename K, typename T, typename Pred, typename A> unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion);
template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m, int nType, int nVersion);
template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion);
-// set
+/**
+ * set
+ */
template<typename K, typename Pred, typename A> unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion);
template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m, int nType, int nVersion);
template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion);
@@ -460,12 +482,12 @@ template<typename Stream, typename K, typename Pred, typename A> void Unserializ
-//
-// If none of the specialized versions above matched, default to calling member function.
-// "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
-// The compiler will only cast int to long if none of the other templates matched.
-// Thanks to Boost serialization for this idea.
-//
+/**
+ * If none of the specialized versions above matched, default to calling member function.
+ * "int nType" is changed to "long nType" to keep from getting an ambiguous overload error.
+ * The compiler will only cast int to long if none of the other templates matched.
+ * Thanks to Boost serialization for this idea.
+ */
template<typename T>
inline unsigned int GetSerializeSize(const T& a, long nType, int nVersion)
{
@@ -488,9 +510,9 @@ inline void Unserialize(Stream& is, T& a, long nType, int nVersion)
-//
-// string
-//
+/**
+ * string
+ */
template<typename C>
unsigned int GetSerializeSize(const std::basic_string<C>& str, int, int)
{
@@ -516,9 +538,9 @@ void Unserialize(Stream& is, std::basic_string<C>& str, int, int)
-//
-// vector
-//
+/**
+ * vector
+ */
template<typename T, typename A>
unsigned int GetSerializeSize_impl(const std::vector<T, A>& v, int nType, int nVersion, const unsigned char&)
{
@@ -606,9 +628,9 @@ inline void Unserialize(Stream& is, std::vector<T, A>& v, int nType, int nVersio
-//
-// others derived from vector
-//
+/**
+ * others derived from vector
+ */
inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVersion)
{
return GetSerializeSize((const std::vector<unsigned char>&)v, nType, nVersion);
@@ -628,9 +650,9 @@ void Unserialize(Stream& is, CScript& v, int nType, int nVersion)
-//
-// pair
-//
+/**
+ * pair
+ */
template<typename K, typename T>
unsigned int GetSerializeSize(const std::pair<K, T>& item, int nType, int nVersion)
{
@@ -653,9 +675,9 @@ void Unserialize(Stream& is, std::pair<K, T>& item, int nType, int nVersion)
-//
-// map
-//
+/**
+ * map
+ */
template<typename K, typename T, typename Pred, typename A>
unsigned int GetSerializeSize(const std::map<K, T, Pred, A>& m, int nType, int nVersion)
{
@@ -689,9 +711,9 @@ void Unserialize(Stream& is, std::map<K, T, Pred, A>& m, int nType, int nVersion
-//
-// set
-//
+/**
+ * set
+ */
template<typename K, typename Pred, typename A>
unsigned int GetSerializeSize(const std::set<K, Pred, A>& m, int nType, int nVersion)
{
@@ -725,9 +747,9 @@ void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
-//
-// Support for ADD_SERIALIZE_METHODS and READWRITE macro
-//
+/**
+ * Support for ADD_SERIALIZE_METHODS and READWRITE macro
+ */
struct CSerActionSerialize
{
bool ForRead() const { return false; }
diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp
index 9cf7a98f46..4869ba52ac 100644
--- a/src/test/alert_tests.cpp
+++ b/src/test/alert_tests.cpp
@@ -154,9 +154,6 @@ BOOST_AUTO_TEST_CASE(AlertApplies)
}
-// This uses sh 'echo' to test the -alertnotify function, writing to a
-// /tmp file. So skip it on Windows:
-#ifndef WIN32
BOOST_AUTO_TEST_CASE(AlertNotify)
{
SetMockTime(11);
@@ -171,15 +168,24 @@ BOOST_AUTO_TEST_CASE(AlertNotify)
std::vector<std::string> r = read_lines(temp);
BOOST_CHECK_EQUAL(r.size(), 4u);
+
+// Windows built-in echo semantics are different than posixy shells. Quotes and
+// whitespace are printed literally.
+
+#ifndef WIN32
BOOST_CHECK_EQUAL(r[0], "Alert 1");
BOOST_CHECK_EQUAL(r[1], "Alert 2, cancels 1");
BOOST_CHECK_EQUAL(r[2], "Alert 2, cancels 1");
BOOST_CHECK_EQUAL(r[3], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed
-
+#else
+ BOOST_CHECK_EQUAL(r[0], "'Alert 1' ");
+ BOOST_CHECK_EQUAL(r[1], "'Alert 2, cancels 1' ");
+ BOOST_CHECK_EQUAL(r[2], "'Alert 2, cancels 1' ");
+ BOOST_CHECK_EQUAL(r[3], "'Evil Alert; /bin/ls; echo ' ");
+#endif
boost::filesystem::remove(temp);
SetMockTime(0);
}
-#endif
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bignum.h b/src/test/bignum.h
index 86980b2af6..f64c987202 100644
--- a/src/test/bignum.h
+++ b/src/test/bignum.h
@@ -3,8 +3,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_BIGNUM_H
-#define BITCOIN_BIGNUM_H
+#ifndef BITCOIN_TEST_BIGNUM_H
+#define BITCOIN_TEST_BIGNUM_H
#include <algorithm>
#include <limits>
@@ -177,4 +177,4 @@ inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a,
inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); }
inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); }
-#endif
+#endif // BITCOIN_TEST_BIGNUM_H
diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json
index 6f451a36ee..71e757714c 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"],
@@ -576,11 +593,48 @@ nSequences are max.
"P2PK NOT with hybrid pubkey but no STRICTENC"
],
[
+ "0x47 0x3044022078033e4227aa05ded69d8da579966578e230d8a7fb44d5f1a0620c3853c24f78022006a2e3f4d872ac8dfdc529110aa37301d65a76255a4b6cce2992adacd4d2c4e201",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "STRICTENC",
+ "P2PK NOT with hybrid pubkey"
+],
+[
+ "0x47 0x304402207592427de20e315d644839754f2a5cca5b978b983a15e6da82109ede01722baa022032ceaf78590faa3f7743821e1b47b897ed1a57f6ee1c8a7519d23774d8de3c4401",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "STRICTENC",
+ "P2PK NOT with invalid hybrid pubkey"
+],
+[
+ "0 0x47 0x304402206797289d3dc81692edae58430276d04641ea5d86967be557163f8494da32fd78022006fc6ab77aaed4ac11ea69cd878ab26e3e24290f47a43e9adf34075d52b7142c01",
+ "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG",
+ "STRICTENC",
+ "1-of-2 with the first 1 hybrid pubkey"
+],
+[
"0x47 0x304402201f82b99a813c9c48c8dee8d2c43b8f637b72353fe9bdcc084537bc17e2ab770402200c43b96a5f7e115f0114eabda32e068145965cb6c7b5ef64833bb4fcf9fc1b3b05",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"STRICTENC",
"P2PK with undefined hashtype"
],
+
+["
+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."
+],
+
[
"0x47 0x30440220166848cd5b82a32b5944d90de3c35249354b43773c2ece1844ee8d1103e2f6c602203b6b046da4243c77adef80ada9201b27bbfdf7f9d5428f40434b060432afd62005",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json
index 439c82ef32..ada45a64ed 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"],
@@ -739,23 +744,48 @@ nSequences are max.
"P2PK with hybrid pubkey but no STRICTENC"
],
[
- "0x47 0x3044022078033e4227aa05ded69d8da579966578e230d8a7fb44d5f1a0620c3853c24f78022006a2e3f4d872ac8dfdc529110aa37301d65a76255a4b6cce2992adacd4d2c4e201",
- "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
- "STRICTENC",
- "P2PK NOT with hybrid pubkey"
-],
-[
"0x47 0x3044022078d6c447887e88dcbe1bc5b613645280df6f4e5935648bc226e9d91da71b3216022047d6b7ef0949b228fc1b359afb8d50500268711354298217b983c26970790c7601",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"",
"P2PK NOT with invalid hybrid pubkey but no STRICTENC"
],
[
- "0x47 0x304402207592427de20e315d644839754f2a5cca5b978b983a15e6da82109ede01722baa022032ceaf78590faa3f7743821e1b47b897ed1a57f6ee1c8a7519d23774d8de3c4401",
- "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "0 0x47 0x304402203b269b9fbc0936877bf855b5fb41757218d9548b246370d991442a5f5bd1c3440220235268a4eaa8c67e543c6e37da81dd36d3b1be2de6b4fef04113389ca6ddc04501",
+ "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "",
+ "1-of-2 with the second 1 hybrid pubkey and no STRICTENC"
+],
+[
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"STRICTENC",
- "P2PK NOT with invalid hybrid pubkey"
+ "1-of-2 with the second 1 hybrid pubkey"
],
+
+["
+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."
+],
+
[
"0x47 0x304402204649e9517ef0377a8f8270bd423053fd98ddff62d74ea553e9579558abbb75e4022044a2b2344469c12e35ed898987711272b634733dd0f5e051288eceb04bd4669e05",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index b32f3774fe..f9e35e0166 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -82,6 +82,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()));
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 93b7fe189a..53c2e7b261 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -4,6 +4,7 @@
#include "main.h"
#include "miner.h"
+#include "pubkey.h"
#include "uint256.h"
#include "util.h"
@@ -56,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));
@@ -79,7 +81,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
pblock->nNonce = blockinfo[i].nonce;
CValidationState state;
- BOOST_CHECK(ProcessBlock(state, NULL, pblock));
+ BOOST_CHECK(ProcessNewBlock(state, NULL, pblock));
BOOST_CHECK(state.IsValid());
pblock->hashPrevBlock = pblock->GetHash();
}
@@ -258,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/multisig_tests.cpp b/src/test/multisig_tests.cpp
index e9fc86779a..8d06caa147 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -6,6 +6,7 @@
#include "keystore.h"
#include "main.h"
#include "script/script.h"
+#include "script/script_error.h"
#include "script/interpreter.h"
#include "script/sign.h"
#include "uint256.h"
@@ -46,6 +47,7 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
{
unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
+ ScriptError err;
CKey key[4];
for (int i = 0; i < 4; i++)
key[i].MakeNewKey(true);
@@ -82,19 +84,22 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys.clear();
keys += key[0],key[1]; // magic operator+= from boost.assign
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK(VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0)));
+ BOOST_CHECK(VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
for (int i = 0; i < 4; i++)
{
keys.clear();
keys += key[i];
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0)), strprintf("a&b 1: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0), &err), strprintf("a&b 1: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
keys.clear();
keys += key[1],key[i];
s = sign_multisig(a_and_b, keys, txTo[0], 0);
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0)), strprintf("a&b 2: %d", i));
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, SignatureChecker(txTo[0], 0), &err), strprintf("a&b 2: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
// Test a OR b:
@@ -104,16 +109,24 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys += key[i];
s = sign_multisig(a_or_b, keys, txTo[1], 0);
if (i == 0 || i == 1)
- BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0)), strprintf("a|b: %d", i));
+ {
+ BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ }
else
- BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0)), strprintf("a|b: %d", i));
+ {
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+ }
}
s.clear();
s << OP_0 << OP_0;
- BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0)));
+ BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
s.clear();
s << OP_0 << OP_1;
- BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0)));
+ BOOST_CHECK(!VerifyScript(s, a_or_b, flags, SignatureChecker(txTo[1], 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
for (int i = 0; i < 4; i++)
@@ -123,9 +136,15 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys += key[i],key[j];
s = sign_multisig(escrow, keys, txTo[2], 0);
if (i < j && i < 3 && j < 3)
- BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0)), strprintf("escrow 1: %d %d", i, j));
+ {
+ BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ }
else
- BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0)), strprintf("escrow 2: %d %d", i, j));
+ {
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, SignatureChecker(txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+ }
}
}
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index fcab652783..a969eefa05 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -6,6 +6,7 @@
#include "keystore.h"
#include "main.h"
#include "script/script.h"
+#include "script/script_error.h"
#include "script/sign.h"
#ifdef ENABLE_WALLET
@@ -27,7 +28,7 @@ Serialize(const CScript& s)
}
static bool
-Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict)
+Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, ScriptError& err)
{
// Create dummy to/from transactions:
CMutableTransaction txFrom;
@@ -42,7 +43,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict)
txTo.vin[0].scriptSig = scriptSig;
txTo.vout[0].nValue = 1;
- return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, SignatureChecker(txTo, 0));
+ return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, SignatureChecker(txTo, 0), &err);
}
@@ -124,6 +125,7 @@ BOOST_AUTO_TEST_CASE(sign)
BOOST_AUTO_TEST_CASE(norecurse)
{
+ ScriptError err;
// Make sure only the outer pay-to-script-hash does the
// extra-validation thing:
CScript invalidAsScript;
@@ -135,7 +137,8 @@ BOOST_AUTO_TEST_CASE(norecurse)
scriptSig << Serialize(invalidAsScript);
// Should not verify, because it will try to execute OP_INVALIDOPCODE
- BOOST_CHECK(!Verify(scriptSig, p2sh, true));
+ BOOST_CHECK(!Verify(scriptSig, p2sh, true, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_BAD_OPCODE, ScriptErrorString(err));
// Try to recur, and verification should succeed because
// the inner HASH160 <> EQUAL should only check the hash:
@@ -143,7 +146,8 @@ BOOST_AUTO_TEST_CASE(norecurse)
CScript scriptSig2;
scriptSig2 << Serialize(invalidAsScript) << Serialize(p2sh);
- BOOST_CHECK(Verify(scriptSig2, p2sh2, true));
+ BOOST_CHECK(Verify(scriptSig2, p2sh2, true, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(set)
@@ -238,6 +242,7 @@ BOOST_AUTO_TEST_CASE(switchover)
{
// Test switch over code
CScript notValid;
+ ScriptError err;
notValid << OP_11 << OP_12 << OP_EQUALVERIFY;
CScript scriptSig;
scriptSig << Serialize(notValid);
@@ -246,9 +251,11 @@ BOOST_AUTO_TEST_CASE(switchover)
// Validation should succeed under old rules (hash is correct):
- BOOST_CHECK(Verify(scriptSig, fund, false));
+ BOOST_CHECK(Verify(scriptSig, fund, false, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
// Fail under new:
- BOOST_CHECK(!Verify(scriptSig, fund, true));
+ BOOST_CHECK(!Verify(scriptSig, fund, true, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EQUALVERIFY, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(AreInputsStandard)
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index a41552fea1..6952f4c584 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -10,9 +10,14 @@
#include "keystore.h"
#include "main.h"
#include "script/script.h"
+#include "script/script_error.h"
#include "script/sign.h"
#include "util.h"
+#if defined(HAVE_CONSENSUS_LIB)
+#include "script/bitcoinconsensus.h"
+#endif
+
#include <fstream>
#include <stdint.h>
#include <string>
@@ -92,7 +97,58 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMu
void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bool expect, const std::string& message)
{
- BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, SignatureChecker(BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey)), 0)) == expect, message);
+ ScriptError err;
+ 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) {
+ // Parse the signature.
+ std::vector<unsigned char> r, s;
+ r = std::vector<unsigned char>(vchSig.begin() + 4, vchSig.begin() + 4 + vchSig[3]);
+ s = std::vector<unsigned char>(vchSig.begin() + 6 + vchSig[3], vchSig.begin() + 6 + vchSig[3] + vchSig[5 + vchSig[3]]);
+ unsigned char hashtype = vchSig.back();
+
+ // Really ugly to implement mod-n negation here, but it would be feature creep to expose such functionality from libsecp256k1.
+ static const unsigned char order[33] = {
+ 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
+ };
+ while (s.size() < 33) {
+ s.insert(s.begin(), 0x00);
+ }
+ int carry = 0;
+ for (int p = 32; p >= 1; p--) {
+ int n = (int)order[p] - s[p] - carry;
+ s[p] = (n + 256) & 0xFF;
+ carry = (n < 0);
+ }
+ assert(carry == 0);
+ if (s.size() > 1 && s[0] == 0 && s[1] < 0x80) {
+ s.erase(s.begin());
+ }
+
+ // Reconstruct the signature.
+ vchSig.clear();
+ vchSig.push_back(0x30);
+ vchSig.push_back(4 + r.size() + s.size());
+ vchSig.push_back(0x02);
+ vchSig.push_back(r.size());
+ vchSig.insert(vchSig.end(), r.begin(), r.end());
+ vchSig.push_back(0x02);
+ vchSig.push_back(s.size());
+ vchSig.insert(vchSig.end(), s.begin(), s.end());
+ vchSig.push_back(hashtype);
}
namespace
@@ -130,7 +186,6 @@ struct KeyData
}
};
-const KeyData keys;
class TestBuilder
{
@@ -194,7 +249,10 @@ public:
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType);
std::vector<unsigned char> vchSig, r, s;
do {
- key.Sign(hash, vchSig, lenS <= 32);
+ key.Sign(hash, vchSig);
+ if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) {
+ NegateSignatureS(vchSig);
+ }
r = std::vector<unsigned char>(vchSig.begin() + 4, vchSig.begin() + 4 + vchSig[3]);
s = std::vector<unsigned char>(vchSig.begin() + 6 + vchSig[3], vchSig.begin() + 6 + vchSig[3] + vchSig[5 + vchSig[3]]);
} while (lenR != r.size() || lenS != s.size());
@@ -269,6 +327,8 @@ public:
BOOST_AUTO_TEST_CASE(script_build)
{
+ const KeyData keys;
+
std::vector<TestBuilder> good;
std::vector<TestBuilder> bad;
@@ -368,15 +428,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
@@ -545,20 +614,25 @@ BOOST_AUTO_TEST_CASE(script_PushData)
static const unsigned char pushdata2[] = { OP_PUSHDATA2, 1, 0, 0x5a };
static const unsigned char pushdata4[] = { OP_PUSHDATA4, 1, 0, 0, 0, 0x5a };
+ ScriptError err;
vector<vector<unsigned char> > directStack;
- BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), true, BaseSignatureChecker()));
+ BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), true, BaseSignatureChecker(), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata1Stack;
- BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), true, BaseSignatureChecker()));
+ BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), true, BaseSignatureChecker(), &err));
BOOST_CHECK(pushdata1Stack == directStack);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata2Stack;
- BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), true, BaseSignatureChecker()));
+ BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), true, BaseSignatureChecker(), &err));
BOOST_CHECK(pushdata2Stack == directStack);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
vector<vector<unsigned char> > pushdata4Stack;
- BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), true, BaseSignatureChecker()));
+ BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), true, BaseSignatureChecker(), &err));
BOOST_CHECK(pushdata4Stack == directStack);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
CScript
@@ -595,6 +669,7 @@ sign_multisig(CScript scriptPubKey, const CKey &key, CTransaction transaction)
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
{
+ ScriptError err;
CKey key1, key2, key3;
key1.MakeNewKey(true);
key2.MakeNewKey(false);
@@ -607,19 +682,24 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12);
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
- BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0)));
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
txTo12.vout[0].nValue = 2;
- BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0)));
+ BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
- BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, SignatureChecker(txTo12, 0)));
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
- BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0)));
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, SignatureChecker(txTo12, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
{
+ ScriptError err;
CKey key1, key2, key3, key4;
key1.MakeNewKey(true);
key2.MakeNewKey(false);
@@ -635,46 +715,55 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
std::vector<CKey> keys;
keys.push_back(key1); keys.push_back(key2);
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key1); keys.push_back(key3);
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key3);
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
keys.clear(); // Must have signatures
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
- BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, SignatureChecker(txTo23, 0)));
+ BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, SignatureChecker(txTo23, 0), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(script_combineSigs)
@@ -788,11 +877,13 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
BOOST_AUTO_TEST_CASE(script_standard_push)
{
+ ScriptError err;
for (int i=0; i<67000; i++) {
CScript script;
script << i;
BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Number " << i << " is not pure push.");
- BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker()), "Number " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Number " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
for (unsigned int i=0; i<=MAX_SCRIPT_ELEMENT_SIZE; i++) {
@@ -800,7 +891,8 @@ BOOST_AUTO_TEST_CASE(script_standard_push)
CScript script;
script << data;
BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Length " << i << " is not pure push.");
- BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker()), "Length " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Length " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
}
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index 7b27703b62..5bf0862c71 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "pubkey.h"
#include "key.h"
#include "script/script.h"
#include "script/standard.h"
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index d4c9b1a0ea..e939e89972 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -10,6 +10,7 @@
#include "keystore.h"
#include "main.h"
#include "script/script.h"
+#include "script/script_error.h"
#include "core_io.h"
#include <map>
@@ -36,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)
{
@@ -86,6 +88,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
// verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
Array tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
+ ScriptError err;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
@@ -142,8 +145,9 @@ BOOST_AUTO_TEST_CASE(tx_valid)
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
- verify_flags, SignatureChecker(tx, i)),
+ verify_flags, SignatureChecker(tx, i), &err),
strTest);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
}
}
}
@@ -160,6 +164,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
// verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
Array tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
+ ScriptError err;
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
@@ -215,10 +220,10 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
- verify_flags, SignatureChecker(tx, i));
+ verify_flags, SignatureChecker(tx, i), &err);
}
-
BOOST_CHECK_MESSAGE(!fValid, strTest);
+ BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err));
}
}
}
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 8f2bd9af4d..9a98fcc41b 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -1,10 +1,10 @@
// 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_LEVELDB_H
-#define BITCOIN_TXDB_LEVELDB_H
+#ifndef BITCOIN_TXDB_H
+#define BITCOIN_TXDB_H
#include "leveldbwrapper.h"
#include "main.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/) */
@@ -62,4 +62,4 @@ public:
bool LoadBlockIndexGuts();
};
-#endif // BITCOIN_TXDB_LEVELDB_H
+#endif // BITCOIN_TXDB_H
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index d3d9cb8a01..e13f1cc350 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -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.
#include "txmempool.h"
@@ -45,9 +45,9 @@ CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
return dResult;
}
-//
-// Keep track of fee/priority for transactions confirmed within N blocks
-//
+/**
+ * Keep track of fee/priority for transactions confirmed within N blocks
+ */
class CBlockAverage
{
private:
@@ -86,8 +86,10 @@ public:
return prioritySamples.size();
}
- // Used as belt-and-suspenders check when reading to detect
- // file corruption
+ /**
+ * Used as belt-and-suspenders check when reading to detect
+ * file corruption
+ */
bool AreSane(const std::vector<CFeeRate>& vecFee, const CFeeRate& minRelayFee)
{
BOOST_FOREACH(CFeeRate fee, vecFee)
@@ -139,16 +141,20 @@ public:
class CMinerPolicyEstimator
{
private:
- // Records observed averages transactions that confirmed within one block, two blocks,
- // three blocks etc.
+ /**
+ * Records observed averages transactions that confirmed within one block, two blocks,
+ * three blocks etc.
+ */
std::vector<CBlockAverage> history;
std::vector<CFeeRate> sortedFeeSamples;
std::vector<double> sortedPrioritySamples;
int nBestSeenHeight;
- // nBlocksAgo is 0 based, i.e. transactions that confirmed in the highest seen block are
- // nBlocksAgo == 0, transactions in the block before that are nBlocksAgo == 1 etc.
+ /**
+ * nBlocksAgo is 0 based, i.e. transactions that confirmed in the highest seen block are
+ * nBlocksAgo == 0, transactions in the block before that are nBlocksAgo == 1 etc.
+ */
void seenTxConfirm(const CFeeRate& feeRate, const CFeeRate& minRelayFee, double dPriority, int nBlocksAgo)
{
// Last entry records "everything else".
@@ -248,7 +254,9 @@ public:
}
}
- // Can return CFeeRate(0) if we don't have any data for that many blocks back. nBlocksToConfirm is 1 based.
+ /**
+ * Can return CFeeRate(0) if we don't have any data for that many blocks back. nBlocksToConfirm is 1 based.
+ */
CFeeRate estimateFee(int nBlocksToConfirm)
{
nBlocksToConfirm--;
@@ -332,7 +340,7 @@ public:
size_t numEntries;
filein >> numEntries;
if (numEntries <= 0 || numEntries > 10000)
- throw runtime_error("Corrupt estimates file. Must have between 1 and 10k entires.");
+ throw runtime_error("Corrupt estimates file. Must have between 1 and 10k entries.");
std::vector<CBlockAverage> fileHistory;
@@ -343,8 +351,8 @@ public:
fileHistory.push_back(entry);
}
- //Now that we've processed the entire fee estimate data file and not
- //thrown any errors, we can copy it to our history
+ // Now that we've processed the entire fee estimate data file and not
+ // thrown any errors, we can copy it to our history
nBestSeenHeight = nFileBestSeenHeight;
history = fileHistory;
assert(history.size() > 0);
@@ -462,7 +470,9 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>
}
}
-// Called when a block is connected. Removes from mempool and updates the miner fee estimator.
+/**
+ * Called when a block is connected. Removes from mempool and updates the miner fee estimator.
+ */
void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
std::list<CTransaction>& conflicts)
{
diff --git a/src/txmempool.h b/src/txmempool.h
index 2ec80cb860..e68b218154 100644
--- a/src/txmempool.h
+++ b/src/txmempool.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_TXMEMPOOL_H
@@ -15,29 +15,34 @@
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) */
static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF;
-/*
+/**
* CTxMemPool stores these:
*/
class CTxMemPoolEntry
{
private:
CTransaction tx;
- CAmount nFee; // Cached to avoid expensive parent-transaction lookups
- size_t nTxSize; // ... and avoid recomputing tx size
- size_t nModSize; // ... and modified size for priority
- int64_t nTime; // Local time when entering the mempool
- double dPriority; // Priority when entering the mempool
- unsigned int nHeight; // Chain height when entering the mempool
+ CAmount nFee; //! Cached to avoid expensive parent-transaction lookups
+ size_t nTxSize; //! ... and avoid recomputing tx size
+ size_t nModSize; //! ... and modified size for priority
+ int64_t nTime; //! Local time when entering the mempool
+ double dPriority; //! Priority when entering the mempool
+ unsigned int nHeight; //! Chain height when entering the mempool
public:
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
@@ -68,7 +73,7 @@ public:
bool IsNull() const { return (ptx == NULL && n == (uint32_t) -1); }
};
-/*
+/**
* CTxMemPool stores valid-according-to-the-current-best-chain
* transactions that may be included in the next block.
*
@@ -81,12 +86,12 @@ public:
class CTxMemPool
{
private:
- bool fSanityCheck; // Normally false, true if -checkmempool or -regtest
+ bool fSanityCheck; //! Normally false, true if -checkmempool or -regtest
unsigned int nTransactionsUpdated;
CMinerPolicyEstimator* minerPolicyEstimator;
- CFeeRate minRelayFee; // Passed to constructor to avoid dependency on main
- uint64_t totalTxSize; // sum of all mempool tx' byte sizes
+ CFeeRate minRelayFee; //! Passed to constructor to avoid dependency on main
+ uint64_t totalTxSize; //! sum of all mempool tx' byte sizes
public:
mutable CCriticalSection cs;
@@ -97,7 +102,7 @@ public:
CTxMemPool(const CFeeRate& _minRelayFee);
~CTxMemPool();
- /*
+ /**
* If sanity-checking is turned on, check makes sure the pool is
* consistent (does not contain two transactions that spend the same inputs,
* all inputs are in the mapNextTx array). If sanity-checking is turned off,
@@ -141,19 +146,21 @@ public:
bool lookup(uint256 hash, CTransaction& result) const;
- // Estimate fee rate needed to get into the next
- // nBlocks
+ /** Estimate fee rate needed to get into the next nBlocks */
CFeeRate estimateFee(int nBlocks) const;
- // Estimate priority needed to get into the next
- // nBlocks
+
+ /** Estimate priority needed to get into the next nBlocks */
double estimatePriority(int nBlocks) const;
- // Write/Read estimates to disk
+
+ /** Write/Read estimates to disk */
bool WriteFeeEstimates(CAutoFile& fileout) const;
bool ReadFeeEstimates(CAutoFile& filein);
};
-/** CCoinsView that brings transactions from a memorypool into view.
- It does not check for spendings by memory pool transactions. */
+/**
+ * CCoinsView that brings transactions from a memorypool into view.
+ * It does not check for spendings by memory pool transactions.
+ */
class CCoinsViewMemPool : public CCoinsViewBacked
{
protected:
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 232c193429..4f5f4047dd 100644
--- a/src/undo.h
+++ b/src/undo.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 H_BITCOIN_TXUNDO
-#define H_BITCOIN_TXUNDO
+#ifndef BITCOIN_UNDO_H
+#define BITCOIN_UNDO_H
#include "compressor.h"
#include "core/transaction.h"
@@ -68,4 +68,4 @@ public:
}
};
-#endif // H_BITCOIN_TXUNDO
+#endif // BITCOIN_UNDO_H
diff --git a/src/univalue/gen.cpp b/src/univalue/gen.cpp
index 881948f46e..f0b352eef0 100644
--- a/src/univalue/gen.cpp
+++ b/src/univalue/gen.cpp
@@ -35,8 +35,8 @@ static void initJsonEscape()
static void outputEscape()
{
printf( "// Automatically generated file. Do not modify.\n"
- "#ifndef __UNIVALUE_ESCAPES_H__\n"
- "#define __UNIVALUE_ESCAPES_H__\n"
+ "#ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n"
+ "#define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n"
"static const char *escapes[256] = {\n");
for (unsigned int i = 0; i < 256; i++) {
@@ -66,7 +66,7 @@ static void outputEscape()
}
printf( "};\n"
- "#endif // __UNIVALUE_ESCAPES_H__\n");
+ "#endif // BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n");
}
int main (int argc, char *argv[])
diff --git a/src/univalue/univalue.h b/src/univalue/univalue.h
index 0a7bf3cceb..5ac301d9e5 100644
--- a/src/univalue/univalue.h
+++ b/src/univalue/univalue.h
@@ -2,8 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef __UNIVALUE_H__
-#define __UNIVALUE_H__
+#ifndef BITCOIN_UNIVALUE_UNIVALUE_H
+#define BITCOIN_UNIVALUE_UNIVALUE_H
#include <stdint.h>
#include <string>
@@ -152,4 +152,4 @@ extern enum jtokentype getJsonToken(std::string& tokenVal,
unsigned int& consumed, const char *raw);
extern const char *uvTypeName(UniValue::VType t);
-#endif // __UNIVALUE_H__
+#endif // BITCOIN_UNIVALUE_UNIVALUE_H
diff --git a/src/univalue/univalue_escapes.h b/src/univalue/univalue_escapes.h
index 1d3a70a968..0514118285 100644
--- a/src/univalue/univalue_escapes.h
+++ b/src/univalue/univalue_escapes.h
@@ -1,6 +1,6 @@
// Automatically generated file. Do not modify.
-#ifndef __UNIVALUE_ESCAPES_H__
-#define __UNIVALUE_ESCAPES_H__
+#ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H
+#define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H
static const char *escapes[256] = {
NULL,
NULL,
@@ -259,4 +259,4 @@ static const char *escapes[256] = {
NULL,
NULL,
};
-#endif // __UNIVALUE_ESCAPES_H__
+#endif // BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H
diff --git a/src/util.cpp b/src/util.cpp
index 544ffc98b8..0cdf4e614d 100644
--- a/src/util.cpp
+++ b/src/util.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)
@@ -105,7 +105,7 @@ bool fLogTimestamps = false;
bool fLogIPs = false;
volatile bool fReopenDebugLog = false;
-// Init OpenSSL library multithreading support
+/** Init OpenSSL library multithreading support */
static CCriticalSection** ppmutexOpenSSL;
void locking_callback(int mode, int i, const char* file, int line)
{
@@ -149,18 +149,22 @@ public:
}
instance_of_cinit;
-// LogPrintf() has been broken a couple of times now
-// by well-meaning people adding mutexes in the most straightforward way.
-// It breaks because it may be called by global destructors during shutdown.
-// Since the order of destruction of static/global objects is undefined,
-// defining a mutex as a global object doesn't work (the mutex gets
-// destroyed, and then some later destructor calls OutputDebugStringF,
-// maybe indirectly, and you get a core dump at shutdown trying to lock
-// the mutex).
+/**
+ * LogPrintf() has been broken a couple of times now
+ * by well-meaning people adding mutexes in the most straightforward way.
+ * It breaks because it may be called by global destructors during shutdown.
+ * Since the order of destruction of static/global objects is undefined,
+ * defining a mutex as a global object doesn't work (the mutex gets
+ * destroyed, and then some later destructor calls OutputDebugStringF,
+ * maybe indirectly, and you get a core dump at shutdown trying to lock
+ * the mutex).
+ */
static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
-// We use boost::call_once() to make sure these are initialized in
-// in a thread-safe manner the first time it is called:
+/**
+ * We use boost::call_once() to make sure these are initialized
+ * in a thread-safe manner the first time called:
+ */
static FILE* fileout = NULL;
static boost::mutex* mutexDebugLog = NULL;
@@ -500,9 +504,11 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
#endif /* WIN32 */
}
-// Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
-// Specifically handles case where path p exists, but it wasn't possible for the user to
-// write to the parent directory.
+/**
+ * Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
+ * Specifically handles case where path p exists, but it wasn't possible for the user to
+ * write to the parent directory.
+ */
bool TryCreateDirectory(const boost::filesystem::path& p)
{
try
@@ -542,8 +548,10 @@ bool TruncateFile(FILE *file, unsigned int length) {
#endif
}
-// this function tries to raise the file descriptor limit to the requested number.
-// It returns the actual file descriptor limit (which may be more or less than nMinFD)
+/**
+ * this function tries to raise the file descriptor limit to the requested number.
+ * It returns the actual file descriptor limit (which may be more or less than nMinFD)
+ */
int RaiseFileDescriptorLimit(int nMinFD) {
#if defined(WIN32)
return 2048;
@@ -563,8 +571,10 @@ int RaiseFileDescriptorLimit(int nMinFD) {
#endif
}
-// this function tries to make a particular range of a file allocated (corresponding to disk space)
-// it is advisory, and the range specified in the arguments will never contain live data
+/**
+ * this function tries to make a particular range of a file allocated (corresponding to disk space)
+ * it is advisory, and the range specified in the arguments will never contain live data
+ */
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
#if defined(WIN32)
// Windows-specific version
diff --git a/src/util.h b/src/util.h
index 4b2415278b..a4aaf29f91 100644
--- a/src/util.h
+++ b/src/util.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.
/**
@@ -40,25 +40,26 @@ extern volatile bool fReopenDebugLog;
void SetupEnvironment();
-/* Return true if log accepts specified category */
+/** Return true if log accepts specified category */
bool LogAcceptCategory(const char* category);
-/* Send a string to the log output */
+/** Send a string to the log output */
int LogPrintStr(const std::string &str);
#define LogPrintf(...) LogPrint(NULL, __VA_ARGS__)
-/* When we switch to C++11, this can be switched to variadic templates instead
+/**
+ * When we switch to C++11, this can be switched to variadic templates instead
* of this macro-based construction (see tinyformat.h).
*/
#define MAKE_ERROR_AND_LOG_FUNC(n) \
- /* Print to debug.log if -debug=category switch is given OR category is NULL. */ \
+ /** Print to debug.log if -debug=category switch is given OR category is NULL. */ \
template<TINYFORMAT_ARGTYPES(n)> \
static inline int LogPrint(const char* category, const char* format, TINYFORMAT_VARARGS(n)) \
{ \
if(!LogAcceptCategory(category)) return 0; \
return LogPrintStr(tfm::format(format, TINYFORMAT_PASSARGS(n))); \
} \
- /* Log error and return false */ \
+ /** Log error and return false */ \
template<TINYFORMAT_ARGTYPES(n)> \
static inline bool error(const char* format, TINYFORMAT_VARARGS(n)) \
{ \
@@ -68,7 +69,8 @@ int LogPrintStr(const std::string &str);
TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_AND_LOG_FUNC)
-/* Zero-arg versions of logging and error, these are not covered by
+/**
+ * Zero-arg versions of logging and error, these are not covered by
* TINYFORMAT_FOREACH_ARGNUM
*/
static inline int LogPrint(const char* category, const char* format)
@@ -162,13 +164,15 @@ bool SoftSetBoolArg(const std::string& strArg, bool fValue);
void SetThreadPriority(int nPriority);
void RenameThread(const char* name);
-// Standard wrapper for do-something-forever thread functions.
-// "Forever" really means until the thread is interrupted.
-// Use it like:
-// new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 900000));
-// or maybe:
-// boost::function<void()> f = boost::bind(&FunctionWithArg, argument);
-// threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds));
+/**
+ * Standard wrapper for do-something-forever thread functions.
+ * "Forever" really means until the thread is interrupted.
+ * Use it like:
+ * new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 900000));
+ * or maybe:
+ * boost::function<void()> f = boost::bind(&FunctionWithArg, argument);
+ * threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds));
+ */
template <typename Callable> void LoopForever(const char* name, Callable func, int64_t msecs)
{
std::string s = strprintf("bitcoin-%s", name);
@@ -196,7 +200,10 @@ template <typename Callable> void LoopForever(const char* name, Callable func,
throw;
}
}
-// .. and a wrapper that just calls func once
+
+/**
+ * .. and a wrapper that just calls func once
+ */
template <typename Callable> void TraceThread(const char* name, Callable func)
{
std::string s = strprintf("bitcoin-%s", name);
diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp
index 267a5b845c..085adae85e 100644
--- a/src/utilmoneystr.cpp
+++ b/src/utilmoneystr.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 "utilmoneystr.h"
diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h
index 65415afd3f..6a153db5fa 100644
--- a/src/utilmoneystr.h
+++ b/src/utilmoneystr.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.
/**
diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp
index 81e156f43f..d0062d4544 100644
--- a/src/utilstrencodings.cpp
+++ b/src/utilstrencodings.cpp
@@ -1,24 +1,26 @@
// 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 "utilstrencodings.h"
#include "tinyformat.h"
-#include <errno.h>
-#include <limits>
#include <cstdlib>
#include <cstring>
+#include <errno.h>
+#include <limits>
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/utilstrencodings.h b/src/utilstrencodings.h
index 0b8c1a1781..0c0171b894 100644
--- a/src/utilstrencodings.h
+++ b/src/utilstrencodings.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.
/**
@@ -19,7 +19,7 @@
#define UEND(a) ((unsigned char*)&((&(a))[1]))
#define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0]))
-// This is needed because the foreach macro can't get over the comma in pair<t1, t2>
+/** This is needed because the foreach macro can't get over the comma in pair<t1, t2> */
#define PAIRTYPE(t1, t2) std::pair<t1, t2>
std::string SanitizeString(const std::string& str);
@@ -45,7 +45,7 @@ int atoi(const std::string& str);
/**
* Convert string to signed 32-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
- * false if not the entire string could be parsed or when overflow or underflow occured.
+ * false if not the entire string could be parsed or when overflow or underflow occurred.
*/
bool ParseInt32(const std::string& str, int32_t *out);
@@ -74,7 +74,8 @@ inline std::string HexStr(const T& vch, bool fSpaces=false)
return HexStr(vch.begin(), vch.end(), fSpaces);
}
-/** Format a paragraph of text to a fixed width, adding spaces for
+/**
+ * Format a paragraph of text to a fixed width, adding spaces for
* indentation to any added line.
*/
std::string FormatParagraph(const std::string in, size_t width=79, size_t indent=0);
diff --git a/src/utiltime.cpp b/src/utiltime.cpp
index 78f0342cba..9c137e8aa0 100644
--- a/src/utiltime.cpp
+++ b/src/utiltime.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)
@@ -14,7 +14,7 @@
using namespace std;
-static int64_t nMockTime = 0; // For unit testing
+static int64_t nMockTime = 0; //! For unit testing
int64_t GetTime()
{
@@ -42,9 +42,12 @@ int64_t GetTimeMicros()
void MilliSleep(int64_t n)
{
-// Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
-// until fixed in 1.52. Use the deprecated sleep method for the broken case.
-// See: https://svn.boost.org/trac/boost/ticket/7238
+
+/**
+ * Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
+ * until fixed in 1.52. Use the deprecated sleep method for the broken case.
+ * See: https://svn.boost.org/trac/boost/ticket/7238
+ */
#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
#elif defined(HAVE_WORKING_BOOST_SLEEP)
diff --git a/src/utiltime.h b/src/utiltime.h
index 6f82e5a836..9d7d42fe47 100644
--- a/src/utiltime.h
+++ b/src/utiltime.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_UTILTIME_H
diff --git a/src/wallet.cpp b/src/wallet.cpp
index d392149dbb..000a088b97 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();
@@ -422,15 +425,13 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
RandAddSeedPerfmon();
vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
- if (!GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE))
- return false;
+ GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
CMasterKey kMasterKey;
RandAddSeedPerfmon();
kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
- if (!GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE))
- return false;
+ GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
CCrypter crypter;
int64_t nStartTime = GetTimeMillis();
@@ -1384,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();
@@ -1504,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;
@@ -1630,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);
diff --git a/src/wallet.h b/src/wallet.h
index b692ad056b..0244ce2368 100644
--- a/src/wallet.h
+++ b/src/wallet.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;
diff --git a/src/wallet_ismine.cpp b/src/wallet_ismine.cpp
index 07149ebd0b..05dc40aaee 100644
--- a/src/wallet_ismine.cpp
+++ b/src/wallet_ismine.cpp
@@ -7,6 +7,7 @@
#include "key.h"
#include "keystore.h"
+#include "script/script.h"
#include "script/standard.h"
#include <boost/foreach.hpp>
diff --git a/src/wallet_ismine.h b/src/wallet_ismine.h
index f326b86815..5f0c0c1a01 100644
--- a/src/wallet_ismine.h
+++ b/src/wallet_ismine.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 H_BITCOIN_WALLET_ISMINE
-#define H_BITCOIN_WALLET_ISMINE
+#ifndef BITCOIN_WALLET_ISMINE_H
+#define BITCOIN_WALLET_ISMINE_H
#include "key.h"
#include "script/standard.h"
@@ -26,4 +26,4 @@ typedef uint8_t isminefilter;
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
-#endif // H_BITCOIN_WALLET_ISMINE
+#endif // BITCOIN_WALLET_ISMINE_H