hygiene: Phase 5 — correct stale comments + name safe magic numbers

Fifth phase of the code-hygiene remediation, done per-file (18 files) via an
18-agent Workflow with strict guardrails. No consensus or security VALUES
changed (verified: pow/hush_utils/hush_bitcoind/net.h/crypter/stratum have
zero non-comment numeric changes); built clean, self-mined, verifychain=true.

Totals: 57 stale comments corrected, 46 user-facing branding fixes, 6
behavior-preserving named constants, 4 stratum warnings, 77 items deliberately
left (consensus/security values, copyright headers).

- Stale comments -> DragonX: corrected HUSH3/HUSH/Komodo/Equihash/Arrakis
  leftovers that misdescribed the active chain (pow AWT/lwma notes, txdb
  "Equihash solution" -> RandomX, wallet CLTV/overwinter/Sapling@1 notes,
  util datadir provenance, crypter's stale mapSproutSpendingKeys invariant).
  Replaced unprofessional/editorializing comments (profane TODOs, "developers
  are elite") with neutral technical notes, preserving the real design info.
- User-facing branding: dumpwallet header "created by Hush" -> "DragonX";
  RPC help text hushd/hush-cli/hushprivkey/hushaddress/Agama -> dragonx*;
  rebranded provably-dead "HUSH3" symbol-fallback literals to DRAGONX.
- Named constants (same values, non-consensus/non-security): addrman
  peer-selection factors (kChanceFactorGrowth/kChanceScale/deprioritize),
  sietch MIN_ZOUTS, an init notarization-DB cache size.
- Left the security macros (ECC/TFM_TIMING_RESISTANT=420, comment-clarified
  only), the consensus subsidy/commission literals + 128/129 TRANSITION
  (comment only), and copyright headers untouched.
- Added a prominent WARNING that the stratum server is Equihash-era and NOT
  updated for DragonX's RandomX PoW (flagged, not rewritten).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-27 15:19:22 -05:00
parent cf15b0a399
commit 817c6b2d0e
18 changed files with 251 additions and 141 deletions

View File

@@ -478,6 +478,20 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
const int kRetriesBetweenSleep = 1000; const int kRetriesBetweenSleep = 1000;
const int kRetrySleepInterval = 100; // milliseconds 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) if (newOnly && nNew == 0)
return CAddrInfo(); return CAddrInfo();
@@ -513,15 +527,15 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
CAddrInfo& info = mapInfo[nId]; CAddrInfo& info = mapInfo[nId];
if (info.IsReachableNetwork()) { if (info.IsReachableNetwork()) {
//deprioritize unreachable networks //deprioritize unreachable networks
fReachableFactor = 0.25; fReachableFactor = kUnreachableDeprioritize;
} }
if (info.IsJustTried()) { if (info.IsJustTried()) {
//deprioritize entries just tried //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; return info;
fChanceFactor *= 1.2; fChanceFactor *= kChanceFactorGrowth;
} }
} else { } else {
// use a new node // use a new node
@@ -553,15 +567,15 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
CAddrInfo& info = mapInfo[nId]; CAddrInfo& info = mapInfo[nId];
if (info.IsReachableNetwork()) { if (info.IsReachableNetwork()) {
//deprioritize unreachable networks //deprioritize unreachable networks
fReachableFactor = 0.25; fReachableFactor = kUnreachableDeprioritize;
} }
if (info.IsJustTried()) { if (info.IsJustTried()) {
//deprioritize entries just tried //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; return info;
fChanceFactor *= 1.2; fChanceFactor *= kChanceFactorGrowth;
} }
} }

View File

@@ -41,7 +41,11 @@
/// \cond INTERNAL /// \cond INTERNAL
#define CC_MAXVINS 1024 #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 SMALLVAL 0.000000000000001
#define SATOSHIDEN ((uint64_t)100000000L) #define SATOSHIDEN ((uint64_t)100000000L)
@@ -58,7 +62,8 @@ struct CC_utxo
/// \endcond /// \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 struct CCcontract_info
{ {
uint8_t evalcode; //!< cc contract eval code, set by CCinit function 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); 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, /// 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 /// @param scriptSig scriptSig to check\n
/// Example: /// Example:
/// \code /// \code
@@ -283,7 +288,7 @@ bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector<CPubKey> &vin
/// cp = CCinit(&C, EVAL_ASSETS); /// cp = CCinit(&C, EVAL_ASSETS);
/// CPubKey ccAssetsPk = GetUnspendable(cp, ccAssetsPriv); /// CPubKey ccAssetsPk = GetUnspendable(cp, ccAssetsPriv);
/// \endcode /// \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); CPubKey GetUnspendable(struct CCcontract_info *cp,uint8_t *unspendablepriv);
// CCutils // CCutils
@@ -373,7 +378,7 @@ int64_t CCfullsupply(uint256 tokenid);
/// @returns true if success /// @returns true if success
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); 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 /// @returns public key as byte array
std::vector<uint8_t> Mypubkey(); std::vector<uint8_t> Mypubkey();
@@ -404,8 +409,8 @@ extern std::vector<CPubKey> 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<CPubKey> pubkeys = NULL_pubkeys); std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector<CPubKey> 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. /// 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. /// 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 hushd daemon, it allows tracking of all the CC addresses. /// 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 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. /// 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); 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. /// 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 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 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 /// @param maxinputs maximum number of inputs to add

View File

@@ -38,7 +38,8 @@ struct NSPV_ntzargs
int32_t NSPV_notarization_find(struct NSPV_ntzargs *args,int32_t height,int32_t dir) 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<uint8_t> opret; int32_t ntzheight = 0; uint256 hashBlock; CTransaction tx; Notarization nota; char *symbol; std::vector<uint8_t> 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)); memset(args,0,sizeof(*args));
if ( dir > 0 ) if ( dir > 0 )
height += 10; height += 10;

