From 860541d2e432d51f8f44ebbe2823ebd409f1bc49 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 4 May 2021 12:25:12 -0400 Subject: [PATCH 01/42] Show relay status in getpeerinfo --- src/net.h | 1 + src/rpc/net.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/net.h b/src/net.h index bdc56de1b..d55d500e1 100644 --- a/src/net.h +++ b/src/net.h @@ -223,6 +223,7 @@ public: int nStartingHeight; uint64_t nSendBytes; uint64_t nRecvBytes; + bool fRelayTxes; bool fAllowlisted; // If true this node bypasses DoS ban limits bool fFeeler; // If true this node is being used as a short lived feeler. double dPingTime; diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 46c3cf24d..6ea9819a8 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -95,6 +95,7 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n" " \"bytessent\": n, (numeric) The total bytes sent\n" " \"bytesrecv\": n, (numeric) The total bytes received\n" + " \"relaytxes\":true|false, (boolean) Whether peer has asked us to relay transactions to it\n" " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n" " \"timeoffset\": ttt, (numeric) The time offset in seconds (deprecated, always 0)\n" " \"pingtime\": n, (numeric) ping time\n" @@ -146,6 +147,8 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) obj.push_back(Pair("lastrecv", stats.nLastRecv)); obj.push_back(Pair("bytessent", stats.nSendBytes)); obj.push_back(Pair("bytesrecv", stats.nRecvBytes)); + obj.push_back(Pair("relaytxes", stats.fRelayTxes)); + obj.push_back(Pair("conntime", stats.nTimeConnected)); obj.push_back(Pair("timeoffset", 0)); obj.push_back(Pair("pingtime", stats.dPingTime)); From d977345b26e53409150a7c9a844c389d96e8052e Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 15 May 2021 12:15:00 -0400 Subject: [PATCH 02/42] Specify that cleanwallettransactions only works on utxos, not zutxos --- src/wallet/rpcwallet.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 1b90c56a5..4da6204e6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1103,7 +1103,7 @@ UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubK if (fHelp || params.size() > 1 ) throw runtime_error( "cleanwallettransactions \"txid\"\n" - "\nRemove all txs that are spent. You can clear all txs bar one, by specifiying a txid.\n" + "\nRemove all transparent UTXOs that are spent. You can clear all transactions bar one, by specifiying a txid.\n" "\nPlease backup your wallet.dat before running this command.\n" "\nArguments:\n" "1. \"txid\" (string, optional) The transaction id to keep.\n" @@ -1133,9 +1133,7 @@ UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubK if ( !pwalletMain->IsMine(tmp_tx) ) { throw runtime_error("\nThe transaction is not yours!\n"); - } - else - { + } else { for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; @@ -1145,14 +1143,10 @@ UniValue cleanwallettransactions(const UniValue& params, bool fHelp, const CPubK } } } - } - else - { + } else { throw runtime_error("\nThe transaction could not be found!\n"); } - } - else - { + } else { // get all locked utxos to relock them later. vector vLockedUTXO; pwalletMain->ListLockedCoins(vLockedUTXO); From 4db320355b6408e4dbec91ba825eeebd1eb31880 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 19 May 2021 10:51:07 -0400 Subject: [PATCH 03/42] Small optimizations during rescanning and ChainTip() --- src/wallet/wallet.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 0a848ff33..b72e96386 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -480,13 +480,19 @@ void CWallet::ChainTip(const CBlockIndex *pindex, pblock->GetBlockTime() > GetTime() - 144*ASSETCHAINS_BLOCKTIME) { BuildWitnessCache(pindex, false); - RunSaplingConsolidation(pindex->GetHeight()); - DeleteWalletTransactions(pindex); + if (fSaplingConsolidationEnabled) { + RunSaplingConsolidation(pindex->GetHeight()); + } + if (fTxDeleteEnabled) { + DeleteWalletTransactions(pindex); + } } else { //Build initial witnesses on every block BuildWitnessCache(pindex, true); - if (initialDownloadCheck && pindex->GetHeight() % fDeleteInterval == 0) { - DeleteWalletTransactions(pindex); + if (fTxDeleteEnabled) { + if (initialDownloadCheck && pindex->GetHeight() % fDeleteInterval == 0) { + DeleteWalletTransactions(pindex); + } } } } else { @@ -1122,6 +1128,7 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly) nd->witnessHeight = pblockindex->GetHeight(); } } + } } @@ -2734,8 +2741,10 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) BuildWitnessCache(pindex, true); //Delete Transactions - if (pindex->GetHeight() % fDeleteInterval == 0) - DeleteWalletTransactions(pindex); + if (fTxDeleteEnabled) { + if (pindex->GetHeight() % fDeleteInterval == 0) + DeleteWalletTransactions(pindex); + } if (GetTime() >= nNow + 60) { nNow = GetTime(); From 379679556607614e82ec7fbbaf5c37373c50ce96 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 19 May 2021 12:04:04 -0400 Subject: [PATCH 04/42] Allow help, z_listaddresses, listaddresses, z_exportkey and dumpprivkey during RPC warmup --- src/rpc/server.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 5ae2c88e1..bf99a5b78 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -825,9 +825,13 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms { LOCK(cs_rpcWarmup); if (fRPCInWarmup) { - // hush-cli stop is the only valid RPC command during warmup - // We don't know if we have valid blocks or wallet yet, nothing else is safe - if (pcmd->name != "stop") { + // Most RPCs are unsafe to run during warmup, but stop+help are fine + // Others may not have data loaded yet, such as wallet details, but + // those RPCs are written defensively to deal with that. Allowing these + // few RPCs means we can see our addresses and make private key backups + // while a very long wallet rescan is happening + if (pcmd->name != "stop" && pcmd->name != "help" && pcmd->name != "z_listaddresses" && pcmd->name != "z_exportkey" && + pcmd->name != "listaddresses" && pcmd->name != "dumpprivkey" ) { throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus); } } From 84f79558d5d7b9a336eb7401b17ec4488ee1026e Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 19 May 2021 21:32:36 -0400 Subject: [PATCH 05/42] Desprout --- src/wallet/wallet.cpp | 6 ------ src/wallet/wallet.h | 4 ---- 2 files changed, 10 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b72e96386..f6d2d7f57 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2385,12 +2385,6 @@ bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb) return pwalletdb->WriteTx(GetHash(), *this); } -void CWallet::WitnessNoteCommitment(std::vector commitments, - std::vector>& witnesses, - uint256 &final_anchor) -{ -} - /** * Reorder the transactions based on block hieght and block index. * Transactions can get out of order when they are deleted and subsequently diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d78834727..965ab5b22 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1122,10 +1122,6 @@ public: void SyncTransaction(const CTransaction& tx, const CBlock* pblock); void RescanWallet(); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); - void WitnessNoteCommitment( - std::vector commitments, - std::vector>& witnesses, - uint256 &final_anchor); void ReorderWalletTransactions(std::map, CWalletTx*> &mapSorted, int64_t &maxOrderPos); void UpdateWalletTransactionOrder(std::map, CWalletTx*> &mapSorted, bool resetOrder); void DeleteTransactions(std::vector &removeTxs); From d3f12a6b7f437652bb53b75c10d84d87dbe03986 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 14 Jun 2021 21:05:20 -0400 Subject: [PATCH 06/42] desprout --- src/main.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 8887292d4..2d352d12d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4429,13 +4429,6 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl // pool. So we invert the sign here. saplingValue += -tx.valueBalance; - /* - for (auto js : tx.vjoinsplit) { - sproutValue += js.vpub_old; - sproutValue -= js.vpub_new; - } - */ - // Ignore following stats unless -zindex enabled if (!fZindex) continue; From 8c25b745b3eb1a70ed965d9db97b9d103b1fa29d Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 15 Jun 2021 00:47:56 -0400 Subject: [PATCH 07/42] 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 08/42] 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 09/42] 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 10/42] 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 11/42] 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 12/42] 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 13/42] 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 14/42] 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 15/42] 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 16/42] 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 e20315ef213606b12674c361be61c71841f79410 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 18 Jun 2021 18:31:20 +0000 Subject: [PATCH 17/42] checkpoints --- src/chainparams.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 5 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 9cd9bb7f9..c6dd5f1f9 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -783,11 +783,79 @@ void *chainparams_commandline() { (492000, uint256S("0x00000013bbbff98ddab19a3178a0088a20628791e94963e5d1ea635015dfa9c6")) (493000, uint256S("0x00000001ed829c061ba14f6953e79d99577079adf5526f1e43e6dc9d9f9571bf")) (494000, uint256S("0x00000018dfeced2d1584a1003fefa4349810239bade096e53b4fa6bbc38a1685")) - (495000, uint256S("0x0000001816af55724cd49c0bfe02c9eac29b4a73db2b7d868b958218a03e6c94")) - (496000, uint256S("0x000000007e2019c5246db5a75122c6826822fa154d68a51eee2ff23f54ec668e")), - (int64_t) 1618760194, // time of last checkpointed block - (int64_t) 842496, // total txs - (double) 1812 // txs in the last day before block 496013 + (495000, uint256S("0x0000001816af55724cd49c0bfe02c9eac29b4a73db2b7d868b958218a03e6c94")) + (496000, uint256S("0x000000007e2019c5246db5a75122c6826822fa154d68a51eee2ff23f54ec668e")) + (497000, uint256S("0x0000000aa5803c0825cfa1a34227d0ecb80be191674365a372f71611eacdc742")) + (498000, uint256S("0x000000166385022d4b4ade0921a5f6c7d4aec56257cd679f7c441aeb0552b28c")) + (499000, uint256S("0x0000002ce5e48efb664e936c9551b2781c742416e519d3a023d087036519507b")) + (500000, uint256S("0x0000000cdfe9389bde0e9f1d649dd2f19ee69d765b00907aa681c3cdaad0bdb6")) + (501000, uint256S("0x00000028736fd4ce6995a46d217c0022d2882165b5f716e94f255877c73f474a")) + (502000, uint256S("0x000000459520215ade21db91a83ad47a806320ba3e290d686149bcf5672e132a")) + (503000, uint256S("0x000000086aee5827d0254e1176a4dfd5c8a7958ee1f61458bdb1eb4d6ffbc131")) + (504000, uint256S("0x000000474906b6ad537fe14eca1316c7be23f181bc554a2244c97634a6d361a7")) + (505000, uint256S("0x00000035db569efc139988b7d506529bb482284bf2dfc40060159b321883974d")) + (506000, uint256S("0x0000000c55ddd54e1f0aa6a59abe774f0e14501743c2594184772031f5bf51fd")) + (507000, uint256S("0x000000061ca0ea34d5d3ddd5d8ceb0dcf9a0720483efd98155c0aa3774387e60")) + (508000, uint256S("0x00000004bd6cdfbbee3945b897c4d6b6f49199d788151fe5536417d31d2f36ab")) + (509000, uint256S("0x0000000b73f9dd08528827a8224decf6635462d2adabac9301e5c17b7a24a5f4")) + (510000, uint256S("0x00000004c41a5b61302564abc741195c915fdf9edd12669f93ac5d4443613664")) + (511000, uint256S("0x000000094319bb7199e5697e458520e95639dcec5180d4442e1470f48feaf125")) + (512000, uint256S("0x00000014516f2d52467edd913c52e1742ca8a767debd9294bbbf8f39bdbae506")) + (513000, uint256S("0x000000177739b5379d196b74faeaabf35dbb9d3f6f9e172f659f68b3288a71c3")) + (514000, uint256S("0x0000000940533509d21f249ab0b0144923e65050a24dbf53863c9c07fd21fd6b")) + (515000, uint256S("0x000000007d256fc4cbfff1c05f83550b8dfdf093b060a98fafac6a090e349bc1")) + (516000, uint256S("0x000000029ee7abc14842e22b4f3e7e3c640c55fa2a898773c83ff34ceb2a5482")) + (517000, uint256S("0x00000019ca7705b4a8b35ae1aa4071401ed1de7449306ef8a34716637f43c2f1")) + (518000, uint256S("0x00000013f4aa06fca6c2a57e80c3950d0e7613f3bcba0b52887d4c7579e5b20a")) + (519000, uint256S("0x0000000b7d1e4efbbb38c91e838a50876be93a6549fdaeb534ec1d8657117e69")) + (520000, uint256S("0x00000000c2fb98b56bf9c549406710b57308081663230a477c7b5983720a456a")) + (521000, uint256S("0x0000000d48660709c9fd60f01b71260e0e6ba3875cdb109b7b037ec6b80f3098")) + (522000, uint256S("0x00000019d0ad6bdebc9d39a5b9a6ae4d844b45bbfcdd97885841a1d8033c956f")) + (523000, uint256S("0x000000121da004ec14c89b67151439765a19aadbdf4d4feca701cce7c3820efb")) + (524000, uint256S("0x00000003d3445c4cb6e980751cd8119679d572f57bbaa3b9c9114e397841827e")) + (525000, uint256S("0x0000000b2a079f083c86f9ab8b0f73dc511c20f6aa44d7735f29409df966f026")) + (526000, uint256S("0x00000004d3ae427a98336ee4bc5e60f00ebd4c88f9ffdd18003f17535465888a")) + (527000, uint256S("0x000000057e5cb13f42332f59b6c2d6f333369b8e4d9bdf6fa9bb441e2ddb5c51")) + (528000, uint256S("0x000000045f51825c19aab9d1d620d7073c2114ccf3e40f63d66c729c71c2bc05")) + (529000, uint256S("0x000000116ac2795cdbde2d3af6d804d9dbf445d2ed12d7cf13c155540f10c119")) + (530000, uint256S("0x0000000be4932b469923d826991810109f2c2ca50d5fa0133c765b5ab96bf315")) + (531000, uint256S("0x0000000a7fdd8ce073da5d95fcbefba5d0366c9b834cac914889108094d0cd18")) + (532000, uint256S("0x0000000600d2ea28f32220c054e2ae66ec8471a2f755ef219a0c81e4a4296135")) + (533000, uint256S("0x0000000a5f4a460970f6dcd3a271315f936648c854c1a7bb251dbc7996f90e92")) + (534000, uint256S("0x00000009b5d0615eb98f06820cc6d66af542b8bbde0cabe5b54b6e7625e77803")) + (535000, uint256S("0x0000000ac06f5d79b927f2dfb54eecd72f9ada28fa59092f5c3c83627b281605")) + (536000, uint256S("0x000000037a51adb2cccf29b9c164386c8418959db16606b70a1389fb8755829f")) + (537000, uint256S("0x0000000a129157792e233e233f85693625abb14be90362ff727ab97e8d5ec340")) + (538000, uint256S("0x00000015e13085045c090a51e9c1114749fa7b465009f2ad70ff278d9ae05b5c")) + (539000, uint256S("0x00000001953384069e477f7e1839dc0498cbeb951adb32bcbf3b96ef487fce4a")) + (540000, uint256S("0x0000000281246b5d2e845aa711b6af76c8cc0d1f39ba25fe414f83bbe47544bb")) + (541000, uint256S("0x0000000f27b777a942d6317438836258c4e34bd3761736a2b32cc2b7c8305d71")) + (542000, uint256S("0x00000005d4667fb45a862d91ba843acbaee033915bf75536c67aeca1a2a3a5ff")) + (543000, uint256S("0x0000000509b08619049b1aec8e715d971b8dbc2175acf7874a37b9ce13dfb137")) + (544000, uint256S("0x0000000582563d79bf72a925ae3bc5c6f0eacbdb317c92fa89eb56d570427fd7")) + (545000, uint256S("0x0000000ff9df3d3a00d682f069819acbc5697b42da69a78f6e07486ac68f0e49")) + (546000, uint256S("0x00000004653460c603fa7a70292a85e286272b587f0b9cea7e73b765e8b0ef7b")) + (547000, uint256S("0x000000074c5f411190c5bf788a37a00506935015df4872cc5471416abadb757d")) + (548000, uint256S("0x00000005444a4ecd1eea940ad5395f2f7839967ee5b01be4a9b68755de4395ac")) + (549000, uint256S("0x0000000216eafee0e40374b8e8db63118cb4e3adc3159068bdafff1f0e0d9deb")) + (550000, uint256S("0x0000000056b84bc88604b9df668b60c020a6926b2dfdcd09955e5d8d3e7a5ca7")) + (551000, uint256S("0x0000000adaaeb79c5c6c49038d7206f88d5b4ecaaf21aaca09b5a7d548f76b25")) + (552000, uint256S("0x00000004185669b566e62cbebc9c50930c8ae0d5c42f23280262a7f55b726553")) + (553000, uint256S("0x00000010112434cdb0203a053e0c22ef16b9d39b8feed2328d7ff97013b216be")) + (554000, uint256S("0x00000006dacee96c0f48fc7250c71cc1e746befa84af8cd2ed0499d8d24cc6cb")) + (555000, uint256S("0x00000001b3b2c149029d5a2e7cedb0683c97692a52cbc91bb532cb78bbcadcc0")) + (556000, uint256S("0x0000000397bdd61939cc3d2c39360c5e3713ef9dd82b8cedac17075b8e177304")) + (557000, uint256S("0x0000000414bb81b82a2e71608086ac585dba19ca249067c9e967d6f44a1d3163")) + (558000, uint256S("0x00000003516d27423b1b5b60eab97d425e7be3f08f14bafd935666b1e955608e")) + (559000, uint256S("0x00000005c44ef4543da5924e65f0fd2d2c8fe926b2f3995b83ccfd1463b443d7")) + (560000, uint256S("0x00000002eb33454ba48e61a50351686115c47cb59b8fb0496432ad58e0484acf")) + (561000, uint256S("0x00000004172d5940c07ec6d493e410fbab8a05dc73e350505e1540d7336eb353")) + (562000, uint256S("0x00000000d9caaf66ad7782046886d3bfdf966c0a015dbae64042cd0c35e516e4")) + (563000, uint256S("0x000000000d953e53c65145bfb41ba544a9ce9e5432c9ed8eabd39873dfcb8ab0")) + (564000, uint256S("0x0000000d49258678c42bc2ea6f9e5d1206c578da8dc564d1a6114ce68bf77817")), + (int64_t) 1623979514, // time of last checkpointed block + (int64_t) 922687, // total txs + (double) 1219 // txs in the last day before block 564690 }; } else { From 0d24faa39ac04b9774eae4c6e5c04287d3ae4a34 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 18 Jun 2021 17:27:18 -0400 Subject: [PATCH 18/42] Allow getpeerinfo during rpc warmup --- src/rpc/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index bf99a5b78..e999cc423 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -831,7 +831,7 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms // few RPCs means we can see our addresses and make private key backups // while a very long wallet rescan is happening if (pcmd->name != "stop" && pcmd->name != "help" && pcmd->name != "z_listaddresses" && pcmd->name != "z_exportkey" && - pcmd->name != "listaddresses" && pcmd->name != "dumpprivkey" ) { + pcmd->name != "listaddresses" && pcmd->name != "dumpprivkey" && pcmd->name != "getpeerinfo" ) { throw JSONRPCError(RPC_IN_WARMUP, rpcWarmupStatus); } } From e6a7423029881d205f6b6c1305adc7922486c0f5 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 18 Jun 2021 19:27:06 -0400 Subject: [PATCH 19/42] 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 4418d1fb6e9f1637ea69416d22dcc7db4b382262 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 19:18:44 +0000 Subject: [PATCH 20/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 53 ------------------------------------------ 1 file changed, 53 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index c22ae3fe8..c4aa7e9c2 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -36,59 +36,6 @@ class Class } ``` -Doxygen comments ------------------ - -To facilitate the generation of documentation, use doxygen-compatible comment blocks for functions, methods and fields. - -For example, to describe a function use: -```c++ -/** - * ... text ... - * @param[in] arg1 A description - * @param[in] arg2 Another argument description - * @pre Precondition for function... - */ -bool function(int arg1, const char *arg2) -``` -A complete list of `@xxx` commands can be found at http://www.stack.nl/~dimitri/doxygen/manual/commands.html. -As Doxygen recognizes the comments by the delimiters (`/**` and `*/` in this case), you don't -*need* to provide any commands for a comment to be valid; just a description text is fine. - -To describe a class use the same construct above the class definition: -```c++ -/** - * Alerts are for notifying old versions if they become too obsolete and - * need to upgrade. The message is displayed in the status bar. - * @see GetWarnings() - */ -class CAlert -{ -``` - -To describe a member or variable use: -```c++ -int var; //!< Detailed description after the member -``` - -Also OK: -```c++ -/// -/// ... text ... -/// -bool function2(int arg1, const char *arg2) -``` - -Not OK (used plenty in the current source, but not picked up): -```c++ -// -// ... text ... -// -``` - -A full list of comment syntaxes picked up by doxygen can be found at http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html, -but if possible use one of the above styles. - Development tips and tricks --------------------------- From 723a537e64eca17ad58d44b0ef5c2694cf1edf80 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 19:27:29 +0000 Subject: [PATCH 21/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index c4aa7e9c2..727f42fd8 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -1,5 +1,32 @@ -Coding -==================== +# Testing a Branch + +To test a branch called `zindexdb` with a fresh clone + +``` +git clone https://git.hush.is/hush/hush3 hush3-testing +cd hush3-testing +git checkout zindexdb +# you need 2GB RAM free per -jN +./build.sh -j2; make; make; make # this deals with build-system race condition bugs + +# we want to test a fresh sync, so backup current data +mv ~/.komodo/{HUSH3,HUSH3-backup} +mkdir ~/.komodo/HUSH3 + +# This is optional but will likely speed up sync time greatly +cp ~/.komodo/{HUSH3-backup,HUSH3}/peers.dat + +echo "zindex=1" >> ~/.komodo/HUSH3/HUSH3.conf + +# This log file is helpful for debugging more and will contain a history of the +# size of the anonset at every block height +./src/hushd &> hushd.log & +# to look at the log +tail -f hushd.log +``` + + +# Coding Various coding styles have been used during the history of the codebase, and the result is not very consistent. However, we're now trying to converge to From f780af1c6ac38ee068a15935bb76c6d58ada8653 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 19:34:48 +0000 Subject: [PATCH 22/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 727f42fd8..68e32a9a9 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -25,7 +25,27 @@ echo "zindex=1" >> ~/.komodo/HUSH3/HUSH3.conf tail -f hushd.log ``` +To get a CSV file of the value of the anonset size for every block height: +``` +grep anonset hushd.log | cut -d= -f2 +``` +This only needs to be calculated once, if we can verify it's correct. These are historical values that do not change. These values should match on all nodes: + +``` +46913,2547,2253,294 +46914,2549,2254,295 +46915,2549,2254,295 +46916,2553,2257,296 +46917,2553,2257,296 +``` + +We should also check a recent block height to verify it's working correctly. The big "test" for this `zindexdb` branch is: + + * If you stop a node, and restart, are the stats from `getchaintxtstats` correct, i.e. the anonset stats? For instance, `shielded_pool_size` should be close to 500000, if it's close to or exactly 0, something is wrong. + * Is there a new file called `zindex.dat` in `~/.komodo/HUSH3/` ? + * Is `zindex.dat` 149 bytes ? + # Coding Various coding styles have been used during the history of the codebase, From 8485e334eed72eafa035693ef67a832a3b5ca137 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 20:33:18 +0000 Subject: [PATCH 23/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 68e32a9a9..3633c9e95 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -13,11 +13,14 @@ git checkout zindexdb mv ~/.komodo/{HUSH3,HUSH3-backup} mkdir ~/.komodo/HUSH3 +# Use your previous config as a base +cp ~/.komodo/{HUSH3,HUSH3-backup}/HUSH3.conf +# Add zindex to your node +echo "zindex=1" >> ~/.komodo/HUSH3/HUSH3.conf + # This is optional but will likely speed up sync time greatly cp ~/.komodo/{HUSH3-backup,HUSH3}/peers.dat -echo "zindex=1" >> ~/.komodo/HUSH3/HUSH3.conf - # This log file is helpful for debugging more and will contain a history of the # size of the anonset at every block height ./src/hushd &> hushd.log & From e4e1077d994e799119994ef555146d9e80d87147 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 20:51:05 +0000 Subject: [PATCH 24/42] Add 'doc/privacy-basics.md' --- doc/privacy-basics.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 doc/privacy-basics.md diff --git a/doc/privacy-basics.md b/doc/privacy-basics.md new file mode 100644 index 000000000..06c792fa0 --- /dev/null +++ b/doc/privacy-basics.md @@ -0,0 +1,8 @@ +# Privacy Basics + + +## Browser Tips + +Firefox is likely the best browser for privacy. Use this to improve + customize: + +http://ebin.city/~werwolf/posts/firefox-hardening-guide/ \ No newline at end of file From d358971963674601c41e34d2fb975369e3948d3e Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 20:58:04 +0000 Subject: [PATCH 25/42] Update 'doc/privacy-basics.md' --- doc/privacy-basics.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/privacy-basics.md b/doc/privacy-basics.md index 06c792fa0..701d5de20 100644 --- a/doc/privacy-basics.md +++ b/doc/privacy-basics.md @@ -1,8 +1,10 @@ # Privacy Basics - ## Browser Tips Firefox is likely the best browser for privacy. Use this to improve + customize: -http://ebin.city/~werwolf/posts/firefox-hardening-guide/ \ No newline at end of file +http://ebin.city/~werwolf/posts/firefox-hardening-guide/ + +Those are helpful when NOT using a Tor browser. If you are using Tor Browser (which is a fork of Firefox), then you do not need the above guide and should probably use the default that Tor Browser devs provide. + From 559eaa71032ae1cf03101bec37bbb46561b680f0 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 20:58:50 +0000 Subject: [PATCH 26/42] Update 'doc/privacy-basics.md' --- doc/privacy-basics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/privacy-basics.md b/doc/privacy-basics.md index 701d5de20..2198a1cb9 100644 --- a/doc/privacy-basics.md +++ b/doc/privacy-basics.md @@ -4,7 +4,7 @@ Firefox is likely the best browser for privacy. Use this to improve + customize: -http://ebin.city/~werwolf/posts/firefox-hardening-guide/ +https://ebin.city/~werwolf/posts/firefox-hardening-guide/ Those are helpful when NOT using a Tor browser. If you are using Tor Browser (which is a fork of Firefox), then you do not need the above guide and should probably use the default that Tor Browser devs provide. From 947173a2ca59aa7b7657b838157df1479ee336ef Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 21:00:24 +0000 Subject: [PATCH 27/42] Update 'doc/privacy-basics.md' --- doc/privacy-basics.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/privacy-basics.md b/doc/privacy-basics.md index 2198a1cb9..b231520c4 100644 --- a/doc/privacy-basics.md +++ b/doc/privacy-basics.md @@ -6,5 +6,7 @@ Firefox is likely the best browser for privacy. Use this to improve + customize: https://ebin.city/~werwolf/posts/firefox-hardening-guide/ +which is a guide around using and customizing the [Arkenfox](https://github.com/arkenfox/user.js/wiki/1.3-Implementation) user.js project + Those are helpful when NOT using a Tor browser. If you are using Tor Browser (which is a fork of Firefox), then you do not need the above guide and should probably use the default that Tor Browser devs provide. From 4bba0e2a5867385c92f3e071acadab003d7f4a11 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 21:28:55 +0000 Subject: [PATCH 28/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 3633c9e95..618d45ffe 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -10,14 +10,16 @@ git checkout zindexdb ./build.sh -j2; make; make; make # this deals with build-system race condition bugs # we want to test a fresh sync, so backup current data -mv ~/.komodo/{HUSH3,HUSH3-backup} +TIME=`perl -e "print time"` +mv ~/.komodo/{HUSH3,HUSH3-backup-$TIME} mkdir ~/.komodo/HUSH3 # Use your previous config as a base -cp ~/.komodo/{HUSH3,HUSH3-backup}/HUSH3.conf +cp ~/.komodo/{HUSH3-backup-$TIME,HUSH3}/HUSH3.conf # Add zindex to your node echo "zindex=1" >> ~/.komodo/HUSH3/HUSH3.conf + # This is optional but will likely speed up sync time greatly cp ~/.komodo/{HUSH3-backup,HUSH3}/peers.dat From 7a0bdd79c800efef2a88635b6ab82d5ebad97ea6 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 17:43:47 -0400 Subject: [PATCH 29/42] . --- 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 30/42] . --- 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 bdf30a90a9a5e8987dd6d82d4481df5eb0d60eab Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 21:53:01 +0000 Subject: [PATCH 31/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 618d45ffe..b54e2b2f9 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -32,7 +32,7 @@ tail -f hushd.log To get a CSV file of the value of the anonset size for every block height: ``` -grep anonset hushd.log | cut -d= -f2 +grep 'setting zstats' hushd.log | cut -d= -f2 ``` This only needs to be calculated once, if we can verify it's correct. These are historical values that do not change. These values should match on all nodes: From e1a5d909a0d058729a1cd2db63c1efa250f6b549 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 17:59:25 -0400 Subject: [PATCH 32/42] . --- 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 ea41d0428686169a9856efe5889e3ef86d528011 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 22:02:30 +0000 Subject: [PATCH 33/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index b54e2b2f9..2533e1ac5 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -32,10 +32,13 @@ tail -f hushd.log To get a CSV file of the value of the anonset size for every block height: ``` -grep 'setting zstats' hushd.log | cut -d= -f2 +grep 'setting zstats' hushd.log | cut -d= -f2 > anonset.csv ``` -This only needs to be calculated once, if we can verify it's correct. These are historical values that do not change. These values should match on all nodes: +This only needs to be calculated once, if we can verify it's correct. These are historical values that do not change. The goal is a web page with a historical view of the HUSH anonset size. + + +These values should match on all nodes: ``` 46913,2547,2253,294 From add73be7b53b9ce4e8025db1d9673965927c1b43 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 21 Jun 2021 22:14:01 +0000 Subject: [PATCH 34/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 2533e1ac5..3ae91bb41 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -32,7 +32,7 @@ tail -f hushd.log To get a CSV file of the value of the anonset size for every block height: ``` -grep 'setting zstats' hushd.log | cut -d= -f2 > anonset.csv +grep anonset hushd.log | cut -d= -f2 > anonset.csv ``` This only needs to be calculated once, if we can verify it's correct. These are historical values that do not change. The goal is a web page with a historical view of the HUSH anonset size. From 0a4b8ed5bfaba2695aba27153d77cc7d11aa0989 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 22 Jun 2021 00:38:02 +0000 Subject: [PATCH 35/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 3ae91bb41..12a1dc9f9 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -1,8 +1,32 @@ -# Testing a Branch +# Fresh sync -To test a branch called `zindexdb` with a fresh clone +Many times, you will want to do a "fresh sync" test, to verify code works when syncing from the genesis block, which is a different code path than a "partial sync" which means you already have part of blockchain history and are "catching up" to get in sync. + +A "fresh sync" goes thru the Initial Blockchain Download (IBD) optimized codepath and is often faster than than rescanning all of history. Both ways of testing any important change should be done. + +One way is: ``` +cd ~/.komodo/HUSH3 +rm blocks chainstate database notarizations hushstate +``` + +If you are using `zindex=1` then you need to also delete zindex.dat + +``` +cd ~/.komodo/HUSH3 +rm zindex.dat blocks chainstate database notarizations hushstate +``` + +It's possible to confused hush if you ran old code, stop, restart, and then write out zindex.dat that is incorrect, with later hushds will load from disk and believe. + + +# Testing a Branch + +To test a branch called `zindexdb` with a fresh clone: + +``` +# TODO: this should probably become a script in ./contrib git clone https://git.hush.is/hush/hush3 hush3-testing cd hush3-testing git checkout zindexdb From c614e5adb3214e290154902eacf6b27e595ac676 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 22 Jun 2021 00:41:34 +0000 Subject: [PATCH 36/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 12a1dc9f9..e73e8bce9 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -2,9 +2,11 @@ Many times, you will want to do a "fresh sync" test, to verify code works when syncing from the genesis block, which is a different code path than a "partial sync" which means you already have part of blockchain history and are "catching up" to get in sync. -A "fresh sync" goes thru the Initial Blockchain Download (IBD) optimized codepath and is often faster than than rescanning all of history. Both ways of testing any important change should be done. +A "fresh sync" goes thru the Initial Blockchain Download (IBD) optimized codepath and is often faster than than rescanning all of history. Fresh sync and partial sync testing any important change should be done for all important changes. -One way is: +A fresh sync preserves peers.dat, so it will always be faster than a "fresh clone", which has to learn enough p2p peers to being syncing, which can often add many minutes to completing a sync. When code related to peers.dat changes (such in the `p2p` branch) then doing a fresh clone is needed to fully test it. + +One way fresh sync is: ``` cd ~/.komodo/HUSH3 From bad7adb778806dbf2196aa113cf1403b4d847118 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 22 Jun 2021 00:42:20 +0000 Subject: [PATCH 37/42] Update 'doc/developer-notes.md' --- doc/developer-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index e73e8bce9..26be1e262 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -6,7 +6,7 @@ A "fresh sync" goes thru the Initial Blockchain Download (IBD) optimized codepat A fresh sync preserves peers.dat, so it will always be faster than a "fresh clone", which has to learn enough p2p peers to being syncing, which can often add many minutes to completing a sync. When code related to peers.dat changes (such in the `p2p` branch) then doing a fresh clone is needed to fully test it. -One way fresh sync is: +One way to do a fresh sync is: ``` cd ~/.komodo/HUSH3 From e829822041831948543e3bbc25edeb0179aa0d55 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 26 Jun 2021 12:27:38 -0400 Subject: [PATCH 38/42] 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; From 2c315965d7ddd486d76d726e02deeb3356e6bb2d Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 26 Jun 2021 13:54:57 -0400 Subject: [PATCH 39/42] Log data about clearing witness cache --- src/wallet/wallet.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f6d2d7f57..3bc3b99cd 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -908,12 +908,15 @@ int64_t CWallet::NullifierCount() void CWallet::ClearNoteWitnessCache() { LOCK(cs_wallet); + int notes = 0; for (std::pair& wtxItem : mapWallet) { for (mapSaplingNoteData_t::value_type& item : wtxItem.second.mapSaplingNoteData) { item.second.witnesses.clear(); item.second.witnessHeight = -1; + notes++; } } + LogPrintf("%s: Cleared witness data from %d wallet items and %d SaplingNotes\n", __func__, mapWallet.size(), notes); } void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex) From b7be25e2d5f4fa33d282d817263d1363bdfd5686 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 26 Jun 2021 14:42:40 -0400 Subject: [PATCH 40/42] Thanks to hellcatz for this patch --- src/main.cpp | 2 +- src/rpc/net.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 94b41fe5a..ec02f3a79 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4025,7 +4025,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); - if ( HUSH_LONGESTCHAIN != 0 && (pindexNew->GetHeight() == HUSH_LONGESTCHAIN || pindexNew->GetHeight() == HUSH_LONGESTCHAIN+1) ) + if ( HUSH_LONGESTCHAIN != 0 && (pindexNew->GetHeight() >= HUSH_LONGESTCHAIN )) HUSH_INSYNC = (int32_t)pindexNew->GetHeight(); else HUSH_INSYNC = 0; //fprintf(stderr,"connect.%d insync.%d ASSETCHAINS_SAPLING.%d\n",(int32_t)pindexNew->GetHeight(),HUSH_INSYNC,ASSETCHAINS_SAPLING); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 6ea9819a8..4533b0196 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -180,15 +180,15 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) } int32_t HUSH_LONGESTCHAIN; +static int32_t hush_longest_depth = 0; int32_t hush_longestchain() { - static int32_t depth; int32_t ht,n=0,num=0,maxheight=0,height = 0; - if ( depth < 0 ) - depth = 0; - if ( depth == 0 ) + if ( hush_longest_depth < 0 ) + hush_longest_depth = 0; + if ( hush_longest_depth == 0 ) { - depth++; + hush_longest_depth++; vector vstats; { //LOCK(cs_main); @@ -215,7 +215,7 @@ int32_t hush_longestchain() if ( ht > height ) height = ht; } - depth--; + hush_longest_depth--; if ( num > (n >> 1) ) { if ( 0 && height != HUSH_LONGESTCHAIN ) From 21333ce153c6509b6720c05c8331078a25789e97 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 26 Jun 2021 15:49:47 -0400 Subject: [PATCH 41/42] Add -rescanheight --- src/init.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 2624945bf..ab4e1c0d8 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -467,6 +467,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-opretmintxfee=", strprintf(_("Minimum fee (in %s/kB) to allow for OP_RETURN transactions (default: %s)"), CURRENCY_UNIT, 400000 )); strUsage += HelpMessageOpt("-paytxfee=", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"), CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK()))); strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup")); + strUsage += HelpMessageOpt("-rescanheight", _("Rescan from specified height when rescan=1 on startup")); strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup")); strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0)); strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1)); @@ -2074,6 +2075,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) { pwalletMain->ClearNoteWitnessCache(); pindexRescan = chainActive.Genesis(); + int rescanHeight = GetArg("-rescanheight", 0); + if (rescanHeight > 0) { + if (rescanHeight > chainActive.Tip()->GetHeight()) { + pindexRescan = chainActive.Tip(); + } else { + pindexRescan = chainActive[rescanHeight]; + } + } } else { CWalletDB walletdb(strWalletFile); CBlockLocator locator; From 172fefeb7baddcb11160aa9d6ffa22bfbdf62324 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 26 Jun 2021 20:37:57 -0400 Subject: [PATCH 42/42] Sometimes you need to say plz --- src/net.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/net.cpp b/src/net.cpp index 218f766d3..d7833b4a0 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -51,6 +51,8 @@ using namespace hush; // This is every 2 blocks, on avg, on HUSH3 #define DUMP_ZINDEX_INTERVAL 150 +#define CHECK_PLZ_STOP_INTERVAL 120 + #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 #endif @@ -92,6 +94,7 @@ namespace { }; } + // Global state variables extern uint16_t ASSETCHAINS_P2PPORT; extern char SMART_CHAIN_SYMBOL[65]; @@ -111,6 +114,8 @@ bool fAddressesInitialized = false; std::string strSubVersion; TLSManager tlsmanager = TLSManager(); +extern void StartShutdown(); + vector vNodes; CCriticalSection cs_vNodes; map mapRelay; @@ -1413,6 +1418,18 @@ void DumpZindexStats() LogPrintf("Flushed stats at height %li to zindex.dat %dms\n", zstats.Height(), GetTimeMillis() - nStart); } +void CheckIfWeShouldStop() +{ + // If the RPC interface is "stuck", such as filling up with deadlocks + // and cannot process any more requests, the only option was to kill the full node. + // This is a disk-based method where a node can realize it should stop, and which + // can help avoid extremely long rescans + if(boost::filesystem::exists(GetDataDir() / "plz_stop")) { + LogPrintf("%s: Found plz_stop file, shutting down...\n", __func__); + StartShutdown(); + } +} + void static ProcessOneShot() { string strDest; @@ -1925,6 +1942,9 @@ void static Discover(boost::thread_group& threadGroup) //extern CWallet pwalletMain; void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) { + + CheckIfWeShouldStop(); + if (fZindex) { uiInterface.InitMessage(_("Loading zindex stats...")); int64_t nStart = GetTimeMillis(); @@ -2014,6 +2034,8 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler) if (fZindex) { scheduler.scheduleEvery(&DumpZindexStats, DUMP_ZINDEX_INTERVAL); } + + scheduler.scheduleEvery(&CheckIfWeShouldStop, CHECK_PLZ_STOP_INTERVAL); } bool StopNode()