//static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward, int nNetworkId) { CMutableTransaction txNew; txNew.nVersion = 1; txNew.vin.resize(1); txNew.vout.resize(1); txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << std::vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); txNew.vout[0].nValue = genesisReward; txNew.vout[0].scriptPubKey = genesisOutputScript; CBlock genesis; genesis.nTime = nTime; genesis.nBits = nBits; genesis.nVersion = nVersion; genesis.vtx.push_back(txNew); genesis.hashPrevBlock.SetNull(); genesis.hashMerkleRoot = BlockMerkleRoot(genesis); genesis.sGRCAddress = ""; for (int i = nNonce; i < 99999999; i++) { genesis.nNonce = i; arith_uint256 hashTarget = arith_uint256().SetCompact(genesis.nBits); if (UintToArith256(genesis.GetHash()) <= hashTarget) break; } printf("NetworkID %f, Nonce %f, Genesis hash %s , MerkleRoot %s \n",(double)nNetworkId,(double)genesis.nNonce,genesis.GetHash().GetHex().c_str(), genesis.hashMerkleRoot.GetHex().c_str()); return genesis; }
uint256 GetMetaDExHash(const uint32_t propertyId) { SHA256_CTX shaCtx; SHA256_Init(&shaCtx); LOCK(cs_tally); std::vector<std::pair<arith_uint256, std::string> > vecMetaDExTrades; for (md_PropertiesMap::const_iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) { if (propertyId == 0 || propertyId == my_it->first) { const md_PricesMap& prices = my_it->second; for (md_PricesMap::const_iterator it = prices.begin(); it != prices.end(); ++it) { const md_Set& indexes = it->second; for (md_Set::const_iterator it = indexes.begin(); it != indexes.end(); ++it) { const CMPMetaDEx& obj = *it; std::string dataStr = GenerateConsensusString(obj); vecMetaDExTrades.push_back(std::make_pair(arith_uint256(obj.getHash().ToString()), dataStr)); } } } } std::sort (vecMetaDExTrades.begin(), vecMetaDExTrades.end()); for (std::vector<std::pair<arith_uint256, std::string> >::iterator it = vecMetaDExTrades.begin(); it != vecMetaDExTrades.end(); ++it) { const std::string& dataStr = it->second; SHA256_Update(&shaCtx, dataStr.c_str(), dataStr.length()); } uint256 metadexHash; SHA256_Final((unsigned char*)&metadexHash, &shaCtx); return metadexHash; }
unsigned int static DarkGravityWave(const CBlockIndex* pindexLast, const Consensus::Params& params) { /* current difficulty formula, gridcoin - DarkGravity v3, written by Evan Duffield - [email protected] */ const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); int64_t nPastBlocks = 24; // make sure we have at least (nPastBlocks + 1) blocks, otherwise just return powLimit if (!pindexLast || pindexLast->nHeight < nPastBlocks) { return bnPowLimit.GetCompact(); } const CBlockIndex *pindex = pindexLast; arith_uint256 bnPastTargetAvg; for (unsigned int nCountBlocks = 1; nCountBlocks <= nPastBlocks; nCountBlocks++) { arith_uint256 bnTarget = arith_uint256().SetCompact(pindex->nBits); if (nCountBlocks == 1) { bnPastTargetAvg = bnTarget; } else { // NOTE: that's not an average really... bnPastTargetAvg = (bnPastTargetAvg * nCountBlocks + bnTarget) / (nCountBlocks + 1); } if(nCountBlocks != nPastBlocks) { assert(pindex->pprev); // should never fail pindex = pindex->pprev; } } arith_uint256 bnNew(bnPastTargetAvg); int64_t nActualTimespan = pindexLast->GetBlockTime() - pindex->GetBlockTime(); // NOTE: is this accurate? nActualTimespan counts it for (nPastBlocks - 1) blocks only... int64_t nTargetTimespan = nPastBlocks * params.nPowTargetSpacing; if (nActualTimespan < nTargetTimespan/3) nActualTimespan = nTargetTimespan/3; if (nActualTimespan > nTargetTimespan*3) nActualTimespan = nTargetTimespan*3; // Retarget bnNew *= nActualTimespan; bnNew /= nTargetTimespan; if (bnNew > bnPowLimit) { bnNew = bnPowLimit; } return bnNew.GetCompact(); }
arith_uint256 GetPrevWorkForAlgoWithDecayV3(const CBlockIndex& block, int algo) { int nDistance = 0; arith_uint256 nWork; const CBlockIndex* pindex = █ pindex = pindex->pprev; while (pindex != NULL) { if (nDistance > 100) { return arith_uint256(0); } if (pindex->GetAlgo() == algo) { arith_uint256 nWork = GetBlockProofBase(*pindex); nWork *= (100 - nDistance); nWork /= 100; return nWork; } pindex = pindex->pprev; nDistance++; } return arith_uint256(0); }
int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params) { arith_uint256 r; int sign = 1; if (to.nChainWork > from.nChainWork) { r = to.nChainWork - from.nChainWork; } else { r = from.nChainWork - to.nChainWork; sign = -1; } r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip); if (r.bits() > 63) { return sign * std::numeric_limits<int64_t>::max(); } return sign * r.GetLow64(); }
valtype CAuxpowBuilder::buildAuxpowChain (const uint256& hashAux, unsigned h, int index) { auxpowChainIndex = index; /* Just use "something" for the branch. Doesn't really matter. */ auxpowChainMerkleBranch.clear (); for (unsigned i = 0; i < h; ++i) auxpowChainMerkleBranch.push_back (ArithToUint256 (arith_uint256 (i))); const uint256 hash = CBlock::CheckMerkleBranch (hashAux, auxpowChainMerkleBranch, index); valtype res = ToByteVector (hash); std::reverse (res.begin (), res.end ()); return res; }
// SYSCOIN generate block // This will figure out a valid hash and Nonce if you're // creating a different genesis block: static bool GenerateGenesisBlock(CBlockHeader &genesisBlock, uint256 *phash) { // Write the first 76 bytes of the block header to a double-SHA256 state. genesisBlock.nTime = time(NULL); CHash256 hasher; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << genesisBlock; assert(ss.size() == 80); hasher.Write((unsigned char*)&ss[0], 76); arith_uint256 hashTarget = arith_uint256().SetCompact(genesisBlock.nBits); while (true) { // Write the last 4 bytes of the block header (the nonce) to a copy of // the double-SHA256 state, and compute the result. CHash256(hasher).Write((unsigned char*)&genesisBlock.nNonce, 4).Finalize((unsigned char*)phash); // Return the nonce if the hash has at least some zero bits, // check if it has enough to reach the target if (((uint16_t*)phash)[15] == 0 && UintToArith256(*phash) <= hashTarget) break; genesisBlock.nNonce++; if (genesisBlock.nNonce == 0) { printf("NONCE WRAPPED, incrementing time\n"); ++genesisBlock.nTime; } // If nothing found after trying for a while, return -1 if ((genesisBlock.nNonce & 0xfff) == 0) printf("nonce %08X: hash = %s (target = %s)\n", genesisBlock.nNonce, (*phash).ToString().c_str(), hashTarget.ToString().c_str()); } printf("genesis.nTime = %u \n", genesisBlock.nTime); printf("genesis.nNonce = %u \n", genesisBlock.nNonce); printf("Generate hash = %s\n", (*phash).ToString().c_str()); printf("genesis.hashMerkleRoot = %s\n", genesisBlock.hashMerkleRoot.ToString().c_str()); }
CRegTestParams() { strNetworkID = "regtest"; consensus.nSubsidyHalvingInterval = 150; consensus.nMasternodePaymentsStartBlock = 240; consensus.nMasternodePaymentsIncreaseBlock = 350; consensus.nMasternodePaymentsIncreasePeriod = 10; consensus.nInstantSendKeepLock = 6; consensus.nBudgetPaymentsStartBlock = 1000; consensus.nBudgetPaymentsCycleBlocks = 50; consensus.nBudgetPaymentsWindowBlocks = 10; consensus.nBudgetProposalEstablishingTime = 60*20; consensus.nSuperblockStartBlock = 1500; consensus.nSuperblockCycle = 10; consensus.nGovernanceMinQuorum = 1; consensus.nGovernanceFilterElements = 100; consensus.nMasternodeMinimumConfirmations = 1; consensus.nMajorityEnforceBlockUpgrade = 750; consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 1000; consensus.BIP34Height = -1; // BIP34 has not necessarily activated on regtest consensus.BIP34Hash = uint256(); consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 24 * 60 * 60; // Gridcoin: 1 day consensus.nPowTargetSpacing = 2.5 * 60; // Gridcoin: 2.5 minutes consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = true; consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016) consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 999999999999ULL; consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0; consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 999999999999ULL; consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].bit = 1; consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 999999999999ULL; // The best chain should have at least this much work. consensus.nMinimumChainWork = uint256S("0x00"); // By default assume that the signatures in ancestors of this block are valid. consensus.defaultAssumeValid = uint256S("0x00"); nMaturity = 10; pchMessageStart[0] = 0xfc; pchMessageStart[1] = 0xc1; pchMessageStart[2] = 0xb7; pchMessageStart[3] = 0xdc; nMaxTipAge = 6 * 60 * 60; // ~144 blocks behind -> 2 x fork detection time, was 24 * 60 * 60 in bitcoin nDelayGetHeadersTime = 0; // never delay GETHEADERS in regtests nDefaultPort = 19994; nPruneAfterHeight = 1000; int iNonce; for (iNonce = 0; iNonce < 99999999; iNonce++) { genesis = CreateGenesisBlock(1511309286, iNonce, 0x207fffff, 1, 50 * COIN, 2); arith_uint256 hashTarget = arith_uint256().SetCompact(genesis.nBits); if (UintToArith256(genesis.GetHash()) <= hashTarget) break; } consensus.hashGenesisBlock = genesis.GetHash(); printf("Genesis Check regtest %f \n",(double)iNonce); printf("Genesis hash %s, MerkleRoot %s \n",genesis.GetHash().GetHex().c_str(), genesis.hashMerkleRoot.GetHex().c_str()); assert(consensus.hashGenesisBlock == uint256S("0x7a3f5e99157fa06e03c307815ce680a23a4673aa0588c68078f05df88ac56e9b")); assert(genesis.hashMerkleRoot == uint256S("0x4442ce0b92014dba69e4c6664ab88081b4d1d2eb6bcafa281f8d712a356011ce")); vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds. vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds. fMiningRequiresPeers = false; fDefaultConsistencyChecks = true; fRequireStandard = false; fMineBlocksOnDemand = true; fTestnetToBeDeprecatedFieldRPC = false; nFulfilledRequestExpireTime = 5*60; // fulfilled requests expire in 5 minutes checkpointData = (CCheckpointData){ boost::assign::map_list_of ( 0, uint256S("0x0")), 0, 0, 0 }; // Regtest Gridcoin addresses start with 'y' base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,140); // Regtest Gridcoin script addresses start with '8' or '9' base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,19); // Regtest private keys start with '9' or 'c' (Bitcoin defaults) base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239); // Regtest Gridcoin BIP32 pubkeys start with 'tpub' (Bitcoin defaults) base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >(); // Regtest Gridcoin BIP32 prvkeys start with 'tprv' (Bitcoin defaults) base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >(); // Regtest Gridcoin BIP44 coin type is '1' (All coin's testnet default) nExtCoinType = 1; }
CTestNetParams() { strNetworkID = "test"; consensus.nSubsidyHalvingInterval = 210240; consensus.nMasternodePaymentsStartBlock = 4010; // not true, but it's ok as long as it's less then nMasternodePaymentsIncreaseBlock consensus.nMasternodePaymentsIncreaseBlock = 4030; consensus.nMasternodePaymentsIncreasePeriod = 10; consensus.nInstantSendKeepLock = 6; consensus.nBudgetPaymentsStartBlock = 4100; consensus.nBudgetPaymentsCycleBlocks = 50; consensus.nBudgetPaymentsWindowBlocks = 10; consensus.nBudgetProposalEstablishingTime = 60*20; consensus.nSuperblockStartBlock = 4200; // NOTE: Should satisfy nSuperblockStartBlock > nBudgetPeymentsStartBlock consensus.nSuperblockCycle = 24; // Superblocks can be issued hourly on testnet consensus.nGovernanceMinQuorum = 1; consensus.nGovernanceFilterElements = 500; consensus.nMasternodeMinimumConfirmations = 1; consensus.nMajorityEnforceBlockUpgrade = 51; consensus.nMajorityRejectBlockOutdated = 75; consensus.nMajorityWindow = 100; consensus.BIP34Height = 1; consensus.BIP34Hash = uint256S("0x0000047d24635e347be3aaaeb66c26be94901a2f962feccd4f95090191f208c1"); consensus.powLimit = uint256S("00000fffff000000000000000000000000000000000000000000000000000000"); consensus.nPowTargetTimespan = 24 * 60 * 60; // Gridcoin: 1 day consensus.nPowTargetSpacing = 2.5 * 60; // Gridcoin: 2.5 minutes consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = false; consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008 // Deployment of BIP68, BIP112, and BIP113. consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0; consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1506556800; // September 28th, 2017 consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1538092800; // September 28th, 2018 // Deployment of DIP0001 consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].bit = 1; consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nStartTime = 1505692800; // Sep 18th, 2017 consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nTimeout = 1537228800; // Sep 18th, 2018 consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nWindowSize = 100; consensus.vDeployments[Consensus::DEPLOYMENT_DIP0001].nThreshold = 50; // 50% of 100 // The best chain should have at least this much work. consensus.nMinimumChainWork = uint256S("00000000000000000000000000000000000000000000000000000003cd72a542"); //4000 // By default assume that the signatures in ancestors of this block are valid. consensus.defaultAssumeValid = uint256S("00000ce22113f3eb8636e225d6a1691e132fdd587aed993e1bc9b07a0235eea4"); //4000 nLastPOWBlock = 200; nMaturity = 15; pchMessageStart[0] = 0xce; pchMessageStart[1] = 0xe2; pchMessageStart[2] = 0xca; pchMessageStart[3] = 0xff; vAlertPubKey = ParseHex(""); nDefaultPort = 32748; nMaxTipAge = 0x7fffffff; // allow mining on top of old blocks for testnet nDelayGetHeadersTime = 24 * 60 * 60; nPruneAfterHeight = 1000; int iNonce; for (iNonce=1356250; iNonce < 99999999; iNonce++) { genesis = CreateGenesisBlock(1511309285, iNonce, 0x1e0ffff0, 1, 50 * COIN, 1); arith_uint256 hashTarget = arith_uint256().SetCompact(genesis.nBits); if (UintToArith256(genesis.GetHash()) <= hashTarget) break; } consensus.hashGenesisBlock = genesis.GetHash(); printf("Genesis Check testnet %f \n",(double)iNonce); printf("Genesis hash %s, MerkleRoot %s \n",genesis.GetHash().GetHex().c_str(), genesis.hashMerkleRoot.GetHex().c_str()); assert(consensus.hashGenesisBlock == uint256S("0x0000094271fd4996a2be9951d2f45b1cf75da8dd59dbba009de2e44d0050843f")); assert(genesis.hashMerkleRoot == uint256S("0x4442ce0b92014dba69e4c6664ab88081b4d1d2eb6bcafa281f8d712a356011ce")); vFixedSeeds.clear(); vSeeds.clear(); vSeeds.push_back(CDNSSeedData("gridcoindot.io", "testnet-seed.gridcoindot.io")); vSeeds.push_back(CDNSSeedData("masternode.io", "test.dnsseed.masternode.io")); // Testnet Gridcoin addresses start with 'y' base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,140); // Testnet Gridcoin script addresses start with '8' or '9' base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,19); // Testnet private keys start with '9' or 'c' (Bitcoin defaults) base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239); // Testnet Gridcoin BIP32 pubkeys start with 'tpub' (Bitcoin defaults) base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >(); // Testnet Gridcoin BIP32 prvkeys start with 'tprv' (Bitcoin defaults) base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >(); // Testnet Gridcoin BIP44 coin type is '1' (All coin's testnet default) nExtCoinType = 1; vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); fMiningRequiresPeers = false; fDefaultConsistencyChecks = false; fRequireStandard = false; fMineBlocksOnDemand = false; fTestnetToBeDeprecatedFieldRPC = true; nPoolMaxTransactions = 3; nFulfilledRequestExpireTime = 5*60; // fulfilled requests expire in 5 minutes strSporkPubKey = "046f78dcf911fbd61910136f7f0f8d90578f68d0b3ac973b5040fb7afb501b5939f39b108b0569dca71488f5bbf498d92e4d1194f6f941307ffd95f75e76869f0e"; checkpointData = (CCheckpointData) { boost::assign::map_list_of ( 0, uint256S("0x0")) ( 0, uint256S("0x0")), 1462856598, // * UNIX timestamp of last checkpoint block 3094, // * total number of transactions between genesis and last checkpoint // (the tx=... number in the SetBestChain debug.log lines) 500 // * estimated number of transactions per day after checkpoint }; }
static UniValue getblocktemplate(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) throw std::runtime_error( "getblocktemplate ( TemplateRequest )\n" "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n" "It returns data needed to construct a block to work on.\n" "For full specification, see BIPs 22, 23, 9, and 145:\n" " https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n" " https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n" " https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n" " https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n" "\nArguments:\n" "1. template_request (json object, optional) A json object in the following spec\n" " {\n" " \"mode\":\"template\" (string, optional) This must be set to \"template\", \"proposal\" (see BIP 23), or omitted\n" " \"capabilities\":[ (array, optional) A list of strings\n" " \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n" " ,...\n" " ],\n" " \"rules\":[ (array, optional) A list of strings\n" " \"support\" (string) client side supported softfork deployment\n" " ,...\n" " ]\n" " }\n" "\n" "\nResult:\n" "{\n" " \"version\" : n, (numeric) The preferred block version\n" " \"rules\" : [ \"rulename\", ... ], (array of strings) specific block rules that are to be enforced\n" " \"vbavailable\" : { (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n" " \"rulename\" : bitnumber (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n" " ,...\n" " },\n" " \"vbrequired\" : n, (numeric) bit mask of versionbits the server requires set in submissions\n" " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n" " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n" " {\n" " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n" " \"txid\" : \"xxxx\", (string) transaction id encoded in little-endian hexadecimal\n" " \"hash\" : \"xxxx\", (string) hash encoded in little-endian hexadecimal (including witness data)\n" " \"depends\" : [ (array) array of numbers \n" " n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n" " ,...\n" " ],\n" " \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n" " \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n" " \"weight\" : n, (numeric) total transaction weight, as counted for purposes of block limits\n" " }\n" " ,...\n" " ],\n" " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n" " \"flags\" : \"xx\" (string) key name is to be ignored, and value included in scriptSig\n" " },\n" " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)\n" " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n" " \"target\" : \"xxxx\", (string) The hash target\n" " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n" " \"mutable\" : [ (array of string) list of ways the block template may be changed \n" " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n" " ,...\n" " ],\n" " \"noncerange\" : \"00000000ffffffff\",(string) A range of valid nonces\n" " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n" " \"sizelimit\" : n, (numeric) limit of block size\n" " \"weightlimit\" : n, (numeric) limit of block weight\n" " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n" " \"bits\" : \"xxxxxxxx\", (string) compressed target of next block\n" " \"height\" : n (numeric) The height of the next block\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblocktemplate", "{\"rules\": [\"segwit\"]}") + HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}") ); LOCK(cs_main); std::string strMode = "template"; UniValue lpval = NullUniValue; std::set<std::string> setClientRules; int64_t nMaxVersionPreVB = -1; if (!request.params[0].isNull()) { const UniValue& oparam = request.params[0].get_obj(); const UniValue& modeval = find_value(oparam, "mode"); if (modeval.isStr()) strMode = modeval.get_str(); else if (modeval.isNull()) { /* Do nothing */ } else throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); lpval = find_value(oparam, "longpollid"); if (strMode == "proposal") { const UniValue& dataval = find_value(oparam, "data"); if (!dataval.isStr()) throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal"); CBlock block; if (!DecodeHexBlk(block, dataval.get_str())) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); uint256 hash = block.GetHash(); const CBlockIndex* pindex = LookupBlockIndex(hash); if (pindex) { if (pindex->IsValid(BLOCK_VALID_SCRIPTS)) return "duplicate"; if (pindex->nStatus & BLOCK_FAILED_MASK) return "duplicate-invalid"; return "duplicate-inconclusive"; } CBlockIndex* const pindexPrev = chainActive.Tip(); // TestBlockValidity only supports blocks built on the current Tip if (block.hashPrevBlock != pindexPrev->GetBlockHash()) return "inconclusive-not-best-prevblk"; CValidationState state; TestBlockValidity(state, Params(), block, pindexPrev, false, true); return BIP22ValidationResult(state); } const UniValue& aClientRules = find_value(oparam, "rules"); if (aClientRules.isArray()) { for (unsigned int i = 0; i < aClientRules.size(); ++i) { const UniValue& v = aClientRules[i]; setClientRules.insert(v.get_str()); } } else { // NOTE: It is important that this NOT be read if versionbits is supported const UniValue& uvMaxVersion = find_value(oparam, "maxversion"); if (uvMaxVersion.isNum()) { nMaxVersionPreVB = uvMaxVersion.get_int64(); } } } if (strMode != "template") throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!"); if (IsInitialBlockDownload()) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks..."); static unsigned int nTransactionsUpdatedLast; if (!lpval.isNull()) { // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions uint256 hashWatchedChain; std::chrono::steady_clock::time_point checktxtime; unsigned int nTransactionsUpdatedLastLP; if (lpval.isStr()) { // Format: <hashBestChain><nTransactionsUpdatedLast> std::string lpstr = lpval.get_str(); hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid"); nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64)); } else { // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier hashWatchedChain = chainActive.Tip()->GetBlockHash(); nTransactionsUpdatedLastLP = nTransactionsUpdatedLast; } // Release the wallet and main lock while waiting LEAVE_CRITICAL_SECTION(cs_main); { checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1); WAIT_LOCK(g_best_block_mutex, lock); while (g_best_block == hashWatchedChain && IsRPCRunning()) { if (g_best_block_cv.wait_until(lock, checktxtime) == std::cv_status::timeout) { // Timeout: Check transactions for update if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP) break; checktxtime += std::chrono::seconds(10); } } } ENTER_CRITICAL_SECTION(cs_main); if (!IsRPCRunning()) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down"); // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners? } const struct VBDeploymentInfo& segwit_info = VersionBitsDeploymentInfo[Consensus::DEPLOYMENT_SEGWIT]; // If the caller is indicating segwit support, then allow CreateNewBlock() // to select witness transactions, after segwit activates (otherwise // don't). bool fSupportsSegwit = setClientRules.find(segwit_info.name) != setClientRules.end(); // Update block static CBlockIndex* pindexPrev; static int64_t nStart; static std::unique_ptr<CBlockTemplate> pblocktemplate; // Cache whether the last invocation was with segwit support, to avoid returning // a segwit-block to a non-segwit caller. static bool fLastTemplateSupportsSegwit = true; if (pindexPrev != chainActive.Tip() || (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5) || fLastTemplateSupportsSegwit != fSupportsSegwit) { // Clear pindexPrev so future calls make a new block, despite any failures from here on pindexPrev = nullptr; // Store the pindexBest used before CreateNewBlock, to avoid races nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrevNew = chainActive.Tip(); nStart = GetTime(); fLastTemplateSupportsSegwit = fSupportsSegwit; // Create new block CScript scriptDummy = CScript() << OP_TRUE; pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy, fSupportsSegwit); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); // Need to update only after we know CreateNewBlock succeeded pindexPrev = pindexPrevNew; } assert(pindexPrev); CBlock* pblock = &pblocktemplate->block; // pointer for convenience const Consensus::Params& consensusParams = Params().GetConsensus(); // Update nTime UpdateTime(pblock, consensusParams, pindexPrev); pblock->nNonce = 0; // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration const bool fPreSegWit = (ThresholdState::ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache)); UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal"); UniValue transactions(UniValue::VARR); std::map<uint256, int64_t> setTxIndex; int i = 0; for (const auto& it : pblock->vtx) { const CTransaction& tx = *it; uint256 txHash = tx.GetHash(); setTxIndex[txHash] = i++; if (tx.IsCoinBase()) continue; UniValue entry(UniValue::VOBJ); entry.pushKV("data", EncodeHexTx(tx)); entry.pushKV("txid", txHash.GetHex()); entry.pushKV("hash", tx.GetWitnessHash().GetHex()); UniValue deps(UniValue::VARR); for (const CTxIn &in : tx.vin) { if (setTxIndex.count(in.prevout.hash)) deps.push_back(setTxIndex[in.prevout.hash]); } entry.pushKV("depends", deps); int index_in_template = i - 1; entry.pushKV("fee", pblocktemplate->vTxFees[index_in_template]); int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template]; if (fPreSegWit) { assert(nTxSigOps % WITNESS_SCALE_FACTOR == 0); nTxSigOps /= WITNESS_SCALE_FACTOR; } entry.pushKV("sigops", nTxSigOps); entry.pushKV("weight", GetTransactionWeight(tx)); transactions.push_back(entry); } UniValue aux(UniValue::VOBJ); aux.pushKV("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())); arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); UniValue aMutable(UniValue::VARR); aMutable.push_back("time"); aMutable.push_back("transactions"); aMutable.push_back("prevblock"); UniValue result(UniValue::VOBJ); result.pushKV("capabilities", aCaps); UniValue aRules(UniValue::VARR); UniValue vbavailable(UniValue::VOBJ); for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { Consensus::DeploymentPos pos = Consensus::DeploymentPos(j); ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache); switch (state) { case ThresholdState::DEFINED: case ThresholdState::FAILED: // Not exposed to GBT at all break; case ThresholdState::LOCKED_IN: // Ensure bit is set in block version pblock->nVersion |= VersionBitsMask(consensusParams, pos); // FALL THROUGH to get vbavailable set... case ThresholdState::STARTED: { const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; vbavailable.pushKV(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit); if (setClientRules.find(vbinfo.name) == setClientRules.end()) { if (!vbinfo.gbt_force) { // If the client doesn't support this, don't indicate it in the [default] version pblock->nVersion &= ~VersionBitsMask(consensusParams, pos); } } break; } case ThresholdState::ACTIVE: { // Add to rules only const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; aRules.push_back(gbt_vb_name(pos)); if (setClientRules.find(vbinfo.name) == setClientRules.end()) { // Not supported by the client; make sure it's safe to proceed if (!vbinfo.gbt_force) { // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name)); } } break; } } } result.pushKV("version", pblock->nVersion); result.pushKV("rules", aRules); result.pushKV("vbavailable", vbavailable); result.pushKV("vbrequired", int(0)); if (nMaxVersionPreVB >= 2) { // If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here // Because BIP 34 changed how the generation transaction is serialized, we can only use version/force back to v2 blocks // This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated aMutable.push_back("version/force"); } result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex()); result.pushKV("transactions", transactions); result.pushKV("coinbaseaux", aux); result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue); result.pushKV("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)); result.pushKV("target", hashTarget.GetHex()); result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1); result.pushKV("mutable", aMutable); result.pushKV("noncerange", "00000000ffffffff"); int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST; int64_t nSizeLimit = MAX_BLOCK_SERIALIZED_SIZE; if (fPreSegWit) { assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0); nSigOpLimit /= WITNESS_SCALE_FACTOR; assert(nSizeLimit % WITNESS_SCALE_FACTOR == 0); nSizeLimit /= WITNESS_SCALE_FACTOR; } result.pushKV("sigoplimit", nSigOpLimit); result.pushKV("sizelimit", nSizeLimit); if (!fPreSegWit) { result.pushKV("weightlimit", (int64_t)MAX_BLOCK_WEIGHT); } result.pushKV("curtime", pblock->GetBlockTime()); result.pushKV("bits", strprintf("%08x", pblock->nBits)); result.pushKV("height", (int64_t)(pindexPrev->nHeight+1)); if (!pblocktemplate->vchCoinbaseCommitment.empty() && fSupportsSegwit) { result.pushKV("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end())); } return result; }
// SYSCOIN DGW diff algo unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) { /* current difficulty formula, dash - DarkGravity v3, written by Evan Duffield - [email protected] */ // Genesis block const arith_uint256 nProofOfWorkLimit = UintToArith256(params.powLimit); if (params.fPowNoRetargeting) return pindexLast->nBits; const CBlockIndex *BlockLastSolved = pindexLast; const CBlockIndex *BlockReading = pindexLast; int64_t nActualTimespan = 0; int64_t LastBlockTime = 0; int64_t PastBlocksMin = 24; int64_t PastBlocksMax = 24; int64_t CountBlocks = 0; arith_uint256 PastDifficultyAverage; arith_uint256 PastDifficultyAveragePrev; // 110 needed for snapshot unit test if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < 200) { return nProofOfWorkLimit.GetCompact(); } for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) { if (PastBlocksMax > 0 && i > PastBlocksMax) { break; } CountBlocks++; if(CountBlocks <= PastBlocksMin) { if (CountBlocks == 1) { PastDifficultyAverage.SetCompact(BlockReading->nBits); } else { PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks) + (arith_uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1); } PastDifficultyAveragePrev = PastDifficultyAverage; } if(LastBlockTime > 0){ int64_t Diff = (LastBlockTime - BlockReading->GetBlockTime()); nActualTimespan += Diff; } LastBlockTime = BlockReading->GetBlockTime(); if (BlockReading->pprev == NULL) { assert(BlockReading); break; } BlockReading = BlockReading->pprev; } arith_uint256 bnNew(PastDifficultyAverage); int64_t _nTargetTimespan = CountBlocks * params.nPowTargetSpacing; if (nActualTimespan < _nTargetTimespan/3) nActualTimespan = _nTargetTimespan/3; if (nActualTimespan > _nTargetTimespan*3) nActualTimespan = _nTargetTimespan*3; // Retarget bnNew *= nActualTimespan; bnNew /= _nTargetTimespan; if (bnNew > nProofOfWorkLimit){ bnNew = nProofOfWorkLimit; } return bnNew.GetCompact(); }
UniValue getblocktemplate(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 1) throw std::runtime_error( "getblocktemplate ( TemplateRequest )\n" "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n" "It returns data needed to construct a block to work on.\n" "For full specification, see BIPs 22, 23, and 9:\n" " https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n" " https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n" " https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n" "\nArguments:\n" "1. template_request (json object, optional) A json object in the following spec\n" " {\n" " \"mode\":\"template\" (string, optional) This must be set to \"template\", \"proposal\" (see BIP 23), or omitted\n" " \"capabilities\":[ (array, optional) A list of strings\n" " \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n" " ,...\n" " ],\n" " \"rules\":[ (array, optional) A list of strings\n" " \"support\" (string) client side supported softfork deployment\n" " ,...\n" " ]\n" " }\n" "\n" "\nResult:\n" "{\n" " \"capabilities\" : [ \"capability\", ... ], (array of strings) specific client side supported features\n" " \"version\" : n, (numeric) The preferred block version\n" " \"rules\" : [ \"rulename\", ... ], (array of strings) specific block rules that are to be enforced\n" " \"vbavailable\" : { (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n" " \"rulename\" : bitnumber (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n" " ,...\n" " },\n" " \"vbrequired\" : n, (numeric) bit mask of versionbits the server requires set in submissions\n" " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n" " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n" " {\n" " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n" " \"hash\" : \"xxxx\", (string) hash/id encoded in little-endian hexadecimal\n" " \"depends\" : [ (array) array of numbers \n" " n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n" " ,...\n" " ],\n" " \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in duffs); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n" " \"sigops\" : n, (numeric) total number of SigOps, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients MUST NOT assume there aren't any\n" " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n" " }\n" " ,...\n" " ],\n" " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n" " \"flags\" : \"xx\" (string) key name is to be ignored, and value included in scriptSig\n" " },\n" " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in duffs)\n" " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n" " \"target\" : \"xxxx\", (string) The hash target\n" " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n" " \"mutable\" : [ (array of string) list of ways the block template may be changed \n" " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n" " ,...\n" " ],\n" " \"noncerange\" : \"00000000ffffffff\",(string) A range of valid nonces\n" " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n" " \"sizelimit\" : n, (numeric) limit of block size\n" " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n" " \"bits\" : \"xxxxxxxx\", (string) compressed target of next block\n" " \"previousbits\" : \"xxxxxxxx\", (string) compressed target of current highest block\n" " \"height\" : n (numeric) The height of the next block\n" " \"masternode\" : [ (array) required masternode payments that must be included in the next block\n" " {\n" " \"payee\" : \"xxxx\", (string) payee address\n" " \"script\" : \"xxxx\", (string) payee scriptPubKey\n" " \"amount\": n (numeric) required amount to pay\n" " }\n" " },\n" " \"masternode_payments_started\" : true|false, (boolean) true, if masternode payments started\n" " \"masternode_payments_enforced\" : true|false, (boolean) true, if masternode payments are enforced\n" " \"superblock\" : [ (array) required superblock payees that must be included in the next block\n" " {\n" " \"payee\" : \"xxxx\", (string) payee address\n" " \"script\" : \"xxxx\", (string) payee scriptPubKey\n" " \"amount\": n (numeric) required amount to pay\n" " }\n" " ,...\n" " ],\n" " \"superblocks_started\" : true|false, (boolean) true, if superblock payments started\n" " \"superblocks_enabled\" : true|false, (boolean) true, if superblock payments are enabled\n" " \"coinbase_payload\" : \"xxxxxxxx\" (string) coinbase transaction payload data encoded in hexadecimal\n" "}\n" "\nExamples:\n" + HelpExampleCli("getblocktemplate", "") + HelpExampleRpc("getblocktemplate", "") ); LOCK(cs_main); std::string strMode = "template"; UniValue lpval = NullUniValue; std::set<std::string> setClientRules; int64_t nMaxVersionPreVB = -1; if (request.params.size() > 0) { const UniValue& oparam = request.params[0].get_obj(); const UniValue& modeval = find_value(oparam, "mode"); if (modeval.isStr()) strMode = modeval.get_str(); else if (modeval.isNull()) { /* Do nothing */ } else throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); lpval = find_value(oparam, "longpollid"); if (strMode == "proposal") { const UniValue& dataval = find_value(oparam, "data"); if (!dataval.isStr()) throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal"); CBlock block; if (!DecodeHexBlk(block, dataval.get_str())) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); uint256 hash = block.GetHash(); BlockMap::iterator mi = mapBlockIndex.find(hash); if (mi != mapBlockIndex.end()) { CBlockIndex *pindex = mi->second; if (pindex->IsValid(BLOCK_VALID_SCRIPTS)) return "duplicate"; if (pindex->nStatus & BLOCK_FAILED_MASK) return "duplicate-invalid"; return "duplicate-inconclusive"; } CBlockIndex* const pindexPrev = chainActive.Tip(); // TestBlockValidity only supports blocks built on the current Tip if (block.hashPrevBlock != pindexPrev->GetBlockHash()) return "inconclusive-not-best-prevblk"; CValidationState state; TestBlockValidity(state, Params(), block, pindexPrev, false, true); return BIP22ValidationResult(state); } const UniValue& aClientRules = find_value(oparam, "rules"); if (aClientRules.isArray()) { for (unsigned int i = 0; i < aClientRules.size(); ++i) { const UniValue& v = aClientRules[i]; setClientRules.insert(v.get_str()); } } else { // NOTE: It is important that this NOT be read if versionbits is supported const UniValue& uvMaxVersion = find_value(oparam, "maxversion"); if (uvMaxVersion.isNum()) { nMaxVersionPreVB = uvMaxVersion.get_int64(); } } } if (strMode != "template") throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); if (Params().MiningRequiresPeers()) { if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Dash Core is not connected!"); if (IsInitialBlockDownload()) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is downloading blocks..."); } // when enforcement is on we need information about a masternode payee or otherwise our block is going to be orphaned by the network std::vector<CTxOut> voutMasternodePayments; if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) && !masternodeSync.IsWinnersListSynced() && !mnpayments.GetBlockTxOuts(chainActive.Height() + 1, 0, voutMasternodePayments)) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is downloading masternode winners..."); // next bock is a superblock and we need governance info to correctly construct it if (sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED) && !masternodeSync.IsSynced() && CSuperblock::IsValidBlockHeight(chainActive.Height() + 1)) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is syncing with network..."); static unsigned int nTransactionsUpdatedLast; if (!lpval.isNull()) { // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions uint256 hashWatchedChain; boost::system_time checktxtime; unsigned int nTransactionsUpdatedLastLP; if (lpval.isStr()) { // Format: <hashBestChain><nTransactionsUpdatedLast> std::string lpstr = lpval.get_str(); hashWatchedChain.SetHex(lpstr.substr(0, 64)); nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64)); } else { // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier hashWatchedChain = chainActive.Tip()->GetBlockHash(); nTransactionsUpdatedLastLP = nTransactionsUpdatedLast; } // Release the wallet and main lock while waiting LEAVE_CRITICAL_SECTION(cs_main); { checktxtime = boost::get_system_time() + boost::posix_time::minutes(1); boost::unique_lock<boost::mutex> lock(csBestBlock); while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning()) { if (!cvBlockChange.timed_wait(lock, checktxtime)) { // Timeout: Check transactions for update if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP) break; checktxtime += boost::posix_time::seconds(10); } } } ENTER_CRITICAL_SECTION(cs_main); if (!IsRPCRunning()) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down"); // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners? } // Update block static CBlockIndex* pindexPrev; static int64_t nStart; static std::unique_ptr<CBlockTemplate> pblocktemplate; if (pindexPrev != chainActive.Tip() || (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) { // Clear pindexPrev so future calls make a new block, despite any failures from here on pindexPrev = nullptr; // Store the chainActive.Tip() used before CreateNewBlock, to avoid races nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrevNew = chainActive.Tip(); nStart = GetTime(); // Create new block CScript scriptDummy = CScript() << OP_TRUE; pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); // Need to update only after we know CreateNewBlock succeeded pindexPrev = pindexPrevNew; } CBlock* pblock = &pblocktemplate->block; // pointer for convenience const Consensus::Params& consensusParams = Params().GetConsensus(); // Update nTime UpdateTime(pblock, consensusParams, pindexPrev); pblock->nNonce = 0; UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal"); UniValue transactions(UniValue::VARR); std::map<uint256, int64_t> setTxIndex; int i = 0; for (const auto& it : pblock->vtx) { const CTransaction& tx = *it; uint256 txHash = tx.GetHash(); setTxIndex[txHash] = i++; if (tx.IsCoinBase()) continue; UniValue entry(UniValue::VOBJ); entry.push_back(Pair("data", EncodeHexTx(tx))); entry.push_back(Pair("hash", txHash.GetHex())); UniValue deps(UniValue::VARR); BOOST_FOREACH (const CTxIn &in, tx.vin) { if (setTxIndex.count(in.prevout.hash)) deps.push_back(setTxIndex[in.prevout.hash]); } entry.push_back(Pair("depends", deps)); int index_in_template = i - 1; entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template])); entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template])); transactions.push_back(entry); } UniValue aux(UniValue::VOBJ); aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()))); arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); UniValue aMutable(UniValue::VARR); aMutable.push_back("time"); aMutable.push_back("transactions"); aMutable.push_back("prevblock"); UniValue result(UniValue::VOBJ); result.push_back(Pair("capabilities", aCaps)); UniValue aRules(UniValue::VARR); UniValue vbavailable(UniValue::VOBJ); for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { Consensus::DeploymentPos pos = Consensus::DeploymentPos(j); ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache); switch (state) { case THRESHOLD_DEFINED: case THRESHOLD_FAILED: // Not exposed to GBT at all break; case THRESHOLD_LOCKED_IN: // Ensure bit is set in block version pblock->nVersion |= VersionBitsMask(consensusParams, pos); // FALL THROUGH to get vbavailable set... case THRESHOLD_STARTED: { const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit)); if (setClientRules.find(vbinfo.name) == setClientRules.end()) { if (!vbinfo.gbt_force) { // If the client doesn't support this, don't indicate it in the [default] version pblock->nVersion &= ~VersionBitsMask(consensusParams, pos); } } break; } case THRESHOLD_ACTIVE: { // Add to rules only const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; aRules.push_back(gbt_vb_name(pos)); if (setClientRules.find(vbinfo.name) == setClientRules.end()) { // Not supported by the client; make sure it's safe to proceed if (!vbinfo.gbt_force) { // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name)); } } break; } } } result.push_back(Pair("version", pblock->nVersion)); result.push_back(Pair("rules", aRules)); result.push_back(Pair("vbavailable", vbavailable)); result.push_back(Pair("vbrequired", int(0))); if (nMaxVersionPreVB >= 2) { // If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here // Because BIP 34 changed how the generation transaction is serialized, we can only use version/force back to v2 blocks // This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated aMutable.push_back("version/force"); } result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); result.push_back(Pair("transactions", transactions)); result.push_back(Pair("coinbaseaux", aux)); result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0]->GetValueOut())); result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast))); result.push_back(Pair("target", hashTarget.GetHex())); result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); result.push_back(Pair("mutable", aMutable)); result.push_back(Pair("noncerange", "00000000ffffffff")); result.push_back(Pair("sigoplimit", (int64_t)MaxBlockSigOps(fDIP0001ActiveAtTip))); result.push_back(Pair("sizelimit", (int64_t)MaxBlockSize(fDIP0001ActiveAtTip))); result.push_back(Pair("curtime", pblock->GetBlockTime())); result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); result.push_back(Pair("previousbits", strprintf("%08x", pblocktemplate->nPrevBits))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); UniValue masternodeObj(UniValue::VARR); for (const auto& txout : pblocktemplate->voutMasternodePayments) { CTxDestination address1; ExtractDestination(txout.scriptPubKey, address1); CBitcoinAddress address2(address1); UniValue obj(UniValue::VOBJ); obj.push_back(Pair("payee", address2.ToString().c_str())); obj.push_back(Pair("script", HexStr(txout.scriptPubKey))); obj.push_back(Pair("amount", txout.nValue)); masternodeObj.push_back(obj); } result.push_back(Pair("masternode", masternodeObj)); result.push_back(Pair("masternode_payments_started", pindexPrev->nHeight + 1 > consensusParams.nMasternodePaymentsStartBlock)); result.push_back(Pair("masternode_payments_enforced", deterministicMNManager->IsDeterministicMNsSporkActive() || sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT))); UniValue superblockObjArray(UniValue::VARR); if(pblocktemplate->voutSuperblockPayments.size()) { for (const auto& txout : pblocktemplate->voutSuperblockPayments) { UniValue entry(UniValue::VOBJ); CTxDestination address1; ExtractDestination(txout.scriptPubKey, address1); CBitcoinAddress address2(address1); entry.push_back(Pair("payee", address2.ToString().c_str())); entry.push_back(Pair("script", HexStr(txout.scriptPubKey))); entry.push_back(Pair("amount", txout.nValue)); superblockObjArray.push_back(entry); } } result.push_back(Pair("superblock", superblockObjArray)); result.push_back(Pair("superblocks_started", pindexPrev->nHeight + 1 > consensusParams.nSuperblockStartBlock)); result.push_back(Pair("superblocks_enabled", sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED))); result.push_back(Pair("coinbase_payload", HexStr(pblock->vtx[0]->vExtraPayload))); return result; }
// partly copied from https://github.com/zcash/zcash/blob/master/src/miner.cpp#L581 bool equihash_(std::string solver, CBlock *pblock, int n, int k) { arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); // Hash state crypto_generichash_blake2b_state state; EhInitialiseState(n, k, state); // I = the block header minus nonce and solution. CEquihashInput I{*pblock}; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << I; // H(I||... crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size()); // H(I||V||... crypto_generichash_blake2b_state curr_state; curr_state = state; crypto_generichash_blake2b_update(&curr_state, pblock->nNonce.begin(), pblock->nNonce.size()); // (x_1, x_2, ...) = A(I, V, n, k) LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n", solver, pblock->nNonce.ToString()); std::function<bool(std::vector<unsigned char>)> validBlock = [&pblock, &hashTarget](std::vector<unsigned char> soln) { // Write the solution to the hash and compute the result. pblock->nSolution = soln; if (UintToArith256(pblock->GetHash()) > hashTarget) { return false; } // Found a solution LogPrintf("CMMMiner:\n"); LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); return true; }; if (solver == "tromp") { // Create solver and initialize it. equi eq(1); eq.setstate(&curr_state); // Intialization done, start algo driver. eq.digit0(0); eq.xfull = eq.bfull = eq.hfull = 0; eq.showbsizes(0); for (u32 r = 1; r < WK; r++) { (r&1) ? eq.digitodd(r, 0) : eq.digiteven(r, 0); eq.xfull = eq.bfull = eq.hfull = 0; eq.showbsizes(r); } eq.digitK(0); // Convert solution indices to byte array (decompress) and pass it to validBlock method. for (size_t s = 0; s < eq.nsols; s++) { std::vector<eh_index> index_vector(PROOFSIZE); for (size_t i = 0; i < PROOFSIZE; i++) { index_vector[i] = eq.sols[s][i]; } std::vector<unsigned char> sol_char = GetMinimalFromIndices(index_vector, DIGITBITS); if (validBlock(sol_char)) return true; } } else { try { if (EhOptimisedSolve(n, k, curr_state, validBlock)) return true; } catch (std::exception&) { LogPrintf("pow/nano.cpp: ", "execption catched..."); } } return false; }
/** * Obtains a hash of the active state to use for consensus verification and checkpointing. * * For increased flexibility, so other implementations like OmniWallet and OmniChest can * also apply this methodology without necessarily using the same exact data types (which * would be needed to hash the data bytes directly), create a string in the following * format for each entry to use for hashing: * * ---STAGE 1 - BALANCES--- * Format specifiers & placeholders: * "%s|%d|%d|%d|%d|%d" - "address|propertyid|balance|selloffer_reserve|accept_reserve|metadex_reserve" * * Note: empty balance records and the pending tally are ignored. Addresses are sorted based * on lexicographical order, and balance records are sorted by the property identifiers. * * ---STAGE 2 - DEX SELL OFFERS--- * Format specifiers & placeholders: * "%s|%s|%d|%d|%d|%d|%d" - "txid|address|propertyid|offeramount|btcdesired|minfee|timelimit" * * Note: ordered ascending by txid. * * ---STAGE 3 - DEX ACCEPTS--- * Format specifiers & placeholders: * "%s|%s|%d|%d|%d" - "matchedselloffertxid|buyer|acceptamount|acceptamountremaining|acceptblock" * * Note: ordered ascending by matchedselloffertxid followed by buyer. * * ---STAGE 4 - METADEX TRADES--- * Format specifiers & placeholders: * "%s|%s|%d|%d|%d|%d|%d" - "txid|address|propertyidforsale|amountforsale|propertyiddesired|amountdesired|amountremaining" * * Note: ordered ascending by txid. * * ---STAGE 5 - CROWDSALES--- * Format specifiers & placeholders: * "%d|%d|%d|%d|%d" - "propertyid|propertyiddesired|deadline|usertokens|issuertokens" * * Note: ordered by property ID. * * ---STAGE 6 - PROPERTIES--- * Format specifiers & placeholders: * "%d|%s" - "propertyid|issueraddress" * * Note: ordered by property ID. * * The byte order is important, and we assume: * SHA256("abc") = "ad1500f261ff10b49c7a1796a36103b02322ae5dde404141eacf018fbf1678ba" * */ uint256 GetConsensusHash() { // allocate and init a SHA256_CTX SHA256_CTX shaCtx; SHA256_Init(&shaCtx); LOCK(cs_tally); if (msc_debug_consensus_hash) PrintToLog("Beginning generation of current consensus hash...\n"); // Balances - loop through the tally map, updating the sha context with the data from each balance and tally type // Placeholders: "address|propertyid|balance|selloffer_reserve|accept_reserve|metadex_reserve" // Sort alphabetically first std::map<std::string, CMPTally> tallyMapSorted; for (std::unordered_map<string, CMPTally>::iterator uoit = mp_tally_map.begin(); uoit != mp_tally_map.end(); ++uoit) { tallyMapSorted.insert(std::make_pair(uoit->first,uoit->second)); } for (std::map<string, CMPTally>::iterator my_it = tallyMapSorted.begin(); my_it != tallyMapSorted.end(); ++my_it) { const std::string& address = my_it->first; CMPTally& tally = my_it->second; tally.init(); uint32_t propertyId = 0; while (0 != (propertyId = (tally.next()))) { std::string dataStr = GenerateConsensusString(tally, address, propertyId); if (dataStr.empty()) continue; // skip empty balances if (msc_debug_consensus_hash) PrintToLog("Adding balance data to consensus hash: %s\n", dataStr); SHA256_Update(&shaCtx, dataStr.c_str(), dataStr.length()); } } // DEx sell offers - loop through the DEx and add each sell offer to the consensus hash (ordered by txid) // Placeholders: "txid|address|propertyid|offeramount|btcdesired|minfee|timelimit" std::vector<std::pair<arith_uint256, std::string> > vecDExOffers; for (OfferMap::iterator it = my_offers.begin(); it != my_offers.end(); ++it) { const CMPOffer& selloffer = it->second; const std::string& sellCombo = it->first; std::string seller = sellCombo.substr(0, sellCombo.size() - 2); std::string dataStr = GenerateConsensusString(selloffer, seller); vecDExOffers.push_back(std::make_pair(arith_uint256(selloffer.getHash().ToString()), dataStr)); } std::sort (vecDExOffers.begin(), vecDExOffers.end()); for (std::vector<std::pair<arith_uint256, std::string> >::iterator it = vecDExOffers.begin(); it != vecDExOffers.end(); ++it) { const std::string& dataStr = it->second; if (msc_debug_consensus_hash) PrintToLog("Adding DEx offer data to consensus hash: %s\n", dataStr); SHA256_Update(&shaCtx, dataStr.c_str(), dataStr.length()); } // DEx accepts - loop through the accepts map and add each accept to the consensus hash (ordered by matchedtxid then buyer) // Placeholders: "matchedselloffertxid|buyer|acceptamount|acceptamountremaining|acceptblock" std::vector<std::pair<std::string, std::string> > vecAccepts; for (AcceptMap::const_iterator it = my_accepts.begin(); it != my_accepts.end(); ++it) { const CMPAccept& accept = it->second; const std::string& acceptCombo = it->first; std::string buyer = acceptCombo.substr((acceptCombo.find("+") + 1), (acceptCombo.size()-(acceptCombo.find("+") + 1))); std::string dataStr = GenerateConsensusString(accept, buyer); std::string sortKey = strprintf("%s-%s", accept.getHash().GetHex(), buyer); vecAccepts.push_back(std::make_pair(sortKey, dataStr)); } std::sort (vecAccepts.begin(), vecAccepts.end()); for (std::vector<std::pair<std::string, std::string> >::iterator it = vecAccepts.begin(); it != vecAccepts.end(); ++it) { const std::string& dataStr = it->second; if (msc_debug_consensus_hash) PrintToLog("Adding DEx accept to consensus hash: %s\n", dataStr); SHA256_Update(&shaCtx, dataStr.c_str(), dataStr.length()); } // MetaDEx trades - loop through the MetaDEx maps and add each open trade to the consensus hash (ordered by txid) // Placeholders: "txid|address|propertyidforsale|amountforsale|propertyiddesired|amountdesired|amountremaining" std::vector<std::pair<arith_uint256, std::string> > vecMetaDExTrades; for (md_PropertiesMap::const_iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) { const md_PricesMap& prices = my_it->second; for (md_PricesMap::const_iterator it = prices.begin(); it != prices.end(); ++it) { const md_Set& indexes = it->second; for (md_Set::const_iterator it = indexes.begin(); it != indexes.end(); ++it) { const CMPMetaDEx& obj = *it; std::string dataStr = GenerateConsensusString(obj); vecMetaDExTrades.push_back(std::make_pair(arith_uint256(obj.getHash().ToString()), dataStr)); } } } std::sort (vecMetaDExTrades.begin(), vecMetaDExTrades.end()); for (std::vector<std::pair<arith_uint256, std::string> >::iterator it = vecMetaDExTrades.begin(); it != vecMetaDExTrades.end(); ++it) { const std::string& dataStr = it->second; if (msc_debug_consensus_hash) PrintToLog("Adding MetaDEx trade data to consensus hash: %s\n", dataStr); SHA256_Update(&shaCtx, dataStr.c_str(), dataStr.length()); } // Crowdsales - loop through open crowdsales and add to the consensus hash (ordered by property ID) // Note: the variables of the crowdsale (amount, bonus etc) are not part of the crowdsale map and not included here to // avoid additionalal loading of SP entries from the database // Placeholders: "propertyid|propertyiddesired|deadline|usertokens|issuertokens" std::vector<std::pair<uint32_t, std::string> > vecCrowds; for (CrowdMap::const_iterator it = my_crowds.begin(); it != my_crowds.end(); ++it) { const CMPCrowd& crowd = it->second; uint32_t propertyId = crowd.getPropertyId(); std::string dataStr = GenerateConsensusString(crowd); vecCrowds.push_back(std::make_pair(propertyId, dataStr)); } std::sort (vecCrowds.begin(), vecCrowds.end()); for (std::vector<std::pair<uint32_t, std::string> >::iterator it = vecCrowds.begin(); it != vecCrowds.end(); ++it) { std::string dataStr = (*it).second; if (msc_debug_consensus_hash) PrintToLog("Adding Crowdsale entry to consensus hash: %s\n", dataStr); SHA256_Update(&shaCtx, dataStr.c_str(), dataStr.length()); } // Properties - loop through each property and store the issuer (to capture state changes via change issuer transactions) // Note: we are loading every SP from the DB to check the issuer, if using consensus_hash_every_block debug option this // will slow things down dramatically. Not an issue to do it once every 10,000 blocks for checkpoint verification. // Placeholders: "propertyid|issueraddress" for (uint8_t ecosystem = 1; ecosystem <= 2; ecosystem++) { uint32_t startPropertyId = (ecosystem == 1) ? 1 : TEST_ECO_PROPERTY_1; for (uint32_t propertyId = startPropertyId; propertyId < _my_sps->peekNextSPID(ecosystem); propertyId++) { CMPSPInfo::Entry sp; if (!_my_sps->getSP(propertyId, sp)) { PrintToLog("Error loading property ID %d for consensus hashing, hash should not be trusted!\n"); continue; } std::string dataStr = GenerateConsensusString(propertyId, sp.issuer); if (msc_debug_consensus_hash) PrintToLog("Adding property to consensus hash: %s\n", dataStr); SHA256_Update(&shaCtx, dataStr.c_str(), dataStr.length()); } } // extract the final result and return the hash uint256 consensusHash; SHA256_Final((unsigned char*)&consensusHash, &shaCtx); if (msc_debug_consensus_hash) PrintToLog("Finished generation of consensus hash. Result: %s\n", consensusHash.GetHex()); return consensusHash; }
// Advance generator state, if most bits of the current state were used if (state < MIN_STATE) { /* The original "legacy" implementation based on CBigNum serialised the value based on valtype and with leading zeros removed. For compatibility with the old consensus behaviour, we replicate this. */ valtype data(state0.begin (), state0.end ()); while (data.back () == 0) data.pop_back (); /* The legacy representation uses the highest bit as sign bit. Thus we have to add a zero at the end if the highest bit is set. */ if (data.back () & 128) data.push_back (0); state0 = SerializeHash (data, SER_GETHASH, 0); state = UintToArith256 (state0); } arith_uint256 res = state; state /= modulo; res -= state * modulo; assert (res.bits () < 64); return res.GetLow64 (); } const arith_uint256 RandomGenerator::MIN_STATE = arith_uint256().SetCompact (0x097FFFFFu);
unsigned int static DarkGravityWave(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { /* current difficulty formula, dash - DarkGravity v3, written by Evan Duffield - [email protected] */ const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); int64_t nPastBlocks = 24; // make sure we have at least (nPastBlocks + 1) blocks, otherwise just return powLimit if (!pindexLast || pindexLast->nHeight < nPastBlocks) { return bnPowLimit.GetCompact(); } if (params.fPowAllowMinDifficultyBlocks && ( // testnet ... (params.hashDevnetGenesisBlock.IsNull() && pindexLast->nChainWork >= UintToArith256(uint256S("0x000000000000000000000000000000000000000000000000003e9ccfe0e03e01"))) || // or devnet !params.hashDevnetGenesisBlock.IsNull())) { // NOTE: 000000000000000000000000000000000000000000000000003e9ccfe0e03e01 is the work of the "wrong" chain, // so this rule activates there immediately and new blocks with high diff from that chain are going // to be rejected by updated nodes. Note, that old nodes are going to reject blocks from updated nodes // after the "right" chain reaches this amount of work too. This is a temporary condition which should // be removed when we decide to hard-fork testnet again. // TODO: remove "testnet+work OR devnet" part on next testnet hard-fork // Special difficulty rule for testnet/devnet: // If the new block's timestamp is more than 2* 2.5 minutes // then allow mining of a min-difficulty block. // start using smoother adjustment on testnet when total work hits // 000000000000000000000000000000000000000000000000003ff00000000000 if (pindexLast->nChainWork >= UintToArith256(uint256S("0x000000000000000000000000000000000000000000000000003ff00000000000")) // and immediately on devnet || !params.hashDevnetGenesisBlock.IsNull()) { // recent block is more than 2 hours old if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + 2 * 60 * 60) { return bnPowLimit.GetCompact(); } // recent block is more than 10 minutes old if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*4) { arith_uint256 bnNew = arith_uint256().SetCompact(pindexLast->nBits) * 10; if (bnNew > bnPowLimit) { bnNew = bnPowLimit; } return bnNew.GetCompact(); } } else { // old stuff if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) { return bnPowLimit.GetCompact(); } } } const CBlockIndex *pindex = pindexLast; arith_uint256 bnPastTargetAvg; for (unsigned int nCountBlocks = 1; nCountBlocks <= nPastBlocks; nCountBlocks++) { arith_uint256 bnTarget = arith_uint256().SetCompact(pindex->nBits); if (nCountBlocks == 1) { bnPastTargetAvg = bnTarget; } else { // NOTE: that's not an average really... bnPastTargetAvg = (bnPastTargetAvg * nCountBlocks + bnTarget) / (nCountBlocks + 1); } if(nCountBlocks != nPastBlocks) { assert(pindex->pprev); // should never fail pindex = pindex->pprev; } } arith_uint256 bnNew(bnPastTargetAvg); int64_t nActualTimespan = pindexLast->GetBlockTime() - pindex->GetBlockTime(); // NOTE: is this accurate? nActualTimespan counts it for (nPastBlocks - 1) blocks only... int64_t nTargetTimespan = nPastBlocks * params.nPowTargetSpacing; if (nActualTimespan < nTargetTimespan/3) nActualTimespan = nTargetTimespan/3; if (nActualTimespan > nTargetTimespan*3) nActualTimespan = nTargetTimespan*3; // Retarget bnNew *= nActualTimespan; bnNew /= nTargetTimespan; if (bnNew > bnPowLimit) { bnNew = bnPowLimit; } return bnNew.GetCompact(); }