diff --git a/src/main.cpp b/src/main.cpp index f9894a5d53..d5e545db59 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,6 +26,7 @@ #include #include #include +#include using namespace std; using namespace boost; @@ -4002,13 +4003,27 @@ void static ProcessGetData(CNode* pfrom) } } if (!pushed && inv.type == MSG_TX) { - CTransaction tx; - if (mempool.lookup(inv.hash, tx)) { + + if(mapDarksendBroadcastTxes.count(inv.hash)){ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss.reserve(1000); - ss << tx; - pfrom->PushMessage("tx", ss); + ss << + mapDarksendBroadcastTxes[inv.hash].tx << + mapDarksendBroadcastTxes[inv.hash].vin << + mapDarksendBroadcastTxes[inv.hash].vchSig << + mapDarksendBroadcastTxes[inv.hash].sigTime; + + pfrom->PushMessage("dstx", ss); pushed = true; + } else { + CTransaction tx; + if (mempool.lookup(inv.hash, tx)) { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss.reserve(1000); + ss << tx; + pfrom->PushMessage("tx", ss); + pushed = true; + } } } if (!pushed) { @@ -4381,12 +4396,58 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } - else if (strCommand == "tx") + else if (strCommand == "tx"|| strCommand == "dstx") { vector vWorkQueue; vector vEraseQueue; CTransaction tx; - vRecv >> tx; + + //masternode signed transaction + bool allowFree = false; + CTxIn vin; + vector vchSig; + int64_t sigTime; + + if(strCommand == "tx") { + vRecv >> tx; + } else if (strCommand == "dstx") { + //these allow masternodes to publish a limited amount of free transactions + vRecv >> tx >> vin >> vchSig >> sigTime; + + BOOST_FOREACH(CMasterNode& mn, vecMasternodes) { + if(mn.vin == vin) { + if(!mn.allowFreeTx){ + //multiple peers can send us a valid masternode transaction + if(fDebug) LogPrintf("dstx: Masternode sending too many transactions %s\n", tx.GetHash().ToString().c_str()); + return true; + } + + std::string strMessage = tx.GetHash().ToString() + boost::lexical_cast(sigTime); + + std::string errorMessage = ""; + if(!darkSendSigner.VerifyMessage(mn.pubkey2, vchSig, strMessage, errorMessage)){ + LogPrintf("dstx: Got bad masternode address signature %s \n", vin.ToString().c_str()); + //pfrom->Misbehaving(20); + return false; + } + + LogPrintf("dstx: Got Masternode transaction %s\n", tx.GetHash().ToString().c_str()); + + allowFree = true; + mn.allowFreeTx = false; + + if(!mapDarksendBroadcastTxes.count(tx.GetHash())){ + CDarksendBroadcastTx dstx; + dstx.tx = tx; + dstx.vin = vin; + dstx.vchSig = vchSig; + dstx.sigTime = sigTime; + + mapDarksendBroadcastTxes.insert(make_pair(tx.GetHash(), dstx)); + } + } + } + } CInv inv(MSG_TX, tx.GetHash()); pfrom->AddInventoryKnown(inv); @@ -4395,7 +4456,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) bool fMissingInputs = false; CValidationState state; - if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs)) + if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs, allowFree)) { mempool.check(pcoinsTip); RelayTransaction(tx, inv.hash);