Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a masternode return of investment RPC #2933

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ BITCOIN_CORE_H = \
script/standard.h \
script/script_error.h \
serialize.h \
simpleroi.h \
shutdown.h \
span.h \
spork.h \
Expand Down Expand Up @@ -450,6 +451,7 @@ libbitcoin_wallet_a_SOURCES = \
crypter.cpp \
legacy/stakemodifier.cpp \
kernel.cpp \
simpleroi.cpp \
wallet/db.cpp \
wallet/fees.cpp \
wallet/init.cpp \
Expand Down
119 changes: 119 additions & 0 deletions src/simpleroi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// simpleroi.cpp
#include "simpleroi.h"
#include "chainparams.h"
#include "masternodeman.h"
#include <inttypes.h>
#include <univalue.h>
#include "validation.h"

const int CSimpRoiArgs::nStakeRoiHrs = 3; // 3 hour averaging for smooth stake values

int64_t CSimpleRoi::getTimeDiff(CSimpRoiArgs& csra, uint64_t n_blocks, int nHeight)
{
if (nHeight < n_blocks) n_blocks = nHeight;
csra.pb0 = chainActive[nHeight - n_blocks];
// return timeDiff
return csra.pb->GetBlockTime() - csra.pb0->GetBlockTime();
}

// returns count enabled or zero on error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// returns count enabled or zero on error
// returns count enabled or zero on error

This says it will return zero on error, but later it returns negative numbers on error

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see line 76

//int CSimpleRoi::getsroi(float * nMnRoi, float * nStakingRoi, float * nBlocksPerDay, CAmount * mnCoins, CAmount * stakedCoins)
int CSimpleRoi::getsroi(CSimpRoiArgs& csra)
{
csra.pb = chainActive.Tip();
if (!csra.pb || !csra.pb->nHeight) return 0;

// calculation values
int nHeight = csra.pb->nHeight; // height of tip
int nTargetSpacing = Params().GetConsensus().nTargetSpacing; // MINUTES per block in seconds
int nTimeSlotLength = Params().GetConsensus().nTimeSlotLength; // seconds for time slot
int64_t nTargetTimespan = Params().GetConsensus().TargetTimespan(nHeight); // MINUTES in seconds to measure 'hashes per sec'
// CAmount nMNCollateral = CMasternode::GetMasternodeNodeCollateral(nHeight); // masternode collateral
CAmount nMNCollateral = Params().GetConsensus().nMNCollateralAmt;
CAmount nMNreward = GetMasternodePayment(nHeight); // masternode reward
CAmount nBlockValue = GetBlockValue(nHeight); // block reward
CAmount nStakeReward = nBlockValue - nMNreward;
int nMNblocks = 2 * 1440 * 60; // 2 days for blocks per day average

// calculate network hashes per second over ~3 hours -- set above
// hours in sec / minutes in sec
uint64_t n_blocks = csra.nStakeRoiHrs * 3600 / nTargetSpacing;
int64_t timeDiff = getTimeDiff(csra, n_blocks, nHeight);
if (timeDiff <= 0) return -2; // no negative or divide by zero exceptions
arith_uint256 workDiff = csra.pb->nChainWork - csra.pb0->nChainWork;
int64_t nSmoothNetHashPS = (int64_t)(workDiff.getdouble() / timeDiff);
//LogPrintf("STAKE nb %d td %2" PRIu64 " smoothhash %4" PRId64 " \n", n_blocks, timeDiff, nSmoothNetHashPS);
// -----------------------------------------------------------------------
// calculate network hashes per second over TargetTimespan
n_blocks = nTargetTimespan / nTargetSpacing;
timeDiff = getTimeDiff(csra, n_blocks, nHeight);
if (timeDiff <= 0) return -1; // no negative or divide by zero exceptions
workDiff = csra.pb->nChainWork - csra.pb0->nChainWork;
int64_t networkHashPS = (int64_t)(workDiff.getdouble() / timeDiff);
//LogPrintf("STAKE nb %d td %2" PRIu64 " networkhsh %4" PRId64 " \n", n_blocks, timeDiff, networkHashPS);
// --------------------------------------------------------------------
// calculate total staked coins
csra.stakedCoins = (CAmount)(networkHashPS * nTimeSlotLength / 1000000);
// calculate smoothed staked coins
csra.smoothCoins = (CAmount)(nSmoothNetHashPS * nTimeSlotLength / 1000000);
// ----------------------------------------------------------------------------
// calculate average blocks per day
n_blocks = nMNblocks / nTargetSpacing;
timeDiff = getTimeDiff(csra, n_blocks, nHeight);
if (timeDiff <= 0) return -3; // no negative or divide by zero exceptions
// csra.nBlocksPerDay = (float)86400 * (n_blocks -1) / timeDiff; --- lattice correction is not needed
csra.nBlocksPerDay = (float)86400 * n_blocks / timeDiff;
// --------------------------------------------------------------
// calculate staking ROI -- StakedRewardsPerYear / stakedCoins
// csra.nStakingRoi = (float)(nStakeReward * csra.nBlocksPerDay * 365 / csra.stakedCoins);
csra.nStakingRoi = (float)(nStakeReward * csra.nBlocksPerDay * 365 / (networkHashPS * nTimeSlotLength));
// calculate smooth staking ROI
// csra.nSmoothRoi = (float)(nStakeReward * csra.nBlocksPerDay * 365 / csra.smoothCoins);
csra.nSmoothRoi = (float)(nStakeReward * csra.nBlocksPerDay * 365 / (nSmoothNetHashPS * nTimeSlotLength));
// -----------------------------------------------------------------------------------------------------------
// calculate total masternode collateral
int nEnabled = mnodeman.CountEnabled();
if (nEnabled <= 0) return 0;
csra.mnCoins = (CAmount)(nMNCollateral * nEnabled / 100000000);
// ---------------------------------------------------------------
// calculate masternode ROI -- reward * blocks_per_day * 365 / collateral
csra.nMnRoi = (float)(nMNreward * csra.nBlocksPerDay * 36500 / (nMNCollateral * nEnabled));
// return enabled masternodes
return nEnabled;
}

