Merge pull request #60 from airk42/cb-inputs
rebased cb-inputs merge back into master
This commit is contained in:
commit
20d7e7a08e
18
configure.ac
18
configure.ac
|
@ -82,6 +82,13 @@ AC_ARG_ENABLE([wallet],
|
|||
[enable_wallet=$enableval],
|
||||
[enable_wallet=yes])
|
||||
|
||||
# Enable fork mining
|
||||
AC_ARG_ENABLE([fork],
|
||||
[AS_HELP_STRING([--enable-fork],
|
||||
[enable fork (default is yes)])],
|
||||
[enable_fork=$enableval],
|
||||
[enable_fork=yes])
|
||||
|
||||
AC_ARG_ENABLE([mining],
|
||||
[AS_HELP_STRING([--enable-mining],
|
||||
[enable mining (default is yes)])],
|
||||
|
@ -856,6 +863,16 @@ else
|
|||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl enable fork_mining
|
||||
AC_MSG_CHECKING([if fork mining should be enabled])
|
||||
if test x$enable_fork != xno; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(FORK_CB_INPUT, 1, [Define to 1 to enable fork mining functions])
|
||||
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl enable mining
|
||||
AC_MSG_CHECKING([if mining should be enabled])
|
||||
if test x$enable_mining != xno; then
|
||||
|
@ -931,6 +948,7 @@ AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin])
|
|||
AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin])
|
||||
AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
|
||||
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
|
||||
AM_CONDITIONAL([FORK_CB_INPUT],[test x$enable_fork = xyes])
|
||||
AM_CONDITIONAL([ENABLE_MINING],[test x$enable_mining = xyes])
|
||||
AM_CONDITIONAL([ENABLE_RUST],[test x$enable_rust = xyes])
|
||||
AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
|
||||
|
|
|
@ -165,7 +165,7 @@ Threads
|
|||
|
||||
- ThreadRPCServer : Remote procedure call handler, listens on port 7932 for connections and services them.
|
||||
|
||||
- ZcashMiner : Generates zcash (if wallet is enabled).
|
||||
- BTCPrivate Miner : Generates BTCPrivate (if wallet is enabled).
|
||||
|
||||
- Shutdown : Does an orderly shutdown of everything.
|
||||
|
||||
|
|
12
src/init.cpp
12
src/init.cpp
|
@ -492,6 +492,11 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||
if (GetBoolArg("-help-debug", false))
|
||||
strUsage += HelpMessageOpt("-blockversion=<n>", strprintf("Override block version to test forking scenarios (default: %d)", (int)CBlock::CURRENT_VERSION));
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
strUsage += HelpMessageGroup(_("Fork :"));
|
||||
strUsage += HelpMessageOpt("-utxo-path=<path>", _("Specify location of utxo files"));
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MINING
|
||||
strUsage += HelpMessageGroup(_("Mining options:"));
|
||||
strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), 0));
|
||||
|
@ -891,6 +896,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
forkUtxoPath = GetArg("-utxo-path", "");
|
||||
forkStartHeight = GetArg("-fork-startheight", FORK_BLOCK_HEIGHT_START);
|
||||
forkHeightRange = GetArg("-fork-heightrange", FORK_BLOCK_HEIGHT_RANGE);
|
||||
forkCBPerBlock = GetArg("-fork-cbperblock", FORK_COINBASE_PER_BLOCK);
|
||||
#endif
|
||||
|
||||
// ********************************************************* Step 3: parameter-to-internal-flags
|
||||
|
||||
fDebug = !mapMultiArgs["-debug"].empty();
|
||||
|
|
237
src/main.cpp
237
src/main.cpp
|
@ -71,6 +71,33 @@ size_t nCoinCacheUsage = 5000 * 300;
|
|||
uint64_t nPruneTarget = 0;
|
||||
bool fAlerts = DEFAULT_ALERTS;
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/range/combine.hpp>
|
||||
|
||||
std::string forkUtxoPath;
|
||||
int64_t forkStartHeight = FORK_BLOCK_HEIGHT_START;
|
||||
int64_t forkHeightRange = FORK_BLOCK_HEIGHT_RANGE;
|
||||
int64_t forkCBPerBlock = FORK_COINBASE_PER_BLOCK;
|
||||
|
||||
std::string GetUTXOFileName(int nHeight)
|
||||
{
|
||||
boost::filesystem::path utxo_path(forkUtxoPath);
|
||||
if (utxo_path.empty() || !utxo_path.has_filename())
|
||||
{
|
||||
LogPrintf("GetUTXOFileName(): UTXO path is not specified, add utxo-path=<path-to-utxop-files> to your btcprivate.conf and restart");
|
||||
return "";
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << boost::format("utxo-%05i.bin") % (nHeight - forkStartHeight);
|
||||
boost::filesystem::path utxo_file = utxo_path;
|
||||
utxo_file /= ss.str();
|
||||
|
||||
return utxo_file.generic_string();
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
|
||||
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
|
||||
|
||||
|
@ -1354,7 +1381,11 @@ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::M
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
|
||||
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos
|
||||
#ifdef FORK_CB_INPUT
|
||||
, int nHeight
|
||||
#endif
|
||||
)
|
||||
{
|
||||
block.SetNull();
|
||||
|
||||
|
@ -1371,17 +1402,30 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
|
|||
return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString());
|
||||
}
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (!isForkBlock(nHeight)) { //when block is in fork region - don't check Solution and PoW
|
||||
#endif
|
||||
|
||||
// Check the header
|
||||
if (!(CheckEquihashSolution(&block, Params()) &&
|
||||
CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())))
|
||||
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
|
||||
{
|
||||
if (!ReadBlockFromDisk(block, pindex->GetBlockPos()))
|
||||
if (!ReadBlockFromDisk(block, pindex->GetBlockPos()
|
||||
#ifdef FORK_CB_INPUT
|
||||
, pindex->nHeight
|
||||
#endif
|
||||
)
|
||||
)
|
||||
return false;
|
||||
if (block.GetHash() != pindex->GetBlockHash())
|
||||
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
|
||||
|
@ -1887,20 +1931,25 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
|||
const CTransaction &tx = block.vtx[i];
|
||||
uint256 hash = tx.GetHash();
|
||||
|
||||
int nNonCBIdx = 0;
|
||||
// restore inputs
|
||||
|
||||
// Check that all outputs are available and match the outputs in the block itself
|
||||
// exactly.
|
||||
{
|
||||
CCoinsModifier outs = view.ModifyCoins(hash);
|
||||
outs->ClearUnspendable();
|
||||
{
|
||||
CCoinsModifier outs = view.ModifyCoins(hash);
|
||||
outs->ClearUnspendable();
|
||||
|
||||
CCoins outsBlock(tx, pindex->nHeight);
|
||||
// The CCoins serialization does not serialize negative numbers.
|
||||
// No network rules currently depend on the version here, so an inconsistency is harmless
|
||||
// but it must be corrected before txout nversion ever influences a network rule.
|
||||
if (outsBlock.nVersion < 0)
|
||||
outs->nVersion = outsBlock.nVersion;
|
||||
if (*outs != outsBlock)
|
||||
fClean = fClean && error("DisconnectBlock(): added transaction mismatch? database corrupted");
|
||||
CCoins outsBlock(tx, pindex->nHeight);
|
||||
// The CCoins serialization does not serialize negative numbers.
|
||||
// No network rules currently depend on the version here, so an inconsistency is harmless
|
||||
// but it must be corrected before txout nversion ever influences a network rule.
|
||||
if (outsBlock.nVersion < 0)
|
||||
outs->nVersion = outsBlock.nVersion;
|
||||
if (*outs != outsBlock) {
|
||||
fClean = fClean && error("DisconnectBlock(): added transaction mismatch? database corrupted");
|
||||
LogPrintf("Transaction mismatch?: id: %d: Amount: %d; ScriptPubKey: %s\n", i, tx.vout[0].nValue, tx.vout[0].scriptPubKey.ToString());
|
||||
}
|
||||
|
||||
// remove outputs
|
||||
outs->Clear();
|
||||
|
@ -1913,8 +1962,12 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
|||
}
|
||||
}
|
||||
|
||||
// restore inputs
|
||||
if (i > 0) { // not coinbases
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (isForkBlock(pindex->nHeight)){ //when block in forking region - all transcations are coinbase
|
||||
nNonCBIdx = forkCBPerBlock;
|
||||
}
|
||||
#endif
|
||||
if (i > nNonCBIdx) { // not coinbases
|
||||
const CTxUndo &txundo = blockUndo.vtxundo[i-1];
|
||||
if (txundo.vprevout.size() != tx.vin.size())
|
||||
return error("DisconnectBlock(): transaction and undo data inconsistent");
|
||||
|
@ -2188,12 +2241,18 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
|||
int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart;
|
||||
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001);
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (!isForkBlock(pindex->nHeight)){ //when block is in forking region - don't check coinbase amount
|
||||
#endif
|
||||
CAmount blockReward = nFees + GetBlockSubsidy(pindex->nHeight, chainparams.GetConsensus());
|
||||
if (block.vtx[0].GetValueOut() > blockReward)
|
||||
return state.DoS(100,
|
||||
error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
|
||||
block.vtx[0].GetValueOut(), blockReward),
|
||||
REJECT_INVALID, "bad-cb-amount");
|
||||
#ifdef FORK_CB_INPUT
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!control.Wait())
|
||||
return state.DoS(100, false);
|
||||
|
@ -2970,6 +3029,10 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f
|
|||
return state.DoS(100, error("CheckBlockHeader(): block version too low"),
|
||||
REJECT_INVALID, "version-too-low");
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (!isTipInForkRange()) { //when in FORK mode (tip is in forking region) - don't check Solution and PoW
|
||||
#endif
|
||||
|
||||
// Check Equihash solution is valid
|
||||
if (fCheckPOW && !CheckEquihashSolution(&block, Params()))
|
||||
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),
|
||||
|
@ -2980,6 +3043,10 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f
|
|||
return state.DoS(50, error("CheckBlockHeader(): proof of work failed"),
|
||||
REJECT_INVALID, "high-hash");
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check timestamp
|
||||
if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
|
||||
return state.Invalid(error("CheckBlockHeader(): block timestamp too far in the future"),
|
||||
|
@ -3028,10 +3095,21 @@ bool CheckBlock(const CBlock& block, CValidationState& state,
|
|||
if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
|
||||
return state.DoS(100, error("CheckBlock(): first tx is not coinbase"),
|
||||
REJECT_INVALID, "bad-cb-missing");
|
||||
for (unsigned int i = 1; i < block.vtx.size(); i++)
|
||||
if (block.vtx[i].IsCoinBase())
|
||||
return state.DoS(100, error("CheckBlock(): more than one coinbase"),
|
||||
REJECT_INVALID, "bad-cb-multiple");
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (isTipInForkRange()) { //when in FORK mode (tip is in forking region) blocks might have up to fork pre-defined value coinbases
|
||||
if (block.vtx.size() > forkCBPerBlock)
|
||||
return state.DoS(100, error("CheckBlock(): it is forking block but there are more than %d coinbase txns", forkCBPerBlock),
|
||||
REJECT_INVALID, "bad-cb-multiple");
|
||||
} else {
|
||||
#endif
|
||||
for (unsigned int i = 1; i < block.vtx.size(); i++)
|
||||
if (block.vtx[i].IsCoinBase())
|
||||
return state.DoS(100, error("CheckBlock(): more than one coinbase"),
|
||||
REJECT_INVALID, "bad-cb-multiple");
|
||||
#ifdef FORK_CB_INPUT
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check transactions
|
||||
BOOST_FOREACH(const CTransaction& tx, block.vtx)
|
||||
|
@ -3063,9 +3141,15 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
|
|||
int nHeight = pindexPrev->nHeight+1;
|
||||
|
||||
// Check proof of work
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (!isForkBlock(nHeight)) { //If current block is FORK, don't check work required
|
||||
#endif
|
||||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
|
||||
return state.DoS(100, error("%s: incorrect proof of work", __func__),
|
||||
REJECT_INVALID, "bad-diffbits");
|
||||
#ifdef FORK_CB_INPUT
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check timestamp against prev
|
||||
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
|
||||
|
@ -3164,7 +3248,11 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
|
|||
return true;
|
||||
}
|
||||
|
||||
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp)
|
||||
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp
|
||||
#ifdef FORK_CB_INPUT
|
||||
, bool fCalledFromMiner
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
AssertLockHeld(cs_main);
|
||||
|
@ -3207,6 +3295,97 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
|
|||
|
||||
int nHeight = pindex->nHeight;
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (isForkBlock(nHeight)) { //if block is in forking region validate it agains file records
|
||||
if (!fCalledFromMiner && !forkUtxoPath.empty()) {
|
||||
|
||||
std::string utxo_file_path = GetUTXOFileName(nHeight);
|
||||
std::ifstream if_utxo(utxo_file_path, std::ios::binary | std::ios::in);
|
||||
if (!if_utxo.is_open()) {
|
||||
LogPrintf("AcceptBlock(): FORK Block - Cannot open UTXO file - %s\n", utxo_file_path);
|
||||
} else {
|
||||
LogPrintf("AcceptBlock(): FORK Block - Validating block - %u with UTXO file - %s\n", nHeight, utxo_file_path);
|
||||
|
||||
vector<pair<uint64_t, CScript> > txFromFile;
|
||||
txFromFile.reserve(forkCBPerBlock);
|
||||
int recs = 0;
|
||||
|
||||
while (if_utxo && recs < forkCBPerBlock) {
|
||||
char term = 0;
|
||||
char coin[8] = {};
|
||||
if (!if_utxo.read(coin, 8)) {
|
||||
LogPrintf("AcceptBlock(): FORK Block - No more data in the file \n");
|
||||
break;
|
||||
}
|
||||
uint64_t amount = bytes2uint64(coin);
|
||||
|
||||
char pubkeysize[8] = {};
|
||||
if (!if_utxo.read(pubkeysize, 8)) {
|
||||
LogPrintf("AcceptBlock(): FORK Block - UTXO file corrupted? - Not more data (PubKeyScript size)\n");
|
||||
break;
|
||||
}
|
||||
int pbsize = bytes2uint64(pubkeysize);
|
||||
if (pbsize == 0) {
|
||||
LogPrintf("AcceptBlock(): FORK Block - UTXO file corrupted? - Warning! PubKeyScript size = 0\n");
|
||||
//but proceed
|
||||
}
|
||||
std::unique_ptr<char[]> pubKeyScript(new char[pbsize]);
|
||||
if (!if_utxo.read(&pubKeyScript[0], pbsize)) {
|
||||
LogPrintf("AcceptBlock(): FORK Block - UTXO file corrupted? - Not more data (PubKeyScript)\n");
|
||||
break;
|
||||
}
|
||||
unsigned char* pks = (unsigned char*)pubKeyScript.get();
|
||||
CScript script = CScript(pks, pks+pbsize);
|
||||
|
||||
txFromFile.push_back(make_pair(amount, script));
|
||||
|
||||
if (!if_utxo.read(&term, 1)) {
|
||||
LogPrintf("AcceptBlock(): FORK Block - UTXO file corrupted? - No more data (record separator)\n");
|
||||
break;
|
||||
}
|
||||
if (term != '\n') {
|
||||
//This maybe not an error, but warning none the less
|
||||
LogPrintf("AcceptBlock(): FORK Block - UTXO file corrupted? - Warning! No record separator ('0xA') was found\n");
|
||||
if_utxo.seekg(-1, ios_base::cur); //move one char back - if it is not a separator, maybe there is not separators at all
|
||||
}
|
||||
recs++;
|
||||
}
|
||||
LogPrintf("AcceptBlock(): FORK Block - %d records read from UTXO file\n", recs);
|
||||
|
||||
if (txFromFile.size() != block.vtx.size() ||
|
||||
recs != block.vtx.size()){
|
||||
state.DoS(100, error("AcceptBlock(): Number of file records - %d doesn't match number of transcations in block - %d\n", recs, block.vtx.size()),
|
||||
REJECT_INVALID, "bad-fork-block");
|
||||
pindex->nStatus |= BLOCK_FAILED_VALID;
|
||||
setDirtyBlockIndex.insert(pindex);
|
||||
return false;
|
||||
}
|
||||
|
||||
int txid = 0;
|
||||
typedef boost::tuple<pair<uint64_t, CScript>&, const CTransaction&> fork_cmp_tuple;
|
||||
BOOST_FOREACH(fork_cmp_tuple cmp, boost::combine(txFromFile, block.vtx)) {
|
||||
pair<uint64_t, CScript>& rec = cmp.get<0>();
|
||||
const CTransaction& tx = cmp.get<1>();
|
||||
|
||||
if (rec.first != tx.vout[0].nValue ||
|
||||
rec.second != tx.vout[0].scriptPubKey)
|
||||
{
|
||||
LogPrintf("AcceptBlock(): FORK Block - Error: Transaction (%d) mismatch\n", txid);
|
||||
LogPrintf("AcceptBlock(): Transaction: Amount: %d; scriptPubKey: %s\n", tx.vout[0].nValue, tx.vout[0].scriptPubKey.ToString());
|
||||
LogPrintf("AcceptBlock(): File Record: Amount: %d; scriptPubKey: %s\n", rec.first, rec.second.ToString());
|
||||
state.DoS(100, error("AcceptBlock(): FORK Block - Transaction (%d) doesn't match record in the UTXO file", txid),
|
||||
REJECT_INVALID, "bad-fork-block");
|
||||
pindex->nStatus |= BLOCK_FAILED_VALID;
|
||||
setDirtyBlockIndex.insert(pindex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
txid++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Write block to history file
|
||||
try {
|
||||
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
|
||||
|
@ -3243,7 +3422,11 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
|
|||
}
|
||||
|
||||
|
||||
bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp)
|
||||
bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp
|
||||
#ifdef FORK_CB_INPUT
|
||||
, bool fCalledFromMiner
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Preliminary checks
|
||||
auto verifier = libzcash::ProofVerifier::Disabled();
|
||||
|
@ -3259,7 +3442,11 @@ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool
|
|||
|
||||
// Store to disk
|
||||
CBlockIndex *pindex = NULL;
|
||||
bool ret = AcceptBlock(*pblock, state, &pindex, fRequested, dbp);
|
||||
bool ret = AcceptBlock(*pblock, state, &pindex, fRequested, dbp
|
||||
#ifdef FORK_CB_INPUT
|
||||
, fCalledFromMiner
|
||||
#endif
|
||||
);
|
||||
if (pindex && pfrom) {
|
||||
mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
|
||||
}
|
||||
|
@ -3289,6 +3476,7 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
|
|||
// NOTE: CheckBlockHeader is called by CheckBlock
|
||||
if (!ContextualCheckBlockHeader(block, state, pindexPrev))
|
||||
return false;
|
||||
|
||||
if (!CheckBlock(block, state, verifier, fCheckPOW, fCheckMerkleRoot))
|
||||
return false;
|
||||
if (!ContextualCheckBlock(block, state, pindexPrev))
|
||||
|
@ -3475,7 +3663,12 @@ CBlockIndex * InsertBlockIndex(uint256 hash)
|
|||
bool static LoadBlockIndexDB()
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (!pblocktree->LoadBlockIndexGuts(forkStartHeight, forkStartHeight+forkHeightRange))
|
||||
#else
|
||||
if (!pblocktree->LoadBlockIndexGuts())
|
||||
#endif
|
||||
return false;
|
||||
|
||||
boost::this_thread::interruption_point();
|
||||
|
|
88
src/main.h
88
src/main.h
|
@ -174,7 +174,12 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals);
|
|||
* @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location.
|
||||
* @return True if state.IsValid()
|
||||
*/
|
||||
bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp);
|
||||
bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp
|
||||
#ifdef FORK_CB_INPUT
|
||||
, bool fCalledFromMiner = false
|
||||
#endif
|
||||
);
|
||||
|
||||
/** Check whether enough disk space is available for an incoming block */
|
||||
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
|
||||
/** Open a block file (blk?????.dat) */
|
||||
|
@ -396,7 +401,11 @@ public:
|
|||
|
||||
/** Functions for disk access for blocks */
|
||||
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart);
|
||||
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos);
|
||||
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos
|
||||
#ifdef FORK_CB_INPUT
|
||||
, int nHeight = -1
|
||||
#endif
|
||||
);
|
||||
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
|
||||
|
||||
|
||||
|
@ -413,6 +422,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
|||
|
||||
/** Context-independent validity checks */
|
||||
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
|
||||
|
||||
bool CheckBlock(const CBlock& block, CValidationState& state,
|
||||
libzcash::ProofVerifier& verifier,
|
||||
bool fCheckPOW = true, bool fCheckMerkleRoot = true);
|
||||
|
@ -431,7 +441,11 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex
|
|||
* - The only caller of AcceptBlock verifies JoinSplit proofs elsewhere.
|
||||
* If dbp is non-NULL, the file is known to already reside on disk
|
||||
*/
|
||||
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp);
|
||||
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, bool fRequested, CDiskBlockPos* dbp
|
||||
#ifdef FORK_CB_INPUT
|
||||
, bool fCalledFromMiner = false
|
||||
#endif
|
||||
);
|
||||
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL);
|
||||
|
||||
|
||||
|
@ -527,4 +541,72 @@ namespace Consensus {
|
|||
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams);
|
||||
}
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
#define FORK_BLOCK_HEIGHT_START 1000000 //current ZCL height is 200K-300K, this value here is placeholder, it will have to be changed to correct fork block height
|
||||
#define FORK_BLOCK_HEIGHT_RANGE 65000
|
||||
#define FORK_COINBASE_PER_BLOCK 10000
|
||||
|
||||
extern std::string forkUtxoPath;
|
||||
extern int64_t forkStartHeight;
|
||||
extern int64_t forkHeightRange;
|
||||
extern int64_t forkCBPerBlock;
|
||||
|
||||
std::string GetUTXOFileName(int nHeight);
|
||||
|
||||
//ex: forkStartHeight = 300 000; forkHeightRange = 65K
|
||||
//A. for miner:
|
||||
// 1. Current height = 299 999; the next block to create 300 000
|
||||
// nHeight is 300 000 - return false
|
||||
// 2. Current height = 300 000; the next block to create 300 001
|
||||
// nHeight is 300 001 - return true - file to use utxo-00001.bin
|
||||
// ...
|
||||
//
|
||||
// n-1. Current height = 364 999; the next block to create 365 000
|
||||
// nHeight is 365 000 - return true - file to use utxo-65000.bin
|
||||
// n. Current height = 365 000; the next block to create 365 001
|
||||
// nHeight is 365 001 - return false
|
||||
//
|
||||
// fork blocks 300001 - 365000
|
||||
//
|
||||
//B. for acceptblock:
|
||||
// 1. Current height = 299 999
|
||||
// nHeight is 299 999 - return false - no verification
|
||||
// 2. Current height = 300 000
|
||||
// nHeight is 300 000 - return false - no verification
|
||||
// 3. Current height = 300 001
|
||||
// nHeight is 300 001 - return true - verify with file utxo-00001.bin
|
||||
// ...
|
||||
//
|
||||
// n. Current height = 365 000
|
||||
// nHeight is 365 000 - return true - verify with file utxo-65000.bin
|
||||
// n+1. Current height = 365 001
|
||||
// nHeight is 365 001 - return false - no verification
|
||||
//
|
||||
inline bool isForkBlock(int nHeight)
|
||||
{
|
||||
return (nHeight > forkStartHeight && nHeight <= forkStartHeight + forkHeightRange);
|
||||
}
|
||||
inline bool isTipInForkRange()
|
||||
{
|
||||
return chainActive.Tip()? isForkBlock(chainActive.Tip()->nHeight): false;
|
||||
}
|
||||
inline bool isNextTipInForkRange()
|
||||
{
|
||||
return chainActive.Tip()? isForkBlock(chainActive.Tip()->nHeight + 1): false;
|
||||
}
|
||||
inline uint64_t bytes2uint64(char *array)
|
||||
{
|
||||
uint64_t x =
|
||||
static_cast<uint64_t>(array[0]) & 0x00000000000000ff |
|
||||
static_cast<uint64_t>(array[1]) << 8 & 0x000000000000ff00 |
|
||||
static_cast<uint64_t>(array[2]) << 16 & 0x0000000000ff0000 |
|
||||
static_cast<uint64_t>(array[3]) << 24 & 0x00000000ff000000 |
|
||||
static_cast<uint64_t>(array[4]) << 32 & 0x000000ff00000000 |
|
||||
static_cast<uint64_t>(array[5]) << 40 & 0x0000ff0000000000 |
|
||||
static_cast<uint64_t>(array[6]) << 48 & 0x00ff000000000000 |
|
||||
static_cast<uint64_t>(array[7]) << 56 & 0xff00000000000000;
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // BITCOIN_MAIN_H
|
||||
|
|
306
src/miner.cpp
306
src/miner.cpp
|
@ -40,6 +40,11 @@
|
|||
#endif
|
||||
#include <mutex>
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
#include <fstream>
|
||||
#endif
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -106,6 +111,143 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams,
|
|||
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
|
||||
}
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
CBlockTemplate* CreateNewForkBlock(bool& bFileNotFound)
|
||||
{
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
const int nHeight = pindexPrev->nHeight + 1;
|
||||
|
||||
string utxo_file_path = GetUTXOFileName(nHeight);
|
||||
|
||||
std::ifstream if_utxo(utxo_file_path, std::ios::binary | std::ios::in);
|
||||
if (!if_utxo.is_open()) {
|
||||
bFileNotFound = true;
|
||||
LogPrintf("CreateNewForkBlock(): Cannot open UTXO file - %s\n", utxo_file_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const CChainParams& chainparams = Params();
|
||||
// Create new block
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
|
||||
if(!pblocktemplate.get())
|
||||
return NULL;
|
||||
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
||||
|
||||
// -regtest only: allow overriding block.nVersion with
|
||||
// -blockversion=N to test forking scenarios
|
||||
if (Params().MineBlocksOnDemand())
|
||||
pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
|
||||
|
||||
// Largest block you're willing to create:
|
||||
unsigned int nBlockMaxSize = (unsigned int)(MAX_BLOCK_SIZE-1000);
|
||||
|
||||
// Minimum block size you want to create; block will be filled with free transactions
|
||||
// until there are no more or the block reaches this size:
|
||||
unsigned int nBlockMinSize = DEFAULT_BLOCK_MIN_SIZE;
|
||||
|
||||
uint64_t nBlockSize = 1000;
|
||||
uint64_t nBlockTx = 0;
|
||||
|
||||
while (if_utxo && nBlockTx < forkCBPerBlock) {
|
||||
char term = 0;
|
||||
|
||||
char coin[8] = {};
|
||||
if (!if_utxo.read(coin, 8)) {
|
||||
LogPrintf("CreateNewForkBlock(): UTXO file corrupted? - No more data (Amount)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
char pubkeysize[8] = {};
|
||||
if (!if_utxo.read(pubkeysize, 8)) {
|
||||
LogPrintf("CreateNewForkBlock(): UTXO file corrupted? - Not more data (PubKeyScript size)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
int pbsize = bytes2uint64(pubkeysize);
|
||||
|
||||
//LogPrintf("CreateNewForkBlock():PubKeyScript size = %d\n", pbsize);
|
||||
|
||||
if (pbsize == 0) {
|
||||
LogPrintf("CreateNewForkBlock(): Warning! UTXO file corrupted? PubKeyScript size = 0\n");
|
||||
//but proceed
|
||||
}
|
||||
|
||||
std::unique_ptr<char[]> pubKeyScript(new char[pbsize]);
|
||||
if (!if_utxo.read(&pubKeyScript[0], pbsize)) {
|
||||
LogPrintf("CreateNewForkBlock(): UTXO file corrupted? Not more data (PubKeyScript)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t amount = bytes2uint64(coin);
|
||||
//LogPrintf("CreateNewForkBlock(): txn %u has ammount %u\n", nBlockTx, amount);
|
||||
|
||||
// Add coinbase tx's
|
||||
CMutableTransaction txNew;
|
||||
txNew.vin.resize(1);
|
||||
txNew.vin[0].prevout.SetNull();
|
||||
txNew.vout.resize(1);
|
||||
|
||||
unsigned char* pks = (unsigned char*)pubKeyScript.get();
|
||||
txNew.vout[0].scriptPubKey = CScript(pks, pks+pbsize);
|
||||
|
||||
//LogPrintf("CreateNewForkBlock(): ScriptPubKey: %s\n", txNew.vout[0].scriptPubKey.ToString());
|
||||
|
||||
|
||||
txNew.vout[0].nValue = amount;
|
||||
txNew.vin[0].scriptSig = CScript() << nHeight+nBlockTx << OP_0;
|
||||
|
||||
unsigned int nTxSize = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
|
||||
if (nBlockSize + nTxSize >= nBlockMaxSize)
|
||||
break;//We cannot skip transaction here as in regular case - or we will loose that skipped transaction
|
||||
|
||||
pblock->vtx.push_back(txNew);
|
||||
pblocktemplate->vTxFees.push_back(-1); // updated at end
|
||||
pblocktemplate->vTxSigOps.push_back(-1); // updated at end
|
||||
nBlockSize += nTxSize;
|
||||
++nBlockTx;
|
||||
|
||||
|
||||
if (!if_utxo.read(&term, 1)) {
|
||||
LogPrintf("CreateNewForkBlock(): No more data (record separator)\n");
|
||||
break;
|
||||
}
|
||||
if (term != '\n') {
|
||||
//This maybe not an error, but warning none the less
|
||||
LogPrintf("CreateNewForkBlock(): Warning! No record separator ('0xA') was found\n");
|
||||
if_utxo.seekg(-1, ios_base::cur); //move one char back - if it is not a separator, maybe there is not separators at all
|
||||
}
|
||||
}
|
||||
LogPrintf("CreateNewForkBlock(): %u tnxs and total size %u\n", nBlockTx, nBlockSize);
|
||||
|
||||
// Randomise nonce
|
||||
arith_uint256 nonce = UintToArith256(GetRandHash());
|
||||
// Clear the top and bottom 16 bits (for local use as thread flags and counters)
|
||||
nonce <<= 32;
|
||||
nonce >>= 16;
|
||||
pblock->nNonce = ArithToUint256(nonce);
|
||||
|
||||
// Fill in header
|
||||
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
|
||||
pblock->hashReserved = uint256();
|
||||
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
|
||||
pblock->nBits = 0x207fffff; // Difficulty = 1
|
||||
//0x207fffff -> 0x 7fffff00 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
//alternativly
|
||||
//0x1d00ffff -> 0x 00000000 ffff0000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
// or
|
||||
//0x1f07ffff -> 0x 007fffff 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|
||||
|
||||
pblock->nSolution.clear();
|
||||
pblocktemplate->vTxSigOps[0] = 0; //NO SigOps
|
||||
|
||||
CValidationState state;
|
||||
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false))
|
||||
throw std::runtime_error("CreateNewForkBlock(): TestBlockValidity failed");
|
||||
|
||||
return pblocktemplate.release();
|
||||
}
|
||||
#endif
|
||||
|
||||
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
{
|
||||
const CChainParams& chainparams = Params();
|
||||
|
@ -451,14 +593,20 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
|
|||
static bool ProcessBlockFound(CBlock* pblock)
|
||||
#endif // ENABLE_WALLET
|
||||
{
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (!isNextTipInForkRange()) {
|
||||
#endif
|
||||
LogPrintf("%s\n", pblock->ToString());
|
||||
#ifdef FORK_CB_INPUT
|
||||
}
|
||||
#endif
|
||||
LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
|
||||
|
||||
// Found a solution
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
|
||||
return error("ZcashMiner: generated block is stale");
|
||||
return error("BTCPrivate Miner: generated block is stale");
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
|
@ -476,8 +624,12 @@ static bool ProcessBlockFound(CBlock* pblock)
|
|||
|
||||
// Process this block the same as if we had received it from another node
|
||||
CValidationState state;
|
||||
if (!ProcessNewBlock(state, NULL, pblock, true, NULL))
|
||||
return error("ZcashMiner: ProcessNewBlock, block not accepted");
|
||||
if (!ProcessNewBlock(state, NULL, pblock, true, NULL
|
||||
#ifdef FORK_CB_INPUT
|
||||
, true
|
||||
#endif
|
||||
))
|
||||
return error("BTCPrivate Miner: ProcessNewBlock, block not accepted");
|
||||
|
||||
TrackMinedBlock(pblock->GetHash());
|
||||
|
||||
|
@ -490,9 +642,9 @@ void static BitcoinMiner(CWallet *pwallet)
|
|||
void static BitcoinMiner()
|
||||
#endif
|
||||
{
|
||||
LogPrintf("ZcashMiner started\n");
|
||||
LogPrintf("BTCPrivate Miner started\n");
|
||||
SetThreadPriority(THREAD_PRIORITY_LOWEST);
|
||||
RenameThread("zcash-miner");
|
||||
RenameThread("btcp-miner");
|
||||
const CChainParams& chainparams = Params();
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
|
@ -520,6 +672,10 @@ void static BitcoinMiner()
|
|||
);
|
||||
miningTimer.start();
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
bool bForkModeStarted = false;
|
||||
#endif
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
if (chainparams.MiningRequiresPeers()) {
|
||||
|
@ -539,32 +695,77 @@ void static BitcoinMiner()
|
|||
miningTimer.start();
|
||||
}
|
||||
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
CBlock *pblock = nullptr;
|
||||
unsigned int nTransactionsUpdatedLast = 0;
|
||||
|
||||
//
|
||||
// Create new block
|
||||
//
|
||||
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
unique_ptr<CBlockTemplate> pblocktemplate;
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
bool isNextBlockFork = isForkBlock(pindexPrev->nHeight+1);
|
||||
if (isNextBlockFork) {
|
||||
if (!bForkModeStarted) {
|
||||
LogPrintf("BTCPrivate Miner: switching into fork mode\n");
|
||||
bForkModeStarted = true;
|
||||
}
|
||||
|
||||
bool bFileNotFound = false;
|
||||
pblocktemplate.reset(CreateNewForkBlock(bFileNotFound));
|
||||
if (!pblocktemplate.get()) {
|
||||
if (bFileNotFound) {
|
||||
MilliSleep(1000);
|
||||
continue;
|
||||
} else {
|
||||
LogPrintf("Error in BTCPrivate Miner: Cannot create Fork Block\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
pblock = &pblocktemplate->block;
|
||||
|
||||
n = 48; k = 5;
|
||||
|
||||
LogPrintf("Running BTCPrivate Miner with %u forking transactions in block (%u bytes) and N = %d, K = %d\n", pblock->vtx.size(),
|
||||
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION),
|
||||
n, k);
|
||||
} else {
|
||||
//if not in forking mode and/or provided file is read to the end - exit
|
||||
if (bForkModeStarted) {
|
||||
LogPrintf("BTCPrivate Miner: Fork is done - switching back to regular miner\n");
|
||||
n = chainparams.EquihashN();
|
||||
k = chainparams.EquihashK();
|
||||
bForkModeStarted = false;
|
||||
}
|
||||
#endif
|
||||
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
|
||||
pblocktemplate.reset(CreateNewBlockWithKey(reservekey));
|
||||
#else
|
||||
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey());
|
||||
pblocktemplate.reset(CreateNewBlockWithKey());
|
||||
#endif
|
||||
if (!pblocktemplate.get())
|
||||
{
|
||||
if (GetArg("-mineraddress", "").empty()) {
|
||||
LogPrintf("Error in ZcashMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
|
||||
} else {
|
||||
// Should never reach here, because -mineraddress validity is checked in init.cpp
|
||||
LogPrintf("Error in ZcashMiner: Invalid -mineraddress\n");
|
||||
if (!pblocktemplate.get())
|
||||
{
|
||||
if (GetArg("-mineraddress", "").empty()) {
|
||||
LogPrintf("Error in BTCPrivate Miner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
|
||||
} else {
|
||||
// Should never reach here, because -mineraddress validity is checked in init.cpp
|
||||
LogPrintf("Error in BTCPrivate Miner: Invalid -mineraddress\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
CBlock *pblock = &pblocktemplate->block;
|
||||
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
|
||||
pblock = &pblocktemplate->block;
|
||||
|
||||
LogPrintf("Running ZcashMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
|
||||
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
|
||||
LogPrintf("Running BTCPrivate Miner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
|
||||
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
} //else
|
||||
#endif
|
||||
|
||||
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
|
||||
|
||||
//
|
||||
// Search
|
||||
|
@ -597,24 +798,32 @@ void static BitcoinMiner()
|
|||
solver, pblock->nNonce.ToString());
|
||||
|
||||
std::function<bool(std::vector<unsigned char>)> validBlock =
|
||||
|
||||
[&pblock, &hashTarget, &m_cs, &cancelSolver, &chainparams
|
||||
#ifdef ENABLE_WALLET
|
||||
[&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams]
|
||||
#else
|
||||
[&pblock, &hashTarget, &m_cs, &cancelSolver, &chainparams]
|
||||
, &pwallet, &reservekey
|
||||
#endif
|
||||
(std::vector<unsigned char> soln) {
|
||||
#ifdef FORK_CB_INPUT
|
||||
, &isNextBlockFork
|
||||
#endif
|
||||
] (std::vector<unsigned char> soln) {
|
||||
// Write the solution to the hash and compute the result.
|
||||
LogPrint("pow", "- Checking solution against target\n");
|
||||
pblock->nSolution = soln;
|
||||
solutionTargetChecks.increment();
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (!isNextBlockFork) {
|
||||
#endif
|
||||
if (UintToArith256(pblock->GetHash()) > hashTarget) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
}
|
||||
#endif
|
||||
// Found a solution
|
||||
SetThreadPriority(THREAD_PRIORITY_NORMAL);
|
||||
LogPrintf("ZcashMiner:\n");
|
||||
LogPrintf("BTCPrivate Miner:\n");
|
||||
LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
|
||||
#ifdef ENABLE_WALLET
|
||||
if (ProcessBlockFound(pblock, *pwallet, reservekey)) {
|
||||
|
@ -691,24 +900,39 @@ void static BitcoinMiner()
|
|||
|
||||
// Check for stop or if block needs to be rebuilt
|
||||
boost::this_thread::interruption_point();
|
||||
// Regtest mode doesn't require peers
|
||||
if (vNodes.empty() && chainparams.MiningRequiresPeers())
|
||||
break;
|
||||
if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff)
|
||||
break;
|
||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
|
||||
break;
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (!isNextBlockFork) {
|
||||
#endif
|
||||
// Regtest mode doesn't require peers
|
||||
if (vNodes.empty() && chainparams.MiningRequiresPeers())
|
||||
break;
|
||||
if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff)
|
||||
break;
|
||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
|
||||
break;
|
||||
#ifdef FORK_CB_INPUT
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pindexPrev != chainActive.Tip())
|
||||
break;
|
||||
|
||||
// Update nNonce and nTime
|
||||
pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
|
||||
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
|
||||
if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks)
|
||||
{
|
||||
// Changing pblock->nTime can change work required on testnet:
|
||||
hashTarget.SetCompact(pblock->nBits);
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (!isNextBlockFork) {
|
||||
#endif
|
||||
if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks)
|
||||
{
|
||||
// Changing pblock->nTime can change work required on testnet:
|
||||
hashTarget.SetCompact(pblock->nBits);
|
||||
}
|
||||
#ifdef FORK_CB_INPUT
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -716,14 +940,14 @@ void static BitcoinMiner()
|
|||
{
|
||||
miningTimer.stop();
|
||||
c.disconnect();
|
||||
LogPrintf("ZcashMiner terminated\n");
|
||||
LogPrintf("BTCPrivate Miner terminated\n");
|
||||
throw;
|
||||
}
|
||||
catch (const std::runtime_error &e)
|
||||
{
|
||||
miningTimer.stop();
|
||||
c.disconnect();
|
||||
LogPrintf("ZcashMiner runtime error: %s\n", e.what());
|
||||
LogPrintf("BTCPrivate Miner runtime error: %s\n", e.what());
|
||||
return;
|
||||
}
|
||||
miningTimer.stop();
|
||||
|
|
|
@ -49,4 +49,8 @@ void GenerateBitcoins(bool fGenerate, int nThreads);
|
|||
|
||||
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
CBlockTemplate* CreateNewForkBlock();
|
||||
#endif
|
||||
|
||||
#endif // BITCOIN_MINER_H
|
||||
|
|
10
src/txdb.cpp
10
src/txdb.cpp
|
@ -272,7 +272,11 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
bool CBlockTreeDB::LoadBlockIndexGuts(int64_t forkStart, int64_t forkStop)
|
||||
#else
|
||||
bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||
#endif
|
||||
{
|
||||
boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
|
||||
|
||||
|
@ -311,8 +315,14 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
|||
pindexNew->nStatus = diskindex.nStatus;
|
||||
pindexNew->nTx = diskindex.nTx;
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
if (pindexNew->nHeight < forkStart || pindexNew->nHeight >= forkStop) {
|
||||
#endif
|
||||
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
|
||||
return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());
|
||||
#ifdef FORK_CB_INPUT
|
||||
}
|
||||
#endif
|
||||
|
||||
pcursor->Next();
|
||||
} else {
|
||||
|
|
|
@ -67,7 +67,13 @@ public:
|
|||
bool WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> > &list);
|
||||
bool WriteFlag(const std::string &name, bool fValue);
|
||||
bool ReadFlag(const std::string &name, bool &fValue);
|
||||
|
||||
#ifdef FORK_CB_INPUT
|
||||
bool LoadBlockIndexGuts(int64_t forkStart, int64_t forkStop);
|
||||
#else
|
||||
bool LoadBlockIndexGuts();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // BITCOIN_TXDB_H
|
||||
|
|
Loading…
Reference in New Issue