Compare commits

...

9 Commits

Author SHA1 Message Date
Richard Holland
1f3382eac7 . 2023-12-27 12:47:51 +00:00
Richard Holland
76f61e56bf clang 2023-12-27 12:19:56 +00:00
Richard Holland
cb4111095c fixes 2023-12-27 12:09:32 +00:00
Richard Holland
c4be4be4e4 clang 2023-12-22 23:01:18 +00:00
Richard Holland
2484491736 compiling 2023-12-22 22:57:23 +00:00
Richard Holland
43c4616e32 . 2023-12-22 16:37:12 +00:00
Richard Holland
6735da10c4 fix wrong native purchase logic uritoken 2023-12-22 16:23:48 +00:00
Richard Holland
8c64749d62 change types on lambda to prevent any risk of overflow 2023-12-22 12:39:00 +00:00
Richard Holland
c3175e1fd4 disallow specifying both escrowid and offsersequence on escrow 2023-12-22 12:23:42 +00:00
4 changed files with 127 additions and 67 deletions

View File

@@ -437,11 +437,19 @@ EscrowFinish::preflight(PreflightContext const& ctx)
{
if (!ctx.tx.isFieldPresent(sfOfferSequence))
return temMALFORMED;
}
if (!ctx.tx.isFieldPresent(sfEscrowID) &&
!ctx.tx.isFieldPresent(sfOfferSequence))
return temMALFORMED;
if (ctx.tx.isFieldPresent(sfEscrowID) &&
ctx.tx.getFieldU32(sfOfferSequence) != 0)
return temMALFORMED;
}
else
{
if ((!ctx.tx.isFieldPresent(sfEscrowID) &&
!ctx.tx.isFieldPresent(sfOfferSequence)) ||
ctx.tx.isFieldPresent(sfEscrowID) &&
ctx.tx.isFieldPresent(sfOfferSequence))
return temMALFORMED;
}
return tesSUCCESS;
}
@@ -472,17 +480,6 @@ EscrowFinish::doApply()
bool const fixV1 = view().rules().enabled(fixXahauV1);
if (!fixV1)
{
if (escrowID && ctx_.tx[sfOfferSequence] != 0)
return temMALFORMED;
}
else
{
if (escrowID && offerSequence)
return temMALFORMED;
}
Keylet k = escrowID ? Keylet(ltESCROW, *escrowID)
: keylet::escrow(ctx_.tx[sfOwner], *offerSequence);
@@ -723,11 +720,19 @@ EscrowCancel::preflight(PreflightContext const& ctx)
{
if (!ctx.tx.isFieldPresent(sfOfferSequence))
return temMALFORMED;
}
if (!ctx.tx.isFieldPresent(sfEscrowID) &&
!ctx.tx.isFieldPresent(sfOfferSequence))
return temMALFORMED;
if (ctx.tx.isFieldPresent(sfEscrowID) &&
ctx.tx.getFieldU32(sfOfferSequence) != 0)
return temMALFORMED;
}
else
{
if ((!ctx.tx.isFieldPresent(sfEscrowID) &&
!ctx.tx.isFieldPresent(sfOfferSequence)) ||
ctx.tx.isFieldPresent(sfEscrowID) &&
ctx.tx.isFieldPresent(sfOfferSequence))
return temMALFORMED;
}
return preflight2(ctx);
}
@@ -744,16 +749,6 @@ EscrowCancel::doApply()
std::optional<std::uint32_t> offerSequence = ctx_.tx[~sfOfferSequence];
bool const fixV1 = view().rules().enabled(fixXahauV1);
if (!fixV1)
{
if (escrowID && ctx_.tx[sfOfferSequence] != 0)
return temMALFORMED;
}
else
{
if (escrowID && offerSequence)
return temMALFORMED;
}
Keylet k = escrowID ? Keylet(ltESCROW, *escrowID)
: keylet::escrow(ctx_.tx[sfOwner], *offerSequence);

View File

