Skip to content

Commit

Permalink
Add amendment guards
Browse files Browse the repository at this point in the history
  • Loading branch information
gregtatcam committed Jul 23, 2024
1 parent 47171d9 commit 408dbf6
Show file tree
Hide file tree
Showing 19 changed files with 113 additions and 6 deletions.
12 changes: 12 additions & 0 deletions include/xrpl/protocol/STEitherAmount.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,18 @@ isMPT(T const& amount)
return false;
}

template <typename T>
requires(
std::is_same_v<T, STEitherAmount> ||
std::is_same_v<T, std::optional<STEitherAmount>>) bool
isMPT(T const& amount)
{
if constexpr (std::is_same_v<T, STEitherAmount>)
return amount.isMPT();
else
return amount && amount->isMPT();
}

template <ValidAmountType T>
bool
isIssue(T const& amount)
Expand Down
3 changes: 2 additions & 1 deletion include/xrpl/protocol/TER.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ enum TEMcodes : TERUnderlyingType {

temARRAY_EMPTY,
temARRAY_TOO_LARGE,
temMPT_NOT_SUPPORTED
temMPT_NOT_SUPPORTED,
temMPT_INVALID_USAGE
};

//------------------------------------------------------------------------------
Expand Down
7 changes: 6 additions & 1 deletion src/libxrpl/protocol/STObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,12 @@ STObject::applyTemplate(const SOTemplate& type)
{
if (auto const v = dynamic_cast<STEitherAmount*>(&iter->get());
v && v->isMPT())
throwFieldErr(e.sField().fieldName, "doesn't support MPT");
{
if (auto const& rules = getCurrentTransactionRules();
rules && rules->enabled(featureMPTokensV1))
throwFieldErr(
e.sField().fieldName, "doesn't support MPT");
}
}
v.emplace_back(std::move(*iter));
v_.erase(iter);
Expand Down
13 changes: 10 additions & 3 deletions src/libxrpl/protocol/STTx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,16 @@ isAccountAndMPTFieldOkay(STObject const& st)
auto t = dynamic_cast<STAccount const*>(st.peekAtPIndex(i));
if (t && t->isDefault())
return false;
auto amt = dynamic_cast<STEitherAmount const*>(st.peekAtPIndex(i));
if (amt && amt->isMPT() && !isMPTAmountAllowed)
return false;
if (st.peekAtIndex(i).getSType() == STI_AMOUNT)
{
auto amt = dynamic_cast<STEitherAmount const*>(st.peekAtPIndex(i));
if (amt && amt->isMPT() && !isMPTAmountAllowed)
{
if (auto const& rules = getCurrentTransactionRules();
rules && rules->enabled(featureMPTokensV1))
return false;
}
}
}

return true;
Expand Down
1 change: 1 addition & 0 deletions src/libxrpl/protocol/TER.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ transResults()
MAKE_ERROR(temINVALID, "The transaction is ill-formed."),
MAKE_ERROR(temINVALID_FLAG, "The transaction has an invalid flag."),
MAKE_ERROR(temMPT_NOT_SUPPORTED, "MPT is not supported."),
MAKE_ERROR(temMPT_INVALID_USAGE, "Invalid MPT usage."),
MAKE_ERROR(temREDUNDANT, "The transaction is redundant."),
MAKE_ERROR(temRIPPLE_EMPTY, "PathSet with no paths."),
MAKE_ERROR(temUNCERTAIN, "In process of determining result. Never returned."),
Expand Down
2 changes: 1 addition & 1 deletion src/test/app/MPToken_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ class MPToken_test : public beast::unit_test::suite

mptAlice.create();

env(offer(alice, mptAlice.mpt(100), XRP(100)), ter(temMALFORMED));
env(offer(alice, mptAlice.mpt(100), XRP(100)), ter(temMPT_NOT_SUPPORTED));
env.close();

