mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 19:15:54 +00:00
Return terADDRESS_COLLISION from preclaim if cannot allocate AccountID
This commit is contained in:
@@ -225,6 +225,8 @@ enum TERcodes : TERUnderlyingType {
|
|||||||
terQUEUED, // Transaction is being held in TxQ until fee drops
|
terQUEUED, // Transaction is being held in TxQ until fee drops
|
||||||
terPRE_TICKET, // Ticket is not yet in ledger but might be on its way
|
terPRE_TICKET, // Ticket is not yet in ledger but might be on its way
|
||||||
terNO_AMM, // AMM doesn't exist for the asset pair
|
terNO_AMM, // AMM doesn't exist for the asset pair
|
||||||
|
terADDRESS_COLLISION, // Failed to allocate AccountID when trying to
|
||||||
|
// create a pseudo-account
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -231,6 +231,7 @@ transResults()
|
|||||||
MAKE_ERROR(terQUEUED, "Held until escalated fee drops."),
|
MAKE_ERROR(terQUEUED, "Held until escalated fee drops."),
|
||||||
MAKE_ERROR(terPRE_TICKET, "Ticket is not yet in ledger."),
|
MAKE_ERROR(terPRE_TICKET, "Ticket is not yet in ledger."),
|
||||||
MAKE_ERROR(terNO_AMM, "AMM doesn't exist for the asset pair."),
|
MAKE_ERROR(terNO_AMM, "AMM doesn't exist for the asset pair."),
|
||||||
|
MAKE_ERROR(terADDRESS_COLLISION, "Failed to allocate an unique account address"),
|
||||||
|
|
||||||
MAKE_ERROR(tesSUCCESS, "The transaction was applied. Only final in a validated ledger."),
|
MAKE_ERROR(tesSUCCESS, "The transaction was applied. Only final in a validated ledger."),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -119,6 +119,12 @@ VaultCreate::preclaim(PreclaimContext const& ctx)
|
|||||||
return tecOBJECT_NOT_FOUND;
|
return tecOBJECT_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto sequence = ctx.tx.getSeqValue();
|
||||||
|
if (auto const accountId = pseudoAccountAddress(
|
||||||
|
ctx.view, keylet::vault(account, sequence).key);
|
||||||
|
accountId == beast::zero)
|
||||||
|
return terADDRESS_COLLISION;
|
||||||
|
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -488,6 +488,9 @@ describeOwnerDir(AccountID const& account);
|
|||||||
[[nodiscard]] TER
|
[[nodiscard]] TER
|
||||||
dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr<SLE>& object);
|
dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr<SLE>& object);
|
||||||
|
|
||||||
|
AccountID
|
||||||
|
pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey);
|
||||||
|
|
||||||
// Which of the owner-object fields should we set: sfAMMID, sfVaultID
|
// Which of the owner-object fields should we set: sfAMMID, sfVaultID
|
||||||
enum class PseudoAccountOwnerType : int { AMM, Vault };
|
enum class PseudoAccountOwnerType : int { AMM, Vault };
|
||||||
|
|
||||||
|
|||||||
@@ -1037,29 +1037,31 @@ dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr<SLE>& object)
|
|||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
if (!view.read(keylet::account(ret)))
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
Expected<std::shared_ptr<SLE>, TER>
|
Expected<std::shared_ptr<SLE>, TER>
|
||||||
createPseudoAccount(
|
createPseudoAccount(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
uint256 const& pseudoOwnerKey,
|
uint256 const& pseudoOwnerKey,
|
||||||
PseudoAccountOwnerType type)
|
PseudoAccountOwnerType type)
|
||||||
{
|
{
|
||||||
auto const accountId = [&]() -> AccountID {
|
auto const accountId = pseudoAccountAddress(view, 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)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
if (!view.read(keylet::account(ret)))
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}();
|
|
||||||
|
|
||||||
if (accountId == beast::zero)
|
if (accountId == beast::zero)
|
||||||
return Unexpected(tecDUPLICATE);
|
return Unexpected(tecDUPLICATE);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user