@@ -817,16 +817,17 @@ Import::preflight(PreflightContext const& ctx)
<< " validation count: " << validationCount;
// check if the validation count is adequate
auto hasInsufficientQuorum = [&ctx](int quorum, int validationCount) {
if (ctx.rules.enabled(fixXahauV1))
{
return quorum > validationCount;
}
else
{
return quorum >= validationCount;
}
};
auto hasInsufficientQuorum =
[&ctx](uint64_t quorum, uint64_t validationCount) {
if (ctx.rules.enabled(fixXahauV1))
{
return quorum > validationCount;
}
else
{
return quorum >= validationCount;
}
};
if (hasInsufficientQuorum(quorum, validationCount))
{
JLOG(ctx.j.warn()) << "Import: xpop did not contain an 80% quorum for "

View File

@@ -144,6 +144,8 @@ URIToken::preflight(PreflightContext const& ctx)
TER
URIToken::preclaim(PreclaimContext const& ctx)
{
bool const fixV1 = ctx.view.rules().enabled(fixXahauV1);
std::shared_ptr<SLE const> sleU;
uint32_t leFlags;
std::optional<AccountID> issuer;
@@ -180,6 +182,11 @@ URIToken::preclaim(PreclaimContext const& ctx)
AccountID const acc = ctx.tx.getAccountID(sfAccount);
uint16_t tt = ctx.tx.getFieldU16(sfTransactionType);
auto const sle =
ctx.view.read(keylet::account(ctx.tx.getAccountID(sfAccount)));
if (!sle)
return tefINTERNAL;
switch (tt)
{
case ttURITOKEN_MINT: {
@@ -228,24 +235,75 @@ URIToken::preclaim(PreclaimContext const& ctx)
if (purchaseAmount < saleAmount)
return tecINSUFFICIENT_PAYMENT;
if (purchaseAmount.native() && saleAmount->native())
if (fixV1)
{
// if it's an xrp sale/purchase then no trustline needed
if (purchaseAmount >
(sleOwner->getFieldAmount(sfBalance) - ctx.tx[sfFee]))
return tecINSUFFICIENT_FUNDS;
if (purchaseAmount.native() && saleAmount->native())
{
// native transfer
STAmount needed{ctx.view.fees().accountReserve(
sle->getFieldU32(sfOwnerCount) + 1)};
STAmount const fee = ctx.tx.getFieldAmount(sfFee).xrp();
if (needed + fee < needed)
return tecINTERNAL;
needed += fee;
if (needed + purchaseAmount < needed)
return tecINTERNAL;
needed += purchaseAmount;
if (needed > sle->getFieldAmount(sfBalance))
return tecINSUFFICIENT_FUNDS;
}
else if (purchaseAmount.native() || saleAmount->native())
{
// should not be able to happen
return tecINTERNAL;
}
else
{
// iou transfer
STAmount availableFunds{accountFunds(
ctx.view,
acc,
purchaseAmount,
fhZERO_IF_FROZEN,
ctx.j)};
if (purchaseAmount > availableFunds)
return tecINSUFFICIENT_FUNDS;
}
}
else
{
// old logic
// execution to here means it's an IOU sale
// check if the buyer has the right trustline with an adequate
// balance
STAmount availableFunds{accountFunds(
ctx.view, acc, purchaseAmount, fhZERO_IF_FROZEN, ctx.j)};
if (purchaseAmount > availableFunds)
return tecINSUFFICIENT_FUNDS;
if (purchaseAmount.native() && saleAmount->native())
{
// if it's an xrp sale/purchase then no trustline needed
if (purchaseAmount >
(sleOwner->getFieldAmount(sfBalance) - ctx.tx[sfFee]))
return tecINSUFFICIENT_FUNDS;
}
else
{
// iou
STAmount availableFunds{accountFunds(
ctx.view,
acc,
purchaseAmount,
fhZERO_IF_FROZEN,
ctx.j)};
if (purchaseAmount > availableFunds)
return tecINSUFFICIENT_FUNDS;
}
}
return tesSUCCESS;
}
@@ -412,17 +470,6 @@ URIToken::doApply()
}
case ttURITOKEN_BUY: {
if (account_ == *owner)
{
// this is a clear operation
sleU->makeFieldAbsent(sfAmount);
if (sleU->isFieldPresent(sfDestination))
sleU->makeFieldAbsent(sfDestination);
sb.update(sleU);
sb.apply(ctx_.rawView());
return tesSUCCESS;
}
STAmount const purchaseAmount = ctx_.tx.getFieldAmount(sfAmount);
// check if the seller has listed it at all
@@ -446,8 +493,22 @@ URIToken::doApply()
// if it's an xrp sale/purchase then no trustline needed
if (purchaseAmount.native())
{
if (purchaseAmount >
((*sleOwner)[sfBalance] - ctx_.tx[sfFee]))
STAmount needed{sb.fees().accountReserve(
sle->getFieldU32(sfOwnerCount) + 1)};
STAmount const fee = ctx_.tx.getFieldAmount(sfFee).xrp();
if (needed + fee < needed)
return tecINTERNAL;
needed += fee;
if (needed + purchaseAmount < needed)
return tecINTERNAL;
needed += purchaseAmount;
if (needed > mPriorBalance)
return tecINSUFFICIENT_FUNDS;
}
else

View File

@@ -454,7 +454,10 @@ struct URIToken_test : public beast::unit_test::suite
using namespace std::literals::chrono_literals;
// setup env
Env env{*this, features};
Env env{
*this, envconfig(), features, nullptr, beast::severities::kWarning
// beast::severities::kTrace
};
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const carol = Account("carol");