diff --git a/src/masternodes/mn_checks.cpp b/src/masternodes/mn_checks.cpp index fd52cce7c9..9098b8f54d 100644 --- a/src/masternodes/mn_checks.cpp +++ b/src/masternodes/mn_checks.cpp @@ -1132,6 +1132,10 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor return Res::Err("wrong commission"); } + if (height >= static_cast(Params().GetConsensus().FortCanningCrunchHeight) && obj.pairSymbol.find('/') != std::string::npos) { + return Res::Err("token symbol should not contain '/'"); + } + /// @todo ownerAddress validity checked only in rpc. is it enough? CPoolPair poolPair(obj.poolPair); auto pairSymbol = obj.pairSymbol; diff --git a/src/miner.cpp b/src/miner.cpp index aadb024b45..e54f86e08c 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -231,7 +231,14 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc uint32_t entries{1}; mnview.ForEachPoolPair([&, id = id](DCT_ID const & poolId, const CPoolPair& pool){ if (pool.idTokenA.v == id || pool.idTokenB.v == id) { - ++entries; + const auto tokenA = mnview.GetToken(pool.idTokenA); + const auto tokenB = mnview.GetToken(pool.idTokenB); + assert(tokenA); + assert(tokenB); + if ((tokenA->destructionHeight == -1 && tokenA->destructionTx == uint256{}) && + (tokenB->destructionHeight == -1 && tokenB->destructionTx == uint256{})) { + ++entries; + } } return true; }); diff --git a/src/validation.cpp b/src/validation.cpp index 10772e11f0..ed09c3d5f6 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2781,7 +2781,14 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl std::vector poolsToMigrate; accountsView.ForEachPoolPair([&, id = id](DCT_ID const & poolId, const CPoolPair& pool){ if (pool.idTokenA.v == id || pool.idTokenB.v == id) { - poolsToMigrate.push_back(poolId); + const auto tokenA = accountsView.GetToken(pool.idTokenA); + const auto tokenB = accountsView.GetToken(pool.idTokenB); + assert(tokenA); + assert(tokenB); + if ((tokenA->destructionHeight == -1 && tokenA->destructionTx == uint256{}) && + (tokenB->destructionHeight == -1 && tokenB->destructionTx == uint256{})) { + poolsToMigrate.push_back(poolId); + } } return true; }); @@ -3763,7 +3770,7 @@ static inline T CalculateNewAmount(const int multiplier, const T amount) { } static Res PoolSplits(CCustomCSView& view, CAmount& totalBalance, ATTRIBUTES& attributes, const DCT_ID oldTokenId, const DCT_ID newTokenId, - const CBlockIndex* pindex, const CreationTxs& creationTxs, const std::string& newTokenSuffix, const int32_t multiplier) { + const CBlockIndex* pindex, const CreationTxs& creationTxs, const int32_t multiplier) { try { assert(creationTxs.count(oldTokenId.v)); @@ -3778,7 +3785,26 @@ static Res PoolSplits(CCustomCSView& view, CAmount& totalBalance, ATTRIBUTES& at newPoolToken.creationTx = creationTx; newPoolToken.minted = 0; - oldPoolToken->symbol += newTokenSuffix; + size_t suffixCount{1}; + view.ForEachPoolPair([&, oldTokenId = oldTokenId](DCT_ID const & poolId, const CPoolPair& pool){ + if (pool.idTokenA == oldTokenId || pool.idTokenB == oldTokenId) { + const auto tokenA = view.GetToken(pool.idTokenA); + const auto tokenB = view.GetToken(pool.idTokenB); + assert(tokenA); + assert(tokenB); + if ((tokenA->destructionHeight != -1 && tokenA->destructionTx != uint256{}) || + (tokenB->destructionHeight != -1 && tokenB->destructionTx != uint256{})) { + const auto poolToken = view.GetToken(poolId); + assert(poolToken); + if (poolToken->symbol.find(oldPoolToken->symbol + "/v") != std::string::npos) { + ++suffixCount; + } + } + } + return true; + }); + + oldPoolToken->symbol += "/v" + std::to_string(suffixCount); oldPoolToken->flags |= static_cast(CToken::TokenFlags::Tradeable); oldPoolToken->destructionHeight = pindex->nHeight; oldPoolToken->destructionTx = pindex->GetBlockHash(); @@ -4171,7 +4197,7 @@ void CChainState::ProcessTokenSplits(const CBlock& block, const CBlockIndex* pin CAmount totalBalance{0}; - res = PoolSplits(view, totalBalance, *attributes, oldTokenId, newTokenId, pindex, creationTxs,newTokenSuffix, multiplier); + res = PoolSplits(view, totalBalance, *attributes, oldTokenId, newTokenId, pindex, creationTxs, multiplier); if (!res) { LogPrintf("%s: Token split failed. %s\n", __func__, res.msg); continue;