View File

@@ -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); 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; const bool ishush3 = strncmp(symbol, "HUSH3",5) == 0 ? true : false;
if(ishush3) { if(ishush3) {
return HUSH_MAGIC; return HUSH_MAGIC;
@@ -1493,16 +1496,19 @@ uint64_t hush_max_money()
return hush_current_supply(10000000); return hush_current_supply(10000000);
} }
// This implements the Hush Emission Curve, the miner subsidy part, // This implements the emission curve (miner subsidy part) and must be kept in
// and must be kept in sync with hush_commision() in hush_bitcoind.h! // sync with hush_commission() in hush_bitcoind.h! Changing these functions,
// Changing these functions are consensus changes! // including the height literals below, is a CONSENSUS change.
// Here Be Dragons! -- Duke Leto // 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 hush_block_subsidy(int height)
{ {
uint64_t subsidy = 0; uint64_t subsidy = 0;
int32_t HALVING1 = GetArg("-z2zheight",340000); int32_t HALVING1 = GetArg("-z2zheight",340000);
//TODO: support INTERVAL :( //TODO: support INTERVAL :(
//int32_t INTERVAL = GetArg("-ac_halving1",840000); //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; int32_t TRANSITION = 128;
if (height < TRANSITION) { if (height < TRANSITION) {
@@ -1585,7 +1591,9 @@ uint64_t hush_block_subsidy(int height)
return subsidy; 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) uint64_t hush_sc_block_subsidy(int nHeight)
{ {
// Find current era, start from beginning reward, and determine current subsidy // 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; int64_t subsidyDifference;
int32_t numhalvings = 0, curEra = 0, sign = 1; int32_t numhalvings = 0, curEra = 0, sign = 1;
static uint64_t cached_subsidy; static int32_t cached_numhalvings; static int cached_era; 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; 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 // 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) if(fDebug)
fprintf(stderr,"%s: HUSH3 subsidy=%ld at height=%d\n",__func__,subsidy,nHeight); fprintf(stderr,"%s: HUSH3 subsidy=%ld at height=%d\n",__func__,subsidy,nHeight);
} else if ( (numhalvings = ((nHeight - nStart) / ASSETCHAINS_HALVING[curEra])) > 0 ) { } 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 ) { if ( ASSETCHAINS_DECAY[curEra] == 0 ) {
subsidy >>= numhalvings; subsidy >>= numhalvings;
} else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 ) { } else if ( ASSETCHAINS_DECAY[curEra] == 100000000 && ASSETCHAINS_ENDSUBSIDY[curEra] != 0 ) {
@@ -1991,7 +2003,8 @@ void hush_args(char *argv0)
uint8_t prevCCi = 0; uint8_t prevCCi = 0;
ASSETCHAINS_CCLIB = GetArg("-ac_cclib","hush3"); 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); Split(GetArg("-ac_ccenable","228,234,235,236,241"), sizeof(ccenables)/sizeof(*ccenables), ccenables, 0);
for (i=nonz=0; i<0x100; i++) for (i=nonz=0; i<0x100; i++)
{ {
@@ -2376,6 +2389,9 @@ void hush_args(char *argv0)
} }
} }
} else { } 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; char fname[512],username[512],password[4096]; int32_t iter; FILE *fp;
ASSETCHAINS_P2PPORT = 7770; ASSETCHAINS_P2PPORT = 7770;
ASSETCHAINS_RPCPORT = 7771; ASSETCHAINS_RPCPORT = 7771;

View File

