Merge pull request #75 from freynder/start-many-enh-v0.11.0.x

Improve support for start-many
This commit is contained in:
evan82 2014-12-14 07:49:17 -07:00
commit 3a8545fa28
21 changed files with 804 additions and 308 deletions

26
doc/masternode_conf.md Normal file
View File

@ -0,0 +1,26 @@
Multi masternode config
=======================
The multi masternode config allows to control multiple masternodes from a single wallet. The wallet needs to have a valid collaral input of 1000 coins for each masternode. To use this, place a file named masternode.conf in the data directory of your install.
The new masternode.conf format consists of a space seperated text file. Each line consisting of an alias, address, private key, collateral output transaction and collateral output index.
Example:
```
mn1 127.0.0.2:19999 93HaYBVUCYjEMeeH1Y4sBGLALQZE1Yc1K64xiqgX37tGBDQL8Xg 2bcd3c84c84f87eaa86e4e56834c92927a07f9e18718810b92e0d0324456a67c 0
mn2 127.0.0.3:19999 93WaAb3htPJEV8E9aQcN23Jt97bPex7YvWfgMDTUdWJvzmrMqey aa9f1034d973377a5e733272c3d0eced1de22555ad45d6b24abadff8087948d4 0
mn3 127.0.0.4:19999 92Da1aYg6sbenP6uwskJgEY2XWB5LwJ7bXRqc3UPeShtHWJDjDv db478e78e3aefaa8c12d12ddd0aeace48c3b451a8b41c570d0ee375e2a02dfd9 1
```
In the example above, the collateral for mn1 consists of transaction:
http://test.explorer.darkcoin.fr/tx/2bcd3c84c84f87eaa86e4e56834c92927a07f9e18718810b92e0d0324456a67c
output index 0 has amount 1000
The following new RPC commands are supported:
* list-conf: shows the parsed masternode.conf
* start-alias \<alias\>
* stop-alias \<alias\>
* start-many
* stop-many
When using the multi masternode setup, it is advised to run the wallet with 'masternode=0' as it is not needed anymore.

View File

@ -51,6 +51,7 @@ BITCOIN_CORE_H = \
limitedmap.h \
main.h \
masternode.h \
masternodeconfig.h \
miner.h \
mruset.h \
netbase.h \
@ -147,6 +148,7 @@ libdarkcoin_common_a_SOURCES = \
core.cpp \
darksend.cpp \
masternode.cpp \
masternodeconfig.cpp \
instantx.cpp \
hash.cpp \
key.cpp \

View File

