void CMasternode::UpdateLastPaid(const CBlockIndex* pindex, int nMaxBlocksToScanBack) { if (!pindex) return; const CBlockIndex* pindexActive = chainActive.Tip(); assert(pindexActive); CDiskBlockPos blockPos = pindexActive->GetBlockPos(); CScript mnpayee = GetScriptForDestination(CScriptID(GetScriptForDestination(WitnessV0KeyHash(pubKeyCollateralAddress.GetID())))); //LogPrint(MCLog::MN, "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s\n", outpoint.ToStringShort()); LOCK(cs_mapMasternodeBlocks); for (int i = 0; pindexActive->nHeight > nBlockLastPaid && i < nMaxBlocksToScanBack; i++) { if (mnpayments.mapMasternodeBlocks.count(pindexActive->nHeight) && mnpayments.mapMasternodeBlocks[pindexActive->nHeight].HasPayeeWithVotes(mnpayee, 2)) { if (blockPos.IsNull() == true) { return; } CBlock block; if (!ReadBlockFromDisk(block, blockPos, Params().GetConsensus())) continue; CAmount nMasternodePayment = GetMasternodePayment(pindexActive->nHeight, block.vtx[0]->GetValueOut()); for (const auto& txout : block.vtx[0]->vout) if (mnpayee == txout.scriptPubKey && nMasternodePayment == txout.nValue) { nBlockLastPaid = pindexActive->nHeight; nTimeLastPaid = pindexActive->nTime; LogPrint(MCLog::MN, "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- found new %d\n", outpoint.ToStringShort(), nBlockLastPaid); return; } } if (pindexActive->pprev == nullptr) { assert(pindexActive); break; } pindexActive = pindexActive->pprev; } // Last payment for this masternode wasn't found in latest mnpayments blocks // or it was found in mnpayments blocks but wasn't found in the blockchain. LogPrint(MCLog::MN, "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- keeping old %d\n", outpoint.ToStringShort(), nBlockLastPaid); }
/** Undo the effects of this block (with given index) on the UTXO set represented by coins. * When FAILED is returned, view is left in an indeterminate state. */ DisconnectResult CViewManager::DisconnectBlock(const CBlock &block, const CBlockIndex *pindex, CCoinsViewCache &view, bool *pfClean) { if (pfClean) *pfClean = false; bool fClean = true; CBlockUndo blockUndo; CDiskBlockPos pos = pindex->GetUndoPos(); if (pos.IsNull()) { ELogFormat("no undo data available"); return DISCONNECT_FAILED; } if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash())) { ELogFormat("failure reading undo data"); return DISCONNECT_FAILED; } if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) { ELogFormat("block and undo data inconsistent"); return DISCONNECT_FAILED; } // undo transactions in reverse order for (int i = block.vtx.size() - 1; i >= 0; i--) { const CTransaction &tx = *(block.vtx[i]); uint256 hash = tx.GetHash(); bool is_coinbase = tx.IsCoinBase(); // Check that all outputs are available and match the outputs in the block itself // exactly. for (size_t o = 0; o < tx.vout.size(); o++) { if (!tx.vout[o].scriptPubKey.IsUnspendable()) { COutPoint out(hash, o); Coin coin; bool is_spent = view.SpendCoin(out, &coin); if (!is_spent || tx.vout[o] != coin.out || pindex->nHeight != coin.nHeight || is_coinbase != coin.fCoinBase) { fClean = false; // transaction output mismatch } } } // restore inputs if (i > 0) { // not coinbases if(tx.IsCoinBase2()){ continue; //continue } CTxUndo &txundo = blockUndo.vtxundo[i - 1]; if (txundo.vprevout.size() != tx.vin.size()) { ELogFormat("transaction and undo data inconsistent"); return DISCONNECT_FAILED; } for (unsigned int j = tx.vin.size(); j-- > 0;) { const COutPoint &out = tx.vin[j].prevout; int res = ApplyTxInUndo(std::move(txundo.vprevout[j]), view, out); if (res == DISCONNECT_FAILED) return DISCONNECT_FAILED; fClean = fClean && res != DISCONNECT_UNCLEAN; } // At this point, all of txundo.vprevout should have been moved out. } } // move best block pointer to prevout block view.SetBestBlock(pindex->pprev->GetBlockHash()); //sbtc-vm GET_CONTRACT_INTERFACE(ifContractObj); uint256 hashStateRoot; uint256 hashUTXORoot; CBlock prevblock; if (!ReadBlockFromDisk(prevblock, pindex->pprev, Params().GetConsensus())) { //TODO LogError rLogError("ReadBlockFromDisk failed at %d, hash=%s", pindex->pprev->nHeight, pindex->pprev->GetBlockHash().ToString()); } else { if(prevblock.GetVMState(hashStateRoot, hashUTXORoot) == RET_VM_STATE_ERR) { ILogFormat("GetVMState err"); } } ifContractObj->UpdateState(hashStateRoot, hashUTXORoot); // ifContractObj->UpdateState(pindex->pprev->hashStateRoot, pindex->pprev->hashUTXORoot); GET_CHAIN_INTERFACE(ifChainObj); if (pfClean == NULL && ifChainObj->IsLogEvents()) { ifContractObj->DeleteResults(block.vtx); ifChainObj->GetBlockTreeDB()->EraseHeightIndex(pindex->nHeight); } return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; }