@@ -121,7 +121,11 @@ static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
static const char* DEFAULT_ASMAP_FILENAME="asmap.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 // Shutdown
// //
@@ -622,7 +626,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-stratumport=<port>", strprintf(_("Listen for Stratum work requests on <port> (default: %u or testnet: %u)"), BaseParams().StratumPort(), BaseParams().StratumPort())); strUsage += HelpMessageOpt("-stratumport=<port>", strprintf(_("Listen for Stratum work requests on <port> (default: %u or testnet: %u)"), BaseParams().StratumPort(), BaseParams().StratumPort()));
strUsage += HelpMessageOpt("-stratumallowip=<ip>", _("Allow Stratum work requests from specified source. Valid for <ip> 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")); strUsage += HelpMessageOpt("-stratumallowip=<ip>", _("Allow Stratum work requests from specified source. Valid for <ip> 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 += HelpMessageGroup(_("DragonX Chain options:"));
strUsage += HelpMessageOpt("-ac_algo", _("Choose PoW mining algorithm, either 'equihash' or 'randomx'. default is Equihash (200,9)")); 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")); strUsage += HelpMessageOpt("-ac_blocktime", _("Block time in seconds, default is 60"));
@@ -789,7 +793,7 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
} }
/** Sanity checks /** 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. * necessary library support.
*/ */
bool InitSanityCheck(void) bool InitSanityCheck(void)
@@ -910,7 +914,7 @@ static void ZC_LoadParams(const CChainParams& chainparams)
if (!found) { if (!found) {
// The traditional place Zcash params are stored, should not hit this case in normal circumstances, // 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_spend = ZC_GetParamsDir() / "sapling-spend.params";
sapling_output = ZC_GetParamsDir() / "sapling-output.params"; sapling_output = ZC_GetParamsDir() / "sapling-output.params";
if (files_exist(sapling_spend, sapling_output)) { if (files_exist(sapling_spend, sapling_output)) {
@@ -987,6 +991,10 @@ bool AppInitServers(boost::thread_group& threadGroup)
RPCServer::OnPreCommand(&OnRPCPreCommand); RPCServer::OnPreCommand(&OnRPCPreCommand);
if (!InitHTTPServer()) if (!InitHTTPServer())
return false; 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()) if (GetBoolArg("-stratum", DEFAULT_STRATUM_ENABLE) && !InitStratumServer())
return false; return false;
if (!StartRPC()) if (!StartRPC())
@@ -1000,7 +1008,7 @@ bool AppInitServers(boost::thread_group& threadGroup)
return true; return true;
} }
/** Initialize Hush. /** Initialize DragonX.
* @pre Parameters should be parsed and config file should be read. * @pre Parameters should be parsed and config file should be read.
*/ */
extern int32_t HUSH_REWIND; 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("\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 #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__); 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)) { if (GetArg("-asmap",1)) {
fs::path asmap_path = fs::path(GetArg("-asmap", "")); 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)) { if(fs::exists(asmap_path)) {
LogPrint("net", "%s: found asmap file at %s\n", __func__, asmap_path.c_str() ); LogPrint("net", "%s: found asmap file at %s\n", __func__, asmap_path.c_str() );
} else { } else {
// Shit is fucked up, die an honorable death // No asmap file found in any known location; abort startup.
InitError(strprintf(_("Could not find any asmap file! Please report this bug to Hush Developers"))); InitError(strprintf(_("Could not find any asmap file! Please report this bug to DragonX Developers")));
return false; return false;
} }
} }
@@ -1637,7 +1645,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// Sanity check // Sanity check
if (!InitSanityCheck()) 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(); std::string strDataDir = GetDataDir().string();
#ifdef ENABLE_WALLET #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)) if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile))
return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir)); return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir));
#endif #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"; boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
if (file) fclose(file); 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("\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) if (fPrintToDebugLog)
OpenDebugLog(); OpenDebugLog();
@@ -2066,7 +2074,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview);
pcoinsTip = new CCoinsViewCache(pcoinscatcher); pcoinsTip = new CCoinsViewCache(pcoinscatcher);
try { try {
pnotarizations = new NotarizationDB(100*1024*1024, false, fReindex); pnotarizations = new NotarizationDB(NOTARIZATION_DB_CACHE_BYTES, false, fReindex);
} catch (const std::exception& e) { } catch (const std::exception& e) {
// The notarizations (dPoW) DB is non-essential and node-regenerable. It has been seen to // 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 // 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::remove_all(ndir.string() + ".corrupt");
boost::filesystem::rename(ndir, 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); InitWarning(msg);
} }
else if (nLoadWalletRet == DB_TOO_NEW) 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) 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()); LogPrintf("%s", strErrors.str());
return InitError(strErrors.str()); return InitError(strErrors.str());
} }
@@ -2664,10 +2672,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
#ifdef ENABLE_MINING #ifdef ENABLE_MINING
#ifndef ENABLE_WALLET #ifndef ENABLE_WALLET
if (GetBoolArg("-minetolocalwallet", false)) { 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)) { 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 #endif // !ENABLE_WALLET

View File

@@ -56,7 +56,7 @@ extern uint8_t ASSETCHAINS_CLEARNET;
// Run asmap health check every 24hr by default // Run asmap health check every 24hr by default
#define ASMAP_HEALTHCHECK_INTERVAL 24*60*60 #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 DUMP_ZINDEX_INTERVAL 150
#define CHECK_PLZ_STOP_INTERVAL 120 #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. // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
#define FEELER_SLEEP_WINDOW 1 #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) #if defined(USE_TLS) && !defined(TLS1_3_VERSION)
// minimum secure protocol is 1.3 // minimum secure protocol is 1.3
@@ -815,7 +817,7 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
nPingUsecWait = GetTimeMicros() - nPingUsecStart; 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.dPingTime = (((double)nPingUsecTime) / 1e6);
stats.dMinPing = (((double)nMinPingUsecTime) / 1e6); stats.dMinPing = (((double)nMinPingUsecTime) / 1e6);
stats.dPingWait = (((double)nPingUsecWait) / 1e6); stats.dPingWait = (((double)nPingUsecWait) / 1e6);
@@ -2514,7 +2516,9 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
return; 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); auto newSize = (vNodes.size() / 2) == 0 ? 1 : (vNodes.size() / 2);
std::shuffle( vRelayNodes.begin(), vRelayNodes.end(), std::mt19937(GetRand(std::numeric_limits<uint32_t>::max())) ); std::shuffle( vRelayNodes.begin(), vRelayNodes.end(), std::mt19937(GetRand(std::numeric_limits<uint32_t>::max())) );
@@ -2773,7 +2777,7 @@ bool CNode::GetTlsValidate()
{ {
if (tlsValidate == eTlsOption::FALLBACK_UNSET) 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 // on a closed VPN with an internal CA or trusted cert system, or
// various other use cases // various other use cases
if ( GetBoolArg("-tlsvalidate", false)) { if ( GetBoolArg("-tlsvalidate", false)) {

View File

@@ -44,9 +44,12 @@
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/signals2/signal.hpp> #include <boost/signals2/signal.hpp>
// Enable WolfSSL Support for Hush // Enable WolfSSL support for DragonX
#include <wolfssl/options.h> #include <wolfssl/options.h>
// 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 ECC_TIMING_RESISTANT
#undef TFM_TIMING_RESISTANT #undef TFM_TIMING_RESISTANT
#define ECC_TIMING_RESISTANT 420 #define ECC_TIMING_RESISTANT 420

View File

@@ -414,7 +414,10 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
// Changing this requires changing many other things and // Changing this requires changing many other things and
// might change consensus. Have fun -- Duke // 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() { int64_t AveragingWindowTimespan() {
// used in const methods, beware! // used in const methods, beware!
// This is the correct AWT for 75s blocktime, before block 340k // 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; int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime;
LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan); 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; 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(); int64_t AWT = ishush3 ? AveragingWindowTimespan() : params.AveragingWindowTimespan();
nActualTimespan = AWT + (nActualTimespan - AWT)/4; nActualTimespan = AWT + (nActualTimespan - AWT)/4;
@@ -481,8 +487,9 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
return bnNew.GetCompact(); return bnNew.GetCompact();
} }
// HUSH does not use these functions but Hush Arrakis Chains can opt-in to using more bleeding edge DAA's // These LWMA difficulty functions are inherited from the Hush lineage and are only used when
// ASIC chains do not need these protections as much -- Duke Leto // 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) unsigned int lwmaGetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{ {
return lwmaCalculateNextWorkRequired(pindexLast, params); return lwmaCalculateNextWorkRequired(pindexLast, params);

View File

@@ -672,7 +672,7 @@ std::string GetWorkUnit(StratumClient& client)
} */ } */
/* if (!Params().MineBlocksOnDemand() && g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) { /* 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; bool fvNodesEmpty;
@@ -683,21 +683,21 @@ std::string GetWorkUnit(StratumClient& client)
if (Params().MiningRequiresPeers() && fvNodesEmpty) 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); 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()) { 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); 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()) { 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__); 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); 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 static CBlockIndex* tip = NULL; // pindexPrev
@@ -924,6 +924,15 @@ bool SubmitBlock(StratumClient& client, const uint256& job_id, const StratumWork
const std::vector<unsigned char>& extranonce1, const std::vector<unsigned char>& extranonce2, const std::vector<unsigned char>& extranonce1, const std::vector<unsigned char>& extranonce2,
boost::optional<uint32_t> nVersion, uint32_t nTime, const std::vector<unsigned char>& sol) boost::optional<uint32_t> nVersion, uint32_t nTime, const std::vector<unsigned char>& 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: // called from stratum_mining_submit and uses following data, came from client:
// ["WORKER_NAME", "JOB_ID", "TIME", "NONCE_2", "EQUIHASH_SOLUTION"] // ["WORKER_NAME", "JOB_ID", "TIME", "NONCE_2", "EQUIHASH_SOLUTION"]
// all other params we have saved in other places // 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); 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) { if (sol.size() != 1347) {
std::string msg = strprintf("%s: solution is wrong length (received %d bytes; expected %d bytes", __func__, extranonce2.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); 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 // This means a miner can run a private pool without TLS and not
// worry about MITM attacks that change addresses, and leaks less metadata. // 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 // 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") { if(addr.ToString() == "x") {
addr = CBitcoinAddress(GetArg("-stratumaddress", "")); addr = CBitcoinAddress(GetArg("-stratumaddress", ""));
const std::string msg = strprintf("%s: Authorized client with default stratum address=%s", __func__, addr.ToString()); 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()) { 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); 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; 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) 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 // {"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). // 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() bool InitStratumServer()
{ {
LOCK(cs_stratum); LOCK(cs_stratum);

View File

@@ -285,8 +285,9 @@ bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockF
std::pair<char, uint256> key = make_pair(DB_BLOCK_INDEX, it->GetBlockHash()); std::pair<char, uint256> key = make_pair(DB_BLOCK_INDEX, it->GetBlockHash());
try { try {
CDiskBlockIndex dbindex {it, [this, &key]() { 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. // 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; CDiskBlockIndex dbindex_old;
if (!Read(key, dbindex_old)) { if (!Read(key, dbindex_old)) {
LogPrintf("%s: Failed to read index entry", __func__); LogPrintf("%s: Failed to read index entry", __func__);
@@ -698,7 +699,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nTime = diskindex.nTime; pindexNew->nTime = diskindex.nTime;
pindexNew->nBits = diskindex.nBits; pindexNew->nBits = diskindex.nBits;
pindexNew->nNonce = diskindex.nNonce; 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->nSolution = diskindex.nSolution;
pindexNew->nStatus = diskindex.nStatus; pindexNew->nStatus = diskindex.nStatus;
pindexNew->nCachedBranchId = diskindex.nCachedBranchId; pindexNew->nCachedBranchId = diskindex.nCachedBranchId;

View File

@@ -499,27 +499,35 @@ boost::filesystem::path GetDefaultDataDir()
if ( SMART_CHAIN_SYMBOL[0] != 0 ) if ( SMART_CHAIN_SYMBOL[0] != 0 )
strcpy(symbol,SMART_CHAIN_SYMBOL); strcpy(symbol,SMART_CHAIN_SYMBOL);
else symbol[0] = 0; else symbol[0] = 0;
// OLD NAMES: // DragonX stores its data under a per-chain subdirectory named after
// Windows < Vista: C:\Documents and Settings\Username\Application Data\Komodo // SMART_CHAIN_SYMBOL (which is "DRAGONX"), so the default datadir resolves
// Windows >= Vista: C:\Users\Username\AppData\Roaming\Komodo // to (Unix) ~/.hush/DRAGONX, (Mac) ~/Library/Application Support/Hush/DRAGONX,
// Mac: ~/Library/Application Support/Komodo // or (Windows) %APPDATA%\Hush\DRAGONX.
// Unix: ~/.komodo //
// 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:\Documents and Settings\Username\Application Data\Hush
// Windows >= Vista: C:\Users\Username\AppData\Roaming\Hush // Windows >= Vista: C:\Users\Username\AppData\Roaming\Hush
// Mac: ~/Library/Application Support/Hush // Mac: ~/Library/Application Support/Hush
// Unix: ~/.hush // Unix: ~/.hush
// ~/.hush was actually used by the original 1.x version of Hush, but we will // Legacy fallback (only used if such a directory already exists):
// only make subdirectories inside of it, so we won't be able to overwrite // Windows < Vista: C:\Documents and Settings\Username\Application Data\Komodo
// an old wallet.dat from the Ice Ages :) // Windows >= Vista: C:\Users\Username\AppData\Roaming\Komodo
// Mac: ~/Library/Application Support/Komodo
// Unix: ~/.komodo
fs::path pathRet; fs::path pathRet;
#ifdef _WIN32 #ifdef _WIN32
// Windows // Windows
pathRet = GetSpecialFolderPath(CSIDL_APPDATA) / "Hush" / symbol; pathRet = GetSpecialFolderPath(CSIDL_APPDATA) / "Hush" / symbol;
// Always use .hush/HUSH3, if it exists (even if .komodo/HUSH3 exists) // Always use Hush\<symbol> (Hush\DRAGONX) if it exists, even if the legacy
// Komodo\<symbol> directory also exists.
if(fs::is_directory(pathRet)) { if(fs::is_directory(pathRet)) {
return pathRet; return pathRet;
} else { } else {
@@ -528,7 +536,7 @@ boost::filesystem::path GetDefaultDataDir()
// existing legacy directory, use that for backward compat // existing legacy directory, use that for backward compat
return pathRet; return pathRet;
} else { } else {
// For new clones, use Hush/ACNAME // For new nodes, use Hush\<symbol>
pathRet = GetSpecialFolderPath(CSIDL_APPDATA) / "Hush" / symbol; pathRet = GetSpecialFolderPath(CSIDL_APPDATA) / "Hush" / symbol;
return pathRet; return pathRet;
} }
@@ -551,7 +559,7 @@ boost::filesystem::path GetDefaultDataDir()
// create Library/Application Support/Hush if it doesn't exist // create Library/Application Support/Hush if it doesn't exist
TryCreateDirectory(tmppath); TryCreateDirectory(tmppath);
// Always use Hush/HUSH3 if it exists // Always use Hush/<symbol> (Hush/DRAGONX) if it exists
if(fs::is_directory(tmppath / symbol)) { if(fs::is_directory(tmppath / symbol)) {
return tmppath / symbol; return tmppath / symbol;
} else { } else {
@@ -563,16 +571,16 @@ boost::filesystem::path GetDefaultDataDir()
// Found legacy dir, use that // Found legacy dir, use that
return tmppath / symbol; return tmppath / symbol;
} else { } else {
// For new clones, use Hush/ACNAME // For new nodes, use Hush/<symbol>
tmppath = pathRet / "Hush" / symbol; tmppath = pathRet / "Hush" / symbol;
} }
return tmppath; return tmppath;
} }
#else #else
// Unix // Unix: current default datadir is ~/.hush/<symbol> (i.e. ~/.hush/DRAGONX)
// New directory :)
fs::path tmppath = pathRet / ".hush" / symbol; fs::path tmppath = pathRet / ".hush" / symbol;
// Always use .hush/HUSH3, if it exists (even if .komodo/HUSH3 exists) // Always use ~/.hush/<symbol> (~/.hush/DRAGONX) if it exists, even if the
// legacy ~/.komodo/<symbol> directory also exists.
if(fs::is_directory(tmppath)) { if(fs::is_directory(tmppath)) {
return tmppath; return tmppath;
} else { } else {
@@ -582,7 +590,7 @@ boost::filesystem::path GetDefaultDataDir()
// existing legacy directory, use that for backward compat // existing legacy directory, use that for backward compat
return tmppath; return tmppath;
} else { } else {
// For new clones, use .hush/ACNAME // For new nodes, use ~/.hush/<symbol>
tmppath = pathRet / ".hush" / symbol; tmppath = pathRet / ".hush" / symbol;
} }
return tmppath; return tmppath;
@@ -598,13 +606,17 @@ static CCriticalSection csPathCached;
static boost::filesystem::path ZC_GetBaseParamsDir() 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; namespace fs = boost::filesystem;
// Windows < Vista: C:\Documents and Settings\Username\Application Data\ZcashParams // Windows < Vista: C:\Documents and Settings\Username\Application Data\ZcashParams
// Windows >= Vista: C:\Users\Username\AppData\Roaming\ZcashParams // Windows >= Vista: C:\Users\Username\AppData\Roaming\ZcashParams
// Mac: ~/Library/Application Support/ZcashParams // Mac: ~/Library/Application Support/ZcashParams
// Unix: ~/.zcash-params // Unix: ~/.zcash-params
// Debian packages: /usr/share/hush // System-wide install (Debian packages): /usr/share/hush
fs::path pathRet; fs::path pathRet;
#ifdef _WIN32 #ifdef _WIN32
return GetSpecialFolderPath(CSIDL_APPDATA) / "ZcashParams"; return GetSpecialFolderPath(CSIDL_APPDATA) / "ZcashParams";

View File

@@ -20,6 +20,12 @@
CAmount fConsolidationTxFee = DEFAULT_CONSOLIDATION_FEE; CAmount fConsolidationTxFee = DEFAULT_CONSOLIDATION_FEE;
bool fConsolidationMapUsed = false; 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(); extern string randomSietchZaddr();
AsyncRPCOperation_saplingconsolidation::AsyncRPCOperation_saplingconsolidation(int targetHeight) : targetHeight_(targetHeight) {} AsyncRPCOperation_saplingconsolidation::AsyncRPCOperation_saplingconsolidation(int targetHeight) : targetHeight_(targetHeight) {}
@@ -238,10 +244,10 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() {
builder.AddSaplingOutput(extsk.expsk.ovk, addr, actualAmountToSend); 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); LogPrint("zrpcunsafe", "%s: Added consolidation output %s with amount=%li\n", opid, addr.GetHash().ToString().c_str(), actualAmountToSend);
// Add sietch zouts // Add sietch zouts: MIN_ZOUTS dummy zero-value shielded outputs to
int MIN_ZOUTS = 7; // randomly-generated z-addresses, so the consolidation tx does not
// shrink the anonymity set.
for(size_t i = 0; i < MIN_ZOUTS; i++) { for(size_t i = 0; i < MIN_ZOUTS; i++) {
// In Privacy Zdust We Trust -- Duke
string zdust = randomSietchZaddr(); string zdust = randomSietchZaddr();
auto zaddr = DecodePaymentAddress(zdust); auto zaddr = DecodePaymentAddress(zdust);
if (IsValidPaymentAddress(zaddr)) { if (IsValidPaymentAddress(zaddr)) {

View File

@@ -215,9 +215,10 @@ bool AsyncRPCOperation_sendmany::main_impl() {
bool isPureTaddrOnlyTx = (isfromtaddr_ && z_outputs_.size() == 0); bool isPureTaddrOnlyTx = (isfromtaddr_ && z_outputs_.size() == 0);
CAmount minersFee = fee_; CAmount minersFee = fee_;
// TODO: fix this garbage ZEC prisoner mindset bullshit // Coinbase-change routing constraint:
// When spending coinbase utxos, you can only specify a single zaddr as the change must go somewhere // When spending coinbase UTXOs, only a single zaddr recipient may be specified, because the
// and if there are multiple zaddrs, we don't know where to send it. // 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 (isfromtaddr_) {
if (isSingleZaddrOutput) { if (isSingleZaddrOutput) {
bool b = find_utxos(true); bool b = find_utxos(true);
@@ -354,8 +355,8 @@ bool AsyncRPCOperation_sendmany::main_impl() {
/** /**
* SCENARIO #0 (All HUSH and Hush Arrakis Chains) * SCENARIO #0 (DragonX and all Sapling-only chains)
* Sprout not involved, so we just use the TransactionBuilder and we're done. * Sprout is not involved, so we just use the TransactionBuilder and we're done.
* We added the transparent inputs to the builder earlier. * We added the transparent inputs to the builder earlier.
*/ */
if (isUsingBuilder_) { if (isUsingBuilder_) {
@@ -506,7 +507,8 @@ bool AsyncRPCOperation_sendmany::main_impl() {
return true; return true;
} }
// END SCENARIO #0 // 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; return false;
} }
@@ -668,7 +670,8 @@ void AsyncRPCOperation_sendmany::add_taddr_outputs_to_tx() {
rawTx.vout.push_back(out); rawTx.vout.push_back(out);
} }
if ( !hush_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) 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 else
rawTx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); rawTx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast();
@@ -698,7 +701,8 @@ void AsyncRPCOperation_sendmany::add_taddr_change_output_to_tx(CBitcoinAddress *
CMutableTransaction rawTx(tx_); CMutableTransaction rawTx(tx_);
rawTx.vout.push_back(out); rawTx.vout.push_back(out);
if ( !hush_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) 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 else
rawTx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); rawTx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast();
tx_ = CTransaction(rawTx); tx_ = CTransaction(rawTx);

