static bool CheckNBits(unsigned int nbits1, int64 time1, unsigned int nbits2, int64 time2)\ { if (time1 > time2) return CheckNBits(nbits2, time2, nbits1, time1); int64 deltaTime = time2-time1; CBigNum required; required.SetCompact(ComputeMinWork(nbits1, deltaTime)); CBigNum have; have.SetCompact(nbits2); return (have <= required); }
void SimulateNextBlock(CBlockIndex*& tip, double* hashRates) { double recTime = 1e9; CBlockIndex* newTip = new CBlockIndex; newTip->pprev = tip; newTip->nHeight = tip->nHeight+1; for (int i=0; i<NUM_ALGOS; i++) { if (hashRates[i] == 0) continue; CBigNum target; unsigned int nBits = GetNextWorkRequired(tip, NULL, i); target.SetCompact(nBits); double dtarget = target.getuint256().getdouble()/pow(2,256); double mean = 1/(hashRates[i]*dtarget); boost::exponential_distribution<double> distr(1/mean); double received = distr(prng); if (received < recTime) { recTime = received; newTip->nVersion = VersionForAlgo(i); newTip->nTime = tip->nTime + received; newTip->nBits=nBits; } } assert(recTime < 1e9); tip = newTip; return; }
double BitsToDifficulty(int nBits) { CBigNum target; target.SetCompact(nBits); // approximate return pow(2, 256-32)/target.getuint256().getdouble(); }
unsigned int static GravityWell(const CBlockIndex* pindexLast, const CBlockHeader *pblock, uint64_t TargetBlocksSpacingSeconds, uint64_t PastBlocksMin, uint64_t PastBlocksMax) { const CBlockIndex *BlockLastSolved = pindexLast; const CBlockIndex *BlockReading = pindexLast; uint64_t PastBlocksMass = 0; int64_t PastRateActualSeconds = 0; int64_t PastRateTargetSeconds = 0; double PastRateAdjustmentRatio = double(1); CBigNum PastDifficultyAverage; CBigNum PastDifficultyAveragePrev; double EventHorizonDeviation; double EventHorizonDeviationFast; double EventHorizonDeviationSlow; CBigNum bnLimit = CBigNum(~uint256(0) >> 20); if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || (uint64_t)BlockLastSolved->nHeight < PastBlocksMin) { return bnLimit.GetCompact(); } for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) { if (PastBlocksMax > 0 && i > PastBlocksMax) { break; } PastBlocksMass++; if (i == 1) { PastDifficultyAverage.SetCompact(BlockReading->nBits); } else { PastDifficultyAverage = ((CBigNum().SetCompact(BlockReading->nBits) - PastDifficultyAveragePrev) / i) + PastDifficultyAveragePrev; } PastDifficultyAveragePrev = PastDifficultyAverage; PastRateActualSeconds = BlockLastSolved->GetBlockTime() - BlockReading->GetBlockTime(); PastRateTargetSeconds = TargetBlocksSpacingSeconds * PastBlocksMass; PastRateAdjustmentRatio = double(1); if (PastRateActualSeconds < 0) { PastRateActualSeconds = 0; } if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) { PastRateAdjustmentRatio = double(PastRateTargetSeconds) / double(PastRateActualSeconds); } EventHorizonDeviation = 1 + (0.7084 * pow((double(PastBlocksMass)/double(144)), -1.228)); EventHorizonDeviationFast = EventHorizonDeviation; EventHorizonDeviationSlow = 1 / EventHorizonDeviation; if (PastBlocksMass >= PastBlocksMin) { if ((PastRateAdjustmentRatio <= EventHorizonDeviationSlow) || (PastRateAdjustmentRatio >= EventHorizonDeviationFast)) { assert(BlockReading); break; } } if (BlockReading->pprev == NULL) { assert(BlockReading); break; } BlockReading = BlockReading->pprev; } CBigNum bnNew(PastDifficultyAverage); if (PastRateActualSeconds != 0 && PastRateTargetSeconds != 0) { bnNew *= PastRateActualSeconds; bnNew /= PastRateTargetSeconds; } if (bnNew > bnLimit) { bnNew = bnLimit; } /// debug print LogPrintf("Difficulty Retarget - Gravity Well\n"); LogPrintf("PastRateAdjustmentRatio = %g\n", PastRateAdjustmentRatio); LogPrintf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString()); LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString()); return bnNew.GetCompact(); }
CBigNum CBlockIndex::GetBlockWork() const { CBigNum bnTarget; bnTarget.SetCompact(nBits); if (bnTarget <= 0) return 0; return (CBigNum(1)<<256) / (bnTarget+1); }
int LitecoinChain::nextWorkRequired(BlockIterator blk) const { const int64_t nTargetTimespan = 3.5 * 24 * 60 * 60; // two weeks const int64_t nTargetSpacing = 2.5 * 60; const int64_t nInterval = nTargetTimespan / nTargetSpacing; // Genesis block int h = blk.height(); if (h == 0) // trick to test that it is asking for the genesis block return _genesisBlock.getBits(); // proofOfWorkLimit().GetCompact(); Actually not for the genesisblock - here it is 0x1e0ffff0, not 0x1e0fffff // Only change once per interval if ((h + 1) % nInterval != 0) return blk->bits; // Litecoin: This fixes an issue where a 51% attack can change difficulty at will. // Go back the full period unless it's the first retarget after genesis. Code courtesy of Art Forz int blockstogoback = nInterval-1; if ((h + 1) != nInterval) blockstogoback = nInterval; // Go back by what we want to be 3.5 days worth of blocks BlockIterator former = blk - blockstogoback; // Limit adjustment step int nActualTimespan = blk->time - former->time; log_debug(" nActualTimespan = %"PRI64d" before bounds", nActualTimespan); if (nActualTimespan < nTargetTimespan/4) nActualTimespan = nTargetTimespan/4; if (nActualTimespan > nTargetTimespan*4) nActualTimespan = nTargetTimespan*4; // Retarget CBigNum bnNew; bnNew.SetCompact(blk->bits); bnNew *= nActualTimespan; bnNew /= nTargetTimespan; if (bnNew > proofOfWorkLimit()) bnNew = proofOfWorkLimit(); /// debug print log_info("GetNextWorkRequired RETARGET"); log_info("\tnTargetTimespan = %"PRI64d" nActualTimespan = %"PRI64d"", nTargetTimespan, nActualTimespan); log_info("\tBefore: %08x %s", blk->bits, CBigNum().SetCompact(blk->bits).getuint256().toString().c_str()); log_info("\tAfter: %08x %s", bnNew.GetCompact(), bnNew.getuint256().toString().c_str()); return bnNew.GetCompact(); }
int TestNet3Chain::nextWorkRequired(BlockIterator blk) const { const int64_t nTargetTimespan = 14 * 24 * 60 * 60; // two weeks const int64_t nTargetSpacing = 10 * 60; const int64_t nInterval = nTargetTimespan / nTargetSpacing; // Genesis block int h = blk.height(); if (h == 0) // trick to test that it is asking for the genesis block return proofOfWorkLimit().GetCompact(); // Only change once per interval if ((h + 1) % nInterval != 0) { // Return the last non-special-min-difficulty-rules-block while (blk.height() % nInterval != 0 && blk->bits == proofOfWorkLimit().GetCompact()) blk--; return blk->bits; } // Go back by what we want to be 14 days worth of blocks BlockIterator former = blk - (nInterval-1); // Limit adjustment step int nActualTimespan = blk->time - former->time; log_debug(" nActualTimespan = %"PRI64d" before bounds", nActualTimespan); if (nActualTimespan < nTargetTimespan/4) nActualTimespan = nTargetTimespan/4; if (nActualTimespan > nTargetTimespan*4) nActualTimespan = nTargetTimespan*4; // Retarget CBigNum bnNew; bnNew.SetCompact(blk->bits); bnNew *= nActualTimespan; bnNew /= nTargetTimespan; if (bnNew > proofOfWorkLimit()) bnNew = proofOfWorkLimit(); /// debug print log_info("GetNextWorkRequired RETARGET"); log_info("\tnTargetTimespan = %"PRI64d" nActualTimespan = %"PRI64d"", nTargetTimespan, nActualTimespan); log_info("\tBefore: %08x %s", blk->bits, CBigNum().SetCompact(blk->bits).getuint256().toString().c_str()); log_info("\tAfter: %08x %s", bnNew.GetCompact(), bnNew.getuint256().toString().c_str()); return bnNew.GetCompact(); }
unsigned int BitcoinChain::nextWorkRequired(const CBlockIndex* pindexLast) const { const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks const int64 nTargetSpacing = 10 * 60; const int64 nInterval = nTargetTimespan / nTargetSpacing; // Genesis block if (pindexLast == NULL) return proofOfWorkLimit().GetCompact(); // Only change once per interval if ((pindexLast->nHeight+1) % nInterval != 0) return pindexLast->nBits; // Go back by what we want to be 14 days worth of blocks const CBlockIndex* pindexFirst = pindexLast; for (int i = 0; pindexFirst && i < nInterval-1; i++) pindexFirst = pindexFirst->pprev; assert(pindexFirst); // Limit adjustment step int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); printf(" nActualTimespan = %"PRI64d" before bounds\n", nActualTimespan); if (nActualTimespan < nTargetTimespan/4) nActualTimespan = nTargetTimespan/4; if (nActualTimespan > nTargetTimespan*4) nActualTimespan = nTargetTimespan*4; // Retarget CBigNum bnNew; bnNew.SetCompact(pindexLast->nBits); bnNew *= nActualTimespan; bnNew /= nTargetTimespan; if (bnNew > proofOfWorkLimit()) bnNew = proofOfWorkLimit(); /// debug print printf("GetNextWorkRequired RETARGET\n"); printf("nTargetTimespan = %"PRI64d" nActualTimespan = %"PRI64d"\n", nTargetTimespan, nActualTimespan); printf("Before: %08x %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().toString().c_str()); printf("After: %08x %s\n", bnNew.GetCompact(), bnNew.getuint256().toString().c_str()); return bnNew.GetCompact(); }
int TerracoinChain::nextWorkRequired(BlockIterator blk) const { const int64_t nTargetTimespan = 60 * 60; // one hour weeks const int64_t nTargetSpacing = 2 * 60; // new block every two minutes const int64_t nInterval = nTargetTimespan / nTargetSpacing; // Genesis block int h = blk.height(); if (h == 0) // trick to test that it is asking for the genesis block return proofOfWorkLimit().GetCompact(); // Only change once per interval if ((h + 1) % nInterval != 0) return blk->bits; // Go back by what we want to be 14 days worth of blocks BlockIterator former = blk - (nInterval-1); // Limit adjustment step int nActualTimespan = blk->time - former->time; log_debug(" nActualTimespan = %"PRI64d" before bounds", nActualTimespan); if (nActualTimespan < nTargetTimespan/4) nActualTimespan = nTargetTimespan/4; if (nActualTimespan > nTargetTimespan*4) nActualTimespan = nTargetTimespan*4; // Retarget CBigNum bnNew; bnNew.SetCompact(blk->bits); bnNew *= nActualTimespan; bnNew /= nTargetTimespan; if (bnNew > proofOfWorkLimit()) bnNew = proofOfWorkLimit(); /// debug print log_info("GetNextWorkRequired RETARGET"); log_info("nTargetTimespan = %"PRI64d" nActualTimespan = %"PRI64d"", nTargetTimespan, nActualTimespan); log_info("Before: %08x %s", blk->bits, CBigNum().SetCompact(blk->bits).getuint256().toString().c_str()); log_info("After: %08x %s", bnNew.GetCompact(), bnNew.getuint256().toString().c_str()); return bnNew.GetCompact(); }
/// This function has changed as it served two purposes: sanity check for headers and real proof of work check. We only need the proofOfWorkLimit for the latter const bool TerracoinChain::checkProofOfWork(const Block& block) const { uint256 hash = block.getHash(); unsigned int nBits = block.getBits(); CBigNum bnTarget; bnTarget.SetCompact(nBits); // Check range if (proofOfWorkLimit() != 0 && (bnTarget <= 0 || bnTarget > proofOfWorkLimit())) { log_error("CheckProofOfWork() : nBits below minimum work"); return false; } // Check proof of work matches claimed amount if (hash > bnTarget.getuint256()) { log_error("CheckProofOfWork() : hash doesn't match nBits"); return false; } return true; }
void MiningPage::timerEvent(QTimerEvent *) { int64 NetworkHashrate = GetNetworkHashPS(120, -1).get_int64(); int64 Hashrate = GetBoolArg("-gen")? gethashespersec(json_spirit::Array(), false).get_int64() : 0; QString NextBlockTime; if (Hashrate == 0) NextBlockTime = QChar(L'∞'); else { CBigNum Target; Target.SetCompact(pindexBest->nBits); CBigNum ExpectedTime = (CBigNum(1) << 256)/(Target*Hashrate); NextBlockTime = formatTimeInterval(ExpectedTime); } ui->labelNethashrate->setText(formatHashrate(NetworkHashrate)); ui->labelYourHashrate->setText(formatHashrate(Hashrate)); ui->labelNextBlock->setText(NextBlockTime); }
/// This function has changed as it served two purposes: sanity check for headers and real proof of work check. We only need the proofOfWorkLimit for the latter /// For namecoin we allow merged mining for the PoW! const bool NamecoinChain::checkProofOfWork(const Block& block) const { log_trace("Enter %s (block.version = %d)", __FUNCTION__, block.getVersion()); // we accept aux pow all the time - the lockins will ensure we get the right chain // Prevent same work from being submitted twice: // - this block must have our chain ID // - parent block must not have the same chain ID (see CAuxPow::Check) // - index of this chain in chain merkle tree must be pre-determined (see CAuxPow::Check) // if (nHeight != INT_MAX && GetChainID() != GetOurChainID()) // return error("CheckProofOfWork() : block does not have our chain ID"); CBigNum target; target.SetCompact(block.getBits()); if (proofOfWorkLimit() != 0 && (target <= 0 || target > proofOfWorkLimit())) { cout << target.GetHex() << endl; cout << proofOfWorkLimit().GetHex() << endl; log_error("CheckProofOfWork() : nBits below minimum work"); return false; } if (block.getVersion()&BLOCK_VERSION_AUXPOW) { if (!block.getAuxPoW().Check(block.getHash(), block.getVersion()/BLOCK_VERSION_CHAIN_START)) { log_error("CheckProofOfWork() : AUX POW is not valid"); return false; } // Check proof of work matches claimed amount if (block.getAuxPoW().GetParentBlockHash() > target.getuint256()) { log_error("CheckProofOfWork() : AUX proof of work failed"); return false; } } else { // Check proof of work matches claimed amount if (block.getHash() > target.getuint256()) { log_error("CheckProofOfWork() : proof of work failed"); return false; } } log_trace("Return(true): %s", __FUNCTION__); return true; }
/** Main Connection Thread. Handles all the networking to allow Mining threads the most performance. **/ void ServerConnection::ServerThread() { /** Don't begin until all mining threads are Created. **/ while (THREADS.size() != nThreads) Sleep(1000); /** Initialize the Server Connection. **/ CLIENT = new LLP::Miner(IP, PORT); /** Initialize a Timer for the Hash Meter. **/ TIMER.Start(); unsigned int nTimerWait = 2; unsigned int nBestHeight = 0; loop { try { /** Run this thread at 1 Cycle per Second. **/ Sleep(50); /** Attempt with best efforts to keep the Connection Alive. **/ if (!CLIENT->Connected() || CLIENT->Errors()) { ResetThreads(); if (!CLIENT->Connect()) continue; else CLIENT->SetChannel(2); } /** Check the Block Height. **/ unsigned int nHeight = CLIENT->GetHeight(5); if (nHeight == 0) { printf("[MASTER] Failed to Update Height\n"); CLIENT->Disconnect(); continue; } /** If there is a new block, Flag the Threads to Stop Mining. **/ if (nHeight != nBestHeight) { nBestHeight = nHeight; printf("[MASTER] Coinshield Network: New Block %u\n", nHeight); ResetThreads(); } /** Rudimentary Meter **/ if (TIMER.Elapsed() > nTimerWait) { double Elapsed = (double)TIMER.ElapsedMilliseconds(); unsigned long long nHashes = Hashes(); //double khash = ((double)nHashes)/Elapsed; unsigned long long khash = nHashes / TIMER.ElapsedMilliseconds(); unsigned int nDifficulty = THREADS[0]->GetBlock()->GetBits(); nDifficulty = nDifficulty & 0xffffff; CBigNum target; target.SetCompact(nDifficulty); //double diff = (double)(0xFFFF * pow(2, 208)) / (double)nDifficulty; printf("[METERS] %llu kHash/s | Height = %u | Diff= %.08f\n", khash, nBestHeight, 1.0 / (double)nDifficulty); TIMER.Reset(); if (nTimerWait == 2) nTimerWait = 20; } /** Check if there is work to do for each Miner Thread. **/ for (unsigned int nIndex = 0; nIndex < THREADS.size(); nIndex++) { /** Attempt to get a new block from the Server if Thread needs One. **/ if (THREADS[nIndex]->GetIsNewBlock()) { /** Retrieve new block from Server. **/ /** Delete the Block Pointer if it Exists. **/ CBlock* pBlock = THREADS[nIndex]->GetBlock(); if (pBlock != NULL) { delete(pBlock); } /** Retrieve new block from Server. **/ pBlock = CLIENT->GetBlock(5); /** If the block is good, tell the Mining Thread its okay to Mine. **/ if (pBlock) { THREADS[nIndex]->SetIsBlockFound(false); THREADS[nIndex]->SetIsNewBlock(false); THREADS[nIndex]->SetBlock(pBlock); THREADS[nIndex]->SetHashes(0); // reset hash count } /** If the Block didn't come in properly, Reconnect to the Server. **/ else { CLIENT->Disconnect(); break; } } /** Submit a block from Mining Thread if Flagged. **/ else if (THREADS[nIndex]->GetIsBlockFound()) { // /** Attempt to Submit the Block to Network. **/ unsigned char RESPONSE = CLIENT->SubmitBlock(THREADS[nIndex]->GetBlock()->GetMerkleRoot(), THREADS[nIndex]->GetBlock()->GetNonce(), 10); double Elapsed = (double)TIMER.ElapsedMilliseconds(); double nHashes = THREADS[nIndex]->GetHashes(); double khash = nHashes / Elapsed; Hashes(); TIMER.Reset(); if (RESPONSE == 200) printf("[MASTER] Block Found by %s on thread %d %.1f kHash/s (accepted) Yay !!!\n", device_name[nIndex], nIndex, khash); else if (RESPONSE == 201) { printf("[MASTER] Block Found by %s on thread %d %.1f kHash/s (rejected) Booo !!!\n", device_name[nIndex], nIndex, khash); THREADS[nIndex]->SetIsNewBlock(true); THREADS[nIndex]->SetIsBlockFound(false); } else { printf("[MASTER] Failure to Submit Block. Reconnecting...\n"); CLIENT->Disconnect(); } break; } } } catch (std::exception& e) { printf("%s\n", e.what()); } } };
unsigned int RetargetGPU(const CBlockIndex* pindex, bool output) { /** Get the Last Block Index [1st block back in Channel]. **/ const CBlockIndex* pindexFirst = GetLastChannelIndex(pindex, 2); if (pindexFirst->pprev == NULL) return bnProofOfWorkStart[2].GetCompact(); /** Get Last Block Index [2nd block back in Channel]. **/ const CBlockIndex* pindexLast = GetLastChannelIndex(pindexFirst->pprev, 2); if (pindexLast->pprev == NULL) return bnProofOfWorkStart[2].GetCompact(); /** Get the Block Times with Minimum of 1 to Prevent Time Warps. **/ int64 nBlockTime = ((pindex->nVersion >= 4) ? GetWeightedTimes(pindexFirst, 5) : max(pindexFirst->GetBlockTime() - pindexLast->GetBlockTime(), (int64) 1)); int64 nBlockTarget = nTargetTimespan; /** Get the Chain Modular from Reserves. **/ double nChainMod = GetFractionalSubsidy(GetChainAge(pindexFirst->GetBlockTime()), 0, ((pindex->nVersion >= 3) ? 40.0 : 20.0)) / (pindexFirst->nReleasedReserve[0] + 1); nChainMod = min(nChainMod, 1.0); nChainMod = max(nChainMod, (pindex->nVersion == 1) ? 0.75 : 0.5); /** Enforce Block Version 2 Rule. Chain mod changes block time requirements, not actual mod after block times. **/ if(pindex->nVersion >= 2) nBlockTarget *= nChainMod; /** The Upper and Lower Bound Adjusters. **/ int64 nUpperBound = nBlockTarget; int64 nLowerBound = nBlockTarget; /** Handle for Version 3 Blocks. Mod determined by time multiplied by max / min. **/ if(pindex->nVersion >= 3) { /** If the time is above target, reduce difficulty by modular of one interval past timespan multiplied by maximum decrease. **/ if(nBlockTime >= nBlockTarget) { /** Take the Minimum overlap of Target Timespan to make that maximum interval. **/ uint64 nOverlap = (uint64)min((nBlockTime - nBlockTarget), (nBlockTarget * 2)); /** Get the Mod from the Proportion of Overlap in one Interval. **/ double nProportions = (double)nOverlap / (nBlockTarget * 2); /** Get Mod from Maximum Decrease Equation with Decimal portions multiplied by Propotions. **/ double nMod = 1.0 - (((pindex->nVersion >= 4) ? 0.15 : 0.75) * nProportions); nLowerBound = nBlockTarget * nMod; } /** If the time is below target, increase difficulty by modular of interval of 1 - Block Target with time of 1 being maximum increase **/ else { /** Get the overlap in reference from Target Timespan. **/ uint64 nOverlap = nBlockTarget - nBlockTime; /** Get the mod from overlap proportion. Time of 1 will be closest to mod of 1. **/ double nProportions = (double) nOverlap / nBlockTarget; /** Get the Mod from the Maximum Increase Equation with Decimal portion multiplied by Proportions. **/ double nMod = 1.0 + (nProportions * 0.075); nLowerBound = nBlockTarget * nMod; } } /** Handle for Version 2 Difficulty Adjustments. **/ else { double nBlockMod = (double) nBlockTarget / nBlockTime; nBlockMod = min(nBlockMod, 1.125); nBlockMod = max(nBlockMod, 0.75); /** Calculate the Lower Bounds. **/ nLowerBound = nBlockTarget * nBlockMod; /** Version 1 Blocks Change Lower Bound from Chain Modular. **/ if(pindex->nVersion == 1) nLowerBound *= nChainMod; /** Set Maximum [difficulty] up to 8%, and Minimum [difficulty] down to 50% **/ nLowerBound = min(nLowerBound, (int64)(nUpperBound + (nUpperBound / 8))); nLowerBound = max(nLowerBound, (3 * nUpperBound ) / 4); } /** Get the Difficulty Stored in Bignum Compact. **/ CBigNum bnNew; bnNew.SetCompact(pindexFirst->nBits); /** Change Number from Upper and Lower Bounds. **/ bnNew *= nUpperBound; bnNew /= nLowerBound; /** Don't allow Difficulty to decrease below minimum. **/ if (bnNew > bnProofOfWorkLimit[2]) bnNew = bnProofOfWorkLimit[2]; /** Console Output if Flagged. **/ if(output) { int64 nDays, nHours, nMinutes; GetChainTimes(GetChainAge(pindexFirst->GetBlockTime()), nDays, nHours, nMinutes); printf("RETARGET[GPU] weighted time=%"PRId64" actual time %"PRId64" [%f %%]\n\tchain time: [%"PRId64" / %"PRId64"]\n\treleased reward: %"PRId64" [%f %%]\n\tdifficulty: [%f to %f]\n\tGPU height: %"PRId64" [AGE %"PRId64" days, %"PRId64" hours, %"PRId64" minutes]\n\n", nBlockTime, max(pindexFirst->GetBlockTime() - pindexLast->GetBlockTime(), (int64) 1), (100.0 * nLowerBound) / nUpperBound, nBlockTarget, nBlockTime, pindexFirst->nReleasedReserve[0] / COIN, 100.0 * nChainMod, GetDifficulty(pindexFirst->nBits, 2), GetDifficulty(bnNew.GetCompact(), 2), pindexFirst->nChannelHeight, nDays, nHours, nMinutes); } return bnNew.GetCompact(); }
bool CreateCoinStake( CBlock &blocknew, CKey &key, vector<const CWalletTx*> &StakeInputs, uint64_t &CoinAge, CWallet &wallet, CBlockIndex* pindexPrev ) { int64_t CoinWeight; CBigNum StakeKernelHash; CTxDB txdb("r"); int64_t StakeWeightSum = 0; double StakeValueSum = 0; int64_t StakeWeightMin=MAX_MONEY; int64_t StakeWeightMax=0; uint64_t StakeCoinAgeSum=0; double StakeDiffSum = 0; double StakeDiffMax = 0; CTransaction &txnew = blocknew.vtx[1]; // second tx is coinstake //initialize the transaction txnew.nTime = blocknew.nTime & (~STAKE_TIMESTAMP_MASK); txnew.vin.clear(); txnew.vout.clear(); // Choose coins to use set <pair <const CWalletTx*,unsigned int> > CoinsToStake; int64_t BalanceToStake = wallet.GetBalance(); int64_t nValueIn = 0; //Request all the coins here, check reserve later if ( BalanceToStake<=0 || !wallet.SelectCoinsForStaking(BalanceToStake*2, txnew.nTime, CoinsToStake, nValueIn) ) { LOCK(MinerStatus.lock); MinerStatus.ReasonNotStaking+=_("No coins; "); if (fDebug) LogPrintf("CreateCoinStake: %s",MinerStatus.ReasonNotStaking); return false; } BalanceToStake -= nReserveBalance; if(fDebug2) LogPrintf("\nCreateCoinStake: Staking nTime/16= %d Bits= %u", txnew.nTime/16,blocknew.nBits); for(const auto& pcoin : CoinsToStake) { const CTransaction &CoinTx =*pcoin.first; //transaction that produced this coin unsigned int CoinTxN =pcoin.second; //index of this coin inside it CTxIndex txindex; { LOCK2(cs_main, wallet.cs_wallet); if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex)) continue; //error? } CBlock CoinBlock; //Block which contains CoinTx { LOCK2(cs_main, wallet.cs_wallet); if (!CoinBlock.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) continue; } // only count coins meeting min age requirement if (CoinBlock.GetBlockTime() + nStakeMinAge > txnew.nTime) continue; if (CoinTx.vout[CoinTxN].nValue > BalanceToStake) continue; { int64_t nStakeValue= CoinTx.vout[CoinTxN].nValue; StakeValueSum += nStakeValue /(double)COIN; //crazy formula... // todo: clean this // todo reuse calculated value for interst CBigNum bn = CBigNum(nStakeValue) * (blocknew.nTime-CoinTx.nTime) / CENT; bn = bn * CENT / COIN / (24 * 60 * 60); StakeCoinAgeSum += bn.getuint64(); } if(blocknew.nVersion==7) { NetworkTimer(); CoinWeight = CalculateStakeWeightV3(CoinTx,CoinTxN,GlobalCPUMiningCPID); StakeKernelHash= CalculateStakeHashV3(CoinBlock,CoinTx,CoinTxN,txnew.nTime,GlobalCPUMiningCPID,mdPORNonce); } else { uint64_t StakeModifier = 0; if(!FindStakeModifierRev(StakeModifier,pindexPrev)) continue; CoinWeight = CalculateStakeWeightV8(CoinTx,CoinTxN,GlobalCPUMiningCPID); StakeKernelHash= CalculateStakeHashV8(CoinBlock,CoinTx,CoinTxN,txnew.nTime,StakeModifier,GlobalCPUMiningCPID); } CBigNum StakeTarget; StakeTarget.SetCompact(blocknew.nBits); StakeTarget*=CoinWeight; StakeWeightSum += CoinWeight; StakeWeightMin=std::min(StakeWeightMin,CoinWeight); StakeWeightMax=std::max(StakeWeightMax,CoinWeight); double StakeKernelDiff = GetBlockDifficulty(StakeKernelHash.GetCompact())*CoinWeight; StakeDiffSum += StakeKernelDiff; StakeDiffMax = std::max(StakeDiffMax,StakeKernelDiff); if (fDebug2) { int64_t RSA_WEIGHT = GetRSAWeightByBlock(GlobalCPUMiningCPID); LogPrintf( "CreateCoinStake: V%d Time %.f, Por_Nonce %.f, Bits %jd, Weight %jd\n" " RSA_WEIGHT %.f\n" " Stk %72s\n" " Trg %72s\n" " Diff %0.7f of %0.7f\n", blocknew.nVersion, (double)txnew.nTime, mdPORNonce, (intmax_t)blocknew.nBits,(intmax_t)CoinWeight, (double)RSA_WEIGHT, StakeKernelHash.GetHex().c_str(), StakeTarget.GetHex().c_str(), StakeKernelDiff, GetBlockDifficulty(blocknew.nBits) ); } if( StakeKernelHash <= StakeTarget ) { // Found a kernel LogPrintf("\nCreateCoinStake: Found Kernel;\n"); blocknew.nNonce= mdPORNonce; vector<valtype> vSolutions; txnouttype whichType; CScript scriptPubKeyOut; CScript scriptPubKeyKernel; scriptPubKeyKernel = CoinTx.vout[CoinTxN].scriptPubKey; if (!Solver(scriptPubKeyKernel, whichType, vSolutions)) { LogPrintf("CreateCoinStake: failed to parse kernel\n"); break; } if (whichType == TX_PUBKEYHASH) // pay to address type { // convert to pay to public key type if (!wallet.GetKey(uint160(vSolutions[0]), key)) { LogPrintf("CreateCoinStake: failed to get key for kernel type=%d\n", whichType); break; // unable to find corresponding public key } scriptPubKeyOut << key.GetPubKey() << OP_CHECKSIG; } else if (whichType == TX_PUBKEY) // pay to public key type { valtype& vchPubKey = vSolutions[0]; if (!wallet.GetKey(Hash160(vchPubKey), key) || key.GetPubKey() != vchPubKey) { LogPrintf("CreateCoinStake: failed to get key for kernel type=%d\n", whichType); break; // unable to find corresponding public key } scriptPubKeyOut = scriptPubKeyKernel; } else { LogPrintf("CreateCoinStake: no support for kernel type=%d\n", whichType); break; // only support pay to public key and pay to address } txnew.vin.push_back(CTxIn(CoinTx.GetHash(), CoinTxN)); StakeInputs.push_back(pcoin.first); if (!txnew.GetCoinAge(txdb, CoinAge)) return error("CreateCoinStake: failed to calculate coin age"); int64_t nCredit = CoinTx.vout[CoinTxN].nValue; txnew.vout.push_back(CTxOut(0, CScript())); // First Must be empty txnew.vout.push_back(CTxOut(nCredit, scriptPubKeyOut)); //txnew.vout.push_back(CTxOut(0, scriptPubKeyOut)); LogPrintf("CreateCoinStake: added kernel type=%d credit=%f\n", whichType,CoinToDouble(nCredit)); LOCK(MinerStatus.lock); MinerStatus.KernelsFound++; MinerStatus.KernelDiffMax = 0; MinerStatus.KernelDiffSum = StakeDiffSum; return true; } } LOCK(MinerStatus.lock); MinerStatus.WeightSum = StakeWeightSum; MinerStatus.ValueSum = StakeValueSum; MinerStatus.WeightMin=StakeWeightMin; MinerStatus.WeightMax=StakeWeightMax; MinerStatus.CoinAgeSum=StakeCoinAgeSum; MinerStatus.KernelDiffMax = std::max(MinerStatus.KernelDiffMax,StakeDiffMax); MinerStatus.KernelDiffSum = StakeDiffSum; MinerStatus.nLastCoinStakeSearchInterval= txnew.nTime; return false; }
CMainParams() { // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. pchMessageStart[0] = 0xf9; pchMessageStart[1] = 0xbe; pchMessageStart[2] = 0xb4; pchMessageStart[3] = 0xd9; vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"); nDefaultPort = 28333; nRPCPort = 8332; bnProofOfWorkLimit = CBigNum(~uint256(0) >> 16); nSubsidyHalvingInterval = 210000; // Build the genesis block. Note that the output of the genesis coinbase cannot // be spent as it did not originally exist in the database. // // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1) // CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0) // CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73) // CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B) // vMerkleTree: 4a5e1e const char* pszTimestamp = "2014-03-30 Nobody 50.06, Kiska 29.66, Fico 20.28; Founder: heXKRhnGdSg"; int extranonce = 42; CTransaction txNew; txNew.vin.resize(1); txNew.vout.resize(1); txNew.vin[0].scriptSig = CScript() << extranonce << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); txNew.vout[0].nValue = 50 * COIN; txNew.vout[0].scriptPubKey = CScript() << ParseHex("2dc4f1967fbf825c77dadd9da14c3608428ada53") << OP_EQUALVERIFY << OP_CHECKSIG; genesis.vtx.push_back(txNew); genesis.hashPrevBlock = 0; genesis.hashMerkleRoot = genesis.BuildMerkleTree(); genesis.nVersion = 1; genesis.nTime = 1396187239; genesis.nBits = 0x1e008fff; genesis.nNonce = 23443383; hashGenesisBlock = genesis.GetHash(); #ifdef MINE_GENESIS CBigNum bnTarget; bnTarget.SetCompact(genesis.nBits); fprintf(stderr, "Target: %s\n", bnTarget.ToString().c_str()); assert(!(bnTarget <= 0 || bnTarget > Params().ProofOfWorkLimit())); while(hashGenesisBlock > bnTarget.getuint256()) { ++genesis.nNonce; if(!genesis.nNonce) { ++extranonce; }; hashGenesisBlock = genesis.GetHash(); } fprintf(stderr, "Nonce = %d\nExtranonce = %d\n", genesis.nNonce, extranonce); fprintf(stderr, "Genesis hash = %s\nMerkle root = %s\n", hashGenesisBlock.GetHex().c_str(), genesis.hashMerkleRoot.GetHex().c_str()); #else assert(hashGenesisBlock == uint256("0x000000530b4b2d75534bfa61c42e62f4402ce579dd8507c70009e69439f4bd19")); assert(genesis.hashMerkleRoot == uint256("0x2446d19ab3361d3484c4f1dade799a54dfd010f193521659a26341c6f50b811a")); #endif vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be")); vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me")); vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com")); vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org")); base58Prefixes[PUBKEY_ADDRESS] = list_of(45); base58Prefixes[SCRIPT_ADDRESS] = list_of(50); base58Prefixes[SECRET_KEY] = list_of(173); base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x88)(0xB2)(0x1E); base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x88)(0xAD)(0xE4); // Convert the pnSeeds array into usable address objects. for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++) { // It'll only connect to one or two seed nodes because once it connects, // it'll get a pile of addresses with newer timestamps. // Seed nodes are given a random 'last seen time' of between one and two // weeks ago. const int64_t nOneWeek = 7*24*60*60; struct in_addr ip; memcpy(&ip, &pnSeed[i], sizeof(ip)); CAddress addr(CService(ip, GetDefaultPort())); addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek; vFixedSeeds.push_back(addr); } }
void MinerThread::SK1024Miner() { SetThreadPriority(GetCurrentThread(), 2); const int throughput = GetThroughput() == 0 ? 512 * 1 * 512 * 8 : GetThroughput(); loop { try { /** Don't mine if the Connection Thread is Submitting Block or Receiving New. **/ while(m_bNewBlock || m_bBlockFound || !m_pBLOCK) Sleep(1); CBigNum target; target.SetCompact(m_pBLOCK->GetBits()); if (m_bBenchmark == true) { target.SetCompact(0x7e006fff); //target.SetCompact(0x7e7fffff); //target.SetCompact(0x7e7fffff); //target = target / 0x300; } while(!m_bNewBlock) { uint1024 hash; unsigned long long hashes=0; unsigned int * TheData =(unsigned int*) m_pBLOCK->GetData(); uint1024 TheTarget = target.getuint1024(); uint64_t Nonce; //= m_pBLOCK->GetNonce(); bool found = false; m_clLock.lock(); { Nonce = m_pBLOCK->GetNonce(); //m_GpuId = 0; found = scanhash_sk1024(m_GpuId, TheData, TheTarget, Nonce, 512 * 8 * 512 * 40, &hashes, throughput, 128, 128); if (hashes < 0xffffffffffff) SetHashes(GetHashes()+hashes); } m_clLock.unlock(); if(found) { m_bBlockFound = true; m_clLock.lock(); { m_pBLOCK->SetNonce(Nonce); } m_clLock.unlock(); break; } // printf("hashes %d m_unHashes %d gethashes %d\n",hashes,m_unHashes,GetHashes()); /*m_clLock.lock(); { m_pBLOCK->SetNonce(m_pBLOCK->GetNonce()+hashes); } m_clLock.unlock(); */ if(Nonce >= MAX_THREADS) //max_thread==> max_nonce { m_bNewBlock = true; break; } } } catch(std::exception& e) { printf("ERROR: %s\n", e.what()); } } }
/** Proof of Stake Retargeting: Modulate Difficulty based on production rate. **/ unsigned int RetargetPOS(const CBlockIndex* pindex, bool output) { /** Get Last Block Index [1st block back in Channel]. **/ const CBlockIndex* pindexFirst = GetLastChannelIndex(pindex, 0); if (pindexFirst->pprev == NULL) return bnProofOfWorkStart[0].GetCompact(); /** Get Last Block Index [2nd block back in Channel]. **/ const CBlockIndex* pindexLast = GetLastChannelIndex(pindexFirst->pprev, 0); if (pindexLast->pprev == NULL) return bnProofOfWorkStart[0].GetCompact(); /** Get the Block Time and Target Spacing. **/ int64 nBlockTime = GetWeightedTimes(pindexFirst, 5); int64 nBlockTarget = STAKE_TARGET_SPACING; /** The Upper and Lower Bound Adjusters. **/ int64 nUpperBound = nBlockTarget; int64 nLowerBound = nBlockTarget; /** If the time is above target, reduce difficulty by modular of one interval past timespan multiplied by maximum decrease. **/ if(nBlockTime >= nBlockTarget) { /** Take the Minimum overlap of Target Timespan to make that maximum interval. **/ uint64 nOverlap = (uint64)min((nBlockTime - nBlockTarget), (nBlockTarget * 2)); /** Get the Mod from the Proportion of Overlap in one Interval. **/ double nProportions = (double)nOverlap / (nBlockTarget * 2); /** Get Mod from Maximum Decrease Equation with Decimal portions multiplied by Propotions. **/ double nMod = 1.0 - (0.15 * nProportions); nLowerBound = nBlockTarget * nMod; } /** If the time is below target, increase difficulty by modular of interval of 1 - Block Target with time of 1 being maximum increase **/ else { /** Get the overlap in reference from Target Timespan. **/ uint64 nOverlap = nBlockTarget - nBlockTime; /** Get the mod from overlap proportion. Time of 1 will be closest to mod of 1. **/ double nProportions = (double) nOverlap / nBlockTarget; /** Get the Mod from the Maximum Increase Equation with Decimal portion multiplied by Proportions. **/ double nMod = 1.0 + (nProportions * 0.075); nLowerBound = nBlockTarget * nMod; } /** Get the Difficulty Stored in Bignum Compact. **/ CBigNum bnNew; bnNew.SetCompact(pindexFirst->nBits); /** Change Number from Upper and Lower Bounds. **/ bnNew *= nUpperBound; bnNew /= nLowerBound; /** Don't allow Difficulty to decrease below minimum. **/ if (bnNew > bnProofOfWorkLimit[0]) bnNew = bnProofOfWorkLimit[0]; if(output) { int64 nDays, nHours, nMinutes; GetChainTimes(GetChainAge(pindexFirst->GetBlockTime()), nDays, nHours, nMinutes); printf("CHECK[POS] weighted time=%"PRId64" actual time =%"PRId64"[%f %%]\n\tchain time: [%"PRId64" / %"PRId64"]\n\tdifficulty: [%f to %f]\n\tPOS height: %"PRId64" [AGE %"PRId64" days, %"PRId64" hours, %"PRId64" minutes]\n\n", nBlockTime, max(pindexFirst->GetBlockTime() - pindexLast->GetBlockTime(), (int64) 1), ((100.0 * nLowerBound) / nUpperBound), nBlockTarget, nBlockTime, GetDifficulty(pindexFirst->nBits, 0), GetDifficulty(bnNew.GetCompact(), 0), pindexFirst->nChannelHeight, nDays, nHours, nMinutes); } return bnNew.GetCompact(); }