From ab7c7ae0bbb7709233d20aa1ed4ab81512d1d3f0 Mon Sep 17 00:00:00 2001 From: Ahmed Hilali Date: Fri, 27 Sep 2019 17:00:00 +0700 Subject: [PATCH 01/30] mn & pos integration; WIP --- src/chainparams.cpp | 5 ++- src/init.cpp | 77 ++++++++++++++++------------------- src/masternodes/masternodes.h | 8 +++- src/miner.cpp | 18 +++++++- src/miner.h | 1 + src/pos.cpp | 38 ++++++++++++++++- src/pos_kernel.cpp | 4 +- src/pos_kernel.h | 2 +- src/validation.cpp | 6 +-- 9 files changed, 103 insertions(+), 56 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index b98b0c6c09..b61e10272e 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -390,8 +390,9 @@ class CRegTestParams : public CChainParams { genesis = CreateGenesisBlock(1296688602, 0x207fffff, 1, 50 * COIN, CreateGenesisMasternodes()); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x000006772a3244d0a5a4911a5cb1d7e910e175f4e4b77c755018459122fa7a89")); - assert(genesis.hashMerkleRoot == uint256S("0x2faeba8cd467cb0df14c48d30b57736f1ed3275790401d127a03d55037df7b5c")); + + assert(consensus.hashGenesisBlock == uint256S("0x5deed118789bf5acdce79974f15b9a1cffb924875f52e702ca93d926d290b31f")); + assert(genesis.hashMerkleRoot == uint256S("0x955d1c4074ccd34639cae5d1234bbef645b34866bfd18f083dd80928618e80fb")); vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds. vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds. diff --git a/src/init.cpp b/src/init.cpp index bf101d7b17..c5c307f659 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1835,54 +1835,49 @@ bool AppInitMain(InitInterfaces& interfaces) }, DUMP_BANS_INTERVAL * 1000); // ********************************************************* Step 14: start minter thread - pos::ThreadStaker::Args stakerParams{}; { - CKey key; - std::vector> wallets = GetWallets(); - if (wallets.size() == 0) { - LogPrintf("Warning! wallets not found"); - return true; - } - std::shared_ptr defaultWallet = wallets[0]; + LOCK(cs_main); - CTxDestination destination; + auto myIDs = pmasternodesview->AmIOperator(); + if (myIDs) + { + pos::ThreadStaker::Args stakerParams{}; + { + std::vector> wallets = GetWallets(); + if (wallets.size() == 0) { + LogPrintf("Warning! wallets not found"); + return true; + } + std::shared_ptr defaultWallet = wallets[0]; - std::string minterAddress = gArgs.GetArg("-minterAddress", ""); - if (minterAddress != "") { - destination = DecodeDestination(minterAddress); - if (!IsValidDestination(destination)) { - LogPrintf("Error: coinstake destination is invalid"); - return false; - } - } else { - std::string strErr; - if(!defaultWallet->GetNewDestination(OutputType::LEGACY, "", destination, strErr)) { - LogPrintf("%s\n", strErr); - return false; - } - } + CKey minterKey; + if (!defaultWallet->GetKey(myIDs->operatorAuthAddress, minterKey)) { + LogPrintf("Error: private key not found"); + return false; + } - CScript coinbaseScript = GetScriptForDestination(destination); - CKey minterKey; - if (!defaultWallet->GetKey(CKeyID(*boost::get(&destination)), minterKey)) { - LogPrintf("Error: private key not found"); - return false; - } + CMasternode const & node = *pmasternodesview->ExistMasternode(myIDs->id); + CTxDestination destination = node.operatorType == 1 ? CTxDestination(PKHash(node.operatorAuthAddress)) : CTxDestination(WitnessV0KeyHash(node.operatorAuthAddress)); - stakerParams.coinbaseScript = coinbaseScript; - stakerParams.minterKey = minterKey; - } + CScript coinbaseScript = GetScriptForDestination(destination); - // Mint proof-of-stake blocks in background - threadGroup.create_thread([=]() { - TraceThread("CoinStaker", [=]() { - // Fill Staker Args + stakerParams.coinbaseScript = coinbaseScript; + stakerParams.minterKey = minterKey; + stakerParams.masternodeID = myIDs->id; + } - // Run ThreadStaker - pos::ThreadStaker threadStaker{}; - threadStaker(stakerParams, chainparams); - }); - }); + // Mint proof-of-stake blocks in background + threadGroup.create_thread([=]() { + TraceThread("CoinStaker", [=]() { + // Fill Staker Args + + // Run ThreadStaker + pos::ThreadStaker threadStaker{}; + threadStaker(stakerParams, chainparams); + }); + }); + } + } return true; } diff --git a/src/masternodes/masternodes.h b/src/masternodes/masternodes.h index 0a138a38ee..bb8af654b5 100644 --- a/src/masternodes/masternodes.h +++ b/src/masternodes/masternodes.h @@ -361,7 +361,9 @@ class CMasternodesViewHistory : public CMasternodesViewCache } historyDiff.emplace(std::make_pair(lastHeight, OnUndoBlock(lastHeight))); -// DecrementMintedBy(); + CBlockIndex* pindex = ::ChainActive()[lastHeight]; + assert(pindex); + DecrementMintedBy(pindex->minter); --lastHeight; } @@ -377,7 +379,9 @@ class CMasternodesViewHistory : public CMasternodesViewCache assert(historyDiff.find(lastHeight) != historyDiff.end()); ApplyCache(&historyDiff.at(lastHeight)); -// IncrementMintedBy(); + CBlockIndex* pindex = ::ChainActive()[lastHeight]; + assert(pindex); + IncrementMintedBy(pindex->minter); } } diff --git a/src/miner.cpp b/src/miner.cpp index 9579f7b7f7..3e504a90c6 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -494,6 +494,20 @@ class Staker { CBlockIndex* tip = getTip(); + // this part of code stay valid until tip got changed + /// @todo @maxb is 'tip' can be changed here? is it possible to pull 'getTip()' and mnview access to the upper (calling 'stake()') block? + uint32_t mintedBlocks(0); + { + LOCK(cs_main); + auto nodePtr = pmasternodesview->ExistMasternode(args.masternodeID); + if (!nodePtr || !nodePtr->IsActive(tip->height)) + { + /// @todo @maxb may be new status for not activated (or already resigned) MN?? + return Status::initWaiting; + } + mintedBlocks = nodePtr->mintedBlocks; + } + withSearchInterval([&](int64_t coinstakeTime, int64_t nSearchInterval) { // // Create block template @@ -509,7 +523,7 @@ class Staker { // find matching Hash pblock->height = tip->nHeight + 1; - pblock->mintedBlocks = 0; // TODO: (SS) rewrite "0" to actual master nodes mintedBlocks + pblock->mintedBlocks = mintedBlocks + 1; // TODO: (SS) rewrite "0" to actual master nodes mintedBlocks pblock->stakeModifier = pos::ComputeStakeModifier(tip->stakeModifier, args.minterKey.GetPubKey().GetID()); bool found = false; @@ -518,7 +532,7 @@ class Staker { pblock->nTime = ((uint32_t)coinstakeTime - t); - if (pos::CheckKernelHash(pblock->stakeModifier, pblock->nBits, (int64_t) pblock->nTime, chainparams.GetConsensus(), pmasternodesview.get()).hashOk) { + if (pos::CheckKernelHash(pblock->stakeModifier, pblock->nBits, (int64_t) pblock->nTime, chainparams.GetConsensus(), args.masternodeID).hashOk) { LogPrint(BCLog::STAKING, "MakeStake: kernel found\n"); found = true; diff --git a/src/miner.h b/src/miner.h index 3526f79041..432ba52dea 100644 --- a/src/miner.h +++ b/src/miner.h @@ -216,6 +216,7 @@ namespace pos { int64_t nMaxTries = -1; CScript coinbaseScript = CScript(); CKey minterKey = CKey(); + uint256 masternodeID = uint256(); }; /// always forward by value to avoid dangling pointers diff --git a/src/pos.cpp b/src/pos.cpp index efe2dc2f86..2785d00659 100644 --- a/src/pos.cpp +++ b/src/pos.cpp @@ -40,12 +40,46 @@ bool CheckHeaderSignature(const CBlockHeader& blockHeader) { } bool CheckProofOfStake_headerOnly(const CBlockHeader& blockHeader, const Consensus::Params& params, CMasternodesView* mnView) { + + /// @todo @maxb may be this is tooooo optimistic? need more validation? + if (blockHeader.height == 0 && blockHeader.GetHash() == params.hashGenesisBlock) { + return true; + } + + // TODO: (SS) check address masternode operator in mnView + /// @todo @maxb check 'mintedBlocks' counter for this minter at this block height!!! + CKeyID minter; + if (!blockHeader.ExtractMinterKey(minter)) { + return false; + } + uint256 masternodeID; + { + // check that block minter exists and active at the height of the block + AssertLockHeld(cs_main); /// @todo @maxb or lock it + auto it = mnView->ExistMasternode(CMasternodesView::AuthIndex::ByOperator, minter); + if (!it || !mnView->ExistMasternode((*it)->second)->IsActive(blockHeader.height)) + { + return false; + } + masternodeID = (*it)->second; + } // checking PoS kernel is faster, so check it first - if (!CheckKernelHash(blockHeader.stakeModifier, blockHeader.nBits, (int64_t) blockHeader.GetBlockTime(), params, mnView).hashOk) { + if (!CheckKernelHash(blockHeader.stakeModifier, blockHeader.nBits, (int64_t) blockHeader.GetBlockTime(), params, masternodeID).hashOk) { return false; } - // TODO: (SS) check address masternode operator in mnView + /// @todo @maxb this is just an example how to get 'mintedBlocks' for given minter from the mn history. + /// I can't find in te code any checks of this counter for headers, so I leave it here. + /// But this is EXTREMELY UNOPTIMAL! Need to be moved to the upper levels to check headers in batches!!! + { + AssertLockHeld(cs_main); /// @todo @maxb or lock it + CMasternodesViewHistory history(mnView); + // minter exists and active at the height of the block - it was checked before + if (history.GetState(blockHeader.height-1).ExistMasternode(masternodeID)->mintedBlocks + 1 != blockHeader.mintedBlocks) + { + return false; + } + } return CheckHeaderSignature(blockHeader); } diff --git a/src/pos_kernel.cpp b/src/pos_kernel.cpp index 0f3d6cfecb..3594881c91 100644 --- a/src/pos_kernel.cpp +++ b/src/pos_kernel.cpp @@ -18,12 +18,12 @@ namespace pos { } CheckKernelHashRes - CheckKernelHash(uint256 stakeModifier, uint32_t nBits, int64_t coinstakeTime, const Consensus::Params& params, CMasternodesView* mnView) { + CheckKernelHash(uint256 stakeModifier, uint32_t nBits, int64_t coinstakeTime, const Consensus::Params& params, uint256 masternodeID) { // Base target arith_uint256 targetProofOfStake; targetProofOfStake.SetCompact(nBits); - uint256 masternodeID = uint256S("0"); // TODO: (SS) change to masternode activation tx hash +// uint256 masternodeID = uint256S("0"); // TODO: (SS) change to masternode activation tx hash const arith_uint256 hashProofOfStake = UintToArith256( CalcKernelHash(stakeModifier, coinstakeTime, masternodeID, params)); diff --git a/src/pos_kernel.h b/src/pos_kernel.h index 4412534019..4ac194b56b 100644 --- a/src/pos_kernel.h +++ b/src/pos_kernel.h @@ -34,7 +34,7 @@ namespace pos { /// 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, const Consensus::Params& params, CMasternodesView* mnView); + CheckKernelHash(uint256 stakeModifier, uint32_t nBits, int64_t coinstakeTime, const Consensus::Params& params, uint256 masternodeID); /// Stake Modifier (hash modifier of proof-of-stake) uint256 ComputeStakeModifier(uint256 prevStakeModifier, const CKeyID& key); diff --git a/src/validation.cpp b/src/validation.cpp index e0ef1a1b83..eab76e7235 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1570,8 +1570,7 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI // move best block pointer to prevout block view.SetBestBlock(pindex->pprev->GetBlockHash()); - /// @todo @maxb temp removed due to assertion -// mnview.DecrementMintedBy(CKeyID()); /// @todo @maxb pindex->pprev->minter or smth + mnview.DecrementMintedBy(pindex->minter); mnview.SetLastHeight(pindex->pprev->nHeight); return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; @@ -2041,8 +2040,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl assert(pindex->phashBlock); // add this block to the view's block chain view.SetBestBlock(pindex->GetBlockHash()); - /// @todo @maxb temp removed due to assertion -// mnview.IncrementMintedBy(CKeyID()); /// @todo @maxb pindex->minter or smth + mnview.IncrementMintedBy(pindex->minter); mnview.SetLastHeight(pindex->nHeight); int64_t nTime5 = GetTimeMicros(); nTimeIndex += nTime5 - nTime4; From 5f6000827a0ee521d90bc6b5028dbd27f9897cd7 Mon Sep 17 00:00:00 2001 From: Ahmed Hilali Date: Mon, 30 Sep 2019 13:59:11 +0700 Subject: [PATCH 02/30] mn & pos integration; WIP - mint working, but not optimal --- src/masternodes/masternodes.h | 2 +- src/masternodes/mn_rpc.cpp | 40 +++++++++++++++++------------------ src/miner.cpp | 13 +++++++----- src/pos.cpp | 6 ++++-- src/pos.h | 2 +- src/validation.cpp | 12 ++++++++--- 6 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/masternodes/masternodes.h b/src/masternodes/masternodes.h index bb8af654b5..52ba94a864 100644 --- a/src/masternodes/masternodes.h +++ b/src/masternodes/masternodes.h @@ -91,7 +91,7 @@ class CMasternode { // Special case for genesis block if (creationHeight == 0) - return h > 0 && (resignHeight == -1 || resignHeight > h); + return resignHeight == -1 || resignHeight > h; return creationHeight + GetMnActivationDelay() <= h && (resignHeight == -1 || resignHeight > h); } diff --git a/src/masternodes/mn_rpc.cpp b/src/masternodes/mn_rpc.cpp index 7744059dd1..36ed0a1dbe 100644 --- a/src/masternodes/mn_rpc.cpp +++ b/src/masternodes/mn_rpc.cpp @@ -43,27 +43,27 @@ extern bool DecodeHexTx(CTransaction & tx, std::string const & strHexTx); // in extern void ScriptPubKeyToJSON(CScript const & scriptPubKey, UniValue & out, bool fIncludeHex); // in rawtransaction.cpp -namespace { -// stolen from rpc_tests.cpp, can't import cause it's in tests module (not linked in main binary) -UniValue CallRPC(std::string args) -{ - std::vector vArgs; - boost::split(vArgs, args, boost::is_any_of(" \t")); - std::string strMethod = vArgs[0]; - vArgs.erase(vArgs.begin()); - JSONRPCRequest request; - request.strMethod = strMethod; - request.params = RPCConvertValues(strMethod, vArgs); - request.fHelp = false; - - if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished(); - - // nothing to "try/catch" here, will be passed over - UniValue result = tableRPC.execute(request); - return result; -} +//namespace { +//// stolen from rpc_tests.cpp, can't import cause it's in tests module (not linked in main binary) +//UniValue CallRPC(std::string args) +//{ +// std::vector vArgs; +// boost::split(vArgs, args, boost::is_any_of(" \t")); +// std::string strMethod = vArgs[0]; +// vArgs.erase(vArgs.begin()); +// JSONRPCRequest request; +// request.strMethod = strMethod; +// request.params = RPCConvertValues(strMethod, vArgs); +// request.fHelp = false; + +// if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished(); + +// // nothing to "try/catch" here, will be passed over +// UniValue result = tableRPC.execute(request); +// return result; +//} -} // namespace +//} // namespace void EnsureBlocksDownloaded() { diff --git a/src/miner.cpp b/src/miner.cpp index 3e504a90c6..f5b4b8e539 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -556,10 +556,13 @@ class Staker { // // Final checks // - err = CheckSignedBlock(pblock, tip, chainparams); - if (err) { - LogPrint(BCLog::STAKING, "CheckSignedBlock(): %s \n", *err); - return; + { + LOCK(cs_main); + err = CheckSignedBlock(pblock, tip, chainparams, args.minterKey.GetPubKey().GetID()); + if (err) { + LogPrint(BCLog::STAKING, "CheckSignedBlock(): %s \n", *err); + return; + } } if (!ProcessNewBlock(chainparams, pblock, true, nullptr)) { @@ -613,7 +616,7 @@ class Staker { return {}; } - boost::optional CheckSignedBlock(const std::shared_ptr& pblock, const CBlockIndex* pindexPrev, const CChainParams& chainparams) { + boost::optional CheckSignedBlock(const std::shared_ptr& pblock, const CBlockIndex* pindexPrev, const CChainParams& chainparams, CKeyID minter) { uint256 hashBlock = pblock->GetHash(); // verify hash target and signature of coinstake tx diff --git a/src/pos.cpp b/src/pos.cpp index 2785d00659..246aaf0ca1 100644 --- a/src/pos.cpp +++ b/src/pos.cpp @@ -11,6 +11,7 @@ static bool CheckStakeModifier(const CBlockIndex* pindexPrev, const CBlockHeader if (blockHeader.hashPrevBlock.IsNull()) return blockHeader.stakeModifier.IsNull(); + /// @todo @maxb is it possible to pass minter key here, or we really need to extract it srom sig??? CKeyID key; if (!blockHeader.ExtractMinterKey(key)) { LogPrintf("CheckStakeModifier: Can't extract minter key\n"); @@ -39,7 +40,7 @@ bool CheckHeaderSignature(const CBlockHeader& blockHeader) { return true; } -bool CheckProofOfStake_headerOnly(const CBlockHeader& blockHeader, const Consensus::Params& params, CMasternodesView* mnView) { +bool ContextualCheckProofOfStake(const CBlockHeader& blockHeader, const Consensus::Params& params, CMasternodesView* mnView) { /// @todo @maxb may be this is tooooo optimistic? need more validation? if (blockHeader.height == 0 && blockHeader.GetHash() == params.hashGenesisBlock) { @@ -89,7 +90,8 @@ bool CheckProofOfStake(const CBlockHeader& blockHeader, const CBlockIndex* pinde return false; } - return CheckProofOfStake_headerOnly(blockHeader, params, mnView); + /// @todo @max this is our own check of own minted block (just to remember) + return ContextualCheckProofOfStake(blockHeader, params, mnView); } unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params::PoS& params) diff --git a/src/pos.h b/src/pos.h index 288ea8b46d..bcea46ad12 100644 --- a/src/pos.h +++ b/src/pos.h @@ -19,7 +19,7 @@ namespace pos { bool CheckHeaderSignature(const CBlockHeader& block); /// Check kernel hash target and coinstake signature - bool CheckProofOfStake_headerOnly(const CBlockHeader& blockHeader, const Consensus::Params& params, CMasternodesView* mnView); + bool ContextualCheckProofOfStake(const CBlockHeader& blockHeader, const Consensus::Params& params, CMasternodesView* mnView); /// Check kernel hash target and coinstake signature. Check that block coinstakeTx matches header bool CheckProofOfStake(const CBlockHeader& blockHeader, const CBlockIndex* pindexPrev, const Consensus::Params& params, CMasternodesView* mnView); diff --git a/src/validation.cpp b/src/validation.cpp index eab76e7235..5e2fb19f8f 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -975,7 +975,11 @@ bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::P } // Check the header - if (!pos::CheckProofOfStake_headerOnly(block, consensusParams, pmasternodesview.get())) + + /// @maxb @todo del me: +// if (!pos::ContextualCheckProofOfStake(block, consensusParams, pmasternodesview.get())) + + if (!pos::CheckHeaderSignature(block)) return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); return true; @@ -2040,6 +2044,8 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl assert(pindex->phashBlock); // add this block to the view's block chain view.SetBestBlock(pindex->GetBlockHash()); + + block.ExtractMinterKey(pindex->minter); mnview.IncrementMintedBy(pindex->minter); mnview.SetLastHeight(pindex->nHeight); @@ -3059,7 +3065,7 @@ static bool FindUndoPos(CValidationState &state, int nFile, FlatFilePos &pos, un static bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true) { - if (fCheckPOW && !pos::CheckProofOfStake_headerOnly(block, consensusParams, pmasternodesview.get())) + if (fCheckPOW && !pos::ContextualCheckProofOfStake(block, consensusParams, pmasternodesview.get())) return state.Invalid(ValidationInvalidReason::BLOCK_INVALID_HEADER, false, REJECT_INVALID, "high-hash", "proof of stake failed"); return true; } @@ -3366,7 +3372,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState return true; } - if (!pos::CheckProofOfStake_headerOnly(block, chainparams.GetConsensus(), pmasternodesview.get())) + if (!pos::ContextualCheckProofOfStake(block, chainparams.GetConsensus(), pmasternodesview.get())) return error("%s: Consensus::CheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); // Get prev block index From d30da2cdecc8a7f09331d9697999d7a9ec8f2ac3 Mon Sep 17 00:00:00 2001 From: Ahmed Hilali Date: Tue, 1 Oct 2019 11:41:44 +0700 Subject: [PATCH 03/30] mn: resign delay and history bug fixes --- src/chainparams.cpp | 3 ++ src/consensus/params.h | 1 + src/masternodes/masternodes.cpp | 63 ++++++++++++++++++--------------- src/masternodes/masternodes.h | 9 ++--- src/masternodes/mn_rpc.cpp | 4 ++- 5 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index b61e10272e..acf69546d3 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -142,6 +142,7 @@ class CMainParams : public CChainParams { // Masternodes' params consensus.mn.activationDelay = 1500; + consensus.mn.resignDelay = 300; consensus.mn.collateralUnlockDelay = 300; consensus.mn.creationFee = 1 * COIN; consensus.mn.collateralAmount = 100 * COIN; @@ -261,6 +262,7 @@ class CTestNetParams : public CChainParams { // Masternodes' params consensus.mn.activationDelay = 10; + consensus.mn.resignDelay = 10; consensus.mn.collateralUnlockDelay = 10; consensus.mn.creationFee = 1 * COIN; consensus.mn.collateralAmount = 10 * COIN; @@ -358,6 +360,7 @@ class CRegTestParams : public CChainParams { // Masternodes' params consensus.mn.activationDelay = 10; + consensus.mn.resignDelay = 10; consensus.mn.collateralUnlockDelay = 10; consensus.mn.creationFee = 1 * COIN; consensus.mn.collateralAmount = 10 * COIN; diff --git a/src/consensus/params.h b/src/consensus/params.h index a9dee5ccb6..7cb54bf3b1 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -97,6 +97,7 @@ struct Params { CAmount creationFee; CAmount collateralAmount; int activationDelay; + int resignDelay; int collateralUnlockDelay; int historyFrame; }; diff --git a/src/masternodes/masternodes.cpp b/src/masternodes/masternodes.cpp index eb11914f11..d6707e02a8 100644 --- a/src/masternodes/masternodes.cpp +++ b/src/masternodes/masternodes.cpp @@ -28,6 +28,11 @@ int GetMnActivationDelay() return Params().GetConsensus().mn.activationDelay; } +int GetMnResignDelay() +{ + return Params().GetConsensus().mn.resignDelay; +} + int GetMnCollateralUnlockDelay() { return Params().GetConsensus().mn.collateralUnlockDelay; @@ -91,15 +96,15 @@ void CMasternode::FromTx(CTransaction const & tx, int heightIn, std::vector h) { status += ", resigned"; } @@ -264,7 +269,9 @@ CMasternodesViewCache CMasternodesView::OnUndoBlock(int height) blocksUndo[height] = {}; } backup.lastHeight = lastHeight; - --lastHeight; + + /// @attention do NOT do THIS!!! it will be done separately by outer SetLastHeight()! +// --lastHeight; return backup; // it is new value diff for height+1 } @@ -321,30 +328,31 @@ CMasternodesViewCache CMasternodesView::OnUndoBlock(int height) /// Call it only for "clear" and "full" (not cached) view void CMasternodesView::PruneOlder(int height) { + return; /// @todo @max temporary off +// /// @todo @max add foolproof (for heights, teams and collateral) +// if (height < 0) +// { +// return; +// } - /// @todo @max add foolproof (for heights, teams and collateral) - if (height < 0) - { - return; - } - - // erase dead nodes - for (auto && it = allNodes.begin(); it != allNodes.end(); ) - { - CMasternode const & node = it->second; - if(node.resignHeight != -1 && node.resignHeight < height) - { - nodesByOwner.erase(node.ownerAuthAddress); - nodesByOperator.erase(node.operatorAuthAddress); - it = allNodes.erase(it); - } - else ++it; - } +// // erase dead nodes +// for (auto && it = allNodes.begin(); it != allNodes.end(); ) +// { +// CMasternode const & node = it->second; +// /// @todo @maxb adjust heights (prune delay method?) +// if(node.resignHeight != -1 && node.resignHeight + < height) +// { +// nodesByOwner.erase(node.ownerAuthAddress); +// nodesByOperator.erase(node.operatorAuthAddress); +// it = allNodes.erase(it); +// } +// else ++it; +// } - // erase undo info - blocksUndo.erase(blocksUndo.begin(), blocksUndo.lower_bound(height)); - // erase old teams info -// teams.erase(teams.begin(), teams.lower_bound(height)); +// // erase undo info +// blocksUndo.erase(blocksUndo.begin(), blocksUndo.lower_bound(height)); +// // erase old teams info +//// teams.erase(teams.begin(), teams.lower_bound(height)); } boost::optional CMasternodesView::AmI(AuthIndex where) const @@ -462,4 +470,3 @@ MasternodesTxType GuessMasternodeTxType(CTransaction const & tx, std::vectorsecond; } - diff --git a/src/masternodes/masternodes.h b/src/masternodes/masternodes.h index 52ba94a864..c5ac18f374 100644 --- a/src/masternodes/masternodes.h +++ b/src/masternodes/masternodes.h @@ -48,6 +48,7 @@ inline void Unserialize(Stream& s, MasternodesTxType & txType) { // Works instead of constants cause 'regtest' differs (don't want to overcharge chainparams) int GetMnActivationDelay(); +int GetMnResignDelay(); int GetMnCollateralUnlockDelay(); int GetMnHistoryFrame(); CAmount GetMnCollateralAmount(); @@ -91,12 +92,12 @@ class CMasternode { // Special case for genesis block if (creationHeight == 0) - return resignHeight == -1 || resignHeight > h; + return resignHeight == -1 || resignHeight + GetMnResignDelay() > h; - return creationHeight + GetMnActivationDelay() <= h && (resignHeight == -1 || resignHeight > h); + return creationHeight + GetMnActivationDelay() <= h && (resignHeight == -1 || resignHeight + GetMnResignDelay() > h); } - std::string GetHumanReadableStatus() const; + std::string GetHumanReadableStatus(int h = ::ChainActive().Height()) const; ADD_SERIALIZE_METHODS; @@ -352,7 +353,7 @@ class CMasternodesViewHistory : public CMasternodesViewCache { // go backward (undo) - for (; lastHeight >= targetHeight; ) + for (; lastHeight > targetHeight; ) { auto it = historyDiff.find(lastHeight); if (it != historyDiff.end()) diff --git a/src/masternodes/mn_rpc.cpp b/src/masternodes/mn_rpc.cpp index 36ed0a1dbe..ca7c858b0b 100644 --- a/src/masternodes/mn_rpc.cpp +++ b/src/masternodes/mn_rpc.cpp @@ -351,7 +351,8 @@ UniValue mn_resign(const JSONRPCRequest& request) auto nodePtr = pmasternodesview->ExistMasternode(nodeId); if (!nodePtr->resignTx.IsNull()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Masternode %s was resigned by tx %s; collateral can be spend at block #%d", nodeIdStr, nodePtr->resignTx.GetHex(), nodePtr->resignHeight+GetMnActivationDelay())); + /// @todo @max adjust delays and heights! + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Masternode %s was resigned by tx %s; collateral can be spend at block #%d", nodeIdStr, nodePtr->resignTx.GetHex(), nodePtr->resignHeight + GetMnCollateralUnlockDelay() /*+ GetMnResignDelay() ???*/)); } CMutableTransaction rawTx; @@ -404,6 +405,7 @@ UniValue mnToJSON(CMasternode const & node) ret.pushKV("resignTx", node.resignTx.GetHex()); ret.pushKV("status", node.GetHumanReadableStatus()); + /// @todo @maxb add unlock height and|or real resign height return ret; } From 85d2679f0375c625e7812819f09710f9ca2c603d Mon Sep 17 00:00:00 2001 From: Ahmed Hilali Date: Mon, 30 Sep 2019 18:04:40 +0700 Subject: [PATCH 04/30] replace PoW mining to PoS minting in generateBlocks function --- src/miner.cpp | 31 ++++-------------- src/miner.h | 26 ++++++++++++++- src/rpc/mining.cpp | 81 ++++++++++++++++++++++++++++------------------ 3 files changed, 80 insertions(+), 58 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index f5b4b8e539..712e6c8cb1 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -20,7 +20,6 @@ #include #include #include