From 414eda99e6468159e2388da97abf5c9f1d00e9a1 Mon Sep 17 00:00:00 2001 From: Ahmed Hilali Date: Tue, 17 Sep 2019 18:21:03 +0700 Subject: [PATCH 1/6] rm nonce, coinstakeAmount and coinstakePrevout --- src/bench/duplicate_inputs.cpp | 4 +-- src/chain.cpp | 2 +- src/chain.h | 6 ----- src/chainparams.cpp | 34 +++++++------------------ src/chainparams.h | 2 +- src/consensus/params.h | 11 +++----- src/miner.cpp | 7 +++-- src/net_processing.cpp | 15 +++++------ src/pos.cpp | 38 ++++++++-------------------- src/pos_kernel.cpp | 22 +++++++--------- src/pos_kernel.h | 7 +++-- src/pow.cpp | 30 +++++++++++----------- src/pow.h | 4 +-- src/primitives/block.cpp | 4 +-- src/primitives/block.h | 15 ++++------- src/qt/bitcoingui.cpp | 2 +- src/qt/modaloverlay.cpp | 6 ++--- src/qt/sendcoinsdialog.cpp | 2 +- src/rpc/blockchain.cpp | 4 +-- src/rpc/mining.cpp | 14 ++++------ src/test/blockencodings_tests.cpp | 4 +-- src/test/blockfilter_index_tests.cpp | 2 +- src/test/denialofservice_tests.cpp | 2 +- src/test/miner_tests.cpp | 2 +- src/test/pow_tests.cpp | 10 ++++---- src/test/setup_common.cpp | 2 +- src/test/util.cpp | 8 +++--- src/test/validation_block_tests.cpp | 6 ++--- src/txdb.cpp | 1 - src/validation.cpp | 4 +-- 30 files changed, 103 insertions(+), 167 deletions(-) diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index 2440341287..746520499c 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -28,8 +28,8 @@ static void DuplicateInputs(benchmark::State& state) LOCK(cs_main); CBlockIndex* pindexPrev = ::ChainActive().Tip(); assert(pindexPrev != nullptr); - block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus()); - block.nNonce = 0; + block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus().pos); + // block.nNonce = 0; auto nHeight = pindexPrev->nHeight + 1; // Make a coinbase TX diff --git a/src/chain.cpp b/src/chain.cpp index 5520d8149a..4077220660 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -144,7 +144,7 @@ int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& fr r = from.nChainWork - to.nChainWork; sign = -1; } - r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip); + r = r * arith_uint256(params.pos.nTargetSpacing) / GetBlockProof(tip); if (r.bits() > 63) { return sign * std::numeric_limits::max(); } diff --git a/src/chain.h b/src/chain.h index 26c303c38d..e5f08c3f3b 100644 --- a/src/chain.h +++ b/src/chain.h @@ -181,7 +181,6 @@ class CBlockIndex uint256 hashMerkleRoot; uint32_t nTime; uint32_t nBits; - uint32_t nNonce; boost::optional proofOfStakeBody; // proof-of-stake specific fields @@ -217,7 +216,6 @@ class CBlockIndex hashMerkleRoot = uint256(); nTime = 0; nBits = 0; - nNonce = 0; } CBlockIndex() @@ -233,7 +231,6 @@ class CBlockIndex hashMerkleRoot = block.hashMerkleRoot; nTime = block.nTime; nBits = block.nBits; - nNonce = block.nNonce; stakeModifier = block.stakeModifier; proofOfStakeBody = block.proofOfStakeBody; } @@ -265,7 +262,6 @@ class CBlockIndex block.hashMerkleRoot = hashMerkleRoot; block.nTime = nTime; block.nBits = nBits; - block.nNonce = nNonce; block.stakeModifier = stakeModifier; block.proofOfStakeBody = proofOfStakeBody; return block; @@ -406,7 +402,6 @@ class CDiskBlockIndex : public CBlockIndex READWRITE(hashMerkleRoot); READWRITE(nTime); READWRITE(nBits); - READWRITE(nNonce); } uint256 GetBlockHash() const @@ -417,7 +412,6 @@ class CDiskBlockIndex : public CBlockIndex block.hashMerkleRoot = hashMerkleRoot; block.nTime = nTime; block.nBits = nBits; - block.nNonce = nNonce; block.stakeModifier = stakeModifier; block.proofOfStakeBody = proofOfStakeBody; return block.GetHash(); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ec66a23226..56aa3c3e64 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -17,7 +17,7 @@ #include #include -static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) +static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { CMutableTransaction txNew; txNew.nVersion = 1; @@ -30,7 +30,6 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi CBlock genesis; genesis.nTime = nTime; genesis.nBits = nBits; - genesis.nNonce = nNonce; genesis.nVersion = nVersion; genesis.vtx.push_back(MakeTransactionRef(std::move(txNew))); genesis.hashPrevBlock.SetNull(); @@ -43,17 +42,17 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi * transaction cannot be spent since 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) + * CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, 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 */ -static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) +static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; const CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; - return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward); + return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nBits, nVersion, genesisReward); } /** @@ -82,13 +81,8 @@ class CMainParams : public CChainParams { consensus.CSVHeight = 419328; // 000000000000000004a1b34462cb8aeebd5799177f7a29cf28f2d1961716b5b5 consensus.SegwitHeight = 481824; // 0000000000000000001c8018d9cb3b742ef25114f27563e3fc4a1902167f9893 - consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks - consensus.nPowTargetSpacing = 10 * 60; - consensus.fPowAllowMinDifficultyBlocks = false; - consensus.fPowNoRetargeting = false; consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016 - consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing + consensus.nMinerConfirmationWindow = 2016; // nTargetTimespan / nTargetSpacing consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008 @@ -113,7 +107,7 @@ class CMainParams : public CChainParams { m_assumed_blockchain_size = 240; m_assumed_chain_state_size = 3; - genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN); + genesis = CreateGenesisBlock(1231006505, 2083236893, 1, 50 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); @@ -199,13 +193,8 @@ class CTestNetParams : public CChainParams { consensus.CSVHeight = 770112; // 00000000025e930139bac5c6c31a403776da130831ab85be56578f3fa75369bb consensus.SegwitHeight = 834624; // 00000000002b980fcd729daaa248fd9316a5200e9b367f4ff2c42453e84201ca - consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks - consensus.nPowTargetSpacing = 10 * 60; - consensus.fPowAllowMinDifficultyBlocks = true; - consensus.fPowNoRetargeting = false; consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains - consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing + consensus.nMinerConfirmationWindow = 2016; // nTargetTimespan / nTargetSpacing consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008 @@ -225,7 +214,7 @@ class CTestNetParams : public CChainParams { m_assumed_blockchain_size = 30; m_assumed_chain_state_size = 2; - genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN); + genesis = CreateGenesisBlock(1296688602, 414098458, 1, 50 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); assert(consensus.hashGenesisBlock == uint256S("0x000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")); assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); @@ -293,11 +282,6 @@ class CRegTestParams : public CChainParams { consensus.CSVHeight = 432; // CSV activated on regtest (Used in rpc activation tests) consensus.SegwitHeight = 0; // SEGWIT is always activated on regtest unless overridden - consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks - consensus.nPowTargetSpacing = 10 * 60; - consensus.fPowAllowMinDifficultyBlocks = true; - consensus.fPowNoRetargeting = true; consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016) consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; @@ -321,7 +305,7 @@ class CRegTestParams : public CChainParams { UpdateActivationParametersFromArgs(args); - genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN); + genesis = CreateGenesisBlock(1296688602, 2, 1, 50 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")); assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); diff --git a/src/chainparams.h b/src/chainparams.h index 8f1d27e03c..90e94c6102 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -74,7 +74,7 @@ class CChainParams /** Minimum free space (in GB) needed for data directory when pruned; Does not include prune target*/ uint64_t AssumedChainStateSize() const { return m_assumed_chain_state_size; } /** Whether it is possible to mine blocks on demand (no retargeting) */ - bool MineBlocksOnDemand() const { return consensus.fPowNoRetargeting; } + bool MineBlocksOnDemand() const { return consensus.pos.fNoRetargeting; } /** Return the BIP70 network string (main, test or regtest) */ std::string NetworkIDString() const { return strNetworkID; } /** Return the list of hostnames to look up for DNS seeds */ diff --git a/src/consensus/params.h b/src/consensus/params.h index c903b48a1d..b969d557ef 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -64,6 +64,7 @@ struct Params { * BIP 16 exception blocks. */ int SegwitHeight; + /** Proof of stake parameters */ struct PoS { uint256 diffLimit; int64_t nTargetTimespan; @@ -81,19 +82,13 @@ struct Params { /** * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, - * (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. + * (nTargetTimespan / nTargetSpacing) which is also used for BIP9 deployments. * Examples: 1916 for 95%, 1512 for testchains. */ uint32_t nRuleChangeActivationThreshold; uint32_t nMinerConfirmationWindow; BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS]; - /** Proof of work parameters */ - uint256 powLimit; - bool fPowAllowMinDifficultyBlocks; - bool fPowNoRetargeting; - int64_t nPowTargetSpacing; - int64_t nPowTargetTimespan; - int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; } + uint256 nMinimumChainWork; uint256 defaultAssumeValid; }; diff --git a/src/miner.cpp b/src/miner.cpp index 63ed457ca2..2771e5f563 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -37,8 +37,8 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam pblock->nTime = nNewTime; // Updating time can change work required on testnet: - if (consensusParams.fPowAllowMinDifficultyBlocks) - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); + if (consensusParams.pos.fAllowMinDifficultyBlocks) + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams.pos); return nNewTime - nOldTime; } @@ -161,8 +161,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); - pblock->nNonce = 0; + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus().pos); pblock->stakeModifier = uint256{}; // SS pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 520dfcbb66..6e1defe503 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -577,12 +577,12 @@ static bool TipMayBeStale(const Consensus::Params &consensusParams) EXCLUSIVE_LO if (g_last_tip_update == 0) { g_last_tip_update = GetTime(); } - return g_last_tip_update < GetTime() - consensusParams.nPowTargetSpacing * 3 && mapBlocksInFlight.empty(); + return g_last_tip_update < GetTime() - consensusParams.pos.nTargetSpacing * 3 && mapBlocksInFlight.empty(); } static bool CanDirectFetch(const Consensus::Params &consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { - return ::ChainActive().Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20; + return ::ChainActive().Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.pos.nTargetSpacing * 20; } static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main) @@ -1913,7 +1913,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr int64_t nTime; CAddress addrMe; CAddress addrFrom; - uint64_t nNonce = 1; uint64_t nServiceInt; ServiceFlags nServices; int nVersion; @@ -1952,7 +1951,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } if (!vRecv.empty()) - vRecv >> addrFrom >> nNonce; + vRecv >> addrFrom; if (!vRecv.empty()) { std::string strSubVer; vRecv >> LIMITED_STRING(strSubVer, MAX_SUBVERSION_LENGTH); @@ -1964,7 +1963,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (!vRecv.empty()) vRecv >> fRelay; // Disconnect if we connected to ourself - if (pfrom->fInbound && !connman->CheckIncomingNonce(nNonce)) + if (pfrom->fInbound) // TODO: SS && !connman->CheckIncomingNonce(nNonce) { LogPrintf("connected to self at %s, disconnecting\n", pfrom->addr.ToString()); pfrom->fDisconnect = true; @@ -2333,7 +2332,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } // If pruning, don't inv blocks unless we have on disk and are likely to still have // for some reasonable time window (1 hour) that block relay might require. - const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / chainparams.GetConsensus().nPowTargetSpacing; + const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / chainparams.GetConsensus().pos.nTargetSpacing; if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= ::ChainActive().Tip()->nHeight - nPrunedBlocksLikelyToHave)) { LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); @@ -3618,7 +3617,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto) // Only actively request headers from a single peer, unless we're close to today. if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) { state.fSyncStarted = true; - state.nHeadersSyncTimeout = GetTimeMicros() + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * (GetAdjustedTime() - pindexBestHeader->GetBlockTime())/(consensusParams.nPowTargetSpacing); + state.nHeadersSyncTimeout = GetTimeMicros() + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * (GetAdjustedTime() - pindexBestHeader->GetBlockTime())/(consensusParams.pos.nTargetSpacing); nSyncStarted++; const CBlockIndex *pindexStart = pindexBestHeader; /* If possible, start at the block preceding the currently @@ -3933,7 +3932,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto) if (state.vBlocksInFlight.size() > 0) { QueuedBlock &queuedBlock = state.vBlocksInFlight.front(); int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0); - if (nNow > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) { + if (nNow > state.nDownloadingSince + consensusParams.pos.nTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) { LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->GetId()); pto->fDisconnect = true; return true; diff --git a/src/pos.cpp b/src/pos.cpp index ccbe7bc520..5ffcedbf32 100644 --- a/src/pos.cpp +++ b/src/pos.cpp @@ -7,21 +7,17 @@ #include #include -static bool CheckStakeModifier(const CBlockIndex* pindexPrev, const CBlock& block, const Consensus::Params& params) { +static bool CheckStakeModifier(const CBlockIndex* pindexPrev, const CBlock& block) { if (block.hashPrevBlock.IsNull()) return block.stakeModifier.IsNull(); - return block.stakeModifier == pos::ComputeStakeModifier_PoS(pindexPrev->stakeModifier, - block.proofOfStakeBody->coinstakePrevout); -} - -bool CheckBlockProof_headerOnly(const CBlockHeader& block, const Consensus::Params& params) { - return pos::CheckProofOfStake_headerOnly(block, params); + uint256 id = block.ExtractMasternodeID(); + return block.stakeModifier == pos::ComputeStakeModifier(pindexPrev->stakeModifier, id); } bool CheckBlockProof(const CBlockIndex* pindexPrev, const CBlock& block, CCoinsViewCache& view, const Consensus::Params& params) { - if (!CheckStakeModifier(pindexPrev, block, params)) { + if (!CheckStakeModifier(pindexPrev, block)) { return false; } @@ -64,8 +60,7 @@ namespace pos { const auto& body = *block.proofOfStakeBody; // checked to exist after IsProofOfStake // checking PoS kernel is faster, so check it first - if (!CheckKernelHash(block.stakeModifier, block.nBits, coinstakeTime, body.coinstakeAmount, - body.coinstakePrevout, params).hashOk) { + if (!CheckKernelHash(block.stakeModifier, block.nBits, coinstakeTime, params).hashOk) { return false; } return CheckHeaderSignature(block); @@ -82,9 +77,6 @@ namespace pos { const auto& body = *block.proofOfStakeBody; // checked to exist after IsProofOfStake - if (body.coinstakePrevout != block.vtx[1]->vin[0].prevout) - return error("CheckProofOfStake(): block claimed PoS prevout doesn't match coinstakeTx (%s != %s)", body.coinstakePrevout.ToString(), block.vtx[1]->vin[0].prevout.ToString()); - // check staker's pubKeyHash { std::vector addressRet; @@ -102,25 +94,15 @@ namespace pos { // check staker's coin { - const Coin& stakeCoin = view.AccessCoin(body.coinstakePrevout); - if (stakeCoin.IsSpent()) - return error("CheckProofOfStake : Could not find previous transaction for PoS %s\n", - body.coinstakePrevout.hash.ToString()); - if ((pindexPrev->nHeight - stakeCoin.nHeight) < params.pos.coinstakeMaturity) - return error("CheckProofOfStake(): coinstakeTx input must have at least 100 confirmations"); - - if (body.coinstakeAmount != stakeCoin.out.nValue) - return error("CheckProofOfStake(): coinstakeTx amount and block coinstakeAmount mismatch"); - // it's vital for security that we use the same scriptPubKey - if (block.vtx[1]->vout[1].scriptPubKey != stakeCoin.out.scriptPubKey) - return error("CheckProofOfStake(): coinstakeTx scriptPubKey and prev. scriptPubKey mismatch"); +// if (stakeCoin.IsSpent()) // TODO: SS check collateral don't spend +// return error("CheckProofOfStake : Could not find previous transaction for PoS %s\n", +// body.coinstakePrevout.hash.ToString()); } - const int64_t coinstakeTime = (int64_t) block.GetBlockTime(); + // checking PoS kernel is faster, so check it first - if (!CheckKernelHash(block.stakeModifier, block.nBits, coinstakeTime, body.coinstakeAmount, body.coinstakePrevout, - params).hashOk) { + if (!CheckKernelHash(block.stakeModifier, block.nBits, coinstakeTime, params).hashOk) { return false; } return CheckHeaderSignature(block); diff --git a/src/pos_kernel.cpp b/src/pos_kernel.cpp index 1072bcc512..62c0961dbb 100644 --- a/src/pos_kernel.cpp +++ b/src/pos_kernel.cpp @@ -1,45 +1,41 @@ #include +#include #include #include #include #include namespace pos { + const uint64_t COINSTAKE_AMOUNT = 1000 * COIN; - uint256 CalcKernelHash(uint256 stakeModifier, int64_t coinstakeTime, const COutPoint& prevout, - const Consensus::Params& params) { + uint256 CalcKernelHash(uint256 stakeModifier, int64_t coinstakeTime, const Consensus::Params& params) { // Calculate hash CDataStream ss(SER_GETHASH, 0); - ss << stakeModifier << coinstakeTime << prevout.hash << prevout.n; + ss << stakeModifier << coinstakeTime; // TODO: SS add masternode id return Hash(ss.begin(), ss.end()); } CheckKernelHashRes - CheckKernelHash(uint256 stakeModifier, uint32_t nBits, int64_t coinstakeTime, CAmount coinstakeAmount, - const COutPoint& prevout, const Consensus::Params& params) { - if (prevout.IsNull() || coinstakeAmount <= 0) { - return {false, arith_uint256{}}; - } - + CheckKernelHash(uint256 stakeModifier, uint32_t nBits, int64_t coinstakeTime, const Consensus::Params& params) { // Base target arith_uint256 targetProofOfStake; targetProofOfStake.SetCompact(nBits); const arith_uint256 hashProofOfStake = UintToArith256( - CalcKernelHash(stakeModifier, coinstakeTime, prevout, params)); + CalcKernelHash(stakeModifier, coinstakeTime, params)); // Now check if proof-of-stake hash meets target protocol - if ((hashProofOfStake / (uint64_t) coinstakeAmount) > targetProofOfStake) { + if ((hashProofOfStake / (uint64_t) COINSTAKE_AMOUNT) > targetProofOfStake) { return {false, hashProofOfStake}; } return {true, hashProofOfStake}; } - uint256 ComputeStakeModifier_PoS(uint256 prevStakeModifier, const COutPoint& prevout) { + uint256 ComputeStakeModifier(uint256 prevStakeModifier, const uint256& id) { // Calculate hash CDataStream ss(SER_GETHASH, 0); - ss << prevStakeModifier << prevout.hash << prevout.n; + ss << prevStakeModifier << id; return Hash(ss.begin(), ss.end()); } } diff --git a/src/pos_kernel.h b/src/pos_kernel.h index 80bac53167..f1277d5bd1 100644 --- a/src/pos_kernel.h +++ b/src/pos_kernel.h @@ -25,18 +25,17 @@ namespace pos { /// Calculate PoS kernel hash uint256 - CalcKernelHash(uint256 stakeModifier, int64_t coinstakeTime, const COutPoint& prevout, const Consensus::Params& params); + CalcKernelHash(uint256 stakeModifier, int64_t coinstakeTime, const Consensus::Params& params); /// Check whether stake kernel meets hash target /// Sets hashProofOfStake, hashOk is true of the kernel meets hash target CheckKernelHashRes - CheckKernelHash(uint256 stakeModifier, uint32_t nBits, int64_t coinstakeTime, CAmount coinstakeAmount, - const COutPoint& prevout, const Consensus::Params& params); + CheckKernelHash(uint256 stakeModifier, uint32_t nBits, int64_t coinstakeTime, const Consensus::Params& params); /// Stake Modifier (hash modifier of proof-of-stake): /// The purpose of stake modifier is to prevent a txout (coin) owner from /// computing future proof-of-stake generated by this txout at the time /// of transaction confirmation. To meet kernel protocol, the txout /// must hash with a future stake modifier to generate the proof. - uint256 ComputeStakeModifier_PoS(uint256 prevStakeModifier, const COutPoint& prevout); + uint256 ComputeStakeModifier(uint256 prevStakeModifier, const uint256& id); } diff --git a/src/pow.cpp b/src/pow.cpp index 1414d37564..12c849fde3 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -10,20 +10,20 @@ #include #include -unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) +unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params::PoS& params) { assert(pindexLast != nullptr); - unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); + unsigned int nProofOfWorkLimit = UintToArith256(params.diffLimit).GetCompact(); // Only change once per difficulty adjustment interval if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) { - if (params.fPowAllowMinDifficultyBlocks) + if (params.fAllowMinDifficultyBlocks) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. - if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) + if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nTargetSpacing*2) return nProofOfWorkLimit; else { @@ -46,27 +46,27 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); } -unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) +unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params::PoS& params) { - if (params.fPowNoRetargeting) + if (params.fNoRetargeting) return pindexLast->nBits; // Limit adjustment step int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; - if (nActualTimespan < params.nPowTargetTimespan/4) - nActualTimespan = params.nPowTargetTimespan/4; - if (nActualTimespan > params.nPowTargetTimespan*4) - nActualTimespan = params.nPowTargetTimespan*4; + if (nActualTimespan < params.nTargetTimespan/4) + nActualTimespan = params.nTargetTimespan/4; + if (nActualTimespan > params.nTargetTimespan*4) + nActualTimespan = params.nTargetTimespan*4; // Retarget - const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); + const arith_uint256 bnDiffLimit = UintToArith256(params.diffLimit); arith_uint256 bnNew; bnNew.SetCompact(pindexLast->nBits); bnNew *= nActualTimespan; - bnNew /= params.nPowTargetTimespan; + bnNew /= params.nTargetTimespan; - if (bnNew > bnPowLimit) - bnNew = bnPowLimit; + if (bnNew > bnDiffLimit) + bnNew = bnDiffLimit; return bnNew.GetCompact(); } @@ -80,7 +80,7 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& bnTarget.SetCompact(nBits, &fNegative, &fOverflow); // Check range - if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) + if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.pos.diffLimit)) return false; // Check proof of work matches claimed amount diff --git a/src/pow.h b/src/pow.h index 1d802cd01e..16d878bccc 100644 --- a/src/pow.h +++ b/src/pow.h @@ -14,8 +14,8 @@ class CBlockHeader; class CBlockIndex; class uint256; -unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params&); -unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params&); +unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params::PoS&); +unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params::PoS&); /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&); diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index dcc292b555..03cee48e75 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -23,12 +23,12 @@ uint256 CBlockHeader::GetHashToSign() const std::string CBlock::ToString() const { std::stringstream s; - s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n", + s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, vtx=%u)\n", GetHash().ToString(), nVersion, hashPrevBlock.ToString(), hashMerkleRoot.ToString(), - nTime, nBits, nNonce, + nTime, nBits, proofOfStakeBody ? HexStr(proofOfStakeBody->sig.begin(), proofOfStakeBody->sig.end()) : "Empty", vtx.size()); for (const auto& tx : vtx) { diff --git a/src/primitives/block.h b/src/primitives/block.h index aaba64d7a4..55b690c1f6 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -24,12 +24,8 @@ class CBlockHeader { public: struct PoS { - COutPoint coinstakePrevout; - CKeyID pubKeyHash; // only for sanity checks - CAmount coinstakeAmount; // only for sanity checks - // PoS: block signature - signed by staker's privkey std::vector sig; @@ -37,9 +33,7 @@ class CBlockHeader template inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(coinstakePrevout); READWRITE(pubKeyHash); - READWRITE(coinstakeAmount); // bool hashToSignAction = s.GetType() & SER_GETSIGNHASH; // if (!hashToSignAction) { // READWRITE(sig); @@ -53,7 +47,6 @@ class CBlockHeader uint256 hashMerkleRoot; uint32_t nTime; uint32_t nBits; - uint32_t nNonce; uint256 stakeModifier; // only for sanity checks boost::optional proofOfStakeBody; @@ -72,7 +65,6 @@ class CBlockHeader READWRITE(hashMerkleRoot); READWRITE(nTime); READWRITE(nBits); - READWRITE(nNonce); READWRITE(stakeModifier); //PoS serialization @@ -88,7 +80,6 @@ class CBlockHeader hashMerkleRoot.SetNull(); nTime = 0; nBits = 0; - nNonce = 0; stakeModifier.SetNull(); proofOfStakeBody = boost::optional{}; } @@ -111,6 +102,11 @@ class CBlockHeader { return (int64_t)nTime; } + + uint256 ExtractMasternodeID() const + { + return uint256{}; // TODO: SS + } }; @@ -167,7 +163,6 @@ class CBlock : public CBlockHeader block.hashMerkleRoot = hashMerkleRoot; block.nTime = nTime; block.nBits = nBits; - block.nNonce = nNonce; block.stakeModifier = stakeModifier; block.proofOfStakeBody = proofOfStakeBody; return block; diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 323797a4b6..230b2fc0a2 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -905,7 +905,7 @@ void BitcoinGUI::updateHeadersSyncProgressLabel() { int64_t headersTipTime = clientModel->getHeaderTipTime(); int headersTipHeight = clientModel->getHeaderTipHeight(); - int estHeadersLeft = (GetTime() - headersTipTime) / Params().GetConsensus().nPowTargetSpacing; + int estHeadersLeft = (GetTime() - headersTipTime) / Params().GetConsensus().pos.nTargetSpacing; if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC) progressBarLabel->setText(tr("Syncing Headers (%1%)...").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1))); } diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index 8ecc33da84..6461b0ceb8 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -128,9 +128,9 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri // not syncing return; - // estimate the number of headers left based on nPowTargetSpacing + // estimate the number of headers left based on nTargetSpacing // and check if the gui is not aware of the best header (happens rarely) - int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing; + int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().pos.nTargetSpacing; bool hasBestHeader = bestHeaderHeight >= count; // show remaining number of blocks @@ -143,7 +143,7 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri } void ModalOverlay::UpdateHeaderSyncLabel() { - int est_headers_left = bestHeaderDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing; + int est_headers_left = bestHeaderDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().pos.nTargetSpacing; ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1, %2%)...").arg(bestHeaderHeight).arg(QString::number(100.0 / (bestHeaderHeight + est_headers_left) * bestHeaderHeight, 'f', 1))); } diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index f23c47736f..0e968c93a0 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -165,7 +165,7 @@ void SendCoinsDialog::setModel(WalletModel *_model) // fee section for (const int n : confTargets) { - ui->confTargetSelector->addItem(tr("%1 (%2 blocks)").arg(GUIUtil::formatNiceTimeOffset(n*Params().GetConsensus().nPowTargetSpacing)).arg(n)); + ui->confTargetSelector->addItem(tr("%1 (%2 blocks)").arg(GUIUtil::formatNiceTimeOffset(n*Params().GetConsensus().pos.nTargetSpacing)).arg(n)); } connect(ui->confTargetSelector, static_cast(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::updateSmartFeeLabel); connect(ui->confTargetSelector, static_cast(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::coinControlUpdateLabels); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 5419e33396..06e284e248 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -106,7 +106,6 @@ UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex result.pushKV("merkleroot", blockindex->hashMerkleRoot.GetHex()); result.pushKV("time", (int64_t)blockindex->nTime); result.pushKV("mediantime", (int64_t)blockindex->GetMedianTimePast()); - result.pushKV("nonce", (uint64_t)blockindex->nNonce); result.pushKV("bits", strprintf("%08x", blockindex->nBits)); result.pushKV("difficulty", GetDifficulty(blockindex)); result.pushKV("chainwork", blockindex->nChainWork.GetHex()); @@ -151,7 +150,6 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn result.pushKV("tx", txs); result.pushKV("time", block.GetBlockTime()); result.pushKV("mediantime", (int64_t)blockindex->GetMedianTimePast()); - result.pushKV("nonce", (uint64_t)block.nNonce); result.pushKV("bits", strprintf("%08x", block.nBits)); result.pushKV("difficulty", GetDifficulty(blockindex)); result.pushKV("chainwork", blockindex->nChainWork.GetHex()); @@ -1583,7 +1581,7 @@ static UniValue getchaintxstats(const JSONRPCRequest& request) }.Check(request); const CBlockIndex* pindex; - int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month + int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().pos.nTargetSpacing; // By default: 1 month if (request.params[1].isNull()) { LOCK(cs_main); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 62a4f16ef4..c71e6cd3b1 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -50,7 +50,7 @@ static UniValue GetNetworkHashPS(int lookup, int height) { // If lookup is -1, then use blocks since last difficulty change. if (lookup <= 0) - lookup = pb->nHeight % Params().GetConsensus().DifficultyAdjustmentInterval() + 1; + lookup = pb->nHeight % Params().GetConsensus().pos.DifficultyAdjustmentInterval() + 1; // If lookup is larger than chain, then set it to chain length. if (lookup > pb->nHeight) @@ -121,16 +121,13 @@ static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, ui LOCK(cs_main); IncrementExtraNonce(pblock, ::ChainActive().Tip(), nExtraNonce); } - while (nMaxTries > 0 && pblock->nNonce < std::numeric_limits::max() && !CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus()) && !ShutdownRequested()) { - ++pblock->nNonce; - --nMaxTries; - } +// while (nMaxTries > 0 && !CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus()) && !ShutdownRequested()) { +// ++pblock->nNonce; +// --nMaxTries; +// } if (nMaxTries == 0 || ShutdownRequested()) { break; } - if (pblock->nNonce == std::numeric_limits::max()) { - continue; - } std::shared_ptr shared_pblock = std::make_shared(*pblock); if (!ProcessNewBlock(Params(), shared_pblock, true, nullptr)) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); @@ -517,7 +514,6 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) // Update nTime UpdateTime(pblock, consensusParams, pindexPrev); - pblock->nNonce = 0; // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration const bool fPreSegWit = (pindexPrev->nHeight + 1 < consensusParams.SegwitHeight); diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 5ce8e6feb0..2a0b4421be 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -48,7 +48,7 @@ static CBlock BuildBlockTestCase() { bool mutated; block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); assert(!mutated); - while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce; + // while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce; return block; } @@ -296,7 +296,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) bool mutated; block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); assert(!mutated); - while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce; + // while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce; // Test simple header round-trip with only coinbase { diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index cf87aa9303..3ee1eb1d5e 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -87,7 +87,7 @@ static CBlock CreateBlock(const CBlockIndex* prev, unsigned int extraNonce = 0; IncrementExtraNonce(&block, prev, extraNonce); - while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; + // while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; return block; } diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index a50d6854f8..96af4973cc 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -172,7 +172,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) BOOST_CHECK(node->fDisconnect == false); } - SetMockTime(GetTime() + 3*consensusParams.nPowTargetSpacing + 1); + SetMockTime(GetTime() + 3*consensusParams.pos.nTargetSpacing + 1); // Now tip should definitely be stale, and we should look for an extra // outbound peer diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 8aef234be0..6b95757285 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) if (txFirst.size() < 4) txFirst.push_back(pblock->vtx[0]); pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); - pblock->nNonce = blockinfo[i].nonce; + // pblock->nNonce = blockinfo[i].nonce; } std::shared_ptr shared_pblock = std::make_shared(*pblock); BOOST_CHECK(ProcessNewBlock(chainparams, shared_pblock, true, nullptr)); diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 1123d4202c..2c0fb5ed3b 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -21,7 +21,7 @@ BOOST_AUTO_TEST_CASE(get_next_work) pindexLast.nHeight = 32255; pindexLast.nTime = 1262152739; // Block #32255 pindexLast.nBits = 0x1d00ffff; - BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00d86aU); + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus().pos), 0x1d00d86aU); } /* Test the constraint on the upper bound for next work */ @@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit) pindexLast.nHeight = 2015; pindexLast.nTime = 1233061996; // Block #2015 pindexLast.nBits = 0x1d00ffff; - BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00ffffU); + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus().pos), 0x1d00ffffU); } /* Test the constraint on the lower bound for actual time taken */ @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual) pindexLast.nHeight = 68543; pindexLast.nTime = 1279297671; // Block #68543 pindexLast.nBits = 0x1c05a3f4; - BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1c0168fdU); + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus().pos), 0x1c0168fdU); } /* Test the constraint on the upper bound for actual time taken */ @@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) pindexLast.nHeight = 46367; pindexLast.nTime = 1269211443; // Block #46367 pindexLast.nBits = 0x1c387f6f; - BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00e1fdU); + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus().pos), 0x1d00e1fdU); } BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) @@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) for (int i = 0; i < 10000; i++) { blocks[i].pprev = i ? &blocks[i - 1] : nullptr; blocks[i].nHeight = i; - blocks[i].nTime = 1269211443 + i * chainParams->GetConsensus().nPowTargetSpacing; + blocks[i].nTime = 1269211443 + i * chainParams->GetConsensus().pos.nTargetSpacing; blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); } diff --git a/src/test/setup_common.cpp b/src/test/setup_common.cpp index bbdf1ef830..e96d882bec 100644 --- a/src/test/setup_common.cpp +++ b/src/test/setup_common.cpp @@ -161,7 +161,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector& IncrementExtraNonce(&block, ::ChainActive().Tip(), extraNonce); } - while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; + // while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce; std::shared_ptr shared_pblock = std::make_shared(block); ProcessNewBlock(chainparams, shared_pblock, true, nullptr); diff --git a/src/test/util.cpp b/src/test/util.cpp index b7bb6deeaa..b1b5d760d7 100644 --- a/src/test/util.cpp +++ b/src/test/util.cpp @@ -56,10 +56,10 @@ CTxIn MineBlock(const CScript& coinbase_scriptPubKey) { auto block = PrepareBlock(coinbase_scriptPubKey); - while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { - ++block->nNonce; - assert(block->nNonce); - } +// while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) { // TODO: SS +// ++block->nNonce; +// assert(block->nNonce); +// } bool processed{ProcessNewBlock(Params(), block, true, nullptr)}; assert(processed); diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index b3368d44b6..d1978b3711 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -93,9 +93,9 @@ std::shared_ptr FinalizeBlock(std::shared_ptr pblock) pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); - while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) { - ++(pblock->nNonce); - } +// while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) { +// ++(pblock->nNonce); +// } return pblock; } diff --git a/src/txdb.cpp b/src/txdb.cpp index be4adfa52d..6958581c12 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -270,7 +270,6 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot; pindexNew->nTime = diskindex.nTime; pindexNew->nBits = diskindex.nBits; - pindexNew->nNonce = diskindex.nNonce; pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; diff --git a/src/validation.cpp b/src/validation.cpp index 95c8aca8bb..a40fdaaa56 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3181,7 +3181,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationSta // Check proof of work const Consensus::Params& consensusParams = params.GetConsensus(); - if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) + if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams.pos)) return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "bad-diffbits", "incorrect proof of work"); // Check against checkpoints @@ -3404,7 +3404,7 @@ bool ProcessNewBlockHeaders(const std::vector& headers, CValidatio { LOCK(cs_main); if (::ChainstateActive().IsInitialBlockDownload() && ppindex && *ppindex) { - LogPrintf("Synchronizing blockheaders, height: %d (~%.2f%%)\n", (*ppindex)->nHeight, 100.0/((*ppindex)->nHeight+(GetAdjustedTime() - (*ppindex)->GetBlockTime()) / Params().GetConsensus().nPowTargetSpacing) * (*ppindex)->nHeight); + LogPrintf("Synchronizing blockheaders, height: %d (~%.2f%%)\n", (*ppindex)->nHeight, 100.0/((*ppindex)->nHeight+(GetAdjustedTime() - (*ppindex)->GetBlockTime()) / Params().GetConsensus().pos.nTargetSpacing) * (*ppindex)->nHeight); } } return true; From 600bbb3ae8a9ae80a6035c8cbe66ce1ef52b77a7 Mon Sep 17 00:00:00 2001 From: Ahmed Hilali Date: Wed, 18 Sep 2019 16:35:23 +0700 Subject: [PATCH 2/6] refactor PoS structure. Add height and mintedBlocks params to CBlockHeader --- src/chain.h | 40 ++++++++++++++++--------------- src/pos.cpp | 28 +++------------------- src/primitives/block.cpp | 9 ++++--- src/primitives/block.h | 51 +++++++++++----------------------------- src/serialize.h | 1 - src/txdb.cpp | 4 +++- 6 files changed, 47 insertions(+), 86 deletions(-) diff --git a/src/chain.h b/src/chain.h index e5f08c3f3b..8e60efd479 100644 --- a/src/chain.h +++ b/src/chain.h @@ -181,10 +181,12 @@ class CBlockIndex uint256 hashMerkleRoot; uint32_t nTime; uint32_t nBits; - boost::optional proofOfStakeBody; // proof-of-stake specific fields + uint64_t height; + uint64_t mintedBlocks; uint256 stakeModifier; // hash modifier for proof-of-stake + std::vector sig; //! (memory only) Sequential id assigned to distinguish order in which blocks are received. int32_t nSequenceId; @@ -208,14 +210,14 @@ class CBlockIndex nSequenceId = 0; nTimeMax = 0; - // PoS - proofOfStakeBody = boost::optional{}; - stakeModifier = uint256{}; - nVersion = 0; hashMerkleRoot = uint256(); nTime = 0; nBits = 0; + stakeModifier = uint256{}; + height = 0; + mintedBlocks = 0; + sig = {}; } CBlockIndex() @@ -231,8 +233,10 @@ class CBlockIndex hashMerkleRoot = block.hashMerkleRoot; nTime = block.nTime; nBits = block.nBits; + height = block.height; + mintedBlocks = block.mintedBlocks; stakeModifier = block.stakeModifier; - proofOfStakeBody = block.proofOfStakeBody; + sig = block.sig; } FlatFilePos GetBlockPos() const { @@ -263,7 +267,9 @@ class CBlockIndex block.nTime = nTime; block.nBits = nBits; block.stakeModifier = stakeModifier; - block.proofOfStakeBody = proofOfStakeBody; + block.height = height; + block.mintedBlocks = mintedBlocks; + block.sig = sig; return block; } @@ -339,11 +345,6 @@ class CBlockIndex return false; } - bool IsProofOfStake() const - { - return (bool) proofOfStakeBody; - } - //! Build the skiplist pointer for this entry. void BuildSkip(); @@ -391,17 +392,15 @@ class CDiskBlockIndex : public CBlockIndex if (nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(nUndoPos)); - //PoS serialization - CBlockHeader::PoS loc_proofOfStake = proofOfStakeBody ? *proofOfStakeBody : CBlockHeader::PoS{}; - READWRITE(loc_proofOfStake); - proofOfStakeBody = loc_proofOfStake; - // block header READWRITE(this->nVersion); READWRITE(hashPrev); READWRITE(hashMerkleRoot); READWRITE(nTime); READWRITE(nBits); + READWRITE(height); + READWRITE(mintedBlocks); + READWRITE(sig); } uint256 GetBlockHash() const @@ -412,8 +411,11 @@ class CDiskBlockIndex : public CBlockIndex block.hashMerkleRoot = hashMerkleRoot; block.nTime = nTime; block.nBits = nBits; - block.stakeModifier = stakeModifier; - block.proofOfStakeBody = proofOfStakeBody; + block.stakeModifier = stakeModifier; + block.height = height; + block.mintedBlocks = mintedBlocks; + block.sig = sig; + return block.GetHash(); } diff --git a/src/pos.cpp b/src/pos.cpp index 5ffcedbf32..175a98c6da 100644 --- a/src/pos.cpp +++ b/src/pos.cpp @@ -29,35 +29,22 @@ namespace pos { /// Check PoS signatures (PoS block hashes are signed with coinstake out pubkey) bool CheckHeaderSignature(const CBlockHeader& block) { - if (!block.IsProofOfStake()) { - return true; - } - - if (block.proofOfStakeBody->sig.empty()) { + if (block.sig.empty()) { LogPrintf("CheckBlockSignature: Bad Block - PoS signature is empty\n"); return false; } CPubKey recoveredPubKey{}; - if (!recoveredPubKey.RecoverCompact(block.GetHashToSign(), block.proofOfStakeBody->sig)) { + if (!recoveredPubKey.RecoverCompact(block.GetHashToSign(), block.sig)) { LogPrintf("CheckBlockSignature: Bad Block - malformed signature\n"); return false; } - if (recoveredPubKey.GetID() != block.proofOfStakeBody->pubKeyHash) { - LogPrintf("CheckBlockSignature: Bad Block - wrong signature\n"); - return false; - } return true; } bool CheckProofOfStake_headerOnly(const CBlockHeader& block, const Consensus::Params& params) { - if (!block.IsProofOfStake()) { - return error("CheckProofOfStake_headerOnly(): called on non-PoS %s", block.GetHash().ToString()); - } - const int64_t coinstakeTime = (int64_t) block.GetBlockTime(); - const auto& body = *block.proofOfStakeBody; // checked to exist after IsProofOfStake // checking PoS kernel is faster, so check it first if (!CheckKernelHash(block.stakeModifier, block.nBits, coinstakeTime, params).hashOk) { @@ -68,15 +55,10 @@ namespace pos { bool CheckProofOfStake(const CBlockIndex* pindexPrev, const CBlock& block, CCoinsViewCache& view, const Consensus::Params& params) { - if (block.IsProofOfStake() != block.HasCoinstakeTx()) { - return false; // block claimed it's PoS, but doesn't have coinstakeTx - } - if (!block.IsCompleteProofOfStake()) { + if (!block.HasCoinstakeTx()) { return error("CheckProofOfStake(): called on a non-PoS block %s", block.GetHash().ToString()); } - const auto& body = *block.proofOfStakeBody; // checked to exist after IsProofOfStake - // check staker's pubKeyHash { std::vector addressRet; @@ -86,10 +68,6 @@ namespace pos { return error("CheckProofOfStake(): coinstakeTx scriptPubKey must be P2PKH"); if (!(typeRet == txnouttype::TX_PUBKEYHASH && addressRet.size() == 1)) return error("CheckProofOfStake(): coinstakeTx scriptPubKey must be P2PKH"); - - CKeyID keyID(boost::get(addressRet[0])); - if (keyID != body.pubKeyHash) - return error("CheckProofOfStake(): coinstakeTx scriptPubKey and block pubKeyHash mismatch"); } // check staker's coin diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 03cee48e75..0a5f1d9712 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -9,6 +9,7 @@ #include #include #include +#include uint256 CBlockHeader::GetHash() const { @@ -17,19 +18,21 @@ uint256 CBlockHeader::GetHash() const uint256 CBlockHeader::GetHashToSign() const { - return SerializeHash(*this, SER_GETSIGNHASH); + CDataStream ss(SER_GETHASH, 0); + ss << nVersion << hashPrevBlock << hashMerkleRoot << nTime << nBits << height << mintedBlocks << stakeModifier; + return Hash(ss.begin(), ss.end()); } std::string CBlock::ToString() const { std::stringstream s; - s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, vtx=%u)\n", + s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, height=%u, mintedBlocks=%u, vtx=%u)\n", GetHash().ToString(), nVersion, hashPrevBlock.ToString(), hashMerkleRoot.ToString(), nTime, nBits, - proofOfStakeBody ? HexStr(proofOfStakeBody->sig.begin(), proofOfStakeBody->sig.end()) : "Empty", + height, mintedBlocks, vtx.size()); for (const auto& tx : vtx) { s << " " << tx->ToString() << "\n"; diff --git a/src/primitives/block.h b/src/primitives/block.h index 55b690c1f6..c9ce0a348e 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -23,24 +23,6 @@ class CBlockHeader { public: - struct PoS { - CKeyID pubKeyHash; // only for sanity checks - - // PoS: block signature - signed by staker's privkey - std::vector sig; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(pubKeyHash); -// bool hashToSignAction = s.GetType() & SER_GETSIGNHASH; -// if (!hashToSignAction) { -// READWRITE(sig); -// } - } - }; - // header int32_t nVersion; uint256 hashPrevBlock; @@ -48,8 +30,10 @@ class CBlockHeader uint32_t nTime; uint32_t nBits; - uint256 stakeModifier; // only for sanity checks - boost::optional proofOfStakeBody; + uint64_t height; + uint64_t mintedBlocks; + uint256 stakeModifier; + std::vector sig; CBlockHeader() { @@ -66,11 +50,9 @@ class CBlockHeader READWRITE(nTime); READWRITE(nBits); READWRITE(stakeModifier); - - //PoS serialization - PoS loc_proofOfStake = proofOfStakeBody ? *proofOfStakeBody : PoS{}; - READWRITE(loc_proofOfStake); - proofOfStakeBody = loc_proofOfStake; + READWRITE(height); + READWRITE(mintedBlocks); + READWRITE(sig); } void SetNull() @@ -81,7 +63,9 @@ class CBlockHeader nTime = 0; nBits = 0; stakeModifier.SetNull(); - proofOfStakeBody = boost::optional{}; + height = 0; + mintedBlocks = 0; + sig = {}; } bool IsNull() const @@ -89,11 +73,6 @@ class CBlockHeader return (nBits == 0); } - bool IsProofOfStake() const - { - return (bool) proofOfStakeBody; - } - uint256 GetHashToSign() const; uint256 GetHash() const; @@ -150,11 +129,6 @@ class CBlock : public CBlockHeader return vtx.size() > 1 && vtx[1]->IsCoinStake(); } - bool IsCompleteProofOfStake() const - { - return IsProofOfStake() && HasCoinstakeTx(); - } - CBlockHeader GetBlockHeader() const { CBlockHeader block; @@ -164,7 +138,10 @@ class CBlock : public CBlockHeader block.nTime = nTime; block.nBits = nBits; block.stakeModifier = stakeModifier; - block.proofOfStakeBody = proofOfStakeBody; + block.height = height; + block.mintedBlocks = mintedBlocks; + block.sig = sig; + return block; } diff --git a/src/serialize.h b/src/serialize.h index a74f2ffd8a..a38d76fc18 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -175,7 +175,6 @@ enum SER_NETWORK = (1 << 0), SER_DISK = (1 << 1), SER_GETHASH = (1 << 2), - SER_GETSIGNHASH = (1 << 3), }; //! Convert the reference base type to X, without changing constness or reference type. diff --git a/src/txdb.cpp b/src/txdb.cpp index 6958581c12..9bac98e192 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -275,7 +275,9 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, //PoS pindexNew->stakeModifier = diskindex.stakeModifier; - pindexNew->proofOfStakeBody = diskindex.proofOfStakeBody; + pindexNew->height = diskindex.height; + pindexNew->mintedBlocks = diskindex.mintedBlocks; + pindexNew->sig = diskindex.sig; if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString()); From 61c6b36c75e208b7e742c1a2554fbffd344a8eac Mon Sep 17 00:00:00 2001 From: Ahmed Hilali Date: Fri, 20 Sep 2019 18:06:58 +0700 Subject: [PATCH 3/6] remove PoW --- src/Makefile.am | 2 - src/bench/duplicate_inputs.cpp | 4 +- src/chain.h | 9 ++ src/miner.cpp | 6 +- src/pos.cpp | 152 ++++++++++++++++++--------- src/pos.h | 6 +- src/pow.cpp | 91 ---------------- src/pow.h | 23 ---- src/rpc/mining.cpp | 2 +- src/test/blockencodings_tests.cpp | 2 +- src/test/blockfilter_index_tests.cpp | 2 +- src/test/pow_tests.cpp | 10 +- src/test/setup_common.cpp | 2 +- src/test/util.cpp | 2 +- src/test/validation_block_tests.cpp | 2 +- src/txdb.cpp | 12 ++- src/validation.cpp | 14 ++- 17 files changed, 146 insertions(+), 195 deletions(-) delete mode 100644 src/pow.cpp delete mode 100644 src/pow.h diff --git a/src/Makefile.am b/src/Makefile.am index 24ae008afc..9a071b0031 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -169,7 +169,6 @@ BITCOIN_CORE_H = \ policy/settings.h \ pos.h \ pos_kernel.h \ - pow.h \ protocol.h \ psbt.h \ random.h \ @@ -290,7 +289,6 @@ libbitcoin_server_a_SOURCES = \ policy/settings.cpp \ pos.cpp \ pos_kernel.cpp \ - pow.cpp \ rest.cpp \ rpc/blockchain.cpp \ rpc/mining.cpp \ diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index 746520499c..d5d45e42a5 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -28,7 +28,7 @@ static void DuplicateInputs(benchmark::State& state) LOCK(cs_main); CBlockIndex* pindexPrev = ::ChainActive().Tip(); assert(pindexPrev != nullptr); - block.nBits = GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus().pos); + block.nBits = pos::GetNextWorkRequired(pindexPrev, &block, chainparams.GetConsensus().pos); // block.nNonce = 0; auto nHeight = pindexPrev->nHeight + 1; diff --git a/src/chain.h b/src/chain.h index 8e60efd479..bd2215c913 100644 --- a/src/chain.h +++ b/src/chain.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -187,6 +188,7 @@ class CBlockIndex uint64_t mintedBlocks; uint256 stakeModifier; // hash modifier for proof-of-stake std::vector sig; + CKeyID minter; // memory only //! (memory only) Sequential id assigned to distinguish order in which blocks are received. int32_t nSequenceId; @@ -348,6 +350,13 @@ class CBlockIndex //! Build the skiplist pointer for this entry. void BuildSkip(); + uint256 GetHashToSign() const + { + CDataStream ss(SER_GETHASH, 0); + ss << nVersion << pprev->GetBlockHash() << hashMerkleRoot << nTime << nBits << height << mintedBlocks << stakeModifier; + return Hash(ss.begin(), ss.end()); + } + //! Efficiently find an ancestor of this block. CBlockIndex* GetAncestor(int height); const CBlockIndex* GetAncestor(int height) const; diff --git a/src/miner.cpp b/src/miner.cpp index 2771e5f563..89cdaf13b7 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include