Proposal Security Overhaul
Submissions to the network now require a fee to be paid to the network (mining fee) using a special transaction with a OP_RETURN && ProposalHash in one of the outputs. This allows the network to filter spam quickly, while also allowing anyone to submit a proposal to the network. To implement these changes we've introduced a few new commands: mnbudget prepare PROPOSAL-NAME URL PAYMENT_COUNT BLOCK_START DASH_ADDRESS DASH_AMOUNT YES|NO|ABSTAIN [USE_IX(TRUE|FALSE)] - To create the special transaction mnbudget submit PROPOSAL-NAME URL PAYMENT_COUNT BLOCK_START DASH_ADDRESS DASH_AMOUNT YES|NO|ABSTAIN FEE_TX - After the transaction is accepted by the network and has 3 confirmations, you can submit the transaction to the network here mnbudget show - Get the proposal hash from here mnbudget vote PROPOSAL-HASH YES|NO|ABSTAIN - You can now simply vote by hash using this command
This commit is contained in:
parent
0e89bbae92
commit
c701839a43
@ -3,7 +3,7 @@ AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 0)
|
||||
define(_CLIENT_VERSION_MINOR, 12)
|
||||
define(_CLIENT_VERSION_REVISION, 0)
|
||||
define(_CLIENT_VERSION_BUILD, 11)
|
||||
define(_CLIENT_VERSION_BUILD, 12)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2015)
|
||||
AC_INIT([Dash Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@dashpay.io],[dash])
|
||||
|
@ -17,7 +17,7 @@
|
||||
#define CLIENT_VERSION_MAJOR 0
|
||||
#define CLIENT_VERSION_MINOR 12
|
||||
#define CLIENT_VERSION_REVISION 0
|
||||
#define CLIENT_VERSION_BUILD 11
|
||||
#define CLIENT_VERSION_BUILD 12
|
||||
|
||||
//! Set to true for release, false for prerelease or test build
|
||||
#define CLIENT_VERSION_IS_RELEASE true
|
||||
|
@ -2374,19 +2374,21 @@ void ThreadCheckDarkSendPool()
|
||||
if(pnode->HasFulfilledRequest("mnsync")) continue;
|
||||
pnode->FulfilledRequest("mnsync");
|
||||
|
||||
LogPrintf("Successfully synced, asking for Masternode list and payment list\n");
|
||||
|
||||
//request full mn list only if Masternodes.dat was updated quite a long time ago
|
||||
|
||||
if(RequestedMasternodeAssets == 0 || RequestedMasternodeAssets == 1){
|
||||
LogPrintf("Successfully synced, asking for Masternode list\n");
|
||||
mnodeman.DsegUpdate(pnode);
|
||||
pnode->PushMessage("getsporks"); //get current network sporks
|
||||
}
|
||||
|
||||
if(RequestedMasternodeAssets == 2 || RequestedMasternodeAssets == 3)
|
||||
if(RequestedMasternodeAssets == 2 || RequestedMasternodeAssets == 3){
|
||||
LogPrintf("Successfully synced, asking for Masternode payee list\n");
|
||||
pnode->PushMessage("mnget"); //sync payees
|
||||
}
|
||||
|
||||
if(RequestedMasternodeAssets == 4 || RequestedMasternodeAssets == 5){
|
||||
LogPrintf("Successfully synced, asking for Masternode Budget votes / Finalized budgets\n");
|
||||
uint256 n = 0;
|
||||
pnode->PushMessage("mnvs", n); //sync masternode votes
|
||||
}
|
||||
|
@ -38,9 +38,9 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
if(!IsSporkActive(SPORK_2_INSTANTX)) return;
|
||||
if(IsInitialBlockDownload()) return;
|
||||
|
||||
if (strCommand == "txlreq")
|
||||
if (strCommand == "ix")
|
||||
{
|
||||
//LogPrintf("ProcessMessageInstantX::txlreq\n");
|
||||
//LogPrintf("ProcessMessageInstantX::ix\n");
|
||||
CDataStream vMsg(vRecv);
|
||||
CTransaction tx;
|
||||
vRecv >> tx;
|
||||
@ -58,7 +58,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
|
||||
BOOST_FOREACH(const CTxOut o, tx.vout){
|
||||
if(!o.scriptPubKey.IsNormalPaymentScript()){
|
||||
LogPrintf("ProcessMessageInstantX::txlreq - Invalid Script %s\n", tx.ToString().c_str());
|
||||
LogPrintf("ProcessMessageInstantX::ix - Invalid Script %s\n", tx.ToString().c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -81,7 +81,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
|
||||
mapTxLockReq.insert(make_pair(tx.GetHash(), tx));
|
||||
|
||||
LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request: %s %s : accepted %s\n",
|
||||
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()
|
||||
);
|
||||
@ -93,7 +93,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
|
||||
// can we get the conflicting transaction as proof?
|
||||
|
||||
LogPrintf("ProcessMessageInstantX::txlreq - Transaction Lock Request: %s %s : rejected %s\n",
|
||||
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()
|
||||
);
|
||||
@ -110,7 +110,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
//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");
|
||||
LogPrintf("ProcessMessageInstantX::ix - Found Existing Complete IX Lock\n");
|
||||
|
||||
CValidationState state;
|
||||
DisconnectBlockAndInputs(state, tx);
|
||||
@ -150,7 +150,7 @@ void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream&
|
||||
|
||||
if(mapUnknownVotes[ctx.vinMasternode.prevout.hash] > GetTime() &&
|
||||
mapUnknownVotes[ctx.vinMasternode.prevout.hash] - GetAverageVoteTime() > 60*10){
|
||||
LogPrintf("ProcessMessageInstantX::txlreq - masternode is spamming transaction votes: %s %s\n",
|
||||
LogPrintf("ProcessMessageInstantX::ix - masternode is spamming transaction votes: %s %s\n",
|
||||
ctx.vinMasternode.ToString().c_str(),
|
||||
ctx.txHash.ToString().c_str()
|
||||
);
|
||||
|
@ -27,7 +27,7 @@ class CConsensusVote;
|
||||
class CTransaction;
|
||||
class CTransactionLock;
|
||||
|
||||
static const int MIN_INSTANTX_PROTO_VERSION = 70085;
|
||||
static const int MIN_INSTANTX_PROTO_VERSION = 70086;
|
||||
|
||||
extern map<uint256, CTransaction> mapTxLockReq;
|
||||
extern map<uint256, CTransaction> mapTxLockReqRejected;
|
||||
|
14
src/main.cpp
14
src/main.cpp
@ -3957,19 +3957,11 @@ bool static AlreadyHave(const CInv& inv)
|
||||
case MSG_BUDGET_VOTE:
|
||||
return mapSeenMasternodeBudgetVotes.count(inv.hash);
|
||||
case MSG_BUDGET_PROPOSAL:
|
||||
if(!mapSeenMasternodeBudgetProposals.count(inv.hash)){
|
||||
return false;
|
||||
} else {
|
||||
return !mapSeenMasternodeBudgetProposals[inv.hash].fInvalid;
|
||||
}
|
||||
return mapSeenMasternodeBudgetProposals.count(inv.hash);
|
||||
case MSG_BUDGET_FINALIZED_VOTE:
|
||||
return mapSeenFinalizedBudgetVotes.count(inv.hash);
|
||||
case MSG_BUDGET_FINALIZED:
|
||||
if(!mapSeenFinalizedBudgets.count(inv.hash)){
|
||||
return false;
|
||||
} else {
|
||||
return !mapSeenFinalizedBudgets[inv.hash].fInvalid;
|
||||
}
|
||||
return mapSeenFinalizedBudgets.count(inv.hash);
|
||||
case MSG_MASTERNODE_ANNOUNCE:
|
||||
return mapSeenMasternodeBroadcast.count(inv.hash);
|
||||
case MSG_MASTERNODE_PING:
|
||||
@ -4111,7 +4103,7 @@ void static ProcessGetData(CNode* pfrom)
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss.reserve(1000);
|
||||
ss << mapTxLockReq[inv.hash];
|
||||
pfrom->PushMessage("txlreq", ss);
|
||||
pfrom->PushMessage("ix", ss);
|
||||
pushed = true;
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,73 @@ int GetBudgetPaymentCycleBlocks(){
|
||||
return 50;
|
||||
}
|
||||
|
||||
bool IsBudgetCollateralValid(uint256 nTxCollateralHash, std::string& strError)
|
||||
{
|
||||
return true;
|
||||
|
||||
CTransaction txCollateral;
|
||||
uint256 hash;
|
||||
if(!GetTransaction(nTxCollateralHash, txCollateral, hash, true)){
|
||||
LogPrintf ("CBudgetProposalBroadcast::FeeTXValid - Can't find collateral tx %s\n", txCollateral.ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(txCollateral.vout.size() < 1) return false;
|
||||
if(txCollateral.nLockTime != 0) return false;
|
||||
|
||||
int64_t nValueIn = 0;
|
||||
int64_t nValueOut = 0;
|
||||
bool missingTx = false;
|
||||
|
||||
BOOST_FOREACH(const CTxOut o, txCollateral.vout){
|
||||
nValueOut += o.nValue;
|
||||
|
||||
if(!o.scriptPubKey.IsNormalPaymentScript()){
|
||||
LogPrintf ("CBudgetProposalBroadcast::FeeTXValid - Invalid Script %s\n", txCollateral.ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool foundOpReturn = false;
|
||||
BOOST_FOREACH(const CTxIn i, txCollateral.vin){
|
||||
CTransaction tx2;
|
||||
uint256 hash;
|
||||
if(GetTransaction(i.prevout.hash, tx2, hash, true)){
|
||||
if(tx2.vout.size() > i.prevout.n) {
|
||||
nValueIn += tx2.vout[i.prevout.n].nValue;
|
||||
}
|
||||
} else{
|
||||
missingTx = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!foundOpReturn){
|
||||
|
||||
}
|
||||
|
||||
if(missingTx){
|
||||
if(fDebug) LogPrintf ("CBudgetProposalBroadcast::FeeTXValid - Unknown inputs in collateral transaction - %s\n", txCollateral.ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
//collateral transactions are required to pay out BUDGET_FEE_TX as a fee to the miners
|
||||
if(nValueIn - nValueOut < BUDGET_FEE_TX) {
|
||||
if(fDebug) LogPrintf ("CBudgetProposalBroadcast::FeeTXValid - did not include enough fees in transaction %d\n%s\n", nValueOut-nValueIn, txCollateral.ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fDebug) LogPrintf("CBudgetProposalBroadcast::FeeTXValid %s\n", txCollateral.ToString().c_str());
|
||||
|
||||
CValidationState state;
|
||||
if(!AcceptableInputs(mempool, state, txCollateral, true, NULL)){
|
||||
if(fDebug) LogPrintf ("CBudgetProposalBroadcast::FeeTXValid - didn't pass IsAcceptable\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBudgetManager::CheckOrphanVotes()
|
||||
{
|
||||
std::map<uint256, CBudgetVote>::iterator it1 = mapOrphanMasternodeBudgetVotes.begin();
|
||||
@ -54,154 +121,6 @@ void CBudgetManager::CheckOrphanVotes()
|
||||
}
|
||||
}
|
||||
|
||||
void CBudgetManager::ResignInvalidProposals()
|
||||
{
|
||||
if(!fMasterNode){
|
||||
CheckSignatureValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
if(pindexPrev == NULL) return;
|
||||
|
||||
//pick a few masternodes responsible for this each cycle
|
||||
int n = mnodeman.GetMasternodeRank(activeMasternode.vin, pindexPrev->nHeight, MIN_BUDGET_PEER_PROTO_VERSION);
|
||||
|
||||
if(n == -1)
|
||||
{
|
||||
CheckSignatureValidity();
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals - Unknown Masternode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(n > 3)
|
||||
{
|
||||
CheckSignatureValidity();
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals - Masternode not in the top %s\n", MIN_BUDGET_PEER_PROTO_VERSION);
|
||||
return;
|
||||
}
|
||||
|
||||
CMasternode* pmn = mnodeman.Find(activeMasternode.vin);
|
||||
if(pmn == NULL) {
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals - unknown masternode - vin:%s \n", pmn->vin.ToString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<uint256, CBudgetProposal>::iterator it1 = mapProposals.begin();
|
||||
while(it1 != mapProposals.end())
|
||||
{
|
||||
if(pmn->nVotedTimes+VOTE_PROP_INC > 100) return; //can't submit to the network anyway
|
||||
|
||||
CBudgetProposal* pbudgetProposal = &((*it1).second);
|
||||
|
||||
CBudgetProposalBroadcast budgetProposalBroadcast(*pbudgetProposal);
|
||||
if(!budgetProposalBroadcast.SignatureValid()){
|
||||
budgetProposalBroadcast.vin = activeMasternode.vin;
|
||||
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals -- proposal - resigning proposal\n");
|
||||
|
||||
CPubKey pubKeyMasternode;
|
||||
CKey keyMasternode;
|
||||
std::string errorMessage;
|
||||
|
||||
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode)){
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals - Error upon calling SetKey");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!budgetProposalBroadcast.Sign(keyMasternode, pubKeyMasternode)){
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals - Failure to sign");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string strError = "";
|
||||
if(budgetProposalBroadcast.IsValid(strError)){
|
||||
//delete if it exists and insert the new object
|
||||
if(mapSeenMasternodeBudgetProposals.count(budgetProposalBroadcast.GetHash())) mapSeenMasternodeBudgetProposals.erase(budgetProposalBroadcast.GetHash());
|
||||
mapSeenMasternodeBudgetProposals.insert(make_pair(budgetProposalBroadcast.GetHash(), budgetProposalBroadcast));
|
||||
|
||||
budgetProposalBroadcast.Relay();
|
||||
} else {
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals -- proposal - still invalid with new signature\n");
|
||||
}
|
||||
}
|
||||
++it1;
|
||||
}
|
||||
|
||||
std::map<uint256, CFinalizedBudget>::iterator it2 = mapFinalizedBudgets.begin();
|
||||
while(it2 != mapFinalizedBudgets.end()){
|
||||
if(pmn->nVotedTimes+VOTE_PROP_INC > 100) return; //can't submit to the network anyway
|
||||
|
||||
CFinalizedBudget* pfinalizedBudget = &((*it2).second);
|
||||
if(!pfinalizedBudget->IsValid()) continue;
|
||||
|
||||
CFinalizedBudgetBroadcast finalizedBudgetBroadcast(*pfinalizedBudget);
|
||||
if(!finalizedBudgetBroadcast.SignatureValid()){
|
||||
finalizedBudgetBroadcast.vin = activeMasternode.vin;
|
||||
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals -- finalized budget - resigning finalized budget\n");
|
||||
|
||||
CPubKey pubKeyMasternode;
|
||||
CKey keyMasternode;
|
||||
std::string errorMessage;
|
||||
|
||||
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode)){
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals - Error upon calling SetKey");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!finalizedBudgetBroadcast.Sign(keyMasternode, pubKeyMasternode)){
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals - Failure to sign");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!finalizedBudgetBroadcast.IsValid()){
|
||||
|
||||
//delete if it exists and insert the new object
|
||||
if(mapFinalizedBudgets.count(finalizedBudgetBroadcast.GetHash())) mapFinalizedBudgets.erase(finalizedBudgetBroadcast.GetHash());
|
||||
mapFinalizedBudgets.insert(make_pair(finalizedBudgetBroadcast.GetHash(), finalizedBudgetBroadcast));
|
||||
|
||||
finalizedBudgetBroadcast.Relay();
|
||||
} else {
|
||||
LogPrintf("CBudgetManager::ResignInvalidProposals -- finalized budget - still invalid with new signature\n");
|
||||
}
|
||||
}
|
||||
++it2;
|
||||
}
|
||||
}
|
||||
|
||||
void CBudgetManager::CheckSignatureValidity()
|
||||
{
|
||||
std::map<uint256, CBudgetProposal>::iterator it1 = mapProposals.begin();
|
||||
while(it1 != mapProposals.end())
|
||||
{
|
||||
CBudgetProposal* pbudgetProposal = &((*it1).second);
|
||||
|
||||
CBudgetProposalBroadcast budgetProposalBroadcast(*pbudgetProposal);
|
||||
if(!budgetProposalBroadcast.SignatureValid()){
|
||||
if(mapSeenMasternodeBudgetProposals.count(budgetProposalBroadcast.GetHash())) {
|
||||
mapSeenMasternodeBudgetProposals[budgetProposalBroadcast.GetHash()].fInvalid = true;
|
||||
}
|
||||
}
|
||||
++it1;
|
||||
}
|
||||
|
||||
std::map<uint256, CFinalizedBudget>::iterator it2 = mapFinalizedBudgets.begin();
|
||||
while(it2 != mapFinalizedBudgets.end())
|
||||
{
|
||||
CFinalizedBudget* pfinalizedBudget = &((*it2).second);
|
||||
|
||||
CFinalizedBudgetBroadcast finalizedBudgetBroadcast(*pfinalizedBudget);
|
||||
if(!finalizedBudgetBroadcast.SignatureValid()){
|
||||
if(mapSeenFinalizedBudgets.count(finalizedBudgetBroadcast.GetHash())) {
|
||||
mapSeenFinalizedBudgets[finalizedBudgetBroadcast.GetHash()].fInvalid = true;
|
||||
}
|
||||
}
|
||||
++it2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBudgetManager::SubmitFinalBudget()
|
||||
{
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
@ -238,11 +157,11 @@ void CBudgetManager::SubmitFinalBudget()
|
||||
LogPrintf("SubmitFinalBudget - Error upon calling SetKey\n");
|
||||
}
|
||||
|
||||
//create fee tx
|
||||
uint256 hash = 0;
|
||||
|
||||
//create the proposal incase we're the first to make it
|
||||
CFinalizedBudgetBroadcast finalizedBudgetBroadcast(activeMasternode.vin, strBudgetName, nBlockStart, vecTxBudgetPayments);
|
||||
if(!finalizedBudgetBroadcast.Sign(keyMasternode, pubKeyMasternode)){
|
||||
LogPrintf("SubmitFinalBudget - Failure to sign.\n");
|
||||
}
|
||||
CFinalizedBudgetBroadcast finalizedBudgetBroadcast(strBudgetName, nBlockStart, vecTxBudgetPayments, hash);
|
||||
|
||||
if(!finalizedBudgetBroadcast.IsValid()){
|
||||
LogPrintf("SubmitFinalBudget - Invalid finalized budget broadcast (are all the hashes correct?)\n");
|
||||
@ -408,13 +327,7 @@ void CBudgetManager::AddFinalizedBudget(CFinalizedBudget& finalizedBudget)
|
||||
LOCK(cs);
|
||||
if(!finalizedBudget.IsValid()) return;
|
||||
|
||||
if(mapFinalizedBudgets.count(finalizedBudget.GetHash()) && mapFinalizedBudgets[finalizedBudget.GetHash()].vin != finalizedBudget.vin) {
|
||||
//this finalized budget must have went invalid, so update the vin to the new one
|
||||
LogPrintf("CBudgetManager::AddFinalizedBudget -- updated vin of invalid finalized budget %s (%s to %s)\n",
|
||||
finalizedBudget.strBudgetName,
|
||||
mapFinalizedBudgets[finalizedBudget.GetHash()].vin.prevout.ToStringShort(),
|
||||
finalizedBudget.vin.prevout.ToStringShort());
|
||||
mapFinalizedBudgets[finalizedBudget.GetHash()].vin = finalizedBudget.vin;
|
||||
if(mapFinalizedBudgets.count(finalizedBudget.GetHash())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -430,13 +343,7 @@ void CBudgetManager::AddProposal(CBudgetProposal& budgetProposal)
|
||||
return;
|
||||
}
|
||||
|
||||
if(mapProposals.count(budgetProposal.GetHash()) && mapProposals[budgetProposal.GetHash()].vin != budgetProposal.vin) {
|
||||
//this budget proposal must have went invalid, so update the vin to the new one
|
||||
LogPrintf("CBudgetManager::AddProposal -- updated vin of invalid budget proposal %s (%s to %s)\n",
|
||||
budgetProposal.strProposalName,
|
||||
mapProposals[budgetProposal.GetHash()].vin.prevout.ToStringShort().c_str(),
|
||||
budgetProposal.vin.prevout.ToStringShort().c_str());
|
||||
mapProposals[budgetProposal.GetHash()].vin = budgetProposal.vin;
|
||||
if(mapProposals.count(budgetProposal.GetHash())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -761,8 +668,6 @@ void CBudgetManager::NewBlock()
|
||||
SubmitFinalBudget();
|
||||
}
|
||||
|
||||
ResignInvalidProposals();
|
||||
|
||||
//this function should be called 1/6 blocks, allowing up to 100 votes per day on all proposals
|
||||
if(chainActive.Height() % 6 != 0) return;
|
||||
|
||||
@ -813,30 +718,20 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
||||
vRecv >> budgetProposalBroadcast;
|
||||
|
||||
if(mapSeenMasternodeBudgetProposals.count(budgetProposalBroadcast.GetHash())){
|
||||
//if this proposal went inactive, we'll update it with the new re-signature
|
||||
if(!mapSeenMasternodeBudgetProposals[budgetProposalBroadcast.GetHash()].fInvalid){
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//set time we first saw this prop
|
||||
budgetProposalBroadcast.nTime = GetAdjustedTime();
|
||||
|
||||
CMasternode* pmn = mnodeman.Find(budgetProposalBroadcast.vin);
|
||||
if(pmn == NULL) {
|
||||
if(fDebug) LogPrintf("mprop - unknown masternode - vin: %s\n", budgetProposalBroadcast.vin.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
if(!budgetProposalBroadcast.SignatureValid()){
|
||||
LogPrintf("mprop - signature invalid\n");
|
||||
Misbehaving(pfrom->GetId(), 20);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string strError = "";
|
||||
if(!IsBudgetCollateralValid(budgetProposalBroadcast.nFeeTXHash, strError)){
|
||||
LogPrintf("Proposal FeeTX is not valid - %s - %s\n", budgetProposalBroadcast.nFeeTXHash.ToString(), strError);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!budgetProposalBroadcast.IsValid(strError)) {
|
||||
LogPrintf("mprop - invalid budget proposal - %s\n", strError.c_str());
|
||||
LogPrintf("mprop - invalid budget proposal - %s\n", strError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -844,20 +739,12 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
||||
if(mapSeenMasternodeBudgetProposals.count(budgetProposalBroadcast.GetHash())) mapSeenMasternodeBudgetProposals.erase(budgetProposalBroadcast.GetHash());
|
||||
mapSeenMasternodeBudgetProposals.insert(make_pair(budgetProposalBroadcast.GetHash(), budgetProposalBroadcast));
|
||||
|
||||
if(IsSyncingMasternodeAssets() || pmn->nVotedTimes < 100){
|
||||
CBudgetProposal budgetProposal(budgetProposalBroadcast);
|
||||
budget.AddProposal(budgetProposal);
|
||||
budgetProposalBroadcast.Relay();
|
||||
CBudgetProposal budgetProposal(budgetProposalBroadcast);
|
||||
budget.AddProposal(budgetProposal);
|
||||
budgetProposalBroadcast.Relay();
|
||||
|
||||
//can only do this six times a day on the network
|
||||
if(!IsSyncingMasternodeAssets()) pmn->nVotedTimes+=VOTE_PROP_INC;
|
||||
|
||||
//We might have active votes for this proposal that are valid now
|
||||
CheckOrphanVotes();
|
||||
} else {
|
||||
LogPrintf("mvote - masternode can't vote again - vin: %s\n", pmn->vin.ToString());
|
||||
return;
|
||||
}
|
||||
//We might have active votes for this proposal that are valid now
|
||||
CheckOrphanVotes();
|
||||
}
|
||||
|
||||
if (strCommand == "mvote") { //Masternode Vote
|
||||
@ -881,7 +768,7 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
||||
}
|
||||
|
||||
mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
||||
if(IsSyncingMasternodeAssets() || pmn->nVotedTimes < 100){
|
||||
if(pmn->nVotedTimes < 100){
|
||||
budget.UpdateProposal(vote, pfrom);
|
||||
vote.Relay();
|
||||
if(!IsSyncingMasternodeAssets()) pmn->nVotedTimes++;
|
||||
@ -896,21 +783,12 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
||||
vRecv >> finalizedBudgetBroadcast;
|
||||
|
||||
if(mapSeenFinalizedBudgets.count(finalizedBudgetBroadcast.GetHash())){
|
||||
//if this budget went inactive, we'll update it with the new re-signature
|
||||
if(!mapSeenFinalizedBudgets[finalizedBudgetBroadcast.GetHash()].fInvalid){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CMasternode* pmn = mnodeman.Find(finalizedBudgetBroadcast.vin);
|
||||
if(pmn == NULL) {
|
||||
if(fDebug) LogPrintf("fbs - unknown masternode - vin: %s\n", finalizedBudgetBroadcast.vin.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
if(!finalizedBudgetBroadcast.SignatureValid()){
|
||||
LogPrintf("fbs - signature invalid\n");
|
||||
Misbehaving(pfrom->GetId(), 20);
|
||||
std::string strError = "";
|
||||
if(!IsBudgetCollateralValid(finalizedBudgetBroadcast.nFeeTXHash, strError)){
|
||||
LogPrintf("Finalized Budget FeeTX is not valid - %s - %s\n", finalizedBudgetBroadcast.nFeeTXHash.ToString(), strError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -923,19 +801,12 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
||||
if(mapSeenFinalizedBudgets.count(finalizedBudgetBroadcast.GetHash())) mapSeenFinalizedBudgets.erase(finalizedBudgetBroadcast.GetHash());
|
||||
mapSeenFinalizedBudgets.insert(make_pair(finalizedBudgetBroadcast.GetHash(), finalizedBudgetBroadcast));
|
||||
|
||||
if(IsSyncingMasternodeAssets() || pmn->nVotedTimes < 100){
|
||||
CFinalizedBudget finalizedBudget(finalizedBudgetBroadcast);
|
||||
budget.AddFinalizedBudget(finalizedBudget);
|
||||
finalizedBudgetBroadcast.Relay();
|
||||
CFinalizedBudget finalizedBudget(finalizedBudgetBroadcast);
|
||||
budget.AddFinalizedBudget(finalizedBudget);
|
||||
finalizedBudgetBroadcast.Relay();
|
||||
|
||||
if(!IsSyncingMasternodeAssets()) pmn->nVotedTimes+=VOTE_PROP_INC;
|
||||
|
||||
//we might have active votes for this budget that are now valid
|
||||
CheckOrphanVotes();
|
||||
} else {
|
||||
LogPrintf("fbs - masternode can't vote again - vin: %s\n", pmn->vin.ToString());
|
||||
return;
|
||||
}
|
||||
//we might have active votes for this budget that are now valid
|
||||
CheckOrphanVotes();
|
||||
}
|
||||
|
||||
if (strCommand == "fbvote") { //Finalized Budget Vote
|
||||
@ -959,7 +830,7 @@ void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
||||
}
|
||||
|
||||
mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
||||
if(IsSyncingMasternodeAssets() || pmn->nVotedTimes < 100){
|
||||
if(pmn->nVotedTimes < 100){
|
||||
budget.UpdateFinalizedBudget(vote, pfrom);
|
||||
vote.Relay();
|
||||
if(!IsSyncingMasternodeAssets()) pmn->nVotedTimes++;
|
||||
@ -1072,7 +943,6 @@ bool CBudgetManager::UpdateFinalizedBudget(CFinalizedBudgetVote& vote, CNode* pf
|
||||
|
||||
CBudgetProposal::CBudgetProposal()
|
||||
{
|
||||
vin = CTxIn();
|
||||
strProposalName = "unknown";
|
||||
nBlockStart = 0;
|
||||
nBlockEnd = 0;
|
||||
@ -1080,9 +950,8 @@ CBudgetProposal::CBudgetProposal()
|
||||
nTime = 0;
|
||||
}
|
||||
|
||||
CBudgetProposal::CBudgetProposal(CTxIn vinIn, std::string strProposalNameIn, std::string strURLIn, int nBlockStartIn, int nBlockEndIn, CScript addressIn, CAmount nAmountIn)
|
||||
CBudgetProposal::CBudgetProposal(std::string strProposalNameIn, std::string strURLIn, int nBlockStartIn, int nBlockEndIn, CScript addressIn, CAmount nAmountIn, uint256 nFeeTXHashIn)
|
||||
{
|
||||
vin = vinIn;
|
||||
strProposalName = strProposalNameIn;
|
||||
strURL = strURLIn;
|
||||
nBlockStart = nBlockStartIn;
|
||||
@ -1090,11 +959,11 @@ CBudgetProposal::CBudgetProposal(CTxIn vinIn, std::string strProposalNameIn, std
|
||||
address = addressIn;
|
||||
nAmount = nAmountIn;
|
||||
nTime = 0;
|
||||
nFeeTXHash = nFeeTXHashIn;
|
||||
}
|
||||
|
||||
CBudgetProposal::CBudgetProposal(const CBudgetProposal& other)
|
||||
{
|
||||
vin = other.vin;
|
||||
strProposalName = other.strProposalName;
|
||||
strURL = other.strURL;
|
||||
nBlockStart = other.nBlockStart;
|
||||
@ -1102,6 +971,8 @@ CBudgetProposal::CBudgetProposal(const CBudgetProposal& other)
|
||||
address = other.address;
|
||||
nAmount = other.nAmount;
|
||||
nTime = other.nTime;
|
||||
nFeeTXHash = other.nFeeTXHash;
|
||||
mapVotes = other.mapVotes;
|
||||
}
|
||||
|
||||
bool CBudgetProposal::IsValid(std::string& strError)
|
||||
@ -1252,31 +1123,28 @@ int CBudgetProposal::GetRemainingPaymentCount()
|
||||
|
||||
CBudgetProposalBroadcast::CBudgetProposalBroadcast()
|
||||
{
|
||||
vin = CTxIn();
|
||||
strProposalName = "unknown";
|
||||
strURL = "";
|
||||
nBlockStart = 0;
|
||||
nBlockEnd = 0;
|
||||
nAmount = 0;
|
||||
nTime = 0;
|
||||
fInvalid = false;
|
||||
nFeeTXHash = 0;
|
||||
}
|
||||
|
||||
CBudgetProposalBroadcast::CBudgetProposalBroadcast(const CBudgetProposal& other)
|
||||
{
|
||||
vin = other.vin;
|
||||
strProposalName = other.strProposalName;
|
||||
strURL = other.strURL;
|
||||
nBlockStart = other.nBlockStart;
|
||||
nBlockEnd = other.nBlockEnd;
|
||||
address = other.address;
|
||||
nAmount = other.nAmount;
|
||||
fInvalid = false;
|
||||
nFeeTXHash = other.nFeeTXHash;
|
||||
}
|
||||
|
||||
CBudgetProposalBroadcast::CBudgetProposalBroadcast(CTxIn vinIn, std::string strProposalNameIn, std::string strURLIn, int nPaymentCount, CScript addressIn, CAmount nAmountIn, int nBlockStartIn)
|
||||
CBudgetProposalBroadcast::CBudgetProposalBroadcast(std::string strProposalNameIn, std::string strURLIn, int nPaymentCount, CScript addressIn, CAmount nAmountIn, int nBlockStartIn, uint256 nFeeTXHashIn)
|
||||
{
|
||||
vin = vinIn;
|
||||
strProposalName = strProposalNameIn;
|
||||
strURL = strURLIn;
|
||||
|
||||
@ -1289,26 +1157,7 @@ CBudgetProposalBroadcast::CBudgetProposalBroadcast(CTxIn vinIn, std::string strP
|
||||
address = addressIn;
|
||||
nAmount = nAmountIn;
|
||||
|
||||
fInvalid = false;
|
||||
}
|
||||
|
||||
bool CBudgetProposalBroadcast::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
|
||||
{
|
||||
// Choose coins to use
|
||||
CPubKey pubKeyCollateralAddress;
|
||||
CKey keyCollateralAddress;
|
||||
|
||||
std::string errorMessage;
|
||||
std::string strMessage = vin.prevout.ToStringShort() + strProposalName + strURL + boost::lexical_cast<std::string>(nBlockStart) +
|
||||
boost::lexical_cast<std::string>(nBlockEnd) + address.ToString() + boost::lexical_cast<std::string>(nAmount);
|
||||
|
||||
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchSig, keyMasternode))
|
||||
return(" Error upon calling SignMessage");
|
||||
|
||||
if(!darkSendSigner.VerifyMessage(pubKeyMasternode, vchSig, strMessage, errorMessage))
|
||||
return(" Error upon calling VerifyMessage");
|
||||
|
||||
return true;
|
||||
nFeeTXHash = nFeeTXHashIn;
|
||||
}
|
||||
|
||||
void CBudgetProposalBroadcast::Relay()
|
||||
@ -1317,29 +1166,6 @@ void CBudgetProposalBroadcast::Relay()
|
||||
RelayInv(inv, MIN_BUDGET_PEER_PROTO_VERSION);
|
||||
}
|
||||
|
||||
bool CBudgetProposalBroadcast::SignatureValid()
|
||||
{
|
||||
std::string errorMessage;
|
||||
|
||||
std::string strMessage = vin.prevout.ToStringShort() + strProposalName + strURL + boost::lexical_cast<std::string>(nBlockStart) +
|
||||
boost::lexical_cast<std::string>(nBlockEnd) + address.ToString() + boost::lexical_cast<std::string>(nAmount);
|
||||
|
||||
CMasternode* pmn = mnodeman.Find(vin);
|
||||
|
||||
if(pmn == NULL)
|
||||
{
|
||||
LogPrintf("CBudgetProposalBroadcast::SignatureValid() - Unknown Masternode - %s\n", vin.ToString().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!darkSendSigner.VerifyMessage(pmn->pubkey2, vchSig, strMessage, errorMessage)) {
|
||||
LogPrintf("CBudgetProposalBroadcast::SignatureValid() - Verify message failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CBudgetVote::CBudgetVote()
|
||||
{
|
||||
vin = CTxIn();
|
||||
@ -1403,21 +1229,21 @@ bool CBudgetVote::SignatureValid()
|
||||
|
||||
CFinalizedBudget::CFinalizedBudget()
|
||||
{
|
||||
vin = CTxIn();
|
||||
strBudgetName = "";
|
||||
nBlockStart = 0;
|
||||
vecProposals.clear();
|
||||
mapVotes.clear();
|
||||
nFeeTXHash = 0;
|
||||
}
|
||||
|
||||
|
||||
CFinalizedBudget::CFinalizedBudget(const CFinalizedBudget& other)
|
||||
{
|
||||
vin = other.vin;
|
||||
strBudgetName = other.strBudgetName;
|
||||
nBlockStart = other.nBlockStart;
|
||||
vecProposals = other.vecProposals;
|
||||
mapVotes = other.mapVotes;
|
||||
nFeeTXHash = other.nFeeTXHash;
|
||||
}
|
||||
|
||||
void CFinalizedBudget::AddOrUpdateVote(CFinalizedBudgetVote& vote)
|
||||
@ -1473,11 +1299,6 @@ void CFinalizedBudget::AutoCheck()
|
||||
}
|
||||
|
||||
}
|
||||
// Feature : Masternodes can delegate finalized budgets to a 3rd party simply by adding this option to the configuration
|
||||
else if (strBudgetMode == vin.prevout.ToStringShort())
|
||||
{
|
||||
SubmitVote();
|
||||
}
|
||||
}
|
||||
// If masternode voted for a proposal, but is now invalid -- remove the vote
|
||||
void CFinalizedBudget::CleanAndRemove()
|
||||
@ -1633,31 +1454,30 @@ void CFinalizedBudget::SubmitVote()
|
||||
|
||||
CFinalizedBudgetBroadcast::CFinalizedBudgetBroadcast()
|
||||
{
|
||||
vin = CTxIn();
|
||||
strBudgetName = "";
|
||||
nBlockStart = 0;
|
||||
vecProposals.clear();
|
||||
mapVotes.clear();
|
||||
vchSig.clear();
|
||||
nFeeTXHash = 0;
|
||||
}
|
||||
|
||||
CFinalizedBudgetBroadcast::CFinalizedBudgetBroadcast(const CFinalizedBudget& other)
|
||||
{
|
||||
vin = other.vin;
|
||||
strBudgetName = other.strBudgetName;
|
||||
nBlockStart = other.nBlockStart;
|
||||
BOOST_FOREACH(CTxBudgetPayment out, other.vecProposals) vecProposals.push_back(out);
|
||||
mapVotes = other.mapVotes;
|
||||
nFeeTXHash = other.nFeeTXHash;
|
||||
}
|
||||
|
||||
CFinalizedBudgetBroadcast::CFinalizedBudgetBroadcast(CTxIn& vinIn, std::string strBudgetNameIn, int nBlockStartIn, std::vector<CTxBudgetPayment> vecProposalsIn)
|
||||
CFinalizedBudgetBroadcast::CFinalizedBudgetBroadcast(std::string strBudgetNameIn, int nBlockStartIn, std::vector<CTxBudgetPayment> vecProposalsIn, uint256 nFeeTXHashIn)
|
||||
{
|
||||
vin = vinIn;
|
||||
printf("%s\n", vin.ToString().c_str());
|
||||
strBudgetName = strBudgetNameIn;
|
||||
nBlockStart = nBlockStartIn;
|
||||
BOOST_FOREACH(CTxBudgetPayment out, vecProposalsIn) vecProposals.push_back(out);
|
||||
mapVotes.clear();
|
||||
nFeeTXHash = nFeeTXHashIn;
|
||||
}
|
||||
|
||||
void CFinalizedBudgetBroadcast::Relay()
|
||||
@ -1666,48 +1486,6 @@ void CFinalizedBudgetBroadcast::Relay()
|
||||
RelayInv(inv, MIN_BUDGET_PEER_PROTO_VERSION);
|
||||
}
|
||||
|
||||
bool CFinalizedBudgetBroadcast::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
|
||||
{
|
||||
// Choose coins to use
|
||||
CPubKey pubKeyCollateralAddress;
|
||||
CKey keyCollateralAddress;
|
||||
|
||||
std::string errorMessage;
|
||||
std::string strMessage = vin.prevout.ToStringShort() + strBudgetName + boost::lexical_cast<std::string>(nBlockStart);
|
||||
BOOST_FOREACH(CTxBudgetPayment& payment, vecProposals) strMessage += payment.nProposalHash.ToString().c_str();
|
||||
|
||||
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchSig, keyMasternode))
|
||||
return(" Error upon calling SignMessage");
|
||||
|
||||
if(!darkSendSigner.VerifyMessage(pubKeyMasternode, vchSig, strMessage, errorMessage))
|
||||
return(" Error upon calling VerifyMessage");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFinalizedBudgetBroadcast::SignatureValid()
|
||||
{
|
||||
std::string errorMessage;
|
||||
|
||||
std::string strMessage = vin.prevout.ToStringShort() + strBudgetName + boost::lexical_cast<std::string>(nBlockStart);
|
||||
BOOST_FOREACH(CTxBudgetPayment& payment, vecProposals) strMessage += payment.nProposalHash.ToString().c_str();
|
||||
|
||||
CMasternode* pmn = mnodeman.Find(vin);
|
||||
|
||||
if(pmn == NULL)
|
||||
{
|
||||
LogPrintf("CFinalizedBudgetBroadcast::SignatureValid() - Unknown Masternode\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!darkSendSigner.VerifyMessage(pmn->pubkey2, vchSig, strMessage, errorMessage)) {
|
||||
LogPrintf("CFinalizedBudgetBroadcast::SignatureValid() - Verify message failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CFinalizedBudgetVote::CFinalizedBudgetVote()
|
||||
{
|
||||
vin = CTxIn();
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "base58.h"
|
||||
#include "masternode.h"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "init.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -29,7 +29,8 @@ class CTxBudgetPayment;
|
||||
#define VOTE_ABSTAIN 0
|
||||
#define VOTE_YES 1
|
||||
#define VOTE_NO 2
|
||||
#define VOTE_PROP_INC 15 //how many "votes" to count for a new proposal
|
||||
|
||||
static const int64_t BUDGET_FEE_TX = (0.5*COIN);
|
||||
|
||||
extern std::map<uint256, CBudgetProposalBroadcast> mapSeenMasternodeBudgetProposals;
|
||||
extern std::map<uint256, CBudgetVote> mapSeenMasternodeBudgetVotes;
|
||||
@ -42,6 +43,9 @@ void DumpBudgets();
|
||||
//Amount of blocks in a months period of time (using 2.6 minutes per)
|
||||
int GetBudgetPaymentCycleBlocks();
|
||||
|
||||
//Check the collateral transaction for the budget proposal/finalized budget
|
||||
bool IsBudgetCollateralValid(uint256 nTxCollateralHash, std::string& strError);
|
||||
|
||||
/** Save Budget Manager (budget.dat)
|
||||
*/
|
||||
class CBudgetDB
|
||||
@ -114,10 +118,6 @@ public:
|
||||
std::string GetRequiredPaymentsString(int64_t nBlockHeight);
|
||||
void FillBlockPayee(CMutableTransaction& txNew, int64_t nFees);
|
||||
|
||||
//Have masternodes resign proposals with masternodes that have went inactive
|
||||
void ResignInvalidProposals();
|
||||
void CheckSignatureValidity();
|
||||
|
||||
void CheckOrphanVotes();
|
||||
void Clear(){
|
||||
LogPrintf("Budget object cleared\n");
|
||||
@ -185,10 +185,10 @@ private:
|
||||
|
||||
public:
|
||||
std::string strBudgetName;
|
||||
CTxIn vin;
|
||||
int nBlockStart;
|
||||
std::vector<CTxBudgetPayment> vecProposals;
|
||||
map<uint256, CFinalizedBudgetVote> mapVotes;
|
||||
uint256 nFeeTXHash;
|
||||
|
||||
CFinalizedBudget();
|
||||
CFinalizedBudget(const CFinalizedBudget& other);
|
||||
@ -204,7 +204,6 @@ public:
|
||||
std::string GetProposals();
|
||||
int GetBlockStart() {return nBlockStart;}
|
||||
int GetBlockEnd() {return nBlockStart + (int)(vecProposals.size()-1);}
|
||||
std::string GetSubmittedBy() {return vin.prevout.ToStringShort();}
|
||||
int GetVoteCount() {return (int)mapVotes.size();}
|
||||
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
|
||||
bool GetProposalByBlock(int64_t nBlockHeight, CTxBudgetPayment& payment)
|
||||
@ -236,13 +235,6 @@ public:
|
||||
string GetStatus();
|
||||
|
||||
uint256 GetHash(){
|
||||
/*
|
||||
vin is not included on purpose
|
||||
- Any masternode can make a proposal and the hashes should match regardless of who made it.
|
||||
- Someone could hyjack a new proposal by changing the vin and the signature check will fail.
|
||||
However, the network will still propagate the correct version and the incorrect one will be rejected.
|
||||
*/
|
||||
|
||||
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
||||
ss << strBudgetName;
|
||||
ss << nBlockStart;
|
||||
@ -258,7 +250,7 @@ public:
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(LIMITED_STRING(strBudgetName, 20));
|
||||
READWRITE(vin);
|
||||
READWRITE(nFeeTXHash);
|
||||
READWRITE(nBlockStart);
|
||||
READWRITE(vecProposals);
|
||||
|
||||
@ -273,13 +265,10 @@ private:
|
||||
std::vector<unsigned char> vchSig;
|
||||
|
||||
public:
|
||||
bool fInvalid;
|
||||
CFinalizedBudgetBroadcast();
|
||||
CFinalizedBudgetBroadcast(const CFinalizedBudget& other);
|
||||
CFinalizedBudgetBroadcast(CTxIn& vinIn, std::string strBudgetNameIn, int nBlockStartIn, std::vector<CTxBudgetPayment> vecProposalsIn);
|
||||
CFinalizedBudgetBroadcast(std::string strBudgetNameIn, int nBlockStartIn, std::vector<CTxBudgetPayment> vecProposalsIn, uint256 nFeeTXHashIn);
|
||||
|
||||
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
|
||||
bool SignatureValid();
|
||||
void Relay();
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
@ -289,10 +278,9 @@ public:
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
//for syncing with other clients
|
||||
READWRITE(LIMITED_STRING(strBudgetName, 20));
|
||||
READWRITE(vin);
|
||||
READWRITE(nBlockStart);
|
||||
READWRITE(vecProposals);
|
||||
READWRITE(vchSig);
|
||||
READWRITE(nFeeTXHash);
|
||||
}
|
||||
};
|
||||
|
||||
@ -354,19 +342,19 @@ public:
|
||||
This allows the proposal website to stay 100% decentralized
|
||||
*/
|
||||
std::string strURL;
|
||||
CTxIn vin;
|
||||
int nBlockStart;
|
||||
int nBlockEnd;
|
||||
int64_t nAmount;
|
||||
CScript address;
|
||||
int64_t nTime;
|
||||
uint256 nFeeTXHash;
|
||||
|
||||
map<uint256, CBudgetVote> mapVotes;
|
||||
//cache object
|
||||
|
||||
CBudgetProposal();
|
||||
CBudgetProposal(const CBudgetProposal& other);
|
||||
CBudgetProposal(CTxIn vinIn, std::string strProposalNameIn, std::string strURLIn, int nBlockStartIn, int nBlockEndIn, CScript addressIn, CAmount nAmountIn);
|
||||
CBudgetProposal(std::string strProposalNameIn, std::string strURLIn, int nBlockStartIn, int nBlockEndIn, CScript addressIn, CAmount nAmountIn, uint256 nFeeTXHashIn);
|
||||
|
||||
void Calculate();
|
||||
void AddOrUpdateVote(CBudgetVote& vote);
|
||||
@ -394,34 +382,9 @@ public:
|
||||
void SetAllotted(int64_t nAllotedIn) {nAlloted = nAllotedIn;}
|
||||
int64_t GetAllotted() {return nAlloted;}
|
||||
|
||||
std::string GetVoteCommand()
|
||||
{
|
||||
//c4 mnbudget vote one http://www.one.com/one.json 100 1000 xx9FwiqeRbuxBn5Sh3SNeoxmgpwQNSuMC4 1000 yes
|
||||
|
||||
int nPayments = GetTotalPaymentCount();
|
||||
|
||||
CTxDestination address1;
|
||||
ExtractDestination(address, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
|
||||
std::string strCommand = "dash-cli mnbudget vote " + strProposalName + " " + strURL + " " + boost::lexical_cast<std::string>(nPayments);
|
||||
strCommand += " " + boost::lexical_cast<std::string>(nBlockStart) + " " + address2.ToString() + " " + boost::lexical_cast<std::string>(nAmount/COIN) + " yes|no";
|
||||
|
||||
return strCommand;
|
||||
}
|
||||
|
||||
|
||||
void CleanAndRemove();
|
||||
|
||||
uint256 GetHash(){
|
||||
/*
|
||||
vin is not included on purpose
|
||||
- Any masternode can make a proposal and the hashes should match regardless of who made it.
|
||||
- Someone could hyjack a new proposal by changing the vin and the signature check will fail.
|
||||
However, the network will still propagate the correct version and the incorrect one will be rejected.
|
||||
*/
|
||||
|
||||
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
||||
ss << strProposalName;
|
||||
ss << strURL;
|
||||
@ -441,12 +404,12 @@ public:
|
||||
//for syncing with other clients
|
||||
READWRITE(LIMITED_STRING(strProposalName, 20));
|
||||
READWRITE(LIMITED_STRING(strURL, 64));
|
||||
READWRITE(vin);
|
||||
READWRITE(nBlockStart);
|
||||
READWRITE(nBlockEnd);
|
||||
READWRITE(nAmount);
|
||||
READWRITE(address);
|
||||
READWRITE(nTime);
|
||||
READWRITE(nFeeTXHash);
|
||||
|
||||
//for saving to the serialized db
|
||||
READWRITE(mapVotes);
|
||||
@ -460,13 +423,10 @@ private:
|
||||
std::vector<unsigned char> vchSig;
|
||||
|
||||
public:
|
||||
bool fInvalid;
|
||||
CBudgetProposalBroadcast();
|
||||
CBudgetProposalBroadcast(const CBudgetProposal& other);
|
||||
CBudgetProposalBroadcast(CTxIn vinIn, std::string strProposalNameIn, std::string strURL, int nPaymentCount, CScript addressIn, CAmount nAmountIn, int nBlockStartIn);
|
||||
CBudgetProposalBroadcast(std::string strProposalNameIn, std::string strURLIn, int nPaymentCount, CScript addressIn, CAmount nAmountIn, int nBlockStartIn, uint256 nFeeTXHashIn);
|
||||
|
||||
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
|
||||
bool SignatureValid();
|
||||
void Relay();
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
@ -477,12 +437,11 @@ public:
|
||||
|
||||
READWRITE(LIMITED_STRING(strProposalName, 20));
|
||||
READWRITE(LIMITED_STRING(strURL, 64));
|
||||
READWRITE(vin);
|
||||
READWRITE(nBlockStart);
|
||||
READWRITE(nBlockEnd);
|
||||
READWRITE(nAmount);
|
||||
READWRITE(address);
|
||||
READWRITE(vchSig);
|
||||
READWRITE(nFeeTXHash);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1797,7 +1797,7 @@ void RelayTransactionLockReq(const CTransaction& tx, bool relayToAll)
|
||||
if(!relayToAll && !pnode->fRelayTxes)
|
||||
continue;
|
||||
|
||||
pnode->PushMessage("txlreq", tx);
|
||||
pnode->PushMessage("ix", tx);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
|
||||
|
||||
transaction.getRecipients();
|
||||
|
||||
if(!wallet->CommitTransaction(*newTx, *keyChange, (recipients[0].useInstantX) ? "txlreq" : "tx"))
|
||||
if(!wallet->CommitTransaction(*newTx, *keyChange, (recipients[0].useInstantX) ? "ix" : "tx"))
|
||||
return TransactionCommitFailed;
|
||||
|
||||
CTransaction* t = (CTransaction*)newTx;
|
||||
|
@ -25,11 +25,13 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
strCommand = params[0].get_str();
|
||||
|
||||
if (fHelp ||
|
||||
(strCommand != "vote-many" && strCommand != "vote" && strCommand != "getvotes" && strCommand != "getinfo" && strCommand != "show" && strCommand != "projection" && strCommand != "check"))
|
||||
(strCommand != "vote-many" && strCommand != "prepare" && strCommand != "submit" && strCommand != "vote" && strCommand != "getvotes" && strCommand != "getinfo" && strCommand != "show" && strCommand != "projection" && strCommand != "check"))
|
||||
throw runtime_error(
|
||||
"mnbudget \"command\"... ( \"passphrase\" )\n"
|
||||
"Vote or show current budgets\n"
|
||||
"\nAvailable commands:\n"
|
||||
" prepare - Prepare proposal for network by signing and creating tx\n"
|
||||
" submit - Submit proposal for network\n"
|
||||
" vote-many - Vote on a Dash initiative\n"
|
||||
" vote-alias - Vote on a Dash initiative\n"
|
||||
" vote - Vote on a Dash initiative/budget\n"
|
||||
@ -40,7 +42,7 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
" check - Scan proposals and remove invalid\n"
|
||||
);
|
||||
|
||||
if(strCommand == "vote-many")
|
||||
if(strCommand == "prepare")
|
||||
{
|
||||
int nBlockMin = 0;
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
@ -48,114 +50,8 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
||||
mnEntries = masternodeConfig.getEntries();
|
||||
|
||||
if (params.size() != 8)
|
||||
throw runtime_error("Correct usage of vote-many is 'mnbudget vote-many PROPOSAL-NAME URL PAYMENT_COUNT BLOCK_START DASH_ADDRESS DASH_AMOUNT YES|NO|ABSTAIN'");
|
||||
|
||||
std::string strProposalName = params[1].get_str();
|
||||
if(strProposalName.size() > 20)
|
||||
return "Invalid proposal name, limit of 20 characters.";
|
||||
|
||||
std::string strURL = params[2].get_str();
|
||||
if(strURL.size() > 64)
|
||||
return "Invalid url, limit of 64 characters.";
|
||||
|
||||
int nPaymentCount = params[3].get_int();
|
||||
if(nPaymentCount < 1)
|
||||
return "Invalid payment count, must be more than zero.";
|
||||
|
||||
//set block min
|
||||
if(pindexPrev != NULL) nBlockMin = pindexPrev->nHeight - GetBudgetPaymentCycleBlocks()*(nPaymentCount+1);
|
||||
|
||||
int nBlockStart = params[4].get_int();
|
||||
if(nBlockStart % GetBudgetPaymentCycleBlocks() != 0){
|
||||
int nNext = pindexPrev->nHeight-(pindexPrev->nHeight % GetBudgetPaymentCycleBlocks())+GetBudgetPaymentCycleBlocks();
|
||||
return "Invalid block start - must be a budget cycle block. Next Valid Block: " + boost::lexical_cast<std::string>(nNext);
|
||||
}
|
||||
|
||||
int nBlockEnd = nBlockStart + (GetBudgetPaymentCycleBlocks()*nPaymentCount);
|
||||
|
||||
if(nBlockStart < nBlockMin)
|
||||
return "Invalid payment count, must be more than current height.";
|
||||
|
||||
if(nBlockEnd < pindexPrev->nHeight)
|
||||
return "Invalid ending block, starting block + (payment_cycle*payments) must be more than current height.";
|
||||
|
||||
CBitcoinAddress address(params[5].get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address");
|
||||
|
||||
// Parse Dash address
|
||||
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
||||
|
||||
CAmount nAmount = AmountFromValue(params[6]);
|
||||
std::string strVote = params[7].get_str().c_str();
|
||||
|
||||
if(strVote != "yes" && strVote != "no") return "You can only vote 'yes' or 'no'";
|
||||
int nVote = VOTE_ABSTAIN;
|
||||
if(strVote == "yes") nVote = VOTE_YES;
|
||||
if(strVote == "no") nVote = VOTE_NO;
|
||||
|
||||
int success = 0;
|
||||
int failed = 0;
|
||||
|
||||
Object resultObj;
|
||||
|
||||
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
|
||||
std::string errorMessage;
|
||||
std::vector<unsigned char> vchMasterNodeSignature;
|
||||
std::string strMasterNodeSignMessage;
|
||||
|
||||
CPubKey pubKeyCollateralAddress;
|
||||
CKey keyCollateralAddress;
|
||||
CPubKey pubKeyMasternode;
|
||||
CKey keyMasternode;
|
||||
|
||||
if(!darkSendSigner.SetKey(mne.getPrivKey(), errorMessage, keyMasternode, pubKeyMasternode)){
|
||||
printf(" Error upon calling SetKey for %s\n", mne.getAlias().c_str());
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
CMasternode* pmn = mnodeman.Find(pubKeyMasternode);
|
||||
if(pmn == NULL)
|
||||
{
|
||||
printf("Can't find masternode by pubkey for %s\n", mne.getAlias().c_str());
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//create the proposal incase we're the first to make it
|
||||
CBudgetProposalBroadcast budgetProposalBroadcast(pmn->vin, strProposalName, strURL, nPaymentCount, scriptPubKey, nAmount, nBlockStart);
|
||||
if(!budgetProposalBroadcast.Sign(keyMasternode, pubKeyMasternode)){
|
||||
return "Failure to sign.";
|
||||
}
|
||||
mapSeenMasternodeBudgetProposals.insert(make_pair(budgetProposalBroadcast.GetHash(), budgetProposalBroadcast));
|
||||
budgetProposalBroadcast.Relay();
|
||||
|
||||
CBudgetVote vote(pmn->vin, budgetProposalBroadcast.GetHash(), nVote);
|
||||
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
||||
return "Failure to sign.";
|
||||
}
|
||||
|
||||
mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
||||
vote.Relay();
|
||||
|
||||
success++;
|
||||
}
|
||||
|
||||
return("Voted successfully " + boost::lexical_cast<std::string>(success) + " time(s) and failed " + boost::lexical_cast<std::string>(failed) + " time(s).");
|
||||
}
|
||||
|
||||
if(strCommand == "vote")
|
||||
{
|
||||
int nBlockMin = 0;
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
|
||||
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
||||
mnEntries = masternodeConfig.getEntries();
|
||||
|
||||
if (params.size() != 8)
|
||||
throw runtime_error("Correct usage of vote-many is 'mnbudget vote PROPOSAL-NAME URL PAYMENT_COUNT BLOCK_START DASH_ADDRESS DASH_AMOUNT YES|NO|ABSTAIN'");
|
||||
if (params.size() != 8 || params.size() != 9)
|
||||
throw runtime_error("Correct usage of vote-many is 'mnbudget prepare PROPOSAL-NAME URL PAYMENT_COUNT BLOCK_START DASH_ADDRESS DASH_AMOUNT YES|NO|ABSTAIN [USE_IX(TRUE|FALSE)]'");
|
||||
|
||||
std::string strProposalName = params[1].get_str();
|
||||
if(strProposalName.size() > 20)
|
||||
@ -208,17 +104,199 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
||||
return(" Error upon calling SetKey");
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
CBudgetProposalBroadcast budgetProposalBroadcast(strProposalName, strURL, nPaymentCount, scriptPubKey, nAmount, nBlockStart, 0);
|
||||
std::string strCommand = "tx";
|
||||
bool useIX = true;
|
||||
if (params.size() > 8)
|
||||
useIX = params[8].get_bool();
|
||||
|
||||
if(useIX)
|
||||
{
|
||||
strCommand = "ix";
|
||||
}
|
||||
|
||||
CWalletTx wtx;
|
||||
pwalletMain->GetBudgetSystemCollateralTX(wtx, budgetProposalBroadcast.GetHash(), useIX);
|
||||
|
||||
// make our change address
|
||||
CReserveKey reservekey(pwalletMain);
|
||||
//send the tx to the network
|
||||
pwalletMain->CommitTransaction(wtx, reservekey, strCommand);
|
||||
|
||||
return wtx.GetHash().ToString().c_str();
|
||||
|
||||
}
|
||||
|
||||
if(strCommand == "submit")
|
||||
{
|
||||
int nBlockMin = 0;
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
|
||||
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
||||
mnEntries = masternodeConfig.getEntries();
|
||||
|
||||
if (params.size() != 9)
|
||||
throw runtime_error("Correct usage of vote-many is 'mnbudget submit PROPOSAL-NAME URL PAYMENT_COUNT BLOCK_START DASH_ADDRESS DASH_AMOUNT YES|NO|ABSTAIN FEE_TX'");
|
||||
|
||||
// Check these inputs the same way we check the vote commands:
|
||||
// **********************************************************
|
||||
|
||||
std::string strProposalName = params[1].get_str();
|
||||
if(strProposalName.size() > 20)
|
||||
return "Invalid proposal name, limit of 20 characters.";
|
||||
|
||||
std::string strURL = params[2].get_str();
|
||||
if(strURL.size() > 64)
|
||||
return "Invalid url, limit of 64 characters.";
|
||||
|
||||
int nPaymentCount = params[3].get_int();
|
||||
if(nPaymentCount < 1)
|
||||
return "Invalid payment count, must be more than zero.";
|
||||
|
||||
//set block min
|
||||
if(pindexPrev != NULL) nBlockMin = pindexPrev->nHeight - GetBudgetPaymentCycleBlocks()*(nPaymentCount+1);
|
||||
|
||||
int nBlockStart = params[4].get_int();
|
||||
if(nBlockStart % GetBudgetPaymentCycleBlocks() != 0){
|
||||
int nNext = pindexPrev->nHeight-(pindexPrev->nHeight % GetBudgetPaymentCycleBlocks())+GetBudgetPaymentCycleBlocks();
|
||||
return "Invalid block start - must be a budget cycle block. Next valid block: " + boost::lexical_cast<std::string>(nNext);
|
||||
}
|
||||
|
||||
int nBlockEnd = nBlockStart + (GetBudgetPaymentCycleBlocks()*nPaymentCount);
|
||||
|
||||
if(nBlockStart < nBlockMin)
|
||||
return "Invalid payment count, must be more than current height.";
|
||||
|
||||
if(nBlockEnd < pindexPrev->nHeight)
|
||||
return "Invalid ending block, starting block + (payment_cycle*payments) must be more than current height.";
|
||||
|
||||
CBitcoinAddress address(params[5].get_str());
|
||||
if (!address.IsValid())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address");
|
||||
|
||||
// Parse Dash address
|
||||
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
||||
|
||||
CAmount nAmount = AmountFromValue(params[6]);
|
||||
std::string strVote = params[7].get_str().c_str();
|
||||
|
||||
if(strVote != "yes" && strVote != "no") return "You can only vote 'yes' or 'no'";
|
||||
int nVote = VOTE_ABSTAIN;
|
||||
if(strVote == "yes") nVote = VOTE_YES;
|
||||
if(strVote == "no") nVote = VOTE_NO;
|
||||
|
||||
CPubKey pubKeyMasternode;
|
||||
CKey keyMasternode;
|
||||
std::string errorMessage;
|
||||
|
||||
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
||||
return(" Error upon calling SetKey");
|
||||
|
||||
uint256 hash = ParseHashV(params[8], "parameter 1");
|
||||
|
||||
//create the proposal incase we're the first to make it
|
||||
CBudgetProposalBroadcast budgetProposalBroadcast(activeMasternode.vin, strProposalName, strURL, nPaymentCount, scriptPubKey, nAmount, nBlockStart);
|
||||
if(!budgetProposalBroadcast.Sign(keyMasternode, pubKeyMasternode)){
|
||||
return "Failure to sign.";
|
||||
CBudgetProposalBroadcast budgetProposalBroadcast(strProposalName, strURL, nPaymentCount, scriptPubKey, nAmount, nBlockStart, hash);
|
||||
|
||||
std::string strError = "";
|
||||
if(!IsBudgetCollateralValid(hash ,strError)){
|
||||
return "Proposal FeeTX is not valid - " + hash.ToString() + " - " + strError;
|
||||
}
|
||||
|
||||
if(!budgetProposalBroadcast.IsValid(strError)){
|
||||
return "Proposal is not valid - " + budgetProposalBroadcast.GetHash().ToString() + " - " + strError;
|
||||
}
|
||||
|
||||
mapSeenMasternodeBudgetProposals.insert(make_pair(budgetProposalBroadcast.GetHash(), budgetProposalBroadcast));
|
||||
budgetProposalBroadcast.Relay();
|
||||
budget.AddProposal(budgetProposalBroadcast);
|
||||
|
||||
CBudgetVote vote(activeMasternode.vin, budgetProposalBroadcast.GetHash(), nVote);
|
||||
|
||||
}
|
||||
|
||||
if(strCommand == "vote-many")
|
||||
{
|
||||
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
||||
mnEntries = masternodeConfig.getEntries();
|
||||
|
||||
if (params.size() != 3)
|
||||
throw runtime_error("Correct usage of vote-many is 'mnbudget vote-many PROPOSAL-HASH YES|NO|ABSTAIN'");
|
||||
|
||||
uint256 hash = ParseHashV(params[1], "parameter 1");
|
||||
std::string strVote = params[2].get_str().c_str();
|
||||
|
||||
if(strVote != "yes" && strVote != "no") return "You can only vote 'yes' or 'no'";
|
||||
int nVote = VOTE_ABSTAIN;
|
||||
if(strVote == "yes") nVote = VOTE_YES;
|
||||
if(strVote == "no") nVote = VOTE_NO;
|
||||
|
||||
int success = 0;
|
||||
int failed = 0;
|
||||
|
||||
Object resultObj;
|
||||
|
||||
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
|
||||
std::string errorMessage;
|
||||
std::vector<unsigned char> vchMasterNodeSignature;
|
||||
std::string strMasterNodeSignMessage;
|
||||
|
||||
CPubKey pubKeyCollateralAddress;
|
||||
CKey keyCollateralAddress;
|
||||
CPubKey pubKeyMasternode;
|
||||
CKey keyMasternode;
|
||||
|
||||
if(!darkSendSigner.SetKey(mne.getPrivKey(), errorMessage, keyMasternode, pubKeyMasternode)){
|
||||
printf(" Error upon calling SetKey for %s\n", mne.getAlias().c_str());
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
CMasternode* pmn = mnodeman.Find(pubKeyMasternode);
|
||||
if(pmn == NULL)
|
||||
{
|
||||
printf("Can't find masternode by pubkey for %s\n", mne.getAlias().c_str());
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
CBudgetVote vote(pmn->vin, hash, nVote);
|
||||
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
||||
return "Failure to sign.";
|
||||
}
|
||||
|
||||
mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
||||
vote.Relay();
|
||||
|
||||
success++;
|
||||
}
|
||||
|
||||
return("Voted successfully " + boost::lexical_cast<std::string>(success) + " time(s) and failed " + boost::lexical_cast<std::string>(failed) + " time(s).");
|
||||
}
|
||||
|
||||
if(strCommand == "vote")
|
||||
{
|
||||
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
||||
mnEntries = masternodeConfig.getEntries();
|
||||
|
||||
if (params.size() != 3)
|
||||
throw runtime_error("Correct usage of vote-many is 'mnbudget vote PROPOSAL-HASH YES|NO|ABSTAIN'");
|
||||
|
||||
uint256 hash = ParseHashV(params[1], "parameter 1");
|
||||
std::string strVote = params[2].get_str().c_str();
|
||||
|
||||
if(strVote != "yes" && strVote != "no") return "You can only vote 'yes' or 'no'";
|
||||
int nVote = VOTE_ABSTAIN;
|
||||
if(strVote == "yes") nVote = VOTE_YES;
|
||||
if(strVote == "no") nVote = VOTE_NO;
|
||||
|
||||
CPubKey pubKeyMasternode;
|
||||
CKey keyMasternode;
|
||||
std::string errorMessage;
|
||||
|
||||
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
||||
return(" Error upon calling SetKey");
|
||||
|
||||
CBudgetVote vote(activeMasternode.vin, hash, nVote);
|
||||
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
||||
return "Failure to sign.";
|
||||
}
|
||||
@ -226,7 +304,6 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
||||
vote.Relay();
|
||||
budget.UpdateProposal(vote, NULL);
|
||||
|
||||
}
|
||||
|
||||
if(strCommand == "projection")
|
||||
@ -244,7 +321,6 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
Object bObj;
|
||||
bObj.push_back(Pair("VoteCommand", pbudgetProposal->GetVoteCommand().c_str()));
|
||||
bObj.push_back(Pair("URL", pbudgetProposal->GetURL()));
|
||||
bObj.push_back(Pair("Hash", pbudgetProposal->GetHash().ToString().c_str()));
|
||||
bObj.push_back(Pair("BlockStart", (int64_t)pbudgetProposal->GetBlockStart()));
|
||||
@ -261,11 +337,6 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
|
||||
std::string strError = "";
|
||||
bObj.push_back(Pair("IsValid", pbudgetProposal->IsValid(strError)));
|
||||
bObj.push_back(Pair("Owner", pbudgetProposal->vin.prevout.ToStringShort().c_str()));
|
||||
|
||||
if(mapSeenMasternodeBudgetProposals.count(pbudgetProposal->GetHash())) {
|
||||
bObj.push_back(Pair("SignatureValid", mapSeenMasternodeBudgetProposals[pbudgetProposal->GetHash()].SignatureValid()));
|
||||
}
|
||||
|
||||
resultObj.push_back(Pair(pbudgetProposal->GetName().c_str(), bObj));
|
||||
}
|
||||
@ -288,7 +359,6 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
Object bObj;
|
||||
bObj.push_back(Pair("VoteCommand", pbudgetProposal->GetVoteCommand().c_str()));
|
||||
bObj.push_back(Pair("URL", pbudgetProposal->GetURL()));
|
||||
bObj.push_back(Pair("Hash", pbudgetProposal->GetHash().ToString().c_str()));
|
||||
bObj.push_back(Pair("BlockStart", (int64_t)pbudgetProposal->GetBlockStart()));
|
||||
@ -304,11 +374,7 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
|
||||
std::string strError = "";
|
||||
bObj.push_back(Pair("IsValid", pbudgetProposal->IsValid(strError)));
|
||||
bObj.push_back(Pair("Owner", pbudgetProposal->vin.prevout.ToStringShort().c_str()));
|
||||
|
||||
if(mapSeenMasternodeBudgetProposals.count(pbudgetProposal->GetHash())) {
|
||||
bObj.push_back(Pair("SignatureValid", mapSeenMasternodeBudgetProposals[pbudgetProposal->GetHash()].SignatureValid()));
|
||||
}
|
||||
|
||||
resultObj.push_back(Pair(pbudgetProposal->GetName().c_str(), bObj));
|
||||
}
|
||||
@ -332,7 +398,6 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
Object obj;
|
||||
obj.push_back(Pair("VoteCommand", pbudgetProposal->GetVoteCommand().c_str()));
|
||||
obj.push_back(Pair("Name", pbudgetProposal->GetName().c_str()));
|
||||
obj.push_back(Pair("Hash", pbudgetProposal->GetHash().ToString().c_str()));
|
||||
obj.push_back(Pair("URL", pbudgetProposal->GetURL().c_str()));
|
||||
@ -349,12 +414,6 @@ Value mnbudget(const Array& params, bool fHelp)
|
||||
|
||||
std::string strError = "";
|
||||
obj.push_back(Pair("IsValid", pbudgetProposal->IsValid(strError)));
|
||||
obj.push_back(Pair("Owner", pbudgetProposal->vin.prevout.ToStringShort().c_str()));
|
||||
|
||||
if(mapSeenMasternodeBudgetProposals.count(pbudgetProposal->GetHash())) {
|
||||
obj.push_back(Pair("SignatureValid", mapSeenMasternodeBudgetProposals[pbudgetProposal->GetHash()].SignatureValid()));
|
||||
}
|
||||
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -452,11 +511,11 @@ Value mnfinalbudget(const Array& params, bool fHelp)
|
||||
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
||||
return(" Error upon calling SetKey");
|
||||
|
||||
//create transaction
|
||||
uint256 hash = 0;
|
||||
|
||||
//create the proposal incase we're the first to make it
|
||||
CFinalizedBudgetBroadcast finalizedBudgetBroadcast(activeMasternode.vin, strBudgetName, nBlockStart, vecPayments);
|
||||
if(!finalizedBudgetBroadcast.Sign(keyMasternode, pubKeyMasternode)){
|
||||
return "Failure to sign.";
|
||||
}
|
||||
CFinalizedBudgetBroadcast finalizedBudgetBroadcast(strBudgetName, nBlockStart, vecPayments, hash);
|
||||
|
||||
if(!finalizedBudgetBroadcast.IsValid())
|
||||
return "Invalid finalized budget broadcast (are all the hashes correct?)";
|
||||
@ -573,11 +632,11 @@ Value mnfinalbudget(const Array& params, bool fHelp)
|
||||
BOOST_FOREACH(CFinalizedBudget* finalizedBudget, winningFbs)
|
||||
{
|
||||
Object bObj;
|
||||
bObj.push_back(Pair("SubmittedBy", finalizedBudget->GetSubmittedBy().c_str()));
|
||||
bObj.push_back(Pair("FeeTX", finalizedBudget->nFeeTXHash.ToString().c_str()));
|
||||
bObj.push_back(Pair("Hash", finalizedBudget->GetHash().ToString().c_str()));
|
||||
bObj.push_back(Pair("BlockStart", (int64_t)finalizedBudget->GetBlockStart()));
|
||||
bObj.push_back(Pair("BlockEnd", (int64_t)finalizedBudget->GetBlockEnd()));
|
||||
bObj.push_back(Pair("finalizedBudgetosals", finalizedBudget->GetProposals().c_str()));
|
||||
bObj.push_back(Pair("Proposals", finalizedBudget->GetProposals().c_str()));
|
||||
bObj.push_back(Pair("VoteCount", (int64_t)finalizedBudget->GetVoteCount()));
|
||||
bObj.push_back(Pair("Status", finalizedBudget->GetStatus().c_str()));
|
||||
resultObj.push_back(Pair(finalizedBudget->GetName().c_str(), bObj));
|
||||
|
@ -10,7 +10,7 @@
|
||||
* network protocol versioning
|
||||
*/
|
||||
|
||||
static const int PROTOCOL_VERSION = 70085;
|
||||
static const int PROTOCOL_VERSION = 70086;
|
||||
|
||||
//! initial proto version, to be increased after version/verack negotiation
|
||||
static const int INIT_PROTO_VERSION = 209;
|
||||
@ -22,16 +22,16 @@ static const int GETHEADERS_VERSION = 70077;
|
||||
static const int MIN_PEER_PROTO_VERSION = 70066;
|
||||
|
||||
//! minimum peer version accepted by DarksendPool
|
||||
static const int MIN_POOL_PEER_PROTO_VERSION = 70085;
|
||||
static const int MIN_POOL_PEER_PROTO_VERSION = 70086;
|
||||
|
||||
//! minimum peer version for masternode budgets
|
||||
static const int MIN_BUDGET_PEER_PROTO_VERSION = 70085;
|
||||
static const int MIN_BUDGET_PEER_PROTO_VERSION = 70086;
|
||||
|
||||
//! minimum peer version that can receive masternode payments
|
||||
// V1 - Last protocol version before update
|
||||
// V2 - Newest protocol version
|
||||
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 = 70066;
|
||||
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70085;
|
||||
static const int MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2 = 70086;
|
||||
|
||||
//! nTime field added to CAddress, starting with this version;
|
||||
//! if possible, avoid requesting addresses nodes older than this
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "checkpoints.h"
|
||||
#include "coincontrol.h"
|
||||
#include "net.h"
|
||||
#include "masternode-budget.h"
|
||||
#include "darksend.h"
|
||||
#include "keepass.h"
|
||||
#include "instantx.h"
|
||||
@ -1086,7 +1087,7 @@ void CWalletTx::RelayWalletTransaction(std::string strCommand)
|
||||
uint256 hash = GetHash();
|
||||
LogPrintf("Relaying wtx %s\n", hash.ToString());
|
||||
|
||||
if(strCommand == "txlreq"){
|
||||
if(strCommand == "ix"){
|
||||
mapTxLockReq.insert(make_pair(hash, (CTransaction)*this));
|
||||
CreateNewLock(((CTransaction)*this));
|
||||
RelayTransactionLockReq((CTransaction)*this, true);
|
||||
@ -1927,7 +1928,7 @@ bool CWallet::SelectCoinsWithoutDenomination(int64_t nTargetValue, set<pair<cons
|
||||
return (nValueRet >= nTargetValue);
|
||||
}
|
||||
|
||||
bool CWallet::CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string strReason)
|
||||
bool CWallet::CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason)
|
||||
{
|
||||
/*
|
||||
To doublespend a collateral transaction, it will require a fee higher than this. So there's
|
||||
@ -1979,6 +1980,30 @@ bool CWallet::CreateCollateralTransaction(CMutableTransaction& txCollateral, std
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, bool useIX)
|
||||
{
|
||||
// make our change address
|
||||
CReserveKey reservekey(pwalletMain);
|
||||
|
||||
CScript scriptChange;
|
||||
scriptChange << OP_RETURN << ToByteVector(hash);
|
||||
|
||||
int64_t nFeeRet = 0;
|
||||
std::string strFail = "";
|
||||
vector< pair<CScript, int64_t> > vecSend;
|
||||
vecSend.push_back(make_pair(scriptChange, CENT));
|
||||
|
||||
CCoinControl *coinControl=NULL;
|
||||
bool success = CreateTransaction(vecSend, tx, reservekey, nFeeRet, strFail, coinControl, ALL_COINS, useIX, (CAmount)BUDGET_FEE_TX);
|
||||
if(!success){
|
||||
LogPrintf("GetBudgetSystemCollateralTX: Error - %s\n", strFail.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CWallet::ConvertList(std::vector<CTxIn> vCoins, std::vector<int64_t>& vecAmounts)
|
||||
{
|
||||
BOOST_FOREACH(CTxIn i, vCoins){
|
||||
@ -1996,8 +2021,10 @@ bool CWallet::ConvertList(std::vector<CTxIn> vCoins, std::vector<int64_t>& vecAm
|
||||
}
|
||||
|
||||
bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, AvailableCoinsType coin_type, bool useIX)
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, AvailableCoinsType coin_type, bool useIX, CAmount nPayFee)
|
||||
{
|
||||
if(useIX && nPayFee < CENT) nPayFee = CENT;
|
||||
|
||||
CAmount nValue = 0;
|
||||
CAmount nFeeDelta = 0;
|
||||
BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend)
|
||||
@ -2023,7 +2050,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
{
|
||||
nFeeRet = 0;
|
||||
if(useIX) nFeeRet = CENT;
|
||||
if(nPayFee!=0) nFeeRet = nPayFee;
|
||||
while (true)
|
||||
{
|
||||
txNew.vin.clear();
|
||||
@ -2206,11 +2233,11 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
|
||||
}
|
||||
|
||||
bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, AvailableCoinsType coin_type, bool useIX)
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, AvailableCoinsType coin_type, bool useIX, CAmount nPayFee)
|
||||
{
|
||||
vector< pair<CScript, CAmount> > vecSend;
|
||||
vecSend.push_back(make_pair(scriptPubKey, nValue));
|
||||
return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl, coin_type, useIX);
|
||||
return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl, coin_type, useIX, nPayFee);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -319,13 +319,13 @@ public:
|
||||
CAmount GetUnconfirmedWatchOnlyBalance() const;
|
||||
CAmount GetImmatureWatchOnlyBalance() const;
|
||||
bool CreateTransaction(const std::vector<std::pair<CScript, CAmount> >& vecSend,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL, AvailableCoinsType coin_type=ALL_COINS, bool useIX=false);
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL, AvailableCoinsType coin_type=ALL_COINS, bool useIX=false, CAmount nPayFee=0);
|
||||
bool CreateTransaction(CScript scriptPubKey, const CAmount& nValue,
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL, AvailableCoinsType coin_type=ALL_COINS, bool useIX=false);
|
||||
CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL, AvailableCoinsType coin_type=ALL_COINS, bool useIX=false, CAmount nPayFee=0);
|
||||
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, std::string strCommand="tx");
|
||||
std::string PrepareDarksendDenominate(int minRounds, int maxRounds);
|
||||
int GenerateDarksendOutputs(int nTotalValue, std::vector<CTxOut>& vout);
|
||||
bool CreateCollateralTransaction(CMutableTransaction &txCollateral, std::string strReason);
|
||||
bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason);
|
||||
bool ConvertList(std::vector<CTxIn> vCoins, std::vector<int64_t>& vecAmounts);
|
||||
|
||||
static CFeeRate minTxFee;
|
||||
@ -345,6 +345,8 @@ public:
|
||||
|
||||
std::set<CTxDestination> GetAccountAddresses(std::string strAccount) const;
|
||||
|
||||
bool GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, bool useIX);
|
||||
|
||||
bool IsDenominated(const CTxIn &txin) const;
|
||||
|
||||
bool IsDenominated(const CTransaction& tx) const
|
||||
|
Loading…
Reference in New Issue
Block a user