// Test CacheBlockAddress Utility class, mostly that constructor and // comparison operators are properly defined. bool TestCacheBlockAddress() { uint32 offset = 100; uint32 segment_id = 1010; CachedReadAccessor::CacheBlockAddress address1(segment_id, offset); TestAssertEquals(offset, address1.Offset()); { // Equality and copy constructor tests. CachedReadAccessor::CacheBlockAddress address2(segment_id, offset); TestAssert(address1 == address2); TestAssert((address1 < address2) == false); CachedReadAccessor::CacheBlockAddress address3 = address1; TestAssert(address2 == address3); } { // less than by segment id CachedReadAccessor::CacheBlockAddress address2(segment_id+1, offset); TestAssert(address1 < address2); TestAssert(address1 != address2); TestAssert((address2 < address1) == false); } { // less than by offset CachedReadAccessor::CacheBlockAddress address2(segment_id, offset+1); TestAssert(address1 < address2); TestAssert(address1 != address2); TestAssert((address2 < address1) == false); } return true; }
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet) { // make sure it's not filled yet txoutMasternodeRet = CTxOut(); CScript payee; if(!mnpayments.GetBlockPayee(nBlockHeight, payee)) { // no masternode detected... int nCount = 0; masternode_info_t mnInfo; if(!mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount, mnInfo)) { // ...and we can't calculate it on our own LogPrintf("CMasternodePayments::FillBlockPayee -- Failed to detect masternode to pay\n"); return; } // fill payee with locally calculated winner and hope for the best payee = GetScriptForDestination(mnInfo.pubKeyCollateralAddress.GetID()); } // GET MASTERNODE PAYMENT VARIABLES SETUP CAmount masternodePayment = GetMasternodePayment(nBlockHeight, blockReward); // split reward between miner ... txNew.vout[0].nValue -= masternodePayment; // ... and masternode txoutMasternodeRet = CTxOut(masternodePayment, payee); txNew.vout.push_back(txoutMasternodeRet); CTxDestination address1; ExtractDestination(payee, address1); CBitcoinAddress address2(address1); LogPrintf("CMasternodePayments::FillBlockPayee -- Masternode payment %lld to %s\n", masternodePayment, address2.ToString()); }
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFees, bool fProofOfStake, bool fZXAPStake) { CBlockIndex* pindexPrev = chainActive.Tip(); if (!pindexPrev) return; bool hasPayment = true; CScript payee; //spork if (!masternodePayments.GetBlockPayee(pindexPrev->nHeight + 1, payee)) { //no masternode detected CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1); if (winningNode) { payee = GetScriptForDestination(winningNode->pubKeyCollateralAddress.GetID()); } else { LogPrint("masternode","CreateNewBlock: Failed to detect masternode to pay\n"); hasPayment = false; } } CAmount blockValue = GetBlockValue(pindexPrev->nHeight); CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight, blockValue, 0, fZXAPStake); if (hasPayment) { if (fProofOfStake) { /**For Proof Of Stake vout[0] must be null * Stake reward can be split into many different outputs, so we must * use vout.size() to align with several different cases. * An additional output is appended as the masternode payment */ unsigned int i = txNew.vout.size(); txNew.vout.resize(i + 1); txNew.vout[i].scriptPubKey = payee; txNew.vout[i].nValue = masternodePayment; //subtract mn payment from the stake reward if (!txNew.vout[1].IsZerocoinMint()) txNew.vout[i - 1].nValue -= masternodePayment; } else { txNew.vout.resize(2); txNew.vout[1].scriptPubKey = payee; txNew.vout[1].nValue = masternodePayment; txNew.vout[0].nValue = blockValue - masternodePayment; } CTxDestination address1; ExtractDestination(payee, address1); CBitcoinAddress address2(address1); LogPrint("masternode","Masternode payment of %s to %s\n", FormatMoney(masternodePayment).c_str(), address2.ToString().c_str()); } else { if (!fProofOfStake) txNew.vout[0].nValue = blockValue; } }
//TODO (Amir): Use CMutableTransaction. void CStormnodePayments::FillBlockPayee(CTransaction& txNew, CAmount nFees) { CBlockIndex* pindexPrev = pindexBest; if(!pindexPrev) return; bool hasPayment = true; CScript payee; //spork if(!stormnodePayments.GetBlockPayee(pindexPrev->nHeight+1, payee)){ //no stormnode detected CStormnode* winningNode = snodeman.GetCurrentStormNode(); if(winningNode){ payee = GetScriptForDestination(winningNode->pubkey.GetID()); } else { LogPrintf("CreateNewBlock: Failed to detect stormnode to pay\n"); hasPayment = false; } } if(hasPayment){ //txNew.vout.resize(2); txNew.vout[1].scriptPubKey = payee; //txNew.vout[1].nValue = stormnodePayment; //txNew.vout[0].nValue -= stormnodePayment; // Stormnode Payments CAmount blockValue = GetBlockValue(pindexPrev->nBits, pindexPrev->nHeight, nFees); CAmount stormnodePayment = GetStormnodePayment(pindexPrev->nHeight+1, blockValue); if(txNew.vout.size() == 4) // 2 stake outputs, stake was split, plus a stormnode payment { txNew.vout[1].nValue = stormnodePayment; blockValue -= stormnodePayment; txNew.vout[2].nValue = (blockValue / 2 / CENT) * CENT; txNew.vout[3].nValue = blockValue - txNew.vout[1].nValue; } else if(txNew.vout.size() == 3) // only 1 stake output, was not split, plus a stormnode payment { txNew.vout[1].nValue = stormnodePayment; blockValue -= stormnodePayment; txNew.vout[2].nValue = blockValue; } CTxDestination address1; ExtractDestination(payee, address1); CDarkSilkAddress address2(address1); LogPrintf("Stormnode payment to %s\n", address2.ToString().c_str()); } }
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFees, bool fProofOfStake) { CBlockIndex* pindexPrev = chainActive.Tip(); if(!pindexPrev) return; bool hasPayment = true; CScript payee; //spork if(!masternodePayments.GetBlockPayee(pindexPrev->nHeight+1, payee)){ //no masternode detected CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1); if(winningNode){ payee = GetScriptForDestination(winningNode->pubKeyCollateralAddress.GetID()); } else { LogPrintf("CreateNewBlock: Failed to detect masternode to pay\n"); hasPayment = false; } } CAmount blockValue = GetBlockValue(pindexPrev->nHeight); CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight, blockValue); if(hasPayment) { if(fProofOfStake) { unsigned int i = txNew.vout.size(); txNew.vout.resize(i + 1); txNew.vout[i].scriptPubKey = payee; txNew.vout[i].nValue = masternodePayment; txNew.vout[i - 1].nValue -= masternodePayment; } else { txNew.vout.resize(2); txNew.vout[1].scriptPubKey = payee; txNew.vout[1].nValue = masternodePayment; txNew.vout[0].nValue = blockValue - masternodePayment; } CTxDestination address1; ExtractDestination(payee, address1); CBitcoinAddress address2(address1); LogPrintf("Masternode payment to %s\n", address2.ToString().c_str()); } }
void tst_QHostAddress::scopeId() { QHostAddress address("fe80::2e0:4cff:fefb:662a%eth0"); QCOMPARE(address.scopeId(), QString("eth0")); QCOMPARE(address.toString().toLower(), QString("fe80::2e0:4cff:fefb:662a%eth0")); QHostAddress address2("fe80::2e0:4cff:fefb:662a"); QCOMPARE(address2.scopeId(), QString()); address2.setScopeId(QString("en0")); QCOMPARE(address2.toString().toLower(), QString("fe80::2e0:4cff:fefb:662a%en0")); address2 = address; QCOMPARE(address2.scopeId(), QString("eth0")); QCOMPARE(address2.toString().toLower(), QString("fe80::2e0:4cff:fefb:662a%eth0")); }
bool CSuperblockManager::GetSuperblockPayments(int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet) { LOCK(governance.cs); // GET THE BEST SUPERBLOCK FOR THIS BLOCK HEIGHT CSuperblock_sptr pSuperblock; if (!CSuperblockManager::GetBestSuperblock(pSuperblock, nBlockHeight)) { LogPrint("gobject", "CSuperblockManager::GetSuperblockPayments -- Can't find superblock for height %d\n", nBlockHeight); return false; } // make sure it's empty, just in case voutSuperblockRet.clear(); // GET SUPERBLOCK OUTPUTS // Superblock payments will be appended to the end of the coinbase vout vector // TODO: How many payments can we add before things blow up? // Consider at least following limits: // - max coinbase tx size // - max "budget" available for (int i = 0; i < pSuperblock->CountPayments(); i++) { CGovernancePayment payment; if (pSuperblock->GetPayment(i, payment)) { // SET COINBASE OUTPUT TO SUPERBLOCK SETTING CTxOut txout = CTxOut(payment.nAmount, payment.script); voutSuperblockRet.push_back(txout); // PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT CTxDestination address1; ExtractDestination(payment.script, address1); CBitcoinAddress address2(address1); // TODO: PRINT NICE N.N DASH OUTPUT LogPrint("gobject", "CSuperblockManager::GetSuperblockPayments -- NEW Superblock: output %d (addr %s, amount %lld)\n", i, address2.ToString(), payment.nAmount); } else { LogPrint("gobject", "CSuperblockManager::GetSuperblockPayments -- Payment not found\n"); } } return true; }
/* virtual methods from class LeScanCallback */ void OnLeScan(const char *address, const char *name) override { { std::string address2(address); if (addresses.find(address2) != addresses.end()) /* already in the list */ return; addresses.emplace(std::move(address2)); } { const ScopeLock protect(mutex); new_items.emplace_front(address, name); } Notify::SendNotification(); };
void MasternodeManager::updateNodeList() { TRY_LOCK(cs_masternodes, lockMasternodes); if(!lockMasternodes) return; ui->countLabel->setText("Updating..."); ui->tableWidget->clearContents(); ui->tableWidget->setRowCount(0); BOOST_FOREACH(CMasterNode mn, vecMasternodes) { int mnRow = 0; ui->tableWidget->insertRow(0); // populate list // Address, Rank, Active, Active Seconds, Last Seen, Pub Key QTableWidgetItem *activeItem = new QTableWidgetItem(QString::number(mn.IsEnabled())); QTableWidgetItem *addressItem = new QTableWidgetItem(QString::fromStdString(mn.addr.ToString())); QTableWidgetItem *rankItem = new QTableWidgetItem(QString::number(GetMasternodeRank(mn.vin, pindexBest->nHeight))); QTableWidgetItem *activeSecondsItem = new QTableWidgetItem(seconds_to_DHMS((qint64)(mn.lastTimeSeen - mn.now))); QTableWidgetItem *lastSeenItem = new QTableWidgetItem(QString::fromStdString(DateTimeStrFormat(mn.lastTimeSeen))); CScript pubkey; pubkey =GetScriptForDestination(mn.pubkey.GetID()); CTxDestination address1; ExtractDestination(pubkey, address1); CBitcoinAddress address2(address1); QTableWidgetItem *pubkeyItem = new QTableWidgetItem(QString::fromStdString(address2.ToString())); ui->tableWidget->setItem(mnRow, 0, addressItem); ui->tableWidget->setItem(mnRow, 1, rankItem); ui->tableWidget->setItem(mnRow, 2, activeItem); ui->tableWidget->setItem(mnRow, 3, activeSecondsItem); ui->tableWidget->setItem(mnRow, 4, lastSeenItem); ui->tableWidget->setItem(mnRow, 5, pubkeyItem); }
std::string CSuperblockManager::GetRequiredPaymentsString(int nBlockHeight) { LOCK(governance.cs); std::string ret = "Unknown"; // GET BEST SUPERBLOCK CSuperblock_sptr pSuperblock; if (!GetBestSuperblock(pSuperblock, nBlockHeight)) { LogPrint("gobject", "CSuperblockManager::GetRequiredPaymentsString -- Can't find superblock for height %d\n", nBlockHeight); return "error"; } // LOOP THROUGH SUPERBLOCK PAYMENTS, CONFIGURE OUTPUT STRING for (int i = 0; i < pSuperblock->CountPayments(); i++) { CGovernancePayment payment; if (pSuperblock->GetPayment(i, payment)) { // PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT CTxDestination address1; ExtractDestination(payment.script, address1); CBitcoinAddress address2(address1); // RETURN NICE OUTPUT FOR CONSOLE if (ret != "Unknown") { ret += ", " + address2.ToString(); } else { ret = address2.ToString(); } } } return ret; }
void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { if(IsInitialBlockDownload()) return; if (strCommand == "mnget") { //Masternode Payments Request Sync if(fLiteMode) return; //disable all Darksend/Masternode related functionality if(pfrom->HasFulfilledRequest("mnget")) { LogPrintf("mnget - peer already asked me for the list\n"); Misbehaving(pfrom->GetId(), 20); return; } pfrom->FulfilledRequest("mnget"); masternodePayments.Sync(pfrom); LogPrintf("mnget - Sent Masternode winners to %s\n", pfrom->addr.ToString().c_str()); } else if (strCommand == "mnw") { //Masternode Payments Declare Winner LOCK(cs_masternodepayments); //this is required in litemode CMasternodePaymentWinner winner; vRecv >> winner; if(chainActive.Tip() == NULL) return; CTxDestination address1; ExtractDestination(winner.payee, address1); CBitcoinAddress address2(address1); uint256 hash = winner.GetHash(); if(mapSeenMasternodeVotes.count(hash)) { if(fDebug) LogPrintf("mnw - seen vote %s Addr %s Height %d bestHeight %d\n", hash.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight); return; } if(winner.nBlockHeight < chainActive.Tip()->nHeight - 10 || winner.nBlockHeight > chainActive.Tip()->nHeight+20){ LogPrintf("mnw - winner out of range %s Addr %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight); return; } if(winner.vin.nSequence != std::numeric_limits<unsigned int>::max()){ LogPrintf("mnw - invalid nSequence\n"); Misbehaving(pfrom->GetId(), 100); return; } LogPrintf("mnw - winning vote - Vin %s Addr %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, chainActive.Tip()->nHeight); if(!masternodePayments.CheckSignature(winner)){ LogPrintf("mnw - invalid signature\n"); Misbehaving(pfrom->GetId(), 100); return; } mapSeenMasternodeVotes.insert(make_pair(hash, winner)); if(masternodePayments.AddWinningMasternode(winner)){ masternodePayments.Relay(winner); } }
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; }
void ProcessMessageAlphanodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { if(!darkSendPool.IsBlockchainSynced()) return; if (strCommand == "mnget") { //Alpha Node Payments Request Sync if(pfrom->HasFulfilledRequest("mnget")) { LogPrintf("mnget - peer already asked me for the list\n"); Misbehaving(pfrom->GetId(), 20); return; } pfrom->FulfilledRequest("mnget"); alphanodePayments.Sync(pfrom); LogPrintf("mnget - Sent Alpha Node winners to %s\n", pfrom->addr.ToString().c_str()); } else if (strCommand == "mnw") { //Alpha Node Payments Declare Winner LOCK(cs_alphanodepayments); //this is required in litemode CAlphanodePaymentWinner winner; vRecv >> winner; if(pindexBest == NULL) return; CTxDestination address1; ExtractDestination(winner.payee, address1); CTaoAddress address2(address1); uint256 hash = winner.GetHash(); if(mapSeenAlphanodeVotes.count(hash)) { if(fDebug) LogPrintf("mnw - seen vote %s Addr %s Height %d bestHeight %d\n", hash.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, pindexBest->nHeight); return; } if(winner.nBlockHeight < pindexBest->nHeight - 10 || winner.nBlockHeight > pindexBest->nHeight+20){ LogPrintf("mnw - winner out of range %s Addr %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, pindexBest->nHeight); return; } if(winner.vin.nSequence != std::numeric_limits<unsigned int>::max()){ LogPrintf("mnw - invalid nSequence\n"); Misbehaving(pfrom->GetId(), 100); return; } LogPrintf("mnw - winning vote - Vin %s Addr %s Height %d bestHeight %d\n", winner.vin.ToString().c_str(), address2.ToString().c_str(), winner.nBlockHeight, pindexBest->nHeight); if(!alphanodePayments.CheckSignature(winner)){ LogPrintf("mnw - invalid signature\n"); Misbehaving(pfrom->GetId(), 100); return; } mapSeenAlphanodeVotes.insert(make_pair(hash, winner)); if(alphanodePayments.AddWinningAlphanode(winner)){ alphanodePayments.Relay(winner); } }
int main(int argc, char *argv[]) { Args args(argc, argv, "HOST KEY"); const char *host = args.ExpectNext(); const char *key = args.ExpectNext(); StaticSocketAddress address; if (!address.Lookup(host, "5597", SOCK_DGRAM)) { fprintf(stderr, "Failed to look up: %s\n", host); return EXIT_FAILURE; } #ifdef HAVE_SKYLINES_TRACKING_HANDLER InitialiseIOThread(); #endif SkyLinesTracking::Client client; #ifdef HAVE_SKYLINES_TRACKING_HANDLER client.SetIOThread(io_thread); Handler handler; client.SetHandler(&handler); #endif IPv4Address address2(1,2,3,4,1234); client.SetKey(ParseUint64(key, NULL, 16)); if (!client.Open(address2)) { fprintf(stderr, "Failed to create client\n"); return EXIT_FAILURE; } if (args.IsEmpty() || StringIsEqual(args.PeekNext(), "fix")) { NMEAInfo basic; basic.Reset(); basic.UpdateClock(); basic.time = fixed(1); basic.time_available.Update(basic.clock); return client.SendFix(basic) ? EXIT_SUCCESS : EXIT_FAILURE; } else if (StringIsEqual(args.PeekNext(), "ping")) { client.SendPing(1); #ifdef HAVE_SKYLINES_TRACKING_HANDLER handler.Wait(); #endif } else if (StringIsEqual(args.PeekNext(), "traffic")) { client.SendTrafficRequest(true, true); #ifdef HAVE_SKYLINES_TRACKING_HANDLER handler.Wait(); #endif } else { DebugReplay *replay = CreateDebugReplay(args); if (replay == NULL) return EXIT_FAILURE; while (replay->Next()) { client.SendFix(replay->Basic()); usleep(100000); } } #ifdef HAVE_SKYLINES_TRACKING_HANDLER client.Close(); DeinitialiseIOThread(); #endif return EXIT_SUCCESS; }
bool CSuperblock::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) { // TODO : LOCK(cs); // No reason for a lock here now since this method only accesses data // internal to *this and since CSuperblock's are accessed only through // shared pointers there's no way our object can get deleted while this // code is running. if (!IsValidBlockHeight(nBlockHeight)) { LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, incorrect block height\n"); return false; } std::string strPayeesPossible = ""; // CONFIGURE SUPERBLOCK OUTPUTS int nOutputs = txNew.vout.size(); int nPayments = CountPayments(); int nMinerAndMasternodePayments = nOutputs - nPayments; LogPrint("gobject", "CSuperblock::IsValid -- nOutputs = %d, nPayments = %d, GetDataAsHexString = %s\n", nOutputs, nPayments, GetGovernanceObject()->GetDataAsHexString()); // We require an exact match (including order) between the expected // superblock payments and the payments actually in the block. if (nMinerAndMasternodePayments < 0) { // This means the block cannot have all the superblock payments // so it is not valid. // TODO: could that be that we just hit coinbase size limit? LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, too few superblock payments\n"); return false; } // payments should not exceed limit CAmount nPaymentsTotalAmount = GetPaymentsTotalAmount(); CAmount nPaymentsLimit = GetPaymentsLimit(nBlockHeight); if (nPaymentsTotalAmount > nPaymentsLimit) { LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, payments limit exceeded: payments %lld, limit %lld\n", nPaymentsTotalAmount, nPaymentsLimit); return false; } // miner and masternodes should not get more than they would usually get CAmount nBlockValue = txNew.GetValueOut(); if (nBlockValue > blockReward + nPaymentsTotalAmount) { LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, block value limit exceeded: block %lld, limit %lld\n", nBlockValue, blockReward + nPaymentsTotalAmount); return false; } int nVoutIndex = 0; for (int i = 0; i < nPayments; i++) { CGovernancePayment payment; if (!GetPayment(i, payment)) { // This shouldn't happen so log a warning LogPrintf("CSuperblock::IsValid -- WARNING: Failed to find payment: %d of %d total payments\n", i, nPayments); continue; } bool fPaymentMatch = false; for (int j = nVoutIndex; j < nOutputs; j++) { // Find superblock payment fPaymentMatch = ((payment.script == txNew.vout[j].scriptPubKey) && (payment.nAmount == txNew.vout[j].nValue)); if (fPaymentMatch) { nVoutIndex = j; break; } } if (!fPaymentMatch) { // Superblock payment not found! CTxDestination address1; ExtractDestination(payment.script, address1); CBitcoinAddress address2(address1); LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid: %d payment %d to %s not found\n", i, payment.nAmount, address2.ToString()); return false; } } return true; }