21 #include <QHostAddress>
33 int end =
nodes.size();
38 if (!mne.castOutputIndex(nIndex))
41 CTxIn txIn(txHash, uint32_t(nIndex));
47 nodes.insert(QString::fromStdString(mne.getAlias()), std::make_pair(QString::fromStdString(mne.getIp()), pmn));
52 Q_EMIT dataChanged(
index(0, 0, QModelIndex()),
index(end, 5, QModelIndex()) );
77 bool isAvailable = rec;
78 int row =
index.row();
79 if (role == Qt::DisplayRole || role == Qt::EditRole) {
80 switch (
index.column()) {
82 return nodes.uniqueKeys().value(row);
84 return nodes.values().value(row).first;
86 return (isAvailable) ? QString::fromStdString(
nodes.values().value(row).second->pubKeyMasternode.GetHash().GetHex()) :
"Not available";
90 return (isAvailable) ? QString::number(rec->
vin.
prevout.
n) :
"Not available";
92 std::pair<QString, CMasternode*> pair =
nodes.values().value(row);
93 std::string status =
"MISSING";
95 status = pair.second->Status();
101 if (status ==
"REMOVE" && !pair.second->pubKeyCollateralAddress.IsValid()) {
105 return QString::fromStdString(status);
111 return QString::fromStdString(mne.getPrivKey());
115 return "Not available";
128 std::pair<QString, CMasternode*> pair =
nodes.values().value(row);
131 return createIndex(row, column,
data);
132 }
else if (!pair.first.isEmpty()) {
133 return createIndex(row, column,
nullptr);
135 return QModelIndex();
142 QString alias = modelIndex.data(Qt::DisplayRole).toString();
143 int idx = modelIndex.row();
144 beginRemoveRows(QModelIndex(), idx, idx);
147 Q_EMIT dataChanged(
index(idx, 0, QModelIndex()),
index(idx, 5, QModelIndex()) );
153 beginInsertRows(QModelIndex(),
nodes.size(),
nodes.size());
159 nodes.insert(QString::fromStdString(mne->
getAlias()), std::make_pair(QString::fromStdString(mne->
getIp()), pmn));
166 QMap<QString, std::pair<QString, CMasternode*>>::const_iterator it =
nodes.find(mnAlias);
167 if (it !=
nodes.end())
return it.value().second->GetActiveState();
168 throw std::runtime_error(std::string(
"Masternode alias not found"));
185 QMap<QString, std::pair<QString, CMasternode*>>::const_iterator it =
nodes.find(mnAlias);
187 throw std::runtime_error(std::string(
"Masternode alias not found"));
211 const QString& alias,
219 QList<SendCoinsRecipient> recipients;
220 recipients.append(sendCoinsRecipient);
226 QString returnMsg = tr(
"Unknown error");
239 ret_error = tr(
"Prepare master node failed.\n\n%1\n").arg(returnMsg);
248 ret_error = tr(
"Cannot send collateral transaction.\n\n%1").arg(returnMsg);
254 std::string txID = walletTx->GetHash().GetHex();
256 for (
int i=0; i < (int)walletTx->vout.size(); i++) {
257 const CTxOut& out = walletTx->vout[i];
263 if (indexOut == -1) {
264 ret_error = tr(
"Invalid collateral output index");
268 ret_outpoint =
COutPoint(walletTx->GetHash(), indexOut);
287 std::string* aliasFilter, std::string* error_ret)
292 QString mnAlias = QString::fromStdString(mne.getAlias());
303 }
else if (*aliasFilter != mne.getAlias()){
310 if (error_ret) *error_ret = ret_str;
319 const std::string& alias,
320 std::string& serviceAddr,
321 const std::string& port,
322 const std::string& mnKeyString,
327 std::string strConfFile = strConfFileQt.toStdString();
328 std::string strDataDir =
GetDataDir().string();
329 fs::path conf_file_path(strConfFile);
330 if (strConfFile != conf_file_path.filename().string()) {
331 throw std::runtime_error(
strprintf(
_(
"%s %s resides outside data directory %s"), strConfFile, strConfFile, strDataDir));
334 fs::path pathBootstrap =
GetDataDir() / strConfFile;
335 if (!fs::exists(pathBootstrap)) {
336 ret_error = tr(
"%1 file doesn't exists").arg(strConfFileQt);
343 if (!streamConfig.good()) {
344 ret_error = tr(
"Invalid %1 file").arg(strConfFileQt);
349 std::string lineCopy;
350 for (std::string line; std::getline(streamConfig, line); linenumber++) {
351 if (line.empty())
continue;
353 std::istringstream iss(line);
354 std::string comment, alias,
ip, privKey, txHash, outputIndex;
356 if (iss >> comment) {
357 if (comment.at(0) ==
'#')
continue;
362 if (!(iss >> alias >>
ip >> privKey >> txHash >> outputIndex)) {
365 if (!(iss >> alias >>
ip >> privKey >> txHash >> outputIndex)) {
366 streamConfig.close();
367 ret_error = tr(
"Error parsing %1 file").arg(strConfFileQt);
371 lineCopy += line +
"\n";
374 if (lineCopy.empty()) {
375 lineCopy =
"# Masternode config file\n"
376 "# Format: alias IP:port masternodeprivkey collateral_output_txid collateral_output_index\n"
377 "# Example: mn1 127.0.0.2:51472 93HaYBVUCYjEMeeH1Y4sBGLALQZE1Yc1K64xiqgX37tGBDQL8Xg 2bcd3c84c84f87eaa86e4e56834c92927a07f9e18718810b92e0d0324456a67c 0"
382 streamConfig.close();
385 std::string indexOutStr = std::to_string(collateralOut.
n);
388 QHostAddress hostAddress(QString::fromStdString(serviceAddr));
389 QAbstractSocket::NetworkLayerProtocol layerProtocol = hostAddress.protocol();
390 if (layerProtocol == QAbstractSocket::IPv6Protocol) {
391 serviceAddr =
"["+serviceAddr+
"]";
395 FILE* configFile =
fopen(pathConfigFile.string().c_str(),
"w");
396 lineCopy += alias+
" "+serviceAddr+
":"+port+
" "+mnKeyString+
" "+txID+
" "+indexOutStr+
"\n";
397 fwrite(lineCopy.c_str(), std::strlen(lineCopy.c_str()), 1, configFile);
401 if (fs::exists(pathOldConfFile)) {
402 fs::remove(pathOldConfFile);
404 rename(pathMasternodeConfigFile, pathOldConfFile);
407 rename(pathConfigFile, pathNewConfFile);
409 auto ret_mn_entry =
masternodeConfig.
add(alias, serviceAddr+
":"+port, mnKeyString, txID, indexOutStr);
417 bool MNModel::removeLegacyMN(
const std::string& alias_to_remove,
const std::string& tx_id,
unsigned int out_index, QString& ret_error)
420 std::string strConfFile = strConfFileQt.toStdString();
421 std::string strDataDir =
GetDataDir().string();
422 fs::path conf_file_path(strConfFile);
423 if (strConfFile != conf_file_path.filename().string()) {
424 throw std::runtime_error(
strprintf(
_(
"%s %s resides outside data directory %s"), strConfFile, strConfFile, strDataDir));
427 fs::path pathBootstrap =
GetDataDir() / strConfFile;
428 if (!fs::exists(pathBootstrap)) {
429 ret_error = tr(
"%1 file doesn't exists").arg(strConfFileQt);
436 if (!streamConfig.good()) {
437 ret_error = tr(
"Invalid %1 file").arg(strConfFileQt);
441 int lineNumToRemove = -1;
443 std::string lineCopy;
444 for (std::string line; std::getline(streamConfig, line); linenumber++) {
445 if (line.empty())
continue;
447 std::istringstream iss(line);
448 std::string comment, alias,
ip, privKey, txHash, outputIndex;
450 if (iss >> comment) {
451 if (comment.at(0) ==
'#')
continue;
456 if (!(iss >> alias >>
ip >> privKey >> txHash >> outputIndex)) {
459 if (!(iss >> alias >>
ip >> privKey >> txHash >> outputIndex)) {
460 streamConfig.close();
461 ret_error = tr(
"Error parsing %1 file").arg(strConfFileQt);
466 if (alias_to_remove == alias) {
467 lineNumToRemove = linenumber;
469 lineCopy += line +
"\n";
473 if (lineCopy.empty()) {
474 lineCopy =
"# Masternode config file\n"
475 "# Format: alias IP:port masternodeprivkey collateral_output_txid collateral_output_index\n"
476 "# Example: mn1 127.0.0.2:51472 93HaYBVUCYjEMeeH1Y4sBGLALQZE1Yc1K64xiqgX37tGBDQL8Xg 2bcd3c84c84f87eaa86e4e56834c92927a07f9e18718810b92e0d0324456a67c 0\n";
479 streamConfig.close();
481 if (lineNumToRemove == -1) {
482 ret_error = tr(
"MN alias %1 not found in %2 file").arg(QString::fromStdString(alias_to_remove)).arg(strConfFileQt);
489 fwrite(lineCopy.c_str(), std::strlen(lineCopy.c_str()), 1, configFile);
493 if (fs::exists(pathOldConfFile)) {
494 fs::remove(pathOldConfFile);
496 rename(pathMasternodeConfigFile, pathOldConfFile);
499 rename(pathConfigFile, pathNewConfFile);
int64_t CAmount
Amount in PIV (Can be negative)
const CChainParams & Params()
Return the currently selected parameters.
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string (with unit)
bool EnableHotColdMasterNode(CTxIn &vin, CService &addr)
Enable cold wallet mode (run a Masternode with no funds)
const Consensus::Params & GetConsensus() const
MessageBoxFlags
Flags for CClientUIInterface::ThreadSafeMessageBox.
static bool Create(const CTxIn &vin, const CService &service, const CKey &keyCollateralAddressNew, const CPubKey &pubKeyCollateralAddressNew, const CKey &keyMasternodeNew, const CPubKey &pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet)
Create Masternode broadcast, needs to be relayed manually after that.
const std::string & getTxHash() const
const std::string & getOutputIndex() const
const std::string & getIp() const
bool castOutputIndex(int &n) const
const std::string & getPrivKey() const
const std::string & getAlias() const
void remove(std::string alias)
CMasternodeConfig::CMasternodeEntry * add(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex)
std::vector< CMasternodeEntry > getEntries()
CPubKey GetPubKey() const
void UpdateMasternodeList(CMasternodeBroadcast &mnb)
Update masternode list and maps using provided CMasternodeBroadcast.
CMasternode * Find(const COutPoint &collateralOut)
Find an entry.
An outpoint - a combination of a transaction hash and an index n into its vout.
An input of a transaction.
An output of a transaction.
int getMNState(const QString &mnAlias)
QMap< QString, std::pair< QString, CMasternode * > > nodes
bool startLegacyMN(const CMasternodeConfig::CMasternodeEntry &mne, int chainHeight, std::string &strError)
bool createMNCollateral(const QString &alias, const QString &addr, COutPoint &ret_outpoint, QString &ret_error)
bool removeMn(const QModelIndex &index)
bool isMNActive(const QString &mnAlias)
CAmount getMNCollateralRequiredAmount()
static bool validateMNIP(const QString &addrStr)
void startAllLegacyMNs(bool onlyMissing, int &amountOfMnFailed, int &amountOfMnStarted, std::string *aliasFilter=nullptr, std::string *error_ret=nullptr)
int rowCount(const QModelIndex &parent=QModelIndex()) const override
WalletModel * walletModel
bool addMn(CMasternodeConfig::CMasternodeEntry *entry)
bool isMNsNetworkSynced()
CMasternodeConfig::CMasternodeEntry * createLegacyMN(COutPoint &collateralOut, const std::string &alias, std::string &serviceAddr, const std::string &port, const std::string &mnKeyString, QString &ret_error)
int getMasternodeCollateralMinConf()
QMap< std::string, bool > collateralTxAccepted
CCoinControl * coinControl
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
bool removeLegacyMN(const std::string &alias_to_remove, const std::string &tx_id, unsigned int out_index, QString &ret_error)
bool isMNInactive(const QString &mnAlias)
QModelIndex index(int row, int column, const QModelIndex &parent) const override
@ WAS_COLLATERAL_ACCEPTED
@ ALIAS
User specified MN alias.
void setCoinControl(CCoinControl *coinControl)
bool isMNCollateralMature(const QString &mnAlias)
int getLastBlockProcessedNum() const
void lockCoin(uint256 hash, unsigned int n, bool isTransparent=true)
void unlockCoin(uint256 hash, unsigned int n, bool isTransparent=true)
SendCoinsReturn sendCoins(WalletModelTransaction &transaction)
OptionsModel * getOptionsModel()
int getWalletTxDepth(const uint256 &txHash) const
SendCoinsReturn prepareTransaction(WalletModelTransaction *transaction, const CCoinControl *coinControl=nullptr, bool fIncludeDelegations=true)
Data model for a walletmodel transaction.
CTransactionRef & getTransaction()
CAmount getTransactionFee()
std::string ToString() const
std::string GetHex() const
CMasternodeConfig masternodeConfig
CMasternodeMan mnodeman
Masternode manager.
CActiveMasternode activeMasternode
Keep track of the active Masternode.
QString ProcessSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, WalletModel *walletModel, CClientUIInterface::MessageBoxFlags &informType, const QString &msgArg, bool fPrepare)
FILE * fopen(const fs::path &p, const char *mode)
bool validateMasternodeIP(const std::string &addrStr)
int MasternodeCollateralMinConf() const
fs::path AbsPathForConfigVal(const fs::path &path, bool net_specific)
const fs::path & GetDataDir(bool fNetSpecific)
const char *const PIVX_MASTERNODE_CONF_FILENAME
fs::path GetMasternodeConfigFile()
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a Optional result.
TierTwoSyncState g_tiertwo_sync_state
std::shared_ptr< const CTransaction > CTransactionRef
uint256 uint256S(const char *str)