@ -4,285 +4,333 @@
#include "activemasternode.h"
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
//
// Bootup the masternode, look for a 1000DRK input and register on the network
//
void CActiveMasternode::RegisterAsMasterNode(bool stop)
void CActiveMasternode::ManageStatus()
{
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((Params().NetworkID() == CChainParams::TESTNET && masterNodeSignAddr.GetPort() != 19999) || (!(Params().NetworkID() == CChainParams::TESTNET) && masterNodeSignAddr.GetPort() != 9999)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Invalid port\n");
isCapableMasterNode = MASTERNODE_NOT_CAPABLE;
if((Params().NetworkID() == CChainParams::TESTNET && service.GetPort() != 19999) || (!(Params().NetworkID() == CChainParams::TESTNET) && service.GetPort() != 9999)) {
notCapableReason = "Invalid port: " + boost::lexical_cast<string>(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;
LogPrintf("CActiveMasternode::ManageStatus() - Is capable master node!\n");
masterNodeSignatureTime = GetAdjustedTime();
status = MASTERNODE_IS_CAPABLE;
notCapableReason = "";
std::string vchPubKey(pubkeyMasterNode.begin(), pubkeyMasterNode.end());
std::string vchPubKey2(pubkey2.begin(), pubkey2.end());
std::string strMessage = masterNodeSignAddr.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(protocolVersion);
pwalletMain->LockCoin(vin.prevout);
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, SecretKey)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sign message failed\n");
return;
}
// send to all nodes
CPubKey pubKeyMasternode;
CKey keyMasternode;
if(!darkSendSigner.VerifyMessage(pubkeyMasterNode, vchMasterNodeSignature, strMessage, errorMessage)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Verify message failed\n");
return;
}
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);
}
return;
}
}
if(isCapableMasterNode != MASTERNODE_IS_CAPABLE && isCapableMasterNode != MASTERNODE_REMOTELY_ENABLED) return;
masterNodeSignatureTime = GetAdjustedTime();
std::string strMessage = masterNodeSignAddr.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + boost::lexical_cast<std::string>(stop);
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, key2)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sign message failed\n");
LogPrintf("Register::ManageStatus() - Error upon calling SetKey: %s\n", errorMessage.c_str());
return;
}
if(!darkSendSigner.VerifyMessage(pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Verify message failed\n");
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");
}
}
//send to all peers
if(!Dseep(errorMessage)) {
LogPrintf("CActiveMasternode::ManageStatus() - Error on Ping: %s", errorMessage.c_str());
}
}
// 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;
if(!darkSendSigner.SetKey(strKeyMasternode, errorMessage, keyMasternode, pubKeyMasternode)) {
LogPrintf("CActiveMasternode::StopMasterNode() - Error: %s\n", errorMessage.c_str());
return false;
}
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;
}
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<unsigned char> vchMasterNodeSignature;
std::string strMasterNodeSignMessage;
int64_t masterNodeSignatureTime = GetAdjustedTime();
std::string strMessage = service.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + boost::lexical_cast<std::string>(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;
}
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Masternode input = %s\n", vinMasternode.ToString().c_str());
if (stop) isCapableMasterNode = MASTERNODE_STOPPED;
//relay to all peers
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
pnode->PushMessage("dseep", vinMasternode, vchMasterNodeSignature, masterNodeSignatureTime, stop);
}
}
//
// 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;
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Address %s MasterNodePrivKey %s\n", strMasterNodeAddr.c_str(), strMasterNodePrivKey.c_str());
std::string errorMessage;
CKey key2;
CPubKey pubkey2;
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, key2, pubkey2))
{
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Invalid masternodeprivkey: '%s'\n", errorMessage.c_str());
// 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;
}
CService masterNodeSignAddr = CService(strMasterNodeAddr);
BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes){
if(mn.addr == masterNodeSignAddr){
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Address in use\n");
return false;
}
}
if((Params().NetworkID() == CChainParams::TESTNET && masterNodeSignAddr.GetPort() != 19999) || (!(Params().NetworkID() == CChainParams::TESTNET) && masterNodeSignAddr.GetPort() != 9999)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Invalid port\n");
return false;
}
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<std::string>(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(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);
}
//send to all peers
LogPrintf("CActiveMasternode::Dseep() - SendDarkSendElectionEntryPing vin = %s\n", vin.ToString().c_str());
SendDarkSendElectionEntryPing(vin, vchMasterNodeSignature, masterNodeSignatureTime, stop);
return true;
}
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;
if(!darkSendSigner.SetKey(strKeyMasternode, errorMessage, keyMasternode, pubKeyMasternode))
{
LogPrintf("CActiveMasternode::Register() - Error upon calling SetKey: %s\n", errorMessage.c_str());
return false;
}
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - No suitable vin found\n");
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<unsigned char> vchMasterNodeSignature;
std::string strMasterNodeSignMessage;
int64_t masterNodeSignatureTime = GetAdjustedTime();
std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end());
std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end());
std::string strMessage = service.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(PROTOCOL_VERSION);
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, keyCollateralAddress)) {
retErrorMessage = "sign message failed: " + errorMessage;
LogPrintf("CActiveMasternode::Register() - Error: %s\n", retErrorMessage.c_str());
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);
}
//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);
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, std::string strTxHash, std::string strOutputIndex) {
CScript pubScript;
// Find possible candidates
vector<COutput> possibleCoins = SelectCoinsMasternode();
COutput *selectedOutput;
// Find the vin
if(!strTxHash.empty()) {
// Let's find it
uint256 txHash(strTxHash);
int outputIndex = boost::lexical_cast<int>(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;
}
}
// At this point we have a selected output, retrieve the associated info
return GetVinFromOutput(*selectedOutput, vin, pubkey, secretKey);
}
bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey)
{
int64_t nValueIn = 0;
// Extract masternode vin information from output
bool CActiveMasternode::GetVinFromOutput(COutput out, CTxIn& vin, CPubKey& pubkey, CKey& secretKey) {
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;
}
vin = CTxIn(out.tx->GetHash(),out.i);
pubScript = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
CTxDestination address1;
ExtractDestination(pubScript, address1);
@ -303,16 +351,62 @@ bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secr
return true;
}
// get all possible outputs for running masternode
vector<COutput> CActiveMasternode::SelectCoinsMasternode()
{
CCoinControl *coinControl=NULL;
vector<COutput> vCoins;
vector<COutput> 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_t 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");

View File

@ -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
@ -19,36 +18,44 @@
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<unsigned char> vchMasterNodeSignature;
// Initialized while registering masternode
CTxIn vin;
CService service;
std::string masterNodeAddr;
CService masterNodeSignAddr;
int isCapableMasterNode;
int64_t 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<COutput> 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_t sigTime, CService& addr);
bool EnableHotColdMasterNode(CTxIn& vin, CService& addr);
};
#endif

