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; }
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; }
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; } } }
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; }
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; }
void OfferStream::permRmOffer (uint256 const& offerIndex) { offerDelete (cancelView_, cancelView_.peek(keylet::offer(offerIndex)), j_); }