Initial high performance version commit.
parent
7b39bc31be
commit
43ede0ac1b
17
README.md
17
README.md
|
@ -1,3 +1,20 @@
|
|||
Primecoin High Performance Version
|
||||
==================================
|
||||
|
||||
This is the high performance version of Sunny King's Primecoin tree.
|
||||
|
||||
Notable changes:
|
||||
* Use GMP for bignum calculations in the mining threads
|
||||
* Reduced sieve size to 100,000 so that important arrays fit into L1 cache
|
||||
* Replaced some bignum calculations with 64-bit arithmetic inside the sieve
|
||||
* Reduced the amount of memory allocations
|
||||
|
||||
Donations are welcome if you want to support my work.
|
||||
|
||||
BTC: 1EaHwHBWeoJtSM2jEdx9Su1NcKvdXbsqxX
|
||||
LTC: LPD1zDChmqcqKGHFHuLX2JWMMEC5jD5J4j
|
||||
XPM: AJHjbkVzHhHugd5bpKDtddVDfhtEB8jQZ4
|
||||
|
||||
Bitcoin integration/staging tree
|
||||
================================
|
||||
|
||||
|
|
|
@ -0,0 +1,425 @@
|
|||
TEMPLATE = app
|
||||
TARGET = primecoin-qt
|
||||
macx:TARGET = "Primecoin-Qt"
|
||||
VERSION = 0.8.3
|
||||
INCLUDEPATH += src src/json src/qt
|
||||
QT += network
|
||||
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
|
||||
CONFIG += no_include_pwd
|
||||
CONFIG += thread
|
||||
|
||||
# win32: Some defines needed for clean compile with mingw64
|
||||
win32:DEFINES += FD_SETSIZE=1024 BOOST_USE_WINDOWS_H WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x501
|
||||
|
||||
# for boost 1.37, add -mt to the boost libraries
|
||||
# use: qmake BOOST_LIB_SUFFIX=-mt
|
||||
# for boost thread win32 with _win32 sufix
|
||||
# use: BOOST_THREAD_LIB_SUFFIX=_win32-...
|
||||
# or when linking against a specific BerkelyDB version: BDB_LIB_SUFFIX=-4.8
|
||||
|
||||
# Dependency library locations can be customized with:
|
||||
# BOOST_INCLUDE_PATH, BOOST_LIB_PATH, BDB_INCLUDE_PATH,
|
||||
# BDB_LIB_PATH, OPENSSL_INCLUDE_PATH and OPENSSL_LIB_PATH respectively
|
||||
|
||||
OBJECTS_DIR = build
|
||||
MOC_DIR = build
|
||||
UI_DIR = build
|
||||
|
||||
# use: qmake "RELEASE=1"
|
||||
contains(RELEASE, 1) {
|
||||
# Mac: compile for maximum compatibility (10.5, 32-bit)
|
||||
macx:QMAKE_CXXFLAGS += -mmacosx-version-min=10.5 -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk
|
||||
macx:QMAKE_CFLAGS += -mmacosx-version-min=10.5 -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk
|
||||
macx:QMAKE_OBJECTIVE_CFLAGS += -mmacosx-version-min=10.5 -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk
|
||||
|
||||
!win32:!macx {
|
||||
# Linux: static link and extra security (see: https://wiki.debian.org/Hardening)
|
||||
LIBS += -Wl,-Bstatic -Wl,-z,relro -Wl,-z,now
|
||||
}
|
||||
}
|
||||
|
||||
!win32 {
|
||||
# for extra security against potential buffer overflows: enable GCCs Stack Smashing Protection
|
||||
QMAKE_CXXFLAGS *= -fstack-protector-all
|
||||
QMAKE_LFLAGS *= -fstack-protector-all
|
||||
# Exclude on Windows cross compile with MinGW 4.2.x, as it will result in a non-working executable!
|
||||
# This can be enabled for Windows, when we switch to MinGW >= 4.4.x.
|
||||
}
|
||||
# for extra security (see: https://wiki.debian.org/Hardening): this flag is GCC compiler-specific
|
||||
QMAKE_CXXFLAGS *= -D_FORTIFY_SOURCE=2
|
||||
# for extra security on Windows: enable ASLR and DEP via GCC linker flags
|
||||
win32:QMAKE_LFLAGS *= -Wl,--dynamicbase -Wl,--nxcompat
|
||||
|
||||
# use: qmake "USE_QRCODE=1"
|
||||
# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support
|
||||
contains(USE_QRCODE, 1) {
|
||||
message(Building with QRCode support)
|
||||
DEFINES += USE_QRCODE
|
||||
LIBS += -lqrencode
|
||||
}
|
||||
|
||||
# use: qmake "USE_UPNP=1" ( enabled by default; default)
|
||||
# or: qmake "USE_UPNP=0" (disabled by default)
|
||||
# or: qmake "USE_UPNP=-" (not supported)
|
||||
# miniupnpc (http://miniupnp.free.fr/files/) must be installed for support
|
||||
contains(USE_UPNP, -) {
|
||||
message(Building without UPNP support)
|
||||
} else {
|
||||
message(Building with UPNP support)
|
||||
count(USE_UPNP, 0) {
|
||||
USE_UPNP=1
|
||||
}
|
||||
DEFINES += USE_UPNP=$$USE_UPNP STATICLIB
|
||||
INCLUDEPATH += $$MINIUPNPC_INCLUDE_PATH
|
||||
LIBS += $$join(MINIUPNPC_LIB_PATH,,-L,) -lminiupnpc
|
||||
win32:LIBS += -liphlpapi
|
||||
}
|
||||
|
||||
# use: qmake "USE_DBUS=1"
|
||||
contains(USE_DBUS, 1) {
|
||||
message(Building with DBUS (Freedesktop notifications) support)
|
||||
DEFINES += USE_DBUS
|
||||
QT += dbus
|
||||
}
|
||||
|
||||
# use: qmake "USE_IPV6=1" ( enabled by default; default)
|
||||
# or: qmake "USE_IPV6=0" (disabled by default)
|
||||
# or: qmake "USE_IPV6=-" (not supported)
|
||||
contains(USE_IPV6, -) {
|
||||
message(Building without IPv6 support)
|
||||
} else {
|
||||
count(USE_IPV6, 0) {
|
||||
USE_IPV6=1
|
||||
}
|
||||
DEFINES += USE_IPV6=$$USE_IPV6
|
||||
}
|
||||
|
||||
contains(BITCOIN_NEED_QT_PLUGINS, 1) {
|
||||
DEFINES += BITCOIN_NEED_QT_PLUGINS
|
||||
QTPLUGIN += qcncodecs qjpcodecs qtwcodecs qkrcodecs qtaccessiblewidgets
|
||||
}
|
||||
|
||||
INCLUDEPATH += src/leveldb/include src/leveldb/helpers
|
||||
LIBS += $$PWD/src/leveldb/libleveldb.a $$PWD/src/leveldb/libmemenv.a
|
||||
!win32 {
|
||||
# we use QMAKE_CXXFLAGS_RELEASE even without RELEASE=1 because we use RELEASE to indicate linking preferences not -O preferences
|
||||
genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a
|
||||
} else {
|
||||
# make an educated guess about what the ranlib command is called
|
||||
isEmpty(QMAKE_RANLIB) {
|
||||
QMAKE_RANLIB = $$replace(QMAKE_STRIP, strip, ranlib)
|
||||
}
|
||||
LIBS += -lshlwapi
|
||||
genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libleveldb.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libmemenv.a
|
||||
}
|
||||
genleveldb.target = $$PWD/src/leveldb/libleveldb.a
|
||||
genleveldb.depends = FORCE
|
||||
PRE_TARGETDEPS += $$PWD/src/leveldb/libleveldb.a
|
||||
QMAKE_EXTRA_TARGETS += genleveldb
|
||||
# Gross ugly hack that depends on qmake internals, unfortunately there is no other way to do it.
|
||||
QMAKE_CLEAN += $$PWD/src/leveldb/libleveldb.a; cd $$PWD/src/leveldb ; $(MAKE) clean
|
||||
|
||||
# regenerate src/build.h
|
||||
!win32|contains(USE_BUILD_INFO, 1) {
|
||||
genbuild.depends = FORCE
|
||||
genbuild.commands = cd $$PWD; /bin/sh share/genbuild.sh $$OUT_PWD/build/build.h
|
||||
genbuild.target = $$OUT_PWD/build/build.h
|
||||
PRE_TARGETDEPS += $$OUT_PWD/build/build.h
|
||||
QMAKE_EXTRA_TARGETS += genbuild
|
||||
DEFINES += HAVE_BUILD_INFO
|
||||
}
|
||||
|
||||
QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wstack-protector
|
||||
|
||||
# Input
|
||||
DEPENDPATH += src src/json src/qt
|
||||
HEADERS += src/qt/bitcoingui.h \
|
||||
src/qt/transactiontablemodel.h \
|
||||
src/qt/addresstablemodel.h \
|
||||
src/qt/optionsdialog.h \
|
||||
src/qt/sendcoinsdialog.h \
|
||||
src/qt/addressbookpage.h \
|
||||
src/qt/signverifymessagedialog.h \
|
||||
src/qt/aboutdialog.h \
|
||||
src/qt/editaddressdialog.h \
|
||||
src/qt/bitcoinaddressvalidator.h \
|
||||
src/alert.h \
|
||||
src/addrman.h \
|
||||
src/base58.h \
|
||||
src/bignum.h \
|
||||
src/checkpoints.h \
|
||||
src/compat.h \
|
||||
src/sync.h \
|
||||
src/util.h \
|
||||
src/hash.h \
|
||||
src/uint256.h \
|
||||
src/serialize.h \
|
||||
src/main.h \
|
||||
src/net.h \
|
||||
src/key.h \
|
||||
src/db.h \
|
||||
src/walletdb.h \
|
||||
src/script.h \
|
||||
src/init.h \
|
||||
src/bloom.h \
|
||||
src/mruset.h \
|
||||
src/checkqueue.h \
|
||||
src/json/json_spirit_writer_template.h \
|
||||
src/json/json_spirit_writer.h \
|
||||
src/json/json_spirit_value.h \
|
||||
src/json/json_spirit_utils.h \
|
||||
src/json/json_spirit_stream_reader.h \
|
||||
src/json/json_spirit_reader_template.h \
|
||||
src/json/json_spirit_reader.h \
|
||||
src/json/json_spirit_error_position.h \
|
||||
src/json/json_spirit.h \
|
||||
src/qt/clientmodel.h \
|
||||
src/qt/guiutil.h \
|
||||
src/qt/transactionrecord.h \
|
||||
src/qt/guiconstants.h \
|
||||
src/qt/optionsmodel.h \
|
||||
src/qt/monitoreddatamapper.h \
|
||||
src/qt/transactiondesc.h \
|
||||
src/qt/transactiondescdialog.h \
|
||||
src/qt/bitcoinamountfield.h \
|
||||
src/wallet.h \
|
||||
src/keystore.h \
|
||||
src/qt/transactionfilterproxy.h \
|
||||
src/qt/transactionview.h \
|
||||
src/qt/walletmodel.h \
|
||||
src/qt/walletview.h \
|
||||
src/qt/walletstack.h \
|
||||
src/qt/walletframe.h \
|
||||
src/bitcoinrpc.h \
|
||||
src/qt/overviewpage.h \
|
||||
src/qt/csvmodelwriter.h \
|
||||
src/crypter.h \
|
||||
src/qt/sendcoinsentry.h \
|
||||
src/qt/qvalidatedlineedit.h \
|
||||
src/qt/bitcoinunits.h \
|
||||
src/qt/qvaluecombobox.h \
|
||||
src/qt/askpassphrasedialog.h \
|
||||
src/protocol.h \
|
||||
src/qt/notificator.h \
|
||||
src/qt/paymentserver.h \
|
||||
src/allocators.h \
|
||||
src/ui_interface.h \
|
||||
src/qt/rpcconsole.h \
|
||||
src/version.h \
|
||||
src/netbase.h \
|
||||
src/clientversion.h \
|
||||
src/txdb.h \
|
||||
src/leveldb.h \
|
||||
src/threadsafety.h \
|
||||
src/limitedmap.h \
|
||||
src/qt/splashscreen.h
|
||||
|
||||
SOURCES += src/qt/bitcoin.cpp \
|
||||
src/qt/bitcoingui.cpp \
|
||||
src/qt/transactiontablemodel.cpp \
|
||||
src/qt/addresstablemodel.cpp \
|
||||
src/qt/optionsdialog.cpp \
|
||||
src/qt/sendcoinsdialog.cpp \
|
||||
src/qt/addressbookpage.cpp \
|
||||
src/qt/signverifymessagedialog.cpp \
|
||||
src/qt/aboutdialog.cpp \
|
||||
src/qt/editaddressdialog.cpp \
|
||||
src/qt/bitcoinaddressvalidator.cpp \
|
||||
src/alert.cpp \
|
||||
src/version.cpp \
|
||||
src/sync.cpp \
|
||||
src/util.cpp \
|
||||
src/hash.cpp \
|
||||
src/netbase.cpp \
|
||||
src/key.cpp \
|
||||
src/script.cpp \
|
||||
src/main.cpp \
|
||||
src/init.cpp \
|
||||
src/net.cpp \
|
||||
src/bloom.cpp \
|
||||
src/checkpoints.cpp \
|
||||
src/addrman.cpp \
|
||||
src/db.cpp \
|
||||
src/walletdb.cpp \
|
||||
src/qt/clientmodel.cpp \
|
||||
src/qt/guiutil.cpp \
|
||||
src/qt/transactionrecord.cpp \
|
||||
src/qt/optionsmodel.cpp \
|
||||
src/qt/monitoreddatamapper.cpp \
|
||||
src/qt/transactiondesc.cpp \
|
||||
src/qt/transactiondescdialog.cpp \
|
||||
src/qt/bitcoinstrings.cpp \
|
||||
src/qt/bitcoinamountfield.cpp \
|
||||
src/wallet.cpp \
|
||||
src/keystore.cpp \
|
||||
src/qt/transactionfilterproxy.cpp \
|
||||
src/qt/transactionview.cpp \
|
||||
src/qt/walletmodel.cpp \
|
||||
src/qt/walletview.cpp \
|
||||
src/qt/walletstack.cpp \
|
||||
src/qt/walletframe.cpp \
|
||||
src/bitcoinrpc.cpp \
|
||||
src/rpcdump.cpp \
|
||||
src/rpcnet.cpp \
|
||||
src/rpcmining.cpp \
|
||||
src/rpcwallet.cpp \
|
||||
src/rpcblockchain.cpp \
|
||||
src/rpcrawtransaction.cpp \
|
||||
src/qt/overviewpage.cpp \
|
||||
src/qt/csvmodelwriter.cpp \
|
||||
src/crypter.cpp \
|
||||
src/qt/sendcoinsentry.cpp \
|
||||
src/qt/qvalidatedlineedit.cpp \
|
||||
src/qt/bitcoinunits.cpp \
|
||||
src/qt/qvaluecombobox.cpp \
|
||||
src/qt/askpassphrasedialog.cpp \
|
||||
src/protocol.cpp \
|
||||
src/qt/notificator.cpp \
|
||||
src/qt/paymentserver.cpp \
|
||||
src/qt/rpcconsole.cpp \
|
||||
src/noui.cpp \
|
||||
src/leveldb.cpp \
|
||||
src/txdb.cpp \
|
||||
src/qt/splashscreen.cpp \
|
||||
src/prime.cpp \
|
||||
src/checkpointsync.cpp
|
||||
|
||||
RESOURCES += src/qt/bitcoin.qrc
|
||||
|
||||
FORMS += src/qt/forms/sendcoinsdialog.ui \
|
||||
src/qt/forms/addressbookpage.ui \
|
||||
src/qt/forms/signverifymessagedialog.ui \
|
||||
src/qt/forms/aboutdialog.ui \
|
||||
src/qt/forms/editaddressdialog.ui \
|
||||
src/qt/forms/transactiondescdialog.ui \
|
||||
src/qt/forms/overviewpage.ui \
|
||||
src/qt/forms/sendcoinsentry.ui \
|
||||
src/qt/forms/askpassphrasedialog.ui \
|
||||
src/qt/forms/rpcconsole.ui \
|
||||
src/qt/forms/optionsdialog.ui
|
||||
|
||||
contains(USE_QRCODE, 1) {
|
||||
HEADERS += src/qt/qrcodedialog.h
|
||||
SOURCES += src/qt/qrcodedialog.cpp
|
||||
FORMS += src/qt/forms/qrcodedialog.ui
|
||||
}
|
||||
|
||||
contains(BITCOIN_QT_TEST, 1) {
|
||||
SOURCES += src/qt/test/test_main.cpp \
|
||||
src/qt/test/uritests.cpp
|
||||
HEADERS += src/qt/test/uritests.h
|
||||
DEPENDPATH += src/qt/test
|
||||
QT += testlib
|
||||
TARGET = bitcoin-qt_test
|
||||
DEFINES += BITCOIN_QT_TEST
|
||||
macx: CONFIG -= app_bundle
|
||||
}
|
||||
|
||||
CODECFORTR = UTF-8
|
||||
|
||||
# for lrelease/lupdate
|
||||
# also add new translations to src/qt/bitcoin.qrc under translations/
|
||||
TRANSLATIONS = $$files(src/qt/locale/bitcoin_*.ts)
|
||||
|
||||
isEmpty(QMAKE_LRELEASE) {
|
||||
win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
|
||||
else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
|
||||
}
|
||||
isEmpty(QM_DIR):QM_DIR = $$PWD/src/qt/locale
|
||||
# automatically build translations, so they can be included in resource file
|
||||
TSQM.name = lrelease ${QMAKE_FILE_IN}
|
||||
TSQM.input = TRANSLATIONS
|
||||
TSQM.output = $$QM_DIR/${QMAKE_FILE_BASE}.qm
|
||||
TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_OUT}
|
||||
TSQM.CONFIG = no_link
|
||||
QMAKE_EXTRA_COMPILERS += TSQM
|
||||
|
||||
# "Other files" to show in Qt Creator
|
||||
OTHER_FILES += README.md \
|
||||
doc/*.rst \
|
||||
doc/*.txt \
|
||||
src/qt/res/bitcoin-qt.rc \
|
||||
src/test/*.cpp \
|
||||
src/test/*.h \
|
||||
src/qt/test/*.cpp \
|
||||
src/qt/test/*.h
|
||||
|
||||
# platform specific defaults, if not overridden on command line
|
||||
isEmpty(BOOST_LIB_SUFFIX) {
|
||||
macx:BOOST_LIB_SUFFIX = -mt
|
||||
win32:BOOST_LIB_SUFFIX = -mt
|
||||
}
|
||||
|
||||
isEmpty(BOOST_THREAD_LIB_SUFFIX) {
|
||||
BOOST_THREAD_LIB_SUFFIX = $$BOOST_LIB_SUFFIX
|
||||
}
|
||||
|
||||
isEmpty(BDB_LIB_PATH) {
|
||||
macx:BDB_LIB_PATH = /opt/local/lib/db48
|
||||
}
|
||||
|
||||
isEmpty(BDB_LIB_SUFFIX) {
|
||||
macx:BDB_LIB_SUFFIX = -4.8
|
||||
}
|
||||
|
||||
isEmpty(BDB_INCLUDE_PATH) {
|
||||
macx:BDB_INCLUDE_PATH = /opt/local/include/db48
|
||||
}
|
||||
|
||||
isEmpty(BOOST_LIB_PATH) {
|
||||
macx:BOOST_LIB_PATH = /opt/local/lib
|
||||
}
|
||||
|
||||
isEmpty(BOOST_INCLUDE_PATH) {
|
||||
macx:BOOST_INCLUDE_PATH = /opt/local/include
|
||||
}
|
||||
|
||||
win32:DEFINES += WIN32
|
||||
win32:RC_FILE = src/qt/res/bitcoin-qt.rc
|
||||
|
||||
win32:!contains(MINGW_THREAD_BUGFIX, 0) {
|
||||
# At least qmake's win32-g++-cross profile is missing the -lmingwthrd
|
||||
# thread-safety flag. GCC has -mthreads to enable this, but it doesn't
|
||||
# work with static linking. -lmingwthrd must come BEFORE -lmingw, so
|
||||
# it is prepended to QMAKE_LIBS_QT_ENTRY.
|
||||
# It can be turned off with MINGW_THREAD_BUGFIX=0, just in case it causes
|
||||
# any problems on some untested qmake profile now or in the future.
|
||||
DEFINES += _MT
|
||||
QMAKE_LIBS_QT_ENTRY = -lmingwthrd $$QMAKE_LIBS_QT_ENTRY
|
||||
}
|
||||
|
||||
!win32:!macx {
|
||||
DEFINES += LINUX
|
||||
LIBS += -lrt
|
||||
# _FILE_OFFSET_BITS=64 lets 32-bit fopen transparently support large files.
|
||||
DEFINES += _FILE_OFFSET_BITS=64
|
||||
}
|
||||
|
||||
macx:HEADERS += src/qt/macdockiconhandler.h
|
||||
macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm
|
||||
macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
|
||||
macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0
|
||||
macx:ICON = src/qt/res/icons/bitcoin.icns
|
||||
macx:QMAKE_CFLAGS_THREAD += -pthread
|
||||
macx:QMAKE_LFLAGS_THREAD += -pthread
|
||||
macx:QMAKE_CXXFLAGS_THREAD += -pthread
|
||||
macx:QMAKE_INFO_PLIST = share/qt/Info.plist
|
||||
|
||||
# Set libraries and includes at end, to use platform-defined defaults if not overridden
|
||||
INCLUDEPATH += $$BOOST_INCLUDE_PATH $$BDB_INCLUDE_PATH $$OPENSSL_INCLUDE_PATH $$QRENCODE_INCLUDE_PATH
|
||||
LIBS += $$join(BOOST_LIB_PATH,,-L,) $$join(BDB_LIB_PATH,,-L,) $$join(OPENSSL_LIB_PATH,,-L,) $$join(QRENCODE_LIB_PATH,,-L,)
|
||||
LIBS += -lssl -lcrypto -ldb_cxx$$BDB_LIB_SUFFIX -lgmp
|
||||
# -lgdi32 has to happen after -lcrypto (see #681)
|
||||
win32:LIBS += -lws2_32 -lshlwapi -lmswsock -lole32 -loleaut32 -luuid -lgdi32
|
||||
LIBS += -lboost_system$$BOOST_LIB_SUFFIX -lboost_filesystem$$BOOST_LIB_SUFFIX -lboost_program_options$$BOOST_LIB_SUFFIX -lboost_thread$$BOOST_THREAD_LIB_SUFFIX
|
||||
win32:LIBS += -lboost_chrono$$BOOST_LIB_SUFFIX
|
||||
macx:LIBS += -lboost_chrono$$BOOST_LIB_SUFFIX
|
||||
|
||||
contains(RELEASE, 1) {
|
||||
!win32:!macx {
|
||||
# Linux: turn dynamic linking back on for c/c++ runtime libraries
|
||||
LIBS += -Wl,-Bdynamic
|
||||
}
|
||||
}
|
||||
|
||||
system($$QMAKE_LRELEASE -silent $$TRANSLATIONS)
|
|
@ -8,6 +8,9 @@ DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE
|
|||
CONFIG += no_include_pwd
|
||||
CONFIG += thread
|
||||
|
||||
# avoid warnings about FD_SETSIZE being redefined
|
||||
win32:DEFINES += FD_SETSIZE=1024
|
||||
|
||||
# for boost 1.37, add -mt to the boost libraries
|
||||
# use: qmake BOOST_LIB_SUFFIX=-mt
|
||||
# for boost thread win32 with _win32 sufix
|
||||
|
@ -407,7 +410,7 @@ macx:QMAKE_INFO_PLIST = share/qt/Info.plist
|
|||
# Set libraries and includes at end, to use platform-defined defaults if not overridden
|
||||
INCLUDEPATH += $$BOOST_INCLUDE_PATH $$BDB_INCLUDE_PATH $$OPENSSL_INCLUDE_PATH $$QRENCODE_INCLUDE_PATH
|
||||
LIBS += $$join(BOOST_LIB_PATH,,-L,) $$join(BDB_LIB_PATH,,-L,) $$join(OPENSSL_LIB_PATH,,-L,) $$join(QRENCODE_LIB_PATH,,-L,)
|
||||
LIBS += -lssl -lcrypto -ldb_cxx$$BDB_LIB_SUFFIX
|
||||
LIBS += -lssl -lcrypto -ldb_cxx$$BDB_LIB_SUFFIX -lgmp
|
||||
# -lgdi32 has to happen after -lcrypto (see #681)
|
||||
win32:LIBS += -lws2_32 -lshlwapi -lmswsock -lole32 -loleaut32 -luuid -lgdi32
|
||||
LIBS += -lboost_system$$BOOST_LIB_SUFFIX -lboost_filesystem$$BOOST_LIB_SUFFIX -lboost_program_options$$BOOST_LIB_SUFFIX -lboost_thread$$BOOST_THREAD_LIB_SUFFIX
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
Primecoin High Performance Version
|
||||
==================================
|
||||
|
||||
This is the high performance version of Sunny King's Primecoin tree.
|
||||
|
||||
Notable changes:
|
||||
* Use GMP for bignum calculations in the mining threads
|
||||
* Reduced sieve size to 100,000 so that important arrays fit into L1 cache
|
||||
* Replaced some bignum calculations with 64-bit arithmetic inside the sieve
|
||||
* Reduced the amount of memory allocations
|
||||
|
||||
Donations are welcome if you want to support my work.
|
||||
|
||||
BTC: 1EaHwHBWeoJtSM2jEdx9Su1NcKvdXbsqxX
|
||||
LTC: LPD1zDChmqcqKGHFHuLX2JWMMEC5jD5J4j
|
||||
XPM: AJHjbkVzHhHugd5bpKDtddVDfhtEB8jQZ4
|
||||
|
||||
Primecoin 0.1.1 BETA
|
||||
====================
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
Primecoin High Performance Version
|
||||
==================================
|
||||
|
||||
This is the high performance version of Sunny King's Primecoin tree.
|
||||
|
||||
Notable changes:
|
||||
* Use GMP for bignum calculations in the mining threads
|
||||
* Reduced sieve size to 100,000 so that important arrays fit into L1 cache
|
||||
* Replaced some bignum calculations with 64-bit arithmetic inside the sieve
|
||||
* Reduced the amount of memory allocations
|
||||
|
||||
Donations are welcome if you want to support my work.
|
||||
|
||||
BTC: 1EaHwHBWeoJtSM2jEdx9Su1NcKvdXbsqxX
|
||||
LTC: LPD1zDChmqcqKGHFHuLX2JWMMEC5jD5J4j
|
||||
XPM: AJHjbkVzHhHugd5bpKDtddVDfhtEB8jQZ4
|
||||
|
||||
Primecoin 0.1.1 BETA
|
||||
====================
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <map>
|
||||
#include <openssl/crypto.h> // for OPENSSL_cleanse()
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN64
|
||||
typedef u_int SOCKET;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
#define MSG_NOSIGNAL 0
|
||||
#define MSG_DONTWAIT 0
|
||||
|
|
40
src/main.cpp
40
src/main.cpp
|
@ -1122,7 +1122,10 @@ unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBl
|
|||
|
||||
bool CheckProofOfWork(uint256 hashBlockHeader, unsigned int nBits, const CBigNum& bnProbablePrime, unsigned int& nChainType, unsigned int& nChainLength)
|
||||
{
|
||||
if (!CheckPrimeProofOfWork(hashBlockHeader, nBits, bnProbablePrime, nChainType, nChainLength))
|
||||
char *strProbablePrime = BN_bn2hex(&bnProbablePrime);
|
||||
mpz_class mpzProbablePrime(strProbablePrime, 16);
|
||||
OPENSSL_free(strProbablePrime);
|
||||
if (!CheckPrimeProofOfWork(hashBlockHeader, nBits, mpzProbablePrime, nChainType, nChainLength))
|
||||
return error("CheckProofOfWork() : check failed for prime proof-of-work");
|
||||
return true;
|
||||
}
|
||||
|
@ -4607,14 +4610,24 @@ void static BitcoinMiner(CWallet *pwallet)
|
|||
unsigned int nTriedMultiplier = 0;
|
||||
|
||||
// Primecoin: try to find hash divisible by primorial
|
||||
CBigNum bnHashFactor;
|
||||
Primorial(nPrimorialHashFactor, bnHashFactor);
|
||||
while ((pblock->GetHeaderHash() < hashBlockHeaderLimit || CBigNum(pblock->GetHeaderHash()) % bnHashFactor != 0) && pblock->nNonce < 0xffff0000)
|
||||
mpz_class mpzHashFactor;
|
||||
Primorial(nPrimorialHashFactor, mpzHashFactor);
|
||||
|
||||
// mustyoshi's patch from https://bitcointalk.org/index.php?topic=251850.msg2689981#msg2689981
|
||||
// with some gmp modifications
|
||||
uint256 phash = pblock->GetHeaderHash();
|
||||
mpz_class mpzHash;
|
||||
mpz_set_uint256(mpzHash.get_mpz_t(), phash);
|
||||
|
||||
while ((phash < hashBlockHeaderLimit || (mpzHash % mpzHashFactor != 0)) && pblock->nNonce < 0xffff0000) {
|
||||
pblock->nNonce++;
|
||||
phash = pblock->GetHeaderHash();
|
||||
mpz_set_uint256(mpzHash.get_mpz_t(), phash);
|
||||
}
|
||||
if (pblock->nNonce >= 0xffff0000)
|
||||
continue;
|
||||
// Primecoin: primorial fixed multiplier
|
||||
CBigNum bnPrimorial;
|
||||
mpz_class mpzPrimorial;
|
||||
unsigned int nRoundTests = 0;
|
||||
unsigned int nRoundPrimesHit = 0;
|
||||
int64 nPrimeTimerStart = GetTimeMicros();
|
||||
|
@ -4632,25 +4645,30 @@ void static BitcoinMiner(CWallet *pwallet)
|
|||
if (!PrimeTableGetPreviousPrime(nPrimorialMultiplier))
|
||||
error("PrimecoinMiner() : primorial decrement overflow");
|
||||
}
|
||||
Primorial(nPrimorialMultiplier, bnPrimorial);
|
||||
Primorial(nPrimorialMultiplier, mpzPrimorial);
|
||||
|
||||
loop
|
||||
{
|
||||
unsigned int nTests = 0;
|
||||
unsigned int nPrimesHit = 0;
|
||||
|
||||
CBigNum bnMultiplierMin = bnPrimeMin * bnHashFactor / CBigNum(pblock->GetHeaderHash()) + 1;
|
||||
while (bnPrimorial < bnMultiplierMin)
|
||||
mpz_class mpzMultiplierMin = mpzPrimeMin * mpzHashFactor / mpzHash + 1;
|
||||
while (mpzPrimorial < mpzMultiplierMin)
|
||||
{
|
||||
if (!PrimeTableGetNextPrime(nPrimorialMultiplier))
|
||||
error("PrimecoinMiner() : primorial minimum overflow");
|
||||
Primorial(nPrimorialMultiplier, bnPrimorial);
|
||||
Primorial(nPrimorialMultiplier, mpzPrimorial);
|
||||
}
|
||||
mpz_class mpzFixedMultiplier;
|
||||
if (mpzPrimorial > mpzHashFactor) {
|
||||
mpzFixedMultiplier = mpzPrimorial / mpzHashFactor;
|
||||
} else {
|
||||
mpzFixedMultiplier = 1;
|
||||
}
|
||||
CBigNum bnFixedMultiplier = (bnPrimorial > bnHashFactor)? (bnPrimorial / bnHashFactor) : 1;
|
||||
|
||||
// Primecoin: mine for prime chain
|
||||
unsigned int nProbableChainLength;
|
||||
if (MineProbablePrimeChain(*pblock, bnFixedMultiplier, fNewBlock, nTriedMultiplier, nProbableChainLength, nTests, nPrimesHit))
|
||||
if (MineProbablePrimeChain(*pblock, mpzFixedMultiplier, fNewBlock, nTriedMultiplier, nProbableChainLength, nTests, nPrimesHit, mpzHash))
|
||||
{
|
||||
SetThreadPriority(THREAD_PRIORITY_NORMAL);
|
||||
CheckWork(pblock, *pwalletMain, reservekey);
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
# Distributed under the conditional MIT/X11 software license,
|
||||
# see the accompanying file COPYING
|
||||
|
||||
DEPSDIR:=/usr/i586-mingw32msvc
|
||||
DEPSDIR:=/usr/i686-pc-mingw32
|
||||
|
||||
CC := i586-mingw32msvc-gcc
|
||||
CXX := i586-mingw32msvc-g++
|
||||
CC := i686-pc-mingw32-gcc
|
||||
CXX := i686-pc-mingw32-g++
|
||||
|
||||
USE_UPNP:=0
|
||||
USE_IPV6:=1
|
||||
|
@ -26,14 +26,16 @@ LIBPATHS= \
|
|||
|
||||
LIBS= \
|
||||
$(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a \
|
||||
-l boost_system-mt-s \
|
||||
-l boost_filesystem-mt-s \
|
||||
-l boost_program_options-mt-s \
|
||||
-l boost_thread_win32-mt-s \
|
||||
-l boost_chrono-mt-s \
|
||||
-l boost_system-mt \
|
||||
-l boost_filesystem-mt \
|
||||
-l boost_program_options-mt \
|
||||
-l boost_thread_win32-mt \
|
||||
-l boost_chrono-mt \
|
||||
-l db_cxx \
|
||||
-l ssl \
|
||||
-l crypto
|
||||
-l crypto \
|
||||
-l z \
|
||||
-l gmp
|
||||
|
||||
DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
|
||||
DEBUGFLAGS=-g
|
||||
|
@ -101,7 +103,7 @@ all: primecoind.exe
|
|||
DEFS += -I"$(CURDIR)/leveldb/include"
|
||||
DEFS += -I"$(CURDIR)/leveldb/helpers"
|
||||
leveldb/libleveldb.a:
|
||||
@echo "Building LevelDB ..." && cd leveldb && TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(xCXXFLAGS)" libleveldb.a libmemenv.a && i586-mingw32msvc-ranlib libleveldb.a && i586-mingw32msvc-ranlib libmemenv.a && cd ..
|
||||
@echo "Building LevelDB ..." && cd leveldb && TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(xCXXFLAGS)" libleveldb.a libmemenv.a && i686-pc-mingw32-ranlib libleveldb.a && i686-pc-mingw32-ranlib libmemenv.a && cd ..
|
||||
|
||||
obj/build.h: FORCE
|
||||
/bin/sh ../share/genbuild.sh obj/build.h
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
# Copyright (c) 2013 Primecoin Developers
|
||||
# Distributed under the conditional MIT/X11 software license,
|
||||
# see the accompanying file COPYING
|
||||
|
||||
DEPSDIR:=/usr/x86_64-w64-mingw32
|
||||
|
||||
CC := x86_64-w64-mingw32-gcc
|
||||
CXX := x86_64-w64-mingw32-g++
|
||||
|
||||
USE_UPNP:=0
|
||||
USE_IPV6:=1
|
||||
|
||||
INCLUDEPATHS= \
|
||||
-I"$(CURDIR)" \
|
||||
-I"$(CURDIR)"/obj \
|
||||
-I"$(DEPSDIR)/boost_1_50_0" \
|
||||
-I"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
|
||||
-I"$(DEPSDIR)/openssl-1.0.1c/include" \
|
||||
-I"$(DEPSDIR)"
|
||||
|
||||
LIBPATHS= \
|
||||
-L"$(DEPSDIR)/boost_1_50_0/stage/lib" \
|
||||
-L"$(DEPSDIR)/db-4.8.30.NC/build_unix" \
|
||||
-L"$(DEPSDIR)/openssl-1.0.1c"
|
||||
|
||||
LIBS= \
|
||||
$(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a \
|
||||
-l boost_system-mt \
|
||||
-l boost_filesystem-mt \
|
||||
-l boost_program_options-mt \
|
||||
-l boost_thread_win32-mt \
|
||||
-l boost_chrono-mt \
|
||||
-l db_cxx \
|
||||
-l ssl \
|
||||
-l crypto \
|
||||
-l z \
|
||||
-l gmp
|
||||
|
||||
DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE -DBOOST_USE_WINDOWS_H -DFD_SETSIZE=1024 -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x501
|
||||
DEBUGFLAGS=-g
|
||||
xCXXFLAGS=-O2 -w -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) $(CXXFLAGS)
|
||||
# enable: ASLR, DEP and large address aware
|
||||
xLDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat $(LDFLAGS)
|
||||
|
||||
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
|
||||
|
||||
ifndef USE_UPNP
|
||||
override USE_UPNP = -
|
||||
endif
|
||||
ifneq (${USE_UPNP}, -)
|
||||
LIBPATHS += -L"$(DEPSDIR)/miniupnpc"
|
||||
LIBS += -l miniupnpc -l iphlpapi
|
||||
DEFS += -DSTATICLIB -DUSE_UPNP=$(USE_UPNP)
|
||||
endif
|
||||
|
||||
ifneq (${USE_IPV6}, -)
|
||||
DEFS += -DUSE_IPV6=$(USE_IPV6)
|
||||
endif
|
||||
|
||||
LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi
|
||||
|
||||
# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
OBJS= \
|
||||
leveldb/libleveldb.a \
|
||||
obj/alert.o \
|
||||
obj/version.o \
|
||||
obj/checkpoints.o \
|
||||
obj/netbase.o \
|
||||
obj/addrman.o \
|
||||
obj/crypter.o \
|
||||
obj/key.o \
|
||||
obj/db.o \
|
||||
obj/init.o \
|
||||
obj/keystore.o \
|
||||
obj/main.o \
|
||||
obj/net.o \
|
||||
obj/protocol.o \
|
||||
obj/bitcoinrpc.o \
|
||||
obj/rpcdump.o \
|
||||
obj/rpcnet.o \
|
||||
obj/rpcmining.o \
|
||||
obj/rpcwallet.o \
|
||||
obj/rpcblockchain.o \
|
||||
obj/rpcrawtransaction.o \
|
||||
obj/script.o \
|
||||
obj/sync.o \
|
||||
obj/util.o \
|
||||
obj/wallet.o \
|
||||
obj/walletdb.o \
|
||||
obj/noui.o \
|
||||
obj/hash.o \
|
||||
obj/bloom.o \
|
||||
obj/leveldb.o \
|
||||
obj/txdb.o \
|
||||
obj/prime.o \
|
||||
obj/checkpointsync.o
|
||||
|
||||
all: primecoind.exe
|
||||
|
||||
DEFS += -I"$(CURDIR)/leveldb/include"
|
||||
DEFS += -I"$(CURDIR)/leveldb/helpers"
|
||||
leveldb/libleveldb.a:
|
||||
@echo "Building LevelDB ..." && cd leveldb && TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(xCXXFLAGS)" libleveldb.a libmemenv.a && x86_64-w64-mingw32-ranlib libleveldb.a && x86_64-w64-mingw32-ranlib libmemenv.a && cd ..
|
||||
|
||||
obj/build.h: FORCE
|
||||
/bin/sh ../share/genbuild.sh obj/build.h
|
||||
version.cpp: obj/build.h
|
||||
DEFS += -DHAVE_BUILD_INFO
|
||||
|
||||
obj/%.o: %.cpp $(HEADERS)
|
||||
$(CXX) -c $(xCXXFLAGS) -o $@ $<
|
||||
|
||||
primecoind.exe: $(OBJS:obj/%=obj/%)
|
||||
$(CXX) $(xCXXFLAGS) $(xLDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
|
||||
|
||||
TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp))
|
||||
|
||||
obj-test/%.o: test/%.cpp $(HEADERS)
|
||||
$(CXX) -c $(TESTDEFS) $(xCXXFLAGS) -o $@ $<
|
||||
|
||||
test_primecoin.exe: $(TESTOBJS) $(filter-out obj/init.o,$(OBJS:obj/%=obj/%))
|
||||
$(CXX) $(xCXXFLAGS) $(xLDFLAGS) -o $@ $(LIBPATHS) $^ -lboost_unit_test_framework-mt-s $(LIBS)
|
||||
|
||||
|
||||
clean:
|
||||
-rm -f obj/*.o
|
||||
-rm -f primecoind.exe
|
||||
-rm -f obj-test/*.o
|
||||
-rm -f test_primecoin.exe
|
||||
-rm -f obj/build.h
|
||||
cd leveldb && TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) clean && cd ..
|
||||
|
||||
FORCE:
|
|
@ -42,7 +42,8 @@ LIBS= \
|
|||
-l boost_chrono$(BOOST_SUFFIX) \
|
||||
-l db_cxx \
|
||||
-l ssl \
|
||||
-l crypto
|
||||
-l crypto \
|
||||
-l gmp
|
||||
|
||||
DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE
|
||||
DEBUGFLAGS=-g
|
||||
|
|
|
@ -53,6 +53,7 @@ LIBS += \
|
|||
-lboost_chrono-mt \
|
||||
-lssl \
|
||||
-lcrypto \
|
||||
-lgmp \
|
||||
-lz
|
||||
TESTDEFS += -DBOOST_TEST_DYN_LINK
|
||||
endif
|
||||
|
|
|
@ -41,7 +41,8 @@ LIBS += \
|
|||
-l boost_thread$(BOOST_LIB_SUFFIX) \
|
||||
-l db_cxx$(BDB_LIB_SUFFIX) \
|
||||
-l ssl \
|
||||
-l crypto
|
||||
-l crypto \
|
||||
-l gmp
|
||||
|
||||
TESTLIBS += \
|
||||
-Wl,-B$(LMODE) \
|
||||
|
|
|
@ -1652,14 +1652,15 @@ bool BindListenPort(const CService &addrBind, string& strError)
|
|||
// some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
|
||||
// and enable it by default or not. Try to enable it, if possible.
|
||||
if (addrBind.IsIPv6()) {
|
||||
#ifdef IPV6_V6ONLY
|
||||
setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
|
||||
int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
|
||||
// this call is allowed to fail
|
||||
setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
|
||||
#else
|
||||
#ifdef IPV6_V6ONLY
|
||||
setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
315
src/prime.cpp
315
src/prime.cpp
|
@ -12,7 +12,7 @@ void GeneratePrimeTable()
|
|||
{
|
||||
vPrimes.clear();
|
||||
// Generate prime table using sieve of Eratosthenes
|
||||
std::vector<bool> vfComposite (nPrimeTableLimit, false);
|
||||
std::bitset<nPrimeTableLimit> vfComposite = std::bitset<nPrimeTableLimit> ();
|
||||
for (unsigned int nFactor = 2; nFactor * nFactor < nPrimeTableLimit; nFactor++)
|
||||
{
|
||||
if (vfComposite[nFactor])
|
||||
|
@ -62,24 +62,24 @@ bool PrimeTableGetPreviousPrime(unsigned int& p)
|
|||
}
|
||||
|
||||
// Compute Primorial number p#
|
||||
void Primorial(unsigned int p, CBigNum& bnPrimorial)
|
||||
void Primorial(unsigned int p, mpz_class& mpzPrimorial)
|
||||
{
|
||||
bnPrimorial = 1;
|
||||
mpzPrimorial = 1;
|
||||
BOOST_FOREACH(unsigned int nPrime, vPrimes)
|
||||
{
|
||||
if (nPrime > p) break;
|
||||
bnPrimorial *= nPrime;
|
||||
mpzPrimorial *= nPrime;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute first primorial number greater than or equal to pn
|
||||
void PrimorialAt(CBigNum& bn, CBigNum& bnPrimorial)
|
||||
void PrimorialAt(mpz_class& bn, mpz_class& mpzPrimorial)
|
||||
{
|
||||
bnPrimorial = 1;
|
||||
mpzPrimorial = 1;
|
||||
BOOST_FOREACH(unsigned int nPrime, vPrimes)
|
||||
{
|
||||
bnPrimorial *= nPrime;
|
||||
if (bnPrimorial >= bn)
|
||||
mpzPrimorial *= nPrime;
|
||||
if (mpzPrimorial >= bn)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -87,17 +87,33 @@ void PrimorialAt(CBigNum& bn, CBigNum& bnPrimorial)
|
|||
// Check Fermat probable primality test (2-PRP): 2 ** (n-1) = 1 (mod n)
|
||||
// true: n is probable prime
|
||||
// false: n is composite; set fractional length in the nLength output
|
||||
static bool FermatProbablePrimalityTest(const CBigNum& n, unsigned int& nLength)
|
||||
static bool FermatProbablePrimalityTest(const mpz_class& n, unsigned int& nLength)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum a = 2; // base; Fermat witness
|
||||
CBigNum e = n - 1;
|
||||
CBigNum r;
|
||||
BN_mod_exp(&r, &a, &e, &n, pctx);
|
||||
if (r == 1)
|
||||
// Faster GMP version
|
||||
|
||||
mpz_t mpzN;
|
||||
mpz_t mpzE;
|
||||
mpz_t mpzR;
|
||||
|
||||
mpz_init_set(mpzN, n.get_mpz_t());
|
||||
mpz_init(mpzE);
|
||||
mpz_sub_ui(mpzE, mpzN, 1);
|
||||
mpz_init(mpzR);
|
||||
mpz_powm(mpzR, mpzTwo.get_mpz_t(), mpzE, mpzN);
|
||||
if (mpz_cmp_ui(mpzR, 1) == 0) {
|
||||
mpz_clear(mpzN);
|
||||
mpz_clear(mpzE);
|
||||
mpz_clear(mpzR);
|
||||
return true;
|
||||
}
|
||||
// Failed Fermat test, calculate fractional length
|
||||
unsigned int nFractionalLength = (((n-r) << nFractionalBits) / n).getuint();
|
||||
mpz_sub(mpzE, mpzN, mpzR);
|
||||
mpz_mul_2exp(mpzR, mpzE, nFractionalBits);
|
||||
mpz_tdiv_q(mpzE, mpzR, mpzN);
|
||||
unsigned int nFractionalLength = mpz_get_ui(mpzE);
|
||||
mpz_clear(mpzN);
|
||||
mpz_clear(mpzE);
|
||||
mpz_clear(mpzR);
|
||||
if (nFractionalLength >= (1 << nFractionalBits))
|
||||
return error("FermatProbablePrimalityTest() : fractional assert");
|
||||
nLength = (nLength & TARGET_LENGTH_MASK) | nFractionalLength;
|
||||
|
@ -111,33 +127,73 @@ static bool FermatProbablePrimalityTest(const CBigNum& n, unsigned int& nLength)
|
|||
// Return values
|
||||
// true: n is probable prime
|
||||
// false: n is composite; set fractional length in the nLength output
|
||||
static bool EulerLagrangeLifchitzPrimalityTest(const CBigNum& n, bool fSophieGermain, unsigned int& nLength)
|
||||
static bool EulerLagrangeLifchitzPrimalityTest(const mpz_class& n, bool fSophieGermain, unsigned int& nLength)
|
||||
{
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum a = 2;
|
||||
CBigNum e = (n - 1) >> 1;
|
||||
CBigNum r;
|
||||
BN_mod_exp(&r, &a, &e, &n, pctx);
|
||||
CBigNum nMod8 = n % 8;
|
||||
// Faster GMP version
|
||||
mpz_t mpzN;
|
||||
mpz_t mpzE;
|
||||
mpz_t mpzR;
|
||||
|
||||
mpz_init_set(mpzN, n.get_mpz_t());
|
||||
mpz_init(mpzE);
|
||||
mpz_sub_ui(mpzE, mpzN, 1);
|
||||
mpz_tdiv_q_2exp(mpzE, mpzE, 1);
|
||||
mpz_init(mpzR);
|
||||
mpz_powm(mpzR, mpzTwo.get_mpz_t(), mpzE, mpzN);
|
||||
unsigned int nMod8 = mpz_tdiv_ui(mpzN, 8);
|
||||
bool fPassedTest = false;
|
||||
if (fSophieGermain && (nMod8 == 7)) // Euler & Lagrange
|
||||
fPassedTest = (r == 1);
|
||||
fPassedTest = !mpz_cmp_ui(mpzR, 1);
|
||||
else if (fSophieGermain && (nMod8 == 3)) // Lifchitz
|
||||
fPassedTest = ((r+1) == n);
|
||||
{
|
||||
mpz_t mpzRplusOne;
|
||||
mpz_init(mpzRplusOne);
|
||||
mpz_add_ui(mpzRplusOne, mpzR, 1);
|
||||
fPassedTest = !mpz_cmp(mpzRplusOne, mpzN);
|
||||
mpz_clear(mpzRplusOne);
|
||||
}
|
||||
else if ((!fSophieGermain) && (nMod8 == 5)) // Lifchitz
|
||||
fPassedTest = ((r+1) == n);
|
||||
{
|
||||
mpz_t mpzRplusOne;
|
||||
mpz_init(mpzRplusOne);
|
||||
mpz_add_ui(mpzRplusOne, mpzR, 1);
|
||||
fPassedTest = !mpz_cmp(mpzRplusOne, mpzN);
|
||||
mpz_clear(mpzRplusOne);
|
||||
}
|
||||
else if ((!fSophieGermain) && (nMod8 == 1)) // LifChitz
|
||||
fPassedTest = (r == 1);
|
||||
{
|
||||
fPassedTest = !mpz_cmp_ui(mpzR, 1);
|
||||
}
|
||||
else
|
||||
return error("EulerLagrangeLifchitzPrimalityTest() : invalid n %% 8 = %d, %s", nMod8.getint(), (fSophieGermain? "first kind" : "second kind"));
|
||||
|
||||
if (fPassedTest)
|
||||
{
|
||||
mpz_clear(mpzN);
|
||||
mpz_clear(mpzE);
|
||||
mpz_clear(mpzR);
|
||||
return error("EulerLagrangeLifchitzPrimalityTest() : invalid n %% 8 = %d, %s", nMod8, (fSophieGermain? "first kind" : "second kind"));
|
||||
}
|
||||
|
||||
if (fPassedTest) {
|
||||
mpz_clear(mpzN);
|
||||
mpz_clear(mpzE);
|
||||
mpz_clear(mpzR);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Failed test, calculate fractional length
|
||||
r = (r * r) % n; // derive Fermat test remainder
|
||||
unsigned int nFractionalLength = (((n-r) << nFractionalBits) / n).getuint();
|
||||
if (nFractionalLength >= (1 << nFractionalBits))
|
||||
mpz_mul(mpzE, mpzR, mpzR);
|
||||
mpz_tdiv_r(mpzR, mpzE, mpzN); // derive Fermat test remainder
|
||||
|
||||
mpz_sub(mpzE, mpzN, mpzR);
|
||||
mpz_mul_2exp(mpzR, mpzE, nFractionalBits);
|
||||
mpz_tdiv_q(mpzE, mpzR, mpzN);
|
||||
unsigned int nFractionalLength = mpz_get_ui(mpzE);
|
||||
mpz_clear(mpzN);
|
||||
mpz_clear(mpzE);
|
||||
mpz_clear(mpzR);
|
||||
|
||||
if (nFractionalLength >= (1 << nFractionalBits)) {
|
||||
return error("EulerLagrangeLifchitzPrimalityTest() : fractional assert");
|
||||
}
|
||||
nLength = (nLength & TARGET_LENGTH_MASK) | nFractionalLength;
|
||||
return false;
|
||||
}
|
||||
|
@ -281,10 +337,10 @@ bool TargetGetNext(unsigned int nBits, int64 nInterval, int64 nTargetSpacing, in
|
|||
// Return value:
|
||||
// true - Probable Cunningham Chain found (length at least 2)
|
||||
// false - Not Cunningham Chain
|
||||
static bool ProbableCunninghamChainTest(const CBigNum& n, bool fSophieGermain, bool fFermatTest, unsigned int& nProbableChainLength)
|
||||
static bool ProbableCunninghamChainTest(const mpz_class& n, bool fSophieGermain, bool fFermatTest, unsigned int& nProbableChainLength)
|
||||
{
|
||||
nProbableChainLength = 0;
|
||||
CBigNum N = n;
|
||||
mpz_class N = n;
|
||||
|
||||
// Fermat test for n first
|
||||
if (!FermatProbablePrimalityTest(N, nProbableChainLength))
|
||||
|
@ -314,16 +370,16 @@ static bool ProbableCunninghamChainTest(const CBigNum& n, bool fSophieGermain, b
|
|||
// Return value:
|
||||
// true - Probable prime chain found (one of nChainLength meeting target)
|
||||
// false - prime chain too short (none of nChainLength meeting target)
|
||||
bool ProbablePrimeChainTest(const CBigNum& bnPrimeChainOrigin, unsigned int nBits, bool fFermatTest, unsigned int& nChainLengthCunningham1, unsigned int& nChainLengthCunningham2, unsigned int& nChainLengthBiTwin)
|
||||
bool ProbablePrimeChainTest(const mpz_class& mpzPrimeChainOrigin, unsigned int nBits, bool fFermatTest, unsigned int& nChainLengthCunningham1, unsigned int& nChainLengthCunningham2, unsigned int& nChainLengthBiTwin)
|
||||
{
|
||||
nChainLengthCunningham1 = 0;
|
||||
nChainLengthCunningham2 = 0;
|
||||
nChainLengthBiTwin = 0;
|
||||
|
||||
// Test for Cunningham Chain of first kind
|
||||
ProbableCunninghamChainTest(bnPrimeChainOrigin-1, true, fFermatTest, nChainLengthCunningham1);
|
||||
ProbableCunninghamChainTest(mpzPrimeChainOrigin-1, true, fFermatTest, nChainLengthCunningham1);
|
||||
// Test for Cunningham Chain of second kind
|
||||
ProbableCunninghamChainTest(bnPrimeChainOrigin+1, false, fFermatTest, nChainLengthCunningham2);
|
||||
ProbableCunninghamChainTest(mpzPrimeChainOrigin+1, false, fFermatTest, nChainLengthCunningham2);
|
||||
// Figure out BiTwin Chain length
|
||||
// BiTwin Chain allows a single prime at the end for odd length chain
|
||||
nChainLengthBiTwin =
|
||||
|
@ -338,7 +394,7 @@ bool ProbablePrimeChainTest(const CBigNum& bnPrimeChainOrigin, unsigned int nBit
|
|||
boost::thread_specific_ptr<CSieveOfEratosthenes> psieve;
|
||||
|
||||
// Mine probable prime chain of form: n = h * p# +/- 1
|
||||
bool MineProbablePrimeChain(CBlock& block, CBigNum& bnFixedMultiplier, bool& fNewBlock, unsigned int& nTriedMultiplier, unsigned int& nProbableChainLength, unsigned int& nTests, unsigned int& nPrimesHit)
|
||||
bool MineProbablePrimeChain(CBlock& block, mpz_class& mpzFixedMultiplier, bool& fNewBlock, unsigned int& nTriedMultiplier, unsigned int& nProbableChainLength, unsigned int& nTests, unsigned int& nPrimesHit, mpz_class& mpzHash)
|
||||
{
|
||||
nProbableChainLength = 0;
|
||||
nTests = 0;
|
||||
|
@ -357,14 +413,16 @@ bool MineProbablePrimeChain(CBlock& block, CBigNum& bnFixedMultiplier, bool& fNe
|
|||
{
|
||||
// Build sieve
|
||||
nStart = GetTimeMicros();
|
||||
psieve.reset(new CSieveOfEratosthenes(nMaxSieveSize, block.nBits, block.GetHeaderHash(), bnFixedMultiplier));
|
||||
CSieveOfEratosthenes *lpsieve = new CSieveOfEratosthenes(block.nBits, mpzHash, mpzFixedMultiplier, pindexPrev);
|
||||
int64 nSieveRoundLimit = (int)GetArg("-gensieveroundlimitms", 1000);
|
||||
while (psieve->Weave() && pindexPrev == pindexBest && (GetTimeMicros() - nStart < 1000 * nSieveRoundLimit));
|
||||
while (lpsieve->Weave() && pindexPrev == pindexBest && (GetTimeMicros() - nStart < 1000 * nSieveRoundLimit));
|
||||
lpsieve->CombineCandidates();
|
||||
if (fDebug && GetBoolArg("-printmining"))
|
||||
printf("MineProbablePrimeChain() : new sieve (%u/%u@%u%%) ready in %uus\n", psieve->GetCandidateCount(), nMaxSieveSize, psieve->GetProgressPercentage(), (unsigned int) (GetTimeMicros() - nStart));
|
||||
printf("MineProbablePrimeChain() : new sieve (%u/%u@%u%%) ready in %uus\n", lpsieve->GetCandidateCount(), nMaxSieveSize, lpsieve->GetProgressPercentage(), (unsigned int) (GetTimeMicros() - nStart));
|
||||
psieve.reset(lpsieve);
|
||||
}
|
||||
|
||||
CBigNum bnChainOrigin;
|
||||
mpz_class mpzChainOrigin;
|
||||
|
||||
nStart = GetTimeMicros();
|
||||
nCurrent = nStart;
|
||||
|
@ -379,13 +437,16 @@ bool MineProbablePrimeChain(CBlock& block, CBigNum& bnFixedMultiplier, bool& fNe
|
|||
fNewBlock = true; // notify caller to change nonce
|
||||
return false;
|
||||
}
|
||||
bnChainOrigin = CBigNum(block.GetHeaderHash()) * bnFixedMultiplier * nTriedMultiplier;
|
||||
mpzChainOrigin = mpzHash * mpzFixedMultiplier * nTriedMultiplier;
|
||||
unsigned int nChainLengthCunningham1 = 0;
|
||||
unsigned int nChainLengthCunningham2 = 0;
|
||||
unsigned int nChainLengthBiTwin = 0;
|
||||
if (ProbablePrimeChainTest(bnChainOrigin, block.nBits, false, nChainLengthCunningham1, nChainLengthCunningham2, nChainLengthBiTwin))
|
||||
if (ProbablePrimeChainTest(mpzChainOrigin, block.nBits, false, nChainLengthCunningham1, nChainLengthCunningham2, nChainLengthBiTwin))
|
||||
{
|
||||
block.bnPrimeChainMultiplier = bnFixedMultiplier * nTriedMultiplier;
|
||||
mpz_class mpzPrimeChainMultiplier = mpzFixedMultiplier * nTriedMultiplier;
|
||||
CBigNum bnPrimeChainMultiplier;
|
||||
bnPrimeChainMultiplier.SetHex(mpzPrimeChainMultiplier.get_str(16));
|
||||
block.bnPrimeChainMultiplier = bnPrimeChainMultiplier;
|
||||
printf("Probable prime chain found for block=%s!!\n Target: %s\n Length: (%s %s %s)\n", block.GetHash().GetHex().c_str(),
|
||||
TargetToString(block.nBits).c_str(), TargetToString(nChainLengthCunningham1).c_str(), TargetToString(nChainLengthCunningham2).c_str(), TargetToString(nChainLengthBiTwin).c_str());
|
||||
nProbableChainLength = std::max(std::max(nChainLengthCunningham1, nChainLengthCunningham2), nChainLengthBiTwin);
|
||||
|
@ -401,7 +462,7 @@ bool MineProbablePrimeChain(CBlock& block, CBigNum& bnFixedMultiplier, bool& fNe
|
|||
}
|
||||
|
||||
// Check prime proof-of-work
|
||||
bool CheckPrimeProofOfWork(uint256 hashBlockHeader, unsigned int nBits, const CBigNum& bnPrimeChainMultiplier, unsigned int& nChainType, unsigned int& nChainLength)
|
||||
bool CheckPrimeProofOfWork(uint256& hashBlockHeader, unsigned int nBits, const mpz_class& mpzPrimeChainMultiplier, unsigned int& nChainType, unsigned int& nChainLength)
|
||||
{
|
||||
// Check target
|
||||
if (TargetGetLength(nBits) < nTargetMinLength || TargetGetLength(nBits) > 99)
|
||||
|
@ -410,19 +471,21 @@ bool CheckPrimeProofOfWork(uint256 hashBlockHeader, unsigned int nBits, const CB
|
|||
// Check header hash limit
|
||||
if (hashBlockHeader < hashBlockHeaderLimit)
|
||||
return error("CheckPrimeProofOfWork() : block header hash under limit");
|
||||
mpz_class mpzHashBlockHeader;
|
||||
mpz_set_uint256(mpzHashBlockHeader.get_mpz_t(), hashBlockHeader);
|
||||
// Check target for prime proof-of-work
|
||||
CBigNum bnPrimeChainOrigin = CBigNum(hashBlockHeader) * bnPrimeChainMultiplier;
|
||||
if (bnPrimeChainOrigin < bnPrimeMin)
|
||||
mpz_class mpzPrimeChainOrigin = mpzHashBlockHeader * mpzPrimeChainMultiplier;
|
||||
if (mpzPrimeChainOrigin < mpzPrimeMin)
|
||||
return error("CheckPrimeProofOfWork() : prime too small");
|
||||
// First prime in chain must not exceed cap
|
||||
if (bnPrimeChainOrigin > bnPrimeMax)
|
||||
if (mpzPrimeChainOrigin > mpzPrimeMax)
|
||||
return error("CheckPrimeProofOfWork() : prime too big");
|
||||
|
||||
// Check prime chain
|
||||
unsigned int nChainLengthCunningham1 = 0;
|
||||
unsigned int nChainLengthCunningham2 = 0;
|
||||
unsigned int nChainLengthBiTwin = 0;
|
||||
if (!ProbablePrimeChainTest(bnPrimeChainOrigin, nBits, false, nChainLengthCunningham1, nChainLengthCunningham2, nChainLengthBiTwin))
|
||||
if (!ProbablePrimeChainTest(mpzPrimeChainOrigin, nBits, false, nChainLengthCunningham1, nChainLengthCunningham2, nChainLengthBiTwin))
|
||||
return error("CheckPrimeProofOfWork() : failed prime chain test target=%s length=(%s %s %s)", TargetToString(nBits).c_str(),
|
||||
TargetToString(nChainLengthCunningham1).c_str(), TargetToString(nChainLengthCunningham2).c_str(), TargetToString(nChainLengthBiTwin).c_str());
|
||||
if (nChainLengthCunningham1 < nBits && nChainLengthCunningham2 < nBits && nChainLengthBiTwin < nBits)
|
||||
|
@ -433,7 +496,7 @@ bool CheckPrimeProofOfWork(uint256 hashBlockHeader, unsigned int nBits, const CB
|
|||
unsigned int nChainLengthCunningham1FermatTest = 0;
|
||||
unsigned int nChainLengthCunningham2FermatTest = 0;
|
||||
unsigned int nChainLengthBiTwinFermatTest = 0;
|
||||
if (!ProbablePrimeChainTest(bnPrimeChainOrigin, nBits, true, nChainLengthCunningham1FermatTest, nChainLengthCunningham2FermatTest, nChainLengthBiTwinFermatTest))
|
||||
if (!ProbablePrimeChainTest(mpzPrimeChainOrigin, nBits, true, nChainLengthCunningham1FermatTest, nChainLengthCunningham2FermatTest, nChainLengthBiTwinFermatTest))
|
||||
return error("CheckPrimeProofOfWork() : failed Fermat test target=%s length=(%s %s %s) lengthFermat=(%s %s %s)", TargetToString(nBits).c_str(),
|
||||
TargetToString(nChainLengthCunningham1).c_str(), TargetToString(nChainLengthCunningham2).c_str(), TargetToString(nChainLengthBiTwin).c_str(),
|
||||
TargetToString(nChainLengthCunningham1FermatTest).c_str(), TargetToString(nChainLengthCunningham2FermatTest).c_str(), TargetToString(nChainLengthBiTwinFermatTest).c_str());
|
||||
|
@ -458,13 +521,13 @@ bool CheckPrimeProofOfWork(uint256 hashBlockHeader, unsigned int nBits, const CB
|
|||
nChainType = PRIME_CHAIN_BI_TWIN;
|
||||
}
|
||||
|
||||
// Check that the certificate (bnPrimeChainMultiplier) is normalized
|
||||
if (bnPrimeChainMultiplier % 2 == 0 && bnPrimeChainOrigin % 4 == 0)
|
||||
// Check that the certificate (mpzPrimeChainMultiplier) is normalized
|
||||
if (mpzPrimeChainMultiplier % 2 == 0 && mpzPrimeChainOrigin % 4 == 0)
|
||||
{
|
||||
unsigned int nChainLengthCunningham1Extended = 0;
|
||||
unsigned int nChainLengthCunningham2Extended = 0;
|
||||
unsigned int nChainLengthBiTwinExtended = 0;
|
||||
if (ProbablePrimeChainTest(bnPrimeChainOrigin / 2, nBits, false, nChainLengthCunningham1Extended, nChainLengthCunningham2Extended, nChainLengthBiTwinExtended))
|
||||
if (ProbablePrimeChainTest(mpzPrimeChainOrigin / 2, nBits, false, nChainLengthCunningham1Extended, nChainLengthCunningham2Extended, nChainLengthBiTwinExtended))
|
||||
{ // try extending down the primechain with a halved multiplier
|
||||
if (nChainLengthCunningham1Extended > nChainLength || nChainLengthCunningham2Extended > nChainLength || nChainLengthBiTwinExtended > nChainLength)
|
||||
return error("CheckPrimeProofOfWork() : prime certificate not normalzied target=%s length=(%s %s %s) extend=(%s %s %s)",
|
||||
|
@ -520,47 +583,117 @@ unsigned int CSieveOfEratosthenes::GetProgressPercentage()
|
|||
// False - sieve already completed
|
||||
bool CSieveOfEratosthenes::Weave()
|
||||
{
|
||||
if (nPrimeSeq >= vPrimes.size() || vPrimes[nPrimeSeq] >= nSieveSize)
|
||||
return false; // sieve has been completed
|
||||
CBigNum p = vPrimes[nPrimeSeq];
|
||||
if (bnFixedFactor % p == 0)
|
||||
{
|
||||
// Nothing in the sieve is divisible by this prime
|
||||
nPrimeSeq++;
|
||||
return true;
|
||||
}
|
||||
// Find the modulo inverse of fixed factor
|
||||
CAutoBN_CTX pctx;
|
||||
CBigNum bnFixedInverse;
|
||||
if (!BN_mod_inverse(&bnFixedInverse, &bnFixedFactor, &p, pctx))
|
||||
return error("CSieveOfEratosthenes::Weave(): BN_mod_inverse of fixed factor failed for prime #%u=%u", nPrimeSeq, vPrimes[nPrimeSeq]);
|
||||
CBigNum bnTwo = 2;
|
||||
CBigNum bnTwoInverse;
|
||||
if (!BN_mod_inverse(&bnTwoInverse, &bnTwo, &p, pctx))
|
||||
return error("CSieveOfEratosthenes::Weave(): BN_mod_inverse of 2 failed for prime #%u=%u", nPrimeSeq, vPrimes[nPrimeSeq]);
|
||||
// Faster GMP version
|
||||
const unsigned int nChainLength = TargetGetLength(nBits);
|
||||
unsigned int nPrimeSeq = 0;
|
||||
unsigned int vPrimesSize = vPrimes.size();
|
||||
|
||||
// Weave the sieve for the prime
|
||||
unsigned int nChainLength = TargetGetLength(nBits);
|
||||
for (unsigned int nBiTwinSeq = 0; nBiTwinSeq < 2 * nChainLength; nBiTwinSeq++)
|
||||
{
|
||||
// Find the first number that's divisible by this prime
|
||||
int nDelta = ((nBiTwinSeq % 2 == 0)? (-1) : 1);
|
||||
unsigned int nSolvedMultiplier = ((bnFixedInverse * (p - nDelta)) % p).getuint();
|
||||
if (nBiTwinSeq % 2 == 1)
|
||||
bnFixedInverse *= bnTwoInverse; // for next number in chain
|
||||
// Keep all variables local for max performance
|
||||
CBlockIndex* pindexPrev = this->pindexPrev;
|
||||
|
||||
// Process only 10% of the primes
|
||||
// Most composites are still found
|
||||
vPrimesSize = (uint64)vPrimesSize * 10 / 100;
|
||||
|
||||
mpz_t mpzFixedFactor; // fixed factor to derive the chain
|
||||
mpz_t mpzFixedFactorMod;
|
||||
mpz_t p;
|
||||
mpz_t mpzFixedInverse;
|
||||
mpz_t mpzTwo;
|
||||
mpz_t mpzTwoInverse;
|
||||
|
||||
unsigned long nFixedFactorMod;
|
||||
unsigned long nFixedInverse;
|
||||
unsigned long nTwoInverse;
|
||||
|
||||
unsigned int vCunningham1Multipliers[nChainLength];
|
||||
unsigned int vCunningham2Multipliers[nChainLength];
|
||||
unsigned int vBiTwinMultipliers[nChainLength];
|
||||
|
||||
mpz_init_set(mpzFixedFactor, this->mpzFixedFactor.get_mpz_t());
|
||||
mpz_init(mpzFixedFactorMod);
|
||||
mpz_init(p);
|
||||
mpz_init(mpzFixedInverse);
|
||||
mpz_init_set_ui(mpzTwo, 2);
|
||||
mpz_init(mpzTwoInverse);
|
||||
|
||||
loop
|
||||
{
|
||||
if (pindexPrev != pindexBest)
|
||||
break; // new block
|
||||
if (nPrimeSeq >= vPrimesSize)
|
||||
break; // sieve has been completed
|
||||
unsigned int nPrime = vPrimes[nPrimeSeq];
|
||||
if (nBiTwinSeq < nChainLength)
|
||||
for (unsigned int nVariableMultiplier = nSolvedMultiplier; nVariableMultiplier < nSieveSize; nVariableMultiplier += nPrime)
|
||||
vfCompositeBiTwin[nVariableMultiplier] = true;
|
||||
if (((nBiTwinSeq & 1u) == 0))
|
||||
for (unsigned int nVariableMultiplier = nSolvedMultiplier; nVariableMultiplier < nSieveSize; nVariableMultiplier += nPrime)
|
||||
if (nPrime >= nMaxSieveSize)
|
||||
break; // sieve has been completed
|
||||
nFixedFactorMod = mpz_tdiv_r_ui(mpzFixedFactorMod, mpzFixedFactor, nPrime);
|
||||
if (nFixedFactorMod == 0)
|
||||
{
|
||||
// Nothing in the sieve is divisible by this prime
|
||||
nPrimeSeq++;
|
||||
continue;
|
||||
}
|
||||
mpz_set_ui(p, nPrime);
|
||||
// Find the modulo inverse of fixed factor
|
||||
if (!mpz_invert(mpzFixedInverse, mpzFixedFactorMod, p))
|
||||
return error("CSieveOfEratosthenes::Weave(): mpz_invert of fixed factor failed for prime #%u=%u", nPrimeSeq, vPrimes[nPrimeSeq]);
|
||||
nFixedInverse = mpz_get_ui(mpzFixedInverse);
|
||||
if (!mpz_invert(mpzTwoInverse, mpzTwo, p))
|
||||
return error("CSieveOfEratosthenes::Weave(): mpz_invert of 2 failed for prime #%u=%u", nPrimeSeq, vPrimes[nPrimeSeq]);
|
||||
nTwoInverse = mpz_get_ui(mpzTwoInverse);
|
||||
|
||||
// Weave the sieve for the prime
|
||||
for (unsigned int nBiTwinSeq = 0; nBiTwinSeq < 2 * nChainLength; nBiTwinSeq++)
|
||||
{
|
||||
// Find the first number that's divisible by this prime
|
||||
int nDelta = ((nBiTwinSeq % 2 == 0)? (-1) : 1);
|
||||
unsigned int nSolvedMultiplier = (uint64)nFixedInverse * (nPrime - nDelta) % nPrime;
|
||||
if (nBiTwinSeq % 2 == 1)
|
||||
nFixedInverse = (uint64)nFixedInverse * nTwoInverse % nPrime;
|
||||
|
||||
if (nBiTwinSeq < nChainLength)
|
||||
vBiTwinMultipliers[nBiTwinSeq] = nSolvedMultiplier;
|
||||
if (((nBiTwinSeq & 1u) == 0))
|
||||
vCunningham1Multipliers[nBiTwinSeq / 2] = nSolvedMultiplier;
|
||||
else
|
||||
vCunningham2Multipliers[nBiTwinSeq / 2] = nSolvedMultiplier;
|
||||
}
|
||||
|
||||
// Loop over each array one at a time for optimal L1 cache performance
|
||||
for (unsigned int i = 0; i < nChainLength; i++)
|
||||
{
|
||||
unsigned int nSolvedMultiplier = vCunningham1Multipliers[i];
|
||||
for (unsigned int nVariableMultiplier = nSolvedMultiplier; nVariableMultiplier < nMaxSieveSize; nVariableMultiplier += nPrime)
|
||||
vfCompositeCunningham1[nVariableMultiplier] = true;
|
||||
if (((nBiTwinSeq & 1u) == 1u))
|
||||
for (unsigned int nVariableMultiplier = nSolvedMultiplier; nVariableMultiplier < nSieveSize; nVariableMultiplier += nPrime)
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < nChainLength; i++)
|
||||
{
|
||||
unsigned int nSolvedMultiplier = vCunningham2Multipliers[i];
|
||||
for (unsigned int nVariableMultiplier = nSolvedMultiplier; nVariableMultiplier < nMaxSieveSize; nVariableMultiplier += nPrime)
|
||||
vfCompositeCunningham2[nVariableMultiplier] = true;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < nChainLength; i++)
|
||||
{
|
||||
unsigned int nSolvedMultiplier = vBiTwinMultipliers[i];
|
||||
for (unsigned int nVariableMultiplier = nSolvedMultiplier; nVariableMultiplier < nMaxSieveSize; nVariableMultiplier += nPrime)
|
||||
vfCompositeBiTwin[nVariableMultiplier] = true;
|
||||
}
|
||||
|
||||
nPrimeSeq++;
|
||||
continue;
|
||||
}
|
||||
nPrimeSeq++;
|
||||
return true;
|
||||
|
||||
this->nPrimeSeq = nPrimeSeq;
|
||||
|
||||
mpz_clear(mpzFixedFactor);
|
||||
mpz_clear(mpzFixedFactorMod);
|
||||
mpz_clear(p);
|
||||
mpz_clear(mpzFixedInverse);
|
||||
mpz_clear(mpzTwo);
|
||||
mpz_clear(mpzTwoInverse);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
66
src/prime.h
66
src/prime.h
|
@ -7,11 +7,19 @@
|
|||
|
||||
#include "main.h"
|
||||
|
||||
static const unsigned int nMaxSieveSize = 1000000u;
|
||||
#include <gmp.h>
|
||||
#include <gmpxx.h>
|
||||
#include <bitset>
|
||||
|
||||
static const unsigned int nMaxSieveSize = 100000u;
|
||||
static const uint256 hashBlockHeaderLimit = (uint256(1) << 255);
|
||||
static const CBigNum bnOne = 1;
|
||||
static const CBigNum bnPrimeMax = (bnOne << 2000) - 1;
|
||||
static const CBigNum bnPrimeMin = (bnOne << 255);
|
||||
static const mpz_class mpzOne = 1;
|
||||
static const mpz_class mpzTwo = 2;
|
||||
static const mpz_class mpzPrimeMax = (mpzOne << 2000) - 1;
|
||||
static const mpz_class mpzPrimeMin = (mpzOne << 255);
|
||||
|
||||
extern unsigned int nTargetInitialLength;
|
||||
extern unsigned int nTargetMinLength;
|
||||
|
@ -24,9 +32,9 @@ bool PrimeTableGetNextPrime(unsigned int& p);
|
|||
bool PrimeTableGetPreviousPrime(unsigned int& p);
|
||||
|
||||
// Compute primorial number p#
|
||||
void Primorial(unsigned int p, CBigNum& bnPrimorial);
|
||||
void Primorial(unsigned int p, mpz_class& mpzPrimorial);
|
||||
// Compute the first primorial number greater than or equal to bn
|
||||
void PrimorialAt(CBigNum& bn, CBigNum& bnPrimorial);
|
||||
void PrimorialAt(mpz_class& bn, mpz_class& mpzPrimorial);
|
||||
|
||||
// Test probable prime chain for: bnPrimeChainOrigin
|
||||
// fFermatTest
|
||||
|
@ -35,7 +43,7 @@ void PrimorialAt(CBigNum& bn, CBigNum& bnPrimorial);
|
|||
// Return value:
|
||||
// true - Probable prime chain found (one of nChainLength meeting target)
|
||||
// false - prime chain too short (none of nChainLength meeting target)
|
||||
bool ProbablePrimeChainTest(const CBigNum& bnPrimeChainOrigin, unsigned int nBits, bool fFermatTest, unsigned int& nChainLengthCunningham1, unsigned int& nChainLengthCunningham2, unsigned int& nChainLengthBiTwin);
|
||||
bool ProbablePrimeChainTest(const mpz_class& mpzPrimeChainOrigin, unsigned int nBits, bool fFermatTest, unsigned int& nChainLengthCunningham1, unsigned int& nChainLengthCunningham2, unsigned int& nChainLengthBiTwin);
|
||||
|
||||
static const unsigned int nFractionalBits = 24;
|
||||
static const unsigned int TARGET_FRACTIONAL_MASK = (1u<<nFractionalBits) - 1;
|
||||
|
@ -57,7 +65,7 @@ bool TargetGetMint(unsigned int nBits, uint64& nMint);
|
|||
bool TargetGetNext(unsigned int nBits, int64 nInterval, int64 nTargetSpacing, int64 nActualSpacing, unsigned int& nBitsNext);
|
||||
|
||||
// Mine probable prime chain of form: n = h * p# +/- 1
|
||||
bool MineProbablePrimeChain(CBlock& block, CBigNum& bnFixedMultiplier, bool& fNewBlock, unsigned int& nTriedMultiplier, unsigned int& nProbableChainLength, unsigned int& nTests, unsigned int& nPrimesHit);
|
||||
bool MineProbablePrimeChain(CBlock& block, mpz_class& mpzFixedMultiplier, bool& fNewBlock, unsigned int& nTriedMultiplier, unsigned int& nProbableChainLength, unsigned int& nTests, unsigned int& nPrimesHit, mpz_class& mpzHash);
|
||||
|
||||
// Check prime proof-of-work
|
||||
enum // prime chain type
|
||||
|
@ -66,7 +74,7 @@ enum // prime chain type
|
|||
PRIME_CHAIN_CUNNINGHAM2 = 2u,
|
||||
PRIME_CHAIN_BI_TWIN = 3u,
|
||||
};
|
||||
bool CheckPrimeProofOfWork(uint256 hashBlockHeader, unsigned int nBits, const CBigNum& bnPrimeChainMultiplier, unsigned int& nChainType, unsigned int& nChainLength);
|
||||
bool CheckPrimeProofOfWork(uint256& hashBlockHeader, unsigned int nBits, const mpz_class& mpzPrimeChainMultiplier, unsigned int& nChainType, unsigned int& nChainLength);
|
||||
|
||||
// prime target difficulty value for visualization
|
||||
double GetPrimeDifficulty(unsigned int nBits);
|
||||
|
@ -78,42 +86,43 @@ std::string GetPrimeChainName(unsigned int nChainType, unsigned int nChainLength
|
|||
// Sieve of Eratosthenes for proof-of-work mining
|
||||
class CSieveOfEratosthenes
|
||||
{
|
||||
unsigned int nSieveSize; // size of the sieve
|
||||
static const unsigned int nSieveSize = nMaxSieveSize; // size of the sieve
|
||||
unsigned int nBits; // target of the prime chain to search for
|
||||
uint256 hashBlockHeader; // block header hash
|
||||
CBigNum bnFixedFactor; // fixed factor to derive the chain
|
||||
mpz_class mpzFixedFactor; // fixed factor to derive the chain
|
||||
|
||||
// bitmaps of the sieve, index represents the variable part of multiplier
|
||||
std::vector<bool> vfCompositeCunningham1;
|
||||
std::vector<bool> vfCompositeCunningham2;
|
||||
std::vector<bool> vfCompositeBiTwin;
|
||||
std::bitset<nMaxSieveSize> vfCompositeCunningham1;
|
||||
std::bitset<nMaxSieveSize> vfCompositeCunningham2;
|
||||
std::bitset<nMaxSieveSize> vfCompositeBiTwin;
|
||||
std::bitset<nMaxSieveSize> vfCandidates;
|
||||
|
||||
unsigned int nPrimeSeq; // prime sequence number currently being processed
|
||||
unsigned int nCandidateMultiplier; // current candidate for power test
|
||||
|
||||
CBlockIndex* pindexPrev;
|
||||
|
||||
public:
|
||||
CSieveOfEratosthenes(unsigned int nSieveSize, unsigned int nBits, uint256 hashBlockHeader, CBigNum& bnFixedMultiplier)
|
||||
CSieveOfEratosthenes(unsigned int nBits, mpz_class& mpzHash, mpz_class& mpzFixedMultiplier, CBlockIndex* pindexPrev)
|
||||
{
|
||||
this->nSieveSize = nSieveSize;
|
||||
this->nBits = nBits;
|
||||
this->hashBlockHeader = hashBlockHeader;
|
||||
this->bnFixedFactor = bnFixedMultiplier * CBigNum(hashBlockHeader);
|
||||
this->mpzFixedFactor = mpzFixedMultiplier * mpzHash;
|
||||
this->pindexPrev = pindexPrev;
|
||||
nPrimeSeq = 0;
|
||||
vfCompositeCunningham1 = std::vector<bool> (1000000, false);
|
||||
vfCompositeCunningham2 = std::vector<bool> (1000000, false);
|
||||
vfCompositeBiTwin = std::vector<bool> (1000000, false);
|
||||
nCandidateMultiplier = 0;
|
||||
}
|
||||
|
||||
void CombineCandidates()
|
||||
{
|
||||
vfCandidates = ~(vfCompositeCunningham1 & vfCompositeCunningham2 & vfCompositeBiTwin);
|
||||
}
|
||||
|
||||
// Get total number of candidates for power test
|
||||
unsigned int GetCandidateCount()
|
||||
{
|
||||
unsigned int nCandidates = 0;
|
||||
for (unsigned int nMultiplier = 0; nMultiplier < nSieveSize; nMultiplier++)
|
||||
for (unsigned int nMultiplier = 0; nMultiplier < nMaxSieveSize; nMultiplier++)
|
||||
{
|
||||
if (!vfCompositeCunningham1[nMultiplier] ||
|
||||
!vfCompositeCunningham2[nMultiplier] ||
|
||||
!vfCompositeBiTwin[nMultiplier])
|
||||
if (vfCandidates[nMultiplier])
|
||||
nCandidates++;
|
||||
}
|
||||
return nCandidates;
|
||||
|
@ -128,14 +137,12 @@ public:
|
|||
loop
|
||||
{
|
||||
nCandidateMultiplier++;
|
||||
if (nCandidateMultiplier >= nSieveSize)
|
||||
if (nCandidateMultiplier >= nMaxSieveSize)
|
||||
{
|
||||
nCandidateMultiplier = 0;
|
||||
return false;
|
||||
}
|
||||
if (!vfCompositeCunningham1[nCandidateMultiplier] ||
|
||||
!vfCompositeCunningham2[nCandidateMultiplier] ||
|
||||
!vfCompositeBiTwin[nCandidateMultiplier])
|
||||
if (vfCandidates[nCandidateMultiplier])
|
||||
{
|
||||
nVariableMultiplier = nCandidateMultiplier;
|
||||
return true;
|
||||
|
@ -153,4 +160,9 @@ public:
|
|||
bool Weave();
|
||||
};
|
||||
|
||||
inline void mpz_set_uint256(mpz_t r, uint256& u)
|
||||
{
|
||||
mpz_import(r, 32 / sizeof(unsigned long), -1, sizeof(unsigned long), -1, 0, &u);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,7 +15,11 @@
|
|||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#else
|
||||
#ifndef _WIN64
|
||||
typedef int pid_t; /* define for Windows compatibility */
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
|
Loading…
Reference in New Issue