Skip to content

Commit

Permalink
update PR #2929 simpleroi
Browse files Browse the repository at this point in the history
  • Loading branch information
techy2 committed Jul 30, 2024
1 parent 9bc2ee2 commit 9515e32
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 0 deletions.
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
//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

0 comments on commit 9515e32

Please sign in to comment.