View File

@@ -24,7 +24,10 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
// 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 ECC_TIMING_RESISTANT
#undef TFM_TIMING_RESISTANT #undef TFM_TIMING_RESISTANT
#define ECC_TIMING_RESISTANT 420 #define ECC_TIMING_RESISTANT 420
@@ -306,7 +309,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
} }
if (keyPass && keyFail) 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); assert(false);
} }
if (keyFail || !keyPass) if (keyFail || !keyPass)

View File

@@ -169,7 +169,8 @@ private:
CKeyingMaterial vMasterKey; 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 //! if fUseCrypto is false, vMasterKey must be empty
bool fUseCrypto; bool fUseCrypto;

View File

@@ -95,7 +95,7 @@ UniValue convertpassphrase(const UniValue& params, bool fHelp, const CPubKey& my
"1. \"agamapassphrase\" (string, required) Agama passphrase\n" "1. \"agamapassphrase\" (string, required) Agama passphrase\n"
"\nResult:\n" "\nResult:\n"
"\"agamapassphrase\": \"agamapassphrase\", (string) Agama passphrase you entered\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" "\"pubkey\": \"publickeyhex\", (string) The hex value of the raw public key\n"
"\"privkey\": \"privatekeyhex\", (string) The hex value of the raw private 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" "\"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) if (fHelp || params.size() < 1 || params.size() > 5)
throw runtime_error( 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" "\nAdds a private key (as returned by dumpprivkey) to your wallet.\n"
"\nArguments:\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" "2. \"label\" (string, optional, default=\"\") An optional label\n"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
"4. height (integer, optional, default=0) start at block height?\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<unsigned char> data(ParseHex(params[0].get_str())); std::vector<unsigned char> data(ParseHex(params[0].get_str()));
script = CScript(data.begin(), data.end()); script = CScript(data.begin(), data.end());
} else { } 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 = ""; string strLabel = "";
@@ -504,7 +504,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys
if (vstr.size() < 2) if (vstr.size() < 2)
continue; 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) { if (fImportZKeys) {
auto spendingkey = DecodeSpendingKey(vstr[0]); auto spendingkey = DecodeSpendingKey(vstr[0]);
int64_t nTime = DecodeDumpTime(vstr[1]); int64_t nTime = DecodeDumpTime(vstr[1]);
@@ -524,7 +524,7 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys
continue; continue;
} else { } else {
LogPrintf("%s: Importing detected an error: invalid spending key. Trying as a transparent key...\n",__func__); 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" "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" "\nExports all wallet keys, for taddr and zaddr, in a human-readable format. Overwriting an existing file is not permitted.\n"
"\nArguments:\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" "\nResult:\n"
"\"path\" (string) The full path of the destination file\n" "\"path\" (string) The full path of the destination file\n"
"\nExamples:\n" "\nExamples:\n"
@@ -680,7 +680,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp, const CPubKey& mypk)
"dumpwallet \"filename\"\n" "dumpwallet \"filename\"\n"
"\nDumps taddr wallet keys in a human-readable format. Overwriting an existing file is not permitted.\n" "\nDumps taddr wallet keys in a human-readable format. Overwriting an existing file is not permitted.\n"
"\nArguments:\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" "\nResult:\n"
"\"path\" (string) The full path of the destination file\n" "\"path\" (string) The full path of the destination file\n"
"\nExamples:\n" "\nExamples:\n"
@@ -736,7 +736,7 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys)
std::sort(vKeyBirth.begin(), vKeyBirth.end()); std::sort(vKeyBirth.begin(), vKeyBirth.end());
// produce output // 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("# * 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("# * 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())); file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime()));

