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()); }
// Test that a Sprout tx with negative version is still rejected // by CheckBlock under Sprout consensus rules. TEST(CheckBlock, BlockSproutRejectsBadVersion) { SelectParams(CBaseChainParams::MAIN); CMutableTransaction mtx; mtx.vin.resize(1); mtx.vin[0].prevout.SetNull(); mtx.vin[0].scriptSig = CScript() << 1 << OP_0; mtx.vout.resize(1); mtx.vout[0].scriptPubKey = CScript() << OP_TRUE; mtx.vout[0].nValue = 0; mtx.vout.push_back(CTxOut( GetBlockSubsidy(1, Params().GetConsensus())/5, Params().GetFoundersRewardScriptAtHeight(1))); mtx.fOverwintered = false; mtx.nVersion = -1; mtx.nVersionGroupId = 0; CTransaction tx {mtx}; CBlock block; block.vtx.push_back(tx); MockCValidationState state; CBlockIndex indexPrev {Params().GenesisBlock()}; auto verifier = libzcash::ProofVerifier::Strict(); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-version-too-low", false)).Times(1); EXPECT_FALSE(CheckBlock(block, state, verifier, false, false)); }
CDarkSendRelay::CDarkSendRelay() { vinThrone = CTxIn(); nBlockHeight = 0; nRelayType = 0; in = CTxIn(); out = CTxOut(); }
CObfuScationRelay::CObfuScationRelay() { vinMasternode = CTxIn(); nBlockHeight = 0; nRelayType = 0; in = CTxIn(); out = CTxOut(); }
CSandStormRelay::CSandStormRelay() { vinStormnode = CTxIn(); nBlockHeight = 0; nRelayType = 0; in = CTxIn(); out = CTxOut(); }
CZeroSendRelay::CZeroSendRelay() { vinBlanknode = CTxIn(); nBlockHeight = 0; nRelayType = 0; in = CTxIn(); out = CTxOut(); }
CDarkSendRelay::CDarkSendRelay() { vinMasternode = CTxIn(); nBlockHeight = 0; nRelayType = 0; in = CTxIn(); out = CTxOut(); }
CTxOut getPrevOut(const COutPoint& out) { CTransaction tx; uint256 hashBlock; if (GetTransaction(out.hash, tx, hashBlock, true)) return tx.vout[out.n]; return CTxOut(); }
/** * Construct a dummy tx that provides the given script as input * for further tests in the given CCoinsView. The txid is returned * to refer to it. The "index" is always 0. The output's * value is always set to 1000 COIN, since it doesn't matter for * the tests we are interested in. * @param scr The script that should be provided as output. * @param nHeight The height of the coin. * @param view Add it to this view. * @return The txid. */ static uint256 addTestCoin (const CScript& scr, unsigned nHeight, CCoinsViewCache& view) { CMutableTransaction mtx; mtx.vout.push_back (CTxOut (1000 * COIN, scr)); const CTransaction tx(mtx); CCoinsModifier entry = view.ModifyCoins (tx.GetHash ()); *entry = CCoins (tx, nHeight); return tx.GetHash (); }
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; }
void CMasternode::Check(bool forceCheck) { if(ShutdownRequested()) return; if(!forceCheck && (GetTime() - lastTimeChecked < MASTERNODE_CHECK_SECONDS)) return; lastTimeChecked = GetTime(); //once spent, stop doing the checks if(activeState == MASTERNODE_VIN_SPENT) return; if(lastPing.sigTime - sigTime < MASTERNODE_MIN_MNP_SECONDS){ activeState = MASTERNODE_PRE_ENABLED; return; } if(!IsPingedWithin(MASTERNODE_REMOVAL_SECONDS)){ activeState = MASTERNODE_REMOVE; return; } if(!IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS)){ activeState = MASTERNODE_EXPIRED; return; } if(!unitTest){ CValidationState state; CMutableTransaction tx = CMutableTransaction(); CTxOut vout = CTxOut(999.99*COIN, darkSendPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); { TRY_LOCK(cs_main, lockMain); if(!lockMain) return; if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)){ activeState = MASTERNODE_VIN_SPENT; return; } } } activeState = MASTERNODE_ENABLED; // OK }
CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), cachedCoinsUsage(0) { // emercoin: insert special randpay utxo that can be spent unlimited number of times // you can only spent 0 emc from it std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(randpaytx, CCoinsCacheEntry())); if (!ret.second) throw std::logic_error("Failed to insert randpay utxo!"); CCoins& coins = ret.first->second.coins; coins.fCoinBase = false; coins.fCoinStake = false; coins.nHeight = 0; coins.nVersion = 1; coins.nTime = 0; CTxOut txout = CTxOut(); txout.nValue = 0; coins.vout.push_back(txout); ret.first->second.flags = CCoinsCacheEntry::DIRTY; // set DIRTY/FRESH flags }
TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) { // Put a transaction in a block with no height in scriptSig CMutableTransaction mtx = GetFirstBlockCoinbaseTx(); mtx.vin[0].scriptSig = CScript() << OP_0; mtx.vout.pop_back(); // remove the FR output CBlock block; block.vtx.push_back(mtx); // Treating block as genesis should pass MockCValidationState state; EXPECT_TRUE(ContextualCheckBlock(block, state, NULL)); // Give the transaction a Founder's Reward vout mtx.vout.push_back(CTxOut( GetBlockSubsidy(1, Params().GetConsensus())/5, Params().GetFoundersRewardScriptAtHeight(1))); // Treating block as non-genesis should fail CTransaction tx2 {mtx}; block.vtx[0] = tx2; CBlock prev; CBlockIndex indexPrev {prev}; indexPrev.nHeight = 0; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); // Setting to an incorrect height should fail mtx.vin[0].scriptSig = CScript() << 2 << OP_0; CTransaction tx3 {mtx}; block.vtx[0] = tx3; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); // After correcting the scriptSig, should pass mtx.vin[0].scriptSig = CScript() << 1 << OP_0; CTransaction tx4 {mtx}; block.vtx[0] = tx4; EXPECT_TRUE(ContextualCheckBlock(block, state, &indexPrev)); }
void static RandomTransaction(CMutableTransaction &tx, bool fSingle) { tx.nVersion = insecure_rand(); tx.vin.clear(); tx.vout.clear(); tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0; int ins = (insecure_rand() % 4) + 1; int outs = fSingle ? ins : (insecure_rand() % 4) + 1; for (int in = 0; in < ins; in++) { tx.vin.push_back(CTxIn()); CTxIn &txin = tx.vin.back(); txin.prevout.hash = GetRandHash(); txin.prevout.n = insecure_rand() % 4; RandomScript(txin.scriptSig); txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1; } for (int out = 0; out < outs; out++) { tx.vout.push_back(CTxOut()); CTxOut &txout = tx.vout.back(); txout.nValue = insecure_rand() % 100000000; RandomScript(txout.scriptPubKey); } }
/** * Implement the rawtx name operation feature. This routine interprets * the given JSON object describing the desired name operation and then * modifies the transaction accordingly. * @param tx The transaction to extend. * @param obj The name operation "description" as given to the call. */ void AddRawTxNameOperation (CMutableTransaction& tx, const UniValue& obj) { UniValue val = find_value (obj, "op"); if (!val.isStr ()) throw JSONRPCError (RPC_INVALID_PARAMETER, "missing op key"); const std::string op = val.get_str (); if (op != "name_update") throw JSONRPCError (RPC_INVALID_PARAMETER, "only name_update is implemented for the rawtx API"); val = find_value (obj, "name"); if (!val.isStr ()) throw JSONRPCError (RPC_INVALID_PARAMETER, "missing name key"); const valtype name = ValtypeFromString (val.get_str ()); val = find_value (obj, "value"); if (!val.isStr ()) throw JSONRPCError (RPC_INVALID_PARAMETER, "missing value key"); const valtype value = ValtypeFromString (val.get_str ()); val = find_value (obj, "address"); if (!val.isStr ()) throw JSONRPCError (RPC_INVALID_PARAMETER, "missing address key"); const CBitcoinAddress toAddress(val.get_str ()); if (!toAddress.IsValid ()) throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, "invalid address"); const CScript addr = GetScriptForDestination (toAddress.Get ()); tx.SetNamecoin (); /* We do not add the name input. This has to be done explicitly, but is easy from the name_show output. That way, createrawtransaction doesn't depend on the chainstate at all. */ const CScript outScript = CNameScript::buildNameUpdate (addr, name, value); tx.vout.push_back (CTxOut (NAME_LOCKED_AMOUNT, outScript)); }
void static RandomTransaction(CMutableTransaction &tx, bool fSingle) { tx.nVersion = InsecureRand32(); tx.vin.clear(); tx.vout.clear(); tx.nLockTime = (InsecureRandBool()) ? InsecureRand32() : 0; int ins = (InsecureRandBits(2)) + 1; int outs = fSingle ? ins : (InsecureRandBits(2)) + 1; for (int in = 0; in < ins; in++) { tx.vin.push_back(CTxIn()); CTxIn &txin = tx.vin.back(); txin.prevout.hash = InsecureRand256(); txin.prevout.n = InsecureRandBits(2); RandomScript(txin.scriptSig); txin.nSequence = (InsecureRandBool()) ? InsecureRand32() : std::numeric_limits<uint32_t>::max(); } for (int out = 0; out < outs; out++) { tx.vout.push_back(CTxOut()); CTxOut &txout = tx.vout.back(); txout.nValue = InsecureRandRange(100000000); RandomScript(txout.scriptPubKey); } }
// Returns a valid but empty mutable transaction at block height 1. CMutableTransaction GetFirstBlockCoinbaseTx() { CMutableTransaction mtx; // No inputs. mtx.vin.resize(1); mtx.vin[0].prevout.SetNull(); // Set height to 1. mtx.vin[0].scriptSig = CScript() << 1 << OP_0; // Give it a single zero-valued, always-valid output. mtx.vout.resize(1); mtx.vout[0].scriptPubKey = CScript() << OP_TRUE; mtx.vout[0].nValue = 0; // Give it a Founder's Reward vout for height 1. mtx.vout.push_back(CTxOut( GetBlockSubsidy(1, Params().GetConsensus())/5, Params().GetFoundersRewardScriptAtHeight(1))); return mtx; }
void CAlphanode::Check() { if(ShutdownRequested()) return; //TODO: Random segfault with this line removed TRY_LOCK(cs_main, lockRecv); if(!lockRecv) return; //once spent, stop doing the checks if(activeState == ALPHANODE_VIN_SPENT) return; if(!UpdatedWithin(ALPHANODE_REMOVAL_SECONDS)){ activeState = ALPHANODE_REMOVE; return; } if(!UpdatedWithin(ALPHANODE_EXPIRATION_SECONDS)){ activeState = ALPHANODE_EXPIRED; return; } if(!unitTest){ CValidationState state; CTransaction tx = CTransaction(); CTxOut vout = CTxOut(Params().DarkSendPoolMax(), darkSendPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); if(!AcceptableInputs(mempool, tx, false, NULL)){ activeState = ALPHANODE_VIN_SPENT; return; } } activeState = ALPHANODE_ENABLED; // OK }
bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS) { // we are a masternode with the same vin (i.e. already activated) and this mnb is ours (matches our Masternode privkey) // so nothing to do here for us if(fMasterNode && vin.prevout == activeMasternode.vin.prevout && pubkey2 == activeMasternode.pubKeyMasternode) return true; // search existing Masternode list CMasternode* pmn = mnodeman.Find(vin); if(pmn != NULL) { // nothing to do here if we already know about this masternode and it's enabled if(pmn->IsEnabled()) return true; // if it's not enabled, remove old MN first and continue else mnodeman.Remove(pmn->vin); } CValidationState state; CMutableTransaction tx = CMutableTransaction(); CTxOut vout = CTxOut(999.99*COIN, darkSendPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); { TRY_LOCK(cs_main, lockMain); if(!lockMain) { // not mnb fault, let it to be checked again later mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); masternodeSync.mapSeenSyncMNB.erase(GetHash()); return false; } if(!AcceptableInputs(mempool, state, CTransaction(tx), false, NULL)) { //set nDos state.IsInvalid(nDoS); return false; } } LogPrint("masternode", "mnb - Accepted Masternode entry\n"); if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){ LogPrintf("mnb - Input must have at least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS); // maybe we miss few blocks, let this mnb to be checked again later mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); masternodeSync.mapSeenSyncMNB.erase(GetHash()); return false; } // verify that sig time is legit in past // should be at least not earlier than block when 1000 DASH tx got MASTERNODE_MIN_CONFIRMATIONS uint256 hashBlock = 0; CTransaction tx2; GetTransaction(vin.prevout.hash, tx2, hashBlock, true); BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi != mapBlockIndex.end() && (*mi).second) { CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1]; // block where tx got MASTERNODE_MIN_CONFIRMATIONS if(pConfIndex->GetBlockTime() > sigTime) { LogPrintf("mnb - Bad sigTime %d for Masternode %20s %105s (%i conf block is at %d)\n", sigTime, addr.ToString(), vin.ToString(), MASTERNODE_MIN_CONFIRMATIONS, pConfIndex->GetBlockTime()); return false; } } LogPrintf("mnb - Got NEW Masternode entry - %s - %s - %s - %lli \n", GetHash().ToString(), addr.ToString(), vin.ToString(), sigTime); CMasternode mn(*this); mnodeman.Add(mn); // if it matches our Masternode privkey, then we've been remotely activated if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){ activeMasternode.EnableHotColdMasterNode(vin, addr); } bool isLocal = addr.IsRFC1918() || addr.IsLocal(); if(Params().NetworkID() == CBaseChainParams::REGTEST) isLocal = false; if(!isLocal) Relay(); return true; }
void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t consensusBranchId) { tx.fOverwintered = insecure_rand() % 2; if (tx.fOverwintered) { if (insecure_rand() % 2) { tx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; tx.nVersion = sapling_version_dist(rng); } else { tx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; tx.nVersion = overwinter_version_dist(rng); } tx.nExpiryHeight = (insecure_rand() % 2) ? insecure_rand() : 0; } else { tx.nVersion = insecure_rand() & 0x7FFFFFFF; } tx.vin.clear(); tx.vout.clear(); tx.vShieldedSpend.clear(); tx.vShieldedOutput.clear(); tx.vjoinsplit.clear(); tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0; int ins = (insecure_rand() % 4) + 1; int outs = fSingle ? ins : (insecure_rand() % 4) + 1; int shielded_spends = (insecure_rand() % 4) + 1; int shielded_outs = (insecure_rand() % 4) + 1; int joinsplits = (insecure_rand() % 4); for (int in = 0; in < ins; in++) { tx.vin.push_back(CTxIn()); CTxIn &txin = tx.vin.back(); txin.prevout.hash = GetRandHash(); txin.prevout.n = insecure_rand() % 4; RandomScript(txin.scriptSig); txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1; } for (int out = 0; out < outs; out++) { tx.vout.push_back(CTxOut()); CTxOut &txout = tx.vout.back(); txout.nValue = insecure_rand() % 100000000; RandomScript(txout.scriptPubKey); } if (tx.nVersionGroupId == SAPLING_VERSION_GROUP_ID) { tx.valueBalance = insecure_rand() % 100000000; for (int spend = 0; spend < shielded_spends; spend++) { SpendDescription sdesc; sdesc.cv = GetRandHash(); sdesc.anchor = GetRandHash(); sdesc.nullifier = GetRandHash(); sdesc.rk = GetRandHash(); randombytes_buf(sdesc.zkproof.begin(), sdesc.zkproof.size()); tx.vShieldedSpend.push_back(sdesc); } for (int out = 0; out < shielded_outs; out++) { OutputDescription odesc; odesc.cv = GetRandHash(); odesc.cm = GetRandHash(); odesc.ephemeralKey = GetRandHash(); randombytes_buf(odesc.encCiphertext.begin(), odesc.encCiphertext.size()); randombytes_buf(odesc.outCiphertext.begin(), odesc.outCiphertext.size()); randombytes_buf(odesc.zkproof.begin(), odesc.zkproof.size()); tx.vShieldedOutput.push_back(odesc); } } if (tx.nVersion >= 2) { for (int js = 0; js < joinsplits; js++) { JSDescription jsdesc; if (insecure_rand() % 2 == 0) { jsdesc.vpub_old = insecure_rand() % 100000000; } else { jsdesc.vpub_new = insecure_rand() % 100000000; } jsdesc.anchor = GetRandHash(); jsdesc.nullifiers[0] = GetRandHash(); jsdesc.nullifiers[1] = GetRandHash(); jsdesc.ephemeralKey = GetRandHash(); jsdesc.randomSeed = GetRandHash(); randombytes_buf(jsdesc.ciphertexts[0].begin(), jsdesc.ciphertexts[0].size()); randombytes_buf(jsdesc.ciphertexts[1].begin(), jsdesc.ciphertexts[1].size()); if (tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION) { libzcash::GrothProof zkproof; randombytes_buf(zkproof.begin(), zkproof.size()); jsdesc.proof = zkproof; } else { jsdesc.proof = libzcash::PHGRProof::random_invalid(); } jsdesc.macs[0] = GetRandHash(); jsdesc.macs[1] = GetRandHash(); tx.vjoinsplit.push_back(jsdesc); } unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; crypto_sign_keypair(tx.joinSplitPubKey.begin(), joinSplitPrivKey); // Empty output script. CScript scriptCode; CTransaction signTx(tx); uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId); assert(crypto_sign_detached(&tx.joinSplitSig[0], NULL, dataToBeSigned.begin(), 32, joinSplitPrivKey ) == 0); } }
for (unsigned int i = 0; i < tx.vin.size(); i++) nResult += AccessCoin(tx.vin[i].prevout).out.nValue; return nResult; } bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const { if (!tx.IsCoinBase()) { for (unsigned int i = 0; i < tx.vin.size(); i++) { if (!HaveCoin(tx.vin[i].prevout)) { return false; } } } return true; } static const size_t MAX_OUTPUTS_PER_BLOCK = MaxBlockSize(true) / ::GetSerializeSize(CTxOut(), SER_NETWORK, PROTOCOL_VERSION); // TODO: merge with similar definition in undo.h. const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid) { COutPoint iter(txid, 0); while (iter.n < MAX_OUTPUTS_PER_BLOCK) { const Coin& alternate = view.AccessCoin(iter); if (!alternate.IsSpent()) return alternate; ++iter.n; } return coinEmpty; }
void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { if (strCommand == "dsee") { //DarkSend Election Entry if (pfrom->nVersion != darkSendPool.MIN_PEER_PROTO_VERSION) { return; } bool fIsInitialDownload = IsInitialBlockDownload(); if(fIsInitialDownload) return; CTxIn vin; CService addr; CPubKey pubkey; CPubKey pubkey2; vector<unsigned char> vchSig; int64 sigTime; int count; int current; int64 lastUpdated; vRecv >> vin >> addr >> vchSig >> sigTime >> pubkey >> pubkey2 >> count >> current >> lastUpdated; bool isLocal = false; // addr.IsRFC1918(); std::string vchPubKey(pubkey.begin(), pubkey.end()); std::string vchPubKey2(pubkey2.begin(), pubkey2.end()); CScript pubkeyScript; pubkeyScript.SetDestination(pubkey.GetID()); if(pubkeyScript.size() != 25) { LogPrintf("dsee - pubkey the wrong size\n"); pfrom->Misbehaving(100); return; } std::string strMessage = addr.ToString() + boost::lexical_cast<std::string>(sigTime) + vchPubKey + vchPubKey2; CScript pubkeyScript2; pubkeyScript2.SetDestination(pubkey2.GetID()); if(pubkeyScript2.size() != 25) { LogPrintf("dsee - pubkey the wrong size\n"); pfrom->Misbehaving(100); return; } std::string errorMessage = ""; if(!darkSendSigner.VerifyMessage(pubkey, vchSig, strMessage, errorMessage)){ LogPrintf("dsee - Got bad masternode address signature\n"); pfrom->Misbehaving(100); return; } if((fTestNet && addr.GetPort() != 19999) || (!fTestNet && addr.GetPort() != 9999)) return; //LogPrintf("Searching existing masternodes : %s - %s\n", addr.ToString().c_str(), vin.ToString().c_str()); BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes) { //LogPrintf(" -- %s\n", mn.vin.ToString().c_str()); if(mn.vin.prevout == vin.prevout) { //count == -1 when it's a new entry // e.g. We don't want the entry relayed/time updated when we're syncing the list if(count == -1 && !mn.UpdatedWithin(MASTERNODE_MIN_SECONDS)){ mn.UpdateLastSeen(); if(mn.now < sigTime){ //take the newest entry LogPrintf("dsee - Got updated entry for %s\n", addr.ToString().c_str()); mn.pubkey2 = pubkey2; mn.now = sigTime; mn.sig = vchSig; if(pubkey2 == activeMasternode.pubkeyMasterNode2){ activeMasternode.EnableHotColdMasterNode(vin, sigTime, addr); } RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated); } } return; } } if(!darkSendSigner.IsVinAssociatedWithPubkey(vin, pubkey)) { LogPrintf("dsee - Got mismatched pubkey and vin\n"); pfrom->Misbehaving(100); return; } LogPrintf("dsee - Got NEW masternode entry %s\n", addr.ToString().c_str()); CValidationState state; CTransaction tx = CTransaction(); CTxOut vout = CTxOut(999.99*COIN, darkSendPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); if(tx.AcceptableInputs(state, true)){ LogPrintf("dsee - Accepted masternode entry %i %i\n", count, current); if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){ LogPrintf("dsee - Input must have least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS); pfrom->Misbehaving(20); return; } addrman.Add(CAddress(addr), pfrom->addr, 2*60*60); CMasterNode mn(addr, vin, pubkey, vchSig, sigTime, pubkey2); mn.UpdateLastSeen(lastUpdated); darkSendMasterNodes.push_back(mn); if(pubkey2 == activeMasternode.pubkeyMasterNode2){ activeMasternode.EnableHotColdMasterNode(vin, sigTime, addr); } if(count == -1 && !isLocal) RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated); } else { LogPrintf("dsee - Rejected masternode entry\n"); int nDoS = 0; if (state.IsInvalid(nDoS)) { LogPrintf("dsee - %s from %s %s was not accepted into the memory pool\n", tx.GetHash().ToString().c_str(), pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str()); if (nDoS > 0) pfrom->Misbehaving(nDoS); } } } else if (strCommand == "dseep") { //DarkSend Election Entry Ping
nResult += AccessCoin(tx.vin[i].prevout).out.nValue; return nResult; } bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const { if (!tx.IsCoinBase()) { for (unsigned int i = 0; i < tx.vin.size(); i++) { if (!HaveCoin(tx.vin[i].prevout)) { return false; } } } return true; } static const size_t MIN_TRANSACTION_OUTPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut(), SER_NETWORK, PROTOCOL_VERSION); static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_OUTPUT_WEIGHT; const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid) { COutPoint iter(txid, 0); while (iter.n < MAX_OUTPUTS_PER_BLOCK) { const Coin& alternate = view.AccessCoin(iter); if (!alternate.IsSpent()) return alternate; ++iter.n; } return coinEmpty; }
void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { if (strCommand == "dsee") { //DarkSend Election Entry if(fLiteMode) return; //disable all darksend/masternode related functionality bool fIsInitialDownload = IsInitialBlockDownload(); if(fIsInitialDownload) return; CTxIn vin; CService addr; CPubKey pubkey; CPubKey pubkey2; vector<unsigned char> vchSig; int64_t sigTime; int count; int current; int64_t lastUpdated; int protocolVersion; std::string strMessage; // 70047 and greater vRecv >> vin >> addr >> vchSig >> sigTime >> pubkey >> pubkey2 >> count >> current >> lastUpdated >> protocolVersion; // make sure signature isn't in the future (past is OK) if (sigTime > GetAdjustedTime() + 60 * 60) { printf("dsee - Signature rejected, too far into the future %s\n", vin.ToString().c_str()); return; } bool isLocal = addr.IsRFC1918() || addr.IsLocal(); //if(Params().MineBlocksOnDemand()) isLocal = false; std::string vchPubKey(pubkey.vchPubKey.begin(), pubkey.vchPubKey.end()); std::string vchPubKey2(pubkey2.vchPubKey.begin(), pubkey2.vchPubKey.end()); strMessage = addr.ToString() + boost::lexical_cast<std::string>(sigTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(protocolVersion); if(protocolVersion < MIN_MN_PROTO_VERSION) { printf("dsee - ignoring outdated masternode %s protocol version %d\n", vin.ToString().c_str(), protocolVersion); return; } CScript pubkeyScript; pubkeyScript =GetScriptForDestination(pubkey.GetID()); if(pubkeyScript.size() != 25) { printf("dsee - pubkey the wrong size\n"); pfrom->Misbehaving(100); return; } CScript pubkeyScript2; pubkeyScript2 =GetScriptForDestination(pubkey2.GetID()); if(pubkeyScript2.size() != 25) { printf("dsee - pubkey2 the wrong size\n"); pfrom->Misbehaving(100); return; } std::string errorMessage = ""; if(!darkSendSigner.VerifyMessage(pubkey, vchSig, strMessage, errorMessage)){ printf("dsee - Got bad masternode address signature\n"); pfrom->Misbehaving(100); return; } //search existing masternode list, this is where we update existing masternodes with new dsee broadcasts LOCK(cs_masternodes); BOOST_FOREACH(CMasterNode& mn, vecMasternodes) { if(mn.vin.prevout == vin.prevout) { // count == -1 when it's a new entry // e.g. We don't want the entry relayed/time updated when we're syncing the list // mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below, // after that they just need to match if(count == -1 && mn.pubkey == pubkey && !mn.UpdatedWithin(MASTERNODE_MIN_DSEE_SECONDS)){ mn.UpdateLastSeen(); if(mn.now < sigTime){ //take the newest entry printf("dsee - Got updated entry for %s\n", addr.ToString().c_str()); mn.pubkey2 = pubkey2; mn.now = sigTime; mn.sig = vchSig; mn.protocolVersion = protocolVersion; mn.addr = addr; RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion); } } return; } } // make sure the vout that was signed is related to the transaction that spawned the masternode // - this is expensive, so it's only done once per masternode if(!darkSendSigner.IsVinAssociatedWithPubkey(vin, pubkey)) { printf("dsee - Got mismatched pubkey and vin\n"); pfrom->Misbehaving(100); return; } if(fDebug) printf("dsee - Got NEW masternode entry %s\n", addr.ToString().c_str()); // make sure it's still unspent // - this is checked later by .check() in many places and by ThreadCheckDarkSendPool() CTransaction tx = CTransaction(); CTxOut vout = CTxOut(24999*COIN, darkSendPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); //if(AcceptableInputs(mempool, state, tx)){ bool* pfMissingInputs = false; if(AcceptableInputs(mempool, tx, false, pfMissingInputs)){ if(fDebug) printf("dsee - Accepted masternode entry %i %i\n", count, current); if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){ printf("dsee - Input must have least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS); pfrom->Misbehaving(20); return; } // use this as a peer addrman.Add(CAddress(addr), pfrom->addr, 2*60*60); // add our masternode CMasterNode mn(addr, vin, pubkey, vchSig, sigTime, pubkey2, protocolVersion); mn.UpdateLastSeen(lastUpdated); vecMasternodes.push_back(mn); // if it matches our masternodeprivkey, then we've been remotely activated if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){ activeMasternode.EnableHotColdMasterNode(vin, addr); } if(count == -1 && !isLocal) RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion); } else { printf("dsee - Rejected masternode entry %s\n", addr.ToString().c_str()); int nDoS = 0; /* if (state.IsInvalid(nDoS)) { printf("dsee - %s from %s %s was not accepted into the memory pool\n", tx.GetHash().ToString().c_str(), pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str()); if (nDoS > 0) pfrom->Misbehaving(nDoS); }*/ } } else if (strCommand == "dseep") { //DarkSend Election Entry Ping