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

Guarding and encapsulating properly CStakerStatus inside the wallet. #2131

Closed
Closed
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
11 changes: 6 additions & 5 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,13 +543,14 @@ bool fStakeableCoins = false;

void CheckForCoins(CWallet* pwallet, std::vector<CStakeableOutput>* availableCoins)
{
if (!pwallet || !pwallet->pStakerStatus)
if (!pwallet || !pwallet->HasStakingStatus())
return;

// control the amount of times the client will check for mintable coins (every block)
{
WAIT_LOCK(g_best_block_mutex, lock);
if (g_best_block == pwallet->pStakerStatus->GetLastHash())
Optional<uint256> opLastHash = pwallet->GetStakingStatusLastHash();
if (!opLastHash || g_best_block == *opLastHash)
Comment on lines +552 to +553

Choose a reason for hiding this comment

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

nit:
we have already checked that pwallet->HasStakingStatus(), so we know that GetStakingStatusLastHash() returns a non-nullopt. So we can just do

Suggested change
Optional<uint256> opLastHash = pwallet->GetStakingStatusLastHash();
if (!opLastHash || g_best_block == *opLastHash)
if (g_best_block == *pwallet->GetStakingStatusLastHash())

or, alternatively, we can keep this as is, and remove the previous call to pwallet->HasStakingStatus() at line 546.

return;
}
fStakeableCoins = pwallet->StakeableCoins(availableCoins);
Expand Down Expand Up @@ -597,9 +598,9 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake)
}

//search our map of hashed blocks, see if bestblock has been hashed yet
if (pwallet->pStakerStatus &&
pwallet->pStakerStatus->GetLastHash() == pindexPrev->GetBlockHash() &&
pwallet->pStakerStatus->GetLastTime() >= GetCurrentTimeSlot()) {
if (pwallet->HasStakingStatus() &&
*pwallet->GetStakingStatusLastHash() == pindexPrev->GetBlockHash() &&
*pwallet->GetStakingStatusLastTime() >= GetCurrentTimeSlot()) {
MilliSleep(2000);
continue;
}
Expand Down
11 changes: 6 additions & 5 deletions src/qt/pivx/topbar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,12 +443,13 @@ void TopBar::setStakingStatusActive(bool fActive)
}
void TopBar::updateStakingStatus()
{
setStakingStatusActive(walletModel &&
!walletModel->isWalletLocked() &&
walletModel->isStakingStatusActive());
if (walletModel && !walletModel->isShutdownRequested()) {
setStakingStatusActive(!walletModel->isWalletLocked() &&
walletModel->isStakingStatusActive());

// Taking advantage of this timer to update Tor status if needed.
updateTorIcon();
// Taking advantage of this timer to update Tor status if needed.
updateTorIcon();
}
}

void TopBar::setNumConnections(int count)
Expand Down
8 changes: 7 additions & 1 deletion src/qt/walletmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "optionsmodel.h"
#include "recentrequeststablemodel.h"
#include "transactiontablemodel.h"
#include "init.h" // for ShutdownRequested(). Future: move to an interface wrapper

#include "base58.h"
#include "coincontrol.h"
Expand Down Expand Up @@ -67,6 +68,11 @@ bool WalletModel::isRegTestNetwork() const
return Params().IsRegTestNet();
}

bool WalletModel::isShutdownRequested()
{
return ShutdownRequested();
}

