diff --git a/src/addrman.cpp b/src/addrman.cpp index ae5d5a50d..a16f0665f 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -478,6 +478,20 @@ CAddrInfo CAddrMan::Select_(bool newOnly) const int kRetriesBetweenSleep = 1000; const int kRetrySleepInterval = 100; // milliseconds + // Peer-selection tuning factors (networking heuristics, not consensus). + // On each rejected candidate the running chance factor is scaled up by this + // amount so the loop is guaranteed to eventually accept a peer. + const double kChanceFactorGrowth = 1.2; + // Candidates on unreachable networks are deprioritized to this fraction of + // their base chance. + const double kUnreachableDeprioritize = 0.25; + // Candidates that were just tried are deprioritized to this fraction of + // their base chance. + const double kJustTriedDeprioritize = 0.10; + // Fixed-point scale for the acceptance probability test: draw a random int in + // [0, kChanceScale) and accept if it falls below (factors * chance) * kChanceScale. + const int kChanceScale = 1 << 30; + if (newOnly && nNew == 0) return CAddrInfo(); @@ -513,15 +527,15 @@ CAddrInfo CAddrMan::Select_(bool newOnly) CAddrInfo& info = mapInfo[nId]; if (info.IsReachableNetwork()) { //deprioritize unreachable networks - fReachableFactor = 0.25; + fReachableFactor = kUnreachableDeprioritize; } if (info.IsJustTried()) { //deprioritize entries just tried - fJustTried = 0.10; + fJustTried = kJustTriedDeprioritize; } - if (RandomInt(1 << 30) < fChanceFactor * fReachableFactor * fJustTried * info.GetChance() * (1 << 30)) + if (RandomInt(kChanceScale) < fChanceFactor * fReachableFactor * fJustTried * info.GetChance() * kChanceScale) return info; - fChanceFactor *= 1.2; + fChanceFactor *= kChanceFactorGrowth; } } else { // use a new node @@ -553,15 +567,15 @@ CAddrInfo CAddrMan::Select_(bool newOnly) CAddrInfo& info = mapInfo[nId]; if (info.IsReachableNetwork()) { //deprioritize unreachable networks - fReachableFactor = 0.25; + fReachableFactor = kUnreachableDeprioritize; } if (info.IsJustTried()) { //deprioritize entries just tried - fJustTried = 0.10; + fJustTried = kJustTriedDeprioritize; } - if (RandomInt(1 << 30) < fChanceFactor * fReachableFactor * fJustTried * info.GetChance() * (1 << 30)) + if (RandomInt(kChanceScale) < fChanceFactor * fReachableFactor * fJustTried * info.GetChance() * kChanceScale) return info; - fChanceFactor *= 1.2; + fChanceFactor *= kChanceFactorGrowth; } } diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 0c7737234..eaf325b92 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -41,7 +41,11 @@ /// \cond INTERNAL #define CC_MAXVINS 1024 -#define CC_REQUIREMENTS_MSG (HUSH_NSPV_SUPERLITE?"to use CC contracts you need to nspv_login first\n":"to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n") +// NOTE: CryptoConditions (CC) contracts are inherited from the Komodo/Hush lineage and are +// largely vestigial on DragonX (ac_private=1 fully-shielded chain). This user-facing message +// still describes the legacy prerequisites for using CC contracts (nspv_login in superlite +// mode, or launching dragonxd with a valid -pubkey=). +#define CC_REQUIREMENTS_MSG (HUSH_NSPV_SUPERLITE?"to use CC contracts you need to nspv_login first\n":"to use CC contracts, you need to launch dragonxd with valid -pubkey= for an address in your wallet\n") #define SMALLVAL 0.000000000000001 #define SATOSHIDEN ((uint64_t)100000000L) @@ -58,7 +62,8 @@ struct CC_utxo /// \endcond -/// CC contract (Antara module) info structure that contains data used for signing and validation of cc contract transactions +/// CC (CryptoConditions) contract info structure that contains data used for signing and validation of cc contract transactions. +/// NOTE: the CC framework (historically called "Antara modules" in the Komodo/Hush lineage) is largely vestigial on DragonX. struct CCcontract_info { uint8_t evalcode; //!< cc contract eval code, set by CCinit function @@ -101,7 +106,7 @@ struct CCcontract_info bool(*validate)(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn); /// checks if the value of evalcode in cp object is present in the scriptSig parameter, - /// that is, the vin for this scriptSig will be validated by the cc contract (Antara module) defined by the eval code in this CCcontract_info object + /// that is, the vin for this scriptSig will be validated by the cc contract defined by the eval code in this CCcontract_info object /// @param scriptSig scriptSig to check\n /// Example: /// \code @@ -283,7 +288,7 @@ bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector &vin /// cp = CCinit(&C, EVAL_ASSETS); /// CPubKey ccAssetsPk = GetUnspendable(cp, ccAssetsPriv); /// \endcode -/// Now ccAssetsPk has Antara 'Assets' module global pubkey and ccAssetsPriv has its publicly available private key +/// Now ccAssetsPk has the 'Assets' CC module global pubkey and ccAssetsPriv has its publicly available private key CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv); // CCutils @@ -373,7 +378,7 @@ int64_t CCfullsupply(uint256 tokenid); /// @returns true if success bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); -/// Returns my pubkey, that is set by -pubkey hushd parameter +/// Returns my pubkey, that is set by the -pubkey dragonxd parameter /// @returns public key as byte array std::vector Mypubkey(); @@ -404,8 +409,8 @@ extern std::vector NULL_pubkeys; //!< constant value for use in functio std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector pubkeys = NULL_pubkeys); /// FinalizeCCTx is a very useful function that will properly sign both CC and normal inputs, adds normal change and might add an opreturn output. -/// This allows for Antara module transaction creation rpc functions to create an CMutableTransaction object, add the appropriate vins and vouts to it and use FinalizeCCTx to properly sign the transaction. -/// By using -addressindex=1 of hushd daemon, it allows tracking of all the CC addresses. +/// This allows for CC module transaction creation rpc functions to create an CMutableTransaction object, add the appropriate vins and vouts to it and use FinalizeCCTx to properly sign the transaction. +/// By using -addressindex=1 of the dragonxd daemon, it allows tracking of all the CC addresses. /// /// For signing the vins the function builds several default probe scriptPubKeys and checks them against the referred previous transactions (vintx) vouts. /// For cryptocondition vins the function creates a basic set of probe cryptconditions with mypk and module global pubkey, both for coins and tokens cases. @@ -473,7 +478,7 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3 int64_t AddNormalinputsLocal(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs); /// AddNormalinputs2 adds normal (not cc) inputs to the transaction object vin array for the specified total amount using utxos on my pubkey's TX_PUBKEY address (my pubkey is set by -pubkey command line parameter), to fund the transaction. -/// 'My pubkey' is the -pubkey parameter of hushd. +/// 'My pubkey' is the -pubkey parameter of dragonxd. /// @param mtx mutable transaction object /// @param total amount of inputs to add. If total equals to 0 the function does not add inputs but returns amount of all available normal inputs in the wallet /// @param maxinputs maximum number of inputs to add diff --git a/src/hush_nSPV_fullnode.h b/src/hush_nSPV_fullnode.h index e08ebdd7b..54756e259 100644 --- a/src/hush_nSPV_fullnode.h +++ b/src/hush_nSPV_fullnode.h @@ -38,7 +38,8 @@ struct NSPV_ntzargs int32_t NSPV_notarization_find(struct NSPV_ntzargs *args,int32_t height,int32_t dir) { int32_t ntzheight = 0; uint256 hashBlock; CTransaction tx; Notarization nota; char *symbol; std::vector opret; - symbol = (SMART_CHAIN_SYMBOL[0] == 0) ? (char *)"HUSH3" : SMART_CHAIN_SYMBOL; + // Notarization symbol; the empty-symbol fallback is dead on DragonX (SMART_CHAIN_SYMBOL is always "DRAGONX", never empty) + symbol = (SMART_CHAIN_SYMBOL[0] == 0) ? (char *)"DRAGONX" : SMART_CHAIN_SYMBOL; memset(args,0,sizeof(*args)); if ( dir > 0 ) height += 10; diff --git a/src/hush_utils.h b/src/hush_utils.h index 96adc502a..1b1cb2eeb 100644 --- a/src/hush_utils.h +++ b/src/hush_utils.h @@ -1447,7 +1447,10 @@ uint32_t hush_smartmagic(char *symbol,uint64_t supply,uint8_t *extraptr,int32_t LogPrintf("DragonX raw magic extralen=%d crc0=%x\n",extralen,crc0); } - //TODO: why is this needed? + // Legacy special case: HUSH3 mainnet had a hardcoded network magic (HUSH_MAGIC) + // rather than the crc32-derived value used by every other chain. This branch is + // dead on DragonX (SMART_CHAIN_SYMBOL is "DRAGONX", never "HUSH3"); it is kept only + // so the function still reproduces HUSH3's magic if ever run with that symbol. const bool ishush3 = strncmp(symbol, "HUSH3",5) == 0 ? true : false; if(ishush3) { return HUSH_MAGIC; @@ -1493,16 +1496,19 @@ uint64_t hush_max_money() return hush_current_supply(10000000); } -// This implements the Hush Emission Curve, the miner subsidy part, -// and must be kept in sync with hush_commision() in hush_bitcoind.h! -// Changing these functions are consensus changes! -// Here Be Dragons! -- Duke Leto +// This implements the emission curve (miner subsidy part) and must be kept in +// sync with hush_commission() in hush_bitcoind.h! Changing these functions, +// including the height literals below, is a CONSENSUS change. +// NOTE: this TRANSITION boundary is 128 here, while hush_commission() uses 129. +// This off-by-one between the two curves is a historical consensus quirk and is +// deliberately left as-is: changing either value would be a consensus change. uint64_t hush_block_subsidy(int height) { uint64_t subsidy = 0; int32_t HALVING1 = GetArg("-z2zheight",340000); //TODO: support INTERVAL :( //int32_t INTERVAL = GetArg("-ac_halving1",840000); + // Consensus: TRANSITION is 128 here vs 129 in hush_commission(); do not change (see note above). int32_t TRANSITION = 128; if (height < TRANSITION) { @@ -1585,7 +1591,9 @@ uint64_t hush_block_subsidy(int height) return subsidy; } -// wrapper for more general supply curves of Hush Arrakis Chains +// Wrapper for the more general supply curves used by assetchains (era/halving/decay driven). +// On DragonX the reward comes from the -ac_reward/-ac_halving parameters set in hush_args(); +// the ishush3 branch below is a legacy special case that is dead on DragonX. uint64_t hush_sc_block_subsidy(int nHeight) { // Find current era, start from beginning reward, and determine current subsidy @@ -1593,6 +1601,8 @@ uint64_t hush_sc_block_subsidy(int nHeight) int64_t subsidyDifference; int32_t numhalvings = 0, curEra = 0, sign = 1; static uint64_t cached_subsidy; static int32_t cached_numhalvings; static int cached_era; + // Legacy-HUSH3 detection: dead on DragonX (SMART_CHAIN_SYMBOL is "DRAGONX"), used only + // to route HUSH3 mainnet through its bespoke hush_block_subsidy() emission curve below. const bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false; // check for backwards compat, older chains with no explicit rewards had 0.0001 block reward @@ -1629,7 +1639,9 @@ uint64_t hush_sc_block_subsidy(int nHeight) if(fDebug) fprintf(stderr,"%s: HUSH3 subsidy=%ld at height=%d\n",__func__,subsidy,nHeight); } else if ( (numhalvings = ((nHeight - nStart) / ASSETCHAINS_HALVING[curEra])) > 0 ) { - // The code below is not compatible with HUSH3 mainnet + // Generic halving/decay path used by DragonX and other assetchains. + // (Legacy HUSH3 mainnet did NOT use this path; it took the ishush3 + // branch above, which reproduces its bespoke emission curve.) if ( ASSETCHAINS_DECAY[curEra] == 0 ) { subsidy >>= numhalvings; } else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 ) { @@ -1991,7 +2003,8 @@ void hush_args(char *argv0) uint8_t prevCCi = 0; ASSETCHAINS_CCLIB = GetArg("-ac_cclib","hush3"); - // these are the enabled CCs on HUSH3 mainnet + // Default CC set inherited from legacy HUSH3 mainnet; only used when a chain + // enables CryptoConditions and does not override -ac_ccenable. Split(GetArg("-ac_ccenable","228,234,235,236,241"), sizeof(ccenables)/sizeof(*ccenables), ccenables, 0); for (i=nonz=0; i<0x100; i++) { @@ -2376,6 +2389,9 @@ void hush_args(char *argv0) } } } else { + // Legacy fallback path taken only when no -ac_name is set (SMART_CHAIN_SYMBOL empty). + // Dead on DragonX, which always runs with -ac_name=DRAGONX. The HUSH3/Bitcoin conf + // paths and default ports below are historical and left as-is for backwards compat. char fname[512],username[512],password[4096]; int32_t iter; FILE *fp; ASSETCHAINS_P2PPORT = 7770; ASSETCHAINS_RPCPORT = 7771; diff --git a/src/init.cpp b/src/init.cpp index 07cc152bf..e726e6623 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -121,7 +121,11 @@ static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat"; static const char* DEFAULT_ASMAP_FILENAME="asmap.dat"; -CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h +// LevelDB read-cache size (bytes) for the notarizations (dPoW) DB. Non-consensus: just the +// in-memory cache the DB is opened with; the value here does not affect validation. +static const size_t NOTARIZATION_DB_CACHE_BYTES = 100 * 1024 * 1024; // 100 MiB + +CClientUIInterface uiInterface; // global UI callback dispatcher (declared extern in ui_interface.h) // Shutdown // @@ -622,7 +626,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-stratumport=", strprintf(_("Listen for Stratum work requests on (default: %u or testnet: %u)"), BaseParams().StratumPort(), BaseParams().StratumPort())); strUsage += HelpMessageOpt("-stratumallowip=", _("Allow Stratum work requests from specified source. Valid for are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times")); - // "ac" stands for "affects consensus" or Arrakis Chain + // "ac" prefix is inherited from the Komodo asset-chain lineage ("asset chain"/"affects consensus") strUsage += HelpMessageGroup(_("DragonX Chain options:")); strUsage += HelpMessageOpt("-ac_algo", _("Choose PoW mining algorithm, either 'equihash' or 'randomx'. default is Equihash (200,9)")); strUsage += HelpMessageOpt("-ac_blocktime", _("Block time in seconds, default is 60")); @@ -789,7 +793,7 @@ void ThreadImport(std::vector vImportFiles) } /** Sanity checks - * Ensure that Hush is running in a usable environment with all + * Ensure that DragonX is running in a usable environment with all * necessary library support. */ bool InitSanityCheck(void) @@ -910,7 +914,7 @@ static void ZC_LoadParams(const CChainParams& chainparams) if (!found) { // The traditional place Zcash params are stored, should not hit this case in normal circumstances, - // as Hush packages sapling params now + // as DragonX packages sapling params now sapling_spend = ZC_GetParamsDir() / "sapling-spend.params"; sapling_output = ZC_GetParamsDir() / "sapling-output.params"; if (files_exist(sapling_spend, sapling_output)) { @@ -987,6 +991,10 @@ bool AppInitServers(boost::thread_group& threadGroup) RPCServer::OnPreCommand(&OnRPCPreCommand); if (!InitHTTPServer()) return false; + // WARNING: the stratum server (stratum.cpp) is Equihash-era code: it assumes a 1347-byte + // Equihash solution and calls CheckEquihashSolution. It has NOT been updated for DragonX's + // 32-byte RandomX solution and must not be relied on for mining without a full revalidation. + // It stays off by default (DEFAULT_STRATUM_ENABLE=false); only -stratum turns it on. if (GetBoolArg("-stratum", DEFAULT_STRATUM_ENABLE) && !InitStratumServer()) return false; if (!StartRPC()) @@ -1000,7 +1008,7 @@ bool AppInitServers(boost::thread_group& threadGroup) return true; } -/** Initialize Hush. +/** Initialize DragonX. * @pre Parameters should be parsed and config file should be read. */ extern int32_t HUSH_REWIND; @@ -1203,7 +1211,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("Hush version %s (%s)\n", FormatFullVersion()); + LogPrintf("DragonX version %s (%s)\n", FormatFullVersion()); #ifdef DEBUG_LOCKORDER @@ -1254,7 +1262,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("%s: parameter interaction: -externalip set -> setting -discover=0\n", __func__); } - // Read asmap file by default for HUSH3 and all Hush Arrakis Chains + // Read asmap file by default on DragonX if (GetArg("-asmap",1)) { fs::path asmap_path = fs::path(GetArg("-asmap", "")); @@ -1300,8 +1308,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if(fs::exists(asmap_path)) { LogPrint("net", "%s: found asmap file at %s\n", __func__, asmap_path.c_str() ); } else { - // Shit is fucked up, die an honorable death - InitError(strprintf(_("Could not find any asmap file! Please report this bug to Hush Developers"))); + // No asmap file found in any known location; abort startup. + InitError(strprintf(_("Could not find any asmap file! Please report this bug to DragonX Developers"))); return false; } } @@ -1637,7 +1645,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Sanity check if (!InitSanityCheck()) - return InitError(_("Initialization sanity check failed. Please check for insanity. Hush is shutting down!")); + return InitError(_("Initialization sanity check failed. Please check for insanity. DragonX is shutting down!")); std::string strDataDir = GetDataDir().string(); #ifdef ENABLE_WALLET @@ -1645,7 +1653,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile)) return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir)); #endif - // Make sure only a single Hush process is using the data directory. + // Make sure only a single DragonX process is using the data directory. boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. if (file) fclose(file); @@ -1668,7 +1676,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("Hush version %s\n", FormatFullVersion()); + LogPrintf("DragonX version %s\n", FormatFullVersion()); if (fPrintToDebugLog) OpenDebugLog(); @@ -2066,7 +2074,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); pcoinsTip = new CCoinsViewCache(pcoinscatcher); try { - pnotarizations = new NotarizationDB(100*1024*1024, false, fReindex); + pnotarizations = new NotarizationDB(NOTARIZATION_DB_CACHE_BYTES, false, fReindex); } catch (const std::exception& e) { // The notarizations (dPoW) DB is non-essential and node-regenerable. It has been seen to // snapshot/flush torn (0-byte log -> leveldb "Database I/O error" on reopen), which @@ -2082,7 +2090,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) boost::filesystem::remove_all(ndir.string() + ".corrupt"); boost::filesystem::rename(ndir, ndir.string() + ".corrupt"); } - pnotarizations = new NotarizationDB(100*1024*1024, false, true); + pnotarizations = new NotarizationDB(NOTARIZATION_DB_CACHE_BYTES, false, true); } @@ -2256,10 +2264,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) InitWarning(msg); } else if (nLoadWalletRet == DB_TOO_NEW) - strErrors << _("Error loading wallet.dat: Wallet requires newer version of Hush") << "\n"; + strErrors << _("Error loading wallet.dat: Wallet requires newer version of DragonX") << "\n"; else if (nLoadWalletRet == DB_NEED_REWRITE) { - strErrors << _("Wallet needed to be rewritten: restart Hush to complete") << "\n"; + strErrors << _("Wallet needed to be rewritten: restart DragonX to complete") << "\n"; LogPrintf("%s", strErrors.str()); return InitError(strErrors.str()); } @@ -2664,10 +2672,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #ifdef ENABLE_MINING #ifndef ENABLE_WALLET if (GetBoolArg("-minetolocalwallet", false)) { - return InitError(_("Hush was not built with wallet support. Set -minetolocalwallet=0 to use -mineraddress, or rebuild Hush with wallet support.")); + return InitError(_("DragonX was not built with wallet support. Set -minetolocalwallet=0 to use -mineraddress, or rebuild DragonX with wallet support.")); } if (GetArg("-mineraddress", "").empty() && GetBoolArg("-gen", false)) { - return InitError(_("Hush was not built with wallet support. Set -mineraddress, or rebuild Hush with wallet support.")); + return InitError(_("DragonX was not built with wallet support. Set -mineraddress, or rebuild DragonX with wallet support.")); } #endif // !ENABLE_WALLET diff --git a/src/net.cpp b/src/net.cpp index 7c0240745..7fc4e7669 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -56,7 +56,7 @@ extern uint8_t ASSETCHAINS_CLEARNET; // Run asmap health check every 24hr by default #define ASMAP_HEALTHCHECK_INTERVAL 24*60*60 -// This is every 2 blocks, on avg, on HUSH3 +// Interval (seconds) between zindex stat dumps when -zindex is enabled. #define DUMP_ZINDEX_INTERVAL 150 #define CHECK_PLZ_STOP_INTERVAL 120 @@ -79,7 +79,9 @@ extern uint8_t ASSETCHAINS_CLEARNET; // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization. #define FEELER_SLEEP_WINDOW 1 -#define USE_TLS "encrypted as fuck" +// Marker macro that enables the TLS p2p transport. Only its definedness is +// ever tested (via defined()/#ifdef); the string value itself is never used. +#define USE_TLS "enabled" #if defined(USE_TLS) && !defined(TLS1_3_VERSION) // minimum secure protocol is 1.3 @@ -815,7 +817,7 @@ void CNode::copyStats(CNodeStats &stats, const std::vector &m_asmap) nPingUsecWait = GetTimeMicros() - nPingUsecStart; } - // Raw ping time is in microseconds, but show it to user as whole seconds (Hush users should be well used to small numbers with many decimal places by now :) + // Raw ping time is in microseconds; convert to seconds for display to the user. stats.dPingTime = (((double)nPingUsecTime) / 1e6); stats.dMinPing = (((double)nMinPingUsecTime) / 1e6); stats.dPingWait = (((double)nPingUsecWait) / 1e6); @@ -2514,7 +2516,9 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss) return; } - // We always round down, except when we have only 1 connection + // Relay to half of our peers, rounding down, but never fewer than 1. + // Equivalent to max(1, vNodes.size()/2): the ternary picks 1 only when the + // integer division vNodes.size()/2 is 0 (i.e. exactly 1 connection). auto newSize = (vNodes.size() / 2) == 0 ? 1 : (vNodes.size() / 2); std::shuffle( vRelayNodes.begin(), vRelayNodes.end(), std::mt19937(GetRand(std::numeric_limits::max())) ); @@ -2773,7 +2777,7 @@ bool CNode::GetTlsValidate() { if (tlsValidate == eTlsOption::FALLBACK_UNSET) { - // This is useful for private Hush Arrakis Chains, that want to exist + // This is useful for private DragonX-based chains that want to exist // on a closed VPN with an internal CA or trusted cert system, or // various other use cases if ( GetBoolArg("-tlsvalidate", false)) { diff --git a/src/net.h b/src/net.h index fdc1984ce..2627e071a 100644 --- a/src/net.h +++ b/src/net.h @@ -44,9 +44,12 @@ #include #include #include -// Enable WolfSSL Support for Hush +// Enable WolfSSL support for DragonX #include -// TODO: these are not set correctly by wolfssl for some reason. Ja bless. +// Force-enable wolfSSL's constant-time (timing-resistant) ECC and TFM code paths. +// These are feature-enable macros that wolfSSL checks with #ifdef, so the numeric +// value is immaterial to behavior; the value 420 is arbitrary and must simply be +// non-empty. Redefined here because wolfssl/options.h does not reliably set them. #undef ECC_TIMING_RESISTANT #undef TFM_TIMING_RESISTANT #define ECC_TIMING_RESISTANT 420 diff --git a/src/pow.cpp b/src/pow.cpp index 7f2d3528d..d5740a9b4 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -414,7 +414,10 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead // Changing this requires changing many other things and // might change consensus. Have fun -- Duke -// NOTE: Ony HUSH3 mainnet should use this function, all HAC's should use params.AveragigWindowTimespan() +// NOTE: This hardcoded AWT is legacy from the original HUSH3 mainnet. On DragonX the +// CalculateNextWorkRequired strncmp(SMART_CHAIN_SYMBOL,"HUSH3",...) check is never true +// (SMART_CHAIN_SYMBOL is "DRAGONX"), so this function is dead here and the params-derived +// AveragingWindowTimespan() is used instead. Kept as-is to avoid a consensus change. int64_t AveragingWindowTimespan() { // used in const methods, beware! // This is the correct AWT for 75s blocktime, before block 340k @@ -432,8 +435,11 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime; LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan); + // Legacy branch: the original HUSH3 mainnet used the hardcoded AveragingWindowTimespan() + // above; every other chain uses the params-derived value. On DragonX the symbol is + // "DRAGONX", so this comparison is always false and the params value is used. The check is + // kept (rather than removed) because it is part of consensus difficulty calculation. bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false; - // If this is HUSH3, use AWT function defined above, else use the one in params int64_t AWT = ishush3 ? AveragingWindowTimespan() : params.AveragingWindowTimespan(); nActualTimespan = AWT + (nActualTimespan - AWT)/4; @@ -481,8 +487,9 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, return bnNew.GetCompact(); } -// HUSH does not use these functions but Hush Arrakis Chains can opt-in to using more bleeding edge DAA's -// ASIC chains do not need these protections as much -- Duke Leto +// These LWMA difficulty functions are inherited from the Hush lineage and are only used when +// ASSETCHAINS_ALGO is neither Equihash nor RandomX (see the dispatch in GetNextWorkRequired). +// DragonX uses RandomX, so this LWMA path is not on DragonX's active difficulty codepath. unsigned int lwmaGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { return lwmaCalculateNextWorkRequired(pindexLast, params); diff --git a/src/stratum.cpp b/src/stratum.cpp index c9f4047d3..9b14289bd 100644 --- a/src/stratum.cpp +++ b/src/stratum.cpp @@ -672,7 +672,7 @@ std::string GetWorkUnit(StratumClient& client) } */ /* if (!Params().MineBlocksOnDemand() && g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) { - throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Hush is not connected!"); + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "DragonX is not connected!"); } */ bool fvNodesEmpty; @@ -683,21 +683,21 @@ std::string GetWorkUnit(StratumClient& client) if (Params().MiningRequiresPeers() && fvNodesEmpty) { - const std::string msg = strprintf("%s: Unable to get work unit, Hush is not connected!", __func__); + const std::string msg = strprintf("%s: Unable to get work unit, DragonX is not connected!", __func__); LogPrint("stratum", "%s\n", msg); - throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Hush is not connected!"); + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "DragonX is not connected!"); } if (IsInitialBlockDownload()) { - const std::string msg = strprintf("%s: Unable to get work unit, Hush is still downloading blocks!", __func__); + const std::string msg = strprintf("%s: Unable to get work unit, DragonX is still downloading blocks!", __func__); LogPrint("stratum", "%s\n", msg); - throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Hush is downloading blocks..."); + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "DragonX is downloading blocks..."); } if (!client.m_authorized && client.m_aux_addr.empty()) { const std::string msg = strprintf("%s: Unable to get work unit, client not authorized! Use address 'x' to mine to the default address", __func__); LogPrint("stratum", "%s\n", msg); - throw JSONRPCError(RPC_INVALID_REQUEST, "Stratum client not authorized. Use mining.authorize first, with a Hush R.. address as the username or 'x' to mine to the default address."); + throw JSONRPCError(RPC_INVALID_REQUEST, "Stratum client not authorized. Use mining.authorize first, with a DragonX R.. address as the username or 'x' to mine to the default address."); } static CBlockIndex* tip = NULL; // pindexPrev @@ -924,6 +924,15 @@ bool SubmitBlock(StratumClient& client, const uint256& job_id, const StratumWork const std::vector& extranonce1, const std::vector& extranonce2, boost::optional nVersion, uint32_t nTime, const std::vector& sol) { + // ============================ WARNING (Equihash-era code) ============================ + // This entire submit path is hardcoded for the legacy Equihash proof-of-work: + // it expects a 1347-byte Equihash solution and calls CheckEquihashSolution() below. + // DragonX uses RandomX PoW (32-byte solution), NOT Equihash. This stratum path has + // NOT been updated for RandomX and must not be relied on without full revalidation. + // The 1347-byte length checks, the "sol.begin()+3" solution offset, and the equihash + // target/difficulty math are all Equihash-era and are intentionally left unchanged. + // ==================================================================================== + // // called from stratum_mining_submit and uses following data, came from client: // ["WORKER_NAME", "JOB_ID", "TIME", "NONCE_2", "EQUIHASH_SOLUTION"] // all other params we have saved in other places @@ -934,7 +943,9 @@ bool SubmitBlock(StratumClient& client, const uint256& job_id, const StratumWork throw JSONRPCError(RPC_INVALID_PARAMETER, msg); } - // TODO: change hardcoded constants on actual determine of solution size, depends on equihash algo type: 200.9, etc. + // WARNING (Equihash-era): 1347 is the Equihash-200,9 solution length. DragonX is RandomX + // (32-byte solution), so this length check does not match the live PoW. Left unchanged + // because this whole path is Equihash-era; do not repurpose without revalidating the miner protocol. if (sol.size() != 1347) { std::string msg = strprintf("%s: solution is wrong length (received %d bytes; expected %d bytes", __func__, extranonce2.size(), 1347); LogPrint("stratum", "%s\n", msg); @@ -1196,7 +1207,7 @@ UniValue stratum_mining_authorize(StratumClient& client, const UniValue& params) // This means a miner can run a private pool without TLS and not // worry about MITM attacks that change addresses, and leaks less metadata. // It also means many miners can be used and updating their mining address does not - // require any changes on each miner, just restart hushd with a new -stratumaddress + // require any changes on each miner, just restart dragonxd with a new -stratumaddress if(addr.ToString() == "x") { addr = CBitcoinAddress(GetArg("-stratumaddress", "")); const std::string msg = strprintf("%s: Authorized client with default stratum address=%s", __func__, addr.ToString()); @@ -1204,9 +1215,9 @@ UniValue stratum_mining_authorize(StratumClient& client, const UniValue& params) } if (!addr.IsValid()) { - const std::string msg = strprintf("%s: Invalid Hush address=%s", __func__, addr.ToString()); + const std::string msg = strprintf("%s: Invalid DragonX address=%s", __func__, addr.ToString()); LogPrint("stratum", "%s\n", msg); - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid Hush address: %s", username)); + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid DragonX address: %s", username)); } client.m_addr = addr; @@ -1250,6 +1261,14 @@ UniValue stratum_mining_configure(StratumClient& client, const UniValue& params) UniValue stratum_mining_submit(StratumClient& client, const UniValue& params) { + // ============================ WARNING (Equihash-era code) ============================ + // This share-submission handler is hardcoded for legacy Equihash: it parses and requires + // a 1347-byte Equihash solution and hands it to SubmitBlock() (which calls + // CheckEquihashSolution). DragonX uses RandomX PoW (32-byte solution), NOT Equihash. + // This path has NOT been updated for RandomX and must not be relied on without full + // revalidation of the miner-facing stratum protocol. + // ==================================================================================== + // // {"id": 4, "method": "mining.submit", "params": ["WORKER_NAME", "JOB_ID", "TIME", "NONCE_2", "EQUIHASH_SOLUTION"]}\n // NONCE_1 is first part of the block header nonce (in hex). @@ -1762,7 +1781,7 @@ void SendKeepAlivePackets() } -/** Configure the Hush stratum server */ +/** Configure the DragonX stratum server */ bool InitStratumServer() { LOCK(cs_stratum); diff --git a/src/txdb.cpp b/src/txdb.cpp index d0541e08a..743bba841 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -285,8 +285,9 @@ bool CBlockTreeDB::WriteBatchSync(const std::vector key = make_pair(DB_BLOCK_INDEX, it->GetBlockHash()); try { CDiskBlockIndex dbindex {it, [this, &key]() { - // It can happen that the index entry is written, then the Equihash solution is cleared from memory, + // It can happen that the index entry is written, then the solution is cleared from memory, // then the index entry is rewritten. In that case we must read the solution from the old entry. + // (GetSolution() returns DragonX's RandomX solution.) CDiskBlockIndex dbindex_old; if (!Read(key, dbindex_old)) { LogPrintf("%s: Failed to read index entry", __func__); @@ -698,7 +699,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pindexNew->nTime = diskindex.nTime; pindexNew->nBits = diskindex.nBits; pindexNew->nNonce = diskindex.nNonce; - // the Equihash solution will be loaded lazily from the dbindex entry + // the solution (DragonX RandomX solution) will be loaded lazily from the dbindex entry // pindexNew->nSolution = diskindex.nSolution; pindexNew->nStatus = diskindex.nStatus; pindexNew->nCachedBranchId = diskindex.nCachedBranchId; diff --git a/src/util.cpp b/src/util.cpp index 29e67f9ce..b9d661260 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -499,27 +499,35 @@ boost::filesystem::path GetDefaultDataDir() if ( SMART_CHAIN_SYMBOL[0] != 0 ) strcpy(symbol,SMART_CHAIN_SYMBOL); else symbol[0] = 0; - // OLD NAMES: - // Windows < Vista: C:\Documents and Settings\Username\Application Data\Komodo - // Windows >= Vista: C:\Users\Username\AppData\Roaming\Komodo - // Mac: ~/Library/Application Support/Komodo - // Unix: ~/.komodo + // DragonX stores its data under a per-chain subdirectory named after + // SMART_CHAIN_SYMBOL (which is "DRAGONX"), so the default datadir resolves + // to (Unix) ~/.hush/DRAGONX, (Mac) ~/Library/Application Support/Hush/DRAGONX, + // or (Windows) %APPDATA%\Hush\DRAGONX. + // + // The "Hush" / "Komodo" parent-directory names below are retained from the + // Hush/Komodo lineage: the ".hush"/"Hush" path is the current location, and + // the ".komodo"/"Komodo" path is only probed as a backward-compatible + // fallback for pre-existing legacy data directories. Do not change these + // string literals -- they determine where node data is read from and written. - // NEW NAMES: + // Current (per-symbol subdirectory lives under these parents): // Windows < Vista: C:\Documents and Settings\Username\Application Data\Hush // Windows >= Vista: C:\Users\Username\AppData\Roaming\Hush // Mac: ~/Library/Application Support/Hush // Unix: ~/.hush - // ~/.hush was actually used by the original 1.x version of Hush, but we will - // only make subdirectories inside of it, so we won't be able to overwrite - // an old wallet.dat from the Ice Ages :) + // Legacy fallback (only used if such a directory already exists): + // Windows < Vista: C:\Documents and Settings\Username\Application Data\Komodo + // Windows >= Vista: C:\Users\Username\AppData\Roaming\Komodo + // Mac: ~/Library/Application Support/Komodo + // Unix: ~/.komodo fs::path pathRet; #ifdef _WIN32 // Windows pathRet = GetSpecialFolderPath(CSIDL_APPDATA) / "Hush" / symbol; - // Always use .hush/HUSH3, if it exists (even if .komodo/HUSH3 exists) + // Always use Hush\ (Hush\DRAGONX) if it exists, even if the legacy + // Komodo\ directory also exists. if(fs::is_directory(pathRet)) { return pathRet; } else { @@ -528,7 +536,7 @@ boost::filesystem::path GetDefaultDataDir() // existing legacy directory, use that for backward compat return pathRet; } else { - // For new clones, use Hush/ACNAME + // For new nodes, use Hush\ pathRet = GetSpecialFolderPath(CSIDL_APPDATA) / "Hush" / symbol; return pathRet; } @@ -551,7 +559,7 @@ boost::filesystem::path GetDefaultDataDir() // create Library/Application Support/Hush if it doesn't exist TryCreateDirectory(tmppath); - // Always use Hush/HUSH3 if it exists + // Always use Hush/ (Hush/DRAGONX) if it exists if(fs::is_directory(tmppath / symbol)) { return tmppath / symbol; } else { @@ -563,16 +571,16 @@ boost::filesystem::path GetDefaultDataDir() // Found legacy dir, use that return tmppath / symbol; } else { - // For new clones, use Hush/ACNAME + // For new nodes, use Hush/ tmppath = pathRet / "Hush" / symbol; } return tmppath; } #else - // Unix - // New directory :) + // Unix: current default datadir is ~/.hush/ (i.e. ~/.hush/DRAGONX) fs::path tmppath = pathRet / ".hush" / symbol; - // Always use .hush/HUSH3, if it exists (even if .komodo/HUSH3 exists) + // Always use ~/.hush/ (~/.hush/DRAGONX) if it exists, even if the + // legacy ~/.komodo/ directory also exists. if(fs::is_directory(tmppath)) { return tmppath; } else { @@ -582,7 +590,7 @@ boost::filesystem::path GetDefaultDataDir() // existing legacy directory, use that for backward compat return tmppath; } else { - // For new clones, use .hush/ACNAME + // For new nodes, use ~/.hush/ tmppath = pathRet / ".hush" / symbol; } return tmppath; @@ -598,13 +606,17 @@ static CCriticalSection csPathCached; static boost::filesystem::path ZC_GetBaseParamsDir() { - // Copied from GetDefaultDataDir and adapted for zcash params. + // Copied from GetDefaultDataDir and adapted for the zk-SNARK parameter files. + // DragonX reuses the upstream Sapling parameter directory layout, so these + // locations retain the historical "ZcashParams" / ".zcash-params" names. Do + // not change these string literals -- they determine where the proving and + // verifying keys are loaded from. namespace fs = boost::filesystem; // Windows < Vista: C:\Documents and Settings\Username\Application Data\ZcashParams // Windows >= Vista: C:\Users\Username\AppData\Roaming\ZcashParams // Mac: ~/Library/Application Support/ZcashParams // Unix: ~/.zcash-params - // Debian packages: /usr/share/hush + // System-wide install (Debian packages): /usr/share/hush fs::path pathRet; #ifdef _WIN32 return GetSpecialFolderPath(CSIDL_APPDATA) / "ZcashParams"; diff --git a/src/wallet/asyncrpcoperation_saplingconsolidation.cpp b/src/wallet/asyncrpcoperation_saplingconsolidation.cpp index 147d9c4a1..5a08f8cc7 100644 --- a/src/wallet/asyncrpcoperation_saplingconsolidation.cpp +++ b/src/wallet/asyncrpcoperation_saplingconsolidation.cpp @@ -20,6 +20,12 @@ CAmount fConsolidationTxFee = DEFAULT_CONSOLIDATION_FEE; bool fConsolidationMapUsed = false; +// Number of Sietch dummy ("zdust") shielded outputs added to every consolidation +// transaction to obscure the real output and keep the anonymity set large. This is +// a wallet privacy-tuning parameter (not a consensus rule); the sweep operation uses +// the same value under the name ZOUTS. +static const int MIN_ZOUTS = 7; + extern string randomSietchZaddr(); AsyncRPCOperation_saplingconsolidation::AsyncRPCOperation_saplingconsolidation(int targetHeight) : targetHeight_(targetHeight) {} @@ -238,10 +244,10 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() { builder.AddSaplingOutput(extsk.expsk.ovk, addr, actualAmountToSend); LogPrint("zrpcunsafe", "%s: Added consolidation output %s with amount=%li\n", opid, addr.GetHash().ToString().c_str(), actualAmountToSend); - // Add sietch zouts - int MIN_ZOUTS = 7; + // Add sietch zouts: MIN_ZOUTS dummy zero-value shielded outputs to + // randomly-generated z-addresses, so the consolidation tx does not + // shrink the anonymity set. for(size_t i = 0; i < MIN_ZOUTS; i++) { - // In Privacy Zdust We Trust -- Duke string zdust = randomSietchZaddr(); auto zaddr = DecodePaymentAddress(zdust); if (IsValidPaymentAddress(zaddr)) { diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 94973aa1b..9c8fafa95 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -215,9 +215,10 @@ bool AsyncRPCOperation_sendmany::main_impl() { bool isPureTaddrOnlyTx = (isfromtaddr_ && z_outputs_.size() == 0); CAmount minersFee = fee_; - // TODO: fix this garbage ZEC prisoner mindset bullshit - // When spending coinbase utxos, you can only specify a single zaddr as the change must go somewhere - // and if there are multiple zaddrs, we don't know where to send it. + // Coinbase-change routing constraint: + // When spending coinbase UTXOs, only a single zaddr recipient may be specified, because the + // change must be routed somewhere and with multiple zaddr recipients there is no unambiguous + // destination for it. See the isSingleZaddrOutput / isMultipleZaddrOutput handling below. if (isfromtaddr_) { if (isSingleZaddrOutput) { bool b = find_utxos(true); @@ -354,8 +355,8 @@ bool AsyncRPCOperation_sendmany::main_impl() { /** - * SCENARIO #0 (All HUSH and Hush Arrakis Chains) - * Sprout not involved, so we just use the TransactionBuilder and we're done. + * SCENARIO #0 (DragonX and all Sapling-only chains) + * Sprout is not involved, so we just use the TransactionBuilder and we're done. * We added the transparent inputs to the builder earlier. */ if (isUsingBuilder_) { @@ -506,7 +507,8 @@ bool AsyncRPCOperation_sendmany::main_impl() { return true; } // END SCENARIO #0 - // No other scenarios, because Hush developers are elite. + // No other scenarios: DragonX is Sapling-only (Sprout removed), so the builder path above + // handles every supported case. Reaching here means the builder was not used, which is unexpected. return false; } @@ -668,7 +670,8 @@ void AsyncRPCOperation_sendmany::add_taddr_outputs_to_tx() { rawTx.vout.push_back(out); } if ( !hush_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) - rawTx.nLockTime = (uint32_t)time(NULL) - 60; // jl777 + // Pre-hardfork: set nLockTime slightly in the past so the tx is immediately spendable. + rawTx.nLockTime = (uint32_t)time(NULL) - 60; else rawTx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); @@ -698,7 +701,8 @@ void AsyncRPCOperation_sendmany::add_taddr_change_output_to_tx(CBitcoinAddress * CMutableTransaction rawTx(tx_); rawTx.vout.push_back(out); if ( !hush_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) - rawTx.nLockTime = (uint32_t)time(NULL) - 60; // jl777 + // Pre-hardfork: set nLockTime slightly in the past so the tx is immediately spendable. + rawTx.nLockTime = (uint32_t)time(NULL) - 60; else rawTx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); tx_ = CTransaction(rawTx); diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index fe2e9ee55..fa29dba19 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -24,7 +24,10 @@ #include #include #include -// TODO: these are not set correctly by wolfssl for some reason. Ja bless. +// Enable wolfSSL timing-resistant ECC and TFM (fastmath) code paths, which +// harden against timing side-channels. wolfSSL gates these purely with #ifdef, +// so the defined value is immaterial (any value enables the feature); we do not +// rely on 420 meaning anything. #undef ECC_TIMING_RESISTANT #undef TFM_TIMING_RESISTANT #define ECC_TIMING_RESISTANT 420 @@ -306,7 +309,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) } if (keyPass && keyFail) { - LogPrintf("Oh shit! The wallet is probably corrupted: Some keys decrypt but not all.\n"); + LogPrintf("The wallet is probably corrupted: some keys decrypt but not all.\n"); assert(false); } if (keyFail || !keyPass) diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 427f9e5df..d79a1b34b 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -169,7 +169,8 @@ private: CKeyingMaterial vMasterKey; - //! if fUseCrypto is true, mapKeys, mapSproutSpendingKeys, and mapSaplingSpendingKeys must be empty + //! if fUseCrypto is true, mapKeys and mapSaplingSpendingKeys must be empty + //! (Sprout was removed; the former mapSproutSpendingKeys no longer exists) //! if fUseCrypto is false, vMasterKey must be empty bool fUseCrypto; diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index dac53a7f6..6c507780b 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -95,7 +95,7 @@ UniValue convertpassphrase(const UniValue& params, bool fHelp, const CPubKey& my "1. \"agamapassphrase\" (string, required) Agama passphrase\n" "\nResult:\n" "\"agamapassphrase\": \"agamapassphrase\", (string) Agama passphrase you entered\n" - "\"address\": \"hushaddress\", (string) Address corresponding to your passphrase\n" + "\"address\": \"dragonxaddress\", (string) Address corresponding to your passphrase\n" "\"pubkey\": \"publickeyhex\", (string) The hex value of the raw public key\n" "\"privkey\": \"privatekeyhex\", (string) The hex value of the raw private key\n" "\"wif\": \"wif\" (string) The private key in WIF format to use with 'importprivkey'\n" @@ -255,10 +255,10 @@ UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk) if (fHelp || params.size() < 1 || params.size() > 5) throw runtime_error( - "importprivkey \"hushprivkey\" ( \"label\" rescan height secret_key)\n" + "importprivkey \"dragonxprivkey\" ( \"label\" rescan height secret_key)\n" "\nAdds a private key (as returned by dumpprivkey) to your wallet.\n" "\nArguments:\n" - "1. \"hushprivkey\" (string, required) The private key (see dumpprivkey)\n" + "1. \"dragonxprivkey\" (string, required) The private key (see dumpprivkey)\n" "2. \"label\" (string, optional, default=\"\") An optional label\n" "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" "4. height (integer, optional, default=0) start at block height?\n" @@ -378,7 +378,7 @@ UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) std::vector data(ParseHex(params[0].get_str())); script = CScript(data.begin(), data.end()); } else { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Hush address or script"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid DragonX address or script"); } string strLabel = ""; @@ -504,7 +504,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys if (vstr.size() < 2) continue; - // Let's see if the address is a valid Hush spending key + // Let's see if the address is a valid DragonX spending key if (fImportZKeys) { auto spendingkey = DecodeSpendingKey(vstr[0]); int64_t nTime = DecodeDumpTime(vstr[1]); @@ -524,7 +524,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys continue; } else { LogPrintf("%s: Importing detected an error: invalid spending key. Trying as a transparent key...\n",__func__); - // Not a valid spending key, so carry on and see if it's a Hush transparent address + // Not a valid spending key, so carry on and see if it's a DragonX transparent address } } @@ -659,7 +659,7 @@ UniValue z_exportwallet(const UniValue& params, bool fHelp, const CPubKey& mypk) "z_exportwallet \"filename\"\n" "\nExports all wallet keys, for taddr and zaddr, in a human-readable format. Overwriting an existing file is not permitted.\n" "\nArguments:\n" - "1. \"filename\" (string, required) The filename, saved in folder set by hushd -exportdir option\n" + "1. \"filename\" (string, required) The filename, saved in folder set by dragonxd -exportdir option\n" "\nResult:\n" "\"path\" (string) The full path of the destination file\n" "\nExamples:\n" @@ -680,7 +680,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp, const CPubKey& mypk) "dumpwallet \"filename\"\n" "\nDumps taddr wallet keys in a human-readable format. Overwriting an existing file is not permitted.\n" "\nArguments:\n" - "1. \"filename\" (string, required) The filename, saved in folder set by hushd -exportdir option\n" + "1. \"filename\" (string, required) The filename, saved in folder set by dragonxd -exportdir option\n" "\nResult:\n" "\"path\" (string) The full path of the destination file\n" "\nExamples:\n" @@ -736,7 +736,7 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys) std::sort(vKeyBirth.begin(), vKeyBirth.end()); // produce output - file << strprintf("# Wallet dump created by Hush %s (%s)\n", CLIENT_BUILD); + file << strprintf("# Wallet dump created by DragonX %s (%s)\n", CLIENT_BUILD); file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime())); file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString()); file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime())); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 638b7d86b..33bed940b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -364,7 +364,7 @@ UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk) CTxDestination dest = DecodeDestination(params[0].get_str()); if (!IsValidDestination(dest)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Hush address!"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid DragonX address!"); } string strAccount; @@ -411,7 +411,7 @@ UniValue getaccount(const UniValue& params, bool fHelp, const CPubKey& mypk) CTxDestination dest = DecodeDestination(params[0].get_str()); if (!IsValidDestination(dest)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Hush address!"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid DragonX address!"); } std::string strAccount; @@ -571,7 +571,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) CTxDestination dest = DecodeDestination(params[0].get_str()); if (!IsValidDestination(dest)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Hush address!"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid DragonX address!"); } // Amount @@ -705,7 +705,8 @@ UniValue kvupdate(const UniValue& params, bool fHelp, const CPubKey& mypk) } } } - ret.push_back(Pair("coin",(char *)(SMART_CHAIN_SYMBOL[0] == 0 ? "HUSH3" : SMART_CHAIN_SYMBOL))); + // The SMART_CHAIN_SYMBOL[0]==0 fallback is dead on DragonX (symbol is always "DRAGONX"); kept for defensiveness. + ret.push_back(Pair("coin",(char *)(SMART_CHAIN_SYMBOL[0] == 0 ? "DRAGONX" : SMART_CHAIN_SYMBOL))); height = chainActive.LastTip()->GetHeight(); if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) ret.push_back(Pair("owner",refpubkey.GetHex())); @@ -895,7 +896,7 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey& // Bitcoin address CTxDestination dest = DecodeDestination(params[0].get_str()); if (!IsValidDestination(dest)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Hush address!"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid DragonX address!"); } CScript scriptPubKey = GetScriptForDestination(dest); if (!IsMine(*pwalletMain, scriptPubKey)) { @@ -1452,7 +1453,7 @@ UniValue sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) CScript tmpspk; tmpspk << ParseHex(name_) << OP_CHECKSIG; if ( !ExtractDestination(tmpspk, dest, true) ) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Hush address or pubkey: ") + name_); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid DragonX address or pubkey: ") + name_); } CScript scriptPubKey = GetScriptForDestination(dest); @@ -2546,7 +2547,7 @@ UniValue encryptwallet(const UniValue& params, bool fHelp, const CPubKey& mypk) // slack space in .dat files; that is bad if the old data is // unencrypted private keys. So: StartShutdown(); - return "wallet encrypted; Hush server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup."; + return "wallet encrypted; DragonX server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup."; } UniValue lockunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) @@ -2854,7 +2855,7 @@ UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) " \"txid\" : \"txid\", (string) the transaction id \n" " \"vout\" : n, (numeric) the vout value\n" " \"generated\" : true|false (boolean) true if txout is a coinbase transaction output\n" - " \"address\" : \"address\", (string) the Hush address\n" + " \"address\" : \"address\", (string) the DragonX address\n" " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n" " \"scriptPubKey\" : \"key\", (string) the script key\n" " \"amount\" : x.xxx, (numeric) the transaction amount in " + CURRENCY_UNIT + "\n" @@ -2888,7 +2889,7 @@ UniValue listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) const UniValue& input = inputs[idx]; CTxDestination dest = DecodeDestination(input.get_str()); if (!IsValidDestination(dest)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Hush address: ") + input.get_str()); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid DragonX address: ") + input.get_str()); } if (!destinations.insert(dest).second) { throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str()); @@ -3423,7 +3424,7 @@ UniValue z_listreceivedaddress(const UniValue& params, bool fHelp,const CPubKey& "This function is slow if no filters are given, use z_listreceivedbyaddress if you do not need filters." "\n" "\nArguments:\n" - "1. \"hushaddress:\" (string, required) \n" + "1. \"dragonxaddress:\" (string, required) \n" "\n" "2. \"Minimum Confimations:\" (numeric, optional, default=0) \n" "\n" @@ -3460,13 +3461,13 @@ UniValue z_listreceivedaddress(const UniValue& params, bool fHelp,const CPubKey& " \"walletconflicts\": [conflicts], An array of wallet conflicts\n" " \"recieved\": { A list of receives from the transaction\n" " \"transparentReceived\": [{ An Array of txos received for transparent addresses\n" - " \"address\": \"hushaddress\", (string) Hush transparent address (t-address)\n" + " \"address\": \"dragonxaddress\", (string) DragonX transparent address (t-address)\n" " \"scriptPubKey\": \"script\", (string) Script for the transparent address (t-address)\n" " \"amount\": x.xxxx, (numeric) Value of output being received " + CURRENCY_UNIT + ", positive for receives\n" " \"vout\": : n, (numeric) the vout value\n" " }],\n" " \"saplingReceived\": [{ An Array of utxos/notes received for sapling addresses\n" - " \"address\": \"hushaddress\", (string) Shielded address (z-address)\n" + " \"address\": \"dragonxaddress\", (string) Shielded address (z-address)\n" " \"amount\": x.xxxx, (numeric) Value of output being received " + CURRENCY_UNIT + ", positive for receives\n" " \"memo\": xxxxx, (string) hexademical string representation of memo field\n" " \"memoStr\" : \"memo\", (string) Only returned if memo contains valid UTF-8 text.\n" @@ -3599,12 +3600,12 @@ UniValue z_listsentbyaddress(const UniValue& params, bool fHelp,const CPubKey&) if (fHelp || params.size() > 5 || params.size() == 3) throw runtime_error( "z_listsentbyaddress\n" - "\nReturns decrypted Hush outputs sent to a single address.\n" + "\nReturns decrypted DragonX outputs sent to a single address.\n" "\n" "This function only returns information on addresses sent from wallet addresses with full spending keys." "\n" "\nArguments:\n" - "1. \"hushaddress:\" (string, required) \n" + "1. \"dragonxaddress:\" (string, required) \n" "\n" "2. \"Minimum Confimations:\" (numeric, optional, default=0) \n" "\n" @@ -3642,13 +3643,13 @@ UniValue z_listsentbyaddress(const UniValue& params, bool fHelp,const CPubKey&) " \"sends\": { A list of outputs of where funds were sent to in the transaction,\n" " only available if the transaction has valid sends (inputs) belonging to the wallet\n" " \"transparentSends\": [{ An Array of spends (outputs) for transparent addresses of the receipient\n" - " \"address\": \"hushaddress\", (string) Hush transparent address (t-address)\n" - " \"scriptPubKey\": \"script\", (string) Script for the Hush transparent address (t-address)\n" + " \"address\": \"dragonxaddress\", (string) DragonX transparent address (t-address)\n" + " \"scriptPubKey\": \"script\", (string) Script for the DragonX transparent address (t-address)\n" " \"amount\": x.xxxx, (numeric) Value of output being sent " + CURRENCY_UNIT + ", negative for sends\n" " \"vout\": : n, (numeric) the vout value\n" " }],\n" " \"saplingSends\": [{ An Array of spends (outputs) for sapling addresses\n" - " \"address\": \"hushaddress\", (string) Hush sapling address (z-address) of the receipient\n" + " \"address\": \"dragonxaddress\", (string) DragonX sapling address (z-address) of the receipient\n" " \"amount\": x.xxxx, (numeric) Value of output being sent" + CURRENCY_UNIT + ", negative for sends\n" " \"memo\": xxxxx, (string) hexademical string representation of memo field\n" " \"memoStr\" : \"memo\", (string) Only returned if memo contains valid UTF-8 text.\n" @@ -4277,7 +4278,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) string address = o.get_str(); auto zaddr = DecodePaymentAddress(address); if (!IsValidPaymentAddress(zaddr)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, address is not a valid Hush zaddr: ") + address); + throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, address is not a valid DragonX zaddr: ") + address); } auto hasSpendingKey = boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr); if (!fIncludeWatchonly && !hasSpendingKey) { @@ -4820,7 +4821,7 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& my // getbalance and "getbalance * 1 true" should return the same number // but they don't because wtx.GetAmounts() does not handle tx where there are no outputs // pwalletMain->GetBalance() does not accept min depth parameter - // so we use our own method to get balance of utxos, lulzwtfbbq + // so we use our own method to get balance of utxos CAmount nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly); CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, !fIncludeWatchonly); CAmount nTotalBalance = nBalance + nPrivateBalance; @@ -4856,7 +4857,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp, const CPubKey& my " \"rk\" : \"rk\", (string) The rk\n" " \"zkproof\" : \"zkproof\", (string) Hexadecimal string representation of raw zksnark proof\n" " \"outputPrev\" : n, (numeric) the index of the output within the vShieldedOutput\n" - " \"address\" : \"zcashaddress\", (string) The Hush shielded address involved in the transaction\n" + " \"address\" : \"dragonxaddress\", (string) The DragonX shielded address involved in the transaction\n" " \"value\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n" " \"valueZat\" : xxxx (numeric) The amount in puposhis\n" " }\n" @@ -4866,7 +4867,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp, const CPubKey& my " {\n" " \"type\" : \"sapling\", (string) The type of address\n" " \"output\" : n, (numeric) the index of the output within the vShieldedOutput\n" - " \"address\" : \"hushaddress\", (string) The Hush address involved in the transaction\n" + " \"address\" : \"dragonxaddress\", (string) The DragonX address involved in the transaction\n" " \"outgoing\" : true|false (boolean) True if the output is not for an address in the wallet\n" " \"value\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n" " \"valueZat\" : xxxx (numeric) The amount in puposhis\n" @@ -5143,7 +5144,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) LOCK2(cs_main, pwalletMain->cs_wallet); - // Hilarious that Komodo commented this out, opening themselves up to metadata attackz, lulz + // Guard against building shielded transactions before the chain is fully synced; + // sending while behind the tip can leak metadata usable for linkability analysis. THROW_IF_SYNCING(HUSH_INSYNC); // Check that the from address is valid. @@ -5388,6 +5390,9 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) // SIETCH: Sprinkle our cave with some magic privacy zdust // End goal is to have this be as large as possible without slowing xtns down too much // A value of 7 will provide much stronger linkability privacy versus pre-Sietch operations + // DEFAULT_MIN_ZOUTS (7): default number of dummy z-outputs padded onto each z_sendmany. + // MAX_ZOUTS (50): upper bound for the operator-tunable -sietch-min-zouts arg. + // The effective floor is clamped to [3, MAX_ZOUTS] below. unsigned int DEFAULT_MIN_ZOUTS=7; unsigned int MAX_ZOUTS=50; unsigned int MIN_ZOUTS=GetArg("-sietch-min-zouts", DEFAULT_MIN_ZOUTS); @@ -5457,9 +5462,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) txsize += GetSerializeSize(tx, SER_NETWORK, tx.nVersion); if (fromTaddr) { txsize += CTXIN_SPEND_DUST_SIZE; - //TODO: On HUSH since block 340k there can no longer be taddr change, - // (except for notary addresses) - // so we can likely make a better estimation of max txsize + // DragonX is ac_private=1 (fully shielded from genesis); transparent outputs are + // banned, so in practice there is no taddr change and this estimate is conservative. txsize += CTXOUT_REGULAR_SIZE; // There will probably be taddr change } txsize += CTXOUT_REGULAR_SIZE * taddrRecipients.size(); @@ -5594,7 +5598,8 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp LOCK2(cs_main, pwalletMain->cs_wallet); - // Hilarious that Komodo commented this out, opening themselves up to metadata attackz, lulz + // Guard against building shielded transactions before the chain is fully synced; + // sending while behind the tip can leak metadata usable for linkability analysis. THROW_IF_SYNCING(HUSH_INSYNC); // Validate the from address @@ -5840,7 +5845,8 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp LOCK2(cs_main, pwalletMain->cs_wallet); - // Hilarious that Komodo commented this out, opening themselves up to metadata attackz, lulz + // Guard against building shielded transactions before the chain is fully synced; + // sending while behind the tip can leak metadata usable for linkability analysis. THROW_IF_SYNCING(HUSH_INSYNC); bool useAnyUTXO = false; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 1fc80f4fa..1c84243a8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -578,7 +578,7 @@ void CWallet::ChainTip(const CBlockIndex *pindex, } void CWallet::RunSaplingSweep(int blockHeight) { - // Sapling is always active since height=1 of HUSH+HACs + // Sapling is always active since height=1 on DragonX // if (!NetworkUpgradeActive(blockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { // return; // } @@ -669,7 +669,7 @@ void CWallet::RunSaplingSweep(int blockHeight) { } void CWallet::RunSaplingConsolidation(int blockHeight) { - // Sapling is always active on HUSH+HACs + // Sapling is always active on DragonX (activated at height=1) //if (!NetworkUpgradeActive(blockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { // return; //} @@ -2380,7 +2380,7 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum) case TX_SCRIPTHASH: scriptID = CScriptID(uint160(vSolutions[0])); - //TODO: remove CLTV stuff not relevant to Hush + //TODO: evaluate whether this CLTV timelock handling is needed on DragonX if (this->GetCScript(scriptID, subscript)) { // if this is a CLTV, handle it differently @@ -4580,7 +4580,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(), std::numeric_limits::max()-1)); - // All Hush Arrakis Chains always have overwinter NU and so this option was never used + // DragonX always has the Overwinter NU active and so this option was never used // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects // const size_t limit = 0; // (size_t)GetArg("-mempooltxinputlimit", 0); //{ @@ -5727,7 +5727,7 @@ SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingE if (params.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight == Consensus::NetworkUpgrade::ALWAYS_ACTIVE) { m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = nTime; } else { - // TODO: set a better time for HUSH+HACs + // TODO: set a better time for DragonX // 154051200 seconds from epoch is Friday, 26 October 2018 00:00:00 GMT - definitely before Sapling activates m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = std::max((int64_t) 154051200, nTime); }