Skip to content
Merged
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
19 changes: 0 additions & 19 deletions divi/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -823,25 +823,6 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
return nSigOps;
}

int GetInputAgeIX(uint256 nTXHash, CTxIn& vin)
{
int sigs = 0;
int nResult = GetInputAge(vin);
if (nResult < 0) nResult = 0;

if (nResult < 6) {
std::map<uint256, CTransactionLock>::iterator i = mapTxLocks.find(nTXHash);
if (i != mapTxLocks.end()) {
sigs = (*i).second.CountSignatures();
}
if (sigs >= SWIFTTX_SIGNATURES_REQUIRED) {
return nSwiftTXDepth + nResult;
}
}

return -1;
}

int GetIXConfirmations(uint256 nTXHash)
{
int sigs = 0;
Expand Down
1 change: 0 additions & 1 deletion divi/src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ void FlushStateToDisk();
/** (try to) add transaction to memory pool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree, bool* pfMissingInputs, bool fRejectInsaneFee = false, bool ignoreFees = false);

int GetInputAgeIX(uint256 nTXHash, CTxIn& vin);
int GetIXConfirmations(uint256 nTXHash);

struct CNodeStateStats {
Expand Down
151 changes: 88 additions & 63 deletions divi/src/masternode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,7 @@ CMasternode::CMasternode()
activeState = MASTERNODE_ENABLED;
sigTime = GetAdjustedTime();
lastPing = CMasternodePing();
cacheInputAge = 0;
cacheInputAgeBlock = 0;
collateralBlock.SetNull();
allowFreeTx = true;
nActiveState = MASTERNODE_ENABLED;
protocolVersion = PROTOCOL_VERSION;
Expand All @@ -144,8 +143,7 @@ CMasternode::CMasternode(const CMasternode& other)
activeState = other.activeState;
sigTime = other.sigTime;
lastPing = other.lastPing;
cacheInputAge = other.cacheInputAge;
cacheInputAgeBlock = other.cacheInputAgeBlock;
collateralBlock = other.collateralBlock;
allowFreeTx = other.allowFreeTx;
nActiveState = MASTERNODE_ENABLED;
protocolVersion = other.protocolVersion;
Expand All @@ -166,8 +164,7 @@ CMasternode::CMasternode(const CMasternodeBroadcast& mnb)
activeState = MASTERNODE_ENABLED;
sigTime = mnb.sigTime;
lastPing = mnb.lastPing;
cacheInputAge = 0;
cacheInputAgeBlock = 0;
collateralBlock = mnb.collateralBlock;
allowFreeTx = true;
nActiveState = MASTERNODE_ENABLED;
protocolVersion = mnb.protocolVersion;
Expand All @@ -192,8 +189,7 @@ void CMasternode::swap(CMasternode& first, CMasternode& second) // nothrow
swap(first.activeState, second.activeState);
swap(first.sigTime, second.sigTime);
swap(first.lastPing, second.lastPing);
swap(first.cacheInputAge, second.cacheInputAge);
swap(first.cacheInputAgeBlock, second.cacheInputAgeBlock);
swap(first.collateralBlock, second.collateralBlock);
swap(first.allowFreeTx, second.allowFreeTx);
swap(first.protocolVersion, second.protocolVersion);
swap(first.nScanningErrorCount, second.nScanningErrorCount);
Expand Down Expand Up @@ -244,14 +240,18 @@ bool CMasternode::IsEnabled() const

int CMasternode::GetMasternodeInputAge() const
{
if (chainActive.Tip() == NULL) return 0;
LOCK(cs_main);

if (cacheInputAge == 0) {
cacheInputAge = GetInputAge(vin);
cacheInputAgeBlock = chainActive.Tip()->nHeight;
}
const auto* pindex = GetCollateralBlock();
if (pindex == nullptr)
return 0;

return cacheInputAge + (chainActive.Tip()->nHeight - cacheInputAgeBlock);
assert(chainActive.Contains(pindex));

const unsigned tipHeight = chainActive.Height();
assert(tipHeight >= pindex->nHeight);

return tipHeight - pindex->nHeight + 1;
}

std::string CMasternode::Status() const
Expand Down Expand Up @@ -735,6 +735,27 @@ bool CMasternodeBroadcastFactory::provideSignatures(
return true;
}

namespace
{

CMasternodePing createDelayedMasternodePing(const CMasternodeBroadcast& mnb)
{
CMasternodePing ping;
const int64_t offsetTimeBy45BlocksInSeconds = 60 * 45;
ping.vin = mnb.vin;
const int depthOfTx = mnb.GetMasternodeInputAge();
const int offset = std::min( std::max(0, depthOfTx), 12 );
const auto* block = chainActive[chainActive.Height() - offset];
ping.blockHash = block->GetBlockHash();
ping.sigTime = std::max(block->GetBlockTime() + offsetTimeBy45BlocksInSeconds, GetAdjustedTime());
ping.vchSig = std::vector<unsigned char>();
LogPrint("masternode","mnp - relay block-time & sigtime: %d vs. %d\n", block->GetBlockTime(), ping.sigTime);

return ping;
}

} // anonymous namespace

void CMasternodeBroadcastFactory::createWithoutSignatures(
CTxIn txin,
CService service,
Expand All @@ -748,8 +769,10 @@ void CMasternodeBroadcastFactory::createWithoutSignatures(
CBitcoinAddress(pubKeyCollateralAddressNew.GetID()).ToString(),
pubKeyMasternodeNew.GetID().ToString());

CMasternodePing mnp = (deferRelay)? CMasternodePing::createDelayedMasternodePing(txin): CMasternodePing(txin);
mnbRet = CMasternodeBroadcast(service, txin, pubKeyCollateralAddressNew, pubKeyMasternodeNew, nMasternodeTier, PROTOCOL_VERSION);
const CMasternodePing mnp = (deferRelay
? createDelayedMasternodePing(mnbRet)
: CMasternodePing(txin));
mnbRet.lastPing = mnp;
mnbRet.sigTime = mnp.sigTime;
}
Expand Down Expand Up @@ -845,6 +868,38 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
return true;
}

const CBlockIndex* CMasternode::GetCollateralBlock() const
{
LOCK(cs_main);

if (!collateralBlock.IsNull()) {
const auto mi = mapBlockIndex.find(collateralBlock);
if (mi != mapBlockIndex.end() && chainActive.Contains(mi->second))
return mi->second;
}
Comment on lines +875 to +879
Copy link

Choose a reason for hiding this comment

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

This could potentially cause some issues if there was some race condition following a fork, as it is possible that it was set before the fork but then not found on the active chain, no?

Copy link
Author

Choose a reason for hiding this comment

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

The cache takes effect only if a block is cached and part of the active chain at the moment the request happens (per the code quoted above).

If this is not the case, e.g. because the cached block was reorged and is no longer part of the active chain, then we simply invalidate and regenerate the cache. So I don't think anything can go wrong here.


uint256 hashBlock;
CTransaction tx;
if (!GetTransaction(vin.prevout.hash, tx, hashBlock, true)) {
collateralBlock.SetNull();
return nullptr;
}

const auto mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end() || mi->second == nullptr) {
collateralBlock.SetNull();
return nullptr;
}

if (!chainActive.Contains(mi->second)) {
collateralBlock.SetNull();
return nullptr;
}

collateralBlock = hashBlock;
return mi->second;
}

bool CMasternodeBroadcast::CheckInputs(int& nDoS) const
{
// we are a masternode with the same vin (i.e. already activated) and this mnb is ours (matches our Masternode privkey)
Expand All @@ -866,25 +921,30 @@ bool CMasternodeBroadcast::CheckInputs(int& nDoS) const

LogPrint("masternode", "mnb - Accepted Masternode entry\n");

if (GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS) {
const CBlockIndex* pindexConf;
{
LOCK(cs_main);
const auto* pindexCollateral = GetCollateralBlock();
if (pindexCollateral == nullptr)
pindexConf = nullptr;
else {
assert(chainActive.Contains(pindexCollateral));
pindexConf = chainActive[pindexCollateral->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1];
assert(pindexConf == nullptr || pindexConf->GetAncestor(pindexCollateral->nHeight) == pindexCollateral);
}
}

if (pindexConf == nullptr) {
LogPrint("masternode","mnb - Input must have at least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS);
return false;
}

// verify that sig time is legit in past
// should be at least not earlier than block when 1000 PIV tx got MASTERNODE_MIN_CONFIRMATIONS
uint256 hashBlock = 0;
CTransaction tx2;
GetTransaction(vin.prevout.hash, tx2, hashBlock, true);
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
if (mi != mapBlockIndex.end() && (*mi).second) {
CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DIVI tx -> 1 confirmation
CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1]; // block where tx got MASTERNODE_MIN_CONFIRMATIONS
if (pConfIndex->GetBlockTime() > sigTime) {
LogPrint("masternode","mnb - Bad sigTime %d for Masternode %s (%i conf block is at %d)\n",
sigTime, vin.prevout.hash.ToString(), MASTERNODE_MIN_CONFIRMATIONS, pConfIndex->GetBlockTime());
return false;
}
if (pindexConf->GetBlockTime() > sigTime) {
LogPrint("masternode","mnb - Bad sigTime %d for Masternode %s (%i conf block is at %d)\n",
sigTime, vin.prevout.hash.ToString(), MASTERNODE_MIN_CONFIRMATIONS, pindexConf->GetBlockTime());
return false;
}

return true;
Expand Down Expand Up @@ -940,22 +1000,6 @@ CMasternodePing::CMasternodePing(CTxIn& newVin)
vchSig = std::vector<unsigned char>();
}

CMasternodePing CMasternodePing::createDelayedMasternodePing(CTxIn& newVin)
{
CMasternodePing ping;
const int64_t offsetTimeBy45BlocksInSeconds = 60 * 45;
ping.vin = newVin;
int depthOfTx = GetInputAge(ping.vin);
int offset = std::min( std::max(0, depthOfTx), 12 );
auto block = chainActive[chainActive.Height()-offset];
ping.blockHash = block->GetBlockHash();
ping.sigTime = std::max(block->GetBlockTime() + offsetTimeBy45BlocksInSeconds, GetAdjustedTime());
ping.vchSig = std::vector<unsigned char>();
LogPrint("masternode","mnp - relay block-time & sigtime: %d vs. %d\n", block->GetBlockTime(), ping.sigTime);

return ping;
}

std::string CMasternodePing::getMessageToSign() const
{
return vin.ToString() + blockHash.ToString() + boost::lexical_cast<std::string>(sigTime);
Expand Down Expand Up @@ -1061,22 +1105,3 @@ void CMasternodePing::Relay() const
CInv inv(MSG_MASTERNODE_PING, GetHash());
RelayInv(inv);
}

int GetInputAge(const CTxIn& vin)
{
CCoinsView viewDummy;
CCoinsViewCache view(&viewDummy);
{
LOCK(mempool.cs);
CCoinsViewMemPool viewMempool(pcoinsTip, mempool);
view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view

const CCoins* coins = view.AccessCoins(vin.prevout.hash);

if (coins) {
if (coins->nHeight < 0) return 0;
return (chainActive.Tip()->nHeight + 1) - coins->nHeight;
} else
return -1;
}
}
23 changes: 14 additions & 9 deletions divi/src/masternode.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ bool GetBlockHashForScoring(uint256& hash, int nBlockHeight);
bool GetBlockHashForScoring(uint256& hash,
const CBlockIndex* pindex, const int offset);

int GetInputAge(const CTxIn& vin);

//
// The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network
//
Expand All @@ -61,7 +59,6 @@ class CMasternodePing

CMasternodePing();
CMasternodePing(CTxIn& newVin);
static CMasternodePing createDelayedMasternodePing(CTxIn& newVin);

ADD_SERIALIZE_METHODS;

Expand Down Expand Up @@ -129,8 +126,16 @@ class CMasternode
mutable CCriticalSection cs;
int64_t lastTimeChecked;

mutable int cacheInputAge;
mutable int cacheInputAgeBlock;
protected:

/** Cached block hash of where the collateral output of this
* masternode got included. */
mutable uint256 collateralBlock;

/** Looks up and returns the block index when the collateral got
* included in the currently active chain. If it is not yet confirmed
* then this returns nullptr. */
const CBlockIndex* GetCollateralBlock() const;

public:
enum state {
Expand Down Expand Up @@ -164,7 +169,6 @@ class CMasternode
CMasternode(const CMasternode& other);
CMasternode(const CMasternodeBroadcast& mnb);


void swap(CMasternode& first, CMasternode& second); // nothrow

CMasternode& operator=(CMasternode from);
Expand Down Expand Up @@ -199,8 +203,7 @@ class CMasternode
READWRITE(protocolVersion);
READWRITE(activeState);
READWRITE(lastPing);
READWRITE(cacheInputAge);
READWRITE(cacheInputAgeBlock);
READWRITE(collateralBlock);
READWRITE(allowFreeTx);
READWRITE(nScanningErrorCount);
READWRITE(nLastScanningErrorBlockHeight);
Expand Down Expand Up @@ -286,8 +289,10 @@ class CMasternodeBroadcast : public CMasternode
if (!ser_action.ForRead ())
tier = static_cast<int> (nTier);
READWRITE(tier);
if (ser_action.ForRead ())
if (ser_action.ForRead ()) {
nTier = static_cast<MasternodeTier> (tier);
collateralBlock.SetNull();
}
}

uint256 GetHash() const
Expand Down
Loading