示例#1
0
TER
CancelOffer::doApply ()
{
    std::uint32_t const uOfferSequence = tx().getFieldU32 (sfOfferSequence);

    auto const sle = view().read(
        keylet::account(account_));
    if (sle->getFieldU32 (sfSequence) - 1 <= uOfferSequence)
    {
        j_.trace << "Malformed transaction: " <<
            "Sequence " << uOfferSequence << " is invalid.";
        return temBAD_SEQUENCE;
    }

    uint256 const offerIndex (getOfferIndex (account_, uOfferSequence));

    auto sleOffer = view().peek (
        keylet::offer(offerIndex));

    if (sleOffer)
    {
        j_.debug << "Trying to cancel offer #" << uOfferSequence;
        return offerDelete (view(), sleOffer, ctx_.app.journal ("View"));
    }

    j_.debug << "Offer #" << uOfferSequence << " can't be found.";
    return tesSUCCESS;
}
示例#2
0
bool
BookTip::step (beast::Journal j)
{
    if (m_valid)
    {
        if (m_entry)
        {
            offerDelete (view_, m_entry, j);
            m_entry = nullptr;
        }
    }

    for(;;)
    {
        // See if there's an entry at or worse than current quality. Notice
        // that the quality is encoded only in the index of the first page
        // of a directory.
        auto const first_page =
            view_.succ (m_book, m_end);

        if (! first_page)
            return false;

        unsigned int di = 0;
        std::shared_ptr<SLE> dir;

        if (dirFirst (view_, *first_page, dir, di, m_index, j))
        {
            m_dir = dir->key();
            m_entry = view_.peek(keylet::offer(m_index));
            m_quality = Quality (getQuality (*first_page));
            m_valid = true;

            // Next query should start before this directory
            m_book = *first_page;

            // The quality immediately before the next quality
            --m_book;

            break;
        }

        // There should never be an empty directory but just in case,
        // we handle that case by advancing to the next directory.
        m_book = *first_page;
    }

    return true;
}
示例#3
0
static
void removeUnfundedOffers (ApplyView& view, std::vector<uint256> const& offers, beast::Journal viewJ)
{
    int removed = 0;

    for (auto const& index : offers)
    {
        if (auto const sleOffer = view.peek (keylet::offer (index)))
        {
            // offer is unfunded
            offerDelete (view, sleOffer, viewJ);
            if (++removed == unfundedOfferRemoveLimit)
                return;
        }
    }
}
示例#4
0
TER
CancelOffer::doApply ()
{
    auto const offerSequence = ctx_.tx[sfOfferSequence];

    auto const sle = view().read(
        keylet::account(account_));

    uint256 const offerIndex (getOfferIndex (account_, offerSequence));

    auto sleOffer = view().peek (
        keylet::offer(offerIndex));

    if (sleOffer)
    {
        JLOG(j_.debug) << "Trying to cancel offer #" << offerSequence;
        return offerDelete (view(), sleOffer, ctx_.app.journal("View"));
    }

    JLOG(j_.debug) << "Offer #" << offerSequence << " can't be found.";
    return tesSUCCESS;
}
示例#5
0
bool
OfferStream::step (Logs& l)
{
    // Modifying the order or logic of these
    // operations causes a protocol breaking change.

    auto viewJ = l.journal ("View");
    for(;;)
    {
        // BookTip::step deletes the current offer from the view before
        // advancing to the next (unless the ledger entry is missing).
        if (! tip_.step(l))
            return false;

        std::shared_ptr<SLE> entry = tip_.entry();

        // If we exceed the maximum number of allowed steps, we're done.
        if (!counter_.step ())
            return false;

        // Remove if missing
        if (! entry)
        {
            erase (view_);
            erase (cancelView_);
            continue;
        }

        // Remove if expired
        using d = NetClock::duration;
        using tp = NetClock::time_point;
        if (entry->isFieldPresent (sfExpiration) &&
            tp{d{(*entry)[sfExpiration]}} <= expire_)
        {
            JLOG(j_.trace) <<
                "Removing expired offer " << entry->getIndex();
            offerDelete (cancelView_,
                cancelView_.peek(keylet::offer(entry->key())), viewJ);
            continue;
        }

        offer_ = Offer (entry, tip_.quality());

        Amounts const amount (offer_.amount());

        // Remove if either amount is zero
        if (amount.empty())
        {
            JLOG(j_.warning) <<
                "Removing bad offer " << entry->getIndex();
            offerDelete (cancelView_,
                cancelView_.peek(keylet::offer(entry->key())), viewJ);
            offer_ = Offer{};
            continue;
        }

        // Calculate owner funds
        auto const owner_funds = accountFunds(view_,
            offer_.owner(), amount.out, fhZERO_IF_FROZEN, viewJ);

        // Check for unfunded offer
        if (owner_funds <= zero)
        {
            // If the owner's balance in the pristine view is the same,
            // we haven't modified the balance and therefore the
            // offer is "found unfunded" versus "became unfunded"
            auto const original_funds = accountFunds(cancelView_,
                offer_.owner(), amount.out, fhZERO_IF_FROZEN, viewJ);

            if (original_funds == owner_funds)
            {
                offerDelete (cancelView_, cancelView_.peek(
                    keylet::offer(entry->key())), viewJ);
                JLOG(j_.trace) <<
                    "Removing unfunded offer " << entry->getIndex();
            }
            else
            {
                JLOG(j_.trace) <<
                    "Removing became unfunded offer " << entry->getIndex();
            }
            offer_ = Offer{};
            continue;
        }

        break;
    }

    return true;
}
示例#6
0
void
OfferStream::permRmOffer (uint256 const& offerIndex)
{
    offerDelete (cancelView_,
                 cancelView_.peek(keylet::offer(offerIndex)), j_);
}