Skip to content

Commit ebbd26a

Browse files
authored
Drop IsInputAssociatedWithPubkey and optimize CheckOutpoint (dashpay#1783)
* Drop IsInputAssociatedWithPubkey and optimize CheckOutpoint * typo
1 parent cd9c699 commit ebbd26a

File tree

3 files changed

+57
-83
lines changed

3 files changed

+57
-83
lines changed

src/governance-object.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -447,14 +447,17 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingMast
447447
masternode_info_t infoMn;
448448
if(!mnodeman.GetMasternodeInfo(vinMasternode.prevout, infoMn)) {
449449

450-
CMasternode::CollateralStatus err = CMasternode::CheckCollateral(vinMasternode.prevout);
451-
if (err == CMasternode::COLLATERAL_OK) {
452-
fMissingMasternode = true;
453-
strError = "Masternode not found: " + strOutpoint;
454-
} else if (err == CMasternode::COLLATERAL_UTXO_NOT_FOUND) {
450+
CMasternode::CollateralStatus err = CMasternode::CheckCollateral(vinMasternode.prevout, CPubKey());
451+
if (err == CMasternode::COLLATERAL_UTXO_NOT_FOUND) {
455452
strError = "Failed to find Masternode UTXO, missing masternode=" + strOutpoint + "\n";
456453
} else if (err == CMasternode::COLLATERAL_INVALID_AMOUNT) {
457454
strError = "Masternode UTXO should have 1000 DASH, missing masternode=" + strOutpoint + "\n";
455+
} else if (err == CMasternode::COLLATERAL_INVALID_PUBKEY) {
456+
fMissingMasternode = true;
457+
strError = "Masternode not found: " + strOutpoint;
458+
} else if (err == CMasternode::COLLATERAL_OK) {
459+
// this should never happen with CPubKey() as a param
460+
strError = "CheckCollateral critical failure! Masternode: " + strOutpoint;
458461
}
459462

460463
return false;

src/masternode.cpp

Lines changed: 45 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,13 @@ arith_uint256 CMasternode::CalculateScore(const uint256& blockHash)
101101
return UintToArith256(ss.GetHash());
102102
}
103103

104-
CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint)
104+
CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint, const CPubKey& pubkey)
105105
{
106106
int nHeight;
107-
return CheckCollateral(outpoint, nHeight);
107+
return CheckCollateral(outpoint, pubkey, nHeight);
108108
}
109109

110-
CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint, int& nHeightRet)
110+
CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outpoint, const CPubKey& pubkey, int& nHeightRet)
111111
{
112112
AssertLockHeld(cs_main);
113113

@@ -120,6 +120,10 @@ CMasternode::CollateralStatus CMasternode::CheckCollateral(const COutPoint& outp
120120
return COLLATERAL_INVALID_AMOUNT;
121121
}
122122

123+
if(pubkey == CPubKey() || coin.out.scriptPubKey != GetScriptForDestination(pubkey.GetID())) {
124+
return COLLATERAL_INVALID_PUBKEY;
125+
}
126+
123127
nHeightRet = coin.nHeight;
124128
return COLLATERAL_OK;
125129
}
@@ -143,8 +147,8 @@ void CMasternode::Check(bool fForce)
143147
TRY_LOCK(cs_main, lockMain);
144148
if(!lockMain) return;
145149

