@@ -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-
265254bool 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
0 commit comments