Initial high performance version commit.

master
mikaelh 2013-07-14 00:42:11 +03:00
parent 7b39bc31be
commit 43ede0ac1b
17 changed files with 936 additions and 146 deletions

View File

@ -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
================================

425
bitcoin-qt-win64.pro Normal file
View File

@ -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)

View File

@ -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

View File

@ -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
====================

View File

@ -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
====================

View File

@ -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()

View File

@ -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

View File

@ -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);

View File

@ -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

136
src/makefile.linux-mingw64 Normal file
View File

@ -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:

View File

@ -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

View File

@ -53,6 +53,7 @@ LIBS += \
-lboost_chrono-mt \
-lssl \
-lcrypto \
-lgmp \
-lz
TESTDEFS += -DBOOST_TEST_DYN_LINK
endif

View File

@ -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) \

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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>