146-
CollateralStatus err = CheckCollateral(vin.prevout);
147-
if (err == COLLATERAL_UTXO_NOT_FOUND) {
150+
Coin coin;
151+
if(!GetUTXOCoin(vin.prevout, coin)) {
148152
nActiveState = MASTERNODE_OUTPOINT_SPENT;
149153
LogPrint("masternode", "CMasternode::Check -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort());
150154
return;
@@ -247,21 +251,6 @@ void CMasternode::Check(bool fForce)
247251
}
248252
}
249253

250-
bool CMasternode::IsInputAssociatedWithPubkey()
251-
{
252-
CScript payee;
253-
payee = GetScriptForDestination(pubKeyCollateralAddress.GetID());
254-
255-
CTransaction tx;
256-
uint256 hash;
257-
if(GetTransaction(vin.prevout.hash, tx, Params().GetConsensus(), hash, true)) {
258-
BOOST_FOREACH(CTxOut out, tx.vout)
259-
if(out.nValue == 1000*COIN && out.scriptPubKey == payee) return true;
260-
}
261-
262-
return false;
263-
}
264-
265254
bool CMasternode::IsValidNetAddr()
266255
{
267256
return IsValidNetAddr(addr);
@@ -542,72 +531,56 @@ bool CMasternodeBroadcast::CheckOutpoint(int& nDos)
542531
return false;
543532
}
544533

545-
if (!CheckSignature(nDos)) {
546-
LogPrintf("CMasternodeBroadcast::CheckOutpoint -- CheckSignature() failed, masternode=%s\n", vin.prevout.ToStringShort());
534+
AssertLockHeld(cs_main);
535+
536+
int nHeight;
537+
CollateralStatus err = CheckCollateral(vin.prevout, pubKeyCollateralAddress, nHeight);
538+
if (err == COLLATERAL_UTXO_NOT_FOUND) {
539+
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort());
547540
return false;
548541
}
549542

550-
{
551-
TRY_LOCK(cs_main, lockMain);
552-
if(!lockMain) {
553-
// not mnb fault, let it to be checked again later
554-
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to aquire lock, addr=%s", addr.ToString());
555-
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
556-
return false;
557-
}
558-
559-
int nHeight;
560-
CollateralStatus err = CheckCollateral(vin.prevout, nHeight);
561-
if (err == COLLATERAL_UTXO_NOT_FOUND) {
562-
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort());
563-
return false;
564-
}
543+
if (err == COLLATERAL_INVALID_AMOUNT) {
544+
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should have 1000 DASH, masternode=%s\n", vin.prevout.ToStringShort());
545+
nDos = 33;
546+
return false;
547+
}
565548

566-
if (err == COLLATERAL_INVALID_AMOUNT) {
567-
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should have 1000 DASH, masternode=%s\n", vin.prevout.ToStringShort());
568-
return false;
569-
}
549+
if(err == COLLATERAL_INVALID_PUBKEY) {
550+
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should match pubKeyCollateralAddress, masternode=%s\n", vin.prevout.ToStringShort());
551+
nDos = 33;
552+
return false;
553+
}
570554

571-
if(chainActive.Height() - nHeight + 1 < Params().GetConsensus().nMasternodeMinimumConfirmations) {
572-
LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO must have at least %d confirmations, masternode=%s\n",
573-
Params().GetConsensus().nMasternodeMinimumConfirmations, vin.prevout.ToStringShort());
574-
// maybe we miss few blocks, let this mnb to be checked again later
575-
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
576-
return false;
577-
}
578-
// remember the hash of the block where masternode collateral had minimum required confirmations
579-
nCollateralMinConfBlockHash = chainActive[nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]->GetBlockHash();
555+
if(chainActive.Height() - nHeight + 1 < Params().GetConsensus().nMasternodeMinimumConfirmations) {
556+
LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO must have at least %d confirmations, masternode=%s\n",
557+
Params().GetConsensus().nMasternodeMinimumConfirmations, vin.prevout.ToStringShort());
558+
// UTXO is legit but has not enough confirmations.
559+
// Maybe we miss few blocks, let this mnb be checked again later.
560+
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
561+
return false;
580562
}
581563

582564
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO verified\n");
583565

