Get rid of main.cpp

master
q3k 2014-01-26 13:35:09 +01:00
parent 38db96811b
commit 6300009a6e
3 changed files with 336 additions and 40 deletions

327
src/bitcoinminer.cpp Normal file
View File

@ -0,0 +1,327 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2011-2013 PPCoin developers
// Copyright (c) 2013 Primecoin developers
// Distributed under conditional MIT/X11 software license,
// see the accompanying file COPYING
#include "prime.h"
#include "json/json_spirit_value.h"
//#include <boost/algorithm/string/replace.hpp>
//#include <boost/filesystem.hpp>
//#include <boost/filesystem/fstream.hpp>
using namespace std;
using namespace boost;
CBlockIndex* pindexBest = NULL;
int64 nHPSTimerStart = 0;
void BitcoinMiner(CBlockProvider *block_provider, unsigned int thread_id)
{
printf("PrimecoinMiner started\n");
SetThreadPriority(THREAD_PRIORITY_LOWEST);
RenameThread("primecoin-miner");
// Each thread has its own kcd ey and counter
unsigned int nExtraNonce = 0; //^
unsigned int nPrimorialMultiplier = nPrimorialHashFactor;
double dTimeExpected = 0; // time expected to prime chain (micro-second)
int64 nSieveGenTime = 0; // how many milliseconds sieve generation took
bool fIncrementPrimorial = true; // increase or decrease primorial factor
CBlock *pblock = NULL;
uint256 old_hash;
unsigned int old_nonce = 0;
try { loop {
//
// Create new block
//
CBlockIndex* pindexPrev = pindexBest;
auto_ptr<CBlockTemplate> pblocktemplate;
if ((pblock = block_provider->getBlock(thread_id, pblock == NULL ? 0 : pblock->nTime)) == NULL) { //server not reachable?
MilliSleep(20000);
continue;
} else if (old_hash == pblock->GetHeaderHash()) {
if (old_nonce >= 0xffff0000) {
MilliSleep(100);
//TODO: FORCE a new getblock!
if (fDebug && GetBoolArg("-printmining"))
printf("Nothing to do --- uh ih uh ah ah bing bang!!\n");
continue;
} else
pblock->nNonce = old_nonce;
} else {
old_hash = pblock->GetHeaderHash();
old_nonce = 0;
}
if (fDebug && GetBoolArg("-printmining"))
printf("Running PrimecoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
//
// Search
//
int64 nStart = GetTime();
bool fNewBlock = true;
unsigned int nTriedMultiplier = 0;
// Primecoin: try to find hash divisible by primorial
unsigned int nHashFactor = PrimorialFast(nPrimorialHashFactor);
// Based on mustyoshi's patch from https://bitcointalk.org/index.php?topic=251850.msg2689981#msg2689981
uint256 phash;
mpz_class mpzHash;
loop {
// Fast loop
if (pblock->nNonce >= 0xffff0000)
break;
// Check that the hash meets the minimum
phash = pblock->GetHeaderHash();
if (phash < hashBlockHeaderLimit) {
pblock->nNonce++;
continue;
}
// Check that the hash is divisible by the fixed primorial
mpz_set_uint256(mpzHash.get_mpz_t(), phash);
if (!mpz_divisible_ui_p(mpzHash.get_mpz_t(), nHashFactor)) {
pblock->nNonce++;
continue;
}
// Use the hash that passed the tests
break;
}
if (pblock->nNonce >= 0xffff0000) {
old_nonce = 0xffff0000;
continue;
}
// Primecoin: primorial fixed multiplier
mpz_class mpzPrimorial;
unsigned int nRoundTests = 0;
unsigned int nRoundPrimesHit = 0;
int64 nPrimeTimerStart = GetTimeMicros();
Primorial(nPrimorialMultiplier, mpzPrimorial);
loop
{
unsigned int nTests = 0;
unsigned int nPrimesHit = 0;
unsigned int nChainsHit = 0;
// Primecoin: adjust round primorial so that the generated prime candidates meet the minimum
mpz_class mpzMultiplierMin = mpzPrimeMin * nHashFactor / mpzHash + 1;
while (mpzPrimorial < mpzMultiplierMin)
{
if (!PrimeTableGetNextPrime(nPrimorialMultiplier))
error("PrimecoinMiner() : primorial minimum overflow");
Primorial(nPrimorialMultiplier, mpzPrimorial);
}
mpz_class mpzFixedMultiplier;
if (mpzPrimorial > nHashFactor) {
mpzFixedMultiplier = mpzPrimorial / nHashFactor;
} else {
mpzFixedMultiplier = 1;
}
// Primecoin: mine for prime chain
unsigned int nProbableChainLength;
if (MineProbablePrimeChain(*pblock, mpzFixedMultiplier, fNewBlock, nTriedMultiplier, nProbableChainLength, nTests, nPrimesHit, nChainsHit, mpzHash, nPrimorialMultiplier, nSieveGenTime, pindexPrev, block_provider != NULL))
{
SetThreadPriority(THREAD_PRIORITY_NORMAL);
block_provider->submitBlock(pblock);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
old_nonce = pblock->nNonce + 1;
break;
}
///
/// ENABLE the following code, if you need data for the perftool
///
/*if (nProbableChainLength > 0 && nTests > 10)
{
static CCriticalSection cs;
{
LOCK(cs);
std::ofstream output_file("miner_data");
std::ofstream output_file_block("miner_data.blk", std::ofstream::out | std::ofstream::binary);
::Serialize(output_file_block, *pblock, 0, 0); //writeblock
output_file << mpzFixedMultiplier.get_str(10) << std::endl;
output_file << fNewBlock << std::endl;
output_file << nTriedMultiplier << std::endl;
output_file << nPrimorialMultiplier << std::endl;
output_file << mpzHash.get_str(10) << std::endl;
output_file.close();
output_file_block.close();
}
}*/
nRoundTests += nTests;
nRoundPrimesHit += nPrimesHit;
// Meter primes/sec
static volatile int64 nPrimeCounter;
static volatile int64 nTestCounter;
static volatile int64 nChainCounter;
static double dChainExpected;
int64 nMillisNow = GetTimeMillis();
if (nHPSTimerStart == 0)
{
nHPSTimerStart = nMillisNow;
nPrimeCounter = 0;
nTestCounter = 0;
nChainCounter = 0;
dChainExpected = 0;
}
else
{
#ifdef __GNUC__
// Use atomic increment
__sync_add_and_fetch(&nPrimeCounter, nPrimesHit);
__sync_add_and_fetch(&nTestCounter, nTests);
__sync_add_and_fetch(&nChainCounter, nChainsHit);
#else
nPrimeCounter += nPrimesHit;
nTestCounter += nTests;
nChainCounter += nChainsHit;
#endif
}
if (nMillisNow - nHPSTimerStart > 60000)
{
static CCriticalSection cs;
{
LOCK(cs);
if (nMillisNow - nHPSTimerStart > 60000)
{
double dPrimesPerMinute = 60000.0 * nPrimeCounter / (nMillisNow - nHPSTimerStart);
double dPrimesPerSec = dPrimesPerMinute / 60.0;
double dTestsPerSec = 1000.0 * nTestCounter / (nMillisNow - nHPSTimerStart);
double dChainsPerMinute = 60000.0 * nChainCounter / (nMillisNow - nHPSTimerStart);
double dChainsPerDay = 86400000.0 * dChainExpected / (GetTimeMillis() - nHPSTimerStart);
nHPSTimerStart = nMillisNow;
nPrimeCounter = 0;
nTestCounter = 0;
nChainCounter = 0;
dChainExpected = 0;
static int64 nLogTime = 0;
if (nMillisNow - nLogTime > 59000)
{
nLogTime = nMillisNow;
printf("[STATS] %s | %4.0f primes/s, %4.0f tests/s, %4.0f %d-chains/h, %3.3f chains/d\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nLogTime / 1000).c_str(), dPrimesPerSec, dTestsPerSec, dChainsPerMinute * 60.0, nStatsChainLength, dChainsPerDay);
}
}
}
}
old_nonce = pblock->nNonce;
// Check for stop or if block needs to be rebuilt
boost::this_thread::interruption_point();
if (pblock->nNonce >= 0xffff0000)
break;
if (pindexPrev != pindexBest/* || (block_provider != NULL && GetTime() - nStart > 200)*/)
break;
if (thread_id == 0 && block_provider != NULL && (GetTime() - nStart) > 300) { //5 minutes no update? something's wrong -> reconnect!
block_provider->forceReconnect();
nStart = GetTime();
}
if (fNewBlock) //aka: sieve's done, we need a updated nonce
{
// Primecoin: a sieve+primality round completes
// Primecoin: estimate time to block
const double dTimeExpectedPrev = dTimeExpected;
unsigned int nCalcRoundTests = max(1u, nRoundTests);
// Make sure the estimated time is very high if only 0 primes were found
if (nRoundPrimesHit == 0)
nCalcRoundTests *= 1000;
int64 nRoundTime = (GetTimeMicros() - nPrimeTimerStart);
dTimeExpected = (double) nRoundTime / nCalcRoundTests;
double dRoundChainExpected = (double) nRoundTests;
for (unsigned int n = 0, nTargetLength = TargetGetLength(pblock->nBits); n < nTargetLength; n++)
{
double dPrimeProbability = EstimateCandidatePrimeProbability(nPrimorialMultiplier, n);
dTimeExpected = dTimeExpected / max(0.01, dPrimeProbability);
dRoundChainExpected *= dPrimeProbability;
}
dChainExpected += dRoundChainExpected;
if (fDebug && GetBoolArg("-printmining"))
{
double dPrimeProbabilityBegin = EstimateCandidatePrimeProbability(nPrimorialMultiplier, 0);
unsigned int nTargetLength = TargetGetLength(pblock->nBits);
double dPrimeProbabilityEnd = EstimateCandidatePrimeProbability(nPrimorialMultiplier, nTargetLength - 1);
printf("PrimecoinMiner() : Round primorial=%u tests=%u primes=%u time=%uus pprob=%1.6f pprob2=%1.6f tochain=%6.3fd expect=%3.9f\n", nPrimorialMultiplier, nRoundTests, nRoundPrimesHit, (unsigned int) nRoundTime, dPrimeProbabilityBegin, dPrimeProbabilityEnd, ((dTimeExpected/1000000.0))/86400.0, dRoundChainExpected);
}
// Primecoin: update time and nonce
//pblock->nTime = max(pblock->nTime, (unsigned int) GetAdjustedTime());
pblock->nTime = max(pblock->nTime, block_provider->GetAdjustedTimeWithOffset(thread_id));
pblock->nNonce++;
loop {
// Fast loop
if (pblock->nNonce >= 0xffff0000)
break;
// Check that the hash meets the minimum
phash = pblock->GetHeaderHash();
if (phash < hashBlockHeaderLimit) {
pblock->nNonce++;
continue;
}
// Check that the hash is divisible by the fixed primorial
mpz_set_uint256(mpzHash.get_mpz_t(), phash);
if (!mpz_divisible_ui_p(mpzHash.get_mpz_t(), nHashFactor)) {
pblock->nNonce++;
continue;
}
// Use the hash that passed the tests
break;
}
if (pblock->nNonce >= 0xffff0000)
break;
// Primecoin: reset sieve+primality round timer
nPrimeTimerStart = GetTimeMicros();
if (dTimeExpected > dTimeExpectedPrev)
fIncrementPrimorial = !fIncrementPrimorial;
// Primecoin: primorial always needs to be incremented if only 0 primes were found
if (nRoundPrimesHit == 0)
fIncrementPrimorial = true;
nRoundTests = 0;
nRoundPrimesHit = 0;
// Primecoin: dynamic adjustment of primorial multiplier
if (fIncrementPrimorial)
{
if (!PrimeTableGetNextPrime(nPrimorialMultiplier))
error("PrimecoinMiner() : primorial increment overflow");
}
else if (nPrimorialMultiplier > nPrimorialHashFactor)
{
if (!PrimeTableGetPreviousPrime(nPrimorialMultiplier))
error("PrimecoinMiner() : primorial decrement overflow");
}
Primorial(nPrimorialMultiplier, mpzPrimorial);
}
}
} }
catch (boost::thread_interrupted)
{
printf("PrimecoinMiner terminated\n");
throw;
}
}

View File

@ -26,10 +26,7 @@
// <START> be compatible to original code (not actually used!)
#include "txdb.h"
#include "walletdb.h"
#include "wallet.h"
#include "ui_interface.h"
CWallet *pwalletMain;
CClientUIInterface uiInterface;
void StartShutdown() {
exit(0);
@ -41,8 +38,7 @@ void StartShutdown() {
*********************************/
extern CBlockIndex *pindexBest;
extern void BitcoinMiner(CWallet *pwallet,
CBlockProvider *CBlockProvider,
extern void BitcoinMiner(CBlockProvider *CBlockProvider,
unsigned int thread_id);
extern bool fPrintToConsole;
extern bool fDebug;
@ -216,7 +212,7 @@ public:
_master->wait_for_master();
std::cout << "[WORKER" << _id << "] GoGoGo!" << std::endl;
boost::this_thread::sleep(boost::posix_time::seconds(2));
BitcoinMiner(NULL, _bprovider, _id);
BitcoinMiner(_bprovider, _id);
std::cout << "[WORKER" << _id << "] Bye Bye!" << std::endl;
}

View File

@ -121,45 +121,18 @@ DEBUGFLAGS=
# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only
# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work.
xCXXFLAGS=-O2 -pthread -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \
$(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS)
$(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS) -march=native
# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only
# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work.
xLDFLAGS=$(LDHARDENING) $(LDFLAGS)
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/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/hash.o \
obj/bloom.o \
obj/noui.o \
obj/leveldb.o \
obj/txdb.o \
obj/prime.o \
obj/checkpointsync.o
obj/bitcoinminer.o
all: primeminer
@ -170,11 +143,11 @@ test check: test_primecoin FORCE
# LevelDB support
#
MAKEOVERRIDES =
LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
DEFS += $(addprefix -I,$(CURDIR)/leveldb/include)
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
leveldb/libleveldb.a:
@echo "Building LevelDB ..." && cd leveldb && $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(xCXXFLAGS)" libleveldb.a libmemenv.a && cd ..
#LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a
#DEFS += $(addprefix -I,$(CURDIR)/leveldb/include)
#DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
#leveldb/libleveldb.a:
# @echo "Building LevelDB ..." && cd leveldb && $(MAKE) CC=$(CC) CXX=$(CXX) OPT="$(xCXXFLAGS)" libleveldb.a libmemenv.a && cd ..
# auto-generated dependencies:
-include obj/*.P