bool WalletModel::isColdStakingNetworkelyEnabled() const
{
return !sporkManager.IsSporkActive(SPORK_19_COLDSTAKING_MAINTENANCE);
Expand All @@ -84,7 +90,7 @@ bool WalletModel::isSaplingEnforced() const

bool WalletModel::isStakingStatusActive() const
{
return wallet && wallet->pStakerStatus && wallet->pStakerStatus->IsActive();
return wallet && wallet->IsStakingActive();
}

bool WalletModel::isHDEnabled() const
Expand Down
1 change: 1 addition & 0 deletions src/qt/walletmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class WalletModel : public QObject

bool isTestNetwork() const;
bool isRegTestNetwork() const;
bool isShutdownRequested();
/** Whether cold staking is enabled or disabled in the network **/
bool isColdStakingNetworkelyEnabled() const;
bool isSaplingInMaintenance() const;
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ UniValue getinfo(const JSONRPCRequest& request)
if (pwalletMain) {
obj.pushKV("walletversion", pwalletMain->GetVersion());
obj.pushKV("balance", ValueFromAmount(pwalletMain->GetAvailableBalance()));
obj.pushKV("staking status", (pwalletMain->pStakerStatus->IsActive() ? "Staking Active" : "Staking Not Active"));
obj.pushKV("staking status", (pwalletMain->IsStakingActive() ? "Staking Active" : "Staking Not Active"));
}
#endif
obj.pushKV("blocks", (int)chainActive.Height());
Expand Down
4 changes: 2 additions & 2 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3683,7 +3683,7 @@ UniValue getstakingstatus(const JSONRPCRequest& request)
{
LOCK2(cs_main, &pwalletMain->cs_wallet);
UniValue obj(UniValue::VOBJ);
obj.pushKV("staking_status", pwalletMain->pStakerStatus->IsActive());
obj.pushKV("staking_status", pwalletMain->IsStakingActive());
obj.pushKV("staking_enabled", gArgs.GetBoolArg("-staking", DEFAULT_STAKING));
bool fColdStaking = gArgs.GetBoolArg("-coldstaking", true);
obj.pushKV("coldstaking_enabled", fColdStaking);
Expand All @@ -3695,7 +3695,7 @@ UniValue getstakingstatus(const JSONRPCRequest& request)
obj.pushKV("stakeablecoins", (int)vCoins.size());
obj.pushKV("stakingbalance", ValueFromAmount(pwalletMain->GetStakingBalance(fColdStaking)));
obj.pushKV("stakesplitthreshold", ValueFromAmount(pwalletMain->nStakeSplitThreshold));
CStakerStatus* ss = pwalletMain->pStakerStatus;
CStakerStatus* ss = pwalletMain->GetStakingStatus();
if (ss) {
obj.pushKV("lastattempt_age", (int)(GetTime() - ss->GetLastTime()));
obj.pushKV("lastattempt_depth", (chainActive.Height() - ss->GetLastHeight()));
Expand Down
57 changes: 55 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4280,7 +4280,6 @@ CWallet::CWallet(std::string strWalletFileIn)
CWallet::~CWallet()
{
delete pwalletdbEncryption;
delete pStakerStatus;
}

void CWallet::SetNull()
Expand All @@ -4300,7 +4299,7 @@ void CWallet::SetNull()
if (pStakerStatus) {
pStakerStatus->SetNull();
} else {
pStakerStatus = new CStakerStatus();
pStakerStatus = MakeUnique<CStakerStatus>();
}
// Stake split threshold
nStakeSplitThreshold = DEFAULT_STAKE_SPLIT_THRESHOLD;
Expand Down Expand Up @@ -4739,3 +4738,57 @@ const CWDestination* CAddressBookIterator::GetDestKey()
CStakeableOutput::CStakeableOutput(const CWalletTx* txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn,
const CBlockIndex*& _pindex) : COutput(txIn, iIn, nDepthIn, fSpendableIn, fSolvableIn),
pindex(_pindex) {}


//////////////// Staking status getters ////////////////

bool CWallet::HasStakingStatus()
{
return pStakerStatus != nullptr;
}

bool CWallet::IsStakingActive()
{
return HasStakingStatus() ? pStakerStatus->IsActive() : false;
}

Optional<uint256> CWallet::GetStakingStatusLastHash()
{
return HasStakingStatus() ? Optional<uint256>(pStakerStatus->GetLastHash()) : nullopt;
}

Optional<int64_t> CWallet::GetStakingStatusLastTime()
{
return HasStakingStatus() ? Optional<int64_t>(pStakerStatus->GetLastTime()) : nullopt;
}

CStakerStatus* CWallet::GetStakingStatus()
{
return HasStakingStatus() ? pStakerStatus.get() : nullptr;
}

const CBlockIndex* CStakerStatus::GetLastTip() { LOCK(cs_stakerStatus); return tipBlock; }
uint256 CStakerStatus::GetLastHash() { LOCK(cs_stakerStatus); return (GetLastTip() == nullptr ? UINT256_ZERO : GetLastTip()->GetBlockHash()); }
int CStakerStatus::GetLastHeight() { LOCK(cs_stakerStatus); return (GetLastTip() == nullptr ? 0 : GetLastTip()->nHeight); }
int CStakerStatus::GetLastCoins() { LOCK(cs_stakerStatus); return nCoins; }
int CStakerStatus::GetLastTries() { LOCK(cs_stakerStatus); return nTries; }
int64_t CStakerStatus::GetLastTime() { LOCK(cs_stakerStatus); return nTime; }
// Set
void CStakerStatus::SetLastCoins(const int coins) { LOCK(cs_stakerStatus); nCoins = coins; }
void CStakerStatus::SetLastTries(const int tries) { LOCK(cs_stakerStatus); nTries = tries; }
void CStakerStatus::SetLastTip(const CBlockIndex* lastTip) { LOCK(cs_stakerStatus); tipBlock = lastTip; }
void CStakerStatus::SetLastTime(const uint64_t lastTime) { LOCK(cs_stakerStatus); nTime = lastTime; }
void CStakerStatus::SetNull()
{
LOCK(cs_stakerStatus);
nCoins = 0;
nTries = 0;
SetLastCoins(0);
SetLastTries(0);
tipBlock = nullptr;
nTime = 0;
}
// Check whether staking status is active (last attempt earlier than 30 seconds ago)
bool CStakerStatus::IsActive() { LOCK(cs_stakerStatus); return (nTime + 30) >= GetTime(); }

//////////////// End staking status getters ////////////////
44 changes: 24 additions & 20 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,29 +185,25 @@ class CStakerStatus
int64_t nTime{0};
int nTries{0};
int nCoins{0};
RecursiveMutex cs_stakerStatus;

public:
explicit CStakerStatus() {}
// Get
const CBlockIndex* GetLastTip() const { return tipBlock; }
uint256 GetLastHash() const { return (GetLastTip() == nullptr ? UINT256_ZERO : GetLastTip()->GetBlockHash()); }
int GetLastHeight() const { return (GetLastTip() == nullptr ? 0 : GetLastTip()->nHeight); }
int GetLastCoins() const { return nCoins; }
int GetLastTries() const { return nTries; }
int64_t GetLastTime() const { return nTime; }
const CBlockIndex* GetLastTip();
uint256 GetLastHash();
int GetLastHeight();
int GetLastCoins();
int GetLastTries();
int64_t GetLastTime();
// Set
void SetLastCoins(const int coins) { nCoins = coins; }
void SetLastTries(const int tries) { nTries = tries; }
void SetLastTip(const CBlockIndex* lastTip) { tipBlock = lastTip; }
void SetLastTime(const uint64_t lastTime) { nTime = lastTime; }
void SetNull()
{
SetLastCoins(0);
SetLastTries(0);
SetLastTip(nullptr);
SetLastTime(0);
}
void SetLastCoins(const int coins);
void SetLastTries(const int tries);
void SetLastTip(const CBlockIndex* lastTip);
void SetLastTime(const uint64_t lastTime);
void SetNull();
// Check whether staking status is active (last attempt earlier than 30 seconds ago)
bool IsActive() const { return (nTime + 30) >= GetTime(); }
bool IsActive();
};

struct CRecipient
Expand Down Expand Up @@ -283,6 +279,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
int64_t nNextResend;
int64_t nLastResend;

// Staker status (last hashed block and time)
std::unique_ptr<CStakerStatus> pStakerStatus;

/**
* Used to keep track of spent outpoints, and
* detect and report conflicts (double-spends or
Expand Down Expand Up @@ -368,8 +367,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
CAmount nStakeSplitThreshold;
// minimum value allowed for nStakeSplitThreshold (customizable with -minstakesplit flag)
static CAmount minStakeSplitThreshold;
// Staker status (last hashed block and time)
CStakerStatus* pStakerStatus = nullptr;

// User-defined fee PIV/kb
bool fUseCustomFee;
Expand Down Expand Up @@ -764,6 +761,13 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
/* Wallets parameter interaction */
static bool ParameterInteraction();

// Staking status getters
bool HasStakingStatus();
bool IsStakingActive();
Optional<uint256> GetStakingStatusLastHash();
Optional<int64_t> GetStakingStatusLastTime();
CStakerStatus* GetStakingStatus();

/**
* Wallet post-init setup
* Gives the wallet a chance to register repetitive tasks and complete post-init tasks
Expand Down