View File

@@ -364,7 +364,7 @@ UniValue setaccount(const UniValue& params, bool fHelp, const CPubKey& mypk)
CTxDestination dest = DecodeDestination(params[0].get_str()); CTxDestination dest = DecodeDestination(params[0].get_str());
if (!IsValidDestination(dest)) { 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; string strAccount;
@@ -411,7 +411,7 @@ UniValue getaccount(const UniValue& params, bool fHelp, const CPubKey& mypk)
CTxDestination dest = DecodeDestination(params[0].get_str()); CTxDestination dest = DecodeDestination(params[0].get_str());
if (!IsValidDestination(dest)) { 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; std::string strAccount;
@@ -571,7 +571,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk)
CTxDestination dest = DecodeDestination(params[0].get_str()); CTxDestination dest = DecodeDestination(params[0].get_str());
if (!IsValidDestination(dest)) { if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Hush address!"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid DragonX address!");
} }
// Amount // 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(); height = chainActive.LastTip()->GetHeight();
if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 )
ret.push_back(Pair("owner",refpubkey.GetHex())); ret.push_back(Pair("owner",refpubkey.GetHex()));
@@ -895,7 +896,7 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp, const CPubKey&
// Bitcoin address // Bitcoin address
CTxDestination dest = DecodeDestination(params[0].get_str()); CTxDestination dest = DecodeDestination(params[0].get_str());
if (!IsValidDestination(dest)) { 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); CScript scriptPubKey = GetScriptForDestination(dest);
if (!IsMine(*pwalletMain, scriptPubKey)) { if (!IsMine(*pwalletMain, scriptPubKey)) {
@@ -1452,7 +1453,7 @@ UniValue sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk)
CScript tmpspk; CScript tmpspk;
tmpspk << ParseHex(name_) << OP_CHECKSIG; tmpspk << ParseHex(name_) << OP_CHECKSIG;
if ( !ExtractDestination(tmpspk, dest, true) ) 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); 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 // slack space in .dat files; that is bad if the old data is
// unencrypted private keys. So: // unencrypted private keys. So:
StartShutdown(); 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) 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" " \"txid\" : \"txid\", (string) the transaction id \n"
" \"vout\" : n, (numeric) the vout value\n" " \"vout\" : n, (numeric) the vout value\n"
" \"generated\" : true|false (boolean) true if txout is a coinbase transaction output\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" " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
" \"scriptPubKey\" : \"key\", (string) the script key\n" " \"scriptPubKey\" : \"key\", (string) the script key\n"
" \"amount\" : x.xxx, (numeric) the transaction amount in " + CURRENCY_UNIT + "\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]; const UniValue& input = inputs[idx];
CTxDestination dest = DecodeDestination(input.get_str()); CTxDestination dest = DecodeDestination(input.get_str());
if (!IsValidDestination(dest)) { 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) { if (!destinations.insert(dest).second) {
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + input.get_str()); 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." "This function is slow if no filters are given, use z_listreceivedbyaddress if you do not need filters."
"\n" "\n"
"\nArguments:\n" "\nArguments:\n"
"1. \"hushaddress:\" (string, required) \n" "1. \"dragonxaddress:\" (string, required) \n"
"\n" "\n"
"2. \"Minimum Confimations:\" (numeric, optional, default=0) \n" "2. \"Minimum Confimations:\" (numeric, optional, default=0) \n"
"\n" "\n"
@@ -3460,13 +3461,13 @@ UniValue z_listreceivedaddress(const UniValue& params, bool fHelp,const CPubKey&
" \"walletconflicts\": [conflicts], An array of wallet conflicts\n" " \"walletconflicts\": [conflicts], An array of wallet conflicts\n"
" \"recieved\": { A list of receives from the transaction\n" " \"recieved\": { A list of receives from the transaction\n"
" \"transparentReceived\": [{ An Array of txos received for transparent addresses\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" " \"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" " \"amount\": x.xxxx, (numeric) Value of output being received " + CURRENCY_UNIT + ", positive for receives\n"
" \"vout\": : n, (numeric) the vout value\n" " \"vout\": : n, (numeric) the vout value\n"
" }],\n" " }],\n"
" \"saplingReceived\": [{ An Array of utxos/notes received for sapling addresses\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" " \"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" " \"memo\": xxxxx, (string) hexademical string representation of memo field\n"
" \"memoStr\" : \"memo\", (string) Only returned if memo contains valid UTF-8 text.\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) if (fHelp || params.size() > 5 || params.size() == 3)
throw runtime_error( throw runtime_error(
"z_listsentbyaddress\n" "z_listsentbyaddress\n"
"\nReturns decrypted Hush outputs sent to a single address.\n" "\nReturns decrypted DragonX outputs sent to a single address.\n"
"\n" "\n"
"This function only returns information on addresses sent from wallet addresses with full spending keys." "This function only returns information on addresses sent from wallet addresses with full spending keys."
"\n" "\n"
"\nArguments:\n" "\nArguments:\n"
"1. \"hushaddress:\" (string, required) \n" "1. \"dragonxaddress:\" (string, required) \n"
"\n" "\n"
"2. \"Minimum Confimations:\" (numeric, optional, default=0) \n" "2. \"Minimum Confimations:\" (numeric, optional, default=0) \n"
"\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" " \"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" " 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" " \"transparentSends\": [{ An Array of spends (outputs) for transparent addresses of the receipient\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 Hush 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" " \"amount\": x.xxxx, (numeric) Value of output being sent " + CURRENCY_UNIT + ", negative for sends\n"
" \"vout\": : n, (numeric) the vout value\n" " \"vout\": : n, (numeric) the vout value\n"
" }],\n" " }],\n"
" \"saplingSends\": [{ An Array of spends (outputs) for sapling addresses\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" " \"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" " \"memo\": xxxxx, (string) hexademical string representation of memo field\n"
" \"memoStr\" : \"memo\", (string) Only returned if memo contains valid UTF-8 text.\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(); string address = o.get_str();
auto zaddr = DecodePaymentAddress(address); auto zaddr = DecodePaymentAddress(address);
if (!IsValidPaymentAddress(zaddr)) { 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); auto hasSpendingKey = boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr);
if (!fIncludeWatchonly && !hasSpendingKey) { 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 // 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 // but they don't because wtx.GetAmounts() does not handle tx where there are no outputs
// pwalletMain->GetBalance() does not accept min depth parameter // 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 nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly);
CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, !fIncludeWatchonly); CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, !fIncludeWatchonly);
CAmount nTotalBalance = nBalance + nPrivateBalance; 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" " \"rk\" : \"rk\", (string) The rk\n"
" \"zkproof\" : \"zkproof\", (string) Hexadecimal string representation of raw zksnark proof\n" " \"zkproof\" : \"zkproof\", (string) Hexadecimal string representation of raw zksnark proof\n"
" \"outputPrev\" : n, (numeric) the index of the output within the vShieldedOutput\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" " \"value\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n"
" \"valueZat\" : xxxx (numeric) The amount in puposhis\n" " \"valueZat\" : xxxx (numeric) The amount in puposhis\n"
" }\n" " }\n"
@@ -4866,7 +4867,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp, const CPubKey& my
" {\n" " {\n"
" \"type\" : \"sapling\", (string) The type of address\n" " \"type\" : \"sapling\", (string) The type of address\n"
" \"output\" : n, (numeric) the index of the output within the vShieldedOutput\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" " \"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" " \"value\" : x.xxx (numeric) The amount in " + CURRENCY_UNIT + "\n"
" \"valueZat\" : xxxx (numeric) The amount in puposhis\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); 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); THROW_IF_SYNCING(HUSH_INSYNC);
// Check that the from address is valid. // 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 // 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 // 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 // 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 DEFAULT_MIN_ZOUTS=7;
unsigned int MAX_ZOUTS=50; unsigned int MAX_ZOUTS=50;
unsigned int MIN_ZOUTS=GetArg("-sietch-min-zouts", DEFAULT_MIN_ZOUTS); 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); txsize += GetSerializeSize(tx, SER_NETWORK, tx.nVersion);
if (fromTaddr) { if (fromTaddr) {
txsize += CTXIN_SPEND_DUST_SIZE; txsize += CTXIN_SPEND_DUST_SIZE;
//TODO: On HUSH since block 340k there can no longer be taddr change, // DragonX is ac_private=1 (fully shielded from genesis); transparent outputs are
// (except for notary addresses) // banned, so in practice there is no taddr change and this estimate is conservative.
// so we can likely make a better estimation of max txsize
txsize += CTXOUT_REGULAR_SIZE; // There will probably be taddr change txsize += CTXOUT_REGULAR_SIZE; // There will probably be taddr change
} }
txsize += CTXOUT_REGULAR_SIZE * taddrRecipients.size(); 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); 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); THROW_IF_SYNCING(HUSH_INSYNC);
// Validate the from address // 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); 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); THROW_IF_SYNCING(HUSH_INSYNC);
bool useAnyUTXO = false; bool useAnyUTXO = false;

