Skip to content

Commit 2a8861d

Browse files
committed
DomainID authorization check moved to doApply
1 parent df8761d commit 2a8861d

File tree

4 files changed

+42
-28
lines changed

4 files changed

+42
-28
lines changed

src/test/app/Vault_test.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ class Vault_test : public beast::unit_test::suite
720720
.id = keylet.key,
721721
.amount = asset(50)});
722722
env(tx, ter{tecNO_AUTH});
723+
env.close();
723724
}
724725

725726
{
@@ -733,6 +734,7 @@ class Vault_test : public beast::unit_test::suite
733734
.id = keylet.key,
734735
.amount = asset(50)});
735736
env(tx);
737+
env.close();
736738
}
737739

738740
{

src/xrpld/app/tx/detail/VaultDeposit.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,27 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
7171
if (isFrozen(ctx.view, account, share))
7272
return tecFROZEN;
7373

74-
if (vault->getFlags() == tfVaultPrivate && account != vault->at(sfOwner))
74+
if ((vault->getFlags() & tfVaultPrivate) && account != vault->at(sfOwner))
7575
{
76+
// The authorization check below is based on DomainID stored in
77+
// MPTokenIssuance. Had the vault shares been a regular MPToken, we
78+
// would allow authorization granted by the issuer explicitly, but Vault
79+
// does not have an MPT issuer (instead it uses pseudo-account, which is
80+
// blackholed and cannot create any transactions).
81+
//
82+
// We also need to do similar check inside doApply(), in order to remove
83+
// expired credentials and/or adjust authorization flag on tokens owned
84+
// by DomainID (i.e. with lsfMPTDomainCheck flag). This is why we
85+
// suppress authorization errors if domainId is set.
86+
uint256 domainId = beast::zero;
7687
auto const err = requireAuth(
77-
ctx.view, MPTIssue(vault->at(sfMPTokenIssuanceID)), account);
78-
return err;
88+
ctx.view,
89+
MPTIssue(vault->at(sfMPTokenIssuanceID)),
90+
account,
91+
&domainId);
7992

80-
// The above will perform authorization check based on DomainID stored
81-
// in MPTokenIssuance. Had this been a regular MPToken, it would also
82-
// allow use of authorization granted by the issuer explicitly, but
83-
// Vault does not have an MPT issuer (instead it uses pseudo-account).
84-
//
85-
// If we passed the above check then we also need to do similar check
86-
// inside doApply(), in order to check for expired credentials.
93+
if (domainId == beast::zero)
94+
return err;
8795
}
8896

8997
return tesSUCCESS;
@@ -120,7 +128,7 @@ VaultDeposit::doApply()
120128

121129
MPTIssue const mptIssue(mptIssuanceID);
122130
// Note, vault owner is always authorized
123-
if (account_ != vault->at(sfOwner) && (vault->getFlags() & tfVaultPrivate))
131+
if ((vault->getFlags() & tfVaultPrivate) && account_ != vault->at(sfOwner))
124132
{
125133
if (auto const err = enforceMPTokenAuthorization(
126134
ctx_.view(), mptIssue, account_, mPriorBalance, j_);

src/xrpld/ledger/View.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,8 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account);
654654
requireAuth(
655655
ReadView const& view,
656656
MPTIssue const& mptIssue,
657-
AccountID const& account);
657+
AccountID const& account,
658+
uint256* domainId = nullptr);
658659

