Skip to content

Commit

Permalink
Allow offers to be removable
Browse files Browse the repository at this point in the history
Signed-off-by: Shawn Xie <[email protected]>
  • Loading branch information
shawnxie999 committed Nov 29, 2022
1 parent ae7cd6f commit 3814b92
Show file tree
Hide file tree
Showing 4 changed files with 328 additions and 73 deletions.
38 changes: 32 additions & 6 deletions src/ripple/app/tx/impl/NFTokenBurn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,14 @@ NFTokenBurn::preclaim(PreclaimContext const& ctx)
}
}

// If there are too many offers, then burning the token would produce too
// much metadata. Disallow burning a token with too many offers.
return nft::notTooManyOffers(ctx.view, ctx.tx[sfNFTokenID]);
if (!ctx.view.rules().enabled(fixUnburnableNFToken))
{
// If there are too many offers, then burning the token would produce
// too much metadata. Disallow burning a token with too many offers.
return nft::notTooManyOffers(ctx.view, ctx.tx[sfNFTokenID]);
}

return tesSUCCESS;
}

TER
Expand All @@ -104,9 +109,30 @@ NFTokenBurn::doApply()
view().update(issuer);
}

// Optimized deletion of all offers.
nft::removeAllTokenOffers(view(), keylet::nft_sells(ctx_.tx[sfNFTokenID]));
nft::removeAllTokenOffers(view(), keylet::nft_buys(ctx_.tx[sfNFTokenID]));
if (ctx_.view().rules().enabled(fixUnburnableNFToken))
{
// Delete up to 500 offers, but prefers buy offers first
auto const deletedBuyOffers = nft::removeTokenOffersWithLimit(
view(),
keylet::nft_buys(ctx_.tx[sfNFTokenID]),
maxDeletableTokenOfferEntries);

if (maxDeletableTokenOfferEntries - deletedBuyOffers > 0)
{
nft::removeTokenOffersWithLimit(
view(),
keylet::nft_sells(ctx_.tx[sfNFTokenID]),
maxDeletableTokenOfferEntries - deletedBuyOffers);
}
}
else
{
// Optimized deletion of all offers.
nft::removeAllTokenOffers(
view(), keylet::nft_sells(ctx_.tx[sfNFTokenID]));
nft::removeAllTokenOffers(
view(), keylet::nft_buys(ctx_.tx[sfNFTokenID]));
}

return tesSUCCESS;
}
Expand Down
33 changes: 33 additions & 0 deletions src/ripple/app/tx/impl/details/NFTokenUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,39 @@ removeAllTokenOffers(ApplyView& view, Keylet const& directory)
});
}

std::size_t
removeTokenOffersWithLimit(
ApplyView& view,
Keylet const& directory,
std::size_t maxDeletableOffers)
{
std::optional<std::uint64_t> pi{0};
std::vector<uint256> offers;
offers.reserve(maxDeletableOffers);

do
{
auto const page = view.peek(keylet::page(directory, *pi));
if (!page)
break;

for (auto const& id : page->getFieldV256(sfIndexes))
{
offers.push_back(id);
if (maxDeletableOffers == offers.size())
break;
}
pi = (*page)[~sfIndexNext];
} while (pi.value_or(0) && maxDeletableOffers != offers.size());

for (auto const& id : offers)
{
if (auto const offer = view.peek(keylet::nftoffer(id)))
deleteTokenOffer(view, offer);
}
return offers.size();
}

TER
notTooManyOffers(ReadView const& view, uint256 const& nftokenID)
{
Expand Down
8 changes: 8 additions & 0 deletions src/ripple/app/tx/impl/details/NFTokenUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ constexpr std::uint16_t const flagTransferable = 0x0008;
void
removeAllTokenOffers(ApplyView& view, Keylet const& directory);

/** Delete up to a specified number of offers from the specified token offer
* directory. */
std::size_t
removeTokenOffersWithLimit(
ApplyView& view,
Keylet const& directory,
std::size_t maxDeletableOffers);

/** Returns tesSUCCESS if NFToken has few enough offers that it can be burned */
TER
notTooManyOffers(ReadView const& view, uint256 const& nftokenID);
Expand Down
Loading

0 comments on commit 3814b92

Please sign in to comment.