From 9944d9931fab92c00771f929a8fd2501b1863225 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 10 Feb 2022 05:09:50 +0800 Subject: [PATCH 01/61] Added new -nftindex param --- src/init.cpp | 7 +++++++ src/main.cpp | 1 + src/main.h | 1 + 3 files changed, 9 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 63611c227..647729bdc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -427,6 +427,7 @@ std::string HelpMessage(HelpMessageMode mode) #endif strUsage += HelpMessageOpt("-allindex", strprintf(_("Maintain all indexes supported (default: %u)"), false)); strUsage += HelpMessageOpt("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), DEFAULT_TXINDEX)); + strUsage += HelpMessageOpt("-nftindex", strprintf(_("Maintain an index of ntf data, used by the nft related rpc calls (default: %u)"), DEFAULT_NFTINDEX)); strUsage += HelpMessageOpt("-addressindex", strprintf(_("Maintain a full address index, used to query for the balance, txids and unspent outputs for addresses (default: %u)"), DEFAULT_ADDRESSINDEX)); strUsage += HelpMessageOpt("-timestampindex", strprintf(_("Maintain a timestamp index for block hashes, used to query blocks hashes by a range of timestamps (default: %u)"), DEFAULT_TIMESTAMPINDEX)); @@ -1629,6 +1630,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler, const std break; } + // Check for changed -nftindex state + if (fNftIndex != GetBoolArg("-nftindex", DEFAULT_NFTINDEX)) { + strLoadError = _("You need to rebuild the database using -reindex-chainstate to change -nftindex"); + break; + } + // Check for changed -addressindex state if (fAddressIndex != GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX)) { strLoadError = _("You need to rebuild the database using -reindex-chainstate to change -addressindex"); diff --git a/src/main.cpp b/src/main.cpp index 99e5db517..ef3e5fe12 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7721,6 +7721,7 @@ bool InitBlockIndex(const CChainParams& chainparams) // Load the flag values | use DEFAULT_* values if not set fTxIndex = GetBoolArg("-txindex", DEFAULT_TXINDEX); + fNftIndex = GetBoolArg("-nftindex", DEFAULT_NFTINDEX); fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX); fTimestampIndex = GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX); fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX); diff --git a/src/main.h b/src/main.h index 370aef5d0..6657dd6be 100644 --- a/src/main.h +++ b/src/main.h @@ -146,6 +146,7 @@ static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; static const bool DEFAULT_PERMIT_BAREMULTISIG = true; static const bool DEFAULT_CHECKPOINTS_ENABLED = true; static const bool DEFAULT_TXINDEX = false; +static const bool DEFAULT_NFTINDEX = false; static const bool DEFAULT_ADDRESSINDEX = false; static const bool DEFAULT_TIMESTAMPINDEX = false; static const bool DEFAULT_SPENTINDEX = false; From c6abfe3b9fcb5e3e850524df85598d71a89c5c5d Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 10 Feb 2022 05:28:35 +0800 Subject: [PATCH 02/61] Added missing declaration --- src/main.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.h b/src/main.h index 6657dd6be..95d58fcbb 100644 --- a/src/main.h +++ b/src/main.h @@ -204,6 +204,7 @@ extern bool fReindex; extern bool fVerifyChain; extern int nScriptCheckThreads; extern bool fTxIndex; +extern bool fNftIndex; extern bool fAddressIndex; extern bool fSpentIndex; extern bool fTimestampIndex; From 192a342b145fb8ee53f9156365869ff26afba8a7 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 10 Feb 2022 06:00:12 +0800 Subject: [PATCH 03/61] Added missing declaration --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index ef3e5fe12..21e0cbe06 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -78,6 +78,7 @@ bool fImporting = false; bool fReindex = false; bool fVerifyChain = false; bool fTxIndex = false; +bool fNftIndex = false; bool fAddressIndex = false; bool fTimestampIndex = false; bool fSpentIndex = false; From 7f62acf74f86a77df9a107ee47b0cc137fbca638 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 14:00:46 +0800 Subject: [PATCH 04/61] Updated ALLINDEX --- src/init.cpp | 2 +- src/main.cpp | 4 ++-- src/main.h | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 647729bdc..8ed2f530f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -425,7 +425,7 @@ std::string HelpMessage(HelpMessageMode mode) #ifndef WIN32 strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)")); #endif - strUsage += HelpMessageOpt("-allindex", strprintf(_("Maintain all indexes supported (default: %u)"), false)); + strUsage += HelpMessageOpt("-allindex", strprintf(_("Maintain all indexes supported (default: %u)"), DEFAULT_ALLINDEX)); strUsage += HelpMessageOpt("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), DEFAULT_TXINDEX)); strUsage += HelpMessageOpt("-nftindex", strprintf(_("Maintain an index of ntf data, used by the nft related rpc calls (default: %u)"), DEFAULT_NFTINDEX)); diff --git a/src/main.cpp b/src/main.cpp index 21e0cbe06..25df4d9fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7728,9 +7728,9 @@ bool InitBlockIndex(const CChainParams& chainparams) fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX); // Check if we want all indexes - if (GetBoolArg("-allindex", false)) + if (GetBoolArg("-allindex", DEFAULT_ALLINDEX)) { - fTxIndex = fAddressIndex = fTimestampIndex = fSpentIndex = true; + fTxIndex = fNftIndex = fAddressIndex = fTimestampIndex = fSpentIndex = true; } // Use the provided setting for -txindex in the new database diff --git a/src/main.h b/src/main.h index 95d58fcbb..094392880 100644 --- a/src/main.h +++ b/src/main.h @@ -145,6 +145,7 @@ static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; /** Default for -permitbaremultisig */ static const bool DEFAULT_PERMIT_BAREMULTISIG = true; static const bool DEFAULT_CHECKPOINTS_ENABLED = true; +static const bool DEFAULT_ALLINDEX = false; static const bool DEFAULT_TXINDEX = false; static const bool DEFAULT_NFTINDEX = false; static const bool DEFAULT_ADDRESSINDEX = false; From 152b3de2ff873993298144d7457011b08a435c46 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 14:22:14 +0800 Subject: [PATCH 05/61] Updated some whitespace in rpcwallet --- src/wallet/rpcwallet.cpp | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8a5dafa6f..05b2fd48c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4116,30 +4116,30 @@ UniValue gettransaction(const UniValue& params, bool fHelp) "\nResult:\n" "{\n" " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"blockhash\" : \"hash\", (string) The block hash\n" - " \"blockindex\" : xx, (numeric) The index of the transaction in the block that includes it\n" - " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n" - " \"txid\" : \"transactionid\", (string) The transaction id.\n" - " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n" - " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n" - " \"bip125-replaceable\": \"yes|no|unknown\" (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" - " may be unknown for unconfirmed transactions not in the mempool\n" - " \"details\" : [\n" - " {\n" - " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n" - " \"address\" : \"navcoinaddress\", (string) The navcoin address involved in the transaction\n" - " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n" - " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n" - " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n" - " \"vout\" : n, (numeric) the vout value\n" - " }\n" - " ,...\n" - " ],\n" - " \"hex\" : \"data\" (string) Raw data for transaction\n" - "}\n" - - "\nExamples:\n" + " \"confirmations\" : n, (numeric) The number of confirmations\n" + " \"blockhash\" : \"hash\", (string) The block hash\n" + " \"blockindex\" : xx, (numeric) The index of the transaction in the block that includes it\n" + " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n" + " \"txid\" : \"transactionid\", (string) The transaction id.\n" + " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n" + " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n" + " \"bip125-replaceable\": \"yes|no|unknown\" (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" + " may be unknown for unconfirmed transactions not in the mempool\n" + " \"details\" : [\n" + " {\n" + " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n" + " \"address\" : \"navcoinaddress\", (string) The navcoin address involved in the transaction\n" + " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n" + " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n" + " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n" + " \"vout\" : n, (numeric) the vout value\n" + " }\n" + " ,...\n" + " ],\n" + " \"hex\" : \"data\" (string) Raw data for transaction\n" + "}\n" + + "\nExamples:\n" + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true") + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") From b4be8131e8e7414e1e479bccf15b290a42125322 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 15:04:35 +0800 Subject: [PATCH 06/61] Added nftindex flags to blocktree logic --- src/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 25df4d9fe..58152df29 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7299,6 +7299,10 @@ bool static LoadBlockIndexDB() pblocktree->ReadFlag("txindex", fTxIndex); LogPrintf("%s: transaction index %s\n", __func__, fTxIndex ? "enabled" : "disabled"); + // Check whether we have an nft index + pblocktree->ReadFlag("nftindex", fNftIndex); + LogPrintf("%s: nft index %s\n", __func__, fNftIndex ? "enabled" : "disabled"); + // Check whether we have an address index pblocktree->ReadFlag("addressindex", fAddressIndex); LogPrintf("%s: address index %s\n", __func__, fAddressIndex ? "enabled" : "disabled"); @@ -7737,6 +7741,10 @@ bool InitBlockIndex(const CChainParams& chainparams) pblocktree->WriteFlag("txindex", fTxIndex); LogPrintf("%s: transaction index %s\n", __func__, fTxIndex ? "enabled" : "disabled"); + // Use the provided setting for -nftindex in the new database + pblocktree->WriteFlag("nftindex", fNftIndex); + LogPrintf("%s: nft index %s\n", __func__, fNftIndex ? "enabled" : "disabled"); + // Use the provided setting for -addressindex in the new database pblocktree->WriteFlag("addressindex", fAddressIndex); LogPrintf("%s: address index %s\n", __func__, fAddressIndex ? "enabled" : "disabled"); From 5e21f5376e8c34431f66127d767ef30928919227 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 15:31:34 +0800 Subject: [PATCH 07/61] Added txdb functions for nft index --- src/txdb.cpp | 12 ++++++++++++ src/txdb.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/txdb.cpp b/src/txdb.cpp index 35bf1e2dd..97748bf1f 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -758,6 +758,18 @@ bool CBlockTreeDB::UpdateAddressUnspentIndex(const std::vector >&vect) { + CDBBatch batch(*this); + for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) { + if (it->second.IsNull()) { + batch.Erase(std::make_pair(DB_NFTUNSPENTINDEX, it->first)); + } else { + batch.Write(std::make_pair(DB_NFTUNSPENTINDEX, it->first), it->second); + } + } + return WriteBatch(batch); +} + bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &unspentOutputs) { diff --git a/src/txdb.h b/src/txdb.h index c84528c5c..c4abac721 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -180,6 +180,7 @@ class CBlockTreeDB : public CDBWrapper bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); bool UpdateSpentIndex(const std::vector >&vect); bool UpdateAddressUnspentIndex(const std::vector >&vect); + bool UpdateNftUnspentIndex(const std::vector >&vect); bool ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &vect); bool WriteAddressIndex(const std::vector > &vect); From ee4040bc01c7fa038d6b442377019ad5adb621d0 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 16:36:38 +0800 Subject: [PATCH 08/61] Added nft index update calls to Connect/Disconnect block --- src/main.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 58152df29..cd3b173e4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2872,6 +2872,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI std::vector > addressHistory; std::map addressHistoryMap; std::vector > addressUnspentIndex; + std::vector > nftUnspentIndex; std::vector > spentIndex; bool fCFund = IsCommunityFundEnabled(pindex->pprev, Params().GetConsensus()); @@ -2927,9 +2928,10 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) { + auto tokenId; if (program.action == MINT) { - auto tokenId = SerializeHash(program.kParameters[0]); + tokenId = SerializeHash(program.kParameters[0]); if (!view.HaveToken(tokenId)) { @@ -2951,7 +2953,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } else if (program.action == BURN) { - auto tokenId = txout.tokenId.token; + tokenId = txout.tokenId.token; if (!view.HaveToken(tokenId)) { @@ -2967,11 +2969,11 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } else if (program.action == CREATE_TOKEN) { - auto tokenId = SerializeHash(program.kParameters[0]); + tokenId = SerializeHash(program.kParameters[0]); view.RemoveToken(tokenId); } else if (program.action == STOP_MINT) { - auto tokenId = SerializeHash(program.kParameters[0]); + tokenId = SerializeHash(program.kParameters[0]); if (!view.HaveToken(tokenId)) { @@ -2982,6 +2984,20 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI token->canMint = true; } + + if (fNftIndex) { + if (!viewMemPool.HaveToken(tokenId)) + { + return state.DoS(100, false, REJECT_INVALID, "wrong-token-id"); + } + + TokenModifier token = view.ModifyToken(tokenId); + + // Check if we have an nft + if (token->nVersion == 1) { + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId), CNftUnspentIndexValue())); + } + } } if (fDotNav) { @@ -3387,6 +3403,10 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI return true; } + if (fNftIndex) + if (!pblocktree->UpdateNftUnspentIndex(nftUnspentIndex)) + return AbortNode(state, "Failed to write nft unspent index"); + if (fAddressIndex) { if (!pblocktree->EraseAddressIndex(addressIndex)) { return AbortNode(state, "Failed to delete address index"); @@ -4034,6 +4054,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::vector > addressHistory; std::map addressHistoryMap; std::vector > addressUnspentIndex; + std::vector > nftUnspentIndex; std::vector > spentIndex; CCheckQueueControl control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : nullptr); @@ -4768,8 +4789,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "error-program-vdata"); } if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) { + auto tokenId; + if (program.action == MINT) { - auto tokenId = SerializeHash(program.kParameters[0]); + tokenId = SerializeHash(program.kParameters[0]); if (!view.HaveToken(tokenId)) { @@ -4798,7 +4821,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "unknown-token-version"); } } else if (program.action == BURN) { - auto tokenId = vout.tokenId.token; + tokenId = vout.tokenId.token; if (!view.HaveToken(tokenId)) { @@ -4820,7 +4843,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "cant-burn"); } } else if (program.action == CREATE_TOKEN) { - auto tokenId = SerializeHash(program.kParameters[0]); + tokenId = SerializeHash(program.kParameters[0]); if (view.HaveToken(tokenId)) { @@ -4835,7 +4858,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin view.AddToken(std::make_pair(tokenId, token)); } else if (program.action == STOP_MINT) { - auto tokenId = SerializeHash(program.kParameters[0]); + tokenId = SerializeHash(program.kParameters[0]); if (!view.HaveToken(tokenId)) { @@ -4850,6 +4873,20 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "cant-stop-minting"); } } + + if (fNftIndex) { + if (!viewMemPool.HaveToken(tokenId)) + { + return state.DoS(100, false, REJECT_INVALID, "wrong-token-id"); + } + + TokenModifier token = view.ModifyToken(tokenId); + + // Check if we have an nft + if (token->nVersion == 1) { + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId), CNftUnspentIndexValue(prevout.GetHash()))); + } + } } if (fDotNav) { @@ -5315,6 +5352,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!pblocktree->WriteTxIndex(vPos)) return AbortNode(state, "Failed to write transaction index"); + if (fNftIndex) + if (!pblocktree->UpdateNftUnspentIndex(nftUnspentIndex)) + return AbortNode(state, "Failed to write nft unspent index"); + if (fAddressIndex) { if (!pblocktree->WriteAddressIndex(addressIndex)) { return AbortNode(state, "Failed to write address index"); From 59058630be5750a19a12f7ccb22308199264a6ca Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 16:48:28 +0800 Subject: [PATCH 09/61] Added nftunspendindex.h --- src/nftunspentindex.h | 65 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/nftunspentindex.h diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h new file mode 100644 index 000000000..621e26ed6 --- /dev/null +++ b/src/nftunspentindex.h @@ -0,0 +1,65 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef NAVCOIN_NFTUNSPENTINDEX_H +#define NAVCOIN_NFTUNSPENTINDEX_H + +#include + +struct CNftUnspentIndexKey { + uint256 tokenId; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(tokenId); + } + + CNftUnspentIndexKey(uint256 t) { + tokenId = t; + } + + CNftUnspentIndexKey() { + SetNull(); + } + + void SetNull() { + tokenId.SetNull(); + } +}; + +struct CNftUnspentIndexValue { + uint256 tokenId; + uint256 txHash; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(tokenId); + READWRITE(txHash); + } + + CNftUnspentIndexValue(uint256 t, uint256 h) { + tokenId = t; + txHash = h; + } + + CNftUnspentIndexValue() { + SetNull(); + } + + void SetNull() { + tokenId.SetNull(); + txHash.SetNull(); + } + + bool IsNull() const { + return tokenId.IsNull(); + } +}; + +#endif // NAVCOIN_NFTUNSPENTINDEX_H From 29deaf7e15964cd57f497667382a90cabf792337 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 16:57:40 +0800 Subject: [PATCH 10/61] Added nftunspendindex.h --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index 2c9a61b91..a178d8315 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -91,6 +91,7 @@ endif # navcoin core # NAVCOIN_CORE_H = \ addressindex.h \ + nftunspentindex.h \ spentindex.h \ timestampindex.h \ addrman.h \ From b9cc1c27abd00e05331e29748e3d58c776bdae70 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 17:24:53 +0800 Subject: [PATCH 11/61] Updates based on alex's input --- src/main.cpp | 10 +++++----- src/main.h | 1 + src/nftunspentindex.h | 29 ++++++++++++++++++++++------- src/txdb.cpp | 4 ++-- src/txdb.h | 2 +- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index cd3b173e4..b3dceb6ed 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2928,7 +2928,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) { - auto tokenId; + uint256 tokenId; if (program.action == MINT) { tokenId = SerializeHash(program.kParameters[0]); @@ -2986,7 +2986,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } if (fNftIndex) { - if (!viewMemPool.HaveToken(tokenId)) + if (!view.HaveToken(tokenId)) { return state.DoS(100, false, REJECT_INVALID, "wrong-token-id"); } @@ -2995,7 +2995,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId), CNftUnspentIndexValue())); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId, txout.nHeight), CNftUnspentIndexValue())); } } } @@ -4789,7 +4789,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "error-program-vdata"); } if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) { - auto tokenId; + uint256 tokenId; if (program.action == MINT) { tokenId = SerializeHash(program.kParameters[0]); @@ -4884,7 +4884,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId), CNftUnspentIndexValue(prevout.GetHash()))); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId, vout.nHeight), CNftUnspentIndexValue(tokenId, prevout))); } } } diff --git a/src/main.h b/src/main.h index 094392880..11c09cbe9 100644 --- a/src/main.h +++ b/src/main.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h index 621e26ed6..e71113701 100644 --- a/src/nftunspentindex.h +++ b/src/nftunspentindex.h @@ -10,16 +10,19 @@ struct CNftUnspentIndexKey { uint256 tokenId; + int blockHeight; ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(tokenId); + READWRITE(blockHeight); } - CNftUnspentIndexKey(uint256 t) { + CNftUnspentIndexKey(uint256 t, int h) { tokenId = t; + blockHeight = h; } CNftUnspentIndexKey() { @@ -28,24 +31,25 @@ struct CNftUnspentIndexKey { void SetNull() { tokenId.SetNull(); + blockHeight = 0; } }; struct CNftUnspentIndexValue { uint256 tokenId; - uint256 txHash; + CTxOut tx; ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(tokenId); - READWRITE(txHash); + READWRITE(tx); } - CNftUnspentIndexValue(uint256 t, uint256 h) { - tokenId = t; - txHash = h; + CNftUnspentIndexValue(uint256 tid, CTxOut txout) { + tokenId = tid; + tx = txout; } CNftUnspentIndexValue() { @@ -54,7 +58,7 @@ struct CNftUnspentIndexValue { void SetNull() { tokenId.SetNull(); - txHash.SetNull(); + tx.SetNull(); } bool IsNull() const { @@ -62,4 +66,15 @@ struct CNftUnspentIndexValue { } }; +struct CNftUnspentIndexKeyCompare +{ + bool operator()(const CNftUnspentIndexKey& a, const CNftUnspentIndexKey& b) const { + if (a.tokenId == b.tokenId) { + return a.blockHeight < b.blockHeight; + } else { + return a.tokenId < b.tokenId; + } + } +}; + #endif // NAVCOIN_NFTUNSPENTINDEX_H diff --git a/src/txdb.cpp b/src/txdb.cpp index 97748bf1f..f41f919af 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -758,9 +758,9 @@ bool CBlockTreeDB::UpdateAddressUnspentIndex(const std::vector >&vect) { +bool CBlockTreeDB::UpdateNftUnspentIndex(const std::vector >&vect) { CDBBatch batch(*this); - for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) { + for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) { if (it->second.IsNull()) { batch.Erase(std::make_pair(DB_NFTUNSPENTINDEX, it->first)); } else { diff --git a/src/txdb.h b/src/txdb.h index c4abac721..25a0a28d8 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -180,7 +180,7 @@ class CBlockTreeDB : public CDBWrapper bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); bool UpdateSpentIndex(const std::vector >&vect); bool UpdateAddressUnspentIndex(const std::vector >&vect); - bool UpdateNftUnspentIndex(const std::vector >&vect); + bool UpdateNftUnspentIndex(const std::vector >&vect); bool ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &vect); bool WriteAddressIndex(const std::vector > &vect); From 10804bb965ccb7c746ff6206648622fe301096d7 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 17:27:56 +0800 Subject: [PATCH 12/61] Added new DB_NFTUNSPENTINDEX char to txdb.h --- src/txdb.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/txdb.cpp b/src/txdb.cpp index f41f919af..a836b69a2 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -26,6 +26,7 @@ static const char DB_ADDRESSUNSPENTINDEX = 'u'; static const char DB_TIMESTAMPINDEX = 's'; static const char DB_BLOCKHASHINDEX = 'z'; static const char DB_SPENTINDEX = 'q'; +static const char DB_NFTUNSPENTINDEX = 'Z'; static const char DB_BLOCK_INDEX = 'b'; static const char DB_VOTEINDEX = 'C'; From af6f3d8fead287ddd7da483710322e0a21c86e93 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 17:32:40 +0800 Subject: [PATCH 13/61] Fixed some references --- src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b3dceb6ed..b1bb5c5e2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2995,7 +2995,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId, txout.nHeight), CNftUnspentIndexValue())); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId, pindex->nHeight), CNftUnspentIndexValue())); } } } @@ -4875,7 +4875,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } if (fNftIndex) { - if (!viewMemPool.HaveToken(tokenId)) + if (!view.HaveToken(tokenId)) { return state.DoS(100, false, REJECT_INVALID, "wrong-token-id"); } @@ -4884,7 +4884,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId, vout.nHeight), CNftUnspentIndexValue(tokenId, prevout))); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId, pindex->nHeight), CNftUnspentIndexValue(tokenId, vout))); } } } From a1a4a12e8b55ce00621eead8103c25e8d790bbc3 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 17:43:38 +0800 Subject: [PATCH 14/61] Moved a line down that I think should not be on the end of the previous line --- src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index b1bb5c5e2..f8691d4d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4906,7 +4906,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, strprintf("wrong-salt-name:%s", program.sParameters[0])); if (pindex->nHeight-recordvalue.height < 6) - return state.DoS(100, false, REJECT_INVALID, strprintf("6-block-maturity-not-reached:%s", program.sParameters[0])); NameDataValues data; + return state.DoS(100, false, REJECT_INVALID, strprintf("6-block-maturity-not-reached:%s", program.sParameters[0])); + + NameDataValues data; if (view.GetNameData(DotNav::GetHashName(program.sParameters[0]), data)) { From e08a92f647c2e95c53452e750837652da2c7d784 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 18:00:41 +0800 Subject: [PATCH 15/61] Removed tokenId from CNftUnspendIndexValue --- src/nftunspentindex.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h index e71113701..43f8b3abf 100644 --- a/src/nftunspentindex.h +++ b/src/nftunspentindex.h @@ -36,19 +36,16 @@ struct CNftUnspentIndexKey { }; struct CNftUnspentIndexValue { - uint256 tokenId; CTxOut tx; ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(tokenId); READWRITE(tx); } - CNftUnspentIndexValue(uint256 tid, CTxOut txout) { - tokenId = tid; + CNftUnspentIndexValue(CTxOut txout) { tx = txout; } @@ -57,12 +54,11 @@ struct CNftUnspentIndexValue { } void SetNull() { - tokenId.SetNull(); tx.SetNull(); } bool IsNull() const { - return tokenId.IsNull(); + return tx.IsNull(); } }; From e767a3f4e48de79088265de7d46c6d625a79ba7c Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 18:20:31 +0800 Subject: [PATCH 16/61] Updated nftunspentindex to serialize the blockHeight as big indian --- src/nftunspentindex.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h index 43f8b3abf..384b7da29 100644 --- a/src/nftunspentindex.h +++ b/src/nftunspentindex.h @@ -12,12 +12,18 @@ struct CNftUnspentIndexKey { uint256 tokenId; int blockHeight; - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(tokenId); - READWRITE(blockHeight); + size_t GetSerializeSize(int nType, int nVersion) const { + return 32 + 4; + } + template + void Serialize(Stream& s, int nType, int nVersion) const { + tokenId.Serialize(s, nType, nVersion); + ser_writedata32be(s, blockHeight); + } + template + void Unserialize(Stream& s, int nType, int nVersion) { + tokenId.Unserialize(s, nType, nVersion); + blockHeight = ser_readdata32be(s); } CNftUnspentIndexKey(uint256 t, int h) { From e33412135a2d34c8f8d71da463041502f2d151ae Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 18:35:25 +0800 Subject: [PATCH 17/61] Changed blockHeight to uint32_t --- src/nftunspentindex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h index 384b7da29..ca13e59c0 100644 --- a/src/nftunspentindex.h +++ b/src/nftunspentindex.h @@ -10,7 +10,7 @@ struct CNftUnspentIndexKey { uint256 tokenId; - int blockHeight; + uint32_t blockHeight; size_t GetSerializeSize(int nType, int nVersion) const { return 32 + 4; From 6415376d70052be243b0d48304945cc739160efc Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 18:36:20 +0800 Subject: [PATCH 18/61] Updated nftunspentindex calls to not have the tokenId in value param --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index f8691d4d8..1fab69996 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4884,7 +4884,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId, pindex->nHeight), CNftUnspentIndexValue(tokenId, vout))); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId, pindex->nHeight), CNftUnspentIndexValue(vout))); } } } From 09af9b675886efb807cedddccbaf20be6512869c Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 18:36:40 +0800 Subject: [PATCH 19/61] Added a Read func for nftunspentindex --- src/txdb.cpp | 24 ++++++++++++++++++++++++ src/txdb.h | 1 + 2 files changed, 25 insertions(+) diff --git a/src/txdb.cpp b/src/txdb.cpp index a836b69a2..dbdcbc77d 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -771,6 +771,30 @@ bool CBlockTreeDB::UpdateNftUnspentIndex(const std::vector > &vect) { + boost::scoped_ptr pcursor(NewIterator()); + + pcursor->Seek(std::make_pair(DB_NFTUNSPENTINDEX, uint256())); + + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + std::pair key; + if (pcursor->GetKey(key) && key.first == DB_NFTUNSPENTINDEX && key.second.tokenId == tokenId) { + CNftUnspentIndexValue nValue; + if (pcursor->GetValue(nValue)) { + vect.push_back(std::make_pair(key.second, nValue)); + pcursor->Next(); + } else { + return error("failed to get nft unspent value"); + } + } else { + break; + } + } + + return true; +} + bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &unspentOutputs) { diff --git a/src/txdb.h b/src/txdb.h index 25a0a28d8..a7410e2c0 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -181,6 +181,7 @@ class CBlockTreeDB : public CDBWrapper bool UpdateSpentIndex(const std::vector >&vect); bool UpdateAddressUnspentIndex(const std::vector >&vect); bool UpdateNftUnspentIndex(const std::vector >&vect); + bool ReadNftUnspentIndex(uint256 tokenId, std::vector >&vect); bool ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &vect); bool WriteAddressIndex(const std::vector > &vect); From c517ba4f5d435bbcaec0d7c5205a417c57bcf497 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 18:41:47 +0800 Subject: [PATCH 20/61] Removed tokenId from CNftUnspentIndexValue --- src/nftunspentindex.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h index ca13e59c0..7a289752c 100644 --- a/src/nftunspentindex.h +++ b/src/nftunspentindex.h @@ -71,11 +71,7 @@ struct CNftUnspentIndexValue { struct CNftUnspentIndexKeyCompare { bool operator()(const CNftUnspentIndexKey& a, const CNftUnspentIndexKey& b) const { - if (a.tokenId == b.tokenId) { - return a.blockHeight < b.blockHeight; - } else { - return a.tokenId < b.tokenId; - } + return a.blockHeight < b.blockHeight; } }; From ce50c307002c5dad63c78fce854abb7af6ae4d46 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 18:45:46 +0800 Subject: [PATCH 21/61] Ops --- src/nftunspentindex.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h index 7a289752c..8f6e32749 100644 --- a/src/nftunspentindex.h +++ b/src/nftunspentindex.h @@ -71,7 +71,10 @@ struct CNftUnspentIndexValue { struct CNftUnspentIndexKeyCompare { bool operator()(const CNftUnspentIndexKey& a, const CNftUnspentIndexKey& b) const { - return a.blockHeight < b.blockHeight; + return a.blockHeight < b.blockHeight; + } else { + return a.tokenId < b.tokenId; + } } }; From 5d20e209b60a7f641c5892db04084969afaa40b0 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 19:00:13 +0800 Subject: [PATCH 22/61] Added -ntfindex=1 to stressor for tokens --- contrib/stressor_token.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/stressor_token.sh b/contrib/stressor_token.sh index 9fba2c45a..00c25bb06 100755 --- a/contrib/stressor_token.sh +++ b/contrib/stressor_token.sh @@ -137,7 +137,7 @@ function copy_array { function nav_cli { - $navpath/navcoin-cli -datadir=${array_data[$1]} -rpcport=${array_rpc_port[$1]} -devnet $2 $3 $4 $5 $6 2> /dev/null + $navpath/navcoin-cli -datadir=${array_data[$1]} -rpcport=${array_rpc_port[$1]} -devnet -nftindex=1 $2 $3 $4 $5 $6 2> /dev/null } function terminate { @@ -585,7 +585,7 @@ function dice_send_token { for t in ${tokens[@]} do shuffle_array "${array_stressing_nodes[@]}" - node_receive=${shuffled_array[0]} + node_receive=${shuffled_array[0]} amount=$(openssl rand 4 | od -DAn) out=$(nav_cli $n sendtoken $t ${array_private_address[$node_receive]} $amount) if [ ! -z $out ] @@ -668,7 +668,7 @@ function dice_send_nft { for t in ${nfts[@]} do shuffle_array "${array_stressing_nodes[@]}" - node_receive=${shuffled_array[0]} + node_receive=${shuffled_array[0]} nftid=$(nav_cli $node listtokens | jq ".[] | select(.id==\"$t\") | .nfts | .[] | select(.balance==\"1\") | .index" | shuf -n 1) # echo 'nftid= ' $nftid out=$(nav_cli $n sendnft $t $nftid ${array_private_address[$node_receive]}) From 65d27f3f4f59666ab1c8759e984b245192a31aea Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 19:01:26 +0800 Subject: [PATCH 23/61] Revert "Ops" This reverts commit ce50c307002c5dad63c78fce854abb7af6ae4d46. --- src/nftunspentindex.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h index 8f6e32749..7a289752c 100644 --- a/src/nftunspentindex.h +++ b/src/nftunspentindex.h @@ -71,10 +71,7 @@ struct CNftUnspentIndexValue { struct CNftUnspentIndexKeyCompare { bool operator()(const CNftUnspentIndexKey& a, const CNftUnspentIndexKey& b) const { - return a.blockHeight < b.blockHeight; - } else { - return a.tokenId < b.tokenId; - } + return a.blockHeight < b.blockHeight; } }; From b3d81e47ab587c9af3a61d29e4b5dc515d2f44c6 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 19:01:30 +0800 Subject: [PATCH 24/61] Revert "Removed tokenId from CNftUnspentIndexValue" This reverts commit c517ba4f5d435bbcaec0d7c5205a417c57bcf497. --- src/nftunspentindex.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h index 7a289752c..ca13e59c0 100644 --- a/src/nftunspentindex.h +++ b/src/nftunspentindex.h @@ -71,7 +71,11 @@ struct CNftUnspentIndexValue { struct CNftUnspentIndexKeyCompare { bool operator()(const CNftUnspentIndexKey& a, const CNftUnspentIndexKey& b) const { - return a.blockHeight < b.blockHeight; + if (a.tokenId == b.tokenId) { + return a.blockHeight < b.blockHeight; + } else { + return a.tokenId < b.tokenId; + } } }; From 60a7c1f4e890c1fd6fb8b199d33b10ad44002a73 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 21:18:34 +0800 Subject: [PATCH 25/61] Added UTXO data to listtokens --- src/main.cpp | 11 +++++++++++ src/main.h | 1 + src/rpc/client.cpp | 1 + src/txdb.cpp | 4 ++-- src/txdb.h | 2 +- src/wallet/rpcwallet.cpp | 24 ++++++++++++++++++++++-- 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 1fab69996..dc1070287 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2167,6 +2167,17 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) return true; } +bool GetNftUnspentIndex(const uint256 &id, std::vector &utxos) +{ + if (!fNftIndex) + return false; + + if (!pblocktree->ReadNftUnspentIndex(id, utxos)) + return false; + + return true; +} + bool HashOnchainActive(const uint256 &hash) { CBlockIndex* pblockindex = mapBlockIndex[hash]; diff --git a/src/main.h b/src/main.h index 11c09cbe9..1de58f03b 100644 --- a/src/main.h +++ b/src/main.h @@ -492,6 +492,7 @@ class CScriptCheck bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector > &hashes); bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); +bool GetNftUnspentIndex(const uint256 &id, std::vector &utxos); bool HashOnchainActive(const uint256 &hash); bool GetAddressIndex(uint160 addressHash, int type, std::vector > &addressIndex, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 65a91916a..5c7edadaf 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -116,6 +116,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listsinceblock", 1 }, { "listsinceblock", 2 }, { "listtokens", 0 }, + { "listtokens", 1 }, { "listtransactions", 1 }, { "listtransactions", 2 }, { "listtransactions", 3 }, diff --git a/src/txdb.cpp b/src/txdb.cpp index dbdcbc77d..13fa19556 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -771,7 +771,7 @@ bool CBlockTreeDB::UpdateNftUnspentIndex(const std::vector > &vect) { +bool CBlockTreeDB::ReadNftUnspentIndex(const uint256 tokenId, std::vector &vect) { boost::scoped_ptr pcursor(NewIterator()); pcursor->Seek(std::make_pair(DB_NFTUNSPENTINDEX, uint256())); @@ -782,7 +782,7 @@ bool CBlockTreeDB::ReadNftUnspentIndex(uint256 tokenId, std::vectorGetKey(key) && key.first == DB_NFTUNSPENTINDEX && key.second.tokenId == tokenId) { CNftUnspentIndexValue nValue; if (pcursor->GetValue(nValue)) { - vect.push_back(std::make_pair(key.second, nValue)); + vect.push_back(nValue.tx); pcursor->Next(); } else { return error("failed to get nft unspent value"); diff --git a/src/txdb.h b/src/txdb.h index a7410e2c0..e56d901c7 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -181,7 +181,7 @@ class CBlockTreeDB : public CDBWrapper bool UpdateSpentIndex(const std::vector >&vect); bool UpdateAddressUnspentIndex(const std::vector >&vect); bool UpdateNftUnspentIndex(const std::vector >&vect); - bool ReadNftUnspentIndex(uint256 tokenId, std::vector >&vect); + bool ReadNftUnspentIndex(const uint256 tokenId, std::vector &utxos); bool ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &vect); bool WriteAddressIndex(const std::vector > &vect); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 05b2fd48c..0160eb5fd 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5988,15 +5988,23 @@ UniValue listtokens(const UniValue& params, bool fHelp) { if (fHelp) throw std::runtime_error( - "listtokens (mine)\n" - "\nList the confidential tokens. Set mine to true to show only tokens you own.\n" + "listtokens (mine) (with_utxo)\n" + "\nList the confidential tokens.\n" + "\nArguments:\n" + "1. mine (boolean, optional, default=false) Show only owned tokens\n" + "2. with_utxo (boolean, optional, default=false) Show last utxo for nfts\n" + + "\nExamples:\n" + HelpExampleCli("listtokens", "") + + HelpExampleCli("listtokens", "true") + + HelpExampleCli("listtokens", "true true") ); LOCK2(cs_main, pwalletMain->cs_wallet); bool fMine = params[0].getBool(); + bool fWithUtxo = params.size() > 1 ? params[1].getBool() : false; UniValue ret(UniValue::VARR); TokenMap mapTokens; @@ -6028,6 +6036,7 @@ UniValue listtokens(const UniValue& params, bool fHelp) else if (it->second.nVersion == 1) { UniValue a(UniValue::VARR); + for (auto& it_: it->second.mapMetadata) { UniValue n(UniValue::VOBJ); n.pushKV("index", it_.first); @@ -6035,8 +6044,19 @@ UniValue listtokens(const UniValue& params, bool fHelp) int64_t tempBalance = pwalletMain->GetPrivateBalance(TokenId(it->first, it_.first)); n.pushKV("balance", std::to_string(tempBalance)); balance += tempBalance; + + std::vector utxos; + if (fWithUtxo && GetNftUnspentIndex(it->first, utxos)) { + auto txout = utxos[utxos.size() - 1]; + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("hash", txout.GetHash().ToString()); + // WE NEED TO ADD MORE DATA HERE, not sure what to show for the utxos + n.pushKV("utxo", utxo); + } + a.push_back(n); } + o.pushKV("nfts", a); } From 765f2d2a70e13885504c96b2bde23a97e2a9d868 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 23:19:26 +0800 Subject: [PATCH 26/61] Replaced tokenId uint256 with tokenId TokenId instead --- src/ctokens/tokenid.h | 4 ++++ src/main.cpp | 8 ++++---- src/nftunspentindex.h | 12 ++++++++---- src/wallet/rpcwallet.cpp | 1 + 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/ctokens/tokenid.h b/src/ctokens/tokenid.h index 2fa2350a9..975363f51 100644 --- a/src/ctokens/tokenid.h +++ b/src/ctokens/tokenid.h @@ -17,6 +17,10 @@ class TokenId TokenId(const uint256& t = uint256(), const uint64_t& i = -1) : token(t), subid(i){} + void SetNull() { token = uint256(); subid = -1; } + + bool IsNull() const { return token == uint256() && subid == -1; } + friend bool operator==(const TokenId& a, const TokenId& b) { return a.token == b.token && a.subid == b.subid; } friend bool operator<(const TokenId& a, const TokenId& b) { diff --git a/src/main.cpp b/src/main.cpp index dc1070287..65a111595 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2937,9 +2937,9 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI { return state.DoS(100, false, REJECT_INVALID, "error-program-vdata"); } - if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) - { - uint256 tokenId; + if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) { + TokenId tokenId; + if (program.action == MINT) { tokenId = SerializeHash(program.kParameters[0]); @@ -4800,7 +4800,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "error-program-vdata"); } if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) { - uint256 tokenId; + TokenId tokenId; if (program.action == MINT) { tokenId = SerializeHash(program.kParameters[0]); diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h index ca13e59c0..81f09feb8 100644 --- a/src/nftunspentindex.h +++ b/src/nftunspentindex.h @@ -6,14 +6,14 @@ #ifndef NAVCOIN_NFTUNSPENTINDEX_H #define NAVCOIN_NFTUNSPENTINDEX_H -#include +#include struct CNftUnspentIndexKey { - uint256 tokenId; + TokenId tokenId; uint32_t blockHeight; size_t GetSerializeSize(int nType, int nVersion) const { - return 32 + 4; + return 32 + 8 + 4; } template void Serialize(Stream& s, int nType, int nVersion) const { @@ -26,7 +26,7 @@ struct CNftUnspentIndexKey { blockHeight = ser_readdata32be(s); } - CNftUnspentIndexKey(uint256 t, int h) { + CNftUnspentIndexKey(TokenId t, int h) { tokenId = t; blockHeight = h; } @@ -39,6 +39,10 @@ struct CNftUnspentIndexKey { tokenId.SetNull(); blockHeight = 0; } + + bool IsNull() const { + return tokenId.IsNull(); + } }; struct CNftUnspentIndexValue { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0160eb5fd..7984f7360 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6050,6 +6050,7 @@ UniValue listtokens(const UniValue& params, bool fHelp) auto txout = utxos[utxos.size() - 1]; UniValue utxo(UniValue::VOBJ); utxo.pushKV("hash", txout.GetHash().ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); // WE NEED TO ADD MORE DATA HERE, not sure what to show for the utxos n.pushKV("utxo", utxo); } From 66a74c33787c30e9a030c860d596198da5ef54a2 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 23:29:36 +0800 Subject: [PATCH 27/61] Replaced tokenId uint256 with tokenId TokenId instead --- src/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 65a111595..d288b9a81 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2938,7 +2938,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI return state.DoS(100, false, REJECT_INVALID, "error-program-vdata"); } if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) { - TokenId tokenId; + uint256 tokenId; if (program.action == MINT) { @@ -3006,7 +3006,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId, pindex->nHeight), CNftUnspentIndexValue())); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(TokenId(tokenId), pindex->nHeight), CNftUnspentIndexValue())); } } } @@ -4800,7 +4800,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "error-program-vdata"); } if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) { - TokenId tokenId; + uint256 tokenId; if (program.action == MINT) { tokenId = SerializeHash(program.kParameters[0]); @@ -4895,7 +4895,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tokenId, pindex->nHeight), CNftUnspentIndexValue(vout))); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(TokenId(tokenId), pindex->nHeight), CNftUnspentIndexValue(vout))); } } } From 532baf159139f3c6f8c27a91c35c53ae904a0279 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 21 Feb 2022 23:55:42 +0800 Subject: [PATCH 28/61] Replaced tokenId uint256 with tokenId TokenId instead --- src/main.cpp | 3 ++- src/main.h | 2 +- src/txdb.cpp | 2 +- src/txdb.h | 2 +- src/wallet/rpcwallet.cpp | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d288b9a81..cf7966d07 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2167,7 +2167,7 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) return true; } -bool GetNftUnspentIndex(const uint256 &id, std::vector &utxos) +bool GetNftUnspentIndex(const TokenId &id, std::vector &utxos) { if (!fNftIndex) return false; @@ -3010,6 +3010,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } } } + if (fDotNav) { if (program.action == REGISTER_NAME) { diff --git a/src/main.h b/src/main.h index 1de58f03b..13a8f0414 100644 --- a/src/main.h +++ b/src/main.h @@ -492,7 +492,7 @@ class CScriptCheck bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector > &hashes); bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); -bool GetNftUnspentIndex(const uint256 &id, std::vector &utxos); +bool GetNftUnspentIndex(const TokenId &id, std::vector &utxos); bool HashOnchainActive(const uint256 &hash); bool GetAddressIndex(uint160 addressHash, int type, std::vector > &addressIndex, diff --git a/src/txdb.cpp b/src/txdb.cpp index 13fa19556..e988cbac6 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -771,7 +771,7 @@ bool CBlockTreeDB::UpdateNftUnspentIndex(const std::vector &vect) { +bool CBlockTreeDB::ReadNftUnspentIndex(const TokenId tokenId, std::vector &vect) { boost::scoped_ptr pcursor(NewIterator()); pcursor->Seek(std::make_pair(DB_NFTUNSPENTINDEX, uint256())); diff --git a/src/txdb.h b/src/txdb.h index e56d901c7..6428af661 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -181,7 +181,7 @@ class CBlockTreeDB : public CDBWrapper bool UpdateSpentIndex(const std::vector >&vect); bool UpdateAddressUnspentIndex(const std::vector >&vect); bool UpdateNftUnspentIndex(const std::vector >&vect); - bool ReadNftUnspentIndex(const uint256 tokenId, std::vector &utxos); + bool ReadNftUnspentIndex(const TokenId tokenId, std::vector &utxos); bool ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &vect); bool WriteAddressIndex(const std::vector > &vect); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 7984f7360..03de87dc0 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6046,7 +6046,7 @@ UniValue listtokens(const UniValue& params, bool fHelp) balance += tempBalance; std::vector utxos; - if (fWithUtxo && GetNftUnspentIndex(it->first, utxos)) { + if (fWithUtxo && GetNftUnspentIndex(TokenId(it->first, it_.first), utxos)) { auto txout = utxos[utxos.size() - 1]; UniValue utxo(UniValue::VOBJ); utxo.pushKV("hash", txout.GetHash().ToString()); From 6eab03a51f4cd283bcedd9fcc345604a37d8cfe1 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 22 Feb 2022 04:21:51 +0800 Subject: [PATCH 29/61] Fixed a crash --- src/wallet/rpcwallet.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 03de87dc0..ca2721a95 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6047,12 +6047,14 @@ UniValue listtokens(const UniValue& params, bool fHelp) std::vector utxos; if (fWithUtxo && GetNftUnspentIndex(TokenId(it->first, it_.first), utxos)) { - auto txout = utxos[utxos.size() - 1]; - UniValue utxo(UniValue::VOBJ); - utxo.pushKV("hash", txout.GetHash().ToString()); - utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); - // WE NEED TO ADD MORE DATA HERE, not sure what to show for the utxos - n.pushKV("utxo", utxo); + if (utxos.size() > 0) { + auto txout = utxos[utxos.size() - 1]; + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("hash", txout.GetHash().ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); + // WE NEED TO ADD MORE DATA HERE, not sure what to show for the utxos + n.pushKV("utxo", utxo); + } } a.push_back(n); From 430dc4f4daeb955daa1b0ca095c2f946c2a7bd5f Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 22 Feb 2022 04:24:33 +0800 Subject: [PATCH 30/61] Updated the way the token is loaded for adding to the index --- src/main.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index cf7966d07..ae13cba0f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2997,6 +2997,11 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } if (fNftIndex) { + TokenId tempToken = txout.tokenId; + + if (tempToken.IsNull()) + tempToken = TokenId(tokenId); + if (!view.HaveToken(tokenId)) { return state.DoS(100, false, REJECT_INVALID, "wrong-token-id"); @@ -3006,7 +3011,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(TokenId(tokenId), pindex->nHeight), CNftUnspentIndexValue())); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tempToken, pindex->nHeight), CNftUnspentIndexValue())); } } } @@ -4887,6 +4892,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } if (fNftIndex) { + TokenId tempToken = vout.tokenId; + + if (tempToken.IsNull()) + tempToken = TokenId(tokenId); + if (!view.HaveToken(tokenId)) { return state.DoS(100, false, REJECT_INVALID, "wrong-token-id"); @@ -4896,7 +4906,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(TokenId(tokenId), pindex->nHeight), CNftUnspentIndexValue(vout))); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tempToken, pindex->nHeight), CNftUnspentIndexValue(vout))); } } } From 18f2ebe8569bb2b342b3b6e6a97329dbb4ee715a Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 22 Feb 2022 04:36:15 +0800 Subject: [PATCH 31/61] Removed redundant checks --- src/main.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ae13cba0f..76c27acdc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2997,11 +2997,6 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } if (fNftIndex) { - TokenId tempToken = txout.tokenId; - - if (tempToken.IsNull()) - tempToken = TokenId(tokenId); - if (!view.HaveToken(tokenId)) { return state.DoS(100, false, REJECT_INVALID, "wrong-token-id"); @@ -3011,7 +3006,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tempToken, pindex->nHeight), CNftUnspentIndexValue())); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(txout.tokenId, pindex->nHeight), CNftUnspentIndexValue())); } } } @@ -4892,11 +4887,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } if (fNftIndex) { - TokenId tempToken = vout.tokenId; - - if (tempToken.IsNull()) - tempToken = TokenId(tokenId); - if (!view.HaveToken(tokenId)) { return state.DoS(100, false, REJECT_INVALID, "wrong-token-id"); @@ -4906,7 +4896,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(tempToken, pindex->nHeight), CNftUnspentIndexValue(vout))); + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(vout.tokenId, pindex->nHeight), CNftUnspentIndexValue(vout))); } } } From d94b861e93811acf3cd4f27291c0b2a745077100 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 22 Feb 2022 04:51:05 +0800 Subject: [PATCH 32/61] Fixed reading method for nft index --- src/txdb.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/txdb.cpp b/src/txdb.cpp index e988cbac6..8d6604e81 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -779,14 +779,18 @@ bool CBlockTreeDB::ReadNftUnspentIndex(const TokenId tokenId, std::vectorValid()) { boost::this_thread::interruption_point(); std::pair key; - if (pcursor->GetKey(key) && key.first == DB_NFTUNSPENTINDEX && key.second.tokenId == tokenId) { - CNftUnspentIndexValue nValue; - if (pcursor->GetValue(nValue)) { - vect.push_back(nValue.tx); - pcursor->Next(); - } else { - return error("failed to get nft unspent value"); + if (pcursor->GetKey(key) && key.first == DB_NFTUNSPENTINDEX) { + if (key.second.tokenId == tokenId) { + CNftUnspentIndexValue nValue; + if (pcursor->GetValue(nValue)) { + vect.push_back(nValue.tx); + pcursor->Next(); + } else { + return error("failed to get nft unspent value"); + } } + + pcursor->Next(); } else { break; } From 4afb9944a8847e6599c7dd1fcb7ba978b9914070 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 22 Feb 2022 07:13:29 +0800 Subject: [PATCH 33/61] Changed some logic and stored the index in a more efficient way --- src/main.cpp | 85 ++++++++++++++++++++-------------------- src/main.h | 2 +- src/nftunspentindex.h | 20 +++++++--- src/txdb.cpp | 4 +- src/txdb.h | 2 +- src/wallet/rpcwallet.cpp | 5 ++- 6 files changed, 64 insertions(+), 54 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 76c27acdc..0d4b630fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2167,7 +2167,7 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) return true; } -bool GetNftUnspentIndex(const TokenId &id, std::vector &utxos) +bool GetNftUnspentIndex(const TokenId &id, std::vector &utxos) { if (!fNftIndex) return false; @@ -2938,11 +2938,9 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI return state.DoS(100, false, REJECT_INVALID, "error-program-vdata"); } if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) { - uint256 tokenId; - if (program.action == MINT) { - tokenId = SerializeHash(program.kParameters[0]); + auto tokenId = SerializeHash(program.kParameters[0]); if (!view.HaveToken(tokenId)) { @@ -2964,7 +2962,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } else if (program.action == BURN) { - tokenId = txout.tokenId.token; + auto tokenId = txout.tokenId.token; if (!view.HaveToken(tokenId)) { @@ -2980,11 +2978,11 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI } else if (program.action == CREATE_TOKEN) { - tokenId = SerializeHash(program.kParameters[0]); + auto tokenId = SerializeHash(program.kParameters[0]); view.RemoveToken(tokenId); } else if (program.action == STOP_MINT) { - tokenId = SerializeHash(program.kParameters[0]); + auto tokenId = SerializeHash(program.kParameters[0]); if (!view.HaveToken(tokenId)) { @@ -2995,20 +2993,6 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI token->canMint = true; } - - if (fNftIndex) { - if (!view.HaveToken(tokenId)) - { - return state.DoS(100, false, REJECT_INVALID, "wrong-token-id"); - } - - TokenModifier token = view.ModifyToken(tokenId); - - // Check if we have an nft - if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(txout.tokenId, pindex->nHeight), CNftUnspentIndexValue())); - } - } } if (fDotNav) @@ -3026,6 +3010,20 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI return state.DoS(100, false, REJECT_INVALID, "error-program-vdata"); } } + + if (fNftIndex) { + auto tokenId = txout.tokenId.token; + + if (view.HaveToken(tokenId)) + { + TokenModifier token = view.ModifyToken(tokenId); + + // Check if we have an nft + if (token->nVersion == 1) { + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(txout.tokenId, pindex->nHeight), CNftUnspentIndexValue())); + } + } + } } if (fAddressIndex) @@ -4781,8 +4779,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin bool fDotNav = IsDotNavEnabled(pindex->pprev, Params().GetConsensus()); - for(const CTxOut& vout: tx.vout) + + for (unsigned int i = 0; i < tx.vout.size(); i++) { + const CTxOut& vout = tx.vout[i]; + if(vout.IsCommunityFundContribution()) { fContribution=true; @@ -4801,10 +4802,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "error-program-vdata"); } if (GetConsensusParameter(Consensus::CONSENSUS_PARAMS_CONFIDENTIAL_TOKENS_ENABLED, view)) { - uint256 tokenId; - if (program.action == MINT) { - tokenId = SerializeHash(program.kParameters[0]); + auto tokenId = SerializeHash(program.kParameters[0]); if (!view.HaveToken(tokenId)) { @@ -4833,7 +4832,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "unknown-token-version"); } } else if (program.action == BURN) { - tokenId = vout.tokenId.token; + auto tokenId = vout.tokenId.token; if (!view.HaveToken(tokenId)) { @@ -4855,7 +4854,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "cant-burn"); } } else if (program.action == CREATE_TOKEN) { - tokenId = SerializeHash(program.kParameters[0]); + auto tokenId = SerializeHash(program.kParameters[0]); if (view.HaveToken(tokenId)) { @@ -4870,7 +4869,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin view.AddToken(std::make_pair(tokenId, token)); } else if (program.action == STOP_MINT) { - tokenId = SerializeHash(program.kParameters[0]); + auto tokenId = SerializeHash(program.kParameters[0]); if (!view.HaveToken(tokenId)) { @@ -4885,20 +4884,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "cant-stop-minting"); } } - - if (fNftIndex) { - if (!view.HaveToken(tokenId)) - { - return state.DoS(100, false, REJECT_INVALID, "wrong-token-id"); - } - - TokenModifier token = view.ModifyToken(tokenId); - - // Check if we have an nft - if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(vout.tokenId, pindex->nHeight), CNftUnspentIndexValue(vout))); - } - } } if (fDotNav) { @@ -5026,6 +5011,22 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, false, REJECT_INVALID, "error-program-vdata"); } } + + if (fNftIndex) { + auto tokenId = vout.tokenId.token; + + if (view.HaveToken(tokenId)) + { + TokenModifier token = view.ModifyToken(tokenId); + + // Check if we have an nft + if (token->nVersion == 1) { + auto op = COutPoint(tx.GetHash(), i); + + nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(vout.tokenId, pindex->nHeight), CNftUnspentIndexValue(op.hash, vout.spendingKey, op.n))); + } + } + } } if(fCFund || fDAOConsultations) diff --git a/src/main.h b/src/main.h index 13a8f0414..4bb8387bf 100644 --- a/src/main.h +++ b/src/main.h @@ -492,7 +492,7 @@ class CScriptCheck bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector > &hashes); bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); -bool GetNftUnspentIndex(const TokenId &id, std::vector &utxos); +bool GetNftUnspentIndex(const TokenId &id, std::vector &utxos); bool HashOnchainActive(const uint256 &hash); bool GetAddressIndex(uint160 addressHash, int type, std::vector > &addressIndex, diff --git a/src/nftunspentindex.h b/src/nftunspentindex.h index 81f09feb8..2b1baaec0 100644 --- a/src/nftunspentindex.h +++ b/src/nftunspentindex.h @@ -46,17 +46,23 @@ struct CNftUnspentIndexKey { }; struct CNftUnspentIndexValue { - CTxOut tx; + uint256 hash; + std::vector spendingKey; + uint32_t n; ADD_SERIALIZE_METHODS; template inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(tx); + READWRITE(hash); + READWRITE(spendingKey); + READWRITE(n); } - CNftUnspentIndexValue(CTxOut txout) { - tx = txout; + CNftUnspentIndexValue(uint256 _hash, std::vector _spendingKey, uint32_t _n) { + hash = _hash; + spendingKey = _spendingKey; + n = _n; } CNftUnspentIndexValue() { @@ -64,11 +70,13 @@ struct CNftUnspentIndexValue { } void SetNull() { - tx.SetNull(); + hash.SetNull(); + spendingKey.clear(); + n = (uint32_t) -1; } bool IsNull() const { - return tx.IsNull(); + return hash.IsNull(); } }; diff --git a/src/txdb.cpp b/src/txdb.cpp index 8d6604e81..dd9767d5b 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -771,7 +771,7 @@ bool CBlockTreeDB::UpdateNftUnspentIndex(const std::vector &vect) { +bool CBlockTreeDB::ReadNftUnspentIndex(const TokenId tokenId, std::vector &vect) { boost::scoped_ptr pcursor(NewIterator()); pcursor->Seek(std::make_pair(DB_NFTUNSPENTINDEX, uint256())); @@ -783,7 +783,7 @@ bool CBlockTreeDB::ReadNftUnspentIndex(const TokenId tokenId, std::vectorGetValue(nValue)) { - vect.push_back(nValue.tx); + vect.push_back(nValue); pcursor->Next(); } else { return error("failed to get nft unspent value"); diff --git a/src/txdb.h b/src/txdb.h index 6428af661..6e5e2a5d5 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -181,7 +181,7 @@ class CBlockTreeDB : public CDBWrapper bool UpdateSpentIndex(const std::vector >&vect); bool UpdateAddressUnspentIndex(const std::vector >&vect); bool UpdateNftUnspentIndex(const std::vector >&vect); - bool ReadNftUnspentIndex(const TokenId tokenId, std::vector &utxos); + bool ReadNftUnspentIndex(const TokenId tokenId, std::vector &utxos); bool ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &vect); bool WriteAddressIndex(const std::vector > &vect); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ca2721a95..dce092464 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6045,12 +6045,13 @@ UniValue listtokens(const UniValue& params, bool fHelp) n.pushKV("balance", std::to_string(tempBalance)); balance += tempBalance; - std::vector utxos; + std::vector utxos; if (fWithUtxo && GetNftUnspentIndex(TokenId(it->first, it_.first), utxos)) { if (utxos.size() > 0) { auto txout = utxos[utxos.size() - 1]; UniValue utxo(UniValue::VOBJ); - utxo.pushKV("hash", txout.GetHash().ToString()); + utxo.pushKV("n", std::to_string(txout.n)); + utxo.pushKV("hash", txout.hash.ToString()); utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); // WE NEED TO ADD MORE DATA HERE, not sure what to show for the utxos n.pushKV("utxo", utxo); From a0648449ff06e0df386dc1f69d93d76ab8de8065 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 22 Feb 2022 07:14:58 +0800 Subject: [PATCH 34/61] Removed a commit that is no longer needed --- src/wallet/rpcwallet.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index dce092464..d768a7a73 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6053,7 +6053,6 @@ UniValue listtokens(const UniValue& params, bool fHelp) utxo.pushKV("n", std::to_string(txout.n)); utxo.pushKV("hash", txout.hash.ToString()); utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); - // WE NEED TO ADD MORE DATA HERE, not sure what to show for the utxos n.pushKV("utxo", utxo); } } From 82f14bd7bf4f45e21b39600d9be335eff3f44bd2 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 22 Feb 2022 07:37:46 +0800 Subject: [PATCH 35/61] Added (with_utxo) to gettoken rpc command --- src/rpc/client.cpp | 1 + src/wallet/rpcwallet.cpp | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 5c7edadaf..6364d3ab0 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -93,6 +93,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getreceivedbyaddress", 1 }, { "getspentinfo", 0}, { "getstakerscript", 1 }, + { "gettoken", 1 }, { "gettransaction", 1 }, { "gettxout", 1 }, { "gettxout", 2 }, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d768a7a73..b06ab040b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6094,15 +6094,16 @@ UniValue gettoken(const UniValue& params, bool fHelp) { if (fHelp) throw std::runtime_error( - "gettoken hash\n" + "gettoken hash (with_utxo)\n" "\nShows information about a token.\n" + HelpExampleCli("gettoken", "90fc7410164a466b78096967ec948fcc13142b0f5fb4397462304c517840d74f") + + HelpExampleCli("gettoken", "90fc7410164a466b78096967ec948fcc13142b0f5fb4397462304c517840d74f true") ); LOCK(cs_main); - bool fMine = params[0].getBool(); + bool fWithUtxo = params.size() > 1 ? params[1].getBool() : false; UniValue ret(UniValue::VOBJ); @@ -6136,6 +6137,23 @@ UniValue gettoken(const UniValue& params, bool fHelp) int64_t tempBalance = pwalletMain->GetPrivateBalance(TokenId(uint256S(params[0].get_str()), it_.first)); n.pushKV("balance", std::to_string(tempBalance)); balance += tempBalance; + + std::vector utxos; + info("TEST1;"); + if (fWithUtxo) + info("TEST2;"); + if (fWithUtxo && GetNftUnspentIndex(TokenId(uint256S(params[0].get_str()), it_.first), utxos)) { + info("TEST3;"); + if (utxos.size() > 0) { + auto txout = utxos[utxos.size() - 1]; + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("n", std::to_string(txout.n)); + utxo.pushKV("hash", txout.hash.ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); + n.pushKV("utxo", utxo); + } + } + a.push_back(n); } ret.pushKV("nfts", a); From 9ea3bdcca9414f1f7eb5c3df4a80286d45362ed5 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 24 Feb 2022 18:08:31 +0800 Subject: [PATCH 36/61] Added new viewstate functions for token utxos --- src/coins.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/coins.h | 11 +++++++++++ src/main.cpp | 4 ++++ 3 files changed, 68 insertions(+) diff --git a/src/coins.cpp b/src/coins.cpp index 33d6526ff..943bcfea6 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -53,6 +53,7 @@ bool CStateView::GetConsultation(const uint256 &cid, CConsultation& consultation bool CStateView::GetConsultationAnswer(const uint256 &cid, CConsultationAnswer& answer) const { return false; } bool CStateView::GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const { return false; } bool CStateView::GetToken(const uint256 &id, TokenInfo& token) const { return false; } +bool CStateView::GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const { return false; }; bool CStateView::GetNameRecord(const uint256 &id, NameRecordValue& height) const { return false; } bool CStateView::GetNameData(const uint256 &id, NameDataValues& data) { return false; } bool CStateView::HaveCoins(const uint256 &txid) const { return false; } @@ -63,6 +64,7 @@ bool CStateView::HaveConsultation(const uint256 &cid) const { return false; } bool CStateView::HaveConsultationAnswer(const uint256 &cid) const { return false; } bool CStateView::HaveConsensusParameter(const int &pid) const { return false; } bool CStateView::HaveToken(const uint256 &id) const { return false; } +bool CStateView::HaveTokenUtxo(const TokenId &id) const { return false; } bool CStateView::HaveNameRecord(const uint256 &id) const { return false; } bool CStateView::HaveNameData(const uint256 &id) const { return false; } bool CStateView::GetAllProposals(CProposalMap& map) { return false; } @@ -92,6 +94,7 @@ bool CStateViewBacked::GetConsultation(const uint256 &cid, CConsultation &consul bool CStateViewBacked::GetConsultationAnswer(const uint256 &cid, CConsultationAnswer &answer) const { return base->GetConsultationAnswer(cid, answer); } bool CStateViewBacked::GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const { return base->GetConsensusParameter(pid, cparameter); } bool CStateViewBacked::GetToken(const uint256 &id, TokenInfo& token) const { return base->GetToken(id, token); } +bool CStateViewBacked::GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const { return base->GetTokenUtxo(id, tokenUtxo); } bool CStateViewBacked::GetNameRecord(const uint256 &id, NameRecordValue& height) const { return base->GetNameRecord(id, height); } bool CStateViewBacked::GetNameData(const uint256 &id, NameDataValues& data) { return base->GetNameData(id, data); } bool CStateViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); } @@ -102,6 +105,7 @@ bool CStateViewBacked::HaveConsultation(const uint256 &cid) const { return base- bool CStateViewBacked::HaveConsultationAnswer(const uint256 &cid) const { return base->HaveConsultationAnswer(cid); } bool CStateViewBacked::HaveConsensusParameter(const int &pid) const { return base->HaveConsensusParameter(pid); } bool CStateViewBacked::HaveToken(const uint256 &id) const { return base->HaveToken(id); } +bool CStateViewBacked::HaveTokenUtxo(const TokenId &id) const { return base->HaveTokenUtxo(id); } bool CStateViewBacked::HaveNameRecord(const uint256 &id) const { return base->HaveNameRecord(id); } bool CStateViewBacked::HaveNameData(const uint256 &id) const { return base->HaveNameData(id); } int CStateViewBacked::GetExcludeVotes() const { return base->GetExcludeVotes(); } @@ -278,6 +282,22 @@ TokenMap::const_iterator CStateViewCache::FetchToken(const uint256 &id) const { return ret; } +CTokenUtxoMap::const_iterator CStateViewCache::FetchTokenUtxo(const TokenId &id) const { + CTokenUtxoMap::iterator it = cacheTokenUtxos.find(id); + + if (it != cacheTokenUtxos.end()) + return it; + + CNftUnspentIndexValue tmp; + + if (!base->GetTokenUtxo(id, tmp) || tmp.IsNull()) + return cacheTokenUtxos.end(); + + CTokenUtxoMap::iterator ret = cacheTokenUtxos.insert(std::make_pair(id, tmp)).first; + + return ret; +} + NameRecordMap::const_iterator CStateViewCache::FetchNameRecord(const uint256 &id) const { NameRecordMap::iterator it = cacheNameRecords.find(id); @@ -389,6 +409,15 @@ bool CStateViewCache::GetToken(const uint256 &id, TokenInfo &token) const { return false; } +bool CStateViewCache::GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const { + CTokenUtxoMap::const_iterator it = FetchTokenUtxo(id); + if (it != cacheTokenUtxos.end() && !it->second.IsNull()) { + tokenUtxo = it->second; + return true; + } + return false; +} + bool CStateViewCache::GetNameRecord(const uint256 &id, NameRecordValue &height) const { NameRecordMap::const_iterator it = FetchNameRecord(id); if (it != cacheNameRecords.end() && !it->second.IsNull()) { @@ -773,6 +802,25 @@ bool CStateViewCache::AddToken(const Token& token) const { return true; } +bool CStateViewCache::UpdateTokenUtxo(const TokenId &id) const { + std::vector utxos; + + if (!GetNftUnspentIndex(id, utxos)) + return false; + + auto utxo = CNftUnspentIndexValue(); + if (utxos.size() > 0) { + utxo = utxos[utxos.size() - 1]; + } + + if (cacheTokenUtxos.count(id)) + cacheTokenUtxos[id] = utxo; + else + cacheTokenUtxos.insert(std::make_pair(id, utxo)); + + return true; +} + bool CStateViewCache::AddNameRecord(const NameRecord& namerecord) const { if (HaveNameRecord(namerecord.first)) return false; @@ -960,6 +1008,11 @@ bool CStateViewCache::HaveToken(const uint256 &id) const { return (it != cacheTokens.end() && !it->second.IsNull()); } +bool CStateViewCache::HaveTokenUtxo(const TokenId &id) const { + CTokenUtxoMap::const_iterator it = FetchTokenUtxo(id); + return (it != cacheTokenUtxos.end() && !it->second.IsNull()); +} + bool CStateViewCache::HaveNameRecord(const uint256 &id) const { NameRecordMap::const_iterator it = FetchNameRecord(id); return (it != cacheNameRecords.end() && !it->second.IsNull()); diff --git a/src/coins.h b/src/coins.h index df5df0fcd..c8d72e8a3 100644 --- a/src/coins.h +++ b/src/coins.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "consensus/dao.h" #include "ctokens/ctokens.h" @@ -323,6 +324,7 @@ typedef std::vector CVoteMapKey; typedef CVoteList CVoteMapValue; typedef std::map CVoteMap; typedef std::map CProposalMap; +typedef std::map CTokenUtxoMap; typedef std::map CPaymentRequestMap; typedef std::map CConsultationMap; typedef std::map CConsultationAnswerMap; @@ -384,8 +386,10 @@ class CStateView virtual bool HaveConsensusParameter(const int &pid) const; virtual bool GetToken(const uint256 &id, TokenInfo& token) const; + virtual bool GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const; virtual bool GetAllTokens(TokenMap& map); virtual bool HaveToken(const uint256 &id) const; + virtual bool HaveTokenUtxo(const TokenId &id) const; virtual bool GetNameRecord(const uint256 &id, NameRecordValue& height) const; virtual bool GetAllNameRecords(NameRecordMap& map); @@ -445,8 +449,10 @@ class CStateViewBacked : public CStateView bool GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const; bool HaveConsensusParameter(const int &pid) const; bool GetToken(const uint256 &id, TokenInfo& token) const; + bool GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const; bool GetAllTokens(TokenMap& map); bool HaveToken(const uint256 &id) const; + bool HaveTokenUtxo(const TokenId &id) const; bool GetNameRecord(const uint256 &id, NameRecordValue& height) const; bool GetAllNameRecords(NameRecordMap& map); @@ -652,6 +658,7 @@ class CStateViewCache : public CStateViewBacked mutable uint256 hashBlock; mutable CCoinsMap cacheCoins; mutable CProposalMap cacheProposals; + mutable CTokenUtxoMap cacheTokenUtxos; mutable CPaymentRequestMap cachePaymentRequests; mutable CVoteMap cacheVotes; mutable CConsultationMap cacheConsultations; @@ -679,6 +686,7 @@ class CStateViewCache : public CStateViewBacked bool HaveConsultationAnswer(const uint256 &cid) const; bool HaveConsensusParameter(const int& pid) const; bool HaveToken(const uint256& id) const; + bool HaveTokenUtxo(const TokenId& id) const; bool HaveNameRecord(const uint256& id) const; bool HaveNameData(const uint256& id) const; bool GetProposal(const uint256 &txid, CProposal &proposal) const; @@ -688,6 +696,7 @@ class CStateViewCache : public CStateViewBacked bool GetConsultationAnswer(const uint256 &cid, CConsultationAnswer& answer) const; bool GetConsensusParameter(const int& pid, CConsensusParameter& cparameter) const; bool GetToken(const uint256& pid, TokenInfo& token) const; + bool GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const; bool GetNameRecord(const uint256& pid, NameRecordValue& height) const; bool GetNameData(const uint256& pid, NameDataValues& data); bool GetAllProposals(CProposalMap& map); @@ -711,6 +720,7 @@ class CStateViewCache : public CStateViewBacked bool AddCachedVoter(const CVoteMapKey &voter, CVoteMapValue& vote) const; bool AddConsultation(const CConsultation& consultation) const; bool AddToken(const Token& token) const; + bool UpdateTokenUtxo(const TokenId &id) const; bool AddNameRecord(const NameRecord& record) const; bool AddNameData(const uint256& id, const NameDataEntry& record) const; bool AddConsultationAnswer(const CConsultationAnswer& answer); @@ -832,6 +842,7 @@ class CStateViewCache : public CStateViewBacked CConsultationAnswerMap::const_iterator FetchConsultationAnswer(const uint256 &cid) const; CConsensusParameterMap::const_iterator FetchConsensusParameter(const int &pid) const; TokenMap::const_iterator FetchToken(const uint256 &id) const; + CTokenUtxoMap::const_iterator FetchTokenUtxo(const TokenId &id) const; NameRecordMap::const_iterator FetchNameRecord(const uint256 &id) const; NameDataMap::const_iterator FetchNameData(const uint256 &id) const; diff --git a/src/main.cpp b/src/main.cpp index 0d4b630fb..668c5561b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3021,6 +3021,8 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI // Check if we have an nft if (token->nVersion == 1) { nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(txout.tokenId, pindex->nHeight), CNftUnspentIndexValue())); + + view.UpdateTokenUtxo(txout.tokenId); } } } @@ -5024,6 +5026,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin auto op = COutPoint(tx.GetHash(), i); nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(vout.tokenId, pindex->nHeight), CNftUnspentIndexValue(op.hash, vout.spendingKey, op.n))); + + view.UpdateTokenUtxo(vout.tokenId); } } } From dd3337ebcbef5cee3f595ff03c32ea12d081f2f8 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 24 Feb 2022 18:38:06 +0800 Subject: [PATCH 37/61] Added new viewstate functions for token utxos --- src/coins.cpp | 12 +----------- src/coins.h | 2 +- src/main.cpp | 19 ++++++++++++++++--- src/main.h | 2 +- src/wallet/rpcwallet.cpp | 38 ++++++++++++++------------------------ 5 files changed, 33 insertions(+), 40 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 943bcfea6..cb739ddfb 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -802,17 +802,7 @@ bool CStateViewCache::AddToken(const Token& token) const { return true; } -bool CStateViewCache::UpdateTokenUtxo(const TokenId &id) const { - std::vector utxos; - - if (!GetNftUnspentIndex(id, utxos)) - return false; - - auto utxo = CNftUnspentIndexValue(); - if (utxos.size() > 0) { - utxo = utxos[utxos.size() - 1]; - } - +bool CStateViewCache::UpdateTokenUtxo(const TokenId &id, const CNftUnspentIndexValue &utxo) const { if (cacheTokenUtxos.count(id)) cacheTokenUtxos[id] = utxo; else diff --git a/src/coins.h b/src/coins.h index c8d72e8a3..0048780cd 100644 --- a/src/coins.h +++ b/src/coins.h @@ -720,7 +720,7 @@ class CStateViewCache : public CStateViewBacked bool AddCachedVoter(const CVoteMapKey &voter, CVoteMapValue& vote) const; bool AddConsultation(const CConsultation& consultation) const; bool AddToken(const Token& token) const; - bool UpdateTokenUtxo(const TokenId &id) const; + bool UpdateTokenUtxo(const TokenId &id, const CNftUnspentIndexValue &utxo) const; bool AddNameRecord(const NameRecord& record) const; bool AddNameData(const uint256& id, const NameDataEntry& record) const; bool AddConsultationAnswer(const CConsultationAnswer& answer); diff --git a/src/main.cpp b/src/main.cpp index 668c5561b..f882f1016 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2167,14 +2167,21 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) return true; } -bool GetNftUnspentIndex(const TokenId &id, std::vector &utxos) +bool GetNftUnspentIndex(const TokenId &id, CNftUnspentIndexValue &utxo) { + std::vector utxos; + if (!fNftIndex) return false; if (!pblocktree->ReadNftUnspentIndex(id, utxos)) return false; + if (utxos.size() > 0) + utxo = utxos[utxos.size() - 1]; + else + utxo = CNftUnspentIndexValue(); + return true; } @@ -3022,7 +3029,10 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI if (token->nVersion == 1) { nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(txout.tokenId, pindex->nHeight), CNftUnspentIndexValue())); - view.UpdateTokenUtxo(txout.tokenId); + CNftUnspentIndexValue lastUtxo; + + if (GetNftUnspentIndex(txout.tokenId, lastUtxo)) + view.UpdateTokenUtxo(txout.tokenId, lastUtxo); } } } @@ -5027,7 +5037,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(vout.tokenId, pindex->nHeight), CNftUnspentIndexValue(op.hash, vout.spendingKey, op.n))); - view.UpdateTokenUtxo(vout.tokenId); + CNftUnspentIndexValue lastUtxo; + + if (GetNftUnspentIndex(vout.tokenId, lastUtxo)) + view.UpdateTokenUtxo(vout.tokenId, lastUtxo); } } } diff --git a/src/main.h b/src/main.h index 4bb8387bf..e55cb990e 100644 --- a/src/main.h +++ b/src/main.h @@ -492,7 +492,7 @@ class CScriptCheck bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector > &hashes); bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); -bool GetNftUnspentIndex(const TokenId &id, std::vector &utxos); +bool GetNftUnspentIndex(const TokenId &id, CNftUnspentIndexValue &utxo); bool HashOnchainActive(const uint256 &hash); bool GetAddressIndex(uint160 addressHash, int type, std::vector > &addressIndex, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b06ab040b..9de7829a6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6045,16 +6045,13 @@ UniValue listtokens(const UniValue& params, bool fHelp) n.pushKV("balance", std::to_string(tempBalance)); balance += tempBalance; - std::vector utxos; - if (fWithUtxo && GetNftUnspentIndex(TokenId(it->first, it_.first), utxos)) { - if (utxos.size() > 0) { - auto txout = utxos[utxos.size() - 1]; - UniValue utxo(UniValue::VOBJ); - utxo.pushKV("n", std::to_string(txout.n)); - utxo.pushKV("hash", txout.hash.ToString()); - utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); - n.pushKV("utxo", utxo); - } + CNftUnspentIndexValue txout; + if (fWithUtxo && view.GetTokenUtxo(TokenId(it->first, it_.first), txout)) { + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("n", std::to_string(txout.n)); + utxo.pushKV("hash", txout.hash.ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); + n.pushKV("utxo", utxo); } a.push_back(n); @@ -6138,20 +6135,13 @@ UniValue gettoken(const UniValue& params, bool fHelp) n.pushKV("balance", std::to_string(tempBalance)); balance += tempBalance; - std::vector utxos; - info("TEST1;"); - if (fWithUtxo) - info("TEST2;"); - if (fWithUtxo && GetNftUnspentIndex(TokenId(uint256S(params[0].get_str()), it_.first), utxos)) { - info("TEST3;"); - if (utxos.size() > 0) { - auto txout = utxos[utxos.size() - 1]; - UniValue utxo(UniValue::VOBJ); - utxo.pushKV("n", std::to_string(txout.n)); - utxo.pushKV("hash", txout.hash.ToString()); - utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); - n.pushKV("utxo", utxo); - } + CNftUnspentIndexValue txout; + if (fWithUtxo && GetNftUnspentIndex(TokenId(uint256S(params[0].get_str()), it_.first), txout)) { + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("n", std::to_string(txout.n)); + utxo.pushKV("hash", txout.hash.ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); + n.pushKV("utxo", utxo); } a.push_back(n); From 7fc6b4b5b8425b00d3a303ec7d72ea3f9c526ef7 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 24 Feb 2022 21:46:52 +0800 Subject: [PATCH 38/61] Updated the nftindex logic --- src/Makefile.am | 2 +- src/coins.cpp | 89 ++++++++++++++----- src/coins.h | 47 ++++++---- .../tokenutxos.h} | 35 +++----- src/main.cpp | 46 ++-------- src/main.h | 2 - src/txdb.cpp | 74 +++++++-------- src/txdb.h | 4 +- src/wallet/rpcwallet.cpp | 34 ++++--- 9 files changed, 174 insertions(+), 159 deletions(-) rename src/{nftunspentindex.h => ctokens/tokenutxos.h} (69%) diff --git a/src/Makefile.am b/src/Makefile.am index a178d8315..62340f459 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -91,7 +91,6 @@ endif # navcoin core # NAVCOIN_CORE_H = \ addressindex.h \ - nftunspentindex.h \ spentindex.h \ timestampindex.h \ addrman.h \ @@ -334,6 +333,7 @@ libnavcoin_consensus_a_SOURCES = \ consensus/programs.h \ consensus/program_actions.h \ ctokens/ctokens.h \ + ctokens/tokenutxos.h \ ctokens/tokenid.h \ dotnav/namedata.h \ dotnav/namerecord.h \ diff --git a/src/coins.cpp b/src/coins.cpp index cb739ddfb..275f2cf85 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -53,7 +53,7 @@ bool CStateView::GetConsultation(const uint256 &cid, CConsultation& consultation bool CStateView::GetConsultationAnswer(const uint256 &cid, CConsultationAnswer& answer) const { return false; } bool CStateView::GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const { return false; } bool CStateView::GetToken(const uint256 &id, TokenInfo& token) const { return false; } -bool CStateView::GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const { return false; }; +bool CStateView::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const { return false; }; bool CStateView::GetNameRecord(const uint256 &id, NameRecordValue& height) const { return false; } bool CStateView::GetNameData(const uint256 &id, NameDataValues& data) { return false; } bool CStateView::HaveCoins(const uint256 &txid) const { return false; } @@ -80,7 +80,7 @@ uint256 CStateView::GetBestBlock() const { return uint256(); } bool CStateView::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap& mapConsultations, CConsultationAnswerMap& mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlock, const int& nCacheExcludeVotes) { return false; } CStateViewCursor *CStateView::Cursor() const { return 0; } @@ -94,7 +94,7 @@ bool CStateViewBacked::GetConsultation(const uint256 &cid, CConsultation &consul bool CStateViewBacked::GetConsultationAnswer(const uint256 &cid, CConsultationAnswer &answer) const { return base->GetConsultationAnswer(cid, answer); } bool CStateViewBacked::GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const { return base->GetConsensusParameter(pid, cparameter); } bool CStateViewBacked::GetToken(const uint256 &id, TokenInfo& token) const { return base->GetToken(id, token); } -bool CStateViewBacked::GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const { return base->GetTokenUtxo(id, tokenUtxo); } +bool CStateViewBacked::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const { return base->GetTokenUtxos(id, tokenUtxos); } bool CStateViewBacked::GetNameRecord(const uint256 &id, NameRecordValue& height) const { return base->GetNameRecord(id, height); } bool CStateViewBacked::GetNameData(const uint256 &id, NameDataValues& data) { return base->GetNameData(id, data); } bool CStateViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); } @@ -123,10 +123,10 @@ void CStateViewBacked::SetBackend(CStateView &viewIn) { base = &viewIn; } bool CStateViewBacked::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap &mapConsultations, CConsultationAnswerMap &mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlock, const int &nCacheExcludeVotes) { - return base->BatchWrite(mapCoins, mapProposals, mapPaymentRequests, mapVotes, mapConsultations, mapAnswers, mapConsensus, mapTokens, mapNameRecords, mapNameData, hashBlock, nCacheExcludeVotes); + return base->BatchWrite(mapCoins, mapProposals, mapPaymentRequests, mapVotes, mapConsultations, mapAnswers, mapConsensus, mapTokens, mapTokenUtxos, mapNameRecords, mapNameData, hashBlock, nCacheExcludeVotes); } CStateViewCursor *CStateViewBacked::Cursor() const { return base->Cursor(); } @@ -282,18 +282,19 @@ TokenMap::const_iterator CStateViewCache::FetchToken(const uint256 &id) const { return ret; } -CTokenUtxoMap::const_iterator CStateViewCache::FetchTokenUtxo(const TokenId &id) const { - CTokenUtxoMap::iterator it = cacheTokenUtxos.find(id); +TokenUtxoMap::const_iterator CStateViewCache::FetchTokenUtxos(const TokenId &id) const { + TokenUtxoMap::iterator it = cacheTokenUtxos.find(id); - if (it != cacheTokenUtxos.end()) + if (it != cacheTokenUtxos.end() && it->second.size() > 0) return it; - CNftUnspentIndexValue tmp; + TokenUtxoValues tmp; - if (!base->GetTokenUtxo(id, tmp) || tmp.IsNull()) + if (!base->GetTokenUtxos(id, tmp) || tmp.size() == 0) return cacheTokenUtxos.end(); - CTokenUtxoMap::iterator ret = cacheTokenUtxos.insert(std::make_pair(id, tmp)).first; + TokenUtxoMap::iterator ret = cacheTokenUtxos.insert(std::make_pair(id, TokenUtxoValues())).first; + tmp.swap(ret->second); return ret; } @@ -409,10 +410,10 @@ bool CStateViewCache::GetToken(const uint256 &id, TokenInfo &token) const { return false; } -bool CStateViewCache::GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const { - CTokenUtxoMap::const_iterator it = FetchTokenUtxo(id); - if (it != cacheTokenUtxos.end() && !it->second.IsNull()) { - tokenUtxo = it->second; +bool CStateViewCache::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const { + TokenUtxoMap::const_iterator it = FetchTokenUtxos(id); + if (it != cacheTokenUtxos.end() && it->second.size() > 0) { + tokenUtxos = it->second; return true; } return false; @@ -645,6 +646,17 @@ TokenModifier CStateViewCache::ModifyToken(const uint256 &id, int nHeight) { return TokenModifier(*this, ret.first, nHeight); } +TokenUtxosModifier CStateViewCache::ModifyTokenUtxos(const TokenId &id, int blockHeight) { + assert(!hasModifier); + std::pair ret = cacheTokenUtxos.insert(std::make_pair(id, TokenUtxoValues())); + if (ret.second) { + if (!base->GetTokenUtxos(id, ret.first->second)) { + ret.first->second.clear(); + } + } + return TokenUtxosModifier(*this, ret.first, blockHeight); +} + NameRecordModifier CStateViewCache::ModifyNameRecord(const uint256 &id, int nHeight) { assert(!hasModifier); std::pair ret = cacheNameRecords.insert(std::make_pair(id, 0)); @@ -802,11 +814,17 @@ bool CStateViewCache::AddToken(const Token& token) const { return true; } -bool CStateViewCache::UpdateTokenUtxo(const TokenId &id, const CNftUnspentIndexValue &utxo) const { - if (cacheTokenUtxos.count(id)) - cacheTokenUtxos[id] = utxo; - else - cacheTokenUtxos.insert(std::make_pair(id, utxo)); +bool CStateViewCache::AddTokenUtxo(const TokenId& id, const TokenUtxoEntry& utxo) const { + if (cacheTokenUtxos.count(id)) { + cacheTokenUtxos[id].erase( + std::remove_if(cacheTokenUtxos[id].begin(), cacheTokenUtxos[id].end(), + [&utxo](const TokenUtxoEntry & o) { return o.first == utxo.first && o.second.IsNull(); }), + cacheTokenUtxos[id].end()); + cacheTokenUtxos[id].push_back(utxo); + } else { + cacheTokenUtxos.insert(std::make_pair(id, TokenUtxoValues())); + cacheTokenUtxos[id].push_back(utxo); + } return true; } @@ -864,6 +882,28 @@ bool CStateViewCache::RemoveToken(const uint256 &id) const { return true; } +bool CStateViewCache::RemoveTokenUtxo(const TokenUtxoKey &key) const { + if (!HaveTokenUtxo(key.tokenId)) + return false; + + if (cacheTokenUtxos.count(key.tokenId)) + { + TokenUtxoValues temp; + + for (auto& it: cacheTokenUtxos[key.tokenId]) { + if (it.first == key.blockHeight) { + temp.push_back(TokenUtxoEntry(key.blockHeight, TokenUtxoValue())); + } else { + temp.push_back(it); + } + } + + cacheTokenUtxos[key.tokenId] = temp; + } + + return true; +} + bool CStateViewCache::RemoveNameRecord(const uint256 &id) const { if (!HaveNameRecord(id)) return false; @@ -999,8 +1039,8 @@ bool CStateViewCache::HaveToken(const uint256 &id) const { } bool CStateViewCache::HaveTokenUtxo(const TokenId &id) const { - CTokenUtxoMap::const_iterator it = FetchTokenUtxo(id); - return (it != cacheTokenUtxos.end() && !it->second.IsNull()); + TokenUtxoMap::const_iterator it = FetchTokenUtxos(id); + return (it != cacheTokenUtxos.end() && it->second.size()); } bool CStateViewCache::HaveNameRecord(const uint256 &id) const { @@ -1059,7 +1099,7 @@ void CStateViewCache::SetBestBlock(const uint256 &hashBlockIn) { bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap& mapVotes, CConsultationMap& mapConsultations, CConsultationAnswerMap& mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, NameRecordMap& mapNameRecords, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlockIn, const int &nCacheExcludeVotesIn) { assert(!hasModifier); assert(!hasModifierConsensus); @@ -1184,7 +1224,7 @@ bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals } bool CStateViewCache::Flush() { - bool fOk = base->BatchWrite(cacheCoins, cacheProposals, cachePaymentRequests, cacheVotes, cacheConsultations, cacheAnswers, cacheConsensus, cacheTokens, cacheNameRecords, cacheNameData, hashBlock, nCacheExcludeVotes); + bool fOk = base->BatchWrite(cacheCoins, cacheProposals, cachePaymentRequests, cacheVotes, cacheConsultations, cacheAnswers, cacheConsensus, cacheTokens, cacheTokenUtxos, cacheNameRecords, cacheNameData, hashBlock, nCacheExcludeVotes); cacheCoins.clear(); cacheProposals.clear(); cachePaymentRequests.clear(); @@ -1193,6 +1233,7 @@ bool CStateViewCache::Flush() { cacheAnswers.clear(); cacheConsensus.clear(); cacheTokens.clear(); + cacheTokenUtxos.clear(); cacheNameRecords.clear(); cacheNameData.clear(); cachedCoinsUsage = 0; diff --git a/src/coins.h b/src/coins.h index 0048780cd..97c10e14d 100644 --- a/src/coins.h +++ b/src/coins.h @@ -12,12 +12,12 @@ #include #include #include -#include -#include "consensus/dao.h" -#include "ctokens/ctokens.h" -#include "dotnav/namerecord.h" -#include "dotnav/namedata.h" +#include +#include +#include +#include +#include #include #include @@ -324,7 +324,6 @@ typedef std::vector CVoteMapKey; typedef CVoteList CVoteMapValue; typedef std::map CVoteMap; typedef std::map CProposalMap; -typedef std::map CTokenUtxoMap; typedef std::map CPaymentRequestMap; typedef std::map CConsultationMap; typedef std::map CConsultationAnswerMap; @@ -386,7 +385,7 @@ class CStateView virtual bool HaveConsensusParameter(const int &pid) const; virtual bool GetToken(const uint256 &id, TokenInfo& token) const; - virtual bool GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const; + virtual bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const; virtual bool GetAllTokens(TokenMap& map); virtual bool HaveToken(const uint256 &id) const; virtual bool HaveTokenUtxo(const TokenId &id) const; @@ -409,7 +408,7 @@ class CStateView virtual bool BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap &mapConsultations, CConsultationAnswerMap &mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlock, const int &nCacheExcludeVotes); @@ -449,7 +448,7 @@ class CStateViewBacked : public CStateView bool GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const; bool HaveConsensusParameter(const int &pid) const; bool GetToken(const uint256 &id, TokenInfo& token) const; - bool GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const; + bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const; bool GetAllTokens(TokenMap& map); bool HaveToken(const uint256 &id) const; bool HaveTokenUtxo(const TokenId &id) const; @@ -469,7 +468,7 @@ class CStateViewBacked : public CStateView bool BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap &mapConsultations, CConsultationAnswerMap &mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlock, const int &nCacheExcludeVotes); CStateViewCursor *Cursor() const; @@ -595,6 +594,22 @@ class TokenModifier friend class CStateViewCache; }; +class TokenUtxosModifier +{ +private: + CStateViewCache& cache; + TokenUtxoMap::iterator it; + TokenUtxosModifier(CStateViewCache& cache_, TokenUtxoMap::iterator it_, int blockHeight=0); + TokenUtxoValues prev; + int blockHeight; + +public: + TokenUtxoValues* operator->() { return &it->second; } + TokenUtxoValues& operator*() { return it->second; } + ~TokenUtxosModifier(); + friend class CStateViewCache; +}; + class NameRecordModifier { private: @@ -658,7 +673,7 @@ class CStateViewCache : public CStateViewBacked mutable uint256 hashBlock; mutable CCoinsMap cacheCoins; mutable CProposalMap cacheProposals; - mutable CTokenUtxoMap cacheTokenUtxos; + mutable TokenUtxoMap cacheTokenUtxos; mutable CPaymentRequestMap cachePaymentRequests; mutable CVoteMap cacheVotes; mutable CConsultationMap cacheConsultations; @@ -696,7 +711,7 @@ class CStateViewCache : public CStateViewBacked bool GetConsultationAnswer(const uint256 &cid, CConsultationAnswer& answer) const; bool GetConsensusParameter(const int& pid, CConsensusParameter& cparameter) const; bool GetToken(const uint256& pid, TokenInfo& token) const; - bool GetTokenUtxo(const TokenId &id, CNftUnspentIndexValue &tokenUtxo) const; + bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const; bool GetNameRecord(const uint256& pid, NameRecordValue& height) const; bool GetNameData(const uint256& pid, NameDataValues& data); bool GetAllProposals(CProposalMap& map); @@ -712,7 +727,7 @@ class CStateViewCache : public CStateViewBacked bool BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap &mapConsultations, CConsultationAnswerMap &mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlockIn, const int &nCacheExcludeVotes); bool AddProposal(const CProposal& proposal) const; @@ -720,7 +735,7 @@ class CStateViewCache : public CStateViewBacked bool AddCachedVoter(const CVoteMapKey &voter, CVoteMapValue& vote) const; bool AddConsultation(const CConsultation& consultation) const; bool AddToken(const Token& token) const; - bool UpdateTokenUtxo(const TokenId &id, const CNftUnspentIndexValue &utxo) const; + bool AddTokenUtxo(const TokenId& id, const TokenUtxoEntry& utxo) const; bool AddNameRecord(const NameRecord& record) const; bool AddNameData(const uint256& id, const NameDataEntry& record) const; bool AddConsultationAnswer(const CConsultationAnswer& answer); @@ -728,6 +743,7 @@ class CStateViewCache : public CStateViewBacked bool RemovePaymentRequest(const uint256 &prid) const; bool RemoveCachedVoter(const CVoteMapKey &voter) const; bool RemoveToken(const uint256 &pid) const; + bool RemoveTokenUtxo(const TokenUtxoKey &key) const; bool RemoveNameRecord(const uint256 &pid) const; bool RemoveNameData(const NameDataKey &id) const; bool RemoveConsultation(const uint256 &cid); @@ -766,6 +782,7 @@ class CStateViewCache : public CStateViewBacked CConsultationAnswerModifier ModifyConsultationAnswer(const uint256 &cid, int nHeight = 0); CConsensusParameterModifier ModifyConsensusParameter(const int &pid, int nHeight = 0); TokenModifier ModifyToken(const uint256 &id, int nHeight = 0); + TokenUtxosModifier ModifyTokenUtxos(const TokenId &id, int blockHeight = 0); NameRecordModifier ModifyNameRecord(const uint256 &id, int nHeight = 0); NameDataModifier ModifyNameData(const uint256& id, int nHeight = 0); @@ -842,7 +859,7 @@ class CStateViewCache : public CStateViewBacked CConsultationAnswerMap::const_iterator FetchConsultationAnswer(const uint256 &cid) const; CConsensusParameterMap::const_iterator FetchConsensusParameter(const int &pid) const; TokenMap::const_iterator FetchToken(const uint256 &id) const; - CTokenUtxoMap::const_iterator FetchTokenUtxo(const TokenId &id) const; + TokenUtxoMap::const_iterator FetchTokenUtxos(const TokenId &id) const; NameRecordMap::const_iterator FetchNameRecord(const uint256 &id) const; NameDataMap::const_iterator FetchNameData(const uint256 &id) const; diff --git a/src/nftunspentindex.h b/src/ctokens/tokenutxos.h similarity index 69% rename from src/nftunspentindex.h rename to src/ctokens/tokenutxos.h index 2b1baaec0..c936a3c90 100644 --- a/src/nftunspentindex.h +++ b/src/ctokens/tokenutxos.h @@ -3,17 +3,17 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef NAVCOIN_NFTUNSPENTINDEX_H -#define NAVCOIN_NFTUNSPENTINDEX_H +#ifndef NAVCOIN_TOKENUTXOS_H +#define NAVCOIN_TOKENUTXOS_H #include -struct CNftUnspentIndexKey { +struct TokenUtxoKey { TokenId tokenId; - uint32_t blockHeight; + uint64_t blockHeight; size_t GetSerializeSize(int nType, int nVersion) const { - return 32 + 8 + 4; + return 32 + 8 + 8; } template void Serialize(Stream& s, int nType, int nVersion) const { @@ -26,12 +26,12 @@ struct CNftUnspentIndexKey { blockHeight = ser_readdata32be(s); } - CNftUnspentIndexKey(TokenId t, int h) { + TokenUtxoKey(TokenId t, int h) { tokenId = t; blockHeight = h; } - CNftUnspentIndexKey() { + TokenUtxoKey() { SetNull(); } @@ -45,7 +45,7 @@ struct CNftUnspentIndexKey { } }; -struct CNftUnspentIndexValue { +struct TokenUtxoValue { uint256 hash; std::vector spendingKey; uint32_t n; @@ -59,13 +59,13 @@ struct CNftUnspentIndexValue { READWRITE(n); } - CNftUnspentIndexValue(uint256 _hash, std::vector _spendingKey, uint32_t _n) { + TokenUtxoValue(uint256 _hash, std::vector _spendingKey, uint32_t _n) { hash = _hash; spendingKey = _spendingKey; n = _n; } - CNftUnspentIndexValue() { + TokenUtxoValue() { SetNull(); } @@ -80,15 +80,8 @@ struct CNftUnspentIndexValue { } }; -struct CNftUnspentIndexKeyCompare -{ - bool operator()(const CNftUnspentIndexKey& a, const CNftUnspentIndexKey& b) const { - if (a.tokenId == b.tokenId) { - return a.blockHeight < b.blockHeight; - } else { - return a.tokenId < b.tokenId; - } - } -}; +typedef std::pair TokenUtxoEntry; +typedef std::vector TokenUtxoValues; +typedef std::map TokenUtxoMap; -#endif // NAVCOIN_NFTUNSPENTINDEX_H +#endif // NAVCOIN_TOKENUTXOS_H diff --git a/src/main.cpp b/src/main.cpp index f882f1016..fb3e5bf81 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2167,24 +2167,6 @@ bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) return true; } -bool GetNftUnspentIndex(const TokenId &id, CNftUnspentIndexValue &utxo) -{ - std::vector utxos; - - if (!fNftIndex) - return false; - - if (!pblocktree->ReadNftUnspentIndex(id, utxos)) - return false; - - if (utxos.size() > 0) - utxo = utxos[utxos.size() - 1]; - else - utxo = CNftUnspentIndexValue(); - - return true; -} - bool HashOnchainActive(const uint256 &hash) { CBlockIndex* pblockindex = mapBlockIndex[hash]; @@ -2890,7 +2872,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI std::vector > addressHistory; std::map addressHistoryMap; std::vector > addressUnspentIndex; - std::vector > nftUnspentIndex; + std::vector > tokenUtxoIndex; std::vector > spentIndex; bool fCFund = IsCommunityFundEnabled(pindex->pprev, Params().GetConsensus()); @@ -3027,12 +3009,8 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI // Check if we have an nft if (token->nVersion == 1) { - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(txout.tokenId, pindex->nHeight), CNftUnspentIndexValue())); - - CNftUnspentIndexValue lastUtxo; - - if (GetNftUnspentIndex(txout.tokenId, lastUtxo)) - view.UpdateTokenUtxo(txout.tokenId, lastUtxo); + if (!view.RemoveTokenUtxo(TokenUtxoKey(txout.tokenId, pindex->nHeight))) + return AbortNode(state, "Failed to write token utxo index"); } } } @@ -3425,10 +3403,6 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI return true; } - if (fNftIndex) - if (!pblocktree->UpdateNftUnspentIndex(nftUnspentIndex)) - return AbortNode(state, "Failed to write nft unspent index"); - if (fAddressIndex) { if (!pblocktree->EraseAddressIndex(addressIndex)) { return AbortNode(state, "Failed to delete address index"); @@ -4076,7 +4050,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::vector > addressHistory; std::map addressHistoryMap; std::vector > addressUnspentIndex; - std::vector > nftUnspentIndex; + std::vector > tokenUtxoIndex; std::vector > spentIndex; CCheckQueueControl control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : nullptr); @@ -5035,12 +5009,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (token->nVersion == 1) { auto op = COutPoint(tx.GetHash(), i); - nftUnspentIndex.push_back(std::make_pair(CNftUnspentIndexKey(vout.tokenId, pindex->nHeight), CNftUnspentIndexValue(op.hash, vout.spendingKey, op.n))); - - CNftUnspentIndexValue lastUtxo; - - if (GetNftUnspentIndex(vout.tokenId, lastUtxo)) - view.UpdateTokenUtxo(vout.tokenId, lastUtxo); + if (!view.AddTokenUtxo(vout.tokenId, std::make_pair(pindex->nHeight, TokenUtxoValue(op.hash, vout.spendingKey, op.n)))) + return AbortNode(state, "Failed to write token utxo index"); } } } @@ -5384,10 +5354,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!pblocktree->WriteTxIndex(vPos)) return AbortNode(state, "Failed to write transaction index"); - if (fNftIndex) - if (!pblocktree->UpdateNftUnspentIndex(nftUnspentIndex)) - return AbortNode(state, "Failed to write nft unspent index"); - if (fAddressIndex) { if (!pblocktree->WriteAddressIndex(addressIndex)) { return AbortNode(state, "Failed to write address index"); diff --git a/src/main.h b/src/main.h index e55cb990e..094392880 100644 --- a/src/main.h +++ b/src/main.h @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -492,7 +491,6 @@ class CScriptCheck bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector > &hashes); bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); -bool GetNftUnspentIndex(const TokenId &id, CNftUnspentIndexValue &utxo); bool HashOnchainActive(const uint256 &hash); bool GetAddressIndex(uint160 addressHash, int type, std::vector > &addressIndex, diff --git a/src/txdb.cpp b/src/txdb.cpp index dd9767d5b..e6342f635 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -68,10 +68,44 @@ bool CStateViewDB::GetToken(const uint256 &id, TokenInfo &token) const { return db.Read(std::make_pair(DB_TOKENS, id), token); } +bool CStateViewDB::GetTokenUtxos(const TokenId &id, TokenUtxoValues &vect) { + vect.clear(); + + boost::scoped_ptr pcursor(db.NewIterator()); + + pcursor->Seek(std::make_pair(DB_NFTUNSPENTINDEX, uint256())); + + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + std::pair key; + if (pcursor->GetKey(key) && key.first == DB_NFTUNSPENTINDEX) { + if (key.second.tokenId == id) { + TokenUtxoValue data; + if (pcursor->GetValue(data)) { + vect.push_back(std::make_pair(key.second.blockHeight, data)); + pcursor->Next(); + } else { + return error("GetTokenUtxos() : failed to read value"); + } + } else { + pcursor->Next(); + } + } else { + break; + } + } + + return true; +} + bool CStateViewDB::HaveToken(const uint256 &id) const { return db.Exists(std::make_pair(DB_TOKENS, id)); } +bool CStateViewDB::HaveTokenUtxos(const TokenId &id) const { + return db.Exists(std::make_pair(DB_NFTUNSPENTINDEX, id)); +} + bool CStateViewDB::GetNameRecord(const uint256 &id, NameRecordValue &height) const { return db.Read(std::make_pair(DB_NAME_RECORDS, id), height); } @@ -759,46 +793,6 @@ bool CBlockTreeDB::UpdateAddressUnspentIndex(const std::vector >&vect) { - CDBBatch batch(*this); - for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) { - if (it->second.IsNull()) { - batch.Erase(std::make_pair(DB_NFTUNSPENTINDEX, it->first)); - } else { - batch.Write(std::make_pair(DB_NFTUNSPENTINDEX, it->first), it->second); - } - } - return WriteBatch(batch); -} - -bool CBlockTreeDB::ReadNftUnspentIndex(const TokenId tokenId, std::vector &vect) { - boost::scoped_ptr pcursor(NewIterator()); - - pcursor->Seek(std::make_pair(DB_NFTUNSPENTINDEX, uint256())); - - while (pcursor->Valid()) { - boost::this_thread::interruption_point(); - std::pair key; - if (pcursor->GetKey(key) && key.first == DB_NFTUNSPENTINDEX) { - if (key.second.tokenId == tokenId) { - CNftUnspentIndexValue nValue; - if (pcursor->GetValue(nValue)) { - vect.push_back(nValue); - pcursor->Next(); - } else { - return error("failed to get nft unspent value"); - } - } - - pcursor->Next(); - } else { - break; - } - } - - return true; -} - bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &unspentOutputs) { diff --git a/src/txdb.h b/src/txdb.h index 6e5e2a5d5..ec59b7aa0 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -113,7 +113,9 @@ class CStateViewDB : public CStateView bool GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const; bool HaveConsensusParameter(const int &pid) const; bool GetToken(const uint256 &id, TokenInfo &token) const; + bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &vect); bool HaveToken(const uint256 &id) const; + bool HaveTokenUtxos(const TokenId &id) const; bool GetNameRecord(const uint256 &id, NameRecordValue &height) const; bool HaveNameRecord(const uint256 &id) const; @@ -180,8 +182,6 @@ class CBlockTreeDB : public CDBWrapper bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); bool UpdateSpentIndex(const std::vector >&vect); bool UpdateAddressUnspentIndex(const std::vector >&vect); - bool UpdateNftUnspentIndex(const std::vector >&vect); - bool ReadNftUnspentIndex(const TokenId tokenId, std::vector &utxos); bool ReadAddressUnspentIndex(uint160 addressHash, int type, std::vector > &vect); bool WriteAddressIndex(const std::vector > &vect); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 9de7829a6..b0e16262b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6045,13 +6045,16 @@ UniValue listtokens(const UniValue& params, bool fHelp) n.pushKV("balance", std::to_string(tempBalance)); balance += tempBalance; - CNftUnspentIndexValue txout; - if (fWithUtxo && view.GetTokenUtxo(TokenId(it->first, it_.first), txout)) { - UniValue utxo(UniValue::VOBJ); - utxo.pushKV("n", std::to_string(txout.n)); - utxo.pushKV("hash", txout.hash.ToString()); - utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); - n.pushKV("utxo", utxo); + TokenUtxoValues utxos; + if (fWithUtxo && view.GetTokenUtxos(TokenId(it->first, it_.first), utxos)) { + if (utxos.size() > 0) { + auto txout = utxos[utxos.size() - 1].second; + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("n", std::to_string(txout.n)); + utxo.pushKV("hash", txout.hash.ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); + n.pushKV("utxo", utxo); + } } a.push_back(n); @@ -6135,13 +6138,16 @@ UniValue gettoken(const UniValue& params, bool fHelp) n.pushKV("balance", std::to_string(tempBalance)); balance += tempBalance; - CNftUnspentIndexValue txout; - if (fWithUtxo && GetNftUnspentIndex(TokenId(uint256S(params[0].get_str()), it_.first), txout)) { - UniValue utxo(UniValue::VOBJ); - utxo.pushKV("n", std::to_string(txout.n)); - utxo.pushKV("hash", txout.hash.ToString()); - utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); - n.pushKV("utxo", utxo); + TokenUtxoValues utxos; + if (fWithUtxo && view.GetTokenUtxos(TokenId(uint256S(params[0].get_str())), utxos)) { + if (utxos.size() > 0) { + auto txout = utxos[utxos.size() - 1].second; + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("n", std::to_string(txout.n)); + utxo.pushKV("hash", txout.hash.ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); + n.pushKV("utxo", utxo); + } } a.push_back(n); From 5e03b3fddc0a34c82cc2751265b31aa8ccad077c Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 24 Feb 2022 22:01:27 +0800 Subject: [PATCH 39/61] Updated TokenUtxoModified logic --- src/coins.cpp | 21 +++++++++++++++++++++ src/coins.h | 1 + 2 files changed, 22 insertions(+) diff --git a/src/coins.cpp b/src/coins.cpp index 275f2cf85..30389911f 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -1481,6 +1481,27 @@ TokenModifier::~TokenModifier() } } +TokenUtxosModifier::TokenUtxosModifier(CStateViewCache& cache_, TokenUtxoMap::iterator it_, int blockHeight_) : cache(cache_), it(it_), blockHeight(blockHeight_) { + assert(!cache.hasModifier); + cache.hasModifier = true; + prev = it->second; +} + +TokenUtxosModifier::~TokenUtxosModifier() +{ + assert(cache.hasModifier); + cache.hasModifier = false; + + if (it->second.size() == 0) { + cache.cacheTokenUtxos[it->first].clear(); + } + + if (!(prev == it->second)) + { + LogPrint("token", "%s: Modified %stoken utxo %s\n", __func__, blockHeight > 0 ? strprintf("at block height %d ", blockHeight) : "", it->first.token.ToString()); + } +} + NameRecordModifier::NameRecordModifier(CStateViewCache& cache_, NameRecordMap::iterator it_, int height_) : cache(cache_), it(it_), height(height_) { assert(!cache.hasModifier); cache.hasModifier = true; diff --git a/src/coins.h b/src/coins.h index 97c10e14d..a2c4c57a3 100644 --- a/src/coins.h +++ b/src/coins.h @@ -846,6 +846,7 @@ class CStateViewCache : public CStateViewBacked friend class CConsultationAnswerModifier; friend class CConsensusParameterModifier; friend class TokenModifier; + friend class TokenUtxosModifier; friend class NameRecordModifier; friend class NameDataModifier; From 3fb8cae901c9348dca07b8d5bf7b97e1f837cbc7 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 24 Feb 2022 22:06:32 +0800 Subject: [PATCH 40/61] Updated TokenUtxoValue --- src/ctokens/tokenutxos.h | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/ctokens/tokenutxos.h b/src/ctokens/tokenutxos.h index c936a3c90..b2f107224 100644 --- a/src/ctokens/tokenutxos.h +++ b/src/ctokens/tokenutxos.h @@ -50,15 +50,6 @@ struct TokenUtxoValue { std::vector spendingKey; uint32_t n; - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(hash); - READWRITE(spendingKey); - READWRITE(n); - } - TokenUtxoValue(uint256 _hash, std::vector _spendingKey, uint32_t _n) { hash = _hash; spendingKey = _spendingKey; @@ -78,6 +69,25 @@ struct TokenUtxoValue { bool IsNull() const { return hash.IsNull(); } + + bool operator==(const TokenUtxoValue& other) const { + return (hash == other.hash && spendingKey == other.spendingKey && n == other.n); + } + + void swap(NameDataValue &to) { + std::swap(to.hash, hash); + std::swap(to.spendingKey, spendingKey); + std::swap(to.n, n); + } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(hash); + READWRITE(spendingKey); + READWRITE(n); + } }; typedef std::pair TokenUtxoEntry; From ea0773bdf0e302fa18b4de731d30b1685dbc5371 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 24 Feb 2022 22:07:25 +0800 Subject: [PATCH 41/61] Updated TokenUtxoValue --- src/ctokens/tokenutxos.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ctokens/tokenutxos.h b/src/ctokens/tokenutxos.h index b2f107224..3a1587665 100644 --- a/src/ctokens/tokenutxos.h +++ b/src/ctokens/tokenutxos.h @@ -74,7 +74,7 @@ struct TokenUtxoValue { return (hash == other.hash && spendingKey == other.spendingKey && n == other.n); } - void swap(NameDataValue &to) { + void swap(TokenUtxoValue &to) { std::swap(to.hash, hash); std::swap(to.spendingKey, spendingKey); std::swap(to.n, n); From 0ab78f454e2d190b20a086894b8775774254115e Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 24 Feb 2022 22:10:50 +0800 Subject: [PATCH 42/61] Renamed DB_NFTUNSPENTINDEX to DB_TOKEN_UTXO --- src/txdb.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/txdb.cpp b/src/txdb.cpp index e6342f635..1a37615a4 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -26,7 +26,6 @@ static const char DB_ADDRESSUNSPENTINDEX = 'u'; static const char DB_TIMESTAMPINDEX = 's'; static const char DB_BLOCKHASHINDEX = 'z'; static const char DB_SPENTINDEX = 'q'; -static const char DB_NFTUNSPENTINDEX = 'Z'; static const char DB_BLOCK_INDEX = 'b'; static const char DB_VOTEINDEX = 'C'; @@ -41,6 +40,7 @@ static const char DB_LAST_BLOCK = 'l'; static const char DB_EXCLUDE_VOTES = 'X'; static const char DB_TOKENS = 'T'; +static const char DB_TOKEN_UTXO = 'Z'; static const char DB_NAME_RECORDS = 'n'; static const char DB_NAME_DATA = 'N'; @@ -73,12 +73,12 @@ bool CStateViewDB::GetTokenUtxos(const TokenId &id, TokenUtxoValues &vect) { boost::scoped_ptr pcursor(db.NewIterator()); - pcursor->Seek(std::make_pair(DB_NFTUNSPENTINDEX, uint256())); + pcursor->Seek(std::make_pair(DB_TOKEN_UTXO, uint256())); while (pcursor->Valid()) { boost::this_thread::interruption_point(); std::pair key; - if (pcursor->GetKey(key) && key.first == DB_NFTUNSPENTINDEX) { + if (pcursor->GetKey(key) && key.first == DB_TOKEN_UTXO) { if (key.second.tokenId == id) { TokenUtxoValue data; if (pcursor->GetValue(data)) { @@ -103,7 +103,7 @@ bool CStateViewDB::HaveToken(const uint256 &id) const { } bool CStateViewDB::HaveTokenUtxos(const TokenId &id) const { - return db.Exists(std::make_pair(DB_NFTUNSPENTINDEX, id)); + return db.Exists(std::make_pair(DB_TOKEN_UTXO, id)); } bool CStateViewDB::GetNameRecord(const uint256 &id, NameRecordValue &height) const { From e580a3090298fd419111f35c12a59790af773017 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 24 Feb 2022 22:34:03 +0800 Subject: [PATCH 43/61] Updated BatchWrite logic for CStateView flush --- src/coins.cpp | 13 ++++++++++--- src/coins.h | 6 +++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 30389911f..98f3c8364 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -80,7 +80,7 @@ uint256 CStateView::GetBestBlock() const { return uint256(); } bool CStateView::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap& mapConsultations, CConsultationAnswerMap& mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap& mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlock, const int& nCacheExcludeVotes) { return false; } CStateViewCursor *CStateView::Cursor() const { return 0; } @@ -123,7 +123,7 @@ void CStateViewBacked::SetBackend(CStateView &viewIn) { base = &viewIn; } bool CStateViewBacked::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap &mapConsultations, CConsultationAnswerMap &mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap& mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlock, const int &nCacheExcludeVotes) { return base->BatchWrite(mapCoins, mapProposals, mapPaymentRequests, mapVotes, mapConsultations, mapAnswers, mapConsensus, mapTokens, mapTokenUtxos, mapNameRecords, mapNameData, hashBlock, nCacheExcludeVotes); @@ -1099,7 +1099,7 @@ void CStateViewCache::SetBestBlock(const uint256 &hashBlockIn) { bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap& mapVotes, CConsultationMap& mapConsultations, CConsultationAnswerMap& mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, NameRecordMap& mapNameRecords, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap& mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlockIn, const int &nCacheExcludeVotesIn) { assert(!hasModifier); assert(!hasModifierConsensus); @@ -1204,6 +1204,13 @@ bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals mapTokens.erase(itOld); } + for (TokenUtxoMap::iterator it = mapTokenUtxos.begin(); it != mapTokenUtxos.end();) { + TokenUtxoValues& entry = cacheTokenUtxos[it->first]; + entry.swap(it->second); + TokenUtxoMap::iterator itOld = it++; + mapTokenUtxos.erase(itOld); + } + for (NameRecordMap::iterator it = mapNameRecords.begin(); it != mapNameRecords.end();) { NameRecordValue& entry = cacheNameRecords[it->first]; entry.swap(it->second); diff --git a/src/coins.h b/src/coins.h index a2c4c57a3..9d12b5923 100644 --- a/src/coins.h +++ b/src/coins.h @@ -408,7 +408,7 @@ class CStateView virtual bool BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap &mapConsultations, CConsultationAnswerMap &mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap& mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlock, const int &nCacheExcludeVotes); @@ -468,7 +468,7 @@ class CStateViewBacked : public CStateView bool BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap &mapConsultations, CConsultationAnswerMap &mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap& mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlock, const int &nCacheExcludeVotes); CStateViewCursor *Cursor() const; @@ -727,7 +727,7 @@ class CStateViewCache : public CStateViewBacked bool BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap &mapConsultations, CConsultationAnswerMap &mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap mapTokenUtxos, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap& mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlockIn, const int &nCacheExcludeVotes); bool AddProposal(const CProposal& proposal) const; From 2fac02ab7dc531e5a1b91666c6276f90d3004f9a Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 24 Feb 2022 22:49:43 +0800 Subject: [PATCH 44/61] Updated BatchWrite logic for txdb batchwrite --- src/txdb.cpp | 19 ++++++++++++++++++- src/txdb.h | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/txdb.cpp b/src/txdb.cpp index 1a37615a4..fb8440977 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -388,7 +388,7 @@ bool CStateViewDB::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap &mapConsultations, CConsultationAnswerMap &mapAnswers, CConsensusParameterMap &mapConsensus, - TokenMap &mapTokens, NameRecordMap &mapNameRecords, + TokenMap &mapTokens, TokenUtxoMap &mapTokenUtxos, NameRecordMap &mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlock, const int &nExcludeVotes) { @@ -493,6 +493,23 @@ bool CStateViewDB::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, mapTokens.erase(itOld); } + for (TokenUtxoMap::iterator it = mapTokenUtxos.begin(); it != mapTokenUtxos.end();) { + if (it->second.size() == 0) { + batch.Erase(std::make_pair(DB_TOKEN_UTXO, it->first)); + } else { + for (auto &it2: it->second) { + if (it2.second.IsNull()) + { + batch.Erase(std::make_pair(DB_TOKEN_UTXO, TokenUtxoKey(it->first, it2.first))); + } else { + batch.Write(std::make_pair(DB_TOKEN_UTXO, TokenUtxoKey(it->first, it2.first)), it2.second); + } + } + } + TokenUtxoMap::iterator itOld = it++; + mapTokenUtxos.erase(itOld); + } + for (NameRecordMap::iterator it = mapNameRecords.begin(); it != mapNameRecords.end();) { if (it->second.IsNull()) { batch.Erase(std::make_pair(DB_NAME_RECORDS, it->first)); diff --git a/src/txdb.h b/src/txdb.h index ec59b7aa0..7541c5736 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -127,7 +127,7 @@ class CStateViewDB : public CStateView bool BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, CPaymentRequestMap &mapPaymentRequests, CVoteMap &mapVotes, CConsultationMap &mapConsultations, CConsultationAnswerMap &mapAnswers, - CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, + CConsensusParameterMap& mapConsensus, TokenMap& mapTokens, TokenUtxoMap &mapTokenUtxos, NameRecordMap& mapNameRecords, NameDataMap& mapNameData, const uint256 &hashBlock, const int &nExcludeVotes); bool GetAllProposals(CProposalMap& map); From 8e94f31a9ffdd50eb53f1f5513c054c309423f18 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Fri, 25 Feb 2022 00:33:15 +0800 Subject: [PATCH 45/61] Fixed a crash and added some logging --- src/coins.cpp | 6 +++--- src/coins.h | 6 +++--- src/main.cpp | 7 ++++--- src/txdb.cpp | 3 +++ 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 98f3c8364..acbe77d1e 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -53,7 +53,7 @@ bool CStateView::GetConsultation(const uint256 &cid, CConsultation& consultation bool CStateView::GetConsultationAnswer(const uint256 &cid, CConsultationAnswer& answer) const { return false; } bool CStateView::GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const { return false; } bool CStateView::GetToken(const uint256 &id, TokenInfo& token) const { return false; } -bool CStateView::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const { return false; }; +bool CStateView::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) { return false; }; bool CStateView::GetNameRecord(const uint256 &id, NameRecordValue& height) const { return false; } bool CStateView::GetNameData(const uint256 &id, NameDataValues& data) { return false; } bool CStateView::HaveCoins(const uint256 &txid) const { return false; } @@ -94,7 +94,7 @@ bool CStateViewBacked::GetConsultation(const uint256 &cid, CConsultation &consul bool CStateViewBacked::GetConsultationAnswer(const uint256 &cid, CConsultationAnswer &answer) const { return base->GetConsultationAnswer(cid, answer); } bool CStateViewBacked::GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const { return base->GetConsensusParameter(pid, cparameter); } bool CStateViewBacked::GetToken(const uint256 &id, TokenInfo& token) const { return base->GetToken(id, token); } -bool CStateViewBacked::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const { return base->GetTokenUtxos(id, tokenUtxos); } +bool CStateViewBacked::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) { return base->GetTokenUtxos(id, tokenUtxos); } bool CStateViewBacked::GetNameRecord(const uint256 &id, NameRecordValue& height) const { return base->GetNameRecord(id, height); } bool CStateViewBacked::GetNameData(const uint256 &id, NameDataValues& data) { return base->GetNameData(id, data); } bool CStateViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); } @@ -410,7 +410,7 @@ bool CStateViewCache::GetToken(const uint256 &id, TokenInfo &token) const { return false; } -bool CStateViewCache::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const { +bool CStateViewCache::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) { TokenUtxoMap::const_iterator it = FetchTokenUtxos(id); if (it != cacheTokenUtxos.end() && it->second.size() > 0) { tokenUtxos = it->second; diff --git a/src/coins.h b/src/coins.h index 9d12b5923..8fa0e09c0 100644 --- a/src/coins.h +++ b/src/coins.h @@ -385,7 +385,7 @@ class CStateView virtual bool HaveConsensusParameter(const int &pid) const; virtual bool GetToken(const uint256 &id, TokenInfo& token) const; - virtual bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const; + virtual bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos); virtual bool GetAllTokens(TokenMap& map); virtual bool HaveToken(const uint256 &id) const; virtual bool HaveTokenUtxo(const TokenId &id) const; @@ -448,7 +448,7 @@ class CStateViewBacked : public CStateView bool GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const; bool HaveConsensusParameter(const int &pid) const; bool GetToken(const uint256 &id, TokenInfo& token) const; - bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const; + bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos); bool GetAllTokens(TokenMap& map); bool HaveToken(const uint256 &id) const; bool HaveTokenUtxo(const TokenId &id) const; @@ -711,7 +711,7 @@ class CStateViewCache : public CStateViewBacked bool GetConsultationAnswer(const uint256 &cid, CConsultationAnswer& answer) const; bool GetConsensusParameter(const int& pid, CConsensusParameter& cparameter) const; bool GetToken(const uint256& pid, TokenInfo& token) const; - bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) const; + bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos); bool GetNameRecord(const uint256& pid, NameRecordValue& height) const; bool GetNameData(const uint256& pid, NameDataValues& data); bool GetAllProposals(CProposalMap& map); diff --git a/src/main.cpp b/src/main.cpp index fb3e5bf81..63c1bc39c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3009,8 +3009,9 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI // Check if we have an nft if (token->nVersion == 1) { - if (!view.RemoveTokenUtxo(TokenUtxoKey(txout.tokenId, pindex->nHeight))) - return AbortNode(state, "Failed to write token utxo index"); + if (view.HaveTokenUtxo(txout.tokenId)) + if (!view.RemoveTokenUtxo(TokenUtxoKey(txout.tokenId, pindex->nHeight))) + return AbortNode(state, "Failed to remove token utxo from index"); } } } @@ -5010,7 +5011,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin auto op = COutPoint(tx.GetHash(), i); if (!view.AddTokenUtxo(vout.tokenId, std::make_pair(pindex->nHeight, TokenUtxoValue(op.hash, vout.spendingKey, op.n)))) - return AbortNode(state, "Failed to write token utxo index"); + return AbortNode(state, "Failed to add token utxo to index"); } } } diff --git a/src/txdb.cpp b/src/txdb.cpp index fb8440977..8bf574adc 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -79,6 +79,7 @@ bool CStateViewDB::GetTokenUtxos(const TokenId &id, TokenUtxoValues &vect) { boost::this_thread::interruption_point(); std::pair key; if (pcursor->GetKey(key) && key.first == DB_TOKEN_UTXO) { + LogPrint("token", "Checking %s vs %s", key.second.tokenId.token.ToString(), id.token.ToString()); if (key.second.tokenId == id) { TokenUtxoValue data; if (pcursor->GetValue(data)) { @@ -500,8 +501,10 @@ bool CStateViewDB::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, for (auto &it2: it->second) { if (it2.second.IsNull()) { + LogPrint("token", "Removing token utxo %s %d \n", it->first.token.ToString(), it->first.subid); batch.Erase(std::make_pair(DB_TOKEN_UTXO, TokenUtxoKey(it->first, it2.first))); } else { + LogPrint("token", "Adding token utxo %s %d \n", it->first.token.ToString(), it->first.subid); batch.Write(std::make_pair(DB_TOKEN_UTXO, TokenUtxoKey(it->first, it2.first)), it2.second); } } From 583bf48a5a22c04e2f268526c0a4b852daf220e7 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Fri, 25 Feb 2022 00:36:11 +0800 Subject: [PATCH 46/61] Removed a log --- src/txdb.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/txdb.cpp b/src/txdb.cpp index 8bf574adc..31d862e12 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -79,7 +79,6 @@ bool CStateViewDB::GetTokenUtxos(const TokenId &id, TokenUtxoValues &vect) { boost::this_thread::interruption_point(); std::pair key; if (pcursor->GetKey(key) && key.first == DB_TOKEN_UTXO) { - LogPrint("token", "Checking %s vs %s", key.second.tokenId.token.ToString(), id.token.ToString()); if (key.second.tokenId == id) { TokenUtxoValue data; if (pcursor->GetValue(data)) { From e2df75faa927ab1713c6b04d87275011e84d0b6c Mon Sep 17 00:00:00 2001 From: mxaddict Date: Fri, 25 Feb 2022 00:39:46 +0800 Subject: [PATCH 47/61] Fix gettoken --- src/wallet/rpcwallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b0e16262b..1fe840c5a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6139,7 +6139,7 @@ UniValue gettoken(const UniValue& params, bool fHelp) balance += tempBalance; TokenUtxoValues utxos; - if (fWithUtxo && view.GetTokenUtxos(TokenId(uint256S(params[0].get_str())), utxos)) { + if (fWithUtxo && view.GetTokenUtxos(TokenId(uint256S(params[0].get_str()), it_.first), utxos)) { if (utxos.size() > 0) { auto txout = utxos[utxos.size() - 1].second; UniValue utxo(UniValue::VOBJ); From 3183371b29daafc213f44f54eec973ebb950d91c Mon Sep 17 00:00:00 2001 From: mxaddict Date: Wed, 2 Mar 2022 12:29:40 +0800 Subject: [PATCH 48/61] Check for null entries in TokenUtxoValues --- src/wallet/rpcwallet.cpp | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 1fe840c5a..fdb12789d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6048,12 +6048,20 @@ UniValue listtokens(const UniValue& params, bool fHelp) TokenUtxoValues utxos; if (fWithUtxo && view.GetTokenUtxos(TokenId(it->first, it_.first), utxos)) { if (utxos.size() > 0) { - auto txout = utxos[utxos.size() - 1].second; - UniValue utxo(UniValue::VOBJ); - utxo.pushKV("n", std::to_string(txout.n)); - utxo.pushKV("hash", txout.hash.ToString()); - utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); - n.pushKV("utxo", utxo); + TokenUtxoValue txout; + for (int i = utxos.size() - 1; i > -1; ++i) { + if (!utxos[i].second.IsNull()) { + txout = utxos[i].second; + break; + } + } + if (!txout.IsNull()) { + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("n", std::to_string(txout.n)); + utxo.pushKV("hash", txout.hash.ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); + n.pushKV("utxo", utxo); + } } } @@ -6141,12 +6149,20 @@ UniValue gettoken(const UniValue& params, bool fHelp) TokenUtxoValues utxos; if (fWithUtxo && view.GetTokenUtxos(TokenId(uint256S(params[0].get_str()), it_.first), utxos)) { if (utxos.size() > 0) { - auto txout = utxos[utxos.size() - 1].second; - UniValue utxo(UniValue::VOBJ); - utxo.pushKV("n", std::to_string(txout.n)); - utxo.pushKV("hash", txout.hash.ToString()); - utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); - n.pushKV("utxo", utxo); + TokenUtxoValue txout; + for (int i = utxos.size() - 1; i > -1; ++i) { + if (!utxos[i].second.IsNull()) { + txout = utxos[i].second; + break; + } + } + if (!txout.IsNull()) { + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("n", std::to_string(txout.n)); + utxo.pushKV("hash", txout.hash.ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); + n.pushKV("utxo", utxo); + } } } From 7681f54d3a786f142db9990604c8a690374ee2a7 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Wed, 2 Mar 2022 17:37:32 +0800 Subject: [PATCH 49/61] Replaced TokenId with unint256 from SerializeHash(TokenId) --- src/coins.cpp | 28 ++++++++++++++-------------- src/coins.h | 18 +++++++++--------- src/ctokens/tokenutxos.h | 18 +++++++++--------- src/main.cpp | 10 +++++++--- src/txdb.cpp | 6 ++---- src/txdb.h | 2 +- src/wallet/rpcwallet.cpp | 20 ++++---------------- 7 files changed, 46 insertions(+), 56 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index acbe77d1e..4981b2ad8 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -53,7 +53,7 @@ bool CStateView::GetConsultation(const uint256 &cid, CConsultation& consultation bool CStateView::GetConsultationAnswer(const uint256 &cid, CConsultationAnswer& answer) const { return false; } bool CStateView::GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const { return false; } bool CStateView::GetToken(const uint256 &id, TokenInfo& token) const { return false; } -bool CStateView::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) { return false; }; +bool CStateView::GetTokenUtxos(const uint256 &id, TokenUtxoValues &tokenUtxos) { return false; }; bool CStateView::GetNameRecord(const uint256 &id, NameRecordValue& height) const { return false; } bool CStateView::GetNameData(const uint256 &id, NameDataValues& data) { return false; } bool CStateView::HaveCoins(const uint256 &txid) const { return false; } @@ -64,7 +64,7 @@ bool CStateView::HaveConsultation(const uint256 &cid) const { return false; } bool CStateView::HaveConsultationAnswer(const uint256 &cid) const { return false; } bool CStateView::HaveConsensusParameter(const int &pid) const { return false; } bool CStateView::HaveToken(const uint256 &id) const { return false; } -bool CStateView::HaveTokenUtxo(const TokenId &id) const { return false; } +bool CStateView::HaveTokenUtxo(const uint256 &id) const { return false; } bool CStateView::HaveNameRecord(const uint256 &id) const { return false; } bool CStateView::HaveNameData(const uint256 &id) const { return false; } bool CStateView::GetAllProposals(CProposalMap& map) { return false; } @@ -94,7 +94,7 @@ bool CStateViewBacked::GetConsultation(const uint256 &cid, CConsultation &consul bool CStateViewBacked::GetConsultationAnswer(const uint256 &cid, CConsultationAnswer &answer) const { return base->GetConsultationAnswer(cid, answer); } bool CStateViewBacked::GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const { return base->GetConsensusParameter(pid, cparameter); } bool CStateViewBacked::GetToken(const uint256 &id, TokenInfo& token) const { return base->GetToken(id, token); } -bool CStateViewBacked::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) { return base->GetTokenUtxos(id, tokenUtxos); } +bool CStateViewBacked::GetTokenUtxos(const uint256 &id, TokenUtxoValues &tokenUtxos) { return base->GetTokenUtxos(id, tokenUtxos); } bool CStateViewBacked::GetNameRecord(const uint256 &id, NameRecordValue& height) const { return base->GetNameRecord(id, height); } bool CStateViewBacked::GetNameData(const uint256 &id, NameDataValues& data) { return base->GetNameData(id, data); } bool CStateViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); } @@ -105,7 +105,7 @@ bool CStateViewBacked::HaveConsultation(const uint256 &cid) const { return base- bool CStateViewBacked::HaveConsultationAnswer(const uint256 &cid) const { return base->HaveConsultationAnswer(cid); } bool CStateViewBacked::HaveConsensusParameter(const int &pid) const { return base->HaveConsensusParameter(pid); } bool CStateViewBacked::HaveToken(const uint256 &id) const { return base->HaveToken(id); } -bool CStateViewBacked::HaveTokenUtxo(const TokenId &id) const { return base->HaveTokenUtxo(id); } +bool CStateViewBacked::HaveTokenUtxo(const uint256 &id) const { return base->HaveTokenUtxo(id); } bool CStateViewBacked::HaveNameRecord(const uint256 &id) const { return base->HaveNameRecord(id); } bool CStateViewBacked::HaveNameData(const uint256 &id) const { return base->HaveNameData(id); } int CStateViewBacked::GetExcludeVotes() const { return base->GetExcludeVotes(); } @@ -282,7 +282,7 @@ TokenMap::const_iterator CStateViewCache::FetchToken(const uint256 &id) const { return ret; } -TokenUtxoMap::const_iterator CStateViewCache::FetchTokenUtxos(const TokenId &id) const { +TokenUtxoMap::const_iterator CStateViewCache::FetchTokenUtxos(const uint256 &id) const { TokenUtxoMap::iterator it = cacheTokenUtxos.find(id); if (it != cacheTokenUtxos.end() && it->second.size() > 0) @@ -410,7 +410,7 @@ bool CStateViewCache::GetToken(const uint256 &id, TokenInfo &token) const { return false; } -bool CStateViewCache::GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos) { +bool CStateViewCache::GetTokenUtxos(const uint256 &id, TokenUtxoValues &tokenUtxos) { TokenUtxoMap::const_iterator it = FetchTokenUtxos(id); if (it != cacheTokenUtxos.end() && it->second.size() > 0) { tokenUtxos = it->second; @@ -646,7 +646,7 @@ TokenModifier CStateViewCache::ModifyToken(const uint256 &id, int nHeight) { return TokenModifier(*this, ret.first, nHeight); } -TokenUtxosModifier CStateViewCache::ModifyTokenUtxos(const TokenId &id, int blockHeight) { +TokenUtxosModifier CStateViewCache::ModifyTokenUtxos(const uint256 &id, int blockHeight) { assert(!hasModifier); std::pair ret = cacheTokenUtxos.insert(std::make_pair(id, TokenUtxoValues())); if (ret.second) { @@ -814,7 +814,7 @@ bool CStateViewCache::AddToken(const Token& token) const { return true; } -bool CStateViewCache::AddTokenUtxo(const TokenId& id, const TokenUtxoEntry& utxo) const { +bool CStateViewCache::AddTokenUtxo(const uint256 &id, const TokenUtxoEntry& utxo) const { if (cacheTokenUtxos.count(id)) { cacheTokenUtxos[id].erase( std::remove_if(cacheTokenUtxos[id].begin(), cacheTokenUtxos[id].end(), @@ -883,14 +883,14 @@ bool CStateViewCache::RemoveToken(const uint256 &id) const { } bool CStateViewCache::RemoveTokenUtxo(const TokenUtxoKey &key) const { - if (!HaveTokenUtxo(key.tokenId)) + if (!HaveTokenUtxo(key.id)) return false; - if (cacheTokenUtxos.count(key.tokenId)) + if (cacheTokenUtxos.count(key.id)) { TokenUtxoValues temp; - for (auto& it: cacheTokenUtxos[key.tokenId]) { + for (auto& it: cacheTokenUtxos[key.id]) { if (it.first == key.blockHeight) { temp.push_back(TokenUtxoEntry(key.blockHeight, TokenUtxoValue())); } else { @@ -898,7 +898,7 @@ bool CStateViewCache::RemoveTokenUtxo(const TokenUtxoKey &key) const { } } - cacheTokenUtxos[key.tokenId] = temp; + cacheTokenUtxos[key.id] = temp; } return true; @@ -1038,7 +1038,7 @@ bool CStateViewCache::HaveToken(const uint256 &id) const { return (it != cacheTokens.end() && !it->second.IsNull()); } -bool CStateViewCache::HaveTokenUtxo(const TokenId &id) const { +bool CStateViewCache::HaveTokenUtxo(const uint256 &id) const { TokenUtxoMap::const_iterator it = FetchTokenUtxos(id); return (it != cacheTokenUtxos.end() && it->second.size()); } @@ -1505,7 +1505,7 @@ TokenUtxosModifier::~TokenUtxosModifier() if (!(prev == it->second)) { - LogPrint("token", "%s: Modified %stoken utxo %s\n", __func__, blockHeight > 0 ? strprintf("at block height %d ", blockHeight) : "", it->first.token.ToString()); + LogPrint("token", "%s: Modified %stoken utxo %s\n", __func__, blockHeight > 0 ? strprintf("at block height %d ", blockHeight) : "", it->first.ToString()); } } diff --git a/src/coins.h b/src/coins.h index 8fa0e09c0..f13144c3c 100644 --- a/src/coins.h +++ b/src/coins.h @@ -385,10 +385,10 @@ class CStateView virtual bool HaveConsensusParameter(const int &pid) const; virtual bool GetToken(const uint256 &id, TokenInfo& token) const; - virtual bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos); + virtual bool GetTokenUtxos(const uint256 &id, TokenUtxoValues &tokenUtxos); virtual bool GetAllTokens(TokenMap& map); virtual bool HaveToken(const uint256 &id) const; - virtual bool HaveTokenUtxo(const TokenId &id) const; + virtual bool HaveTokenUtxo(const uint256 &id) const; virtual bool GetNameRecord(const uint256 &id, NameRecordValue& height) const; virtual bool GetAllNameRecords(NameRecordMap& map); @@ -448,10 +448,10 @@ class CStateViewBacked : public CStateView bool GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const; bool HaveConsensusParameter(const int &pid) const; bool GetToken(const uint256 &id, TokenInfo& token) const; - bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos); + bool GetTokenUtxos(const uint256 &id, TokenUtxoValues &tokenUtxos); bool GetAllTokens(TokenMap& map); bool HaveToken(const uint256 &id) const; - bool HaveTokenUtxo(const TokenId &id) const; + bool HaveTokenUtxo(const uint256 &id) const; bool GetNameRecord(const uint256 &id, NameRecordValue& height) const; bool GetAllNameRecords(NameRecordMap& map); @@ -701,7 +701,7 @@ class CStateViewCache : public CStateViewBacked bool HaveConsultationAnswer(const uint256 &cid) const; bool HaveConsensusParameter(const int& pid) const; bool HaveToken(const uint256& id) const; - bool HaveTokenUtxo(const TokenId& id) const; + bool HaveTokenUtxo(const uint256 &id) const; bool HaveNameRecord(const uint256& id) const; bool HaveNameData(const uint256& id) const; bool GetProposal(const uint256 &txid, CProposal &proposal) const; @@ -711,7 +711,7 @@ class CStateViewCache : public CStateViewBacked bool GetConsultationAnswer(const uint256 &cid, CConsultationAnswer& answer) const; bool GetConsensusParameter(const int& pid, CConsensusParameter& cparameter) const; bool GetToken(const uint256& pid, TokenInfo& token) const; - bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &tokenUtxos); + bool GetTokenUtxos(const uint256 &id, TokenUtxoValues &tokenUtxos); bool GetNameRecord(const uint256& pid, NameRecordValue& height) const; bool GetNameData(const uint256& pid, NameDataValues& data); bool GetAllProposals(CProposalMap& map); @@ -735,7 +735,7 @@ class CStateViewCache : public CStateViewBacked bool AddCachedVoter(const CVoteMapKey &voter, CVoteMapValue& vote) const; bool AddConsultation(const CConsultation& consultation) const; bool AddToken(const Token& token) const; - bool AddTokenUtxo(const TokenId& id, const TokenUtxoEntry& utxo) const; + bool AddTokenUtxo(const uint256 &id, const TokenUtxoEntry& utxo) const; bool AddNameRecord(const NameRecord& record) const; bool AddNameData(const uint256& id, const NameDataEntry& record) const; bool AddConsultationAnswer(const CConsultationAnswer& answer); @@ -782,7 +782,7 @@ class CStateViewCache : public CStateViewBacked CConsultationAnswerModifier ModifyConsultationAnswer(const uint256 &cid, int nHeight = 0); CConsensusParameterModifier ModifyConsensusParameter(const int &pid, int nHeight = 0); TokenModifier ModifyToken(const uint256 &id, int nHeight = 0); - TokenUtxosModifier ModifyTokenUtxos(const TokenId &id, int blockHeight = 0); + TokenUtxosModifier ModifyTokenUtxos(const uint256 &id, int blockHeight = 0); NameRecordModifier ModifyNameRecord(const uint256 &id, int nHeight = 0); NameDataModifier ModifyNameData(const uint256& id, int nHeight = 0); @@ -860,7 +860,7 @@ class CStateViewCache : public CStateViewBacked CConsultationAnswerMap::const_iterator FetchConsultationAnswer(const uint256 &cid) const; CConsensusParameterMap::const_iterator FetchConsensusParameter(const int &pid) const; TokenMap::const_iterator FetchToken(const uint256 &id) const; - TokenUtxoMap::const_iterator FetchTokenUtxos(const TokenId &id) const; + TokenUtxoMap::const_iterator FetchTokenUtxos(const uint256 &id) const; NameRecordMap::const_iterator FetchNameRecord(const uint256 &id) const; NameDataMap::const_iterator FetchNameData(const uint256 &id) const; diff --git a/src/ctokens/tokenutxos.h b/src/ctokens/tokenutxos.h index 3a1587665..6156f697b 100644 --- a/src/ctokens/tokenutxos.h +++ b/src/ctokens/tokenutxos.h @@ -9,25 +9,25 @@ #include struct TokenUtxoKey { - TokenId tokenId; + uint256 id; uint64_t blockHeight; size_t GetSerializeSize(int nType, int nVersion) const { - return 32 + 8 + 8; + return 32 + 8; } template void Serialize(Stream& s, int nType, int nVersion) const { - tokenId.Serialize(s, nType, nVersion); + id.Serialize(s, nType, nVersion); ser_writedata32be(s, blockHeight); } template void Unserialize(Stream& s, int nType, int nVersion) { - tokenId.Unserialize(s, nType, nVersion); + id.Unserialize(s, nType, nVersion); blockHeight = ser_readdata32be(s); } - TokenUtxoKey(TokenId t, int h) { - tokenId = t; + TokenUtxoKey(uint256 t, int h) { + id = t; blockHeight = h; } @@ -36,12 +36,12 @@ struct TokenUtxoKey { } void SetNull() { - tokenId.SetNull(); + id.SetNull(); blockHeight = 0; } bool IsNull() const { - return tokenId.IsNull(); + return id.IsNull(); } }; @@ -92,6 +92,6 @@ struct TokenUtxoValue { typedef std::pair TokenUtxoEntry; typedef std::vector TokenUtxoValues; -typedef std::map TokenUtxoMap; +typedef std::map TokenUtxoMap; #endif // NAVCOIN_TOKENUTXOS_H diff --git a/src/main.cpp b/src/main.cpp index 63c1bc39c..c1f1475b0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3007,10 +3007,12 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI { TokenModifier token = view.ModifyToken(tokenId); + auto tokenIdHash = SerializeHash(txout.tokenId); + // Check if we have an nft if (token->nVersion == 1) { - if (view.HaveTokenUtxo(txout.tokenId)) - if (!view.RemoveTokenUtxo(TokenUtxoKey(txout.tokenId, pindex->nHeight))) + if (view.HaveTokenUtxo(tokenIdHash)) + if (!view.RemoveTokenUtxo(TokenUtxoKey(tokenIdHash, pindex->nHeight))) return AbortNode(state, "Failed to remove token utxo from index"); } } @@ -5006,11 +5008,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin { TokenModifier token = view.ModifyToken(tokenId); + auto tokenIdHash = SerializeHash(vout.tokenId); + // Check if we have an nft if (token->nVersion == 1) { auto op = COutPoint(tx.GetHash(), i); - if (!view.AddTokenUtxo(vout.tokenId, std::make_pair(pindex->nHeight, TokenUtxoValue(op.hash, vout.spendingKey, op.n)))) + if (!view.AddTokenUtxo(tokenIdHash, std::make_pair(pindex->nHeight, TokenUtxoValue(op.hash, vout.spendingKey, op.n)))) return AbortNode(state, "Failed to add token utxo to index"); } } diff --git a/src/txdb.cpp b/src/txdb.cpp index 31d862e12..6ab6464c7 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -68,7 +68,7 @@ bool CStateViewDB::GetToken(const uint256 &id, TokenInfo &token) const { return db.Read(std::make_pair(DB_TOKENS, id), token); } -bool CStateViewDB::GetTokenUtxos(const TokenId &id, TokenUtxoValues &vect) { +bool CStateViewDB::GetTokenUtxos(const uint256 &id, TokenUtxoValues &vect) { vect.clear(); boost::scoped_ptr pcursor(db.NewIterator()); @@ -79,7 +79,7 @@ bool CStateViewDB::GetTokenUtxos(const TokenId &id, TokenUtxoValues &vect) { boost::this_thread::interruption_point(); std::pair key; if (pcursor->GetKey(key) && key.first == DB_TOKEN_UTXO) { - if (key.second.tokenId == id) { + if (key.second.id == id) { TokenUtxoValue data; if (pcursor->GetValue(data)) { vect.push_back(std::make_pair(key.second.blockHeight, data)); @@ -500,10 +500,8 @@ bool CStateViewDB::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, for (auto &it2: it->second) { if (it2.second.IsNull()) { - LogPrint("token", "Removing token utxo %s %d \n", it->first.token.ToString(), it->first.subid); batch.Erase(std::make_pair(DB_TOKEN_UTXO, TokenUtxoKey(it->first, it2.first))); } else { - LogPrint("token", "Adding token utxo %s %d \n", it->first.token.ToString(), it->first.subid); batch.Write(std::make_pair(DB_TOKEN_UTXO, TokenUtxoKey(it->first, it2.first)), it2.second); } } diff --git a/src/txdb.h b/src/txdb.h index 7541c5736..aeb1ea8ac 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -113,7 +113,7 @@ class CStateViewDB : public CStateView bool GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const; bool HaveConsensusParameter(const int &pid) const; bool GetToken(const uint256 &id, TokenInfo &token) const; - bool GetTokenUtxos(const TokenId &id, TokenUtxoValues &vect); + bool GetTokenUtxos(const uint256 &id, TokenUtxoValues &vect); bool HaveToken(const uint256 &id) const; bool HaveTokenUtxos(const TokenId &id) const; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index fdb12789d..2f2c0392c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6046,15 +6046,9 @@ UniValue listtokens(const UniValue& params, bool fHelp) balance += tempBalance; TokenUtxoValues utxos; - if (fWithUtxo && view.GetTokenUtxos(TokenId(it->first, it_.first), utxos)) { + if (fWithUtxo && view.GetTokenUtxos(SerializeHash(TokenId(it->first, it_.first)), utxos)) { if (utxos.size() > 0) { - TokenUtxoValue txout; - for (int i = utxos.size() - 1; i > -1; ++i) { - if (!utxos[i].second.IsNull()) { - txout = utxos[i].second; - break; - } - } + auto txout = utxos[utxos.size() - 1].second; if (!txout.IsNull()) { UniValue utxo(UniValue::VOBJ); utxo.pushKV("n", std::to_string(txout.n)); @@ -6147,15 +6141,9 @@ UniValue gettoken(const UniValue& params, bool fHelp) balance += tempBalance; TokenUtxoValues utxos; - if (fWithUtxo && view.GetTokenUtxos(TokenId(uint256S(params[0].get_str()), it_.first), utxos)) { + if (fWithUtxo && view.GetTokenUtxos(SerializeHash(TokenId(uint256S(params[0].get_str()), it_.first)), utxos)) { if (utxos.size() > 0) { - TokenUtxoValue txout; - for (int i = utxos.size() - 1; i > -1; ++i) { - if (!utxos[i].second.IsNull()) { - txout = utxos[i].second; - break; - } - } + auto txout = utxos[utxos.size() - 1].second; if (!txout.IsNull()) { UniValue utxo(UniValue::VOBJ); utxo.pushKV("n", std::to_string(txout.n)); From c76aec622f5aba2e5dbe08e07cd32b63d77e5162 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Wed, 2 Mar 2022 22:38:27 +0800 Subject: [PATCH 50/61] Added more logging for now --- src/coins.cpp | 44 ++++++++++++++++++++++++++++++++++++---- src/coins.h | 14 +++++++------ src/ctokens/tokenutxos.h | 19 ++++++++++++++++- src/main.cpp | 2 +- src/txdb.cpp | 15 +++++++++++++- src/txdb.h | 2 +- src/wallet/rpcwallet.cpp | 3 +++ 7 files changed, 85 insertions(+), 14 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 4981b2ad8..ee6bcc55d 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -64,7 +64,7 @@ bool CStateView::HaveConsultation(const uint256 &cid) const { return false; } bool CStateView::HaveConsultationAnswer(const uint256 &cid) const { return false; } bool CStateView::HaveConsensusParameter(const int &pid) const { return false; } bool CStateView::HaveToken(const uint256 &id) const { return false; } -bool CStateView::HaveTokenUtxo(const uint256 &id) const { return false; } +bool CStateView::HaveTokenUtxos(const uint256 &id) const { return false; } bool CStateView::HaveNameRecord(const uint256 &id) const { return false; } bool CStateView::HaveNameData(const uint256 &id) const { return false; } bool CStateView::GetAllProposals(CProposalMap& map) { return false; } @@ -105,7 +105,7 @@ bool CStateViewBacked::HaveConsultation(const uint256 &cid) const { return base- bool CStateViewBacked::HaveConsultationAnswer(const uint256 &cid) const { return base->HaveConsultationAnswer(cid); } bool CStateViewBacked::HaveConsensusParameter(const int &pid) const { return base->HaveConsensusParameter(pid); } bool CStateViewBacked::HaveToken(const uint256 &id) const { return base->HaveToken(id); } -bool CStateViewBacked::HaveTokenUtxo(const uint256 &id) const { return base->HaveTokenUtxo(id); } +bool CStateViewBacked::HaveTokenUtxos(const uint256 &id) const { return base->HaveTokenUtxos(id); } bool CStateViewBacked::HaveNameRecord(const uint256 &id) const { return base->HaveNameRecord(id); } bool CStateViewBacked::HaveNameData(const uint256 &id) const { return base->HaveNameData(id); } int CStateViewBacked::GetExcludeVotes() const { return base->GetExcludeVotes(); } @@ -815,17 +815,28 @@ bool CStateViewCache::AddToken(const Token& token) const { } bool CStateViewCache::AddTokenUtxo(const uint256 &id, const TokenUtxoEntry& utxo) const { + LogPrint("token", "%s: &cacheTokenUtxos %x\n", __func__, &cacheTokenUtxos); + LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); if (cacheTokenUtxos.count(id)) { + LogPrint("token", "%s: adding token utxo %s\n", __func__, id.ToString()); cacheTokenUtxos[id].erase( std::remove_if(cacheTokenUtxos[id].begin(), cacheTokenUtxos[id].end(), [&utxo](const TokenUtxoEntry & o) { return o.first == utxo.first && o.second.IsNull(); }), cacheTokenUtxos[id].end()); cacheTokenUtxos[id].push_back(utxo); } else { + LogPrint("token", "%s: creating token utxo %s\n", __func__, id.ToString()); cacheTokenUtxos.insert(std::make_pair(id, TokenUtxoValues())); cacheTokenUtxos[id].push_back(utxo); } + for (auto &it: cacheTokenUtxos) { + for (auto &itx: it.second) { + LogPrint("token", "%s: token utxo %s at height %d\n", __func__, it.first.ToString(), itx.first); + } + } + LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); + return true; } @@ -842,7 +853,9 @@ bool CStateViewCache::AddNameRecord(const NameRecord& namerecord) const { } bool CStateViewCache::AddNameData(const uint256& id, const NameDataEntry& namerecord) const { + LogPrint("token", "%s: &cacheNameData %x\n", __func__, &cacheNameData); if (cacheNameData.count(id)) { + LogPrint("token", "%s: adding namedata map %s\n", __func__, id.ToString()); cacheNameData[id].erase( std::remove_if(cacheNameData[id].begin(), cacheNameData[id].end(), [&namerecord](const NameDataEntry & o) { return o.first == namerecord.first && o.second.IsNull(); }), @@ -851,10 +864,17 @@ bool CStateViewCache::AddNameData(const uint256& id, const NameDataEntry& namere } else { + LogPrint("token", "%s: creating namedata map %s\n", __func__, id.ToString()); cacheNameData.insert(std::make_pair(id, NameDataValues())); cacheNameData[id].push_back(namerecord); } + for (auto &it: cacheNameData) { + for (auto &itx: it.second) { + LogPrint("token", "%s: namedata %s at height %d\n", __func__, it.first.ToString(), itx.first); + } + } + return true; } @@ -883,7 +903,7 @@ bool CStateViewCache::RemoveToken(const uint256 &id) const { } bool CStateViewCache::RemoveTokenUtxo(const TokenUtxoKey &key) const { - if (!HaveTokenUtxo(key.id)) + if (!HaveTokenUtxos(key.id)) return false; if (cacheTokenUtxos.count(key.id)) @@ -1038,7 +1058,7 @@ bool CStateViewCache::HaveToken(const uint256 &id) const { return (it != cacheTokens.end() && !it->second.IsNull()); } -bool CStateViewCache::HaveTokenUtxo(const uint256 &id) const { +bool CStateViewCache::HaveTokenUtxos(const uint256 &id) const { TokenUtxoMap::const_iterator it = FetchTokenUtxos(id); return (it != cacheTokenUtxos.end() && it->second.size()); } @@ -1204,6 +1224,9 @@ bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals mapTokens.erase(itOld); } + LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); + LogPrint("token", "%s: mapTokenUtxos.size() %d\n", __func__, mapTokenUtxos.size()); + for (TokenUtxoMap::iterator it = mapTokenUtxos.begin(); it != mapTokenUtxos.end();) { TokenUtxoValues& entry = cacheTokenUtxos[it->first]; entry.swap(it->second); @@ -1211,6 +1234,9 @@ bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals mapTokenUtxos.erase(itOld); } + LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); + LogPrint("token", "%s: mapTokenUtxos.size() %d\n", __func__, mapTokenUtxos.size()); + for (NameRecordMap::iterator it = mapNameRecords.begin(); it != mapNameRecords.end();) { NameRecordValue& entry = cacheNameRecords[it->first]; entry.swap(it->second); @@ -1218,6 +1244,9 @@ bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals mapNameRecords.erase(itOld); } + LogPrint("token", "%s: cacheNameData.size() %d\n", __func__, cacheNameData.size()); + LogPrint("token", "%s: mapNameData.size() %d\n", __func__, mapNameData.size()); + for (NameDataMap::iterator it = mapNameData.begin(); it != mapNameData.end();) { NameDataValues& entry = cacheNameData[it->first]; entry.swap(it->second); @@ -1225,6 +1254,9 @@ bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals mapNameData.erase(itOld); } + LogPrint("token", "%s: cacheNameData.size() %d\n", __func__, cacheNameData.size()); + LogPrint("token", "%s: mapNameData.size() %d\n", __func__, mapNameData.size()); + hashBlock = hashBlockIn; nCacheExcludeVotes = nCacheExcludeVotesIn; return true; @@ -1489,6 +1521,7 @@ TokenModifier::~TokenModifier() } TokenUtxosModifier::TokenUtxosModifier(CStateViewCache& cache_, TokenUtxoMap::iterator it_, int blockHeight_) : cache(cache_), it(it_), blockHeight(blockHeight_) { + LogPrint("token", "%s: CALLED!!!!!!!\n"); assert(!cache.hasModifier); cache.hasModifier = true; prev = it->second; @@ -1496,6 +1529,7 @@ TokenUtxosModifier::TokenUtxosModifier(CStateViewCache& cache_, TokenUtxoMap::it TokenUtxosModifier::~TokenUtxosModifier() { + LogPrint("token", "%s: CALLED!!!!!!!\n"); assert(cache.hasModifier); cache.hasModifier = false; @@ -1531,6 +1565,7 @@ NameRecordModifier::~NameRecordModifier() } NameDataModifier::NameDataModifier(CStateViewCache& cache_, NameDataMap::iterator it_, int height_) : cache(cache_), it(it_), height(height_) { + LogPrint("token", "%s: CALLED!!!!!!!\n"); assert(!cache.hasModifier); cache.hasModifier = true; prev = it->second; @@ -1538,6 +1573,7 @@ NameDataModifier::NameDataModifier(CStateViewCache& cache_, NameDataMap::iterato NameDataModifier::~NameDataModifier() { + LogPrint("token", "%s: CALLED!!!!!!!\n"); assert(cache.hasModifier); cache.hasModifier = false; diff --git a/src/coins.h b/src/coins.h index f13144c3c..77bad3110 100644 --- a/src/coins.h +++ b/src/coins.h @@ -385,10 +385,11 @@ class CStateView virtual bool HaveConsensusParameter(const int &pid) const; virtual bool GetToken(const uint256 &id, TokenInfo& token) const; - virtual bool GetTokenUtxos(const uint256 &id, TokenUtxoValues &tokenUtxos); virtual bool GetAllTokens(TokenMap& map); virtual bool HaveToken(const uint256 &id) const; - virtual bool HaveTokenUtxo(const uint256 &id) const; + + virtual bool GetTokenUtxos(const uint256 &id, TokenUtxoValues &tokenUtxos); + virtual bool HaveTokenUtxos(const uint256 &id) const; virtual bool GetNameRecord(const uint256 &id, NameRecordValue& height) const; virtual bool GetAllNameRecords(NameRecordMap& map); @@ -448,10 +449,11 @@ class CStateViewBacked : public CStateView bool GetConsensusParameter(const int &pid, CConsensusParameter& cparameter) const; bool HaveConsensusParameter(const int &pid) const; bool GetToken(const uint256 &id, TokenInfo& token) const; - bool GetTokenUtxos(const uint256 &id, TokenUtxoValues &tokenUtxos); bool GetAllTokens(TokenMap& map); bool HaveToken(const uint256 &id) const; - bool HaveTokenUtxo(const uint256 &id) const; + + bool GetTokenUtxos(const uint256 &id, TokenUtxoValues &tokenUtxos); + bool HaveTokenUtxos(const uint256 &id) const; bool GetNameRecord(const uint256 &id, NameRecordValue& height) const; bool GetAllNameRecords(NameRecordMap& map); @@ -673,13 +675,13 @@ class CStateViewCache : public CStateViewBacked mutable uint256 hashBlock; mutable CCoinsMap cacheCoins; mutable CProposalMap cacheProposals; - mutable TokenUtxoMap cacheTokenUtxos; mutable CPaymentRequestMap cachePaymentRequests; mutable CVoteMap cacheVotes; mutable CConsultationMap cacheConsultations; mutable CConsultationAnswerMap cacheAnswers; mutable CConsensusParameterMap cacheConsensus; mutable TokenMap cacheTokens; + mutable TokenUtxoMap cacheTokenUtxos; mutable NameRecordMap cacheNameRecords; mutable NameDataMap cacheNameData; mutable int nCacheExcludeVotes; @@ -701,7 +703,7 @@ class CStateViewCache : public CStateViewBacked bool HaveConsultationAnswer(const uint256 &cid) const; bool HaveConsensusParameter(const int& pid) const; bool HaveToken(const uint256& id) const; - bool HaveTokenUtxo(const uint256 &id) const; + bool HaveTokenUtxos(const uint256 &id) const; bool HaveNameRecord(const uint256& id) const; bool HaveNameData(const uint256& id) const; bool GetProposal(const uint256 &txid, CProposal &proposal) const; diff --git a/src/ctokens/tokenutxos.h b/src/ctokens/tokenutxos.h index 6156f697b..77a517c9a 100644 --- a/src/ctokens/tokenutxos.h +++ b/src/ctokens/tokenutxos.h @@ -6,7 +6,7 @@ #ifndef NAVCOIN_TOKENUTXOS_H #define NAVCOIN_TOKENUTXOS_H -#include +#include struct TokenUtxoKey { uint256 id; @@ -43,6 +43,23 @@ struct TokenUtxoKey { bool IsNull() const { return id.IsNull(); } + + bool operator==(const TokenUtxoKey& other) const { + return (id == other.id && blockHeight == other.blockHeight); + } + + bool operator<(const TokenUtxoKey& b) const { + if (id == b.id) { + return blockHeight < b.blockHeight; + } else { + return id < b.id; + } + } + + void swap(TokenUtxoKey &to) { + std::swap(to.id, id); + std::swap(to.blockHeight, blockHeight); + } }; struct TokenUtxoValue { diff --git a/src/main.cpp b/src/main.cpp index c1f1475b0..75f2ae98b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3011,7 +3011,7 @@ bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockI // Check if we have an nft if (token->nVersion == 1) { - if (view.HaveTokenUtxo(tokenIdHash)) + if (view.HaveTokenUtxos(tokenIdHash)) if (!view.RemoveTokenUtxo(TokenUtxoKey(tokenIdHash, pindex->nHeight))) return AbortNode(state, "Failed to remove token utxo from index"); } diff --git a/src/txdb.cpp b/src/txdb.cpp index 6ab6464c7..289f44bf3 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -69,6 +69,7 @@ bool CStateViewDB::GetToken(const uint256 &id, TokenInfo &token) const { } bool CStateViewDB::GetTokenUtxos(const uint256 &id, TokenUtxoValues &vect) { + LogPrint("token", "%s: called!!!\n", __func__); vect.clear(); boost::scoped_ptr pcursor(db.NewIterator()); @@ -102,7 +103,7 @@ bool CStateViewDB::HaveToken(const uint256 &id) const { return db.Exists(std::make_pair(DB_TOKENS, id)); } -bool CStateViewDB::HaveTokenUtxos(const TokenId &id) const { +bool CStateViewDB::HaveTokenUtxos(const uint256 &id) const { return db.Exists(std::make_pair(DB_TOKEN_UTXO, id)); } @@ -493,15 +494,24 @@ bool CStateViewDB::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, mapTokens.erase(itOld); } + for (auto &it: mapTokenUtxos) { + for (auto &itx: it.second) { + LogPrint("token", "%s: mapTokenUtxos utxo %s at height %d\n", __func__, it.first.ToString(), itx.first); + } + } + for (TokenUtxoMap::iterator it = mapTokenUtxos.begin(); it != mapTokenUtxos.end();) { if (it->second.size() == 0) { + LogPrint("token", "%s: removing token utxo %s \n", __func__, it->first.ToString()); batch.Erase(std::make_pair(DB_TOKEN_UTXO, it->first)); } else { for (auto &it2: it->second) { if (it2.second.IsNull()) { + LogPrint("token", "%s: removing token utxo %s at height %d \n", __func__, it->first.ToString(), it2.first); batch.Erase(std::make_pair(DB_TOKEN_UTXO, TokenUtxoKey(it->first, it2.first))); } else { + LogPrint("token", "%s: adding token utxo %s at height %d \n", __func__, it->first.ToString(), it2.first); batch.Write(std::make_pair(DB_TOKEN_UTXO, TokenUtxoKey(it->first, it2.first)), it2.second); } } @@ -522,13 +532,16 @@ bool CStateViewDB::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, for (NameDataMap::iterator it = mapNameData.begin(); it != mapNameData.end();) { if (it->second.size() == 0) { + LogPrint("token", "%s: removing namedata %s \n", __func__, it->first.ToString()); batch.Erase(std::make_pair(DB_NAME_DATA, it->first)); } else { for (auto &it2: it->second) { if (it2.second.IsNull()) { + LogPrint("token", "%s: removing namedata %s at height %d \n", __func__, it->first.ToString(), it2.first); batch.Erase(std::make_pair(DB_NAME_DATA, NameDataKey(it->first, it2.first))); } else { + LogPrint("token", "%s: adding namedata %s at height %d \n", __func__, it->first.ToString(), it2.first); batch.Write(std::make_pair(DB_NAME_DATA, NameDataKey(it->first, it2.first, it2.second.key)), it2.second); } } diff --git a/src/txdb.h b/src/txdb.h index aeb1ea8ac..25624ac18 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -115,7 +115,7 @@ class CStateViewDB : public CStateView bool GetToken(const uint256 &id, TokenInfo &token) const; bool GetTokenUtxos(const uint256 &id, TokenUtxoValues &vect); bool HaveToken(const uint256 &id) const; - bool HaveTokenUtxos(const TokenId &id) const; + bool HaveTokenUtxos(const uint256 &id) const; bool GetNameRecord(const uint256 &id, NameRecordValue &height) const; bool HaveNameRecord(const uint256 &id) const; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2f2c0392c..feade8e79 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6048,6 +6048,9 @@ UniValue listtokens(const UniValue& params, bool fHelp) TokenUtxoValues utxos; if (fWithUtxo && view.GetTokenUtxos(SerializeHash(TokenId(it->first, it_.first)), utxos)) { if (utxos.size() > 0) { + for (auto &x: utxos) { + LogPrint("token", "%s: token utxo %s at height %d\n", __func__, x.second.hash.ToString(), x.first); + } auto txout = utxos[utxos.size() - 1].second; if (!txout.IsNull()) { UniValue utxo(UniValue::VOBJ); From 21c82f7b860182a386f183b819ab3719eb21799e Mon Sep 17 00:00:00 2001 From: mxaddict Date: Wed, 2 Mar 2022 23:15:14 +0800 Subject: [PATCH 51/61] Removed some logging --- src/coins.cpp | 31 ------------------------------- src/txdb.cpp | 13 ------------- src/wallet/rpcwallet.cpp | 3 --- 3 files changed, 47 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index ee6bcc55d..48c3a4d09 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -815,7 +815,6 @@ bool CStateViewCache::AddToken(const Token& token) const { } bool CStateViewCache::AddTokenUtxo(const uint256 &id, const TokenUtxoEntry& utxo) const { - LogPrint("token", "%s: &cacheTokenUtxos %x\n", __func__, &cacheTokenUtxos); LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); if (cacheTokenUtxos.count(id)) { LogPrint("token", "%s: adding token utxo %s\n", __func__, id.ToString()); @@ -830,11 +829,6 @@ bool CStateViewCache::AddTokenUtxo(const uint256 &id, const TokenUtxoEntry& utxo cacheTokenUtxos[id].push_back(utxo); } - for (auto &it: cacheTokenUtxos) { - for (auto &itx: it.second) { - LogPrint("token", "%s: token utxo %s at height %d\n", __func__, it.first.ToString(), itx.first); - } - } LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); return true; @@ -853,9 +847,7 @@ bool CStateViewCache::AddNameRecord(const NameRecord& namerecord) const { } bool CStateViewCache::AddNameData(const uint256& id, const NameDataEntry& namerecord) const { - LogPrint("token", "%s: &cacheNameData %x\n", __func__, &cacheNameData); if (cacheNameData.count(id)) { - LogPrint("token", "%s: adding namedata map %s\n", __func__, id.ToString()); cacheNameData[id].erase( std::remove_if(cacheNameData[id].begin(), cacheNameData[id].end(), [&namerecord](const NameDataEntry & o) { return o.first == namerecord.first && o.second.IsNull(); }), @@ -864,17 +856,10 @@ bool CStateViewCache::AddNameData(const uint256& id, const NameDataEntry& namere } else { - LogPrint("token", "%s: creating namedata map %s\n", __func__, id.ToString()); cacheNameData.insert(std::make_pair(id, NameDataValues())); cacheNameData[id].push_back(namerecord); } - for (auto &it: cacheNameData) { - for (auto &itx: it.second) { - LogPrint("token", "%s: namedata %s at height %d\n", __func__, it.first.ToString(), itx.first); - } - } - return true; } @@ -1224,9 +1209,6 @@ bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals mapTokens.erase(itOld); } - LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); - LogPrint("token", "%s: mapTokenUtxos.size() %d\n", __func__, mapTokenUtxos.size()); - for (TokenUtxoMap::iterator it = mapTokenUtxos.begin(); it != mapTokenUtxos.end();) { TokenUtxoValues& entry = cacheTokenUtxos[it->first]; entry.swap(it->second); @@ -1234,9 +1216,6 @@ bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals mapTokenUtxos.erase(itOld); } - LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); - LogPrint("token", "%s: mapTokenUtxos.size() %d\n", __func__, mapTokenUtxos.size()); - for (NameRecordMap::iterator it = mapNameRecords.begin(); it != mapNameRecords.end();) { NameRecordValue& entry = cacheNameRecords[it->first]; entry.swap(it->second); @@ -1244,9 +1223,6 @@ bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals mapNameRecords.erase(itOld); } - LogPrint("token", "%s: cacheNameData.size() %d\n", __func__, cacheNameData.size()); - LogPrint("token", "%s: mapNameData.size() %d\n", __func__, mapNameData.size()); - for (NameDataMap::iterator it = mapNameData.begin(); it != mapNameData.end();) { NameDataValues& entry = cacheNameData[it->first]; entry.swap(it->second); @@ -1254,9 +1230,6 @@ bool CStateViewCache::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals mapNameData.erase(itOld); } - LogPrint("token", "%s: cacheNameData.size() %d\n", __func__, cacheNameData.size()); - LogPrint("token", "%s: mapNameData.size() %d\n", __func__, mapNameData.size()); - hashBlock = hashBlockIn; nCacheExcludeVotes = nCacheExcludeVotesIn; return true; @@ -1521,7 +1494,6 @@ TokenModifier::~TokenModifier() } TokenUtxosModifier::TokenUtxosModifier(CStateViewCache& cache_, TokenUtxoMap::iterator it_, int blockHeight_) : cache(cache_), it(it_), blockHeight(blockHeight_) { - LogPrint("token", "%s: CALLED!!!!!!!\n"); assert(!cache.hasModifier); cache.hasModifier = true; prev = it->second; @@ -1529,7 +1501,6 @@ TokenUtxosModifier::TokenUtxosModifier(CStateViewCache& cache_, TokenUtxoMap::it TokenUtxosModifier::~TokenUtxosModifier() { - LogPrint("token", "%s: CALLED!!!!!!!\n"); assert(cache.hasModifier); cache.hasModifier = false; @@ -1565,7 +1536,6 @@ NameRecordModifier::~NameRecordModifier() } NameDataModifier::NameDataModifier(CStateViewCache& cache_, NameDataMap::iterator it_, int height_) : cache(cache_), it(it_), height(height_) { - LogPrint("token", "%s: CALLED!!!!!!!\n"); assert(!cache.hasModifier); cache.hasModifier = true; prev = it->second; @@ -1573,7 +1543,6 @@ NameDataModifier::NameDataModifier(CStateViewCache& cache_, NameDataMap::iterato NameDataModifier::~NameDataModifier() { - LogPrint("token", "%s: CALLED!!!!!!!\n"); assert(cache.hasModifier); cache.hasModifier = false; diff --git a/src/txdb.cpp b/src/txdb.cpp index 289f44bf3..e8633b113 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -69,7 +69,6 @@ bool CStateViewDB::GetToken(const uint256 &id, TokenInfo &token) const { } bool CStateViewDB::GetTokenUtxos(const uint256 &id, TokenUtxoValues &vect) { - LogPrint("token", "%s: called!!!\n", __func__); vect.clear(); boost::scoped_ptr pcursor(db.NewIterator()); @@ -494,24 +493,15 @@ bool CStateViewDB::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, mapTokens.erase(itOld); } - for (auto &it: mapTokenUtxos) { - for (auto &itx: it.second) { - LogPrint("token", "%s: mapTokenUtxos utxo %s at height %d\n", __func__, it.first.ToString(), itx.first); - } - } - for (TokenUtxoMap::iterator it = mapTokenUtxos.begin(); it != mapTokenUtxos.end();) { if (it->second.size() == 0) { - LogPrint("token", "%s: removing token utxo %s \n", __func__, it->first.ToString()); batch.Erase(std::make_pair(DB_TOKEN_UTXO, it->first)); } else { for (auto &it2: it->second) { if (it2.second.IsNull()) { - LogPrint("token", "%s: removing token utxo %s at height %d \n", __func__, it->first.ToString(), it2.first); batch.Erase(std::make_pair(DB_TOKEN_UTXO, TokenUtxoKey(it->first, it2.first))); } else { - LogPrint("token", "%s: adding token utxo %s at height %d \n", __func__, it->first.ToString(), it2.first); batch.Write(std::make_pair(DB_TOKEN_UTXO, TokenUtxoKey(it->first, it2.first)), it2.second); } } @@ -532,16 +522,13 @@ bool CStateViewDB::BatchWrite(CCoinsMap &mapCoins, CProposalMap &mapProposals, for (NameDataMap::iterator it = mapNameData.begin(); it != mapNameData.end();) { if (it->second.size() == 0) { - LogPrint("token", "%s: removing namedata %s \n", __func__, it->first.ToString()); batch.Erase(std::make_pair(DB_NAME_DATA, it->first)); } else { for (auto &it2: it->second) { if (it2.second.IsNull()) { - LogPrint("token", "%s: removing namedata %s at height %d \n", __func__, it->first.ToString(), it2.first); batch.Erase(std::make_pair(DB_NAME_DATA, NameDataKey(it->first, it2.first))); } else { - LogPrint("token", "%s: adding namedata %s at height %d \n", __func__, it->first.ToString(), it2.first); batch.Write(std::make_pair(DB_NAME_DATA, NameDataKey(it->first, it2.first, it2.second.key)), it2.second); } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index feade8e79..2f2c0392c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6048,9 +6048,6 @@ UniValue listtokens(const UniValue& params, bool fHelp) TokenUtxoValues utxos; if (fWithUtxo && view.GetTokenUtxos(SerializeHash(TokenId(it->first, it_.first)), utxos)) { if (utxos.size() > 0) { - for (auto &x: utxos) { - LogPrint("token", "%s: token utxo %s at height %d\n", __func__, x.second.hash.ToString(), x.first); - } auto txout = utxos[utxos.size() - 1].second; if (!txout.IsNull()) { UniValue utxo(UniValue::VOBJ); From 34959d71889ddd8896e49887e9bf27b5711cae63 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Wed, 2 Mar 2022 23:25:21 +0800 Subject: [PATCH 52/61] Updated some logging --- src/coins.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 48c3a4d09..c68ebf3a9 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -815,21 +815,22 @@ bool CStateViewCache::AddToken(const Token& token) const { } bool CStateViewCache::AddTokenUtxo(const uint256 &id, const TokenUtxoEntry& utxo) const { - LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); if (cacheTokenUtxos.count(id)) { - LogPrint("token", "%s: adding token utxo %s\n", __func__, id.ToString()); cacheTokenUtxos[id].erase( std::remove_if(cacheTokenUtxos[id].begin(), cacheTokenUtxos[id].end(), [&utxo](const TokenUtxoEntry & o) { return o.first == utxo.first && o.second.IsNull(); }), cacheTokenUtxos[id].end()); cacheTokenUtxos[id].push_back(utxo); } else { - LogPrint("token", "%s: creating token utxo %s\n", __func__, id.ToString()); cacheTokenUtxos.insert(std::make_pair(id, TokenUtxoValues())); cacheTokenUtxos[id].push_back(utxo); } - LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); + for (auto &it: cacheTokenUtxos) { + for (auto &itx: it.second) { + LogPrint("token", "%s: token utxo %s at height %d\n", __func__, it.first.ToString(), itx.first); + } + } return true; } @@ -860,6 +861,12 @@ bool CStateViewCache::AddNameData(const uint256& id, const NameDataEntry& namere cacheNameData[id].push_back(namerecord); } + for (auto &it: cacheNameData) { + for (auto &itx: it.second) { + LogPrint("token", "%s: namedata %s at height %d\n", __func__, it.first.ToString(), itx.first); + } + } + return true; } From cc4634ce5bd9bc7f6d3c8ecb4e45036bd670a1b3 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Wed, 2 Mar 2022 23:39:16 +0800 Subject: [PATCH 53/61] Updated some logging --- src/coins.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/coins.cpp b/src/coins.cpp index c68ebf3a9..3a038925c 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -815,17 +815,22 @@ bool CStateViewCache::AddToken(const Token& token) const { } bool CStateViewCache::AddTokenUtxo(const uint256 &id, const TokenUtxoEntry& utxo) const { + LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); if (cacheTokenUtxos.count(id)) { + LogPrint("token", "%s: adding token utxo %s\n", __func__, id.ToString()); cacheTokenUtxos[id].erase( std::remove_if(cacheTokenUtxos[id].begin(), cacheTokenUtxos[id].end(), [&utxo](const TokenUtxoEntry & o) { return o.first == utxo.first && o.second.IsNull(); }), cacheTokenUtxos[id].end()); cacheTokenUtxos[id].push_back(utxo); } else { + LogPrint("token", "%s: creating token utxo %s\n", __func__, id.ToString()); cacheTokenUtxos.insert(std::make_pair(id, TokenUtxoValues())); cacheTokenUtxos[id].push_back(utxo); } + LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); + for (auto &it: cacheTokenUtxos) { for (auto &itx: it.second) { LogPrint("token", "%s: token utxo %s at height %d\n", __func__, it.first.ToString(), itx.first); From 7c18569130b61d036fb1f3cea1527156fc906358 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 3 Mar 2022 15:45:42 +0800 Subject: [PATCH 54/61] Add a call to view.HaveTokenUtxos to reload the cache with old values before running view.AddTokenUtxo --- src/coins.cpp | 17 ----------------- src/main.cpp | 5 +++++ 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 3a038925c..6c0848144 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -815,28 +815,17 @@ bool CStateViewCache::AddToken(const Token& token) const { } bool CStateViewCache::AddTokenUtxo(const uint256 &id, const TokenUtxoEntry& utxo) const { - LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); if (cacheTokenUtxos.count(id)) { - LogPrint("token", "%s: adding token utxo %s\n", __func__, id.ToString()); cacheTokenUtxos[id].erase( std::remove_if(cacheTokenUtxos[id].begin(), cacheTokenUtxos[id].end(), [&utxo](const TokenUtxoEntry & o) { return o.first == utxo.first && o.second.IsNull(); }), cacheTokenUtxos[id].end()); cacheTokenUtxos[id].push_back(utxo); } else { - LogPrint("token", "%s: creating token utxo %s\n", __func__, id.ToString()); cacheTokenUtxos.insert(std::make_pair(id, TokenUtxoValues())); cacheTokenUtxos[id].push_back(utxo); } - LogPrint("token", "%s: cacheTokenUtxos.size() %d\n", __func__, cacheTokenUtxos.size()); - - for (auto &it: cacheTokenUtxos) { - for (auto &itx: it.second) { - LogPrint("token", "%s: token utxo %s at height %d\n", __func__, it.first.ToString(), itx.first); - } - } - return true; } @@ -866,12 +855,6 @@ bool CStateViewCache::AddNameData(const uint256& id, const NameDataEntry& namere cacheNameData[id].push_back(namerecord); } - for (auto &it: cacheNameData) { - for (auto &itx: it.second) { - LogPrint("token", "%s: namedata %s at height %d\n", __func__, it.first.ToString(), itx.first); - } - } - return true; } diff --git a/src/main.cpp b/src/main.cpp index 75f2ae98b..d49021415 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5014,6 +5014,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (token->nVersion == 1) { auto op = COutPoint(tx.GetHash(), i); + if (view.HaveTokenUtxos(tokenIdHash)) + LogPrint("token", "%s: We have an old utxo set for token"); + else + LogPrint("token", "%s: Fresh utxo set for token"); + if (!view.AddTokenUtxo(tokenIdHash, std::make_pair(pindex->nHeight, TokenUtxoValue(op.hash, vout.spendingKey, op.n)))) return AbortNode(state, "Failed to add token utxo to index"); } From 32f1884aa322bd0e97ba64f49e58a8e0291de165 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Thu, 3 Mar 2022 16:11:56 +0800 Subject: [PATCH 55/61] Fixed rpcwallet listtokens and gettoken to use latest non-null entry from GetTokenUtxos --- src/wallet/rpcwallet.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2f2c0392c..cde2c66d7 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -6048,7 +6048,16 @@ UniValue listtokens(const UniValue& params, bool fHelp) TokenUtxoValues utxos; if (fWithUtxo && view.GetTokenUtxos(SerializeHash(TokenId(it->first, it_.first)), utxos)) { if (utxos.size() > 0) { - auto txout = utxos[utxos.size() - 1].second; + TokenUtxoValue txout; + auto i = utxos.end(); + while (i != utxos.begin()) + { + --i; + if (!i->second.IsNull()) { + txout = i->second; + break; + } + } if (!txout.IsNull()) { UniValue utxo(UniValue::VOBJ); utxo.pushKV("n", std::to_string(txout.n)); @@ -6143,7 +6152,16 @@ UniValue gettoken(const UniValue& params, bool fHelp) TokenUtxoValues utxos; if (fWithUtxo && view.GetTokenUtxos(SerializeHash(TokenId(uint256S(params[0].get_str()), it_.first)), utxos)) { if (utxos.size() > 0) { - auto txout = utxos[utxos.size() - 1].second; + TokenUtxoValue txout; + auto i = utxos.end(); + while (i != utxos.begin()) + { + --i; + if (!i->second.IsNull()) { + txout = i->second; + break; + } + } if (!txout.IsNull()) { UniValue utxo(UniValue::VOBJ); utxo.pushKV("n", std::to_string(txout.n)); From 3bcfbb579a1222996574c087624efb5e2b574bf9 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Sun, 6 Mar 2022 14:26:27 +0800 Subject: [PATCH 56/61] Moved nftindex call to navcoind --- contrib/stressor_token.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/stressor_token.sh b/contrib/stressor_token.sh index 00c25bb06..de161226a 100755 --- a/contrib/stressor_token.sh +++ b/contrib/stressor_token.sh @@ -137,7 +137,7 @@ function copy_array { function nav_cli { - $navpath/navcoin-cli -datadir=${array_data[$1]} -rpcport=${array_rpc_port[$1]} -devnet -nftindex=1 $2 $3 $4 $5 $6 2> /dev/null + $navpath/navcoin-cli -datadir=${array_data[$1]} -rpcport=${array_rpc_port[$1]} -devnet $2 $3 $4 $5 $6 2> /dev/null } function terminate { @@ -819,7 +819,7 @@ function random_verifychain_check { } function start_node { - $(echo $navpath)/navcoind -datadir=${array_data[$1]} -port=${array_p2p_port[$1]} -rpcport=${array_rpc_port[$1]} -devnet -daemon -debug=dao -debug=statehash -ntpminmeasures=0 -dandelion=0 -disablesafemode -staking=0 2> /dev/null + $(echo $navpath)/navcoind -datadir=${array_data[$1]} -port=${array_p2p_port[$1]} -rpcport=${array_rpc_port[$1]} -devnet -daemon -nftindex=1 -debug=dao -debug=statehash -ntpminmeasures=0 -dandelion=0 -disablesafemode -staking=0 2> /dev/null # gdb -batch -ex "run" -ex "bt" --args $(echo $navpath)/navcoind -datadir=${array_data[$1]} -port=${array_p2p_port[$1]} -rpcport=${array_rpc_port[$1]} -devnet -debug=dao -debug=statehash -ntpminmeasures=0 -dandelion=0 -disablesafemode -staking=0 > out.gdb & } From 3402ed0eaf25c878a3a094c1984d69ee4c319f30 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Mon, 7 Mar 2022 23:53:20 +0800 Subject: [PATCH 57/61] Made rpc function changes discussed with alex, added getnft and listnft functions --- src/rpc/client.cpp | 5 +- src/wallet/rpcwallet.cpp | 266 +++++++++++++++++++++++++++------------ 2 files changed, 189 insertions(+), 82 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 6364d3ab0..03b3a46b0 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -94,6 +94,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getspentinfo", 0}, { "getstakerscript", 1 }, { "gettoken", 1 }, + { "getnft", 1 }, + { "getnft", 2 }, { "gettransaction", 1 }, { "gettxout", 1 }, { "gettxout", 2 }, @@ -117,7 +119,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listsinceblock", 1 }, { "listsinceblock", 2 }, { "listtokens", 0 }, - { "listtokens", 1 }, + { "listnfts", 0 }, + { "listnfts", 1 }, { "listtransactions", 1 }, { "listtransactions", 2 }, { "listtransactions", 3 }, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index cde2c66d7..d9e748369 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5988,23 +5988,20 @@ UniValue listtokens(const UniValue& params, bool fHelp) { if (fHelp) throw std::runtime_error( - "listtokens (mine) (with_utxo)\n" + "listtokens (mine)\n" "\nList the confidential tokens.\n" "\nArguments:\n" "1. mine (boolean, optional, default=false) Show only owned tokens\n" - "2. with_utxo (boolean, optional, default=false) Show last utxo for nfts\n" "\nExamples:\n" + HelpExampleCli("listtokens", "") + HelpExampleCli("listtokens", "true") - + HelpExampleCli("listtokens", "true true") ); LOCK2(cs_main, pwalletMain->cs_wallet); bool fMine = params[0].getBool(); - bool fWithUtxo = params.size() > 1 ? params[1].getBool() : false; UniValue ret(UniValue::VARR); TokenMap mapTokens; @@ -6018,7 +6015,9 @@ UniValue listtokens(const UniValue& params, bool fHelp) if (!view.GetToken(it->first, token)) continue; - int64_t balance = 0; + // Check for regular tokens + if (it->second.nVersion != 0) + continue; UniValue o(UniValue::VOBJ); o.pushKV("version", it->second.nVersion); @@ -6028,52 +6027,118 @@ UniValue listtokens(const UniValue& params, bool fHelp) o.pushKV(it->second.nVersion == 0 ? "token_code" : "scheme", it->second.sDesc); o.pushKV("current_supply", it->second.nVersion == 0 ? FormatMoney(it->second.currentSupply) : std::to_string(it->second.mapMetadata.size())); o.pushKV("max_supply", it->second.nVersion == 0 ? FormatMoney(it->second.totalSupply) : std::to_string(it->second.totalSupply)); - if (it->second.nVersion == 0) + o.pushKV("balance", FormatMoney(pwalletMain->GetPrivateBalance(TokenId(it->first, -1)))); + + // Is this token ours? + bool fTokenIsMine = false; + + blsctKey pk; + if (!pwalletMain->GetBLSCTTokenKey(it->second.key, pk)) { - balance += pwalletMain->GetPrivateBalance(TokenId(it->first, -1)); - o.pushKV("balance", FormatMoney(balance)); + blsctKey sk; + + if (!pwalletMain->GetBLSCTSpendKey(sk)) + throw JSONRPCError(RPC_TYPE_ERROR, "Wallet not available"); + + pk = sk.PrivateChildHash(SerializeHash("nft/"+it->second.sName+it->second.sDesc)); + + pwalletMain->AddBLSCTTokenKey(pk); } - else if (it->second.nVersion == 1) - { - UniValue a(UniValue::VARR); - - for (auto& it_: it->second.mapMetadata) { - UniValue n(UniValue::VOBJ); - n.pushKV("index", it_.first); - n.pushKV("metadata", it_.second); - int64_t tempBalance = pwalletMain->GetPrivateBalance(TokenId(it->first, it_.first)); - n.pushKV("balance", std::to_string(tempBalance)); - balance += tempBalance; - - TokenUtxoValues utxos; - if (fWithUtxo && view.GetTokenUtxos(SerializeHash(TokenId(it->first, it_.first)), utxos)) { - if (utxos.size() > 0) { - TokenUtxoValue txout; - auto i = utxos.end(); - while (i != utxos.begin()) - { - --i; - if (!i->second.IsNull()) { - txout = i->second; - break; - } - } - if (!txout.IsNull()) { - UniValue utxo(UniValue::VOBJ); - utxo.pushKV("n", std::to_string(txout.n)); - utxo.pushKV("hash", txout.hash.ToString()); - utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); - n.pushKV("utxo", utxo); + + if (pk.GetG1Element() == it->second.key) + fTokenIsMine = true; + + o.pushKV("is_mine", fTokenIsMine); + if (!fMine || (fMine && fTokenIsMine)) + ret.push_back(o); + } + } + return ret; +} + +UniValue listnfts(const UniValue& params, bool fHelp) +{ + if (fHelp) + throw std::runtime_error( + "listnfts (mine) (with_utxo)\n" + "\nList the confidential tokens.\n" + + "\nArguments:\n" + "1. mine (boolean, optional, default=false) Show only owned tokens\n" + "2. with_utxo (boolean, optional, default=false) Show last utxo for nfts\n" + + "\nExamples:\n" + + HelpExampleCli("listnfts", "") + + HelpExampleCli("listnfts", "true") + + HelpExampleCli("listnfts", "true true") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + bool fMine = params[0].getBool(); + bool fWithUtxo = params.size() > 1 ? params[1].getBool() : false; + + UniValue ret(UniValue::VARR); + TokenMap mapTokens; + CStateViewCache view(pcoinsTip); + + if(view.GetAllTokens(mapTokens)) + { + for (TokenMap::iterator it = mapTokens.begin(); it != mapTokens.end(); it++) + { + TokenInfo token; + if (!view.GetToken(it->first, token)) + continue; + + // Check for nft + if (it->second.nVersion != 1) + continue; + + UniValue o(UniValue::VOBJ); + o.pushKV("version", it->second.nVersion); + o.pushKV("id", it->first.ToString()); + o.pushKV("pubkey", HexStr(it->second.key.Serialize())); + o.pushKV("name", it->second.sName); + o.pushKV(it->second.nVersion == 0 ? "token_code" : "scheme", it->second.sDesc); + o.pushKV("current_supply", it->second.nVersion == 0 ? FormatMoney(it->second.currentSupply) : std::to_string(it->second.mapMetadata.size())); + o.pushKV("max_supply", it->second.nVersion == 0 ? FormatMoney(it->second.totalSupply) : std::to_string(it->second.totalSupply)); + + UniValue a(UniValue::VARR); + + for (auto& it_: it->second.mapMetadata) { + UniValue n(UniValue::VOBJ); + n.pushKV("index", it_.first); + n.pushKV("metadata", it_.second); + n.pushKV("balance", pwalletMain->GetPrivateBalance(TokenId(it->first, it_.first))); + + TokenUtxoValues utxos; + if (fWithUtxo && view.GetTokenUtxos(SerializeHash(TokenId(it->first, it_.first)), utxos)) { + if (utxos.size() > 0) { + TokenUtxoValue txout; + auto i = utxos.end(); + while (i != utxos.begin()) + { + --i; + if (!i->second.IsNull()) { + txout = i->second; + break; } } + if (!txout.IsNull()) { + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("n", std::to_string(txout.n)); + utxo.pushKV("hash", txout.hash.ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); + n.pushKV("utxo", utxo); + } } - - a.push_back(n); } - o.pushKV("nfts", a); + a.push_back(n); } + o.pushKV("nfts", a); + // Is this token ours? bool fTokenIsMine = false; @@ -6098,6 +6163,7 @@ UniValue listtokens(const UniValue& params, bool fHelp) ret.push_back(o); } } + return ret; } @@ -6124,7 +6190,8 @@ UniValue gettoken(const UniValue& params, bool fHelp) if (!view.GetToken(uint256S(params[0].get_str()), token)) return ret; - int64_t balance = 0; + if (token.nVersion != 0) + return ret; ret.pushKV("version", token.nVersion); ret.pushKV("id", params[0].get_str()); @@ -6133,50 +6200,85 @@ UniValue gettoken(const UniValue& params, bool fHelp) ret.pushKV(token.nVersion == 0 ? "token_code" : "scheme", token.sDesc); ret.pushKV("current_supply", token.nVersion == 0 ? FormatMoney(token.currentSupply) : std::to_string(token.mapMetadata.size())); ret.pushKV("max_supply", token.nVersion == 0 ? FormatMoney(token.totalSupply) : std::to_string(token.totalSupply)); - if (token.nVersion == 0) - { - balance += pwalletMain->GetPrivateBalance(TokenId(uint256S(params[0].get_str()), -1)); - ret.pushKV("balance", FormatMoney(balance)); - } - else if (token.nVersion == 1) - { - UniValue a(UniValue::VARR); - for (auto& it_: token.mapMetadata) { - UniValue n(UniValue::VOBJ); - n.pushKV("index", it_.first); - n.pushKV("metadata", it_.second); - int64_t tempBalance = pwalletMain->GetPrivateBalance(TokenId(uint256S(params[0].get_str()), it_.first)); - n.pushKV("balance", std::to_string(tempBalance)); - balance += tempBalance; - - TokenUtxoValues utxos; - if (fWithUtxo && view.GetTokenUtxos(SerializeHash(TokenId(uint256S(params[0].get_str()), it_.first)), utxos)) { - if (utxos.size() > 0) { - TokenUtxoValue txout; - auto i = utxos.end(); - while (i != utxos.begin()) - { - --i; - if (!i->second.IsNull()) { - txout = i->second; - break; - } - } - if (!txout.IsNull()) { - UniValue utxo(UniValue::VOBJ); - utxo.pushKV("n", std::to_string(txout.n)); - utxo.pushKV("hash", txout.hash.ToString()); - utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); - n.pushKV("utxo", utxo); + ret.pushKV("balance", FormatMoney(pwalletMain->GetPrivateBalance(TokenId(uint256S(params[0].get_str()), -1)))); + + return ret; +} + +UniValue getnft(const UniValue& params, bool fHelp) +{ + if (fHelp) + throw std::runtime_error( + "getnft hash (subid) (with_utxo)\n" + "\nShows information about a token.\n" + + + HelpExampleCli("getnft", "90fc7410164a466b78096967ec948fcc13142b0f5fb4397462304c517840d74f") + + HelpExampleCli("getnft", "90fc7410164a466b78096967ec948fcc13142b0f5fb4397462304c517840d74f 1") + + HelpExampleCli("getnft", "90fc7410164a466b78096967ec948fcc13142b0f5fb4397462304c517840d74f 1 true") + ); + + LOCK(cs_main); + + UniValue ret(UniValue::VOBJ); + + CStateViewCache view(pcoinsTip); + + TokenInfo token; + if (!view.GetToken(uint256S(params[0].get_str()), token)) + return ret; + + if (token.nVersion != 1) + return ret; + + int64_t nSubid = params.size() > 1 ? params[1].get_int() : -1; + + bool fWithUtxo = params.size() > 2 ? params[2].getBool() : false; + + ret.pushKV("version", token.nVersion); + ret.pushKV("id", params[0].get_str()); + ret.pushKV("pubkey", HexStr(token.key.Serialize())); + ret.pushKV("name", token.sName); + ret.pushKV(token.nVersion == 0 ? "token_code" : "scheme", token.sDesc); + ret.pushKV("current_supply", token.nVersion == 0 ? FormatMoney(token.currentSupply) : std::to_string(token.mapMetadata.size())); + ret.pushKV("max_supply", token.nVersion == 0 ? FormatMoney(token.totalSupply) : std::to_string(token.totalSupply)); + UniValue a(UniValue::VARR); + for (auto& it_: token.mapMetadata) { + if (nSubid > -1 && it_.first != nSubid) + continue; + + UniValue n(UniValue::VOBJ); + n.pushKV("index", it_.first); + n.pushKV("metadata", it_.second); + n.pushKV("balance", pwalletMain->GetPrivateBalance(TokenId(uint256S(params[0].get_str()), it_.first))); + + TokenUtxoValues utxos; + if (fWithUtxo && view.GetTokenUtxos(SerializeHash(TokenId(uint256S(params[0].get_str()), it_.first)), utxos)) { + if (utxos.size() > 0) { + TokenUtxoValue txout; + auto i = utxos.end(); + while (i != utxos.begin()) + { + --i; + if (!i->second.IsNull()) { + txout = i->second; + break; } } + if (!txout.IsNull()) { + UniValue utxo(UniValue::VOBJ); + utxo.pushKV("n", std::to_string(txout.n)); + utxo.pushKV("hash", txout.hash.ToString()); + utxo.pushKV("spendingKey", HexStr(txout.spendingKey)); + n.pushKV("utxo", utxo); + } } - - a.push_back(n); } - ret.pushKV("nfts", a); + + a.push_back(n); } + ret.pushKV("nfts", a); + return ret; } @@ -6224,7 +6326,9 @@ static const CRPCCommand commands[] = { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true }, { "wallet", "listprivateaddresses", &listprivateaddresses, true }, { "wallet", "listtokens", &listtokens, true }, + { "wallet", "listnfts", &listnfts, true }, { "wallet", "gettoken", &gettoken, true }, + { "wallet", "getnft", &getnft, true }, { "wallet", "getbalance", &getbalance, false }, { "wallet", "getnewaddress", &getnewaddress, true }, { "wallet", "getcoldstakingaddress", &getcoldstakingaddress, true }, From 9dbbf583cf117a125fcd5f0a5898f2e3e4109be2 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 8 Mar 2022 00:20:13 +0800 Subject: [PATCH 58/61] Updated stressor_token --- contrib/stressor_token.sh | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/contrib/stressor_token.sh b/contrib/stressor_token.sh index de161226a..8b4bbc622 100755 --- a/contrib/stressor_token.sh +++ b/contrib/stressor_token.sh @@ -643,11 +643,11 @@ function dice_mint_nft { shuffle_array "${array_stressing_nodes[@]}" node=${shuffled_array[0]} node_receive=${shuffled_array[1]} - nfts=($(nav_cli $node listtokens | jq '.[] | select(.version==1) | .id' | tr "\n" " " | tr -d '"')) + nfts=($(nav_cli $node listnfts | jq '.[] | select(.version==1) | .id' | tr "\n" " " | tr -d '"')) random_scheme=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 100) for n in ${nfts[@]} do - nft_id=$(nav_cli $node listtokens | jq ".[] | select(.id==\"$n\") | .current_supply" | tr -d '"') + nft_id=$(nav_cli $node listnfts | jq ".[] | select(.id==\"$n\") | .current_supply" | tr -d '"') # echo 'nft_id = ' $nft_id out=$(nav_cli $node mintnft $n $nft_id ${array_private_address[$node_receive]} $random_scheme) if [ ! -z $out ] @@ -662,14 +662,14 @@ function dice_send_nft { dice=$(bc <<< "$RANDOM % 100") if [ $dice -lt 90 ]; then - nfts=($(nav_cli $node listtokens | jq '.[] | select(.version==1) | .id' | tr "\n" " " | tr -d '"')) + nfts=($(nav_cli $node listnfts | jq '.[] | select(.version==1) | .id' | tr "\n" " " | tr -d '"')) for n in ${array_stressing_nodes[@]} do for t in ${nfts[@]} do shuffle_array "${array_stressing_nodes[@]}" node_receive=${shuffled_array[0]} - nftid=$(nav_cli $node listtokens | jq ".[] | select(.id==\"$t\") | .nfts | .[] | select(.balance==\"1\") | .index" | shuf -n 1) + nftid=$(nav_cli $node listnfts | jq ".[] | select(.id==\"$t\") | .nfts | .[] | select(.balance==\"1\") | .index" | shuf -n 1) # echo 'nftid= ' $nftid out=$(nav_cli $n sendnft $t $nftid ${array_private_address[$node_receive]}) if [ ! -z $out ] @@ -1105,7 +1105,8 @@ while [ $wait_until_cycle -gt $this_cycle ]; do shuffle_array "${array_stressing_nodes[@]}" node=${shuffled_array[0]} echo Current block: $current_block Current cycle: $this_cycle - $cycles_left cycle\(s\) left to finish. - echo Tokens and NFTs created: $(nav_cli $node listtokens | jq ".[].name" | wc -l) + echo Tokens created: $(nav_cli $node listtokens | jq ".[].name" | wc -l) + echo NFTs created: $(nav_cli $node listnfts | jq ".[].name" | wc -l) echo Active nodes: ${array_active_nodes[@]} Inactive nodes: ${array_stopped_nodes[@]} # for j in $(seq 0 1 $( bc <<< "$node_count-1")); # do @@ -1189,7 +1190,8 @@ then node=${shuffled_array[0]} check_consensus_parameters $node blocks=$(nav_cli $node getinfo|jq .blocks) - echo Tokens and NFTs created: $(nav_cli $node listtokens | jq ".[].name" | wc -l) + echo Tokens created: $(nav_cli $node listtokens | jq ".[].name" | wc -l) + echo NFTs created: $(nav_cli $node listnfts | jq ".[].name" | wc -l) done cycles_left=$(bc <<< "$wait_until_cycle - $this_cycle") previous_block=$current_block @@ -1236,7 +1238,8 @@ echo '' echo Waiting until all nodes are synced wait_until_sync "${array_active_nodes[@]}" echo Ok! Block: $(nav_cli $node getinfo|jq .blocks) Cycle: $(bc <<< $(nav_cli $node getinfo|jq .blocks)/$voting_cycle_length). -echo Tokens and NFTs created: $(nav_cli $node listtokens | jq ".[].name" | wc -l) +echo Tokens created: $(nav_cli $node listtokens | jq ".[].name" | wc -l) +echo NFTs created: $(nav_cli $node listnfts | jq ".[].name" | wc -l) echo '' echo Running verifychain test with node ${verifychain_nodes[@]}... From 6e1f7edbe92a0779d5cbc377a13b07d1534c87d0 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 8 Mar 2022 19:51:50 +0800 Subject: [PATCH 59/61] Updates to the stressor for tokens/nfts --- contrib/stressor_token.sh | 1838 +++++++++++++++++++------------------ 1 file changed, 937 insertions(+), 901 deletions(-) diff --git a/contrib/stressor_token.sh b/contrib/stressor_token.sh index 8b4bbc622..bccc5db32 100755 --- a/contrib/stressor_token.sh +++ b/contrib/stressor_token.sh @@ -88,743 +88,781 @@ bool_network_split=1 #######################################################################################Functions function initialize_network { - array_p2p_port=() - array_rpc_port=() - array_data=() - array_user=() - array_pwd=() + array_p2p_port=() + array_rpc_port=() + array_data=() + array_user=() + array_pwd=() } function initialize_node { - array_p2p_port[$1]=$( bc <<< "10000+$1" ) - array_rpc_port[$1]=$( bc <<< "30000+$1" ) - data_=$(mktemp -d) - array_data[$1]=$data_ - array_user[$1]=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 10) - array_pwd[$1]=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 10) - echo "-datadir=${array_data[$1]} -rpcport=${array_rpc_port[$1]}" - start_node $1 - array_active_nodes[$1]=$1 - array_all_nodes[$1]=$1 + array_p2p_port[$1]=$( bc <<< "10000+$1" ) + array_rpc_port[$1]=$( bc <<< "30000+$1" ) + data_=$(mktemp -d) + array_data[$1]=$data_ + array_user[$1]=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 10) + array_pwd[$1]=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 10) + echo "-datadir=${array_data[$1]} -rpcport=${array_rpc_port[$1]}" + start_node $1 + array_active_nodes[$1]=$1 + array_all_nodes[$1]=$1 } function remove_node { - unset array_active_nodes[$1] - unset array_all_nodes[$1] - unset array_data[$1] - unset array_user[$1] - unset array_pwd[$1] - unset array_p2p_port[$1] - unset array_rpc_port[$1] - unset array_stopped_nodes[$1] + unset array_active_nodes[$1] + unset array_all_nodes[$1] + unset array_data[$1] + unset array_user[$1] + unset array_pwd[$1] + unset array_p2p_port[$1] + unset array_rpc_port[$1] + unset array_stopped_nodes[$1] } trap ctrl_c INT function ctrl_c() { - terminate 1 + terminate 1 } function copy_array { - declare -n array=$1 - unset $2 - for i in ${!array[@]}; - do - eval "$2[$i]=\"${array[$i]}\"" - done + declare -n array=$1 + unset $2 + for i in ${!array[@]}; + do + eval "$2[$i]=\"${array[$i]}\"" + done } function nav_cli { - $navpath/navcoin-cli -datadir=${array_data[$1]} -rpcport=${array_rpc_port[$1]} -devnet $2 $3 $4 $5 $6 2> /dev/null + $navpath/navcoin-cli -datadir=${array_data[$1]} -rpcport=${array_rpc_port[$1]} -devnet $2 $3 $4 $5 $6 2> /dev/null } function terminate { - if [ "$1" == 1 ]; - then - fail_logs_D=$(echo "/tmp/stresser_fail_logs_$RANDOM") - mkdir $fail_logs_D - for i in $(seq 0 1 $( bc <<< "$node_count-1") ); - do - folder_name=$(echo "${array_data[$i]}" | cut -c 10-) - nav_cli $i listproposals > ${array_data[$i]}/devnet/listproposals.out - nav_cli $i listconsultations > ${array_data[$i]}/devnet/listconsultations.out - cp ${array_data[$i]}/devnet/debug.log $fail_logs_D/debug-out-node$i-$folder_name - cp ${array_data[$i]}/devnet/listproposals.out $fail_logs_D/listproposals.out-node$i-$folder_name - cp ${array_data[$i]}/devnet/listconsultations.out $fail_logs_D/listconsultations.out-node$i-$folder_name - done - echo debug.log files, listconsultations.out, listproposals.out files are copied to $fail_logs_D - fi - for i in ${array_active_nodes[@]}; - do - nav_cli $i stop - done - echo "Stopping all nodes..." - sleep 30 - echo Done - killall -9 navcoind - exit $1 + if [ "$1" == 1 ]; + then + fail_logs_D=$(echo "/tmp/stresser_fail_logs_$RANDOM") + mkdir $fail_logs_D + for i in $(seq 0 1 $( bc <<< "$node_count-1") ); + do + folder_name=$(echo "${array_data[$i]}" | cut -c 10-) + nav_cli $i listproposals > ${array_data[$i]}/devnet/listproposals.out + nav_cli $i listconsultations > ${array_data[$i]}/devnet/listconsultations.out + cp ${array_data[$i]}/devnet/debug.log $fail_logs_D/debug-out-node$i-$folder_name + cp ${array_data[$i]}/devnet/listproposals.out $fail_logs_D/listproposals.out-node$i-$folder_name + cp ${array_data[$i]}/devnet/listconsultations.out $fail_logs_D/listconsultations.out-node$i-$folder_name + done + echo debug.log files, listconsultations.out, listproposals.out files are copied to $fail_logs_D + fi + for i in ${array_active_nodes[@]}; + do + nav_cli $i stop + done + echo "Stopping all nodes..." + sleep 30 + echo Done + killall -9 navcoind + exit $1 } function connect_nodes { - nav_cli "$1" "addnode 127.0.0.1:$( bc <<< 10000+$2 ) add" - nav_cli "$1" "addnode 127.0.0.1:$( bc <<< 10000+$2 ) onetry" + nav_cli "$1" "addnode 127.0.0.1:$( bc <<< 10000+$2 ) add" + nav_cli "$1" "addnode 127.0.0.1:$( bc <<< 10000+$2 ) onetry" } function disconnect_nodes { - nav_cli "$1" "addnode 127.0.0.1:$( bc <<< 10000+$2 ) remove" - nav_cli "$1" "disconnectnode 127.0.0.1:$( bc <<< 10000+$2 )" + nav_cli "$1" "addnode 127.0.0.1:$( bc <<< 10000+$2 ) remove" + nav_cli "$1" "disconnectnode 127.0.0.1:$( bc <<< 10000+$2 )" } function select_random_nodes { - if [ "$2" == 1 ]; - then - array_random_nodes=($(shuf -i 1-$( bc <<< "$node_count-1" ) -n $1)) - else - array_random_nodes=($(shuf -i 0-$( bc <<< "$node_count-1" ) -n $1)) - fi + if [ "$2" == 1 ]; + then + array_random_nodes=($(shuf -i 1-$( bc <<< "$node_count-1" ) -n $1)) + else + array_random_nodes=($(shuf -i 0-$( bc <<< "$node_count-1" ) -n $1)) + fi } function shuffle_array { - local array=("$@") - shuffled_array=($(shuf -e ${array[@]})) + local array=("$@") + shuffled_array=($(shuf -e ${array[@]})) } #Establish topology using set variable $network_topology function connect_network { - local local_array=("$@") - if [ "${#local_array[@]}" -lt 1 ]; - then - return - fi - for i in ${!local_array[@]}; - do - local connection_pair=(${local_array[$i]}) - out=$(connect_nodes ${connection_pair[0]} ${connection_pair[1]}) - done - sleep 1 - check_connection "${local_array[@]}" + local local_array=("$@") + if [ "${#local_array[@]}" -lt 1 ]; + then + return + fi + for i in ${!local_array[@]}; + do + local connection_pair=(${local_array[$i]}) + out=$(connect_nodes ${connection_pair[0]} ${connection_pair[1]}) + done + sleep 1 + check_connection "${local_array[@]}" } function disconnect_network { - local local_array=("$@") - for i in ${!local_array[@]}; - do - local connection_pair=(${local_array[$i]}) - out=$(disconnect_nodes ${connection_pair[0]} ${connection_pair[1]}) - done - sleep 5 + local local_array=("$@") + for i in ${!local_array[@]}; + do + local connection_pair=(${local_array[$i]}) + out=$(disconnect_nodes ${connection_pair[0]} ${connection_pair[1]}) + done + sleep 5 } #Checks if topology is correctly connected function check_connection { - local array=("$@") - check_connection_done=0 - for i in ${!array[@]}; - do - local connection_pair=(${array[$i]}) - check=$(nav_cli ${connection_pair[0]} getpeerinfo | grep "\"addr\": \"127.0.0.1:$( bc <<< "10000+${connection_pair[1]}" )\"") - if [ -z "$check" ]; - then - echo "Node ${connection_pair[0]} failed to connect to node ${connection_pair[1]}" - echo " " - echo "Trying to reconnect to all nodes...please wait" - sleep 5 - connect_network "${array[@]}" - break - fi - done - if [ "$check_connection_done" == 0 ]; - then - echo "All nodes are connected!" - check_connection_done=1 - fi + local array=("$@") + check_connection_done=0 + for i in ${!array[@]}; + do + local connection_pair=(${array[$i]}) + check=$(nav_cli ${connection_pair[0]} getpeerinfo | grep "\"addr\": \"127.0.0.1:$( bc <<< "10000+${connection_pair[1]}" )\"") + if [ -z "$check" ]; + then + echo "Node ${connection_pair[0]} failed to connect to node ${connection_pair[1]}" + echo " " + echo "Trying to reconnect to all nodes...please wait" + sleep 5 + connect_network "${array[@]}" + break + fi + done + if [ "$check_connection_done" == 0 ]; + then + echo "All nodes are connected!" + check_connection_done=1 + fi } function create_random_network_topology { - unset array_topology_node_pairs - local local_array_create_random_network_topology=("$@") - if [ "${#local_array_create_random_network_topology[@]}" -eq 1 ]; - then - return - fi - array_network_connection_pool=() - for j in $(seq 0 1 $( bc <<< "${#local_array_create_random_network_topology[@]}-2" )); - do - for k in $(seq $( bc <<< "$j+1" ) 1 $( bc <<< "${#local_array_create_random_network_topology[@]}-1" )); - do - array_network_connection_pool+=("${local_array_create_random_network_topology[$j]} ${local_array_create_random_network_topology[$k]}") - done - done - if [ "${#local_array_create_random_network_topology[@]}" -lt 100 ]; - then - network_density_upper_bound=$( echo $(echo "e(1.4*l(${#local_array_create_random_network_topology[@]}-1))" | bc -l)/1 | bc ) - else - network_density_upper_bound=$( echo "${#local_array_create_random_network_topology[@]}*8" | bc ) - fi - #network_denstiy is used to create a somewhat loosely connect network topology - network_density_lower_bound=$( echo "${#local_array_create_random_network_topology[@]} - 1" | bc ) - network_density=$( shuf -i $network_density_lower_bound-$network_density_upper_bound -n 1 ) - array_topology_index=($(shuf -i 0-$( bc <<< "${#array_network_connection_pool[@]} - 1") -n $network_density)) - for i in $(seq 0 1 $( bc <<< "$network_density-1" )); - do - array_topology_node_pairs[$i]=${array_network_connection_pool[${array_topology_index[$i]}]} - done - - check_network_connected array_topology_node_pairs - - while [ "${#array_connected_nodes[@]}" -lt "${#local_array_create_random_network_topology[@]}" ]; + unset array_topology_node_pairs + local local_array_create_random_network_topology=("$@") + if [ "${#local_array_create_random_network_topology[@]}" -eq 1 ]; + then + return + fi + array_network_connection_pool=() + for j in $(seq 0 1 $( bc <<< "${#local_array_create_random_network_topology[@]}-2" )); + do + for k in $(seq $( bc <<< "$j+1" ) 1 $( bc <<< "${#local_array_create_random_network_topology[@]}-1" )); do - create_random_network_topology "${local_array_create_random_network_topology[@]}" + array_network_connection_pool+=("${local_array_create_random_network_topology[$j]} ${local_array_create_random_network_topology[$k]}") done + done + if [ "${#local_array_create_random_network_topology[@]}" -lt 100 ]; + then + network_density_upper_bound=$( echo $(echo "e(1.4*l(${#local_array_create_random_network_topology[@]}-1))" | bc -l)/1 | bc ) + else + network_density_upper_bound=$( echo "${#local_array_create_random_network_topology[@]}*8" | bc ) + fi + #network_denstiy is used to create a somewhat loosely connect network topology + network_density_lower_bound=$( echo "${#local_array_create_random_network_topology[@]} - 1" | bc ) + network_density=$( shuf -i $network_density_lower_bound-$network_density_upper_bound -n 1 ) + array_topology_index=($(shuf -i 0-$( bc <<< "${#array_network_connection_pool[@]} - 1") -n $network_density)) + for i in $(seq 0 1 $( bc <<< "$network_density-1" )); + do + array_topology_node_pairs[$i]=${array_network_connection_pool[${array_topology_index[$i]}]} + done + + check_network_connected array_topology_node_pairs + + while [ "${#array_connected_nodes[@]}" -lt "${#local_array_create_random_network_topology[@]}" ]; + do + create_random_network_topology "${local_array_create_random_network_topology[@]}" + done } function check_network_connected { - unset array_to_be_checked_connected - copy_array $1 array_to_be_checked_connected - connection_progression_old=0 - connection_progression_new=2 - unset array_connected_nodes - for i in ${array_to_be_checked_connected[@]}; - do - if [ -n $i ]; - then - array_connected_nodes=($i) - break - fi - done - while [ "$connection_progression_old" != "$connection_progression_new" ]; - do - connection_progression_old=$connection_progression_new - for i in ${!array_to_be_checked_connected[@]}; - do - array_connection=(${array_to_be_checked_connected[$i]}) - for j in ${!array_connected_nodes[@]}; - do - within_network=0 - if [ "${array_connection[0]}" == "${array_connected_nodes[$j]}" ]; - then - for k in $(seq 0 1 $( bc <<< " ${#array_connected_nodes[@]}-1" )); - do - if [ "${array_connection[1]}" == "${array_connected_nodes[$k]}" ]; - then - within_network=1 - fi - done - if [ "$within_network" == 0 ]; - then - array_connected_nodes+=("${array_connection[1]}") - array_to_be_checked_connected[$i]="" - ((connection_progression_new++)) - fi - elif [ "${array_connection[1]}" == "${array_connected_nodes[$j]}" ]; - then - for k in $(seq 0 1 $( bc <<< " ${#array_connected_nodes[@]}-1" )); - do - if [ "${array_connection[0]}" == "${array_connected_nodes[$k]}" ]; - then - within_network=1 - fi - done - if [ "$within_network" == 0 ]; - then - array_connected_nodes+=("${array_connection[0]}") - array_to_be_checked_connected[$i]="" - ((connection_progression_new++)) - fi - fi - done - done - done + unset array_to_be_checked_connected + copy_array $1 array_to_be_checked_connected + connection_progression_old=0 + connection_progression_new=2 + unset array_connected_nodes + for i in ${array_to_be_checked_connected[@]}; + do + if [ -n $i ]; + then + array_connected_nodes=($i) + break + fi + done + while [ "$connection_progression_old" != "$connection_progression_new" ]; + do + connection_progression_old=$connection_progression_new + for i in ${!array_to_be_checked_connected[@]}; + do + array_connection=(${array_to_be_checked_connected[$i]}) + for j in ${!array_connected_nodes[@]}; + do + within_network=0 + if [ "${array_connection[0]}" == "${array_connected_nodes[$j]}" ]; + then + for k in $(seq 0 1 $( bc <<< " ${#array_connected_nodes[@]}-1" )); + do + if [ "${array_connection[1]}" == "${array_connected_nodes[$k]}" ]; + then + within_network=1 + fi + done + if [ "$within_network" == 0 ]; + then + array_connected_nodes+=("${array_connection[1]}") + array_to_be_checked_connected[$i]="" + ((connection_progression_new++)) + fi + elif [ "${array_connection[1]}" == "${array_connected_nodes[$j]}" ]; + then + for k in $(seq 0 1 $( bc <<< " ${#array_connected_nodes[@]}-1" )); + do + if [ "${array_connection[0]}" == "${array_connected_nodes[$k]}" ]; + then + within_network=1 + fi + done + if [ "$within_network" == 0 ]; + then + array_connected_nodes+=("${array_connection[0]}") + array_to_be_checked_connected[$i]="" + ((connection_progression_new++)) + fi + fi + done + done + done } function stop_selected_nodes { - if [ "$attempts" == 10 ]; - then - echo Cannot find suitable nodes to stop - copy_array array_topology_node_pairs_backcup array_topology_node_pairs - copy_array array_topology_node_pairs_stopped_backup array_topology_node_pairs_stopped - return - fi - echo "Stopping nodes ${array_nodes_to_stop[@]}" - for i in ${array_nodes_to_stop[@]}; - do - stop_node $i - done - - sleep 5 - for i in ${array_nodes_to_stop[@]}; - do - unset array_active_nodes[$i] - if [ -n ${array_stressing_nodes[$i]} ]; - then - array_stopped_stressing_nodes[$i]=${array_stressing_nodes[$i]} - unset array_stressing_nodes[$i] - fi - array_stopped_nodes[$i]=$i - done -# echo Currently active nodes are: ${array_active_nodes[@]} inactive ones are: ${array_stopped_nodes[@]} -# echo array topology node pairs is ${array_topology_node_pairs[@]} -# echo array topology node pairs stopped is ${array_topology_node_pairs_stopped[@]} with size of ${#array_topology_node_pairs_stopped[@]} + if [ "$attempts" == 10 ]; + then + echo Cannot find suitable nodes to stop + copy_array array_topology_node_pairs_backcup array_topology_node_pairs + copy_array array_topology_node_pairs_stopped_backup array_topology_node_pairs_stopped + return + fi + echo "Stopping nodes ${array_nodes_to_stop[@]}" + for i in ${array_nodes_to_stop[@]}; + do + stop_node $i + done + + sleep 5 + for i in ${array_nodes_to_stop[@]}; + do + unset array_active_nodes[$i] + if [ -n ${array_stressing_nodes[$i]} ]; + then + array_stopped_stressing_nodes[$i]=${array_stressing_nodes[$i]} + unset array_stressing_nodes[$i] + fi + array_stopped_nodes[$i]=$i + done + # echo Currently active nodes are: ${array_active_nodes[@]} inactive ones are: ${array_stopped_nodes[@]} + # echo array topology node pairs is ${array_topology_node_pairs[@]} + # echo array topology node pairs stopped is ${array_topology_node_pairs_stopped[@]} with size of ${#array_topology_node_pairs_stopped[@]} } function select_random_nodes_to_stop { - attempts=0 - copy_array array_topology_node_pairs array_topology_node_pairs_backcup - copy_array array_topology_node_pairs_stopped array_topology_node_pairs_stopped_backup - echo "Trying to find nodes to stop while avoiding network splitting..." - unset array_connected_nodes - while [ "${#array_connected_nodes[@]}" -lt "$( bc <<< "$node_count-$1" )" ] && [ "$attempts" -lt 10 ]; + attempts=0 + copy_array array_topology_node_pairs array_topology_node_pairs_backcup + copy_array array_topology_node_pairs_stopped array_topology_node_pairs_stopped_backup + echo "Trying to find nodes to stop while avoiding network splitting..." + unset array_connected_nodes + while [ "${#array_connected_nodes[@]}" -lt "$( bc <<< "$node_count-$1" )" ] && [ "$attempts" -lt 10 ]; + do + unset array_topology_node_pairs + copy_array array_topology_node_pairs_backcup array_topology_node_pairs + copy_array array_topology_node_pairs_stopped_backup array_topology_node_pairs_stopped + ((attempts++)) + shuffle_array "${array_active_nodes[@]}" + unset array_nodes_to_stop + for i in $(seq 0 1 $( bc <<< "$1 - 1" )); do - unset array_topology_node_pairs - copy_array array_topology_node_pairs_backcup array_topology_node_pairs - copy_array array_topology_node_pairs_stopped_backup array_topology_node_pairs_stopped - ((attempts++)) - shuffle_array "${array_active_nodes[@]}" - unset array_nodes_to_stop - for i in $(seq 0 1 $( bc <<< "$1 - 1" )); - do - array_nodes_to_stop[${shuffled_array[$i]}]=${shuffled_array[$i]} - done - check_stopping_nodes_cause_network_split "${array_nodes_to_stop[@]}" + array_nodes_to_stop[${shuffled_array[$i]}]=${shuffled_array[$i]} done + check_stopping_nodes_cause_network_split "${array_nodes_to_stop[@]}" + done } function check_stopping_nodes_cause_network_split { - local local_array=("$@") - for i in ${!array_topology_node_pairs[@]}; - do - local node_pair=(${array_topology_node_pairs[$i]}) - for j in ${local_array[@]} - do - if [ "${node_pair[0]}" == "$j" ] || [ "${node_pair[1]}" == "$j" ]; - then - array_topology_node_pairs_stopped[$i]=${array_topology_node_pairs[$i]} - unset array_topology_node_pairs[$i] - node_pair=() - fi - done - done - check_network_connected array_topology_node_pairs + local local_array=("$@") + for i in ${!array_topology_node_pairs[@]}; + do + local node_pair=(${array_topology_node_pairs[$i]}) + for j in ${local_array[@]} + do + if [ "${node_pair[0]}" == "$j" ] || [ "${node_pair[1]}" == "$j" ]; + then + array_topology_node_pairs_stopped[$i]=${array_topology_node_pairs[$i]} + unset array_topology_node_pairs[$i] + node_pair=() + fi + done + done + check_network_connected array_topology_node_pairs } function start_random_stopped_nodes { - local local_array=() - if [ ${#array_stopped_nodes[@]} == 0 ]; - then - echo "All nodes are already active." - else - for i in ${!array_stopped_nodes[@]}; - do - dice=$( bc <<< "$RANDOM % 2" ) - if [ "$dice" -eq 1 ]; - then - local_array[$i]=$i - start_stopped_node $i - else - echo skipping starting node $i - fi - done - echo Waiting 30 seconds for navcoind... - sleep 30 - for j in ${!local_array[@]}; - do - connect_node_to_network $j - echo "Nodes $j balance: $(nav_cli $j getbalance) tNAV" - done - fi - echo Currently active nodes are: ${array_active_nodes[@]} inactive ones are: ${array_stopped_nodes[@]} + local local_array=() + if [ ${#array_stopped_nodes[@]} == 0 ]; + then + echo "All nodes are already active." + else + for i in ${!array_stopped_nodes[@]}; + do + dice=$( bc <<< "$RANDOM % 2" ) + if [ "$dice" -eq 1 ]; + then + local_array[$i]=$i + start_stopped_node $i + else + echo skipping starting node $i + fi + done + echo Waiting 30 seconds for navcoind... + sleep 30 + for j in ${!local_array[@]}; + do + connect_node_to_network $j + echo "Nodes $j balance: $(nav_cli $j getbalance) tNAV" + done + fi + echo Currently active nodes are: ${array_active_nodes[@]} inactive ones are: ${array_stopped_nodes[@]} } function start_stopped_node { - echo Starting node $1... - start_node $1 - unset array_stopped_nodes[$1] - array_active_nodes[$1]=$1 - if [ -n ${array_stopped_stressing_nodes[$1]} ]; - then - array_stressing_nodes[$1]=${array_stopped_stressing_nodes[$1]} - unset array_stopped_stressing_nodes[$1] - fi + echo Starting node $1... + start_node $1 + unset array_stopped_nodes[$1] + array_active_nodes[$1]=$1 + if [ -n ${array_stopped_stressing_nodes[$1]} ]; + then + array_stressing_nodes[$1]=${array_stopped_stressing_nodes[$1]} + unset array_stopped_stressing_nodes[$1] + fi } function connect_node_to_network { - echo Connecting node $1 to the network... - for i in ${!array_topology_node_pairs_stopped[@]}; - do - local node_connection=(${array_topology_node_pairs_stopped[$i]}) - if [ "$1" == "${node_connection[0]}" ] || [ "$1" == "${node_connection[1]}" ]; - then - local match=0 - for k in ${array_stopped_nodes[@]}; - do - if [ "$k" == "${node_connection[0]}" ] || [ "$k" == "${node_connection[1]}" ]; - then - match=1 - fi - done - if [ "$match" == 0 ] && [ -z ${array_topology_node_pairs[$i]} ]; - then - array_topology_node_pairs[$i]=${array_topology_node_pairs_stopped[$i]} - unset array_topology_node_pairs_stopped[$i] - fi - fi - done - connect_network "${array_topology_node_pairs[@]}" + echo Connecting node $1 to the network... + for i in ${!array_topology_node_pairs_stopped[@]}; + do + local node_connection=(${array_topology_node_pairs_stopped[$i]}) + if [ "$1" == "${node_connection[0]}" ] || [ "$1" == "${node_connection[1]}" ]; + then + local match=0 + for k in ${array_stopped_nodes[@]}; + do + if [ "$k" == "${node_connection[0]}" ] || [ "$k" == "${node_connection[1]}" ]; + then + match=1 + fi + done + if [ "$match" == 0 ] && [ -z ${array_topology_node_pairs[$i]} ]; + then + array_topology_node_pairs[$i]=${array_topology_node_pairs_stopped[$i]} + unset array_topology_node_pairs_stopped[$i] + fi + fi + done + connect_network "${array_topology_node_pairs[@]}" } function wait_until_sync { - sleep 5 - local local_array=("$@") - local local_array_best_hash=() - wait_until_sync_done=0 - for i in ${local_array[@]}; - do - local_array_best_hash[$i]=$(nav_cli $i getbestblockhash) -# echo best block hash of node $i: -# echo "$(nav_cli $i getbestblockhash)" - done - if [ $(printf "%s\n" "${local_array_best_hash[@]}" | LC_CTYPE=C sort -z -u | uniq | grep -n -c .) -gt 1 ]; - then - echo best block hash mismatch!!! -# echo array topoloy node pairs is "${array_topology_node_pairs[@]}" -# echo array topology node pairs stopped is "${array_topology_node_pairs_stopped[@]}" - sleep 1 - shuffle_array "${local_array[@]}" - node=${shuffled_array[0]} - $(nav_cli $node "generate 1") - echo now on blcok $(nav_cli $node "getblockcount") - if [ "$network_split_started" == 1 ]; - then - for wusi in $(seq 0 1 $( bc <<< "$network_count-1" )); - do - echo Syncing network $wusi... - eval "connect_network \"\${array_topology_node_pairs_network$nc[@]}\"" - done - else - connect_network "${array_topology_node_pairs[@]}" - fi - sleep 2 - wait_until_sync "${local_array[@]}" - fi - if [ "$wait_until_sync_done" == 0 ]; - then - echo Best block hashes matched! - wait_until_sync_done=1 - fi + sleep 5 + local local_array=("$@") + local local_array_best_hash=() + wait_until_sync_done=0 + for i in ${local_array[@]}; + do + local_array_best_hash[$i]=$(nav_cli $i getbestblockhash) + echo best block hash of node $i: + echo "$(nav_cli $i getbestblockhash)" + done + if [ $(printf "%s\n" "${local_array_best_hash[@]}" | LC_CTYPE=C sort -z -u | uniq | grep -n -c .) -gt 1 ]; + then + echo best block hash mismatch!!! + echo array topoloy node pairs is "${array_topology_node_pairs[@]}" + echo array topology node pairs stopped is "${array_topology_node_pairs_stopped[@]}" + sleep 1 + shuffle_array "${local_array[@]}" + node=${shuffled_array[0]} + $(nav_cli $node "generate 1") + echo now on block $(nav_cli $node "getblockcount") + if [ "$network_split_started" == 1 ]; + then + for wusi in $(seq 0 1 $( bc <<< "$network_count-1" )); + do + echo Syncing network $wusi... + eval "connect_network \"\${array_topology_node_pairs_network$nc[@]}\"" + done + else + connect_network "${array_topology_node_pairs[@]}" + fi + sleep 2 + wait_until_sync "${local_array[@]}" + fi + if [ "$wait_until_sync_done" == 0 ]; + then + echo Best block hashes matched! + wait_until_sync_done=1 + fi } function random_transactions { - dice=$(bc <<< "$RANDOM % 100") - if [ $dice -lt 75 ]; + dice=$(bc <<< "$RANDOM % 100") + if [ $dice -lt 75 ]; + then + transaction_amount=$( bc <<< "$RANDOM%1000" ) + shuffle_array "${array_stressing_nodes[@]}" + node_send=${shuffled_array[0]} + node_receive=${shuffled_array[1]} + if [ $dice -lt 30 ]; then - transaction_amount=$( bc <<< "$RANDOM%1000" ) - shuffle_array "${array_stressing_nodes[@]}" - node_send=${shuffled_array[0]} - node_receive=${shuffled_array[1]} - if [ $dice -lt 30 ]; - then - out=$(nav_cli ${array_stressing_nodes[$node_send]} sendtoaddress ${array_address[$node_receive]} $transaction_amount) - else - out=$(nav_cli ${array_stressing_nodes[$node_send]} privatesendtoaddress ${array_address[$node_receive]} $transaction_amount) - fi - fi + out=$(nav_cli ${array_stressing_nodes[$node_send]} sendtoaddress ${array_address[$node_receive]} $transaction_amount) + else + out=$(nav_cli ${array_stressing_nodes[$node_send]} privatesendtoaddress ${array_address[$node_receive]} $transaction_amount) + fi + fi } function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; } function dice_create_token { - dice=$(bc <<< "$RANDOM % 100") - if [ $dice -lt 20 ]; - then - shuffle_array "${array_stressing_nodes[@]}" - supply=$(openssl rand 4 | od -DAn) - node=${shuffled_array[0]} - random_name=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 10) - random_symbol=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 3) - out=$(nav_cli $node createtoken $random_name $random_symbol $supply) - if [ ! -z $out ] - then - echo 'create token success!' - fi - fi + dice=$(bc <<< "$RANDOM % 100") + if [ $dice -lt 20 ]; + then + shuffle_array "${array_stressing_nodes[@]}" + supply=$(openssl rand 4 | od -DAn) + node=${shuffled_array[0]} + random_name=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 10) + random_symbol=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 3) + out=$(nav_cli $node createtoken $random_name $random_symbol $supply) + if [ ! -z $out ] + then + echo 'create token success!' + fi + fi } function dice_mint_token { - dice=$(bc <<< "$RANDOM % 100") - if [ $dice -lt 70 ]; - then - shuffle_array "${array_stressing_nodes[@]}" - node=${shuffled_array[0]} - node_receive=${shuffled_array[1]} - tokens=($(nav_cli $node listtokens | jq '.[] | select(.version==0) | .id' | tr "\n" " " | tr -d '"')) - for t in ${tokens[@]} - do - amount=$(openssl rand 4 | od -DAn) - out=$(nav_cli $node minttoken $t ${array_private_address[$node_receive]} $amount) - if [ ! -z $out ] - then - echo 'mint token success!' - fi - done - fi + dice=$(bc <<< "$RANDOM % 100") + if [ $dice -lt 70 ]; + then + shuffle_array "${array_stressing_nodes[@]}" + node=${shuffled_array[0]} + node_receive=${shuffled_array[1]} + tokens=($(nav_cli $node listtokens | jq '.[] | select(.version==0) | .id' | tr "\n" " " | tr -d '"')) + echo $tokens + for t in ${tokens[@]} + do + amount=$(openssl rand 4 | od -DAn) + out=$(nav_cli $node minttoken $t ${array_private_address[$node_receive]} $amount) + if [ ! -z $out ] + then + echo 'mint token success!' + fi + done + fi } function dice_send_token { - dice=$(bc <<< "$RANDOM % 100") - if [ $dice -lt 80 ]; - then - tokens=($(nav_cli $node listtokens | jq '.[] | select(.version==0) | .id' | tr "\n" " " | tr -d '"')) - for n in ${array_stressing_nodes[@]} - do - for t in ${tokens[@]} - do - shuffle_array "${array_stressing_nodes[@]}" - node_receive=${shuffled_array[0]} - amount=$(openssl rand 4 | od -DAn) - out=$(nav_cli $n sendtoken $t ${array_private_address[$node_receive]} $amount) - if [ ! -z $out ] - then - echo 'send token success!' - fi - done - done - fi + dice=$(bc <<< "$RANDOM % 100") + if [ $dice -lt 80 ]; + then + tokens=($(nav_cli $node listtokens | jq '.[] | select(.version==0) | .id' | tr "\n" " " | tr -d '"')) + echo $tokens + for n in ${array_stressing_nodes[@]} + do + for t in ${tokens[@]} + do + shuffle_array "${array_stressing_nodes[@]}" + node_receive=${shuffled_array[0]} + amount=$(openssl rand 4 | od -DAn) + out=$(nav_cli $n sendtoken $t ${array_private_address[$node_receive]} $amount) + if [ ! -z $out ] + then + echo 'send token success!' + fi + done + done + fi } function dice_burn_token { - dice=$(bc <<< "$RANDOM % 100") - if [ $dice -lt 50 ]; - then - tokens=($(nav_cli $node listtokens | jq '.[] | select(.version==0) | .id' | tr "\n" " " | tr -d '"')) - for n in ${array_stressing_nodes[@]} - do - for t in ${tokens[@]} - do - amount=$(openssl rand 4 | od -DAn) - out=$(nav_cli $n burntoken $t $amount) - if [ ! -z $out ] - then - echo 'burn token success!' - fi - done - done - fi + dice=$(bc <<< "$RANDOM % 100") + if [ $dice -lt 50 ]; + then + tokens=($(nav_cli $node listtokens | jq '.[] | select(.version==0) | .id' | tr "\n" " " | tr -d '"')) + echo $tokens + for n in ${array_stressing_nodes[@]} + do + for t in ${tokens[@]} + do + amount=$(openssl rand 4 | od -DAn) + out=$(nav_cli $n burntoken $t $amount) + if [ ! -z $out ] + then + echo 'burn token success!' + fi + done + done + fi } function dice_create_nft { - dice=$(bc <<< "$RANDOM % 100") - if [ $dice -lt 20 ]; - then - shuffle_array "${array_stressing_nodes[@]}" - supply=$RANDOM - node=${shuffled_array[0]} - random_name=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 10) - random_scheme=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 100) - out=$(nav_cli $node createnft $random_name $random_scheme $supply) - if [ ! -z $out ] - then - echo 'create nft success!' - fi - fi + dice=$(bc <<< "$RANDOM % 100") + if [ $dice -lt 20 ]; + then + shuffle_array "${array_stressing_nodes[@]}" + supply=$RANDOM + node=${shuffled_array[0]} + random_name=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 10) + random_scheme=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 100) + out=$(nav_cli $node createnft $random_name $random_scheme $supply) + if [ ! -z $out ] + then + echo 'create nft success!' + fi + fi } function dice_mint_nft { - dice=$(bc <<< "$RANDOM % 100") - if [ $dice -lt 70 ]; - then - shuffle_array "${array_stressing_nodes[@]}" - node=${shuffled_array[0]} - node_receive=${shuffled_array[1]} - nfts=($(nav_cli $node listnfts | jq '.[] | select(.version==1) | .id' | tr "\n" " " | tr -d '"')) - random_scheme=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 100) - for n in ${nfts[@]} - do - nft_id=$(nav_cli $node listnfts | jq ".[] | select(.id==\"$n\") | .current_supply" | tr -d '"') -# echo 'nft_id = ' $nft_id - out=$(nav_cli $node mintnft $n $nft_id ${array_private_address[$node_receive]} $random_scheme) - if [ ! -z $out ] - then - echo 'mint nft success!' - fi - done - fi + dice=$(bc <<< "$RANDOM % 100") + if [ $dice -lt 70 ]; + then + shuffle_array "${array_stressing_nodes[@]}" + node=${shuffled_array[0]} + node_receive=${shuffled_array[1]} + nfts=($(nav_cli $node listnfts | jq '.[] | select(.version==1) | .id' | tr "\n" " " | tr -d '"')) + echo $nfts + random_scheme=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 100) + for n in ${nfts[@]} + do + nft_id=$(nav_cli $node listnfts | jq ".[] | select(.id==\"$n\") | .current_supply" | tr -d '"') + # echo 'nft_id = ' $nft_id + out=$(nav_cli $node mintnft $n $nft_id ${array_private_address[$node_receive]} $random_scheme) + if [ ! -z $out ] + then + echo 'mint nft success!' + fi + done + fi } function dice_send_nft { - dice=$(bc <<< "$RANDOM % 100") - if [ $dice -lt 90 ]; - then - nfts=($(nav_cli $node listnfts | jq '.[] | select(.version==1) | .id' | tr "\n" " " | tr -d '"')) - for n in ${array_stressing_nodes[@]} - do - for t in ${nfts[@]} - do - shuffle_array "${array_stressing_nodes[@]}" - node_receive=${shuffled_array[0]} - nftid=$(nav_cli $node listnfts | jq ".[] | select(.id==\"$t\") | .nfts | .[] | select(.balance==\"1\") | .index" | shuf -n 1) -# echo 'nftid= ' $nftid - out=$(nav_cli $n sendnft $t $nftid ${array_private_address[$node_receive]}) - if [ ! -z $out ] - then - echo 'send nft success!' - fi - done - done - fi - + dice=$(bc <<< "$RANDOM % 100") + if [ $dice -lt 90 ]; + then + nfts=($(nav_cli $node listnfts | jq '.[] | select(.version==1) | .id' | tr "\n" " " | tr -d '"')) + echo $nfts + for n in ${array_stressing_nodes[@]} + do + for t in ${nfts[@]} + do + shuffle_array "${array_stressing_nodes[@]}" + node_receive=${shuffled_array[0]} + nftid=$(nav_cli $node listnfts | jq ".[] | select(.id==\"$t\") | .nfts | .[] | select(.balance==\"1\") | .index" | shuf -n 1) + #echo 'nftid= ' $nftid + out=$(nav_cli $n sendnft $t $nftid ${array_private_address[$node_receive]}) + if [ ! -z $out ] + then + echo 'send nft success!' + fi + done + done + fi } function check_token_hash { - sleep 1 - local local_array=("$@") - local local_array_tokenhash=() - for i in ${local_array[@]}; - do - local_array_tokenhash[$i]=$(nav_cli $i "listtokens" | jq -c '[.[]|del(.balance)|del(.nfts)]'|shasum|awk '{print $1}') - done -# echo 'token hashes = ' ${local_array_tokenhash[@]} - if [ $(printf "%s\n" "${local_array_tokenhash[@]}" | LC_CTYPE=C sort -z -u | uniq | grep -n -c .) -gt 1 ]; + check_token_hash_token + check_token_hash_nft +} + +function check_token_hash_token { + sleep 1 + local local_array=("$@") + local local_array_tokenhash=() + for i in ${local_array[@]}; + do + local_array_tokenhash[$i]=$(nav_cli $i "listtokens" | jq -c '[.[]|del(.balance)|del(.nfts)|del(.is_mine)]'|shasum|awk '{print $1}') + done + echo 'token hashes = ' ${local_array_tokenhash[@]} + if [ $(printf "%s\n" "${local_array_tokenhash[@]}" | LC_CTYPE=C sort -z -u | uniq | grep -n -c .) -gt 1 ]; + then + if [ "$bool_assert_state_mismatch" != 1 ]; then - if [ "$bool_assert_state_mismatch" != 1 ]; - then - echo TOKEN HASH MISMATCH! Syncing again to make sure best block hashes match. - bool_assert_state_mismatch=1 - wait_until_sync "${local_array[@]}" - check_token_hash "${local_array[@]}" - else - echo TOKEN HASH MISMATCH! - for i in ${!local_array_tokenhash[@]}; - do - echo the hashes of nodes $i are ${local_array_tokenhash[$i]} - done - terminate 1 - fi + echo TOKEN HASH MISMATCH! Syncing again to make sure best block hashes match. + bool_assert_state_mismatch=1 + wait_until_sync "${local_array[@]}" + check_token_hash_token "${local_array[@]}" + else + echo TOKEN HASH MISMATCH! + for i in ${!local_array_tokenhash[@]}; + do + echo the hashes of node $i are ${local_array_tokenhash[$i]} + done + terminate 1 fi - echo Token hash check OK! - bool_assert_state_mismatch=0 + fi + echo Token hash check OK! + bool_assert_state_mismatch=0 } +function check_token_hash_nft { + sleep 1 + local local_array=("$@") + local local_array_tokenhash=() + for i in ${local_array[@]}; + do + local_array_tokenhash[$i]=$(nav_cli $i "listnfts" | jq -c '[.[]|del(.balance)|del(.nfts)|del(.is_mine)]'|shasum|awk '{print $1}') + done + echo 'nft hashes = ' ${local_array_tokenhash[@]} + if [ $(printf "%s\n" "${local_array_tokenhash[@]}" | LC_CTYPE=C sort -z -u | uniq | grep -n -c .) -gt 1 ]; + then + if [ "$bool_assert_state_mismatch" != 1 ]; + then + echo NFT HASH MISMATCH! Syncing again to make sure best block hashes match. + bool_assert_state_mismatch=1 + wait_until_sync "${local_array[@]}" + check_token_hash_nft "${local_array[@]}" + else + echo NFT HASH MISMATCH! + for i in ${!local_array_tokenhash[@]}; + do + echo the hashes of node $i are ${local_array_tokenhash[$i]} + done + terminate 1 + fi + fi + echo NFT hash check OK! + bool_assert_state_mismatch=0 +} function check_consensus_parameters { - consensusparameter_tmp=($(nav_cli $1 getconsensusparameters | tr -d "[],\n")) - if [ "${#consensusparameter_tmp[@]}" -gt 10 ]; - then - copy_array consensusparameter_tmp consensusparameter_new - fi - for i in $(seq 0 1 $( bc <<< "${#consensusparameter_new[@]}-1" )); - do - if [ "${consensusparameter_new[$i]}" != "${consensusparameter_old[$i]}" ]; - then - echo Consensus Parameter ${consensus_parameter_name[$i]} changed from ${consensusparameter_old[$i]} to ${consensusparameter_new[$i]}!!! - fi - done - consensusparameter_old=("${consensusparameter_new[@]}") + consensusparameter_tmp=($(nav_cli $1 getconsensusparameters | tr -d "[],\n")) + if [ "${#consensusparameter_tmp[@]}" -gt 10 ]; + then + copy_array consensusparameter_tmp consensusparameter_new + fi + for i in $(seq 0 1 $( bc <<< "${#consensusparameter_new[@]}-1" )); + do + if [ "${consensusparameter_new[$i]}" != "${consensusparameter_old[$i]}" ]; + then + echo Consensus Parameter ${consensus_parameter_name[$i]} changed from ${consensusparameter_old[$i]} to ${consensusparameter_new[$i]}!!! + fi + done + consensusparameter_old=("${consensusparameter_new[@]}") } function stress { - for i in ${array_stressing_nodes[@]}; - do - out=$(nav_cli $i "staking true") - done - time=$(bc <<< $(date +%s)+$1) - while [ $time -gt $(date +%s) ] - do - dice_create_token - dice_mint_token - dice_send_token - dice_burn_token - dice_create_nft - dice_mint_nft - dice_send_nft - if [ "$bool_random_tx" == 1 ]; - then - random_transactions - fi - check_cycle - sleep $stress_sleep_time - done + for i in ${array_stressing_nodes[@]}; + do + out=$(nav_cli $i "staking true") + done + time=$(bc <<< $(date +%s)+$1) + while [ $time -gt $(date +%s) ] + do + dice_create_token + dice_mint_token + dice_send_token + dice_burn_token + dice_create_nft + dice_mint_nft + dice_send_nft + if [ "$bool_random_tx" == 1 ]; + then + random_transactions + fi + check_cycle + sleep $stress_sleep_time + done } function check_node { - blocks=`nav_cli $2 getinfo|jq .blocks` - block_increment=${#array_verifychain_nodes[@]} - for i in $(seq $1 $block_increment $blocks); - do - verifyoutput=`nav_cli $2 verifychain 4 $i` - if [[ "$verifyoutput" == "false" ]]; - then - verifyoutput+=`echo ' - ' && echo failed at $(grep 'ERROR: VerifyDB()' ${array_data[$2]}/devnet/debug.log |tail -1|sed 's/.*block at \(\d*\)/\1/')` - terminate 1 - fi - echo Node $2 - Rewinding to \ - $(bc <<< $blocks-$i) \ - - reconnecting up to $blocks \ - - verifychain 4 $i -\> $verifyoutput; - done - verifyoutput=`nav_cli $2 verifychain 4 0` - echo "Node $2 - Doing verifychain 4 0 -> $verifyoutput" - echo "node $2 finished" -} + blocks=`nav_cli $2 getinfo|jq .blocks` + block_increment=${#array_verifychain_nodes[@]} + for i in $(seq $1 $block_increment $blocks); + do + verifyoutput=`nav_cli $2 verifychain 4 $i` + if [[ "$verifyoutput" == "false" ]]; + then + verifyoutput+=`echo ' - ' && echo failed at $(grep 'ERROR: VerifyDB()' ${array_data[$2]}/devnet/debug.log |tail -1|sed 's/.*block at \(\d*\)/\1/')` + terminate 1 + fi + echo Node $2 - Rewinding to \ + $(bc <<< $blocks-$i) \ + - reconnecting up to $blocks \ + - verifychain 4 $i -\> $verifyoutput; + done + verifyoutput=`nav_cli $2 verifychain 4 0` + echo "Node $2 - Doing verifychain 4 0 -> $verifyoutput" + echo "node $2 finished" + } function check_cycle { - shuffle_array "${array_stressing_nodes[@]}" - node=${shuffled_array[0]} - blocks=$(nav_cli $node getinfo|jq .blocks) - if [ "$( bc <<< "$blocks - $last_cycle_end_block_height" )" -gt "$voting_cycle_length" ]; - then - last_cycle_end_block_height=$(echo "$last_cycle_end_block_height+$voting_cycle_length" | bc ) - voting_cycle_length=${consensusparameter_new[0]} - ((this_cycle++)) - fi + shuffle_array "${array_stressing_nodes[@]}" + node=${shuffled_array[0]} + blocks=$(nav_cli $node getinfo|jq .blocks) + if [ "$( bc <<< "$blocks - $last_cycle_end_block_height" )" -gt "$voting_cycle_length" ]; + then + last_cycle_end_block_height=$(echo "$last_cycle_end_block_height+$voting_cycle_length" | bc ) + voting_cycle_length=${consensusparameter_new[0]} + ((this_cycle++)) + fi } function random_verifychain_check { - echo "Performing random verifycahin check..." - - echo "Selecting random verifychain nodes..." - shuffle_array "${array_active_nodes[@]}" - if [ "${#array_active_nodes[@]}" -lt 7 ]; - then - for i in $(seq 0 1 $( bc <<< "${#array_active_nodes[@]} - 1" )); - do - array_verifychain_nodes[$i]=${shuffled_array[$i]} - done - else - for i in $(seq 0 1 7 ); - do - array_verifychain_nodes[$i]=${shuffled_array[$i]} - done - fi - echo '' - echo Running verifychain test with node ${array_verifychain_nodes[@]}... - echo '' - - starting_block=0 - for i in ${!array_verifychain_nodes[@]}; - do - ((starting_block++)) - check_node $starting_block ${array_verifychain_nodes[$i]} & - done - wait + echo "Performing random verifycahin check..." + + echo "Selecting random verifychain nodes..." + shuffle_array "${array_active_nodes[@]}" + if [ "${#array_active_nodes[@]}" -lt 7 ]; + then + for i in $(seq 0 1 $( bc <<< "${#array_active_nodes[@]} - 1" )); + do + array_verifychain_nodes[$i]=${shuffled_array[$i]} + done + else + for i in $(seq 0 1 7 ); + do + array_verifychain_nodes[$i]=${shuffled_array[$i]} + done + fi + echo '' + echo Running verifychain test with node ${array_verifychain_nodes[@]}... + echo '' + + starting_block=0 + for i in ${!array_verifychain_nodes[@]}; + do + ((starting_block++)) + check_node $starting_block ${array_verifychain_nodes[$i]} & + done + wait } function start_node { - $(echo $navpath)/navcoind -datadir=${array_data[$1]} -port=${array_p2p_port[$1]} -rpcport=${array_rpc_port[$1]} -devnet -daemon -nftindex=1 -debug=dao -debug=statehash -ntpminmeasures=0 -dandelion=0 -disablesafemode -staking=0 2> /dev/null -# gdb -batch -ex "run" -ex "bt" --args $(echo $navpath)/navcoind -datadir=${array_data[$1]} -port=${array_p2p_port[$1]} -rpcport=${array_rpc_port[$1]} -devnet -debug=dao -debug=statehash -ntpminmeasures=0 -dandelion=0 -disablesafemode -staking=0 > out.gdb & + $(echo $navpath)/navcoind -datadir=${array_data[$1]} -port=${array_p2p_port[$1]} -rpcport=${array_rpc_port[$1]} -devnet -daemon -nftindex=1 -debug=dao -debug=statehash -ntpminmeasures=-1 -dandelion=0 -disablesafemode -staking=0 2> /dev/null + # gdb -batch -ex "run" -ex "bt" --args $(echo $navpath)/navcoind -datadir=${array_data[$1]} -port=${array_p2p_port[$1]} -rpcport=${array_rpc_port[$1]} -devnet -debug=dao -debug=statehash -ntpminmeasures=-1 -dandelion=0 -disablesafemode -staking=0 > out.gdb & } function stop_node { - out=$(nav_cli $1 stop) + out=$(nav_cli $1 stop) } ##########################################################Script body @@ -833,7 +871,7 @@ initialize_network for i in $(seq 0 1 $( bc <<< "$node_count-1" )); do - initialize_node $i + initialize_node $i done echo '' @@ -844,53 +882,53 @@ sleep 30 if [ "$node_count" == 1 ]; then - array_stressing_nodes=0 - array_verifychain_nodes=0 - stressing_node_count=1 + array_stressing_nodes=0 + array_verifychain_nodes=0 + stressing_node_count=1 else - if [ -z $array_topology ]; - then - echo "Creating random network topology..." - create_random_network_topology "${array_active_nodes[@]}" - echo "Created topology that has ${#array_topology_node_pairs[@]} connections out of max connections ${#array_network_connection_pool[@]} in the network" - echo "Network topology: ${array_topology_node_pairs[@]}" - else - echo "Using speficyfied network topology ${array_topology_node_pairs[@]}" - fi - - - echo "running script with $stressing_node_count stressing nodes in a network of $node_count nodes" - - if [ -z $array_stressing_nodes ]; - then - echo "Selecting random stressing nodes..." - shuffle_array "${array_active_nodes[@]}" - for i in $(seq 0 1 $( bc <<< "$stressing_node_count-1" )); - do - array_stressing_nodes[${shuffled_array[$i]}]=${shuffled_array[$i]} - done - else - echo "Using specified stressing nodes" - fi - - echo "array_stressing_nodes = ${array_stressing_nodes[@]}" - - if [ -z $array_verifychain_nodes ]; - then - echo "Selecting random verifychain nodes..." - shuffle_array "${array_active_nodes[@]}" - for i in $(seq 0 1 7); - do - array_verifychain_nodes[$i]=${shuffled_array[$i]} - done - else - echo "Using specified verifychain nodes" - fi - - echo "array_verifychain_nodes = ${array_verifychain_nodes[@]}" - - - connect_network "${array_topology_node_pairs[@]}" + if [ -z $array_topology ]; + then + echo "Creating random network topology..." + create_random_network_topology "${array_active_nodes[@]}" + echo "Created topology that has ${#array_topology_node_pairs[@]} connections out of max connections ${#array_network_connection_pool[@]} in the network" + echo "Network topology: ${array_topology_node_pairs[@]}" + else + echo "Using speficyfied network topology ${array_topology_node_pairs[@]}" + fi + + + echo "running script with $stressing_node_count stressing nodes in a network of $node_count nodes" + + if [ -z $array_stressing_nodes ]; + then + echo "Selecting random stressing nodes..." + shuffle_array "${array_active_nodes[@]}" + for i in $(seq 0 1 $( bc <<< "$stressing_node_count-1" )); + do + array_stressing_nodes[${shuffled_array[$i]}]=${shuffled_array[$i]} + done + else + echo "Using specified stressing nodes" + fi + + echo "array_stressing_nodes = ${array_stressing_nodes[@]}" + + if [ -z $array_verifychain_nodes ]; + then + echo "Selecting random verifychain nodes..." + shuffle_array "${array_active_nodes[@]}" + for i in $(seq 0 1 7); + do + array_verifychain_nodes[$i]=${shuffled_array[$i]} + done + else + echo "Using specified verifychain nodes" + fi + + echo "array_verifychain_nodes = ${array_verifychain_nodes[@]}" + + + connect_network "${array_topology_node_pairs[@]}" fi out=$(nav_cli 0 "generate 10") @@ -899,20 +937,20 @@ out=$(nav_cli 0 "generate 10") array_address=() for n in ${!array_stressing_nodes[@]}; do - array_address[$n]=$(nav_cli ${array_stressing_nodes[$n]} getnewaddress) + array_address[$n]=$(nav_cli ${array_stressing_nodes[$n]} getnewaddress) done for i in {1..10}; do - for j in ${array_address[@]}; - do - out=$(nav_cli 0 "sendtoaddress $j 10000") - done - out=$(nav_cli 0 "generate 1") + for j in ${array_address[@]}; + do + out=$(nav_cli 0 "sendtoaddress $j 10000") + done + out=$(nav_cli 0 "generate 1") done sleep 1 for n in ${array_stressing_nodes[@]}; do - echo "Node $n balance: $(nav_cli $n getbalance) NAV" + echo "Node $n balance: $(nav_cli $n getbalance) NAV" done @@ -921,8 +959,8 @@ blocks=$(nav_cli 0 getblockcount) echo 'blocks=' $blocks while [ $blocks -lt 300 ]; do - out=$(nav_cli 0 "generate 10") - blocks=$(nav_cli 0 getblockcount) + out=$(nav_cli 0 "generate 10") + blocks=$(nav_cli 0 getblockcount) done echo 'Distributing xNAV to nodes...' @@ -930,20 +968,20 @@ echo 'Distributing xNAV to nodes...' array_private_address=() for n in ${!array_stressing_nodes[@]}; do - array_private_address[$n]=$(nav_cli ${array_stressing_nodes[$n]} getnewprivateaddress) + array_private_address[$n]=$(nav_cli ${array_stressing_nodes[$n]} getnewprivateaddress) done -for i in {1..10}; +for i in {1..$node_count}; do - for j in ${array_private_address[@]}; - do - out=$(nav_cli 0 "sendtoaddress $j 10000") - done - out=$(nav_cli 0 "generate 1") + for j in ${array_private_address[@]}; + do + out=$(nav_cli 0 "sendtoaddress $j 10000") + done + out=$(nav_cli 0 "generate 1") done sleep 30 for n in ${array_stressing_nodes[@]}; do - echo "Node $n balance: $(nav_cli $n getwalletinfo | jq '.private_balance') xNAV" + echo "Node $n balance: $(nav_cli $n getwalletinfo | jq '.private_balance') xNAV" done out=$(nav_cli 0 "generate 10") @@ -959,7 +997,7 @@ consensus_parameter_count=$(nav_cli 0 getconsensusparameters | jq length) echo 'consensus parameter count =' $consensus_parameter_count for i in $(seq 0 1 $( bc <<< "$consensus_parameter_count - 1" )); do - eval "consensus_parameter_name[\$i]=\$(nav_cli 0 \"getconsensusparameters true\" | jq -r '.[] | select(.id==$i) | .desc')" + eval "consensus_parameter_name[\$i]=\$(nav_cli 0 \"getconsensusparameters true\" | jq -r '.[] | select(.id==$i) | .desc')" done consensusparameter_old=($(nav_cli 0 getconsensusparameters | tr -d "[],\n")) consensusparameter_original=("${consensusparameter_old[@]}") @@ -976,241 +1014,239 @@ check_consensus_parameters $node node_count_to_stop=$(echo "sqrt($node_count)" | bc ) while [ $wait_until_cycle -gt $this_cycle ]; do + echo '' + echo '' + echo Stressing for $seconds_round seconds... + + stress $seconds_round + + echo Waiting until nodes are synced... + wait_until_sync "${array_active_nodes[@]}" - echo '' - echo '' - echo Stressing for $seconds_round seconds... - - stress $seconds_round - - echo Waiting until nodes are synced... - - wait_until_sync "${array_active_nodes[@]}" - - for i in ${array_stressing_nodes[@]}; - do - out=$(nav_cli $i "staking false") - echo "Node $i balance: $(nav_cli $i getwalletinfo | jq '.private_balance') xNAV" - done - - echo Checking token hashes match... - - check_token_hash "${array_active_nodes[@]}" - shuffle_array "${array_stressing_nodes[@]}" - node=${shuffled_array[0]} - check_consensus_parameters $node - - if [ "$node_count" == 1 ]; - then - out=$(nav_cli 0 "generate 5") - fi - - if [ "$bool_random_verifychain_check" == 1 ]; - then - dice=$( bc <<< "$RANDOM % 60" ) - if [ "$dice" == 1 ]; - then - random_verifychain_check - fi - fi - if [ "$bool_stopstart_nodes" == 1 ]; - then - dice=$( bc <<< "$RANDOM % 3" ) - node_count_to_stop_this_round=$( bc <<< "$RANDOM % $node_count_to_stop + 1" ) - if [ "${#array_active_nodes[@]}" -gt "$( bc <<< "$node_count_to_stop_this_round + 2" )" ]; - then - if [ "$dice" != 1 ]; - then - select_random_nodes_to_stop $node_count_to_stop_this_round - stop_selected_nodes - fi - fi - if [ "$dice" == 1 ]; - then - start_random_stopped_nodes - fi - fi - if [ "$bool_random_new_topology" == 1 ]; - then - dice=$( bc <<< "$RANDOM % 10" ) - if [ "$dice" == 1 ]; - then - - attempts=0 - copy_array array_topology_node_pairs array_topology_node_pairs_backcup - copy_array array_topology_node_pairs_stopped array_topology_node_pairs_stopped_backup - unset array_connected_nodes - echo "Trying to create a new network topology while avoiding network splitting..." - while [ "${#array_connected_nodes[@]}" -lt "${#array_active_nodes[@]}" ] && [ "$attempts" -lt 10 ]; - do - copy_array array_topology_node_pairs_backup array_topology_node_pairs - copy_array array_topology_node_pairs_stopped_backup array_topology_node_pairs_stopped - create_random_network_topology ${array_all_nodes[@]} - unset array_topology_node_pairs_stopped - check_stopping_nodes_cause_network_split "${array_stopped_nodes[@]}" - ((attempts++)) - done - if [ "$attempts" == 10 ]; - then - copy_array array_topology_node_pairs_backup array_topology_node_pairs - copy_array array_topology_node_pairs_stopped_backup array_topology_node_pairs_stopped - else - disconnect_network "${array_topology_node_pairs_backup[@]}" - connect_network "${array_topology_node_pairs[@]}" - echo "Created topology that has ${#array_topology_node_pairs[@]} connections out of max connections ${#array_network_connection_pool[@]} in the network" - fi - echo array topoloy node pairs is "${array_topology_node_pairs[@]}" with index "${!array_topology_node_pairs[@]}" - echo array topology node pairs stopped is "${array_topology_node_pairs_stopped[@]}" with index "${!array_topology_node_pairs_stopped[@]}" - fi - fi - - if [ "$bool_sync_new_node" == 1 ]; - then - dice=$( bc <<< "$RANDOM % 10" ) - if [ "$dice" == 0 ]; - then - echo Initializing a new node to test syncing from genesis... - shuffle_array "${array_active_nodes[@]}" - node=${shuffled_array[0]} - ((node_count++)) - array_topology_node_pairs+=("$node_count $node") - #echo "array topology node pairs is now ${array_topology_node_pairs[@]}" - initialize_node $node_count - echo Waiting 30 sec for navcoind... - sleep 30 - connect_network "${array_topology_node_pairs[@]}" - sleep 30 - wait_until_sync "${array_active_nodes[@]}" - check_token_hash "${array_active_nodes[@]}" - echo Removing test sync node... - stop_node $node_count - sleep 30 - remove_node $node_count - for i in ${!array_topology_node_pairs[@]}; - do - unset connection - connection=(${array_topology_node_pairs[$i]}) - if [ "$node_count" == "${connection[0]}" ] || [ "$node_count" == "${connection[1]}" ]; - then - unset array_topology_node_pairs[$i] - fi - done - ((node_count--)) - fi - fi - cycles_left=$(bc <<< "$wait_until_cycle - $this_cycle") - previous_block=$current_block - current_block=$blocks - shuffle_array "${array_stressing_nodes[@]}" - node=${shuffled_array[0]} - echo Current block: $current_block Current cycle: $this_cycle - $cycles_left cycle\(s\) left to finish. - echo Tokens created: $(nav_cli $node listtokens | jq ".[].name" | wc -l) - echo NFTs created: $(nav_cli $node listnfts | jq ".[].name" | wc -l) - echo Active nodes: ${array_active_nodes[@]} Inactive nodes: ${array_stopped_nodes[@]} -# for j in $(seq 0 1 $( bc <<< "$node_count-1")); -# do -# echo Reorganizations Node $j: $(prev=0;for i in $(grep height= ${array_data[$j]}/devnet/debug.log|sed -n -e '/height\='$previous_block'/,$p'|sed -n 's/.*height\=\([0-9]*\) .*/\1/p'); do if [ $i -lt $prev ]; then echo $i; fi; prev=$i; done) -# done + for i in ${array_stressing_nodes[@]}; + do + out=$(nav_cli $i "staking false") + echo "Node $i balance: $(nav_cli $i getwalletinfo | jq '.private_balance') xNAV" + done + + echo Checking token hashes match... + + check_token_hash "${array_active_nodes[@]}" + shuffle_array "${array_stressing_nodes[@]}" + node=${shuffled_array[0]} + check_consensus_parameters $node + + if [ "$node_count" == 1 ]; + then + out=$(nav_cli 0 "generate 5") + fi + + if [ "$bool_random_verifychain_check" == 1 ]; + then + dice=$( bc <<< "$RANDOM % 60" ) + if [ "$dice" == 1 ]; + then + random_verifychain_check + fi + fi + if [ "$bool_stopstart_nodes" == 1 ]; + then + dice=$( bc <<< "$RANDOM % 3" ) + node_count_to_stop_this_round=$( bc <<< "$RANDOM % $node_count_to_stop + 1" ) + if [ "${#array_active_nodes[@]}" -gt "$( bc <<< "$node_count_to_stop_this_round + 2" )" ]; + then + if [ "$dice" != 1 ]; + then + select_random_nodes_to_stop $node_count_to_stop_this_round + stop_selected_nodes + fi + fi + if [ "$dice" == 1 ]; + then + start_random_stopped_nodes + fi + fi + if [ "$bool_random_new_topology" == 1 ]; + then + dice=$( bc <<< "$RANDOM % 10" ) + if [ "$dice" == 1 ]; + then + + attempts=0 + copy_array array_topology_node_pairs array_topology_node_pairs_backcup + copy_array array_topology_node_pairs_stopped array_topology_node_pairs_stopped_backup + unset array_connected_nodes + echo "Trying to create a new network topology while avoiding network splitting..." + while [ "${#array_connected_nodes[@]}" -lt "${#array_active_nodes[@]}" ] && [ "$attempts" -lt 10 ]; + do + copy_array array_topology_node_pairs_backup array_topology_node_pairs + copy_array array_topology_node_pairs_stopped_backup array_topology_node_pairs_stopped + create_random_network_topology ${array_all_nodes[@]} + unset array_topology_node_pairs_stopped + check_stopping_nodes_cause_network_split "${array_stopped_nodes[@]}" + ((attempts++)) + done + if [ "$attempts" == 10 ]; + then + copy_array array_topology_node_pairs_backup array_topology_node_pairs + copy_array array_topology_node_pairs_stopped_backup array_topology_node_pairs_stopped + else + disconnect_network "${array_topology_node_pairs_backup[@]}" + connect_network "${array_topology_node_pairs[@]}" + echo "Created topology that has ${#array_topology_node_pairs[@]} connections out of max connections ${#array_network_connection_pool[@]} in the network" + fi + echo array topoloy node pairs is "${array_topology_node_pairs[@]}" with index "${!array_topology_node_pairs[@]}" + echo array topology node pairs stopped is "${array_topology_node_pairs_stopped[@]}" with index "${!array_topology_node_pairs_stopped[@]}" + fi + fi + + if [ "$bool_sync_new_node" == 1 ]; + then + dice=$( bc <<< "$RANDOM % 10" ) + if [ "$dice" == 0 ]; + then + echo Initializing a new node to test syncing from genesis... + shuffle_array "${array_active_nodes[@]}" + node=${shuffled_array[0]} + ((node_count++)) + array_topology_node_pairs+=("$node_count $node") + #echo "array topology node pairs is now ${array_topology_node_pairs[@]}" + initialize_node $node_count + echo Waiting 30 sec for navcoind... + sleep 30 + connect_network "${array_topology_node_pairs[@]}" + sleep 30 + wait_until_sync "${array_active_nodes[@]}" + check_token_hash "${array_active_nodes[@]}" + echo Removing test sync node... + stop_node $node_count + sleep 30 + remove_node $node_count + for i in ${!array_topology_node_pairs[@]}; + do + unset connection + connection=(${array_topology_node_pairs[$i]}) + if [ "$node_count" == "${connection[0]}" ] || [ "$node_count" == "${connection[1]}" ]; + then + unset array_topology_node_pairs[$i] + fi + done + ((node_count--)) + fi + fi + cycles_left=$(bc <<< "$wait_until_cycle - $this_cycle") + previous_block=$current_block + current_block=$blocks + shuffle_array "${array_stressing_nodes[@]}" + node=${shuffled_array[0]} + echo Current block: $current_block Current cycle: $this_cycle - $cycles_left cycle\(s\) left to finish. + echo Tokens created: $(nav_cli $node listtokens | jq ".[].name" | wc -l) + echo NFTs created: $(nav_cli $node listnfts | jq ".[].name" | wc -l) + echo Active nodes: ${array_active_nodes[@]} Inactive nodes: ${array_stopped_nodes[@]} + # for j in $(seq 0 1 $( bc <<< "$node_count-1")); + # do + # echo Reorganizations Node $j: $(prev=0;for i in $(grep height= ${array_data[$j]}/devnet/debug.log|sed -n -e '/height\='$previous_block'/,$p'|sed -n 's/.*height\=\([0-9]*\) .*/\1/p'); do if [ $i -lt $prev ]; then echo $i; fi; prev=$i; done) + # done done ##############################Network Splitting if [ "$bool_network_split" == 1 ]; then - echo Stopping and then starting all nodes... - for i in ${array_active_nodes[@]}; - do - echo Stopping node $i... - stop_node $i - done - sleep 10 - for i in ${array_all_nodes[@]}; - do - echo Starting node $i... - start_node $i - done - echo Waiting 30 sec for navcoind... - sleep 30 - echo Splitting the network into $network_count sub networks... - network_split_started=1 - counter=0 - for i in ${array_stressing_nodes[@]}; - do - if [ "$counter" == "$network_count" ]; - then - counter=0 - fi - eval "array_stressing_nodes_network$counter[$i]=$i" - eval "array_all_nodes_network$counter[$i]=$i" - ((counter++)) - done - counter=0 - for i in ${array_all_nodes[@]}; - do - if [ "$counter" == "$network_count" ]; - then - counter=0 - fi - match=0 - for j in ${array_stressing_nodes[@]}; - do - if [ "$j" == "$i" ]; - then - match=1 - fi - done - if [ "$match" != 1 ]; - then - eval "array_all_nodes_network$counter[$i]=$i" - fi - ((counter++)) - done - copy_array array_topology_node_pairs array_topology_node_pairs_backup - for nc in $(seq 0 1 $( bc <<< "$network_count-1" )); - do - eval "echo stressing nodes in network $nc: \${array_stressing_nodes_network$nc[@]}" - eval "echo nodes in network $nc: \${array_all_nodes_network$nc[@]} index: \${!array_all_nodes_network$nc[@]}" - eval "create_random_network_topology \"\${array_all_nodes_network$nc[@]}\"" - copy_array array_topology_node_pairs array_topology_node_pairs_network$nc - eval "echo topology of network$nc is: \"\${array_topology_node_pairs_network$nc[@]}\"" - eval "connect_network \"\${array_topology_node_pairs_network$nc[@]}\"" - done - wait_until_cycle=$(bc <<< "$this_cycle + $cycles_network_split") - while [ $wait_until_cycle -gt $this_cycle ]; do - echo '' - echo Stressing for $seconds_round seconds... - stress $seconds_round - for nc in $(seq 0 1 $( bc <<< "$network_count - 1" )); - do - echo Waiting until nodes are synced... - eval "wait_until_sync \"\${array_all_nodes_network$nc[@]}\"" - echo Checking token hashes match... - eval "check_token_hash \"\${array_all_nodes_network$nc[@]}\"" - eval "shuffle_array \"\${array_all_nodes_network$nc[@]}\"" - node=${shuffled_array[0]} - check_consensus_parameters $node - blocks=$(nav_cli $node getinfo|jq .blocks) - echo Tokens created: $(nav_cli $node listtokens | jq ".[].name" | wc -l) - echo NFTs created: $(nav_cli $node listnfts | jq ".[].name" | wc -l) - done - cycles_left=$(bc <<< "$wait_until_cycle - $this_cycle") - previous_block=$current_block - current_block=$blocks - shuffle_array "${array_stressing_nodes[@]}" - node=${shuffled_array[0]} - echo Current block: $current_block - echo Current cycle: $this_cycle - $cycles_left cycle\(s\) left to finish. - for i in ${array_stressing_nodes[@]}; - do - out=$(nav_cli $i "staking false") - echo "Node $i balance: $(nav_cli $i getwalletinfo | jq '.private_balance') xNAV" - done - done - - create_random_network_topology "${array_all_nodes[@]}" - connect_network "${array_topology_node_pairs[@]}" - wait_until_sync "${array_all_nodes[@]}" - check_token_hash "${array_all_nodes[@]}" + echo Stopping and then starting all nodes... + for i in ${array_active_nodes[@]}; + do + echo Stopping node $i... + stop_node $i + done + sleep 10 + for i in ${array_all_nodes[@]}; + do + echo Starting node $i... + start_node $i + done + echo Waiting 30 sec for navcoind... + sleep 30 + echo Splitting the network into $network_count sub networks... + network_split_started=1 + counter=0 + for i in ${array_stressing_nodes[@]}; + do + if [ "$counter" == "$network_count" ]; + then + counter=0 + fi + eval "array_stressing_nodes_network$counter[$i]=$i" + eval "array_all_nodes_network$counter[$i]=$i" + ((counter++)) + done + counter=0 + for i in ${array_all_nodes[@]}; + do + if [ "$counter" == "$network_count" ]; + then + counter=0 + fi + match=0 + for j in ${array_stressing_nodes[@]}; + do + if [ "$j" == "$i" ]; + then + match=1 + fi + done + if [ "$match" != 1 ]; + then + eval "array_all_nodes_network$counter[$i]=$i" + fi + ((counter++)) + done + copy_array array_topology_node_pairs array_topology_node_pairs_backup + for nc in $(seq 0 1 $( bc <<< "$network_count-1" )); + do + eval "echo stressing nodes in network $nc: \${array_stressing_nodes_network$nc[@]}" + eval "echo nodes in network $nc: \${array_all_nodes_network$nc[@]} index: \${!array_all_nodes_network$nc[@]}" + eval "create_random_network_topology \"\${array_all_nodes_network$nc[@]}\"" + copy_array array_topology_node_pairs array_topology_node_pairs_network$nc + eval "echo topology of network$nc is: \"\${array_topology_node_pairs_network$nc[@]}\"" + eval "connect_network \"\${array_topology_node_pairs_network$nc[@]}\"" + done + wait_until_cycle=$(bc <<< "$this_cycle + $cycles_network_split") + while [ $wait_until_cycle -gt $this_cycle ]; do + echo '' + echo Stressing for $seconds_round seconds... + stress $seconds_round + for nc in $(seq 0 1 $( bc <<< "$network_count - 1" )); + do + echo Waiting until nodes are synced... + eval "wait_until_sync \"\${array_all_nodes_network$nc[@]}\"" + echo Checking token hashes match... + eval "check_token_hash \"\${array_all_nodes_network$nc[@]}\"" + eval "shuffle_array \"\${array_all_nodes_network$nc[@]}\"" + node=${shuffled_array[0]} + check_consensus_parameters $node + blocks=$(nav_cli $node getinfo|jq .blocks) + echo Tokens created: $(nav_cli $node listtokens | jq ".[].name" | wc -l) + echo NFTs created: $(nav_cli $node listnfts | jq ".[].name" | wc -l) + done + cycles_left=$(bc <<< "$wait_until_cycle - $this_cycle") + previous_block=$current_block + current_block=$blocks + shuffle_array "${array_stressing_nodes[@]}" + node=${shuffled_array[0]} + echo Current block: $current_block + echo Current cycle: $this_cycle - $cycles_left cycle\(s\) left to finish. + for i in ${array_stressing_nodes[@]}; + do + out=$(nav_cli $i "staking false") + echo "Node $i balance: $(nav_cli $i getwalletinfo | jq '.private_balance') xNAV" + done + done + + create_random_network_topology "${array_all_nodes[@]}" + connect_network "${array_topology_node_pairs[@]}" + wait_until_sync "${array_all_nodes[@]}" + check_token_hash "${array_all_nodes[@]}" fi ############################# @@ -1222,17 +1258,17 @@ echo '' echo Stopping stresser. Waiting until $extra_blocks blocks are staked for i in ${array_stressing_nodes[@]}; do - out=$(nav_cli $i "staking true") + out=$(nav_cli $i "staking true") done while [ $blocks -lt $wait_until ]; do - sleep 30 - blocks=$(nav_cli $node getinfo|jq .blocks) - echo $(bc <<< "$wait_until-$blocks") blocks left... + sleep 30 + blocks=$(nav_cli $node getinfo|jq .blocks) + echo $(bc <<< "$wait_until-$blocks") blocks left... done for i in ${array_stressing_nodes[@]}; do - out=$(nav_cli $i "staking false") + out=$(nav_cli $i "staking false") done echo '' echo Waiting until all nodes are synced @@ -1248,15 +1284,15 @@ echo '' starting_block=0 for i in ${!array_verifychain_nodes[@]}; do - ((starting_block++)) - check_node $starting_block ${array_verifychain_nodes[$i]} & + ((starting_block++)) + check_node $starting_block ${array_verifychain_nodes[$i]} & done wait for n in ${array_stressing_nodes[@]}; do - echo "Node $n balance: $(nav_cli $n getbalance) tNAV" + echo "Node $n balance: $(nav_cli $n getbalance) tNAV" done From 589a9807e9deca4a1c2008c248e49e1db78e4e11 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 8 Mar 2022 20:07:45 +0800 Subject: [PATCH 60/61] Updates to the stressor for tokens/nfts --- contrib/stressor_token.sh | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/contrib/stressor_token.sh b/contrib/stressor_token.sh index bccc5db32..c22216fd0 100755 --- a/contrib/stressor_token.sh +++ b/contrib/stressor_token.sh @@ -485,8 +485,8 @@ function wait_until_sync { for i in ${local_array[@]}; do local_array_best_hash[$i]=$(nav_cli $i getbestblockhash) - echo best block hash of node $i: - echo "$(nav_cli $i getbestblockhash)" + echo best block hash of node $i: $(nav_cli $i getbestblockhash) + echo best block height of node $i: $(nav_cli $i getblockcount) done if [ $(printf "%s\n" "${local_array_best_hash[@]}" | LC_CTYPE=C sort -z -u | uniq | grep -n -c .) -gt 1 ]; then @@ -563,7 +563,6 @@ function dice_mint_token { node=${shuffled_array[0]} node_receive=${shuffled_array[1]} tokens=($(nav_cli $node listtokens | jq '.[] | select(.version==0) | .id' | tr "\n" " " | tr -d '"')) - echo $tokens for t in ${tokens[@]} do amount=$(openssl rand 4 | od -DAn) @@ -581,7 +580,6 @@ function dice_send_token { if [ $dice -lt 80 ]; then tokens=($(nav_cli $node listtokens | jq '.[] | select(.version==0) | .id' | tr "\n" " " | tr -d '"')) - echo $tokens for n in ${array_stressing_nodes[@]} do for t in ${tokens[@]} @@ -605,7 +603,6 @@ function dice_burn_token { if [ $dice -lt 50 ]; then tokens=($(nav_cli $node listtokens | jq '.[] | select(.version==0) | .id' | tr "\n" " " | tr -d '"')) - echo $tokens for n in ${array_stressing_nodes[@]} do for t in ${tokens[@]} @@ -647,7 +644,6 @@ function dice_mint_nft { node=${shuffled_array[0]} node_receive=${shuffled_array[1]} nfts=($(nav_cli $node listnfts | jq '.[] | select(.version==1) | .id' | tr "\n" " " | tr -d '"')) - echo $nfts random_scheme=$(env LC_CTYPE=C tr -dc "a-zA-Z0-9-_\$\?" < /dev/urandom | head -c 100) for n in ${nfts[@]} do @@ -667,7 +663,6 @@ function dice_send_nft { if [ $dice -lt 90 ]; then nfts=($(nav_cli $node listnfts | jq '.[] | select(.version==1) | .id' | tr "\n" " " | tr -d '"')) - echo $nfts for n in ${array_stressing_nodes[@]} do for t in ${nfts[@]} From bb1adde3e9933af2d79b11a4b602abb8883a9ba5 Mon Sep 17 00:00:00 2001 From: mxaddict Date: Tue, 8 Mar 2022 20:21:37 +0800 Subject: [PATCH 61/61] Updates to the stressor for tokens/nfts --- contrib/stressor_token.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contrib/stressor_token.sh b/contrib/stressor_token.sh index c22216fd0..e72fd0684 100755 --- a/contrib/stressor_token.sh +++ b/contrib/stressor_token.sh @@ -485,8 +485,7 @@ function wait_until_sync { for i in ${local_array[@]}; do local_array_best_hash[$i]=$(nav_cli $i getbestblockhash) - echo best block hash of node $i: $(nav_cli $i getbestblockhash) - echo best block height of node $i: $(nav_cli $i getblockcount) + echo best block hash/height of node $i: $(nav_cli $i getblockcount) $(nav_cli $i getbestblockhash) done if [ $(printf "%s\n" "${local_array_best_hash[@]}" | LC_CTYPE=C sort -z -u | uniq | grep -n -c .) -gt 1 ]; then @@ -852,7 +851,7 @@ function random_verifychain_check { } function start_node { - $(echo $navpath)/navcoind -datadir=${array_data[$1]} -port=${array_p2p_port[$1]} -rpcport=${array_rpc_port[$1]} -devnet -daemon -nftindex=1 -debug=dao -debug=statehash -ntpminmeasures=-1 -dandelion=0 -disablesafemode -staking=0 2> /dev/null + $(echo $navpath)/navcoind -datadir=${array_data[$1]} -port=${array_p2p_port[$1]} -rpcport=${array_rpc_port[$1]} -devnet -daemon -nftindex -debug=dao -debug=statehash -ntpminmeasures=-1 -dandelion=0 -disablesafemode -staking=0 2> /dev/null # gdb -batch -ex "run" -ex "bt" --args $(echo $navpath)/navcoind -datadir=${array_data[$1]} -port=${array_p2p_port[$1]} -rpcport=${array_rpc_port[$1]} -devnet -debug=dao -debug=statehash -ntpminmeasures=-1 -dandelion=0 -disablesafemode -staking=0 > out.gdb & }