diff --git a/src/chainparams.cpp b/src/chainparams.cpp index caab5da09..52747833d 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2018 The Bitcoin Private developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -106,7 +107,7 @@ class CMainParams : public CChainParams { // TODO: setup a DNSSeed vSeeds.push_back(CDNSSeedData("btcprivate.org", "dnsseed.btcprivate.org")); vSeeds.push_back(CDNSSeedData("btcprivate.co", "dnsseed.btcprivate.co")); - + // guarantees the first 2 characters, when base58 encoded, are "b1" base58Prefixes[PUBKEY_ADDRESS] = {0x13,0x25}; // guarantees the first 2 characters, when base58 encoded, are "bx" @@ -152,6 +153,10 @@ class CMainParams : public CChainParams { nForkStartHeight = 272991; nForkHeightRange = 5467; + + nEquihashForkHeight = 600001; + nEquihashNnew = 144; + nEquihashKnew = 5; } }; static CMainParams mainParams; @@ -236,6 +241,10 @@ class CTestNetParams : public CMainParams { nForkStartHeight = 10; nForkHeightRange = 300; + + nEquihashForkHeight = 500; + nEquihashNnew = 144; + nEquihashKnew = 5; } }; static CTestNetParams testNetParams; @@ -305,6 +314,10 @@ class CRegTestParams : public CTestNetParams { nForkStartHeight = 0; nForkHeightRange = 0; + + nEquihashForkHeight = 100; + nEquihashNnew = 96; + nEquihashKnew = 5; } }; static CRegTestParams regTestParams; diff --git a/src/chainparams.h b/src/chainparams.h index 653be73d2..9e26f5dbe 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2018 The Bitcoin Private developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,6 +10,7 @@ #include "chainparamsbase.h" #include "checkpoints.h" #include "consensus/params.h" +#include "crypto/equihash.h" #include "primitives/block.h" #include "protocol.h" @@ -62,8 +64,28 @@ class CChainParams bool RequireStandard() const { return fRequireStandard; } int64_t MaxTipAge() const { return nMaxTipAge; } int64_t PruneAfterHeight() const { return nPruneAfterHeight; } - unsigned int EquihashN() const { return nEquihashN; } - unsigned int EquihashK() const { return nEquihashK; } + + unsigned int EquihashN(int height) const + { + if(height >= nEquihashForkHeight) + return nEquihashNnew; + + return nEquihashN; + } + + unsigned int EquihashK(int height) const + { + if(height >= nEquihashForkHeight) + return nEquihashKnew; + + return nEquihashK; + } + + unsigned int EquihashSolutionWidth(int height) const + { + return EhSolutionWidth(EquihashN(height), EquihashK(height)); + } + std::string CurrencyUnits() const { return strCurrencyUnits; } /** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } @@ -80,6 +102,9 @@ class CChainParams uint64_t ForkStartHeight() const { return nForkStartHeight; }; uint64_t ForkHeightRange() const { return nForkHeightRange; }; + + uint64_t EquihashForkHeight() const { return nEquihashForkHeight; }; + protected: CChainParams() {} @@ -108,6 +133,10 @@ class CChainParams uint64_t nForkStartHeight; uint64_t nForkHeightRange; + + uint64_t nEquihashForkHeight; + unsigned int nEquihashNnew; + unsigned int nEquihashKnew; }; /** diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index 814a9f8d5..3610fbc95 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2016 Jack Grigg // Copyright (c) 2016 The Zcash developers +// Copyright (c) 2018 The Bitcoin Private developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -274,6 +275,7 @@ std::vector FullStepRow::GetIndices(size_t len, size_t len } template + bool HasCollision(StepRow& a, StepRow& b, int l) { // This doesn't need to be constant time. @@ -792,6 +794,18 @@ template bool Equihash<200,9>::OptimisedSolve(const eh_HashState& base_state, #endif template bool Equihash<200,9>::IsValidSolution(const eh_HashState& base_state, std::vector soln); +// Explicit instantiations for Equihash<144,5> +template int Equihash<144,5>::InitialiseState(eh_HashState& base_state); +#ifdef ENABLE_MINING +template bool Equihash<144,5>::BasicSolve(const eh_HashState& base_state, + const std::function)> validBlock, + const std::function cancelled); +template bool Equihash<144,5>::OptimisedSolve(const eh_HashState& base_state, + const std::function)> validBlock, + const std::function cancelled); +#endif +template bool Equihash<144,5>::IsValidSolution(const eh_HashState& base_state, std::vector soln); + // Explicit instantiations for Equihash<96,5> template int Equihash<96,5>::InitialiseState(eh_HashState& base_state); #ifdef ENABLE_MINING diff --git a/src/crypto/equihash.h b/src/crypto/equihash.h index 6691844ba..5dcb2eac0 100644 --- a/src/crypto/equihash.h +++ b/src/crypto/equihash.h @@ -1,5 +1,6 @@ // Copyright (c) 2016 Jack Grigg // Copyright (c) 2016 The Zcash developers +// Copyright (c) 2018 The Bitcoin Private developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -199,12 +200,15 @@ static Equihash<96,3> Eh96_3; static Equihash<200,9> Eh200_9; static Equihash<96,5> Eh96_5; static Equihash<48,5> Eh48_5; +static Equihash<144,5> Eh144_5; #define EhInitialiseState(n, k, base_state) \ if (n == 96 && k == 3) { \ Eh96_3.InitialiseState(base_state); \ } else if (n == 200 && k == 9) { \ Eh200_9.InitialiseState(base_state); \ + } else if (n == 144 && k == 5) { \ + Eh144_5.InitialiseState(base_state); \ } else if (n == 96 && k == 5) { \ Eh96_5.InitialiseState(base_state); \ } else if (n == 48 && k == 5) { \ @@ -222,6 +226,8 @@ inline bool EhBasicSolve(unsigned int n, unsigned int k, const eh_HashState& bas return Eh96_3.BasicSolve(base_state, validBlock, cancelled); } else if (n == 200 && k == 9) { return Eh200_9.BasicSolve(base_state, validBlock, cancelled); + } else if (n == 144 && k == 5) { + return Eh144_5.BasicSolve(base_state, validBlock, cancelled); } else if (n == 96 && k == 5) { return Eh96_5.BasicSolve(base_state, validBlock, cancelled); } else if (n == 48 && k == 5) { @@ -246,6 +252,8 @@ inline bool EhOptimisedSolve(unsigned int n, unsigned int k, const eh_HashState& return Eh96_3.OptimisedSolve(base_state, validBlock, cancelled); } else if (n == 200 && k == 9) { return Eh200_9.OptimisedSolve(base_state, validBlock, cancelled); + } else if (n == 144 && k == 5) { + return Eh144_5.OptimisedSolve(base_state, validBlock, cancelled); } else if (n == 96 && k == 5) { return Eh96_5.OptimisedSolve(base_state, validBlock, cancelled); } else if (n == 48 && k == 5) { @@ -268,6 +276,8 @@ inline bool EhOptimisedSolveUncancellable(unsigned int n, unsigned int k, const ret = Eh96_3.IsValidSolution(base_state, soln); \ } else if (n == 200 && k == 9) { \ ret = Eh200_9.IsValidSolution(base_state, soln); \ + } else if (n == 144 && k == 5) { \ + ret = Eh144_5.IsValidSolution(base_state, soln); \ } else if (n == 96 && k == 5) { \ ret = Eh96_5.IsValidSolution(base_state, soln); \ } else if (n == 48 && k == 5) { \ @@ -276,4 +286,24 @@ inline bool EhOptimisedSolveUncancellable(unsigned int n, unsigned int k, const throw std::invalid_argument("Unsupported Equihash parameters"); \ } +inline unsigned int EhSolutionWidth(int n, int k) +{ + unsigned int ret; + if (n == 96 && k == 3) { + ret = Eh96_3.SolutionWidth; + } else if (n == 200 && k == 9) { + ret = Eh200_9.SolutionWidth; + } else if (n == 144 && k == 5) { + ret = Eh144_5.SolutionWidth; + } else if (n == 96 && k == 5) { + ret = Eh96_5.SolutionWidth; + } else if (n == 48 && k == 5) { + ret = Eh48_5.SolutionWidth; + } else { + throw std::invalid_argument("Unsupported Equihash parameters"); + } + + return ret; +} + #endif // BITCOIN_EQUIHASH_H diff --git a/src/main.cpp b/src/main.cpp index a9badef22..3072e9f89 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2018 The Bitcoin Private developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -3107,9 +3108,21 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f REJECT_INVALID, "version-too-low"); // Check Equihash solution is valid - if (fCheckPOW && !CheckEquihashSolution(&block, Params())) - return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"), - REJECT_INVALID, "invalid-solution"); + if (fCheckPOW) { + const CChainParams& chainparams = Params(); + + int oldSize = chainparams.EquihashSolutionWidth(chainparams.EquihashForkHeight()); + int newSize = chainparams.EquihashSolutionWidth(chainparams.EquihashForkHeight() - 1); + + if (block.nSolution.size() != oldSize && block.nSolution.size() != newSize) + return state.DoS(100, error("CheckBlockHeader(): Equihash solution has invalid size have %d need [%d, %d]", + block.nSolution.size(), oldSize, newSize), + REJECT_INVALID, "invalid-solution-size"); + + if (!CheckEquihashSolution(&block, chainparams)) + return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"), + REJECT_INVALID, "invalid-solution"); + } // Check proof of work matches claimed amount if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) @@ -3199,7 +3212,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, return true; } -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev) +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev, bool fCheckPow) { const CChainParams& chainParams = Params(); const Consensus::Params& consensusParams = chainParams.GetConsensus(); @@ -3232,6 +3245,12 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta return state.Invalid(error("%s: block's timestamp is too early", __func__), REJECT_INVALID, "time-too-old"); + // Check that equihash solution has the proper length + if (fCheckPow && block.nSolution.size() != chainParams.EquihashSolutionWidth(nHeight)) + return state.Invalid(error("%s: incorrect equihash solution size have %d need %d", + __func__, block.nSolution.size(), chainParams.EquihashSolutionWidth(nHeight)), + REJECT_INVALID, "equihash-solution-size"); + if (fCheckpointsEnabled) { // Don't accept any forks from the main chain prior to last checkpoint @@ -3546,7 +3565,7 @@ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex auto verifier = libzcash::ProofVerifier::Disabled(); // NOTE: CheckBlockHeader is called by CheckBlock - if (!ContextualCheckBlockHeader(block, state, pindexPrev)) + if (!ContextualCheckBlockHeader(block, state, pindexPrev, fCheckPOW)) return false; if (!CheckBlock(block, state, verifier, fCheckPOW, fCheckMerkleRoot)) diff --git a/src/main.h b/src/main.h index 5525dc72b..ba20b8b09 100644 --- a/src/main.h +++ b/src/main.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2018 The Bitcoin Private developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -429,7 +430,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true); /** Context-dependent validity checks */ -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev); +bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev, bool fCheckPow = true); bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); /** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ diff --git a/src/miner.cpp b/src/miner.cpp index e2e3c23e4..05dda695c 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2018 The Bitcoin Private developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -692,8 +693,8 @@ void static BitcoinMiner() // Each thread has its own counter unsigned int nExtraNonce = 0; - unsigned int n = chainparams.EquihashN(); - unsigned int k = chainparams.EquihashK(); + unsigned int n; + unsigned int k; std::string solver = GetArg("-equihashsolver", "default"); assert(solver == "tromp" || solver == "default"); @@ -740,6 +741,9 @@ void static BitcoinMiner() // unique_ptr pblocktemplate; + n = chainparams.EquihashN(pindexPrev->nHeight + 1); + k = chainparams.EquihashK(pindexPrev->nHeight + 1); + bool isNextBlockFork = isForkBlock(pindexPrev->nHeight+1); if (isNextBlockFork) { diff --git a/src/pow.cpp b/src/pow.cpp index d5a41c6db..3bc23cce1 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2018 The Bitcoin Private developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -105,8 +106,20 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, bool CheckEquihashSolution(const CBlockHeader *pblock, const CChainParams& params) { - unsigned int n = params.EquihashN(); - unsigned int k = params.EquihashK(); + uint64_t forkHeight = params.EquihashForkHeight(); + unsigned int solution_size = pblock->nSolution.size(); + + unsigned int n; + unsigned int k; + if (solution_size == params.EquihashSolutionWidth(forkHeight)) { + n = params.EquihashN(forkHeight); + k = params.EquihashK(forkHeight); + } else if (forkHeight > 0 && solution_size == params.EquihashSolutionWidth(forkHeight - 1)) { + n = params.EquihashN(forkHeight - 1); + k = params.EquihashK(forkHeight - 1); + } else { + return error("CheckEquihashsolution(): invalid solution size"); + } // Hash state crypto_generichash_blake2b_state state; diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 581a3b938..4938bbe43 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2018 The Bitcoin Private developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -202,10 +203,15 @@ UniValue generate(const UniValue& params, bool fHelp) } unsigned int nExtraNonce = 0; UniValue blockHashes(UniValue::VARR); - unsigned int n = Params().EquihashN(); - unsigned int k = Params().EquihashK(); + const CChainParams& chainparams = Params(); + unsigned int n; + unsigned int k; + while (nHeight < nHeightEnd) { + n = chainparams.EquihashN(nHeight + 1); + k = chainparams.EquihashK(nHeight + 1); + #ifdef ENABLE_WALLET std::unique_ptr pblocktemplate(CreateNewBlockWithKey(reservekey)); #else diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 86fe5de3f..12f078da9 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -138,8 +138,9 @@ double benchmark_solve_equihash() CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << I; - unsigned int n = Params(CBaseChainParams::MAIN).EquihashN(); - unsigned int k = Params(CBaseChainParams::MAIN).EquihashK(); + const CChainParams& params = Params(CBaseChainParams::MAIN); + unsigned int n = params.EquihashN(params.EquihashForkHeight()); + unsigned int k = params.EquihashK(params.EquihashForkHeight()); crypto_generichash_blake2b_state eh_state; EhInitialiseState(n, k, eh_state); crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size()); @@ -404,4 +405,3 @@ double benchmark_connectblock_slow() return duration; } -