Fix bug in pseudoAccountAddress and add unit test

This commit is contained in:
Bronek Kozicki
2025-03-28 20:53:02 +00:00
parent d3c1d02c72
commit 1807b441ee
2 changed files with 35 additions and 3 deletions

View File

@@ -19,6 +19,7 @@
#include <test/jtx/Account.h>
#include <test/jtx/Env.h>
#include <test/jtx/amount.h>
#include <test/jtx/credentials.h>
#include <test/jtx/fee.h>
#include <test/jtx/mpt.h>
@@ -26,6 +27,8 @@
#include <test/jtx/utility.h>
#include <test/jtx/vault.h>
#include <xrpld/ledger/View.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/unit_test/suite.h>
#include <xrpl/json/json_forwards.h>
@@ -1159,6 +1162,35 @@ class Vault_test : public beast::unit_test::suite
}
}
void
testFailedPseudoAccount()
{
using namespace test::jtx;
testcase("failed pseudo-account allocation");
Env env{*this};
Account const owner{"owner"};
Vault vault{env};
env.fund(XRP(1000), owner);
auto const keylet = keylet::vault(owner.id(), env.seq(owner));
for (int i = 0; i < 256; ++i)
{
AccountID const accountId =
ripple::pseudoAccountAddress(*env.current(), keylet.key);
env(pay(env.master.id(), accountId, XRP(1000)),
seq(autofill),
fee(autofill),
sig(autofill));
}
auto [tx, keylet1] =
vault.create({.owner = owner, .asset = xrpIssue()});
BEAST_EXPECT(keylet.key == keylet1.key);
env(tx, ter{terADDRESS_COLLISION});
}
public:
void
run() override
@@ -1171,6 +1203,7 @@ public:
testWithIOU();
testWithDomainCheck();
testNonTransferableShares();
testFailedPseudoAccount();
}
};

View File

@@ -1040,7 +1040,6 @@ dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr<SLE>& object)
AccountID
pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey)
{
AccountID ret = beast::zero;
// This number must not be changed without an amendment
constexpr int maxAccountAttempts = 256;
for (auto i = 0; i < maxAccountAttempts; ++i)
@@ -1048,11 +1047,11 @@ pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey)
ripesha_hasher rsh;
auto const hash = sha512Half(i, view.info().parentHash, pseudoOwnerKey);
rsh(hash.data(), hash.size());
ret = static_cast<ripesha_hasher::result_type>(rsh);
AccountID const ret{static_cast<ripesha_hasher::result_type>(rsh)};
if (!view.read(keylet::account(ret)))
return ret;
}
return ret;
return beast::zero;
}
Expected<std::shared_ptr<SLE>, TER>