View File

@@ -578,7 +578,7 @@ void CWallet::ChainTip(const CBlockIndex *pindex,
} }
void CWallet::RunSaplingSweep(int blockHeight) { 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)) { // if (!NetworkUpgradeActive(blockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
// return; // return;
// } // }
@@ -669,7 +669,7 @@ void CWallet::RunSaplingSweep(int blockHeight) {
} }
void CWallet::RunSaplingConsolidation(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)) { //if (!NetworkUpgradeActive(blockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) {
// return; // return;
//} //}
@@ -2380,7 +2380,7 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum)
case TX_SCRIPTHASH: case TX_SCRIPTHASH:
scriptID = CScriptID(uint160(vSolutions[0])); 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->GetCScript(scriptID, subscript))
{ {
// if this is a CLTV, handle it differently // if this is a CLTV, handle it differently
@@ -4580,7 +4580,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(), txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(),
std::numeric_limits<unsigned int>::max()-1)); std::numeric_limits<unsigned int>::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 // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
// const size_t limit = 0; // (size_t)GetArg("-mempooltxinputlimit", 0); // 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) { if (params.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight == Consensus::NetworkUpgrade::ALWAYS_ACTIVE) {
m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = nTime; m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = nTime;
} else { } 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 // 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); m_wallet->mapSaplingZKeyMetadata[ivk].nCreateTime = std::max((int64_t) 154051200, nTime);
} }