From 8c25b745b3eb1a70ed965d9db97b9d103b1fa29d Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Jun 2021 00:47:56 -0400 Subject: [PATCH 01/15] Start to persist zindex stats to disk --- src/main.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.h | 10 ++++++ 2 files changed, 102 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 2d352d12d..16389256b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -572,6 +572,96 @@ namespace { } // anon namespace +// CZindexDB +CZindexDB::CZindexDB() +{ + pathAddr = GetDataDir() / "zindex.dat"; +} + +bool CZindexDB::Read(CZindexStats& zstats) +{ + // open input file, and associate with CAutoFile + FILE *file = fopen(pathAddr.string().c_str(), "rb"); + CAutoFile filein(file, SER_DISK, CLIENT_VERSION); + if (filein.IsNull()) + return error("%s: Failed to open file %s", __func__, pathAddr.string()); + + // use file size to size memory buffer + int fileSize = boost::filesystem::file_size(pathAddr); + int dataSize = fileSize - sizeof(uint256); + // Don't try to resize to a negative number if file is small + if (dataSize < 0) + dataSize = 0; + vector vchData; + vchData.resize(dataSize); + uint256 hashIn; + + // read data and checksum from file + try { + filein.read((char *)&vchData[0], dataSize); + filein >> hashIn; + } + catch (const std::exception& e) { + return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } + filein.fclose(); + + CDataStream ssZstats(vchData, SER_DISK, CLIENT_VERSION); + + // verify stored checksum matches input data + uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); + if (hashIn != hashTmp) + return error("%s: Checksum mismatch, data corrupted", __func__); + + unsigned char pchMsgTmp[4]; + try { + // de-serialize file header (network specific magic number) and .. + ssZstats >> FLATDATA(pchMsgTmp); + + // ... verify the network matches ours + if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) + return error("%s: Invalid network magic number", __func__); + + // de-serialize address data into one CAddrMan object + ssZstats >> addr; + } + catch (const std::exception& e) { + return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } + + return true; +} + +bool CZindexDB::Write(const CZindexStats& zstats) +{ + // Generate random temporary filename + unsigned short randv = 0; + GetRandBytes((unsigned char*)&randv, sizeof(randv)); + std::string tmpfn = strprintf("zindex.dat.%04x", randv); + + // serialize zstats, checksum data up to that point, then append checksum + CDataStream ssZstats(SER_DISK, CLIENT_VERSION); + ssZstats << FLATDATA(Params().MessageStart()); + ssZstats << zstats; + uint256 hash = Hash(ssZstats.begin(), ssZstats.end()); + ssZstats << hash; + + // Write and commit header, data + try { + fileout << ssPeers; + } catch (const std::exception& e) { + return error("%s: Serialize or I/O error - %s", __func__, e.what()); + } + FileCommit(fileout.Get()); + fileout.fclose(); + + // replace existing zindex.dat, if any, with new zindex.dat.XXXX + if (!RenameOver(pathTmp, pathAddr)) + return error("%s: Rename-into-place failed", __func__); + + return true; +} + bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { LOCK(cs_main); CNodeState *state = State(nodeid); @@ -4603,6 +4693,8 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl } } + // TODO: Update zindex.dat on disk + if (fZindex) fprintf(stderr, "ht.%d, ShieldedPayments=%d, ShieldedTx=%d, ShieldedOutputs=%d, FullyShieldedTx=%d, ntz=%d\n", pindexNew->GetHeight(), nShieldedPayments, nShieldedTx, nShieldedOutputs, nFullyShieldedTx, nNotarizations ); diff --git a/src/main.h b/src/main.h index 078e48cef..9aae210ef 100644 --- a/src/main.h +++ b/src/main.h @@ -950,4 +950,14 @@ std::pair>, uint64_t> DrainRecent void SetChainNotifiedSequence(uint64_t recentlyConflictedSequence); bool ChainIsFullyNotified(); +class CZindexDB +{ +private: + boost::filesystem::path pathAddr; +public: + CZindexDB(); + bool Write(const CZindexDB& addr); + bool Read(CZindexDB& addr); +}; + #endif // HUSH_MAIN_H From 40bd639bd891a67b3c5b4f23ed6d0f69bbbf50e5 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Jun 2021 21:58:18 -0400 Subject: [PATCH 02/15] Read zdb on startup and serialize every 150s and on shutdown --- src/net.cpp | 35 +++++++++++++++++++++++++++++++++-- src/net.h | 1 + 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 808df788c..1dd1cce37 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -48,6 +48,9 @@ using namespace hush; // Satoshi originally used 10 seconds(!), did they know something Peter Wuille didn't? #define DUMP_ADDRESSES_INTERVAL 300 +// This is every 2 blocks, on avg, on HUSH3 +#define DUMP_ZINDEX_INTERVAL 150 + #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 #endif @@ -1400,6 +1403,16 @@ void DumpAddresses() LogPrint("net", "Flushed %d addresses to peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart); } +void DumpZindexStats() +{ + int64_t nStart = GetTimeMillis(); + + CZindexDB zdb; + zdb.Write(zstats); + + LogPrintf("Flushed %d items to zindex.dat %dms\n", zstats.size(), GetTimeMillis() - nStart); +} + void static ProcessOneShot() { string strDest; @@ -1911,6 +1924,19 @@ void static Discover(boost::thread_group& threadGroup) void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) { + if (fZindex) { + uiInterface.InitMessage(_("Loading zindex stats...")); + int64_t nStart = GetTimeMillis(); + { + CZindexDB zdb; + if (!zdb.Read(zstats)) { + LogPrintf("Invalid or missing zindex.dat! Stats may be incorrect!!!\n"); + // TODO: move invalid files out of the way? + } + } + LogPrintf("Loaded %i items from zindex.dat %dms\n", zstats.size(), GetTimeMillis() - nStart); + } + uiInterface.InitMessage(_("Loading addresses...")); // Load addresses for peers.dat int64_t nStart = GetTimeMillis(); @@ -1919,8 +1945,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) if (!adb.Read(addrman)) LogPrintf("Invalid or missing peers.dat! This can happen when upgrading. Whatevz, recreating\n"); } - LogPrintf("Loaded %i addresses from peers.dat %dms\n", - addrman.size(), GetTimeMillis() - nStart); + LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart); fAddressesInitialized = true; if (semOutbound == NULL) { @@ -1968,6 +1993,9 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) // Dump network addresses scheduler.scheduleEvery(&DumpAddresses, DUMP_ADDRESSES_INTERVAL); + + // Dump zindex stats + scheduler.scheduleEvery(&DumpZstats, DUMP_ZINDEX_INTERVAL); } bool StopNode() @@ -1977,6 +2005,9 @@ bool StopNode() for (int i=0; i<(MAX_OUTBOUND_CONNECTIONS + MAX_FEELER_CONNECTIONS); i++) semOutbound->post(); + // persist current zindex stats to disk before we exit + DumpZindexStats(); + if (HUSH_NSPV_FULLNODE && fAddressesInitialized) { DumpAddresses(); diff --git a/src/net.h b/src/net.h index d55d500e1..e0437421f 100644 --- a/src/net.h +++ b/src/net.h @@ -174,6 +174,7 @@ extern bool fListen; extern uint64_t nLocalServices; extern uint64_t nLocalHostNonce; extern CAddrMan addrman; +extern CZindexStats zstats; /** Maximum number of connections to simultaneously allow (aka connection slots) */ extern int nMaxConnections; From 646012c35682288f5115708c140377290b50cf93 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Jun 2021 23:21:05 -0400 Subject: [PATCH 03/15] Fix incorrect comments mentioning JoinSplits --- src/chain.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/chain.h b/src/chain.h index 1d8f2a462..bb0b2897f 100644 --- a/src/chain.h +++ b/src/chain.h @@ -266,7 +266,7 @@ public: int64_t nPayments; //! (memory only) Number of shielded transactions (of any kind) in the block up to and including this block. - //! A shielded transaction is defined as a transaction that contains at least 1 JoinSplit, which includes + //! A shielded transaction is defined as a transaction that contains at least 1 ShieldedInput or ShieldedOutput //! shielding/de-shielding and other complex transaction possibilties including multiple taddrs/zaddrs as //! inputs and outputs. int64_t nShieldedTx; @@ -278,7 +278,7 @@ public: int64_t nShieldedSpends; //! (memory only) Number of fully shielded transactions. A fully shielded transaction is defined - //! as a transaction containing JoinSplits and only shielded inputs and outputs, i.e. no transparent + //! as a transaction containing only shielded inputs and outputs, i.e. no transparent // inputs or outputs: z->z or z->(z,z) or z->(z,z,z,) etc... int64_t nFullyShieldedTx; @@ -295,7 +295,7 @@ public: int64_t nFullyShieldedPayments; //! (memory only) Number of deshielding transactions. A deshielding transaction is defined - //! as a transaction containing JoinSplits and at least one transparent output. + //! as a transaction containing ShieldedInputs and at least one transparent output. int64_t nDeshieldingTx; //! (memory only) Number of deshielding payments. A deshielding payment is defined @@ -303,7 +303,7 @@ public: int64_t nDeshieldingPayments; //! (memory only) Number of shielding transactions. A shielding transaction is defined - //! as a transaction containing JoinSplits and at least one transparent input + //! as a transaction containing ShieldedOutputs and at least one transparent input // i.e. t->z or t->(z,t) or z->(z,z,t) int64_t nShieldingTx; @@ -322,7 +322,7 @@ public: int64_t nChainPayments; //! (memory only) Number of shielded transactions (of any kind) in the chain up to and including this block. - //! A shielded transaction is defined as a transaction that contains at least 1 JoinSplit, which includes + //! A shielded transaction is defined as a transaction that contains at least 1 ShieldedInput or ShieldedOutput //! shielding/de-shielding and other complex transaction possibilties including multiple taddrs/zaddrs as //! inputs and outputs. int64_t nChainShieldedTx; @@ -334,7 +334,7 @@ public: int64_t nChainShieldedSpends; //! (memory only) Number of fully shielded transactions. A fully shielded transaction is defined - //! as a transaction containing JoinSplits and only shielded inputs and outputs, i.e. no transparent + //! as a transaction containing and only shielded inputs and outputs, i.e. no transparent // inputs or outputs: z->z or z->(z,z) or z->(z,z,z,) etc... int64_t nChainFullyShieldedTx; @@ -351,7 +351,7 @@ public: int64_t nChainFullyShieldedPayments; //! (memory only) Number of deshielding transactions. A deshielding transaction is defined - //! as a transaction containing JoinSplits and at least one transparent output. + //! as a transaction containing ShieldedInputs and at least one transparent output. int64_t nChainDeshieldingTx; //! (memory only) Number of deshielding payments. A deshielding payment is defined @@ -359,7 +359,7 @@ public: int64_t nChainDeshieldingPayments; //! (memory only) Number of shielding transactions. A shielding transaction is defined - //! as a transaction containing JoinSplits and at least one transparent input + //! as a transaction containing ShieldedOutputs and at least one transparent input // i.e. t->z or t->(z,t) or z->(z,z,t) int64_t nChainShieldingTx; From 231850740ea09142c193c8df82a21a0a7ba60258 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 16 Jun 2021 11:07:20 -0400 Subject: [PATCH 04/15] CZindexStats --- src/main.cpp | 20 ++++++---- src/main.h | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/net.cpp | 7 ++-- 3 files changed, 119 insertions(+), 12 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 16389256b..77d321251 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -609,9 +609,9 @@ bool CZindexDB::Read(CZindexStats& zstats) CDataStream ssZstats(vchData, SER_DISK, CLIENT_VERSION); // verify stored checksum matches input data - uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); + uint256 hashTmp = Hash(ssZstats.begin(), ssZstats.end()); if (hashIn != hashTmp) - return error("%s: Checksum mismatch, data corrupted", __func__); + return error("%s: zstats Checksum mismatch, data corrupted", __func__); unsigned char pchMsgTmp[4]; try { @@ -622,10 +622,9 @@ bool CZindexDB::Read(CZindexStats& zstats) if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) return error("%s: Invalid network magic number", __func__); - // de-serialize address data into one CAddrMan object - ssZstats >> addr; - } - catch (const std::exception& e) { + // de-serialize data into one CZindexStats object + ssZstats >> zstats; + } catch (const std::exception& e) { return error("%s: Deserialize or I/O error - %s", __func__, e.what()); } @@ -646,9 +645,16 @@ bool CZindexDB::Write(const CZindexStats& zstats) uint256 hash = Hash(ssZstats.begin(), ssZstats.end()); ssZstats << hash; + // open temp output file, and associate with CAutoFile + boost::filesystem::path pathTmp = GetDataDir() / tmpfn; + FILE *file = fopen(pathTmp.string().c_str(), "wb"); + CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); + if (fileout.IsNull()) + return error("%s: Failed to open file %s", __func__, pathTmp.string()); + // Write and commit header, data try { - fileout << ssPeers; + fileout << ssZstats; } catch (const std::exception& e) { return error("%s: Serialize or I/O error - %s", __func__, e.what()); } diff --git a/src/main.h b/src/main.h index 9aae210ef..676a069cd 100644 --- a/src/main.h +++ b/src/main.h @@ -950,14 +950,114 @@ std::pair>, uint64_t> DrainRecent void SetChainNotifiedSequence(uint64_t recentlyConflictedSequence); bool ChainIsFullyNotified(); +class CZindexStats +{ +//private: +public: + int64_t nHeight; + int64_t nChainTx; + int64_t nChainNotarizations; + int64_t nChainPayments; + int64_t nChainShieldedTx; + int64_t nChainShieldedOutputs; + int64_t nChainShieldedSpends; + int64_t nChainFullyShieldedTx; + int64_t nChainShieldingPayments; + int64_t nChainShieldedPayments; + int64_t nChainFullyShieldedPayments; + int64_t nChainDeshieldingTx; + int64_t nChainDeshieldingPayments; + int64_t nChainShieldingTx; + + size_t Height() const + { + return nHeight; + } + + void Clear() + { + LOCK(cs_main); + nChainTx=0; + nChainNotarizations=0; + nChainPayments=0; + nChainShieldedTx=0; + nChainShieldedOutputs=0; + nChainShieldedSpends=0; + nChainFullyShieldedTx=0; + nChainShieldingPayments=0; + nChainShieldedPayments=0; + nChainFullyShieldedPayments=0; + nChainDeshieldingTx=0; + nChainDeshieldingPayments=0; + nChainShieldingTx=0; + } + + CZindexStats() + { + Clear(); + } + + ~CZindexStats() + { + } + + template void Serialize(Stream &s) const + { + LOCK(cs_main); + + // So we can detect a new version and force a rescan + unsigned char nVersion = 1; + s << nVersion; + s << nHeight; + s << nChainTx; + s << nChainNotarizations; + s << nChainPayments; + s << nChainShieldedTx; + s << nChainShieldedOutputs; + s << nChainShieldedSpends; + s << nChainFullyShieldedTx; + s << nChainShieldingPayments; + s << nChainShieldedPayments; + s << nChainFullyShieldedPayments; + s << nChainDeshieldingTx; + s << nChainDeshieldingPayments; + s << nChainShieldingTx; + } + + template void Unserialize(Stream& s) + { + LOCK(cs_main); + + Clear(); + unsigned char nVersion; + s >> nVersion; + s >> nHeight; + s >> nChainTx; + s >> nChainNotarizations; + s >> nChainPayments; + s >> nChainShieldedTx; + s >> nChainShieldedOutputs; + s >> nChainShieldedSpends; + s >> nChainFullyShieldedTx; + s >> nChainShieldingPayments; + s >> nChainShieldedPayments; + s >> nChainFullyShieldedPayments; + s >> nChainDeshieldingTx; + s >> nChainDeshieldingPayments; + s >> nChainShieldingTx; + } +}; + +// Wrapper for zindex.dat stats class CZindexDB { private: boost::filesystem::path pathAddr; public: CZindexDB(); - bool Write(const CZindexDB& addr); - bool Read(CZindexDB& addr); + bool Write(const CZindexStats& zstats); + bool Read(CZindexStats& zstats); }; + #endif // HUSH_MAIN_H diff --git a/src/net.cpp b/src/net.cpp index 1dd1cce37..46e6dac90 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -106,6 +106,7 @@ static CNode* pnodeLocalHost = NULL; uint64_t nLocalHostNonce = 0; static std::vector vhListenSocket; CAddrMan addrman; +CZindexStats zstats; int nMaxConnections = DEFAULT_MAX_PEER_CONNECTIONS; bool fAddressesInitialized = false; std::string strSubVersion; @@ -1410,7 +1411,7 @@ void DumpZindexStats() CZindexDB zdb; zdb.Write(zstats); - LogPrintf("Flushed %d items to zindex.dat %dms\n", zstats.size(), GetTimeMillis() - nStart); + LogPrintf("Flushed stats at height %li to zindex.dat %dms\n", zstats.Height(), GetTimeMillis() - nStart); } void static ProcessOneShot() @@ -1934,7 +1935,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) // TODO: move invalid files out of the way? } } - LogPrintf("Loaded %i items from zindex.dat %dms\n", zstats.size(), GetTimeMillis() - nStart); + LogPrintf("Loaded stats at height %li from zindex.dat %dms\n", zstats.Height(), GetTimeMillis() - nStart); } uiInterface.InitMessage(_("Loading addresses...")); @@ -1995,7 +1996,7 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) scheduler.scheduleEvery(&DumpAddresses, DUMP_ADDRESSES_INTERVAL); // Dump zindex stats - scheduler.scheduleEvery(&DumpZstats, DUMP_ZINDEX_INTERVAL); + scheduler.scheduleEvery(&DumpZindexStats, DUMP_ZINDEX_INTERVAL); } bool StopNode() From 666054bec5c417ab6dd554d37c0a355bcf251a6a Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 16 Jun 2021 12:38:12 -0400 Subject: [PATCH 05/15] Make compiler happy and start updating zstats in-memory data --- src/main.cpp | 6 +++++- src/net.cpp | 1 - src/net.h | 1 - 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 77d321251..f3892031d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,6 +76,7 @@ using namespace std; CCriticalSection cs_main; extern uint8_t NOTARY_PUBKEY33[33]; extern int32_t HUSH_LOADINGBLOCKS,HUSH_LONGESTCHAIN,HUSH_INSYNC,HUSH_CONNECTING,HUSH_EXTRASATOSHI; +extern CZindexStats zstats; int32_t HUSH_NEWBLOCKS; int32_t hush_block2pubkey33(uint8_t *pubkey33,CBlock *block); bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); @@ -4661,6 +4662,10 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl pindex->nChainFullyShieldedPayments = (pindex->pprev ? pindex->pprev->nChainFullyShieldedPayments : 0) + pindex->nFullyShieldedPayments; pindex->nChainShieldingPayments = (pindex->pprev ? pindex->pprev->nChainShieldingPayments : 0) + pindex->nShieldingPayments; pindex->nChainDeshieldingPayments = (pindex->pprev ? pindex->pprev->nChainDeshieldingPayments : 0) + pindex->nDeshieldingPayments; + + // Update in-memory structure that gets serialized to zindex.dat + zstats.nHeight = pindex->GetHeight(); + zstats.nChainShieldedSpends = pindex->nChainShieldedSpends; } if (pindex->pprev) { @@ -4699,7 +4704,6 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl } } - // TODO: Update zindex.dat on disk if (fZindex) fprintf(stderr, "ht.%d, ShieldedPayments=%d, ShieldedTx=%d, ShieldedOutputs=%d, FullyShieldedTx=%d, ntz=%d\n", diff --git a/src/net.cpp b/src/net.cpp index 46e6dac90..16a397c09 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -95,7 +95,6 @@ namespace { // Global state variables extern uint16_t ASSETCHAINS_P2PPORT; extern char SMART_CHAIN_SYMBOL[65]; - bool fDiscover = true; bool fListen = true; uint64_t nLocalServices = NODE_NETWORK | NODE_NSPV; diff --git a/src/net.h b/src/net.h index e0437421f..d55d500e1 100644 --- a/src/net.h +++ b/src/net.h @@ -174,7 +174,6 @@ extern bool fListen; extern uint64_t nLocalServices; extern uint64_t nLocalHostNonce; extern CAddrMan addrman; -extern CZindexStats zstats; /** Maximum number of connections to simultaneously allow (aka connection slots) */ extern int nMaxConnections; From fe1b7f34b907e825fe279ae018967fdb8c7a3302 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 16 Jun 2021 13:29:07 -0400 Subject: [PATCH 06/15] Update in-memory zstats --- src/main.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f3892031d..f1624d7a4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4664,8 +4664,21 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl pindex->nChainDeshieldingPayments = (pindex->pprev ? pindex->pprev->nChainDeshieldingPayments : 0) + pindex->nDeshieldingPayments; // Update in-memory structure that gets serialized to zindex.dat - zstats.nHeight = pindex->GetHeight(); - zstats.nChainShieldedSpends = pindex->nChainShieldedSpends; + zstats.nHeight = pindex->GetHeight(); + zstats.nChainNotarizations = pindex->nChainNotarizations ; + zstats.nChainShieldedTx = pindex->nChainShieldedTx ; + zstats.nChainShieldedOutputs = pindex->nChainShieldedOutputs ; + zstats.nChainShieldedSpends = pindex->nChainShieldedSpends ; + zstats.nChainFullyShieldedTx = pindex->nChainFullyShieldedTx ; + zstats.nChainShieldingTx = pindex->nChainShieldingTx ; + zstats.nChainDeshieldingTx = pindex->nChainDeshieldingTx ; + zstats.nChainPayments = pindex->nChainPayments ; + zstats.nChainShieldedPayments = pindex->nChainShieldedPayments ; + zstats.nChainFullyShieldedPayments = pindex->nChainFullyShieldedPayments ; + zstats.nChainShieldingPayments = pindex->nChainShieldingPayments ; + zstats.nChainDeshieldingPayments = pindex->nChainDeshieldingPayments ; + fprintf(stderr,"%s: setting zstats with zspends=%li, zouts=%li, anonset=%li\n", __FUNCTION__, zstats.nChainShieldedOutputs, zstats.nChainShieldedSpends, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends); + } if (pindex->pprev) { From 20779308d82d595b6ab20c92600b7f48548329ac Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 17 Jun 2021 16:26:24 -0400 Subject: [PATCH 07/15] Dump zindex.dat on first startup, if it does not exist --- src/net.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 16a397c09..51bc90f19 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1922,6 +1922,7 @@ void static Discover(boost::thread_group& threadGroup) #endif } +//extern CWallet pwalletMain; void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) { if (fZindex) { @@ -1930,11 +1931,26 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) { CZindexDB zdb; if (!zdb.Read(zstats)) { - LogPrintf("Invalid or missing zindex.dat! Stats may be incorrect!!!\n"); - // TODO: move invalid files out of the way? + // The first time nodes use zindex.dat code, no file will be found + // TODO: rescan if invalid only + LogPrintf("Invalid or missing zindex.dat! Generating new...\n"); + + //bool update = true; + //pwalletMain->ScanForWalletTransactions(chainActive.Genesis(),update); + + // We assume this is the first startup with zindex.dat code, and serialize current data to disk. + DumpZindexStats(); + + // Now read-in the stats we just wrote to disk to memory + if(!zdb.Read(zstats)) { + LogPrintf("Invalid or missing zindex.dat! Stats may be corrupt\n"); + } else { + LogPrintf("Loaded stats at height %li from zindex.dat %dms\n", zstats.Height(), GetTimeMillis() - nStart); + } + } else { + LogPrintf("Loaded stats at height %li from zindex.dat %dms\n", zstats.Height(), GetTimeMillis() - nStart); } } - LogPrintf("Loaded stats at height %li from zindex.dat %dms\n", zstats.Height(), GetTimeMillis() - nStart); } uiInterface.InitMessage(_("Loading addresses...")); From b03ed9d9d2662386e4b12f35e32cac47c419316e Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 17 Jun 2021 16:47:04 -0400 Subject: [PATCH 08/15] If chain stats are zero, load them from zindex.dat data --- src/main.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index f1624d7a4..953a2c1d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4650,6 +4650,36 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl if (fZdebug) { //fprintf(stderr,"%s: setting blockchain zstats with zspends=%d, zouts=%d\n", __FUNCTION__, nShieldedSpendsInBlock, nShieldedOutputsInBlock ); } + if (pindex->pprev) { + // If chain stats are zero (such as after restart), load data from zindex.dat + if (pindex->pprev->nChainNotarizations == 0) + pindex->pprev->nChainNotarizations = zstats.nChainNotarizations; + if (pindex->pprev->nChainShieldedTx == 0) + pindex->pprev->nChainShieldedTx = zstats.nChainShieldedTx; + if (pindex->pprev->nChainShieldedOutputs == 0) + pindex->pprev->nChainShieldedOutputs = zstats.nChainShieldedOutputs; + if (pindex->pprev->nChainShieldedSpends == 0) { + pindex->pprev->nChainShieldedSpends = zstats.nChainShieldedSpends; + fprintf(stderr, "%s: loaded anonset=%li from disk\n", __func__, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends); + } + if (pindex->pprev->nChainFullyShieldedTx == 0) + pindex->pprev->nChainFullyShieldedTx = zstats.nChainFullyShieldedTx; + if (pindex->pprev->nChainShieldingTx == 0) + pindex->pprev->nChainShieldingTx = zstats.nChainShieldingTx; + if (pindex->pprev->nChainDeshieldingTx == 0) + pindex->pprev->nChainDeshieldingTx = zstats.nChainDeshieldingTx; + if (pindex->pprev->nChainPayments == 0) + pindex->pprev->nChainPayments = zstats.nChainPayments; + if (pindex->pprev->nChainShieldedPayments == 0) + pindex->pprev->nChainShieldedPayments = zstats.nChainShieldedPayments; + if (pindex->pprev->nChainFullyShieldedPayments == 0) + pindex->pprev->nChainFullyShieldedPayments = zstats.nChainFullyShieldedPayments; + if (pindex->pprev->nChainShieldingPayments == 0) + pindex->pprev->nChainShieldingPayments = zstats.nChainShieldingPayments; + if (pindex->pprev->nChainDeshieldingPayments == 0) + pindex->pprev->nChainDeshieldingPayments = zstats.nChainDeshieldingPayments; + } + pindex->nChainNotarizations = (pindex->pprev ? pindex->pprev->nChainNotarizations : 0) + pindex->nNotarizations; pindex->nChainShieldedTx = (pindex->pprev ? pindex->pprev->nChainShieldedTx : 0) + pindex->nShieldedTx; pindex->nChainShieldedOutputs = (pindex->pprev ? pindex->pprev->nChainShieldedOutputs : 0) + pindex->nShieldedOutputs; From 21cca9ec2993223260b8952266cfa7a3e0702925 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 18 Jun 2021 11:41:47 -0400 Subject: [PATCH 09/15] Only dump zindex.dat if -zindex is enabled --- src/net.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 51bc90f19..218f766d3 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2010,8 +2010,10 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) // Dump network addresses scheduler.scheduleEvery(&DumpAddresses, DUMP_ADDRESSES_INTERVAL); - // Dump zindex stats - scheduler.scheduleEvery(&DumpZindexStats, DUMP_ZINDEX_INTERVAL); + // Dump zindex stats if -zindex is enabled + if (fZindex) { + scheduler.scheduleEvery(&DumpZindexStats, DUMP_ZINDEX_INTERVAL); + } } bool StopNode() From 8d9d2322abffe97f86d45994fdb65da4817a2b1c Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 18 Jun 2021 11:57:39 -0400 Subject: [PATCH 10/15] Log stats height vs node local height --- src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 953a2c1d3..76300e1a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4660,7 +4660,8 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl pindex->pprev->nChainShieldedOutputs = zstats.nChainShieldedOutputs; if (pindex->pprev->nChainShieldedSpends == 0) { pindex->pprev->nChainShieldedSpends = zstats.nChainShieldedSpends; - fprintf(stderr, "%s: loaded anonset=%li from disk\n", __func__, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends); + // TODO: if zstats.nHeight != chainActive.Height() the stats will be off + fprintf(stderr, "%s: loaded anonset=%li at stats height=%li vs local height=%d from disk\n", __func__, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends, zstats.nHeight, chainActive.Height() ); } if (pindex->pprev->nChainFullyShieldedTx == 0) pindex->pprev->nChainFullyShieldedTx = zstats.nChainFullyShieldedTx; From e6a7423029881d205f6b6c1305adc7922486c0f5 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 18 Jun 2021 19:27:06 -0400 Subject: [PATCH 11/15] Log height so we can easily see the historical value of anonset size for all block heights --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 76300e1a6..8ae274001 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4708,7 +4708,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl zstats.nChainFullyShieldedPayments = pindex->nChainFullyShieldedPayments ; zstats.nChainShieldingPayments = pindex->nChainShieldingPayments ; zstats.nChainDeshieldingPayments = pindex->nChainDeshieldingPayments ; - fprintf(stderr,"%s: setting zstats with zspends=%li, zouts=%li, anonset=%li\n", __FUNCTION__, zstats.nChainShieldedOutputs, zstats.nChainShieldedSpends, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends); + fprintf(stderr,"%s: setting zstats with height,zspends,zouts,anonset=%li,%li,%li,%li\n", __FUNCTION__, zstats.nHeight, zstats.nChainShieldedOutputs, zstats.nChainShieldedSpends, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends); } From 7a0bdd79c800efef2a88635b6ab82d5ebad97ea6 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 17:43:47 -0400 Subject: [PATCH 12/15] . --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 76300e1a6..ef57ccc7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4708,7 +4708,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl zstats.nChainFullyShieldedPayments = pindex->nChainFullyShieldedPayments ; zstats.nChainShieldingPayments = pindex->nChainShieldingPayments ; zstats.nChainDeshieldingPayments = pindex->nChainDeshieldingPayments ; - fprintf(stderr,"%s: setting zstats with zspends=%li, zouts=%li, anonset=%li\n", __FUNCTION__, zstats.nChainShieldedOutputs, zstats.nChainShieldedSpends, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends); + fprintf(stderr,"%s: setting zstats with zouts=%li, zspends=%li, anonset=%li\n", __FUNCTION__, zstats.nChainShieldedOutputs, zstats.nChainShieldedSpends, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends); } From 6f6b5b739396513485067da139f6a3fc17f2056b Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 17:49:41 -0400 Subject: [PATCH 13/15] . --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index ef57ccc7f..cf6a4ce32 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4661,7 +4661,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl if (pindex->pprev->nChainShieldedSpends == 0) { pindex->pprev->nChainShieldedSpends = zstats.nChainShieldedSpends; // TODO: if zstats.nHeight != chainActive.Height() the stats will be off - fprintf(stderr, "%s: loaded anonset=%li at stats height=%li vs local height=%d from disk\n", __func__, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends, zstats.nHeight, chainActive.Height() ); + fprintf(stderr, "%s: loaded anonymity set of %li at stats height=%li vs local height=%d from disk\n", __func__, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends, zstats.nHeight, chainActive.Height() ); } if (pindex->pprev->nChainFullyShieldedTx == 0) pindex->pprev->nChainFullyShieldedTx = zstats.nChainFullyShieldedTx; From e1a5d909a0d058729a1cd2db63c1efa250f6b549 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 17:59:25 -0400 Subject: [PATCH 14/15] . --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 8ae274001..1ea9c3b46 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4708,7 +4708,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl zstats.nChainFullyShieldedPayments = pindex->nChainFullyShieldedPayments ; zstats.nChainShieldingPayments = pindex->nChainShieldingPayments ; zstats.nChainDeshieldingPayments = pindex->nChainDeshieldingPayments ; - fprintf(stderr,"%s: setting zstats with height,zspends,zouts,anonset=%li,%li,%li,%li\n", __FUNCTION__, zstats.nHeight, zstats.nChainShieldedOutputs, zstats.nChainShieldedSpends, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends); + fprintf(stderr,"%s: setting zstats with height,zouts,zspends,anonset=%li,%li,%li,%li\n", __FUNCTION__, zstats.nHeight, zstats.nChainShieldedOutputs, zstats.nChainShieldedSpends, zstats.nChainShieldedOutputs - zstats.nChainShieldedSpends); } From e829822041831948543e3bbc25edeb0179aa0d55 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 26 Jun 2021 12:27:38 -0400 Subject: [PATCH 15/15] logging to help debug window stats being wrong after restart --- src/main.cpp | 4 +++- src/rpc/blockchain.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 62e4741b3..94b41fe5a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4669,8 +4669,10 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl pindex->pprev->nChainShieldingTx = zstats.nChainShieldingTx; if (pindex->pprev->nChainDeshieldingTx == 0) pindex->pprev->nChainDeshieldingTx = zstats.nChainDeshieldingTx; - if (pindex->pprev->nChainPayments == 0) + if (pindex->pprev->nChainPayments == 0) { + fprintf(stderr, "%s: setting nChainPayments=%li at height %d\n", __func__, zstats.nChainPayments, chainActive.Height() ); pindex->pprev->nChainPayments = zstats.nChainPayments; + } if (pindex->pprev->nChainShieldedPayments == 0) pindex->pprev->nChainShieldedPayments = zstats.nChainShieldedPayments; if (pindex->pprev->nChainFullyShieldedPayments == 0) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 7c38ef1eb..609f26420 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1660,10 +1660,12 @@ UniValue getchaintxstats(const UniValue& params, bool fHelp, const CPubKey& mypk throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 0 and the block's height - 1"); } } + LogPrintf("%s: blockcount = %d\n", __func__, blockcount); const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->GetHeight() - blockcount); int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast(); int nTxDiff = pindex->nChainTx - pindexPast->nChainTx; + LogPrintf("%s: pindexPast.height = %d, pindex.height = %d\n", __func__, pindexPast->GetHeight(), pindex->GetHeight() ); UniValue ret(UniValue::VOBJ); ret.pushKV("time", (int64_t)pindex->nTime); @@ -1695,6 +1697,7 @@ UniValue getchaintxstats(const UniValue& params, bool fHelp, const CPubKey& mypk ret.pushKV("window_tx_count", nTxDiff); ret.pushKV("window_interval", nTimeDiff); int64_t nPaymentsDiff = pindex->nChainPayments - pindexPast->nChainPayments; + LogPrintf("%s: pindexPast.nChainPayments = %d, pindex.nChainPayments = %d\n", __func__, pindexPast->nChainPayments, pindex->nChainPayments ); int64_t nShieldedTxDiff = pindex->nChainShieldedTx - pindexPast->nChainShieldedTx; int64_t nShieldingTxDiff = pindex->nChainShieldingTx - pindexPast->nChainShieldingTx; int64_t nDeshieldingTxDiff = pindex->nChainDeshieldingTx - pindexPast->nChainDeshieldingTx;