/* Update our model of the wallet incrementally, to synchronize our model of the wallet
       with that of the core.

       Call with list of hashes of transactions that were added, removed or changed.
    */
    void updateWallet(const QList<uint256> &updated)
    {
        // Walk through updated transactions, update model as needed.
#ifdef WALLET_UPDATE_DEBUG
        qDebug() << "updateWallet";
#endif
        // Sort update list, and iterate through it in reverse, so that model updates
        //  can be emitted from end to beginning (so that earlier updates will not influence
        // the indices of latter ones).
        QList<uint256> updated_sorted = updated;
        qSort(updated_sorted);

        {
            LOCK(wallet->cs_wallet);
            for(int update_idx = updated_sorted.size()-1; update_idx >= 0; --update_idx)
            {
                const uint256 &hash = updated_sorted.at(update_idx);

                // Find transaction in wallet
                std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(hash);
                bool inWallet = mi != wallet->mapWallet.end();

                // Find bounds of this transaction in model
                QList<TransactionRecord>::iterator lower = qLowerBound(
                            cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
                QList<TransactionRecord>::iterator upper = qUpperBound(
                            cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan());
                int lowerIndex = (lower - cachedWallet.begin());
                int upperIndex = (upper - cachedWallet.begin());

                // Determine if transaction is in model already
                bool inModel = false;
                if(lower != upper)
                {
                    inModel = true;
                }

#ifdef WALLET_UPDATE_DEBUG
                qDebug() << "  " << QString::fromStdString(hash.ToString()) << inWallet << " " << inModel
                         << lowerIndex << "-" << upperIndex;
#endif

                if(inWallet && !inModel)
                {
                    if(!mapBlockIndex.count(mi->second.hashBlock))
                        continue;

                    CBlockIndex *pindex = mapBlockIndex[mi->second.hashBlock];
                    if(!pindex)
                        continue;

                    // Added -- insert at the right position
                    QList<TransactionRecord> toInsert =
                        TransactionRecord::decomposeTransaction(wallet, mi->second, pindex->IsProofOfBurn());

                    if(!toInsert.isEmpty()) /* only if something to insert */
                    {
                        parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1);
                        int insert_idx = lowerIndex;
                        foreach(const TransactionRecord &rec, toInsert)
                        {
                            cachedWallet.insert(insert_idx, rec);
                            insert_idx += 1;
                        }
                        parent->endInsertRows();
                    }
                }
                else if(!inWallet && inModel)
Esempio n. 2
0
bool CTxDB::LoadBlockIndex()
{
    // Get database cursor
    Dbc* pcursor = GetCursor();
    if (!pcursor)
        return false;

    // Load mapBlockIndex
    unsigned int fFlags = DB_SET_RANGE;
  for(;;)
    {
        // Read next record
        CDataStream ssKey(SER_DISK, CLIENT_VERSION);
        if (fFlags == DB_SET_RANGE)
            ssKey << make_pair(string("blockindex"), uint256(0));
        CDataStream ssValue(SER_DISK, CLIENT_VERSION);
        int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
        fFlags = DB_NEXT;
        if (ret == DB_NOTFOUND)
            break;
        else if (ret != 0)
            return false;

        // Unserialize

        try {
        string strType;
        ssKey >> strType;
        if (strType == "blockindex" && !fRequestShutdown)
        {
            CDiskBlockIndex diskindex;
            ssValue >> diskindex;

            uint256 blockHash = diskindex.GetBlockHash();

            // Construct block index object
            CBlockIndex* pindexNew    = InsertBlockIndex(blockHash);
            pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
            pindexNew->pnext          = InsertBlockIndex(diskindex.hashNext);
            pindexNew->nFile          = diskindex.nFile;
            pindexNew->nBlockPos      = diskindex.nBlockPos;
            pindexNew->nHeight        = diskindex.nHeight;
            pindexNew->nMint          = diskindex.nMint;
            pindexNew->nMoneySupply   = diskindex.nMoneySupply;
            pindexNew->nFlags         = diskindex.nFlags;
            pindexNew->nStakeModifier = diskindex.nStakeModifier;
            pindexNew->prevoutStake   = diskindex.prevoutStake;
            pindexNew->nStakeTime     = diskindex.nStakeTime;
            pindexNew->hashProofOfStake = diskindex.hashProofOfStake;
            pindexNew->nVersion       = diskindex.nVersion;
            pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
            pindexNew->nTime          = diskindex.nTime;
            pindexNew->nBits          = diskindex.nBits;
            pindexNew->nNonce         = diskindex.nNonce;

            //Load Proof of Burn switch and indexes
            pindexNew->fProofOfBurn   = diskindex.fProofOfBurn;
            pindexNew->burnHash       = diskindex.burnHash;
            pindexNew->burnBlkHeight  = diskindex.burnBlkHeight;
            pindexNew->burnCTx        = diskindex.burnCTx;
            pindexNew->burnCTxOut     = diskindex.burnCTxOut;
            pindexNew->nEffectiveBurnCoins = diskindex.nEffectiveBurnCoins;
            pindexNew->nBurnBits      = diskindex.nBurnBits;

            // Watch for genesis block
            if (pindexGenesisBlock == NULL && blockHash == hashGenesisBlock)
                pindexGenesisBlock = pindexNew;

            if (!pindexNew->CheckIndex())
                return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);

            // ppcoin: build setStakeSeen
            if (pindexNew->IsProofOfStake())
                setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime));
            else if(pindexNew->IsProofOfBurn()) //build the setBurnSeen
                setBurnSeen.insert(pindexNew->GetProofOfBurn());
        }
        else
        {
            break; // if shutdown requested or finished loading block index
        }
        }    // try
        catch (std::exception &e) {