BEAST_EXPECT(expectOffers(env, alice, 0));
Expand Down
4 changes: 4 additions & 0 deletions src/xrpld/app/tx/detail/AMMBid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ AMMBid::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
(isMPT(ctx.tx[~sfBidMin]) || isMPT(ctx.tx[~sfBidMax])))
return temMPT_INVALID_USAGE;

if (ctx.tx.getFlags() & tfUniversalMask)
{
JLOG(ctx.j.debug()) << "AMM Bid: invalid flags.";
Expand Down
4 changes: 4 additions & 0 deletions src/xrpld/app/tx/detail/AMMCreate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ AMMCreate::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
(isMPT(ctx.tx[sfAmount]) || isMPT(ctx.tx[sfAmount2])))
return temMPT_NOT_SUPPORTED;

if (ctx.tx.getFlags() & tfUniversalMask)
{
JLOG(ctx.j.debug()) << "AMM Instance: invalid flags.";
Expand Down
8 changes: 8 additions & 0 deletions src/xrpld/app/tx/detail/AMMDeposit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ AMMDeposit::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1))
{
if (isMPT(ctx.tx[~sfAmount]) || isMPT(ctx.tx[~sfAmount2]))
return temMPT_NOT_SUPPORTED;
if (isMPT(ctx.tx[~sfEPrice]) || isMPT(ctx.tx[~sfLPTokenOut]))
return temMPT_INVALID_USAGE;
}

auto const flags = ctx.tx.getFlags();
if (flags & tfDepositMask)
{
Expand Down
8 changes: 8 additions & 0 deletions src/xrpld/app/tx/detail/AMMWithdraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ AMMWithdraw::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1))
{
if (isMPT(ctx.tx[~sfAmount]) || isMPT(ctx.tx[~sfAmount2]))
return temMPT_NOT_SUPPORTED;
if (isMPT(ctx.tx[~sfEPrice]) || isMPT(ctx.tx[~sfLPTokenIn]))
return temMPT_INVALID_USAGE;
}

auto const flags = ctx.tx.getFlags();
if (flags & tfWithdrawMask)
{
Expand Down
4 changes: 4 additions & 0 deletions src/xrpld/app/tx/detail/CashCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ CashCheck::preflight(PreflightContext const& ctx)
if (!isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
(isMPT(ctx.tx[~sfAmount]) || isMPT(ctx.tx[~sfDeliverMin])))
return temMPT_NOT_SUPPORTED;

if (ctx.tx.getFlags() & tfUniversalMask)
{
// There are no flags (other than universal) for CashCheck yet.
Expand Down
5 changes: 5 additions & 0 deletions src/xrpld/app/tx/detail/Change.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ Change::preflight(PreflightContext const& ctx)
if (!isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
(isMPT(ctx.tx[~sfBaseFeeDrops]) || isMPT(ctx.tx[~sfReserveBaseDrops]) ||
isMPT(ctx.tx[~sfReserveIncrementDrops])))
return temMPT_INVALID_USAGE;

auto account = ctx.tx.getAccountID(sfAccount);
if (account != beast::zero)
{
Expand Down
3 changes: 3 additions & 0 deletions src/xrpld/app/tx/detail/CreateCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ CreateCheck::preflight(PreflightContext const& ctx)
if (!isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) && isMPT(ctx.tx[sfSendMax]))
return temMPT_NOT_SUPPORTED;

if (ctx.tx.getFlags() & tfUniversalMask)
{
// There are no flags (other than universal) for CreateCheck yet.
Expand Down
4 changes: 4 additions & 0 deletions src/xrpld/app/tx/detail/CreateOffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ CreateOffer::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
(isMPT(ctx.tx[sfTakerPays]) || isMPT(ctx.tx[sfTakerGets])))
return temMPT_NOT_SUPPORTED;

auto& tx = ctx.tx;
auto& j = ctx.j;

Expand Down
4 changes: 4 additions & 0 deletions src/xrpld/app/tx/detail/NFTokenAcceptOffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ NFTokenAcceptOffer::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
isMPT(ctx.tx[~sfNFTokenBrokerFee]))
return temMPT_INVALID_USAGE;

if (ctx.tx.getFlags() & tfNFTokenAcceptOfferMask)
return temINVALID_FLAG;

Expand Down
3 changes: 3 additions & 0 deletions src/xrpld/app/tx/detail/NFTokenCreateOffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ NFTokenCreateOffer::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) && isMPT(ctx.tx[sfAmount]))
return temMPT_NOT_SUPPORTED;