// convert COIN to string with thousands comma seperators
std::string CSimpleRoi::CAmount2Kwithcommas(CAmount koin) {
std::string s = strprintf("%" PRId64, (int64_t)koin);
int j = 0;
std::string k;

for (int i = s.size() - 1; i >= 0;) {
k.push_back(s[i]);
j++;
i--;
if (j % 3 == 0 && i >= 0) k.push_back(',');
}
reverse(k.begin(), k.end());
return k;
};


bool CSimpleRoi::generateROI(UniValue& roi, std::string& sGerror)
{
CSimpRoiArgs csra;
int nEnabled = getsroi(csra);
if (nEnabled <= 0) {
sGerror = strprintf("Not enough valid data %d", nEnabled);
return false;
}
roi.pushKV(strprintf("%d hour avg ROI", csra.nStakeRoiHrs), strprintf("%4.1f%%", csra.nSmoothRoi));
roi.pushKV(strprintf("%2d min stk ROI", Params().GetConsensus().TargetTimespan(csra.pb->nHeight) / 60), strprintf("%4.1f%%", csra.nStakingRoi));
roi.pushKV("network stake", CAmount2Kwithcommas(csra.smoothCoins));
roi.pushKV("--------------","--------------");
roi.pushKV("masternode ROI", strprintf("%4.1f%%", csra.nMnRoi));
roi.pushKV("tot collateral", CAmount2Kwithcommas(csra.mnCoins));
roi.pushKV("enabled nodes", strprintf("%d", nEnabled));
roi.pushKV("blocks per day", strprintf("%4.1f", csra.nBlocksPerDay));
return true;
}
39 changes: 39 additions & 0 deletions src/simpleroi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// simpleroi.h
#ifndef CSIMPLE_ROI_H
#define CSIMPLE_ROI_H

#include "amount.h"
#include "chain.h"
#include <string>
#include <univalue.h>

class CSimpRoiArgs
{
public: // things passed between functions
float nMnRoi;
float nStakingRoi;
float nSmoothRoi;
float nBlocksPerDay;
CBlockIndex *pb;
CBlockIndex *pb0;
CAmount mnCoins;
CAmount stakedCoins;
CAmount smoothCoins;
static const int nStakeRoiHrs; // initialized in simpleroi.cpp
};

class CSimpleRoi
{
public:
bool generateROI(UniValue& roi, std::string& sGerror);

private:
// returns timeDiff over nBlocks
int64_t getTimeDiff(CSimpRoiArgs& csra, uint64_t nblocks, int nHeight);
// convert COIN to string with thousands comma seperators
std::string CAmount2Kwithcommas(CAmount koin);
// returns enabled masternode, populates CsimpRoiArgs
int getsroi(CSimpRoiArgs& csra);
};

#endif // CSIMPLE_ROI_H
34 changes: 34 additions & 0 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "sapling/key_io_sapling.h"
#include "sapling/sapling_operation.h"
#include "shutdown.h"
#include "simpleroi.h"
#include "spork.h"
#include "timedata.h"
#include "utilmoneystr.h"
Expand Down Expand Up @@ -4747,6 +4748,38 @@ UniValue rescanblockchain(const JSONRPCRequest& request)
return response;
}

UniValue getroi(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 0) {
int nRoiMinutes = Params().GetConsensus().nTargetTimespan; // defalut if no Tip()
CSimpRoiArgs csra;
CBlockIndex * pb = chainActive.Tip();
if (pb && pb->nHeight) {
nRoiMinutes = Params().GetConsensus().TargetTimespan(pb->nHeight);
}
std::string sTopline = strprintf(" \"%d hour avg ROI: nnnn.n%%\", smoothed staking ROI\n", csra.nStakeRoiHrs);
std::string sLine2 = strprintf(" \"%2d min stk ROI: nnnn.n%%\", real time staking ROI\n", nRoiMinutes / 60);
throw std::runtime_error(
"getroi\n" +
sTopline +
sLine2 +
" \"tot stake coin: nnnnnnnn\", estimate of total staked coins\n"
"\n"
" \"masternode ROI: nnnn.n%\", masternode ROI\n"
" \"tot collateral: nnnnnnnn\", total masternode collateral\n"
" \"enabled nodes: nnnn\", number of enabled masternodes\n"
" \"blocks per day: nnnn.n\", number of blocks per day\n"
"\n"
);
}
CSimpleRoi csimproi;
UniValue roi(UniValue::VOBJ);
std::string sGerror;

if (csimproi.generateROI(roi, sGerror)) return roi;
throw std::runtime_error(sGerror);
}

extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
extern UniValue importprivkey(const JSONRPCRequest& request);
Expand Down Expand Up @@ -4789,6 +4822,7 @@ static const CRPCCommand commands[] =
{ "wallet", "getnewstakingaddress", &getnewstakingaddress, true, {"label"} },
{ "wallet", "getrawchangeaddress", &getrawchangeaddress, true, {} },
{ "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, {"address","minconf"} },
{ "wallet", "getroi", &getroi, false, {} },
{ "wallet", "gettransaction", &gettransaction, false, {"txid","include_watchonly"} },
{ "wallet", "getstakesplitthreshold", &getstakesplitthreshold, false, {} },
{ "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, {} },
Expand Down
Loading