diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index dac86ba279..d189ce151a 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -168,6 +168,7 @@ HEADERS += src/qt/bitcoingui.h \ src/core.h \ src/masternode.h \ src/activemasternode.h \ + src/masternodeconfig.h \ src/net.h \ src/key.h \ src/db.h \ @@ -269,6 +270,7 @@ SOURCES += src/qt/bitcoin.cpp \ src/instantx.cpp \ src/masternode.cpp \ src/activemasternode.cpp \ + src/masternodeconfig.cpp \ src/core.cpp \ src/init.cpp \ src/net.cpp \ diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 79e2ef1340..98a5e6916b 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -2,289 +2,337 @@ #include "core.h" #include "activemasternode.h" -using namespace std; -using namespace boost; - CActiveMasternode activeMasternode; // // Bootup the masternode, look for a 1000DRK input and register on the network // -void CActiveMasternode::RegisterAsMasterNode(bool stop) +void CActiveMasternode::ManageStatus() { - if(!fMasterNode) return; + std::string errorMessage; + + LogPrintf("CActiveMasternode::ManageStatus() - Begin\n"); + + if(!fMasterNode) return; //need correct adjusted time to send ping bool fIsInitialDownload = IsInitialBlockDownload(); if(fIsInitialDownload) { - isCapableMasterNode = MASTERNODE_SYNC_IN_PROCESS; - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sync in progress. Must wait until sync is complete to start masternode.\n"); + status = MASTERNODE_SYNC_IN_PROCESS; + LogPrintf("CActiveMasternode::ManageStatus() - Sync in progress. Must wait until sync is complete to start masternode.\n"); return; } - std::string errorMessage; - - CKey key2; - CPubKey pubkey2; - - if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, key2, pubkey2)) - { - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Invalid masternodeprivkey: '%s'\n", errorMessage.c_str()); - exit(0); + if(status == MASTERNODE_INPUT_TOO_NEW || status == MASTERNODE_NOT_CAPABLE || status == MASTERNODE_SYNC_IN_PROCESS){ + status = MASTERNODE_NOT_PROCESSED; } - if(isCapableMasterNode == MASTERNODE_INPUT_TOO_NEW || isCapableMasterNode == MASTERNODE_NOT_CAPABLE || isCapableMasterNode == MASTERNODE_SYNC_IN_PROCESS){ - isCapableMasterNode = MASTERNODE_NOT_PROCESSED; - } - - if(isCapableMasterNode == MASTERNODE_NOT_PROCESSED) { + if(status == MASTERNODE_NOT_PROCESSED) { if(strMasterNodeAddr.empty()) { - if(!GetLocal(masterNodeSignAddr)) { - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Can't detect external address. Please use the masternodeaddr configuration option.\n"); - isCapableMasterNode = MASTERNODE_NOT_CAPABLE; + if(!GetLocal(service)) { + notCapableReason = "Can't detect external address. Please use the masternodeaddr configuration option."; + status = MASTERNODE_NOT_CAPABLE; + LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str()); return; } } else { - masterNodeSignAddr = CService(strMasterNodeAddr); + service = CService(strMasterNodeAddr); } - if((fTestNet && masterNodeSignAddr.GetPort() != 19999) || (!fTestNet && masterNodeSignAddr.GetPort() != 9999)) { - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Invalid port\n"); - isCapableMasterNode = MASTERNODE_NOT_CAPABLE; + if((fTestNet && service.GetPort() != 19999) || (!fTestNet && service.GetPort() != 9999)) { + notCapableReason = "Invalid port: " + boost::lexical_cast(service.GetPort()) + " -only 9999 or 19999 are supported."; + status = MASTERNODE_NOT_CAPABLE; + LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str()); return; } - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Checking inbound connection to '%s'\n", masterNodeSignAddr.ToString().c_str()); + LogPrintf("CActiveMasternode::ManageStatus() - Checking inbound connection to '%s'\n", service.ToString().c_str()); - if(ConnectNode((CAddress)masterNodeSignAddr, masterNodeSignAddr.ToString().c_str())){ - masternodePortOpen = MASTERNODE_PORT_OPEN; - } else { - masternodePortOpen = MASTERNODE_PORT_NOT_OPEN; - isCapableMasterNode = MASTERNODE_NOT_CAPABLE; - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Port not open.\n"); + if(!ConnectNode((CAddress)service, service.ToString().c_str())){ + notCapableReason = "Could not connect to " + service.ToString(); + status = MASTERNODE_NOT_CAPABLE; + LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str()); return; } if(pwalletMain->IsLocked()){ - isCapableMasterNode = MASTERNODE_NOT_CAPABLE; - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Not capable.\n"); + notCapableReason = "Wallet is locked."; + status = MASTERNODE_NOT_CAPABLE; + LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str()); return; } - isCapableMasterNode = MASTERNODE_NOT_CAPABLE; + // Set defaults + status = MASTERNODE_NOT_CAPABLE; + notCapableReason = "Unknown."; - CKey SecretKey; // Choose coins to use - if(GetMasterNodeVin(vinMasternode, pubkeyMasterNode, SecretKey)) { + CPubKey pubKeyCollateralAddress; + CKey keyCollateralAddress; - if(GetInputAge(vinMasternode) < MASTERNODE_MIN_CONFIRMATIONS){ - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Input must have least %d confirmations - %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS, GetInputAge(vinMasternode)); - isCapableMasterNode = MASTERNODE_INPUT_TOO_NEW; + if(GetMasterNodeVin(vin, pubKeyCollateralAddress, keyCollateralAddress)) { + + if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){ + LogPrintf("CActiveMasternode::ManageStatus() - Input must have least %d confirmations - %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS, GetInputAge(vin)); + status = MASTERNODE_INPUT_TOO_NEW; return; } - int protocolVersion = PROTOCOL_VERSION; - - masterNodeSignatureTime = GetAdjustedTime(); + LogPrintf("CActiveMasternode::ManageStatus() - Is capable master node!\n"); - std::string vchPubKey(pubkeyMasterNode.begin(), pubkeyMasterNode.end()); - std::string vchPubKey2(pubkey2.begin(), pubkey2.end()); - std::string strMessage = masterNodeSignAddr.ToString() + boost::lexical_cast(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast(protocolVersion); + status = MASTERNODE_IS_CAPABLE; + notCapableReason = ""; - if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, SecretKey)) { - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sign message failed\n"); - return; - } + pwalletMain->LockCoin(vin.prevout); - if(!darkSendSigner.VerifyMessage(pubkeyMasterNode, vchMasterNodeSignature, strMessage, errorMessage)) { - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Verify message failed\n"); - return; - } + // send to all nodes + CPubKey pubKeyMasternode; + CKey keyMasternode; - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Is capable master node!\n"); - - isCapableMasterNode = MASTERNODE_IS_CAPABLE; - - pwalletMain->LockCoin(vinMasternode.prevout); - - bool found = false; - BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes) - if(mn.vin == vinMasternode) - found = true; - - if(!found) { - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Adding myself to masternode list %s - %s\n", masterNodeSignAddr.ToString().c_str(), vinMasternode.ToString().c_str()); - CMasterNode mn(masterNodeSignAddr, vinMasternode, pubkeyMasterNode, vchMasterNodeSignature, masterNodeSignatureTime, pubkey2, PROTOCOL_VERSION); - mn.UpdateLastSeen(masterNodeSignatureTime); - darkSendMasterNodes.push_back(mn); - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Masternode input = %s\n", vinMasternode.ToString().c_str()); - } - - //relay to all - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode)) { - pnode->PushMessage("dsee", vinMasternode, masterNodeSignAddr, vchMasterNodeSignature, masterNodeSignatureTime, pubkeyMasterNode, pubkey2, -1, -1, masterNodeSignatureTime, protocolVersion); + LogPrintf("Register::ManageStatus() - Error upon calling SetKey: %s\n", errorMessage.c_str()); + return; + } + + if(!Register(vin, service, keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage)) { + LogPrintf("CActiveMasternode::ManageStatus() - Error on Register: %s", errorMessage.c_str()); } return; + } else { + LogPrintf("CActiveMasternode::ManageStatus() - Could not find suitable coins!\n"); } } - if(isCapableMasterNode != MASTERNODE_IS_CAPABLE && isCapableMasterNode != MASTERNODE_REMOTELY_ENABLED) return; + //send to all peers + if(!Dseep(errorMessage)) { + LogPrintf("CActiveMasternode::ManageStatus() - Error on Ping: %s", errorMessage.c_str()); + } +} - masterNodeSignatureTime = GetAdjustedTime(); +// Send stop dseep to network for remote masternode +bool CActiveMasternode::StopMasterNode(std::string strService, std::string strKeyMasternode, std::string& errorMessage) { + CTxIn vin; + CKey keyMasternode; + CPubKey pubKeyMasternode; - std::string strMessage = masterNodeSignAddr.ToString() + boost::lexical_cast(masterNodeSignatureTime) + boost::lexical_cast(stop); + if(!darkSendSigner.SetKey(strKeyMasternode, errorMessage, keyMasternode, pubKeyMasternode)) { + LogPrintf("CActiveMasternode::StopMasterNode() - Error: %s\n", errorMessage.c_str()); + return false; + } - if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, key2)) { - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sign message failed\n"); - return; + return StopMasterNode(vin, CService(strService), keyMasternode, pubKeyMasternode, errorMessage); +} + +// Send stop dseep to network for main masternode +bool CActiveMasternode::StopMasterNode(std::string& errorMessage) { + if(status != MASTERNODE_IS_CAPABLE && status != MASTERNODE_REMOTELY_ENABLED) { + errorMessage = "masternode is not in a running status"; + LogPrintf("CActiveMasternode::StopMasterNode() - Error: %s\n", errorMessage.c_str()); + return false; + } + + status = MASTERNODE_STOPPED; + + CPubKey pubKeyMasternode; + CKey keyMasternode; + + if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode)) + { + LogPrintf("Register::ManageStatus() - Error upon calling SetKey: %s\n", errorMessage.c_str()); + return false; } - if(!darkSendSigner.VerifyMessage(pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) { - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Verify message failed\n"); - return; + return StopMasterNode(vin, service, keyMasternode, pubKeyMasternode, errorMessage); +} + +// Send stop dseep to network for any masternode +bool CActiveMasternode::StopMasterNode(CTxIn vin, CService service, CKey keyMasternode, CPubKey pubKeyMasternode, std::string& errorMessage) { + pwalletMain->UnlockCoin(vin.prevout); + return Dseep(vin, service, keyMasternode, pubKeyMasternode, errorMessage, true); +} + +bool CActiveMasternode::Dseep(std::string& errorMessage) { + if(status != MASTERNODE_IS_CAPABLE && status != MASTERNODE_REMOTELY_ENABLED) { + errorMessage = "masternode is not in a running status"; + LogPrintf("CActiveMasternode::Dseep() - Error: %s\n", errorMessage.c_str()); + return false; + } + + CPubKey pubKeyMasternode; + CKey keyMasternode; + + if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode)) + { + LogPrintf("Register::ManageStatus() - Error upon calling SetKey: %s\n", errorMessage.c_str()); + return false; } + return Dseep(vin, service, keyMasternode, pubKeyMasternode, errorMessage, false); +} + +bool CActiveMasternode::Dseep(CTxIn vin, CService service, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &retErrorMessage, bool stop) { + std::string errorMessage; + std::vector vchMasterNodeSignature; + std::string strMasterNodeSignMessage; + int64 masterNodeSignatureTime = GetAdjustedTime(); + + std::string strMessage = service.ToString() + boost::lexical_cast(masterNodeSignatureTime) + boost::lexical_cast(stop); + + if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, keyMasternode)) { + retErrorMessage = "sign message failed: " + errorMessage; + LogPrintf("CActiveMasternode::Dseep() - Error: %s\n", retErrorMessage.c_str()); + return false; + } + + if(!darkSendSigner.VerifyMessage(pubKeyMasternode, vchMasterNodeSignature, strMessage, errorMessage)) { + retErrorMessage = "Verify message failed: " + errorMessage; + LogPrintf("CActiveMasternode::Dseep() - Error: %s\n", retErrorMessage.c_str()); + return false; + } + + // Update Last Seen timestamp in masternode list bool found = false; BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes) { //LogPrintf(" -- %s\n", mn.vin.ToString().c_str()); - - if(mn.vin == vinMasternode) { + if(mn.vin == vin) { found = true; mn.UpdateLastSeen(); } } + if(!found){ - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Darksend Masternode List doesn't include our masternode, Shutting down masternode pinging service! %s\n", vinMasternode.ToString().c_str()); - isCapableMasterNode = MASTERNODE_STOPPED; - return; + // Seems like we are trying to send a ping while the masternode is not registered in the network + retErrorMessage = "Darksend Masternode List doesn't include our masternode, Shutting down masternode pinging service! " + vin.ToString(); + LogPrintf("CActiveMasternode::Dseep() - Error: %s\n", retErrorMessage.c_str()); + status = MASTERNODE_NOT_CAPABLE; + notCapableReason = retErrorMessage; + return false; } - LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Masternode input = %s\n", vinMasternode.ToString().c_str()); + //send to all peers + LogPrintf("CActiveMasternode::Dseep() - SendDarkSendElectionEntryPing vin = %s\n", vin.ToString().c_str()); + SendDarkSendElectionEntryPing(vin, vchMasterNodeSignature, masterNodeSignatureTime, stop); - if (stop) isCapableMasterNode = MASTERNODE_STOPPED; - - //relay to all peers - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - { - pnode->PushMessage("dseep", vinMasternode, vchMasterNodeSignature, masterNodeSignatureTime, stop); - } + return true; } -// -// Bootup the masternode, look for a 1000DRK input and register on the network -// Takes 2 parameters to start a remote masternode -// -bool CActiveMasternode::RegisterAsMasterNodeRemoteOnly(std::string strMasterNodeAddr, std::string strMasterNodePrivKey) -{ - if(!fMasterNode) return false; +bool CActiveMasternode::Register(std::string strService, std::string strKeyMasternode, std::string txHash, std::string strOutputIndex, std::string& errorMessage) { + CTxIn vin; + CPubKey pubKeyCollateralAddress; + CKey keyCollateralAddress; + CPubKey pubKeyMasternode; + CKey keyMasternode; - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Address %s MasterNodePrivKey %s\n", strMasterNodeAddr.c_str(), strMasterNodePrivKey.c_str()); + if(!darkSendSigner.SetKey(strKeyMasternode, errorMessage, keyMasternode, pubKeyMasternode)) + { + LogPrintf("Register::Register() - Error upon calling SetKey: %s\n", errorMessage.c_str()); + return false; + } + if(!GetMasterNodeVin(vin, pubKeyCollateralAddress, keyCollateralAddress, txHash, strOutputIndex)) { + errorMessage = "could not allocate vin"; + LogPrintf("Register::Register() - Error: %s\n", errorMessage.c_str()); + return false; + } + return Register(vin, CService(strService), keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage); +} + +bool CActiveMasternode::Register(CTxIn vin, CService service, CKey keyCollateralAddress, CPubKey pubKeyCollateralAddress, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &retErrorMessage) { std::string errorMessage; + std::vector vchMasterNodeSignature; + std::string strMasterNodeSignMessage; + int64 masterNodeSignatureTime = GetAdjustedTime(); - CKey key2; - CPubKey pubkey2; + std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end()); + std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end()); + std::string strMessage = service.ToString() + boost::lexical_cast(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast(PROTOCOL_VERSION); - if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, key2, pubkey2)) - { - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Invalid masternodeprivkey: '%s'\n", errorMessage.c_str()); - return false; + if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, keyCollateralAddress)) { + retErrorMessage = "sign message failed: " + errorMessage; + LogPrintf("CActiveMasternode::Register() - Error: %s\n", retErrorMessage.c_str()); + return false; } - CService masterNodeSignAddr = CService(strMasterNodeAddr); - BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes){ - if(mn.addr == masterNodeSignAddr){ - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Address in use\n"); - return false; - } + if(!darkSendSigner.VerifyMessage(pubKeyCollateralAddress, vchMasterNodeSignature, strMessage, errorMessage)) { + retErrorMessage = "Verify message failed: " + errorMessage; + LogPrintf("CActiveMasternode::Register() - Error: %s\n", retErrorMessage.c_str()); + return false; + } + + bool found = false; + BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes) + if(mn.vin == vin) + found = true; + + if(!found) { + LogPrintf("CActiveMasternode::Register() - Adding to masternode list service: %s - vin: %s\n", service.ToString().c_str(), vin.ToString().c_str()); + CMasterNode mn(service, vin, pubKeyCollateralAddress, vchMasterNodeSignature, masterNodeSignatureTime, pubKeyMasternode, PROTOCOL_VERSION); + mn.UpdateLastSeen(masterNodeSignatureTime); + darkSendMasterNodes.push_back(mn); } - if((fTestNet && masterNodeSignAddr.GetPort() != 19999) || (!fTestNet && masterNodeSignAddr.GetPort() != 9999)) { - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Invalid port\n"); - return false; - } + //send to all peers + LogPrintf("CActiveMasternode::Register() - SendDarkSendElectionEntry vin = %s\n", vin.ToString().c_str()); + SendDarkSendElectionEntry(vin, service, vchMasterNodeSignature, masterNodeSignatureTime, pubKeyCollateralAddress, pubKeyMasternode, -1, -1, masterNodeSignatureTime, PROTOCOL_VERSION); - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Checking inbound connection to '%s'\n", masterNodeSignAddr.ToString().c_str()); - - if(!ConnectNode((CAddress)masterNodeSignAddr, masterNodeSignAddr.ToString().c_str())){ - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Error connecting to port\n"); - return false; - } - - if(pwalletMain->IsLocked()){ - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Wallet is locked\n"); - return false; - } - - CKey SecretKey; - CTxIn vinMasternode; - CPubKey pubkeyMasterNode; - int masterNodeSignatureTime = 0; - - // Choose coins to use - while (GetMasterNodeVin(vinMasternode, pubkeyMasterNode, SecretKey)) { - // don't use a vin that's registered - BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes) - if(mn.vin == vinMasternode) - continue; - - if(GetInputAge(vinMasternode) < MASTERNODE_MIN_CONFIRMATIONS) - continue; - - masterNodeSignatureTime = GetAdjustedTime(); - - std::string vchPubKey(pubkeyMasterNode.begin(), pubkeyMasterNode.end()); - std::string vchPubKey2(pubkey2.begin(), pubkey2.end()); - std::string strMessage = masterNodeSignAddr.ToString() + boost::lexical_cast(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast(PROTOCOL_VERSION); - - if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, SecretKey)) { - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Sign message failed\n"); - return false; - } - - if(!darkSendSigner.VerifyMessage(pubkeyMasterNode, vchMasterNodeSignature, strMessage, errorMessage)) { - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Verify message failed\n"); - return false; - } - - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Is capable master node!\n"); - - pwalletMain->LockCoin(vinMasternode.prevout); - - int protocolVersion = PROTOCOL_VERSION; - //relay to all - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - { - pnode->PushMessage("dsee", vinMasternode, masterNodeSignAddr, vchMasterNodeSignature, masterNodeSignatureTime, pubkeyMasterNode, pubkey2, -1, -1, masterNodeSignatureTime, protocolVersion); - } - - return true; - } - - LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - No sutable vin found\n"); - return false; + return true; } +bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey) { + return GetMasterNodeVin(vin, pubkey, secretKey, "", ""); +} -bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey) -{ - int64 nValueIn = 0; +bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex) { CScript pubScript; - // try once before we try to denominate - if (!pwalletMain->SelectCoinsMasternode(vin, nValueIn, pubScript)) - { - if(fDebug) LogPrintf("CActiveMasternode::GetMasterNodeVin - I'm not a capable masternode\n"); - return false; + // Find possible candidates + vector possibleCoins = SelectCoinsMasternode(); + COutput *selectedOutput; + + // Find the vin + if(!strTxHash.empty()) { + // Let's find it + uint256 txHash(strTxHash); + int outputIndex = boost::lexical_cast(outputIndex); + bool found = false; + BOOST_FOREACH(COutput& out, possibleCoins) { + if(true) { + selectedOutput = &out; + found = true; + break; + } + } + if(!found) { + LogPrintf("CActiveMasternode::GetMasterNodeVin - Could not locate valid vin\n"); + return false; + } + } else { + // No output specified, Select the first one + if(possibleCoins.size() > 0) { + selectedOutput = &possibleCoins[0]; + } else { + LogPrintf("CActiveMasternode::GetMasterNodeVin - Could not locate specified vin from possible list\n"); + return false; + } } - CTxDestination address1; + // At this point we have a selected output, retrieve the associated info + return GetVinFromOutput(*selectedOutput, vin, pubkey, secretKey); +} + + +// Extract masternode vin information from output +bool CActiveMasternode::GetVinFromOutput(COutput out, CTxIn& vin, CPubKey& pubkey, CKey& secretKey) { + + CScript pubScript; + + vin = CTxIn(out.tx->GetHash(),out.i); + pubScript = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey + + CTxDestination address1; ExtractDestination(pubScript, address1); CBitcoinAddress address2(address1); @@ -303,16 +351,62 @@ bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secr return true; } +// get all possible outputs for running masternode +vector CActiveMasternode::SelectCoinsMasternode() +{ + CCoinControl *coinControl=NULL; + vector vCoins; + vector filteredCoins; + + // Retrieve all possible outputs + pwalletMain->AvailableCoins(vCoins, true, coinControl, ALL_COINS); + + // Filter + BOOST_FOREACH(const COutput& out, vCoins) + { + if(out.tx->vout[out.i].nValue == 1000*COIN) { //exactly + filteredCoins.push_back(out); + } + } + return filteredCoins; +} + + +/* select coins with specified transaction hash and output index */ +/* +bool CActiveMasternode::SelectCoinsMasternode(CTxIn& vin, int64& nValueIn, CScript& pubScript, std::string strTxHash, std::string strOutputIndex) +{ + CWalletTx ctx; + + // Convert configuration strings + uint256 txHash; + int outputIndex; + txHash.SetHex(strTxHash); + std::istringstream(strOutputIndex) >> outputIndex; + + if(pwalletMain->GetTransaction(txHash, ctx)) { + if(ctx.vout[outputIndex].nValue == 1000*COIN) { //exactly + vin = CTxIn(ctx.GetHash(), outputIndex); + pubScript = ctx.vout[outputIndex].scriptPubKey; // the inputs PubKey + nValueIn = ctx.vout[outputIndex].nValue; + return true; + } + } + + return false; +} +*/ + // when starting a masternode, this can enable to run as a hot wallet with no funds -bool CActiveMasternode::EnableHotColdMasterNode(CTxIn& vin, int64 sigTime, CService& addr) +bool CActiveMasternode::EnableHotColdMasterNode(CTxIn& newVin, CService& newService) { if(!fMasterNode) return false; - isCapableMasterNode = MASTERNODE_REMOTELY_ENABLED; + status = MASTERNODE_REMOTELY_ENABLED; - vinMasternode = vin; - masterNodeSignatureTime = sigTime; - masterNodeSignAddr = addr; + //The values below are needed for signing dseep messages going forward + this->vin = newVin; + this->service = newService; LogPrintf("CActiveMasternode::EnableHotColdMasterNode() - Enabled! You may shut down the cold daemon.\n"); diff --git a/src/activemasternode.h b/src/activemasternode.h index bdf8999115..af625f3903 100644 --- a/src/activemasternode.h +++ b/src/activemasternode.h @@ -1,4 +1,3 @@ - // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying @@ -21,36 +20,45 @@ extern CActiveMasternode activeMasternode; class CActiveMasternode { public: - CTxIn vinMasternode; - CPubKey pubkeyMasterNode; - CPubKey pubkeyMasterNode2; + // Initialized by init.cpp + // Keys for the main masternode + CPubKey pubKeyMasternode; - std::string strMasterNodeSignMessage; - std::vector vchMasterNodeSignature; + // Initialized while registering masternode + CTxIn vin; + CService service; - std::string masterNodeAddr; - CService masterNodeSignAddr; - - int isCapableMasterNode; - int64 masterNodeSignatureTime; - int masternodePortOpen; + int status; + std::string notCapableReason; CActiveMasternode() { - isCapableMasterNode = MASTERNODE_NOT_PROCESSED; - masternodePortOpen = 0; + status = MASTERNODE_NOT_PROCESSED; } + void ManageStatus(); // manage status of main masternode + + bool Dseep(std::string& errorMessage); // ping for main masternode + bool Dseep(CTxIn vin, CService service, CKey key, CPubKey pubKey, std::string &retErrorMessage, bool stop); // ping for any masternode + + bool StopMasterNode(std::string& errorMessage); // stop main masternode + bool StopMasterNode(std::string strService, std::string strKeyMasternode, std::string& errorMessage); // stop remote masternode + bool StopMasterNode(CTxIn vin, CService service, CKey key, CPubKey pubKey, std::string& errorMessage); // stop any masternode + + bool Register(std::string strService, std::string strKey, std::string txHash, std::string strOutputIndex, std::string& errorMessage); // register remote masternode + bool Register(CTxIn vin, CService service, CKey key, CPubKey pubKey, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &retErrorMessage); // register any masternode + // get 1000DRK input that can be used for the masternode bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey); + bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex); + vector SelectCoinsMasternode(); + bool GetVinFromOutput(COutput out, CTxIn& vin, CPubKey& pubkey, CKey& secretKey); - // start the masternode and register with the network - void RegisterAsMasterNode(bool stop); - // start a remote masternode - bool RegisterAsMasterNodeRemoteOnly(std::string strMasterNodeAddr, std::string strMasterNodePrivKey); + //bool SelectCoinsMasternode(CTxIn& vin, int64& nValueIn, CScript& pubScript, std::string strTxHash, std::string strOutputIndex); // enable hot wallet mode (run a masternode with no funds) - bool EnableHotColdMasterNode(CTxIn& vin, int64 sigTime, CService& addr); + bool EnableHotColdMasterNode(CTxIn& vin, CService& addr); + }; -#endif \ No newline at end of file +#endif diff --git a/src/darksend.cpp b/src/darksend.cpp index 4d7de9f88a..ca94e33918 100644 --- a/src/darksend.cpp +++ b/src/darksend.cpp @@ -109,7 +109,7 @@ void ProcessMessageDarksend(CNode* pfrom, std::string& strCommand, CDataStream& vRecv >> nDenom >> txCollateral; std::string error = ""; - int mn = GetMasternodeByVin(activeMasternode.vinMasternode); + int mn = GetMasternodeByVin(activeMasternode.vin); if(mn == -1){ std::string strError = "Not in the masternode list"; pfrom->PushMessage("dssu", darkSendPool.sessionID, darkSendPool.GetState(), darkSendPool.GetEntriesCount(), MASTERNODE_REJECTED, strError); @@ -591,7 +591,7 @@ void CDarkSendPool::Check() if(!mapDarksendBroadcastTxes.count(txNew.GetHash())){ CDarksendBroadcastTx dstx; dstx.tx = txNew; - dstx.vin = activeMasternode.vinMasternode; + dstx.vin = activeMasternode.vin; dstx.vchSig = vchSig; dstx.sigTime = sigTime; @@ -799,7 +799,7 @@ void CDarkSendPool::CheckTimeout(){ if(state == POOL_STATUS_QUEUE && sessionUsers == GetMaxPoolTransactions()) { CDarksendQueue dsq; dsq.nDenom = sessionDenom; - dsq.vin = activeMasternode.vinMasternode; + dsq.vin = activeMasternode.vin; dsq.time = GetTime(); dsq.ready = true; dsq.Sign(); @@ -1852,7 +1852,7 @@ bool CDarkSendPool::IsCompatibleWithSession(int64 nDenom, CTransaction txCollate //broadcast that I'm accepting entries, only if it's the first entry though CDarksendQueue dsq; dsq.nDenom = nDenom; - dsq.vin = activeMasternode.vinMasternode; + dsq.vin = activeMasternode.vin; dsq.time = GetTime(); dsq.Sign(); dsq.Relay(); @@ -2104,6 +2104,8 @@ void ThreadCheckDarkSendPool() RenameThread("bitcoin-darksend"); unsigned int c = 0; + std::string errorMessage; + while (true) { c++; @@ -2152,16 +2154,14 @@ void ThreadCheckDarkSendPool() } } - if(c % MASTERNODE_PING_SECONDS == 0){ - activeMasternode.RegisterAsMasterNode(false); + activeMasternode.ManageStatus(); } if(c % 60 == 0){ //if we've used 1/5 of the masternode list, then clear the list. if((int)vecMasternodesUsed.size() > (int)darkSendMasterNodes.size() / 5) vecMasternodesUsed.clear(); - } //auto denom every 2.5 minutes (liquidity provides try less often) diff --git a/src/init.cpp b/src/init.cpp index 5b9aa76f56..00c93adfc5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -12,6 +12,7 @@ #include "ui_interface.h" #include "checkpointsync.h" #include "activemasternode.h" +#include "masternodeconfig.h" #include #include @@ -198,6 +199,10 @@ bool AppInit(int argc, char* argv[]) return false; } + // Process masternode config + masternodeConfig.read(GetMasternodeConfigFile()); + + // Command-line RPC for (int i = 1; i < argc; i++) if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "darkcoin:")) @@ -384,7 +389,8 @@ std::string HelpMessage() "\n" + _("Masternode options:") + "\n" + " -masternode= " + _("Enable the client to act as a masternode (0-1, default: 0)") + "\n" + - " -masternodeprivkey= " + _("Set the masternode private key") + "\n" + + " -mnconf= " + _("Specify masternode configuration file (default: masternode.conf)") + "\n" + + " -masternodeprivkey= " + _("Set the masternode private key") + "\n" + " -masternodeaddr= " + _("Set external address:port to get to this masternode (example: address:port)") + "\n" + " -masternodeminprotocol= " + _("Ignore masternodes less than version (example: 70050; default : 0)") + "\n" + @@ -1232,7 +1238,7 @@ bool AppInit2(boost::thread_group& threadGroup) return InitError(_("Invalid masternodeprivkey. Please see documenation.")); } - activeMasternode.pubkeyMasterNode2 = pubkey; + activeMasternode.pubKeyMasternode = pubkey; } else { return InitError(_("You must specify a masternodeprivkey in the configuration. Please see documentation for help.")); diff --git a/src/instantx.cpp b/src/instantx.cpp index 4aa01e5872..5515a9ff53 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -207,7 +207,7 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64 nBlockHeight) } int winner = GetCurrentMasterNode(1, nBlockHeight); - int n = GetMasternodeRank(activeMasternode.vinMasternode, nBlockHeight, MIN_INSTANTX_PROTO_VERSION); + int n = GetMasternodeRank(activeMasternode.vin, nBlockHeight, MIN_INSTANTX_PROTO_VERSION); if(n == -1 || winner == -1) { @@ -225,7 +225,7 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64 nBlockHeight) } CConsensusVote ctx; - ctx.vinMasternode = activeMasternode.vinMasternode; + ctx.vinMasternode = activeMasternode.vin; ctx.approved = approved; ctx.txHash = tx.GetHash(); ctx.nBlockHeight = nBlockHeight; @@ -274,7 +274,7 @@ void ProcessConsensusVote(CConsensusVote& ctx) } //We're not the winning masternode - if(darkSendMasterNodes[winner].vin != activeMasternode.vinMasternode) { + if(darkSendMasterNodes[winner].vin != activeMasternode.vin) { LogPrintf("InstantX::ProcessConsensusVote - I'm not the winning masternode\n"); return; } @@ -453,4 +453,4 @@ void CTransactionLock::AddSignature(CConsensusVote cv) int CTransactionLock::CountSignatures() { return vecConsensusVotes.size(); -} \ No newline at end of file +} diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index aa4157270d..5bb1d745fd 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -73,6 +73,7 @@ OBJS= \ obj/core.o \ obj/masternode.o \ obj/activemasternode.o \ + obj/masternodeconfig.o \ obj/instantx.o \ obj/keystore.o \ obj/darksend.o \ diff --git a/src/makefile.mingw b/src/makefile.mingw index 9ce14a2e48..ddbb3f39c3 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -85,6 +85,7 @@ OBJS= \ obj/core.o \ obj/masternode.o \ obj/activemasternode.o \ + obj/masternodeconfig.o \ obj/instantx.o \ obj/keystore.o \ obj/main.o \ diff --git a/src/makefile.osx b/src/makefile.osx index 010caf5645..c9a01dde35 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -90,6 +90,7 @@ OBJS= \ obj/core.o \ obj/masternode.o \ obj/activemasternode.o \ + obj/masternodeconfig.o \ obj/instantx.o \ obj/keystore.o \ obj/main.o \ diff --git a/src/makefile.unix b/src/makefile.unix index 48fcd31176..e92f8f8274 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -127,6 +127,7 @@ OBJS= \ obj/init.o \ obj/core.o \ obj/masternode.o \ + obj/masternodeconfig.o \ obj/activemasternode.o \ obj/instantx.o \ obj/keystore.o \ diff --git a/src/masternode.cpp b/src/masternode.cpp index c0cc1132ee..31080128a5 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -1,11 +1,8 @@ - - #include "masternode.h" #include "activemasternode.h" #include "darksend.h" #include "core.h" - /** The list of active masternodes */ std::vector darkSendMasterNodes; /** Object for who's going to get paid on which blocks */ @@ -163,8 +160,8 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream darkSendMasterNodes.push_back(mn); // if it matches our masternodeprivkey, then we've been remotely activated - if(pubkey2 == activeMasternode.pubkeyMasterNode2 && protocolVersion == PROTOCOL_VERSION){ - activeMasternode.EnableHotColdMasterNode(vin, sigTime, addr); + if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){ + activeMasternode.EnableHotColdMasterNode(vin, addr); } if(count == -1 && !isLocal) @@ -194,6 +191,8 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream bool stop; vRecv >> vin >> vchSig >> sigTime >> stop; + //LogPrintf("dseep - Received: vin: %s sigTime: %lld stop: %s\n", vin.ToString().c_str(), sigTime, stop ? "true" : "false"); + if (sigTime > GetAdjustedTime() + 60 * 60) { LogPrintf("dseep - Signature rejected, too far into the future %s\n", vin.ToString().c_str()); return; @@ -208,7 +207,8 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes) { if(mn.vin.prevout == vin.prevout) { - // take this only if it's newer + // LogPrintf("dseep - Found corresponding mn for vin: %s\n", vin.ToString().c_str()); + // take this only if it's newer if(mn.lastDseep < sigTime){ std::string strMessage = mn.addr.ToString() + boost::lexical_cast(sigTime) + boost::lexical_cast(stop); diff --git a/src/masternodeconfig.cpp b/src/masternodeconfig.cpp new file mode 100644 index 0000000000..e1800dabf9 --- /dev/null +++ b/src/masternodeconfig.cpp @@ -0,0 +1,31 @@ +#include "masternodeconfig.h" +#include "util.h" + +CMasternodeConfig masternodeConfig; + +void CMasternodeConfig::add(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex) { + CMasternodeEntry cme(alias, ip, privKey, txHash, outputIndex); + entries.push_back(cme); +} + +void CMasternodeConfig::read(boost::filesystem::path path) { + boost::filesystem::ifstream streamConfig(GetMasternodeConfigFile()); + if (!streamConfig.good()) { + return; // No masternode.conf file is OK + } + + for(std::string line; std::getline(streamConfig, line); ) + { + if(line.empty()) { + continue; + } + std::istringstream iss(line); + std::string alias, ip, privKey, txHash, outputIndex; + if (!(iss >> alias >> ip >> privKey >> txHash >> outputIndex)) { + LogPrintf("CMasternodeConfig::read - Could not parse masternode.conf. Line: %s\n", line.c_str()); + } + add(alias, ip, privKey, txHash, outputIndex); + } + + streamConfig.close(); +} diff --git a/src/masternodeconfig.h b/src/masternodeconfig.h new file mode 100644 index 0000000000..c5e95c4101 --- /dev/null +++ b/src/masternodeconfig.h @@ -0,0 +1,102 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef SRC_MASTERNODECONFIG_H_ +#define SRC_MASTERNODECONFIG_H_ + +#include +#include + +#include +#include + +class CMasternodeConfig; +extern CMasternodeConfig masternodeConfig; + +class CMasternodeConfig +{ + +public: + class CMasternodeEntry { + + private: + std::string alias; + std::string ip; + std::string privKey; + std::string txHash; + std::string outputIndex; + + public: + + CMasternodeEntry(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex) { + this->alias = alias; + this->ip = ip; + this->privKey = privKey; + this->txHash = txHash; + this->outputIndex = outputIndex; + } + + const std::string& getAlias() const { + return alias; + } + + void setAlias(const std::string& alias) { + this->alias = alias; + } + + const std::string& getOutputIndex() const { + return outputIndex; + } + + void setOutputIndex(const std::string& outputIndex) { + this->outputIndex = outputIndex; + } + + const std::string& getPrivKey() const { + return privKey; + } + + void setPrivKey(const std::string& privKey) { + this->privKey = privKey; + } + + const std::string& getTxHash() const { + return txHash; + } + + void setTxHash(const std::string& txHash) { + this->txHash = txHash; + } + + const std::string& getIp() const { + return ip; + } + + void setIp(const std::string& ip) { + this->ip = ip; + } + }; + + CMasternodeConfig() { + entries = std::vector(); + } + + void clear(); + void read(boost::filesystem::path path); + void add(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex); + + std::vector& getEntries() { + return entries; + } + +private: + std::vector entries; + + +}; + + +#endif /* SRC_MASTERNODECONFIG_H_ */ + diff --git a/src/net.cpp b/src/net.cpp index 52ff32e93a..15b8990260 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1970,6 +1970,15 @@ void RelayDarkSendElectionEntry(const CTxIn vin, const CService addr, const std: } } +void SendDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64 lastUpdated, const int protocolVersion) +{ + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + { + pnode->PushMessage("dsee", vin, addr, vchSig, nNow, pubkey, pubkey2, count, current, lastUpdated, protocolVersion); + } +} + void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vector vchSig, const int64 nNow, const bool stop) { LOCK(cs_vNodes); @@ -1981,6 +1990,15 @@ void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vector vchSig, const int64 nNow, const bool stop) +{ + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + { + pnode->PushMessage("dseep", vin, vchSig, nNow, stop); + } +} + void RelayDarkSendCompletedTransaction(const int sessionID, const bool error, const std::string errorMessage) { LOCK(cs_vNodes); @@ -1988,4 +2006,4 @@ void RelayDarkSendCompletedTransaction(const int sessionID, const bool error, co { pnode->PushMessage("dsc", sessionID, error, errorMessage); } -} \ No newline at end of file +} diff --git a/src/net.h b/src/net.h index beb1bfabde..af61f394e8 100644 --- a/src/net.h +++ b/src/net.h @@ -691,7 +691,9 @@ void RelayDarkSendFinalTransaction(const int sessionID, const CTransaction& txNe void RelayDarkSendIn(const std::vector& in, const int64& nAmount, const CTransaction& txCollateral, const std::vector& out); void RelayDarkSendStatus(const int sessionID, const int newState, const int newEntriesCount, const int newAccepted, const std::string error=""); void RelayDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64 lastUpdated, const int protocolVersion); +void SendDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64 lastUpdated, const int protocolVersion); void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vector vchSig, const int64 nNow, const bool stop); +void SendDarkSendElectionEntryPing(const CTxIn vin, const std::vector vchSig, const int64 nNow, const bool stop); void RelayDarkSendCompletedTransaction(const int sessionID, const bool error, const std::string errorMessage); void RelayDarkSendMasterNodeContestant(); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 0d8680538c..ef59161295 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -15,6 +15,7 @@ #include "ui_interface.h" #include "paymentserver.h" #include "splashscreen.h" +#include "masternodeconfig.h" #include #if QT_VERSION < 0x050000 @@ -154,6 +155,9 @@ int main(int argc, char *argv[]) } ReadConfigFile(mapArgs, mapMultiArgs); + // Process masternode config + masternodeConfig.read(GetMasternodeConfigFile()); + // Application identification (must be set before OptionsModel is initialized, // as it is used to locate QSettings) QApplication::setOrganizationName("DarkCoin"); diff --git a/src/rpcdarksend.cpp b/src/rpcdarksend.cpp index 2585c5a866..285ebf7b99 100644 --- a/src/rpcdarksend.cpp +++ b/src/rpcdarksend.cpp @@ -9,12 +9,10 @@ #include "init.h" #include "masternode.h" #include "activemasternode.h" +#include "masternodeconfig.h" #include "bitcoinrpc.h" -#include using namespace json_spirit; -using namespace std; - Value darksend(const Array& params, bool fHelp) @@ -75,7 +73,7 @@ Value getpoolinfo(const Array& params, bool fHelp) "Returns an object containing anonymous pool-related information."); Object obj; - obj.push_back(Pair("connected_to_masternode", activeMasternode.masterNodeAddr)); + obj.push_back(Pair("connected_to_masternode", activeMasternode.service.ToString())); obj.push_back(Pair("current_masternode", GetCurrentMasterNode())); obj.push_back(Pair("state", darkSendPool.GetState())); obj.push_back(Pair("entries", darkSendPool.GetEntriesCount())); @@ -90,10 +88,10 @@ Value masternode(const Array& params, bool fHelp) strCommand = params[0].get_str(); if (fHelp || - (strCommand != "start" && strCommand != "start-many" && strCommand != "stop" && strCommand != "list" && strCommand != "count" && strCommand != "enforce" + (strCommand != "start" && strCommand != "start-alias" && strCommand != "start-many" && strCommand != "stop" && strCommand != "stop-alias" && strCommand != "stop-many" && strCommand != "list" && strCommand != "list-conf" && strCommand != "count" && strCommand != "enforce" && strCommand != "debug" && strCommand != "current" && strCommand != "winners" && strCommand != "genkey" && strCommand != "connect")) throw runtime_error( - "masternode passphrase\n"); + "masternode passphrase\n"); if (strCommand == "stop") { @@ -115,15 +113,126 @@ Value masternode(const Array& params, bool fHelp) } } - activeMasternode.RegisterAsMasterNode(true); + std::string errorMessage; + if(!activeMasternode.StopMasterNode(errorMessage)) { + return "stop failed: " + errorMessage; + } pwalletMain->Lock(); - if(activeMasternode.isCapableMasterNode == MASTERNODE_STOPPED) return "successfully stopped masternode"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_NOT_CAPABLE) return "not capable masternode"; + if(activeMasternode.status == MASTERNODE_STOPPED) return "successfully stopped masternode"; + if(activeMasternode.status == MASTERNODE_NOT_CAPABLE) return "not capable masternode"; return "unknown"; } + if (strCommand == "stop-alias") + { + if (params.size() < 2){ + throw runtime_error( + "command needs at least 2 parameters\n"); + } + + std::string alias = params[1].get_str().c_str(); + + if(pwalletMain->IsLocked()) { + SecureString strWalletPass; + strWalletPass.reserve(100); + + if (params.size() == 3){ + strWalletPass = params[2].get_str().c_str(); + } else { + throw runtime_error( + "Your wallet is locked, passphrase is required\n"); + } + + if(!pwalletMain->Unlock(strWalletPass)){ + return "incorrect passphrase"; + } + } + + bool found = false; + + Object statusObj; + statusObj.push_back(Pair("alias", alias)); + + BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) { + if(mne.getAlias() == alias) { + found = true; + std::string errorMessage; + bool result = activeMasternode.StopMasterNode(mne.getIp(), mne.getPrivKey(), errorMessage); + + statusObj.push_back(Pair("result", result ? "successful" : "failed")); + if(!result) { + statusObj.push_back(Pair("errorMessage", errorMessage)); + } + break; + } + } + + if(!found) { + statusObj.push_back(Pair("result", "failed")); + statusObj.push_back(Pair("errorMessage", "could not find alias in config. Verify with list-conf.")); + } + + pwalletMain->Lock(); + return statusObj; + } + + if (strCommand == "stop-many") + { + if(pwalletMain->IsLocked()) { + SecureString strWalletPass; + strWalletPass.reserve(100); + + if (params.size() == 2){ + strWalletPass = params[1].get_str().c_str(); + } else { + throw runtime_error( + "Your wallet is locked, passphrase is required\n"); + } + + if(!pwalletMain->Unlock(strWalletPass)){ + return "incorrect passphrase"; + } + } + + int total = 0; + int successful = 0; + int fail = 0; + + + Object resultsObj; + + BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) { + total++; + + std::string errorMessage; + bool result = activeMasternode.StopMasterNode(mne.getIp(), mne.getPrivKey(), errorMessage); + + Object statusObj; + statusObj.push_back(Pair("alias", mne.getAlias())); + statusObj.push_back(Pair("result", result ? "successful" : "failed")); + + if(result) { + successful++; + } else { + fail++; + statusObj.push_back(Pair("errorMessage", errorMessage)); + } + + resultsObj.push_back(Pair("status", statusObj)); + } + pwalletMain->Lock(); + + Object returnObj; + returnObj.push_back(Pair("overall", "Successfully stopped " + boost::lexical_cast(successful) + " masternodes, failed to stop " + + boost::lexical_cast(fail) + ", total " + boost::lexical_cast(total))); + returnObj.push_back(Pair("detail", resultsObj)); + + return returnObj; + + } + if (strCommand == "list") { std::string strCommand = "active"; @@ -187,57 +296,140 @@ Value masternode(const Array& params, bool fHelp) } } - activeMasternode.RegisterAsMasterNode(false); + activeMasternode.status = MASTERNODE_NOT_PROCESSED; // TODO: consider better way + std::string errorMessage; + activeMasternode.ManageStatus(); pwalletMain->Lock(); - if(activeMasternode.isCapableMasterNode == MASTERNODE_REMOTELY_ENABLED) return "masternode started remotely"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_INPUT_TOO_NEW) return "masternode input must have at least 15 confirmations"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_STOPPED) return "masternode is stopped"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_IS_CAPABLE) return "successfully started masternode"; - if(activeMasternode.masternodePortOpen == MASTERNODE_PORT_NOT_OPEN) return "inbound port is not open. Please open it and try again. (19999 for testnet and 9999 for mainnet)"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_NOT_CAPABLE) return "not capable masternode"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_SYNC_IN_PROCESS) return "sync in process. Must wait until client is synced to start."; + if(activeMasternode.status == MASTERNODE_REMOTELY_ENABLED) return "masternode started remotely"; + if(activeMasternode.status == MASTERNODE_INPUT_TOO_NEW) return "masternode input must have at least 15 confirmations"; + if(activeMasternode.status == MASTERNODE_STOPPED) return "masternode is stopped"; + if(activeMasternode.status == MASTERNODE_IS_CAPABLE) return "successfully started masternode"; + if(activeMasternode.status == MASTERNODE_NOT_CAPABLE) return "not capable masternode: " + activeMasternode.notCapableReason; + if(activeMasternode.status == MASTERNODE_SYNC_IN_PROCESS) return "sync in process. Must wait until client is synced to start."; return "unknown"; } + + if (strCommand == "start-alias") + { + if (params.size() < 2){ + throw runtime_error( + "command needs at least 2 parameters\n"); + } + + std::string alias = params[1].get_str().c_str(); + + if(pwalletMain->IsLocked()) { + SecureString strWalletPass; + strWalletPass.reserve(100); + + if (params.size() == 3){ + strWalletPass = params[2].get_str().c_str(); + } else { + throw runtime_error( + "Your wallet is locked, passphrase is required\n"); + } + + if(!pwalletMain->Unlock(strWalletPass)){ + return "incorrect passphrase"; + } + } + + bool found = false; + + Object statusObj; + statusObj.push_back(Pair("alias", alias)); + + BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) { + if(mne.getAlias() == alias) { + found = true; + std::string errorMessage; + bool result = activeMasternode.Register(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), errorMessage); + + statusObj.push_back(Pair("result", result ? "successful" : "failed")); + if(!result) { + statusObj.push_back(Pair("errorMessage", errorMessage)); + } + break; + } + } + + if(!found) { + statusObj.push_back(Pair("result", "failed")); + statusObj.push_back(Pair("errorMessage", "could not find alias in config. Verify with list-conf.")); + } + + pwalletMain->Lock(); + return statusObj; + + } if (strCommand == "start-many") { - boost::filesystem::path pathDebug = GetDataDir() / "masternode.conf"; - std::ifstream infile(pathDebug.string().c_str()); + if(pwalletMain->IsLocked()) { + SecureString strWalletPass; + strWalletPass.reserve(100); - std::string line; - int total = 0; - int successful = 0; - int fail = 0; - while (std::getline(infile, line)) - { - std::istringstream iss(line); - std::string a, b; - if (!(iss >> a >> b)) { break; } // error + if (params.size() == 2){ + strWalletPass = params[1].get_str().c_str(); + } else { + throw runtime_error( + "Your wallet is locked, passphrase is required\n"); + } - total++; - if(activeMasternode.RegisterAsMasterNodeRemoteOnly(a, b)){ - successful++; - } else { - fail++; - } - } - - printf(" Successfully started %d masternodes, failed to start %d, total %d\n", successful, fail, total); - return ""; + if(!pwalletMain->Unlock(strWalletPass)){ + return "incorrect passphrase"; + } + } + + std::vector mnEntries; + mnEntries = masternodeConfig.getEntries(); + + int total = 0; + int successful = 0; + int fail = 0; + + Object resultsObj; + + BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) { + total++; + + std::string errorMessage; + bool result = activeMasternode.Register(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), errorMessage); + + Object statusObj; + statusObj.push_back(Pair("alias", mne.getAlias())); + statusObj.push_back(Pair("result", result ? "succesful" : "failed")); + + if(result) { + successful++; + } else { + fail++; + statusObj.push_back(Pair("errorMessage", errorMessage)); + } + + resultsObj.push_back(Pair("status", statusObj)); + } + pwalletMain->Lock(); + + Object returnObj; + returnObj.push_back(Pair("overall", "Successfully started " + boost::lexical_cast(successful) + " masternodes, failed to start " + + boost::lexical_cast(fail) + ", total " + boost::lexical_cast(total))); + returnObj.push_back(Pair("detail", resultsObj)); + + return returnObj; } if (strCommand == "debug") { - if(activeMasternode.isCapableMasterNode == MASTERNODE_REMOTELY_ENABLED) return "masternode started remotely"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_INPUT_TOO_NEW) return "masternode input must have at least 15 confirmations"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_IS_CAPABLE) return "successfully started masternode"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_STOPPED) return "masternode is stopped"; - if(activeMasternode.masternodePortOpen == MASTERNODE_PORT_NOT_OPEN) return "inbound port is not open. Please open it and try again. (19999 for testnet and 9999 for mainnet)"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_NOT_CAPABLE) return "not capable masternode"; - if(activeMasternode.isCapableMasterNode == MASTERNODE_SYNC_IN_PROCESS) return "sync in process. Must wait until client is synced to start."; + if(activeMasternode.status == MASTERNODE_REMOTELY_ENABLED) return "masternode started remotely"; + if(activeMasternode.status == MASTERNODE_INPUT_TOO_NEW) return "masternode input must have at least 15 confirmations"; + if(activeMasternode.status == MASTERNODE_IS_CAPABLE) return "successfully started masternode"; + if(activeMasternode.status == MASTERNODE_STOPPED) return "masternode is stopped"; + if(activeMasternode.status == MASTERNODE_NOT_CAPABLE) return "not capable masternode: " + activeMasternode.notCapableReason; + if(activeMasternode.status == MASTERNODE_SYNC_IN_PROCESS) return "sync in process. Must wait until client is synced to start."; CTxIn vin = CTxIn(); CPubKey pubkey = CScript(); @@ -318,6 +510,26 @@ Value masternode(const Array& params, bool fHelp) } } + if(strCommand == "list-conf") + { + std::vector mnEntries; + mnEntries = masternodeConfig.getEntries(); + + Object resultObj; + + BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) { + Object mnObj; + mnObj.push_back(Pair("alias", mne.getAlias())); + mnObj.push_back(Pair("address", mne.getIp())); + mnObj.push_back(Pair("privateKey", mne.getPrivKey())); + mnObj.push_back(Pair("txHash", mne.getTxHash())); + mnObj.push_back(Pair("outputIndex", mne.getOutputIndex())); + resultObj.push_back(Pair("masternode", mnObj)); + } + + return resultObj; + } + return Value::null; } diff --git a/src/util.cpp b/src/util.cpp index 7c3500b208..de151c4a0e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1127,6 +1127,13 @@ boost::filesystem::path GetConfigFile() return pathConfigFile; } +boost::filesystem::path GetMasternodeConfigFile() +{ + boost::filesystem::path pathConfigFile(GetArg("-mnconf", "masternode.conf")); + if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; + return pathConfigFile; +} + void ReadConfigFile(map& mapSettingsRet, map >& mapMultiSettingsRet) { diff --git a/src/util.h b/src/util.h index 507ade862d..2e86e6ae33 100644 --- a/src/util.h +++ b/src/util.h @@ -210,6 +210,7 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); boost::filesystem::path GetDefaultDataDir(); const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); boost::filesystem::path GetConfigFile(); +boost::filesystem::path GetMasternodeConfigFile(); boost::filesystem::path GetPidFile(); #ifndef WIN32 void CreatePidFile(const boost::filesystem::path &path, pid_t pid); diff --git a/src/wallet.cpp b/src/wallet.cpp index 798c9fc6ae..741bb74c06 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1201,26 +1201,6 @@ static void ApproximateBestSubset(vector vCoins; - AvailableCoins(vCoins, true, coinControl, ALL_COINS); - - BOOST_FOREACH(const COutput& out, vCoins) - { - if(out.tx->vout[out.i].nValue == 1000*COIN){ //exactly - vin = CTxIn(out.tx->GetHash(),out.i); - pubScript = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey - nValueRet = out.tx->vout[out.i].nValue; - return true; - } - } - - return false; -} - bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, vector vCoins, set >& setCoinsRet, int64& nValueRet) const {