bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight) { if(!masternodeSync.IsSynced()) { //there is no budget data to use to check anything -- find the longest chain LogPrint("mnpayments", "Client not synced, skipping block payee checks\n"); return true; } //check if it's a budget block if(IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)){ if(budget.IsBudgetPaymentBlock(nBlockHeight)){ if(budget.IsTransactionValid(txNew, nBlockHeight)){ return true; } else { LogPrintf("Invalid budget payment detected %s\n", txNew.ToString().c_str()); if(IsSporkActive(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT)){ return false; } else { LogPrintf("Budget enforcement is disabled, accepting block\n"); return true; } } } } //check for masternode payee if(masternodePayments.IsTransactionValid(txNew, nBlockHeight)) { return true; } else { LogPrintf("Invalid mn payment detected %s\n", txNew.ToString().c_str()); if(IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)){ return false; } else { LogPrintf("Masternode payment enforcement is disabled, accepting block\n"); return true; } } return false; }
// check to make sure the collateral provided by the client is valid bool CPrivateSend::IsCollateralValid(const CTransaction& txCollateral) { if(txCollateral.vout.empty()) return false; if(txCollateral.nLockTime != 0) return false; CAmount nValueIn = 0; CAmount nValueOut = 0; for (const auto& txout : txCollateral.vout) { nValueOut += txout.nValue; bool fAllowData = true; if(!txout.scriptPubKey.IsPayToPublicKeyHash() && !(fAllowData && txout.scriptPubKey.IsUnspendable())) { LogPrintf ("CPrivateSend::IsCollateralValid -- Invalid Script, txCollateral=%s", txCollateral.ToString()); return false; } } for (const auto& txin : txCollateral.vin) { Coin coin; if(!GetUTXOCoin(txin.prevout, coin)) { LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- Unknown inputs in collateral transaction, txCollateral=%s", txCollateral.ToString()); return false; } nValueIn += coin.out.nValue; } //collateral transactions are required to pay out a small fee to the miners if(nValueIn - nValueOut < GetCollateralAmount()) { LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- did not include enough fees in transaction: fees: %d, txCollateral=%s", nValueOut - nValueIn, txCollateral.ToString()); return false; } LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- %s", txCollateral.ToString()); { LOCK(cs_main); CValidationState validationState; if(!AcceptToMemoryPool(mempool, validationState, MakeTransactionRef(txCollateral), false, NULL, NULL, false, maxTxFee, true)) { LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- didn't pass AcceptToMemoryPool()\n"); return false; } } return true; }
void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { if(fLiteMode) return; //disable all sandstorm/stormnode related functionality if(!IsSporkActive(SPORK_2_INSTANTX)) return; if(IsInitialBlockDownload()) return; if (strCommand == "txlreq") { //LogPrintf("ProcessMessageInstantX::txlreq\n"); CDataStream vMsg(vRecv); CTransaction tx; vRecv >> tx; CInv inv(MSG_TXLOCK_REQUEST, tx.GetHash()); pfrom->AddInventoryKnown(inv); if(mapTxLockReq.count(tx.GetHash()) || mapTxLockReqRejected.count(tx.GetHash())){ return; } if(!IsIXTXValid(tx)){ return; } BOOST_FOREACH(const CTxOut o, tx.vout){ if(!o.scriptPubKey.IsNormalPaymentScript()){ printf ("ProcessMessageInstantX::txlreq - Invalid Script %s\n", tx.ToString().c_str()); return; } } int nBlockHeight = CreateNewLock(tx); bool fMissingInputs = false; CValidationState state; if (AcceptToMemoryPool(mempool, tx, true, &fMissingInputs)) { vector<CInv> vInv; vInv.push_back(inv); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) pnode->PushMessage("inv", vInv); DoConsensusVote(tx, nBlockHeight); mapTxLockReq.insert(make_pair(tx.GetHash(), tx)); LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request: %s %s : accepted %s\n", pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(), tx.GetHash().ToString().c_str() ); return; } else { mapTxLockReqRejected.insert(make_pair(tx.GetHash(), tx)); // can we get the conflicting transaction as proof? LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request: %s %s : rejected %s\n", pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(), tx.GetHash().ToString().c_str() ); BOOST_FOREACH(const CTxIn& in, tx.vin){ if(!mapLockedInputs.count(in.prevout)){ mapLockedInputs.insert(make_pair(in.prevout, tx.GetHash())); } } // resolve conflicts std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(tx.GetHash()); if (i != mapTxLocks.end()){ //we only care if we have a complete tx lock if((*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){ if(!CheckForConflictingLocks(tx)){ LogPrintf("ProcessMessageInstantX::txlreq - Found Existing Complete IX Lock\n"); CValidationState state; mapTxLockReq.insert(make_pair(tx.GetHash(), tx)); } } } return; } }
void CPrivateSendServer::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv, CConnman& connman) { if(!fMasterNode) return; if(fLiteMode) return; // ignore all Monoeci related functionality if(!masternodeSync.IsBlockchainSynced()) return; if(strCommand == NetMsgType::DSACCEPT) { if(pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { LogPrintf("DSACCEPT -- incompatible version! nVersion: %d\n", pfrom->nVersion); PushStatus(pfrom, STATUS_REJECTED, ERR_VERSION, connman); return; } if(IsSessionReady()) { // too many users in this session already, reject new ones LogPrintf("DSACCEPT -- queue is already full!\n"); PushStatus(pfrom, STATUS_ACCEPTED, ERR_QUEUE_FULL, connman); return; } int nDenom; CTransaction txCollateral; vRecv >> nDenom >> txCollateral; LogPrint("privatesend", "DSACCEPT -- nDenom %d (%s) txCollateral %s", nDenom, CPrivateSend::GetDenominationsToString(nDenom), txCollateral.ToString()); masternode_info_t mnInfo; if(!mnodeman.GetMasternodeInfo(activeMasternode.outpoint, mnInfo)) { PushStatus(pfrom, STATUS_REJECTED, ERR_MN_LIST, connman); return; } if(vecSessionCollaterals.size() == 0 && mnInfo.nLastDsq != 0 && mnInfo.nLastDsq + mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION)/5 > mnodeman.nDsqCount) { LogPrintf("DSACCEPT -- last dsq too recent, must wait: addr=%s\n", pfrom->addr.ToString()); PushStatus(pfrom, STATUS_REJECTED, ERR_RECENT, connman); return; } PoolMessage nMessageID = MSG_NOERR; bool fResult = nSessionID == 0 ? CreateNewSession(nDenom, txCollateral, nMessageID, connman) : AddUserToExistingSession(nDenom, txCollateral, nMessageID); if(fResult) { LogPrintf("DSACCEPT -- is compatible, please submit!\n"); PushStatus(pfrom, STATUS_ACCEPTED, nMessageID, connman); return; } else { LogPrintf("DSACCEPT -- not compatible with existing transactions!\n"); PushStatus(pfrom, STATUS_REJECTED, nMessageID, connman); return; } } else if(strCommand == NetMsgType::DSQUEUE) {
void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { if(fLiteMode) return; //disable all sandstorm/stormnode related functionality if(!IsSporkActive(SPORK_2_INSTANTX)) return; if(!stormnodeSync.IsBlockchainSynced()) return; if (strCommand == "ix") { //LogPrintf("ProcessMessageInstantX::ix\n"); CDataStream vMsg(vRecv); CTransaction tx; vRecv >> tx; CInv inv(MSG_TXLOCK_REQUEST, tx.GetHash()); pfrom->AddInventoryKnown(inv); if(mapTxLockReq.count(tx.GetHash()) || mapTxLockReqRejected.count(tx.GetHash())){ return; } if(!IsIXTXValid(tx)){ return; } BOOST_FOREACH(const CTxOut o, tx.vout){ // IX supports normal scripts and unspendable scripts (used in SS collateral and Budget collateral). // TODO: Look into other script types that are normal and can be included if(!o.scriptPubKey.IsNormalPaymentScript() && !o.scriptPubKey.IsUnspendable()){ LogPrintf("ProcessMessageInstantX::ix - Invalid Script %s\n", tx.ToString().c_str()); return; } } int nBlockHeight = CreateNewLock(tx); bool fMissingInputs = false; //CValidationState state; bool fAccepted = false; { LOCK(cs_main); //TODO (Amir): Pass state to AcceptToMemoryPool fAccepted = AcceptToMemoryPool(mempool, tx, true, &fMissingInputs); } if (fAccepted) { RelayInv(inv); DoConsensusVote(tx, nBlockHeight); mapTxLockReq.insert(make_pair(tx.GetHash(), tx)); LogPrintf("ProcessMessageInstantX::ix - Transaction Lock Request: %s %s : accepted %s\n", pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(), tx.GetHash().ToString().c_str() ); return; } else { mapTxLockReqRejected.insert(make_pair(tx.GetHash(), tx)); // can we get the conflicting transaction as proof? LogPrintf("ProcessMessageInstantX::ix - Transaction Lock Request: %s %s : rejected %s\n", pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str(), tx.GetHash().ToString().c_str() ); BOOST_FOREACH(const CTxIn& in, tx.vin){ if(!mapLockedInputs.count(in.prevout)){ mapLockedInputs.insert(make_pair(in.prevout, tx.GetHash())); } } // resolve conflicts std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(tx.GetHash()); if (i != mapTxLocks.end()){ //we only care if we have a complete tx lock if((*i).second.CountSignatures() >= INSTANTX_SIGNATURES_REQUIRED){ if(!CheckForConflictingLocks(tx)){ LogPrintf("ProcessMessageInstantX::ix - Found Existing Complete IX Lock\n"); //reprocess the last 15 blocks ReprocessBlocks(15); mapTxLockReq.insert(make_pair(tx.GetHash(), tx)); } } } return; } }
bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) { if(!masternodeSync.IsSynced()) { //there is no budget data to use to check anything, let's just accept the longest chain if(fDebug) LogPrintf("IsBlockPayeeValid -- WARNING: Client not synced, skipping block payee checks\n"); return true; } // we are still using budgets, but we have no data about them anymore, // we can only check masternode payments const Consensus::Params& consensusParams = Params().GetConsensus(); if(nBlockHeight < consensusParams.nSuperblockStartBlock) { if(mnpayments.IsTransactionValid(txNew, nBlockHeight)) { LogPrint("mnpayments", "IsBlockPayeeValid -- Valid masternode payment at height %d: %s", nBlockHeight, txNew.ToString()); return true; } int nOffset = nBlockHeight % consensusParams.nBudgetPaymentsCycleBlocks; if(nBlockHeight >= consensusParams.nBudgetPaymentsStartBlock && nOffset < consensusParams.nBudgetPaymentsWindowBlocks) { if(!sporkManager.IsSporkActive(SPORK_13_OLD_SUPERBLOCK_FLAG)) { // no budget blocks should be accepted here, if SPORK_13_OLD_SUPERBLOCK_FLAG is disabled LogPrint("gobject", "IsBlockPayeeValid -- ERROR: Client synced but budget spork is disabled and masternode payment is invalid\n"); return false; } // NOTE: this should never happen in real, SPORK_13_OLD_SUPERBLOCK_FLAG MUST be disabled when 12.1 starts to go live LogPrint("gobject", "IsBlockPayeeValid -- WARNING: Probably valid budget block, have no data, accepting\n"); // TODO: reprocess blocks to make sure they are legit? return true; } if(sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { LogPrintf("IsBlockPayeeValid -- ERROR: Invalid masternode payment detected at height %d: %s", nBlockHeight, txNew.ToString()); return false; } LogPrintf("IsBlockPayeeValid -- WARNING: Masternode payment enforcement is disabled, accepting any payee\n"); return true; } // superblocks started // SEE IF THIS IS A VALID SUPERBLOCK if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)) { if(CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) { if(CSuperblockManager::IsValid(txNew, nBlockHeight, blockReward)) { LogPrint("gobject", "IsBlockPayeeValid -- Valid superblock at height %d: %s", nBlockHeight, txNew.ToString()); return true; } LogPrintf("IsBlockPayeeValid -- ERROR: Invalid superblock detected at height %d: %s", nBlockHeight, txNew.ToString()); // should NOT allow such superblocks, when superblocks are enabled return false; } // continue validation, should pay MN LogPrint("gobject", "IsBlockPayeeValid -- No triggered superblock detected at height %d\n", nBlockHeight); } else { // should NOT allow superblocks at all, when superblocks are disabled LogPrint("gobject", "IsBlockPayeeValid -- Superblocks are disabled, no superblocks allowed\n"); } // IF THIS ISN'T A SUPERBLOCK OR SUPERBLOCK IS INVALID, IT SHOULD PAY A MASTERNODE DIRECTLY if(mnpayments.IsTransactionValid(txNew, nBlockHeight)) { LogPrint("mnpayments", "IsBlockPayeeValid -- Valid masternode payment at height %d: %s", nBlockHeight, txNew.ToString()); return true; } if(sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { LogPrintf("IsBlockPayeeValid -- ERROR: Invalid masternode payment detected at height %d: %s", nBlockHeight, txNew.ToString()); return false; } LogPrintf("IsBlockPayeeValid -- WARNING: Masternode payment enforcement is disabled, accepting any payee\n"); return true; }
bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) { if(!masternodeSync.IsSynced()) { //there is no budget data to use to check anything, let's just accept the longest chain if(fDebug) LogPrintf("IsBlockPayeeValid -- WARNING: Client not synced, skipping block payee checks\n"); return true; } // we are still using budgets, but we have no data about them anymore, // we can only check masternode payments const Consensus::Params& consensusParams = Params().GetConsensus(); if(nBlockHeight < consensusParams.nSuperblockStartBlock) { // NOTE: old budget system is disabled since 12.1 and we should never enter this branch // anymore when sync is finished (on mainnet). We have no old budget data but these blocks // have tons of confirmations and can be safely accepted without payee verification LogPrint("gobject", "IsBlockPayeeValid -- WARNING: Client synced but old budget system is disabled, accepting any payee\n"); return true; } // superblocks started // SEE IF THIS IS A VALID SUPERBLOCK if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)) { if(CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) { if(CSuperblockManager::IsValid(txNew, nBlockHeight, blockReward)) { LogPrint("gobject", "IsBlockPayeeValid -- Valid superblock at height %d: %s", nBlockHeight, txNew.ToString()); return true; } LogPrintf("IsBlockPayeeValid -- ERROR: Invalid superblock detected at height %d: %s", nBlockHeight, txNew.ToString()); // should NOT allow such superblocks, when superblocks are enabled return false; } // continue validation, should pay MN LogPrint("gobject", "IsBlockPayeeValid -- No triggered superblock detected at height %d\n", nBlockHeight); } else { // should NOT allow superblocks at all, when superblocks are disabled LogPrint("gobject", "IsBlockPayeeValid -- Superblocks are disabled, no superblocks allowed\n"); } // IF THIS ISN'T A SUPERBLOCK OR SUPERBLOCK IS INVALID, IT SHOULD PAY A MASTERNODE DIRECTLY if(mnpayments.IsTransactionValid(txNew, nBlockHeight)) { LogPrint("mnpayments", "IsBlockPayeeValid -- Valid masternode payment at height %d: %s", nBlockHeight, txNew.ToString()); return true; } if(sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { LogPrintf("IsBlockPayeeValid -- ERROR: Invalid masternode payment detected at height %d: %s", nBlockHeight, txNew.ToString()); return false; } LogPrintf("IsBlockPayeeValid -- WARNING: Masternode payment enforcement is disabled, accepting any payee\n"); return true; }
tuple<bool, uint64_t, string> CVmRunEvn::run(shared_ptr<CBaseTransaction>& Tx, CAccountViewCache& view, CScriptDBViewCache& VmDB, int nHeight, uint64_t nBurnFactor, uint64_t &uRunStep) { if(nBurnFactor == 0) { // assert(0); return std::make_tuple (false, 0, string("VmScript nBurnFactor == 0 \n")); } m_ScriptDBTip = &VmDB; CTransaction* tx = static_cast<CTransaction*>(Tx.get()); if(tx->llFees <= CBaseTransaction::nMinTxFee) { return std::make_tuple (false, 0, string("vm run evn fee too litter\n")); } uint64_t maxstep = ((tx->llFees-CBaseTransaction::nMinTxFee)/ nBurnFactor) * 100; if(maxstep > MAX_BLOCK_RUN_STEP){ maxstep = MAX_BLOCK_RUN_STEP; } LogPrint("vm", "tx hash:%s fees=%lld fuelrate=%lld maxstep:%d\n", Tx->GetHash().GetHex(), tx->llFees, nBurnFactor, maxstep); if (!intial(Tx, view, nHeight)) { return std::make_tuple (false, 0, string("VmScript inital Failed\n")); } int64_t step = pMcu.get()->run(maxstep,this); if (0 == step) { return std::make_tuple(false, 0, string("VmScript run Failed\n")); } else if (-1 == step) { return std::make_tuple(false, 0, string("execure tx contranct run step exceed the max step limit\n")); }else{ uRunStep = step; } LogPrint("vm", "tx:%s,step:%ld\n", tx->ToString(view), uRunStep); if (!CheckOperate(m_output)) { return std::make_tuple (false, 0, string("VmScript CheckOperate Failed \n")); } if (!OpeatorAccount(m_output, view, nHeight)) { return std::make_tuple (false, 0, string("VmScript OpeatorAccount Failed\n")); } LogPrint("vm", "isCheckAccount:%d\n", isCheckAccount); if(isCheckAccount) { LogPrint("vm","isCheckAccount is true\n"); if(!CheckAppAcctOperate(tx)) return std::make_tuple (false, 0, string("VmScript CheckAppAcct Failed\n")); } if(!OpeatorAppAccount(MapAppOperate, *m_ScriptDBTip)) { return std::make_tuple (false, 0, string("OpeatorApp Account Failed\n")); } if(SysCfg().GetOutPutLog() && m_output.size() > 0) { CScriptDBOperLog operlog; uint256 txhash = GetCurTxHash(); if(!m_ScriptDBTip->WriteTxOutPut(txhash, m_output, operlog)) return std::make_tuple (false, 0, string("write tx out put Failed \n")); m_dblog->push_back(operlog); } uint64_t spend = uRunStep * nBurnFactor; if((spend < uRunStep) || (spend < nBurnFactor)){ return std::make_tuple (false, 0, string("mul error\n")); } return std::make_tuple (true, spend, string("VmScript Sucess\n")); }
void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { if(fLiteMode) return; //disable all darksend/masternode related functionality if(!IsSporkActive(SPORK_2_INSTANTX)) return; if(!masternodeSync.IsBlockchainSynced()) return; if (strCommand == NetMsgType::IX) { //LogPrintf("ProcessMessageInstantX::ix\n"); CDataStream vMsg(vRecv); CTransaction tx; vRecv >> tx; // FIXME: this part of simulating inv is not good actually, leaving it only for 12.1 backwards compatibility // and since we are using invs for relaying even initial ix request, this can (and should) be safely removed in 12.2 CInv inv(MSG_TXLOCK_REQUEST, tx.GetHash()); pfrom->AddInventoryKnown(inv); GetMainSignals().Inventory(inv.hash); // have we seen it already? if(mapTxLockReq.count(inv.hash) || mapTxLockReqRejected.count(inv.hash)) return; // is it a valid one? if(!IsIXTXValid(tx)) return; BOOST_FOREACH(const CTxOut o, tx.vout){ // IX supports normal scripts and unspendable scripts (used in DS collateral and Budget collateral). // TODO: Look into other script types that are normal and can be included if(!o.scriptPubKey.IsNormalPaymentScript() && !o.scriptPubKey.IsUnspendable()){ LogPrintf("ProcessMessageInstantX::ix - Invalid Script %s", tx.ToString()); return; } } int nBlockHeight = CreateNewLock(tx); bool fMissingInputs = false; CValidationState state; bool fAccepted = false; { LOCK(cs_main); fAccepted = AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs); } if (fAccepted) { RelayInv(inv); DoConsensusVote(tx, nBlockHeight); mapTxLockReq.insert(make_pair(tx.GetHash(), tx)); LogPrintf("ProcessMessageInstantX::ix - Transaction Lock Request: %s %s : accepted %s\n", pfrom->addr.ToString(), pfrom->cleanSubVer, tx.GetHash().ToString() ); // Masternodes will sometimes propagate votes before the transaction is known to the client. // If this just happened - update transaction status, try forcing external script notification, // lock inputs and resolve conflicting locks if(IsLockedIXTransaction(tx.GetHash())) { UpdateLockedTransaction(tx, true); LockTransactionInputs(tx); ResolveConflicts(tx); } return; } else { mapTxLockReqRejected.insert(make_pair(tx.GetHash(), tx)); // can we get the conflicting transaction as proof? LogPrintf("ProcessMessageInstantX::ix - Transaction Lock Request: %s %s : rejected %s\n", pfrom->addr.ToString(), pfrom->cleanSubVer, tx.GetHash().ToString() ); LockTransactionInputs(tx); ResolveConflicts(tx); return; } }