Add invariant checks for pseudo-account

This commit is contained in:
Bronek Kozicki
2025-03-28 17:04:38 +00:00
parent 696cf2b563
commit aff08b7543
4 changed files with 108 additions and 3 deletions

View File

@@ -59,6 +59,17 @@ private:
XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0}));
});
// XRP to IOU, without featureSingleAssetVault
testAMM(
[&](AMM& ammAlice, Env&) {
BEAST_EXPECT(ammAlice.expectBalances(
XRP(10'000), USD(10'000), IOUAmount{10'000'000, 0}));
},
{},
0,
{},
{supported_amendments() - featureSingleAssetVault});
// IOU to IOU
testAMM(
[&](AMM& ammAlice, Env&) {

View File

@@ -829,6 +829,74 @@ class Invariants_test : public beast::unit_test::suite
},
XRPAmount{},
STTx{ttPAYMENT, [](STObject& tx) {}});
doInvariantCheck(
{{"pseudo-account created by a wrong transaction type"}},
[](Account const&, Account const&, ApplyContext& ac) {
Account const A3{"A3"};
Keylet const acctKeylet = keylet::account(A3);
auto const sleNew = std::make_shared<SLE>(acctKeylet);
sleNew->setFieldU32(sfSequence, 0);
sleNew->setFieldH256(sfAMMID, uint256(1));
sleNew->setFieldU32(
sfFlags,
lsfDisableMaster | lsfDefaultRipple | lsfDefaultRipple);
ac.view().insert(sleNew);
return true;
},
XRPAmount{},
STTx{ttPAYMENT, [](STObject& tx) {}});
doInvariantCheck(
{{"account created with wrong starting sequence number"}},
[](Account const&, Account const&, ApplyContext& ac) {
Account const A3{"A3"};
Keylet const acctKeylet = keylet::account(A3);
auto const sleNew = std::make_shared<SLE>(acctKeylet);
sleNew->setFieldU32(sfSequence, ac.view().seq());
sleNew->setFieldH256(sfAMMID, uint256(1));
sleNew->setFieldU32(
sfFlags,
lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth);
ac.view().insert(sleNew);
return true;
},
XRPAmount{},
STTx{ttAMM_CREATE, [](STObject& tx) {}});
doInvariantCheck(
{{"pseudo-account created with wrong flags"}},
[](Account const&, Account const&, ApplyContext& ac) {
Account const A3{"A3"};
Keylet const acctKeylet = keylet::account(A3);
auto const sleNew = std::make_shared<SLE>(acctKeylet);
sleNew->setFieldU32(sfSequence, 0);
sleNew->setFieldH256(sfAMMID, uint256(1));
sleNew->setFieldU32(
sfFlags, lsfDisableMaster | lsfDefaultRipple);
ac.view().insert(sleNew);
return true;
},
XRPAmount{},
STTx{ttVAULT_CREATE, [](STObject& tx) {}});
doInvariantCheck(
{{"pseudo-account created with wrong flags"}},
[](Account const&, Account const&, ApplyContext& ac) {
Account const A3{"A3"};
Keylet const acctKeylet = keylet::account(A3);
auto const sleNew = std::make_shared<SLE>(acctKeylet);
sleNew->setFieldU32(sfSequence, 0);
sleNew->setFieldH256(sfAMMID, uint256(1));
sleNew->setFieldU32(
sfFlags,
lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth |
lsfRequireDestTag);
ac.view().insert(sleNew);
return true;
},
XRPAmount{},
STTx{ttAMM_CREATE, [](STObject& tx) {}});
}
void

View File

@@ -886,6 +886,7 @@ ValidNewAccountRoot::visitEntry(
accountSeq_ = (*after)[sfSequence];
pseudoAccount_ =
after->isFieldPresent(sfAMMID) || after->isFieldPresent(sfVaultID);
flags_ = after->getFlags();
}
}
@@ -914,9 +915,19 @@ ValidNewAccountRoot::finalize(
tx.getTxnType() == ttXCHAIN_ADD_ACCOUNT_CREATE_ATTESTATION) &&
result == tesSUCCESS)
{
bool const pseudoAccount =
(pseudoAccount_ && view.rules().enabled(featureSingleAssetVault));
if (pseudoAccount && tx.getTxnType() != ttAMM_CREATE &&
tx.getTxnType() != ttVAULT_CREATE)
{
JLOG(j.fatal()) << "Invariant failed: pseudo-account created by a "
"wrong transaction type";
return false;
}
std::uint32_t const startingSeq = //
(pseudoAccount_ &&
view.rules().enabled(featureSingleAssetVault)) //
pseudoAccount //
? 0 //
: view.rules().enabled(featureDeletableAccounts) //
? view.seq() //
@@ -928,6 +939,20 @@ ValidNewAccountRoot::finalize(
"wrong starting sequence number";
return false;
}
if (pseudoAccount)
{
std::uint32_t const expected =
(lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth);
if (flags_ != expected)
{
JLOG(j.fatal())
<< "Invariant failed: pseudo-account created with "
"wrong flags";
return false;
}
}
return true;
}

View File

@@ -439,6 +439,7 @@ class ValidNewAccountRoot
std::uint32_t accountsCreated_ = 0;
std::uint32_t accountSeq_ = 0;
bool pseudoAccount_ = false;
std::uint32_t flags_ = 0;
public:
void