659660
/** Check if the account lacks required authorization.
660661
*

src/xrpld/ledger/detail/View.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2183,7 +2183,8 @@ TER
21832183
requireAuth(
21842184
ReadView const& view,
21852185
MPTIssue const& mptIssue,
2186-
AccountID const& account)
2186+
AccountID const& account,
2187+
uint256* domainId)
21872188
{
21882189
auto const mptID = keylet::mptIssuance(mptIssue.getMptID());
21892190
auto const sleIssuance = view.read(mptID);
@@ -2220,7 +2221,12 @@ requireAuth(
22202221
if (auto const err =
22212222
credentials::validDomain(view, *maybeDomainID, account);
22222223
!isTesSuccess(err))
2224+
{
2225+
if (err != tecINVALID_DOMAIN && domainId != nullptr)
2226+
(*domainId) = *maybeDomainID;
2227+
22232228
return err;
2229+
}
22242230

22252231
// We are authorized by permissioned domain.
22262232
return tesSUCCESS;
@@ -2237,16 +2243,17 @@ enforceMPTokenAuthorization(
22372243
auto const mptIssuanceID = mptIssue.getMptID();
22382244
auto const sleIssuance = view.read(keylet::mptIssuance(mptIssuanceID));
22392245
if (!sleIssuance)
2240-
return tefINTERNAL; // Should have called requireAuth earlier
2246+
return tefINTERNAL;
22412247

22422248
XRPL_ASSERT(
2243-
sleIssuance->getFieldU32(sfFlags) & lsfMPTRequireAuth,
2249+
sleIssuance->getFlags() & lsfMPTRequireAuth,
22442250
"ripple::verifyAuth : MPTokenIssuance requires authorization");
22452251

22462252
if (account == sleIssuance->at(sfIssuer))
22472253
return tesSUCCESS; // Won't create MPToken for the token issuer
22482254

2249-
auto sleToken = view.read(keylet::mptoken(mptIssuanceID, account));
2255+
auto const keylet = keylet::mptoken(mptIssuanceID, account);
2256+
auto sleToken = view.read(keylet);
22502257
bool const domainOwned =
22512258
(sleToken && (sleToken->getFlags() & lsfMPTDomainCheck));
22522259

@@ -2282,16 +2289,15 @@ enforceMPTokenAuthorization(
22822289
{
22832290
// We found an MPToken with lsfMPTDomainCheck flag, but the account is
22842291
// no longer authorized.
2285-
if (sleToken->getFieldU32(sfFlags) & lsfMPTAuthorized)
2292+
if (sleToken->getFlags() & lsfMPTAuthorized)
22862293
{
22872294
// Must reset lsfMPTAuthorized, no current credentials
2288-
auto sleMpt = view.peek(keylet::mptoken(mptIssuanceID, account));
2295+
auto sleMpt = view.peek(keylet);
22892296
XRPL_ASSERT(sleMpt, "ripple::verifyAuth : non-null bad MPToken");
2290-
std::uint32_t const flags = sleMpt->getFieldU32(sfFlags);
2291-
sleMpt->setFieldU32(sfFlags, flags & ~lsfMPTAuthorized);
2297+
sleMpt->clearFlag(lsfMPTAuthorized);
22922298
view.update(sleMpt);
22932299

2294-
sleToken = nullptr; // return tecNO_AUTH at the end of function
2300+
sleToken = sleMpt; // without lsfMPTAuthorized
22952301
}
22962302
}
22972303
else if (!authorizedByDomain)
@@ -2310,10 +2316,9 @@ enforceMPTokenAuthorization(
23102316
if ((sleToken->getFlags() & lsfMPTAuthorized) == 0)
23112317
{
23122318
// Must set lsfMPTAuthorized, we found new credentials
2313-
auto sleMpt = view.peek(keylet::mptoken(mptIssuanceID, account));
2319+
auto sleMpt = view.peek(keylet);
23142320
XRPL_ASSERT(sleMpt, "ripple::verifyAuth : non-null good MPToken");
2315-
std::uint32_t const flags = sleMpt->getFieldU32(sfFlags);
2316-
sleMpt->setFieldU32(sfFlags, flags | lsfMPTAuthorized);
2321+
sleMpt->setFlag(lsfMPTAuthorized);
23172322
view.update(sleMpt);
23182323

23192324
sleToken = sleMpt; // with lsfMPTAuthorized
@@ -2334,11 +2339,9 @@ enforceMPTokenAuthorization(
23342339
!isTesSuccess(err))
23352340
return err;
23362341

2337-
auto sleMpt = view.peek(keylet::mptoken(mptIssuanceID, account));
2342+
auto sleMpt = view.peek(keylet);
23382343
XRPL_ASSERT(sleMpt, "ripple::verifyAuth : non-null new MPToken");
2339-
std::uint32_t const flags = sleMpt->getFieldU32(sfFlags);
2340-
sleMpt->setFieldU32(
2341-
sfFlags, flags | lsfMPTDomainCheck | lsfMPTAuthorized);
2344+
sleMpt->setFlag(lsfMPTDomainCheck | lsfMPTAuthorized);
23422345
view.update(sleMpt);
23432346

23442347
sleToken = sleMpt; // with lsfMPTAuthorized

0 commit comments

Comments
 (0)