View File

@ -11,6 +11,7 @@
#include "noui.h"
#include "ui_interface.h"
#include "util.h"
#include "masternodeconfig.h"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
@ -78,6 +79,9 @@ bool AppInit(int argc, char* argv[])
fprintf(stderr,"Error reading configuration file: %s\n", e.what());
return false;
}
masternodeConfig.read(GetMasternodeConfigFile());
// Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause)
if (!SelectParamsFromCommandLine()) {
fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");

View File

@ -110,7 +110,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;
@ -798,7 +798,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();
@ -1850,7 +1850,7 @@ bool CDarkSendPool::IsCompatibleWithSession(int64_t nDenom, CTransaction txColla
//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();
@ -2102,6 +2102,8 @@ void ThreadCheckDarkSendPool()
RenameThread("bitcoin-darksend");
unsigned int c = 0;
std::string errorMessage;
while (true)
{
c++;
@ -2150,16 +2152,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)

View File

@ -7,8 +7,8 @@
#define DARKSEND_H
#include "core.h"
#include "masternode.h"
#include "main.h"
#include "masternode.h"
#include "activemasternode.h"
class CTxIn;

View File

@ -1113,7 +1113,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."));

View File

@ -210,7 +210,7 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64_t 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)
{
@ -228,7 +228,7 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64_t nBlockHeight)
}
CConsensusVote ctx;
ctx.vinMasternode = activeMasternode.vinMasternode;
ctx.vinMasternode = activeMasternode.vin;
ctx.approved = approved;
ctx.txHash = tx.GetHash();
ctx.nBlockHeight = nBlockHeight;
@ -277,7 +277,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;
}

View File

@ -1,5 +1,3 @@
#include "masternode.h"
#include "activemasternode.h"
#include "darksend.h"
@ -164,10 +162,10 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream
mn.UpdateLastSeen(lastUpdated);
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 it matches our masternodeprivkey, then we've been remotely activated
if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){
activeMasternode.EnableHotColdMasterNode(vin, addr);
}
if(count == -1 && !isLocal)
RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion);
@ -196,6 +194,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;
@ -210,6 +210,7 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream
BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes) {
if(mn.vin.prevout == vin.prevout) {
// 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<std::string>(sigTime) + boost::lexical_cast<std::string>(stop);

32
src/masternodeconfig.cpp Normal file
View File

@ -0,0 +1,32 @@
#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());
continue;
}
add(alias, ip, privKey, txHash, outputIndex);
}
streamConfig.close();
}

102
src/masternodeconfig.h Normal file
View File

@ -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 <string>
#include <vector>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
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<CMasternodeEntry>();
}
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<CMasternodeEntry>& getEntries() {
return entries;
}
private:
std::vector<CMasternodeEntry> entries;
};
#endif /* SRC_MASTERNODECONFIG_H_ */

View File

@ -12,6 +12,7 @@
#ifdef ENABLE_WALLET
#include "wallet.h"
#endif
#include "masternode.h"
//////////////////////////////////////////////////////////////////////////////
//

View File

@ -1911,6 +1911,15 @@ void RelayDarkSendElectionEntry(const CTxIn vin, const CService addr, const std:
}
}
void SendDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector<unsigned char> vchSig, const int64_t nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64_t 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<unsigned char> vchSig, const int64_t nNow, const bool stop)
{
LOCK(cs_vNodes);
@ -1922,6 +1931,15 @@ void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vector<unsigned
}
}
void SendDarkSendElectionEntryPing(const CTxIn vin, const std::vector<unsigned char> vchSig, const int64_t 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);
@ -1931,7 +1949,6 @@ void RelayDarkSendCompletedTransaction(const int sessionID, const bool error, co
}
}
void CNode::RecordBytesRecv(uint64_t bytes)
{
LOCK(cs_totalBytesRecv);

View File

@ -764,7 +764,9 @@ void RelayDarkSendFinalTransaction(const int sessionID, const CTransaction& txNe
void RelayDarkSendIn(const std::vector<CTxIn>& in, const int64_t& nAmount, const CTransaction& txCollateral, const std::vector<CTxOut>& 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<unsigned char> vchSig, const int64_t nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64_t lastUpdated, const int protocolVersion);
void SendDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector<unsigned char> vchSig, const int64_t nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64_t lastUpdated, const int protocolVersion);
void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vector<unsigned char> vchSig, const int64_t nNow, const bool stop);
void SendDarkSendElectionEntryPing(const CTxIn vin, const std::vector<unsigned char> vchSig, const int64_t nNow, const bool stop);
void RelayDarkSendCompletedTransaction(const int sessionID, const bool error, const std::string errorMessage);
void RelayDarkSendMasterNodeContestant();