584-
// make sure the input that was signed in masternode broadcast message is related to the transaction
585-
// that spawned the Masternode - this is expensive, so it's only done once per Masternode
586-
if(!IsInputAssociatedWithPubkey()) {
587-
LogPrintf("CMasternodeMan::CheckOutpoint -- Got mismatched pubKeyCollateralAddress and vin\n");
588-
nDos = 33;
566+
// Verify that sig time is legit, should be at least not earlier than the timestamp of the block
567+
// at which collateral became nMasternodeMinimumConfirmations blocks deep.
568+
// NOTE: this is not accurate because block timestamp is NOT guaranteed to be 100% correct one.
569+
CBlockIndex* pRequiredConfIndex = chainActive[nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]; // block where tx got nMasternodeMinimumConfirmations
570+
if(pRequiredConfIndex->GetBlockTime() > sigTime) {
571+
LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Bad sigTime %d (%d conf block is at %d) for Masternode %s %s\n",
572+
sigTime, Params().GetConsensus().nMasternodeMinimumConfirmations, pRequiredConfIndex->GetBlockTime(), vin.prevout.ToStringShort(), addr.ToString());
589573
return false;
590574
}
591575

592-
// verify that sig time is legit in past
593-
// should be at least not earlier than block when 1000 DASH tx got nMasternodeMinimumConfirmations
594-
uint256 hashBlock = uint256();
595-
CTransaction tx2;
596-
GetTransaction(vin.prevout.hash, tx2, Params().GetConsensus(), hashBlock, true);
597-
{
598-
LOCK(cs_main);
599-
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
600-
if (mi != mapBlockIndex.end() && (*mi).second) {
601-
CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation
602-
CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]; // block where tx got nMasternodeMinimumConfirmations
603-
if(pConfIndex->GetBlockTime() > sigTime) {
604-
LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Bad sigTime %d (%d conf block is at %d) for Masternode %s %s\n",
605-
sigTime, Params().GetConsensus().nMasternodeMinimumConfirmations, pConfIndex->GetBlockTime(), vin.prevout.ToStringShort(), addr.ToString());
606-
return false;
607-
}
608-
}
576+
if (!CheckSignature(nDos)) {
577+
LogPrintf("CMasternodeBroadcast::CheckOutpoint -- CheckSignature() failed, masternode=%s\n", vin.prevout.ToStringShort());
578+
return false;
609579
}
610580

581+
// remember the block hash when collateral for this masternode had minimum required confirmations
582+
nCollateralMinConfBlockHash = pRequiredConfIndex->GetBlockHash();
583+
611584
return true;
612585
}
613586

src/masternode.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ class CMasternode : public masternode_info_t
149149
enum CollateralStatus {
150150
COLLATERAL_OK,
151151
COLLATERAL_UTXO_NOT_FOUND,
152-
COLLATERAL_INVALID_AMOUNT
152+
COLLATERAL_INVALID_AMOUNT,
153+
COLLATERAL_INVALID_PUBKEY
153154
};
154155

155156

@@ -203,8 +204,8 @@ class CMasternode : public masternode_info_t
203204

204205
bool UpdateFromNewBroadcast(CMasternodeBroadcast& mnb, CConnman& connman);
205206

206-
static CollateralStatus CheckCollateral(const COutPoint& outpoint);
207-
static CollateralStatus CheckCollateral(const COutPoint& outpoint, int& nHeightRet);
207+
static CollateralStatus CheckCollateral(const COutPoint& outpoint, const CPubKey& pubkey);
208+
static CollateralStatus CheckCollateral(const COutPoint& outpoint, const CPubKey& pubkey, int& nHeightRet);
208209
void Check(bool fForce = false);
209210

210211
bool IsBroadcastedWithin(int nSeconds) { return GetAdjustedTime() - sigTime < nSeconds; }
@@ -251,9 +252,6 @@ class CMasternode : public masternode_info_t
251252
return false;
252253
}
253254

254-
/// Is the input associated with collateral public key? (and there is 1000 DASH - checking if valid masternode)
255-
bool IsInputAssociatedWithPubkey();
256-
257255
bool IsValidNetAddr();
258256
static bool IsValidNetAddr(CService addrIn);
259257

0 commit comments

Comments
 (0)