diff --git a/configure.ac b/configure.ac index cc6e5dd..5720c2a 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 1) define(_CLIENT_VERSION_MINOR, 2) -define(_CLIENT_VERSION_REVISION, 2) +define(_CLIENT_VERSION_REVISION, 3) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2019) diff --git a/share/genbuild.sh b/share/genbuild.sh index eebeb04..a0a7764 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -18,7 +18,7 @@ SUFFIX="" LAST_COMMIT_DATE="" if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then # clean 'dirty' status of touched files that haven't been modified - git diff >/dev/null 2>/dev/null + git diff >/dev/null 2>/dev/null # if latest commit is tagged and not dirty, then override using the tag name RAWDESC=$(git describe --abbrev=0 2>/dev/null) @@ -28,7 +28,7 @@ if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/ # otherwise generate suffix from git, i.e. string like "59887e8-dirty" SUFFIX=$(git rev-parse --short HEAD) - git diff-index --quiet HEAD -- || SUFFIX="$SUFFIX-dirty" + git diff-index --quiet HEAD -- || SUFFIX="$SUFFIX-" # get a string like "2012-04-10 16:27:19 +0200" LAST_COMMIT_DATE="$(git log -n 1 --format="%ci")" @@ -48,4 +48,4 @@ if [ "$INFO" != "$NEWINFO" ]; then if [ -n "$LAST_COMMIT_DATE" ]; then echo "#define BUILD_DATE \"$LAST_COMMIT_DATE\"" >> "$FILE" fi -fi \ No newline at end of file +fi diff --git a/src/config/mnpcoin-config.h b/src/config/mnpcoin-config.h index b3ecadb..d6a0c74 100644 --- a/src/config/mnpcoin-config.h +++ b/src/config/mnpcoin-config.h @@ -21,7 +21,7 @@ #define CLIENT_VERSION_MINOR 2 /* Build revision */ -#define CLIENT_VERSION_REVISION 2 +#define CLIENT_VERSION_REVISION 3 /* Version is release */ #define COPYRIGHT_YEAR 2019 @@ -274,7 +274,7 @@ #define PACKAGE_NAME "MNPCoin Core" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "MNPCoin Core 1.0.0" +#define PACKAGE_STRING "MNPCoin Core 1.2.3" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "mnpcoin" @@ -283,7 +283,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.0.0" +#define PACKAGE_VERSION "1.2.3" /* Define to necessary symbol if this constant uses a non-standard name on your system. */ diff --git a/src/init.cpp b/src/init.cpp index 08491f9..ef23084 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -525,6 +525,10 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-rpcsslprivatekeyfile=", strprintf(_("Server private key (default: %s)"), "server.pem")); strUsage += HelpMessageOpt("-rpcsslciphers=", strprintf(_("Acceptable ciphers (default: %s)"), "TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH")); + strUsage += HelpMessageOpt("-blockspamfilter=", strprintf(_("Use block spam filter (default: %u)"), DEFAULT_BLOCK_SPAM_FILTER)); + strUsage += HelpMessageOpt("-blockspamfiltermaxsize=", strprintf(_("Maximum size of the list of indexes in the block spam filter (default: %u)"), DEFAULT_BLOCK_SPAM_FILTER_MAX_SIZE)); + strUsage += HelpMessageOpt("-blockspamfiltermaxavg=", strprintf(_("Maximum average size of an index occurrence in the block spam filter (default: %u)"), DEFAULT_BLOCK_SPAM_FILTER_MAX_AVG)); + return strUsage; } diff --git a/src/main.cpp b/src/main.cpp index 10137d9..640e6f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers // Copyright (c) 2014-2015 The Dash developers -// Copyright (c) 2015-2017 The PIVX developers +// Copyright (c) 2015-2019 The PIVX developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -63,7 +63,6 @@ CCriticalSection cs_main; BlockMap mapBlockIndex; map mapProofOfStake; -map mapStakeSpent; set > setStakeSeen; map mapHashedBlocks; CChain chainActive; @@ -200,7 +199,84 @@ struct CBlockReject { uint256 hashBlock; }; -/** + +class CNodeBlocks +{ +public: + CNodeBlocks(): + maxSize(0), + maxAvg(0) + { + maxSize = GetArg("-blockspamfiltermaxsize", DEFAULT_BLOCK_SPAM_FILTER_MAX_SIZE); + maxAvg = GetArg("-blockspamfiltermaxavg", DEFAULT_BLOCK_SPAM_FILTER_MAX_AVG); + } + + bool onBlockReceived(int nHeight) { + if(nHeight > 0 && maxSize && maxAvg) { + addPoint(nHeight); + return true; + } + return false; + } + + bool updateState(CValidationState& state, bool ret) + { + // No Blocks + size_t size = points.size(); + if(size == 0) + return ret; + + // Compute the number of the received blocks + size_t nBlocks = 0; + for(auto point : points) + { + nBlocks += point.second; + } + + // Compute the average value per height + double nAvgValue = (double)nBlocks / size; + + // Ban the node if try to spam + bool banNode = (nAvgValue >= 1.5 * maxAvg && size >= maxAvg) || + (nAvgValue >= maxAvg && nBlocks >= maxSize) || + (nBlocks >= maxSize * 3); + if(banNode) + { + // Clear the points and ban the node + points.clear(); + return state.DoS(100, error("block-spam ban node for sending spam")); + } + + return ret; + } + +private: + void addPoint(int height) + { + // Remove the last element in the list + if(points.size() == maxSize) + { + points.erase(points.begin()); + } + + // Add the point to the list + int occurrence = 0; + auto mi = points.find(height); + if (mi != points.end()) + occurrence = (*mi).second; + occurrence++; + points[height] = occurrence; + } + +private: + std::map points; + size_t maxSize; + size_t maxAvg; +}; + + + + /** * Maintain validation-specific state about nodes, protected by cs_main, instead * by CNode's own locks. This simplifies asynchronous operation, where * processing of incoming data is done after the ProcessMessage call returns, @@ -238,6 +314,8 @@ struct CNodeState { //! Whether this peer wants invs or headers (when possible) for block announcements. bool fPreferHeaders; + CNodeBlocks nodeBlocks; + CNodeState() { fCurrentlyConnected = false; @@ -2740,10 +2818,6 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex if (coins->vout.size() < out.n + 1) coins->vout.resize(out.n + 1); coins->vout[out.n] = undo.txout; - - // erase the spent input - if(IsSporkActive(SPORK_17_FAKE_STAKE_FIX) && block.GetBlockTime() >= GetSporkValue(SPORK_17_FAKE_STAKE_FIX)) - mapStakeSpent.erase(out); } } } @@ -3315,27 +3389,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!pblocktree->WriteTxIndex(vPos)) return state.Abort("Failed to write transaction index"); - if(IsSporkActive(SPORK_17_FAKE_STAKE_FIX) && block.GetBlockTime() >= GetSporkValue(SPORK_17_FAKE_STAKE_FIX)){ - // add new entries - for (const CTransaction tx:block.vtx) { - if (tx.IsCoinBase()) - continue; - for (const CTxIn in: tx.vin) { - LogPrint("map", "mapStakeSpent: Insert %s | %u\n", in.prevout.ToString(), pindex->nHeight); - mapStakeSpent.insert(std::make_pair(in.prevout, pindex->nHeight)); - } - } - - // delete old entries - for (auto it = mapStakeSpent.begin(); it != mapStakeSpent.end();) { - if (it->second < pindex->nHeight - Params().MaxReorganizationDepth()) { - LogPrint("map", "mapStakeSpent: Erase %s | %u\n", it->first.ToString(), it->second); - it = mapStakeSpent.erase(it); - } else { - it++; - } - } - } // add this block to the view's block chain view.SetBestBlock(pindex->GetBlockHash()); @@ -4591,57 +4644,183 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, } int nHeight = pindex->nHeight; + int splitHeight = -1; if(IsSporkActive(SPORK_17_FAKE_STAKE_FIX) && block.GetBlockTime() >= GetSporkValue(SPORK_17_FAKE_STAKE_FIX)) { if (block.IsProofOfStake()) { LOCK(cs_main); - CCoinsViewCache coins(pcoinsTip); + // Blocks arrives in order, so if prev block is not the tip then we are on a fork. + // Extra info: duplicated blocks are skipping this checks, so we don't have to worry about those here. + bool isBlockFromFork = pindexPrev != nullptr && chainActive.Tip() != pindexPrev; - if (!coins.HaveInputs(block.vtx[1])) { - // the inputs are spent at the chain tip so we should look at the recently spent outputs + // Coin stake + CTransaction &stakeTxIn = block.vtx[1]; - for (CTxIn in : block.vtx[1].vin) { - auto it = mapStakeSpent.find(in.prevout); - if (it == mapStakeSpent.end()) { - return false; - } - if (it->second <= pindexPrev->nHeight) { - return false; + // Inputs + std::vector mnpInputs; + std::vector zMNPInputs; + + for (CTxIn stakeIn : stakeTxIn.vin) { + if(stakeIn.scriptSig.IsZerocoinSpend()){ + zMNPInputs.push_back(stakeIn); + }else{ + mnpInputs.push_back(stakeIn); + } + } + const bool hasMNPInputs = !mnpInputs.empty(); + const bool hasZMNPInputs = !zMNPInputs.empty(); + + // ZC started after PoS. + // Check for serial double spent on the same block, TODO: Move this to the proper method.. + + vector inBlockSerials; + for (CTransaction tx : block.vtx) { + for (CTxIn in: tx.vin) { + if(nHeight >= Params().Zerocoin_StartHeight()) { + if (in.scriptSig.IsZerocoinSpend()) { + CoinSpend spend = TxInToZerocoinSpend(in); + // Check for serials double spending in the same block + if (std::find(inBlockSerials.begin(), inBlockSerials.end(), spend.getCoinSerialNumber()) != + inBlockSerials.end()) { + return state.DoS(100, error("%s: serial double spent on the same block", __func__)); + } + inBlockSerials.push_back(spend.getCoinSerialNumber()); + } } + if(tx.IsCoinStake()) continue; + if(hasMNPInputs) + // Check if coinstake input is double spent inside the same block + for (CTxIn mnpIn : mnpInputs){ + if(mnpIn.prevout == in.prevout){ + // double spent coinstake input inside block + return error("%s: double spent coinstake input inside block", __func__); + } + } } } + inBlockSerials.clear(); - // if this is on a fork - if (!chainActive.Contains(pindexPrev) && pindexPrev != NULL) { + // Check whether is a fork or not + if (isBlockFromFork) { // start at the block we're adding on to - CBlockIndex *last = pindexPrev; - - //while that block is not on the main chain - while (!chainActive.Contains(last) && pindexPrev != NULL) { - CBlock bl; - ReadBlockFromDisk(bl, last); - // loop through every spent input from said block - for (CTransaction t: bl.vtx) { + CBlockIndex *prev = pindexPrev; + + int readBlock = 0; + vector vBlockSerials; + CBlock bl; + // Go backwards on the forked chain up to the split + do { + // Check if the forked chain is longer than the max reorg limit + if(readBlock == Params().MaxReorganizationDepth()){ + // TODO: Remove this chain from disk. + return error("%s: forked chain longer than maximum reorg limit", __func__); + } + + if(!ReadBlockFromDisk(bl, prev)) + // Previous block not on disk + return error("%s: previous block %s not on disk", __func__, prev->GetBlockHash().GetHex()); + // Increase amount of read blocks + readBlock++; + // Loop through every input from said block + for (CTransaction t : bl.vtx) { for (CTxIn in: t.vin) { - // loop through every spent input in the staking transaction of the new block - for (CTxIn stakeIn: block.vtx[1].vin) { - // if they spend the same input - if (stakeIn.prevout == in.prevout) { - //reject the block - return false; + // Loop through every input of the staking tx + for (CTxIn stakeIn : mnpInputs) { + // if it's already spent + + // First regular staking check + if(hasMNPInputs) { + if (stakeIn.prevout == in.prevout) { + return state.DoS(100, error("%s: input already spent on a previous block", __func__)); + } + } + // Second, if there is zPoS staking then store the serials for later check + if(hasZMNPInputs) { + if(in.scriptSig.IsZerocoinSpend()){ + vBlockSerials.push_back(TxInToZerocoinSpend(in).getCoinSerialNumber()); + } } } } } - // go to the parent block - last = pindexPrev->pprev; - } - } - } - } + prev = prev->pprev; + + } while (!chainActive.Contains(prev)); + + // Split height + splitHeight = prev->nHeight; + + // Now that this loop if completed. Check if we have zMNP inputs. + // if(hasZMNPInputs){ + // + // for (CTxIn zMnpInput : zMNPInputs) { + // CoinSpend spend = TxInToZerocoinSpend(zMnpInput); + // + // // First check if the serials were not already spent on the forked blocks. + // CBigNum coinSerial = spend.getCoinSerialNumber(); + // for(CBigNum serial : vBlockSerials){ + // if(serial == coinSerial){ + // return state.DoS(100, error("%s: serial double spent on fork", __func__)); + // } + // } + // // Now check if the serial exists before the chain split. + // int nHeightTx = 0; + // if (IsSerialInBlockchain(spend.getCoinSerialNumber(), nHeightTx)){ + // // if the height is nHeightTx > chainSplit means that the spent occurred after the chain split + // if(nHeightTx <= splitHeight){ + // return state.DoS(100, error("%s: serial double spent on main chain", __func__)); + // } + // } + // + // // if (!ContextualCheckZerocoinSpendNoSerialCheck(stakeTxIn, spend, pindex, 0)) + // // return state.DoS(100,error("%s: ContextualCheckZerocoinSpend failed for tx %s", __func__, + // // stakeTxIn.GetHash().GetHex()), REJECT_INVALID, "bad-txns-invalid-zmnp"); + // + // // Now only the ZKP left.. + // // As the spend maturity is 200, the acc value must be accumulated, otherwise it's not ready to be spent + // CBigNum bnAccumulatorValue = 0; + // if (!zerocoinDB->ReadAccumulatorValue(spend.getAccumulatorChecksum(), bnAccumulatorValue)) { + // return state.DoS(100, error("%s: stake zerocoinspend not ready to be spent", __func__)); + // } + // + // Accumulator accumulator(Params().Zerocoin_Params(chainActive.Height() < Params().Zerocoin_StartHeight()), + // spend.getDenomination(), bnAccumulatorValue); + // + // // Check that the coinspend is valid + // if(!spend.Verify(accumulator)) + // return state.DoS(100, error("%s: zerocoin spend did not verify", __func__)); + // + // } // zMNPInputs loop + // + // } // hasZMNPInputs + + } // isBlockFromFork + + // If the stake is not a zPoS then let's check if the inputs were spent on the main chain + const CCoinsViewCache coins(pcoinsTip); + if(!stakeTxIn.IsZerocoinSpend()) { + for (CTxIn in: stakeTxIn.vin) { + const CCoins* coin = coins.AccessCoins(in.prevout.hash); + + if(!coin && !isBlockFromFork){ + // No coins on the main chain + return error("%s: coin stake inputs not available on main chain, received height %d vs current %d", __func__, nHeight, chainActive.Height()); + } + if(coin && !coin->IsAvailable(in.prevout.n)){ + // If this is not available get the height of the spent and validate it with the forked height + // Check if this occurred before the chain split + if(!(isBlockFromFork && coin->nHeight > splitHeight)){ + // Coins not available + return error("%s: coin stake inputs already spent in main chain", __func__); + } + } + } + } + } // isPoS + } // SPORK_17_FAKE_STAKE_FIX // Write block to history file try { @@ -4775,14 +4954,33 @@ bool ProcessNewBlock(CValidationState& state, CNode* pfrom, CBlock* pblock, CDis } // Store to disk - CBlockIndex* pindex = NULL; + CBlockIndex* pindex = nullptr; bool ret = AcceptBlock (*pblock, state, &pindex, dbp, checked); if (pindex && pfrom) { mapBlockSource[pindex->GetBlockHash ()] = pfrom->GetId (); } CheckBlockIndex (); - if (!ret) - return error ("%s : AcceptBlock FAILED", __func__); + if (!ret) { + // Check spamming + if(pindex && pfrom && GetBoolArg("-blockspamfilter", DEFAULT_BLOCK_SPAM_FILTER)) { + CNodeState *nodestate = State(pfrom->GetId()); + if(nodestate != nullptr) { + nodestate->nodeBlocks.onBlockReceived(pindex->nHeight); + bool nodeStatus = true; + // UpdateState will return false if the node is attacking us or update the score and return true. + nodeStatus = nodestate->nodeBlocks.updateState(state, nodeStatus); + int nDoS = 0; + if (state.IsInvalid(nDoS)) { + if (nDoS > 0) + Misbehaving(pfrom->GetId(), nDoS); + nodeStatus = false; + } + if (!nodeStatus) + return error("%s : AcceptBlock FAILED - block spam protection", __func__); + } + } + return error("%s : AcceptBlock FAILED", __func__); + } // !ret } if (!ActivateBestChain(state, pblock, checked)) diff --git a/src/main.h b/src/main.h index 5faebca..7d6f04c 100644 --- a/src/main.h +++ b/src/main.h @@ -1,7 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers // Copyright (c) 2014-2015 The Dash developers -// Copyright (c) 2015-2017 The PIVX developers +// Copyright (c) 2015-2019 The PIVX developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -110,6 +110,13 @@ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; /** Enable bloom filter */ static const bool DEFAULT_PEERBLOOMFILTERS = true; +/** Default for -blockspamfilter, use header spam filter */ +static const bool DEFAULT_BLOCK_SPAM_FILTER = true; +/** Default for -blockspamfiltermaxsize, maximum size of the list of indexes in the block spam filter */ +static const unsigned int DEFAULT_BLOCK_SPAM_FILTER_MAX_SIZE = COINBASE_MATURITY; +/** Default for -blockspamfiltermaxavg, maximum average size of an index occurrence in the block spam filter */ +static const unsigned int DEFAULT_BLOCK_SPAM_FILTER_MAX_AVG = 10; + /** "reject" message codes */ static const unsigned char REJECT_MALFORMED = 0x01; static const unsigned char REJECT_INVALID = 0x10; @@ -183,11 +190,11 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals); /** Unregister a network node */ void UnregisterNodeSignals(CNodeSignals& nodeSignals); -/** +/** * Process an incoming block. This only returns after the best known valid * block is made active. Note that it does not, however, guarantee that the * specific block passed to it has been checked for validity! - * + * * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation. * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. * @param[in] pblock The block we want to process. @@ -311,7 +318,7 @@ bool MoneyRange(CAmount nValueOut); /** * Check transaction inputs, and make sure any * pay-to-script-hash transactions are evaluating IsStandard scripts - * + * * Why bother? To avoid denial-of-service attacks; an attacker * can submit a standard HASH... OP_EQUAL transaction, * which will get accepted into blocks. The redemption @@ -320,14 +327,14 @@ bool MoneyRange(CAmount nValueOut); * DUP CHECKSIG DROP ... repeated 100 times... OP_1 */ -/** +/** * Check for standard transaction types * @param[in] mapInputs Map of previous transactions that have outputs we're spending * @return True if all inputs (scriptSigs) use only standard transaction forms */ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); -/** +/** * Count ECDSA signature operations the old-fashioned (pre-0.6) way * @return number of sigops this transaction's outputs will produce when spent * @see CTransaction::FetchInputs @@ -336,7 +343,7 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx); /** * Count ECDSA signature operations in pay-to-script-hash inputs. - * + * * @param[in] mapInputs Map of previous transactions that have outputs we're spending * @return maximum number of sigops required to validate this transaction's inputs * @see CTransaction::FetchInputs @@ -415,9 +422,9 @@ class CBlockUndo }; -/** +/** * Closure representing one script verification - * Note that this stores references to the spending transaction + * Note that this stores references to the spending transaction */ class CScriptCheck { diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 5c01221..3d4041e 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -254,7 +254,7 @@ void OverviewPage::setBalance(const CAmount& balance, const CAmount& unconfirmed // Adjust bubble-help according to AutoMint settings // QString automintHelp = tr("Current percentage of zMNP.\nIf AutoMint is enabled this percentage will settle around the configured AutoMint percentage (default = 10%).\n"); -// bool fEnableZeromint = GetBoolArg("-enablezeromint", true); +// bool fEnableZeromint = GetBoolArg("-enablezeromint", false); // int nZeromintPercentage = GetArg("-zeromintpercentage", 10); // if (fEnableZeromint) { // automintHelp += tr("AutoMint is currently enabled and set to ") + QString::number(nZeromintPercentage) + "%.\n"; diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index b4a078a..076a3d9 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -28,7 +28,7 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle* networkStyle) { // set reference point, paddings int paddingLeft = 14; - int paddingTop = 470; + int paddingTop = 450; int titleVersionVSpace = 17; int titleCopyrightVSpace = 32; @@ -40,8 +40,8 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle* networkStyle) QString copyrightTextBtc = QChar(0xA9) + QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers")); QString copyrightTextDash = QChar(0xA9) + QString(" 2014-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Dash Core developers")); QString copyrightTextPIVX = QChar(0xA9) + QString(" 2015-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The PIVX Core developers")); - QString copyrightTextWagerr = QChar(0xA9) + QString(" %1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Wagerr Core developers")); - QString copyrightTextMNPCoin = QChar(0xA9) + QString(" %1 ").arg(COPYRIGHT_YEAR) + QString(tr("The MNPCoin Core developers")); + QString copyrightTextWagerr = QChar(0xA9) + QString(" 2018-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Wagerr Core developers")); + QString copyrightTextMNPCoin = QChar(0xA9) + QString(" 2018-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The MNPCoin Core developers")); QString titleAddText = networkStyle->getTitleAddText(); QString font = QApplication::font().toString(); diff --git a/src/util.cpp b/src/util.cpp index 17ae098..0f22175 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -115,7 +115,7 @@ bool fLiteMode = false; bool fEnableSwiftTX = true; int nSwiftTXDepth = 5; // Automatic Zerocoin minting -bool fEnableZeromint = true; +bool fEnableZeromint = false; int nZeromintPercentage = 10; int nPreferredDenom = 0; const int64_t AUTOMINT_DELAY = (60 * 5); // Wait at least 5 minutes until Automint starts diff --git a/src/version.h b/src/version.h index 96b5212..b615cc3 100644 --- a/src/version.h +++ b/src/version.h @@ -11,7 +11,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 70020; +static const int PROTOCOL_VERSION = 70030; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; @@ -20,8 +20,8 @@ static const int INIT_PROTO_VERSION = 209; static const int GETHEADERS_VERSION = 70000; //! disconnect from peers older than this proto version -static const int MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT = 70010; -static const int MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT = 70020; +static const int MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT = 70020; +static const int MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT = 70030; //! nTime field added to CAddress, starting with this version; //! if possible, avoid requesting addresses nodes older than this