View File

@ -21,6 +21,7 @@
#include "paymentserver.h"
#include "walletmodel.h"
#endif
#include "masternodeconfig.h"
#include "init.h"
#include "main.h"
@ -533,6 +534,8 @@ int main(int argc, char *argv[])
return false;
}
masternodeConfig.read(GetMasternodeConfigFile());
/// 7. Determine network (and switch to network specific options)
// - Do not call Params() before this step
// - Do this after parsing the configuration file, as the network can be switched there

View File

@ -9,6 +9,7 @@
#include "init.h"
#include "masternode.h"
#include "activemasternode.h"
#include "masternodeconfig.h"
#include "rpcserver.h"
#include <boost/lexical_cast.hpp>
@ -83,6 +84,7 @@ Value getpoolinfo(const Array& params, bool fHelp)
return obj;
}
Value masternode(const Array& params, bool fHelp)
{
string strCommand;
@ -90,10 +92,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 <start|start-many|stop|list|count|debug|current|winners|genkey|enforce> passphrase\n");
"masternode <start|start-alias|start-many|stop|stop-alias|stop-many|list|list-conf|count|debug|current|winners|genkey|enforce> passphrase\n");
if (strCommand == "stop")
{
@ -115,15 +117,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<std::string>(successful) + " masternodes, failed to stop " +
boost::lexical_cast<std::string>(fail) + ", total " + boost::lexical_cast<std::string>(total)));
returnObj.push_back(Pair("detail", resultsObj));
return returnObj;
}
if (strCommand == "list")
{
std::string strCommand = "active";
@ -187,57 +300,139 @@ 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);
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";
}
}
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
mnEntries = masternodeConfig.getEntries();
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
Object resultsObj;
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
total++;
if(activeMasternode.RegisterAsMasterNodeRemoteOnly(a, b)){
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));
}
printf(" Successfully started %d masternodes, failed to start %d, total %d\n", successful, fail, total);
return "";
resultsObj.push_back(Pair("status", statusObj));
}
pwalletMain->Lock();
Object returnObj;
returnObj.push_back(Pair("overall", "Successfully started " + boost::lexical_cast<std::string>(successful) + " masternodes, failed to start " +
boost::lexical_cast<std::string>(fail) + ", total " + boost::lexical_cast<std::string>(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 +513,26 @@ Value masternode(const Array& params, bool fHelp)
}
}
if(strCommand == "list-conf")
{
std::vector<CMasternodeConfig::CMasternodeEntry> 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;
}

View File

@ -1033,6 +1033,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<string, string>& mapSettingsRet,
map<string, vector<string> >& mapMultiSettingsRet)
{

View File

@ -195,6 +195,7 @@ bool TryCreateDirectory(const boost::filesystem::path& p);
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);

View File

@ -10,10 +10,12 @@
#include "checkpoints.h"
#include "coincontrol.h"
#include "net.h"
#include "darksend.h"
#include <boost/algorithm/string/replace.hpp>
#include <openssl/rand.h>
using namespace std;
// Settings
@ -1246,25 +1248,6 @@ static void ApproximateBestSubset(vector<pair<int64_t, pair<const CWalletTx*,uns
}
}
/* select coins with 1 unspent output */
bool CWallet::SelectCoinsMasternode(CTxIn& vin, int64_t& nValueRet, CScript& pubScript) const
{
CCoinControl *coinControl=NULL;
vector<COutput> 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_t nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const

View File

@ -7,7 +7,6 @@
#define BITCOIN_WALLET_H
#include "core.h"
#include "darksend.h"
#include "crypter.h"
#include "key.h"
#include "keystore.h"