auto const txFlags = ctx.tx.getFlags();

if (txFlags & tfNFTokenCreateOfferMask)
Expand Down
3 changes: 3 additions & 0 deletions src/xrpld/app/tx/detail/NFTokenMint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ NFTokenMint::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) && isMPT(ctx.tx[~sfAmount]))
return temMPT_NOT_SUPPORTED;

// Prior to fixRemoveNFTokenAutoTrustLine, transfer of an NFToken between
// accounts allowed a TrustLine to be added to the issuer of that token
// without explicit permission from that issuer. This was enabled by
Expand Down
3 changes: 3 additions & 0 deletions src/xrpld/app/tx/detail/SetTrust.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ SetTrust::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) && isMPT(ctx.tx[~sfLimitAmount]))
return temMPT_INVALID_USAGE;

auto& tx = ctx.tx;
auto& j = ctx.j;

Expand Down
28 changes: 28 additions & 0 deletions src/xrpld/app/tx/detail/XChainBridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,10 @@ attestationPreflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
(isMPT(ctx.tx[sfAmount]) || isMPT(ctx.tx[~sfSignatureReward])))
return temMPT_NOT_SUPPORTED;

if (ctx.tx.getFlags() & tfUniversalMask)
return temINVALID_FLAG;

Expand Down Expand Up @@ -1383,6 +1387,11 @@ XChainCreateBridge::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
(isMPT(ctx.tx[sfSignatureReward]) ||
isMPT(ctx.tx[~sfMinAccountCreateAmount])))
return temMPT_NOT_SUPPORTED;

if (ctx.tx.getFlags() & tfUniversalMask)
return temINVALID_FLAG;

Expand Down Expand Up @@ -1564,6 +1573,11 @@ BridgeModify::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
(isMPT(ctx.tx[~sfSignatureReward]) ||
isMPT(ctx.tx[~sfMinAccountCreateAmount])))
return temMPT_NOT_SUPPORTED;

if (ctx.tx.getFlags() & tfBridgeModifyMask)
return temINVALID_FLAG;

Expand Down Expand Up @@ -1674,6 +1688,9 @@ XChainClaim::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) && isMPT(ctx.tx[sfAmount]))
return temMPT_NOT_SUPPORTED;

if (ctx.tx.getFlags() & tfUniversalMask)
return temINVALID_FLAG;

Expand Down Expand Up @@ -1912,6 +1929,9 @@ XChainCommit::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) && isMPT(ctx.tx[sfAmount]))
return temMPT_NOT_SUPPORTED;

if (ctx.tx.getFlags() & tfUniversalMask)
return temINVALID_FLAG;

Expand Down Expand Up @@ -2028,6 +2048,10 @@ XChainCreateClaimID::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
isMPT(ctx.tx[sfSignatureReward]))
return temMPT_NOT_SUPPORTED;

if (ctx.tx.getFlags() & tfUniversalMask)
return temINVALID_FLAG;

Expand Down Expand Up @@ -2183,6 +2207,10 @@ XChainCreateAccountCommit::preflight(PreflightContext const& ctx)
if (auto const ret = preflight1(ctx); !isTesSuccess(ret))
return ret;

if (ctx.rules.enabled(featureMPTokensV1) &&
(isMPT(ctx.tx[sfAmount]) || isMPT(ctx.tx[sfSignatureReward])))
return temMPT_NOT_SUPPORTED;

if (ctx.tx.getFlags() & tfUniversalMask)
return temINVALID_FLAG;

Expand Down

0 comments on commit 408dbf6

Please sign in to comment.