コード例 #1
0
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);
}
コード例 #2
0
/** 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;
}