mirror of
https://github.com/XRPLF/rippled.git
synced 2026-10-01 01:08:03 +00:00
# Conflicts: # include/xrpl/protocol/Indexes.h # include/xrpl/protocol/LedgerFormats.h # include/xrpl/protocol/TxFlags.h # include/xrpl/protocol/jss.h # include/xrpl/tx/invariants/InvariantCheck.h # src/libxrpl/protocol/Indexes.cpp
655 lines
14 KiB
C++
655 lines
14 KiB
C++
#pragma once
|
|
|
|
#include <xrpl/basics/Slice.h>
|
|
#include <xrpl/basics/base_uint.h>
|
|
#include <xrpl/beast/utility/instrumentation.h>
|
|
#include <xrpl/json/json_value.h>
|
|
#include <xrpl/protocol/AccountID.h>
|
|
#include <xrpl/protocol/Asset.h>
|
|
#include <xrpl/protocol/Book.h>
|
|
#include <xrpl/protocol/Issue.h>
|
|
#include <xrpl/protocol/Keylet.h>
|
|
#include <xrpl/protocol/LedgerFormats.h>
|
|
#include <xrpl/protocol/Protocol.h>
|
|
#include <xrpl/protocol/STXChainBridge.h>
|
|
#include <xrpl/protocol/SeqProxy.h>
|
|
#include <xrpl/protocol/UintTypes.h>
|
|
|
|
#include <boost/endian/conversion.hpp>
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <functional>
|
|
#include <set>
|
|
#include <utility>
|
|
|
|
namespace xrpl {
|
|
|
|
class SeqProxy;
|
|
|
|
// Structured-key helpers: read/write the low 64 bits of a uint256 keylet
|
|
// in big-endian byte order. Used by every AMM keylet scheme that
|
|
// embeds an ordered subkey (tick index, bitmap-word index, bin ID) into
|
|
// the low 64 bits so SHAMap range walks visit entries in subkey order.
|
|
//
|
|
// We type-pun via std::memcpy rather than a reinterpret_cast through
|
|
// uint64_t* — the latter violates strict aliasing and has no alignment
|
|
// guarantee on base_uint's underlying byte storage. memcpy of an
|
|
// 8-byte value compiles to a single load/store on x86_64 / ARM64 under
|
|
// any optimization level, so the safer idiom is free at runtime.
|
|
inline void
|
|
setLow64BE(uint256& key, std::uint64_t value) noexcept
|
|
{
|
|
auto const be = boost::endian::native_to_big(value);
|
|
std::memcpy(key.end() - sizeof(std::uint64_t), &be, sizeof(std::uint64_t));
|
|
}
|
|
|
|
[[nodiscard]] inline std::uint64_t
|
|
getLow64BE(uint256 const& key) noexcept
|
|
{
|
|
std::uint64_t be;
|
|
std::memcpy(&be, key.end() - sizeof(std::uint64_t), sizeof(std::uint64_t));
|
|
return boost::endian::big_to_native(be);
|
|
}
|
|
/**
|
|
* Keylet computation functions.
|
|
*
|
|
* Entries in the ledger are located using 256-bit locators. The locators are
|
|
* calculated using a wide range of parameters specific to the entry whose
|
|
* locator we are calculating (e.g. an account's locator is derived from the
|
|
* account's address, whereas the locator for an offer is derived from the
|
|
* account and the offer sequence.)
|
|
*
|
|
* To enhance type safety during lookup and make the code more robust, we use
|
|
* keylets, which contain not only the locator of the object but also the type
|
|
* of the object being referenced.
|
|
*
|
|
* These functions each return a type-specific keylet.
|
|
*/
|
|
namespace keylet {
|
|
|
|
/**
|
|
* AccountID root
|
|
*/
|
|
Keylet
|
|
account(AccountID const& id) noexcept;
|
|
|
|
/**
|
|
* The index of the amendment table
|
|
*/
|
|
Keylet const&
|
|
amendments() noexcept;
|
|
|
|
/**
|
|
* Any item that can be in an owner dir.
|
|
*/
|
|
Keylet
|
|
child(uint256 const& key) noexcept;
|
|
|
|
/**
|
|
* The index of the "short" skip list
|
|
*
|
|
* The "short" skip list is a node (at a fixed index) that holds the hashes
|
|
* of ledgers since the last flag ledger. It will contain, at most, 256 hashes.
|
|
*/
|
|
Keylet const&
|
|
skip() noexcept;
|
|
|
|
/**
|
|
* The index of the long skip for a particular ledger range.
|
|
*
|
|
* The "long" skip list is a node that holds the hashes of (up to) 256 flag
|
|
* ledgers.
|
|
*
|
|
* It can be used to efficiently skip back to any ledger using only two hops:
|
|
* the first hop gets the "long" skip list for the ledger it wants to retrieve
|
|
* and uses it to get the hash of the flag ledger whose short skip list will
|
|
* contain the hash of the requested ledger.
|
|
*/
|
|
Keylet
|
|
skip(LedgerIndex ledger) noexcept;
|
|
|
|
/**
|
|
* The (fixed) index of the object containing the ledger fees.
|
|
*/
|
|
Keylet const&
|
|
feeSettings() noexcept;
|
|
|
|
/**
|
|
* The (fixed) index of the object containing the ledger negativeUNL.
|
|
*/
|
|
Keylet const&
|
|
negativeUNL() noexcept;
|
|
|
|
/**
|
|
* The beginning of an order book
|
|
*/
|
|
Keylet
|
|
book(Book const& b);
|
|
|
|
/**
|
|
* The index of a trust line for a given currency
|
|
*
|
|
* Note that a trustline is *shared* between two accounts (commonly referred
|
|
* to as the issuer and the holder); if Alice sets up a trust line to Bob for
|
|
* BTC, and Bob trusts Alice for BTC, here is only a single BTC trust line
|
|
* between them.
|
|
*/
|
|
/**
|
|
* @{.
|
|
*/
|
|
Keylet
|
|
trustLine(AccountID const& id0, AccountID const& id1, Currency const& currency) noexcept;
|
|
|
|
inline Keylet
|
|
trustLine(AccountID const& id, Issue const& issue) noexcept
|
|
{
|
|
return trustLine(id, issue.account, issue.currency);
|
|
}
|
|
/**
|
|
* @}.
|
|
*/
|
|
|
|
/**
|
|
* An offer from an account
|
|
*/
|
|
/**
|
|
* @{.
|
|
*/
|
|
Keylet
|
|
offer(AccountID const& id, SeqProxy const& seq) noexcept;
|
|
|
|
inline Keylet
|
|
offer(uint256 const& key) noexcept
|
|
{
|
|
return {ltOFFER, key};
|
|
}
|
|
/**
|
|
* @}.
|
|
*/
|
|
|
|
/**
|
|
* The initial directory page for a specific quality
|
|
*/
|
|
Keylet
|
|
quality(Keylet const& k, std::uint64_t const q) noexcept;
|
|
|
|
/**
|
|
* The directory for the next lower quality
|
|
*/
|
|
Keylet
|
|
next(Keylet const& k);
|
|
|
|
/**
|
|
* A ticket belonging to an account
|
|
*/
|
|
/**
|
|
* @{.
|
|
*/
|
|
Keylet
|
|
ticket(AccountID const& id, SeqProxy const& ticketSeq);
|
|
|
|
inline Keylet
|
|
ticket(uint256 const& key)
|
|
{
|
|
return {ltTICKET, key};
|
|
}
|
|
/**
|
|
* @}.
|
|
*/
|
|
|
|
/**
|
|
* A SignerList
|
|
*/
|
|
Keylet
|
|
signerList(AccountID const& account) noexcept;
|
|
|
|
/**
|
|
* A Sponsorship
|
|
*/
|
|
Keylet
|
|
sponsorship(AccountID const& sponsor, AccountID const& sponsee) noexcept;
|
|
|
|
/**
|
|
* A Check
|
|
*/
|
|
/**
|
|
* @{.
|
|
*/
|
|
Keylet
|
|
check(AccountID const& id, SeqProxy const& seq) noexcept;
|
|
|
|
inline Keylet
|
|
check(uint256 const& key) noexcept
|
|
{
|
|
return {ltCHECK, key};
|
|
}
|
|
/**
|
|
* @}.
|
|
*/
|
|
|
|
/**
|
|
* A DepositPreauth
|
|
*/
|
|
/**
|
|
* @{.
|
|
*/
|
|
Keylet
|
|
depositPreauth(AccountID const& owner, AccountID const& preauthorized) noexcept;
|
|
|
|
Keylet
|
|
depositPreauth(
|
|
AccountID const& owner,
|
|
std::set<std::pair<AccountID, Slice>> const& authCreds) noexcept;
|
|
|
|
inline Keylet
|
|
depositPreauth(uint256 const& key) noexcept
|
|
{
|
|
return {ltDEPOSIT_PREAUTH, key};
|
|
}
|
|
/**
|
|
* @}.
|
|
*/
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Any ledger entry
|
|
*/
|
|
Keylet
|
|
unchecked(uint256 const& key) noexcept;
|
|
|
|
/**
|
|
* The root page of an account's directory
|
|
*/
|
|
Keylet
|
|
ownerDir(AccountID const& id) noexcept;
|
|
|
|
/**
|
|
* A page in a directory
|
|
*/
|
|
/**
|
|
* @{.
|
|
*/
|
|
Keylet
|
|
page(uint256 const& root, std::uint64_t const index = 0) noexcept;
|
|
|
|
inline Keylet
|
|
page(Keylet const& root, std::uint64_t const index = 0) noexcept
|
|
{
|
|
XRPL_ASSERT(root.type == ltDIR_NODE, "xrpl::keylet::page : valid root type");
|
|
return page(root.key, index);
|
|
}
|
|
/**
|
|
* @}.
|
|
*/
|
|
|
|
/**
|
|
* An escrow entry
|
|
*/
|
|
Keylet
|
|
escrow(AccountID const& src, SeqProxy const& seq) noexcept;
|
|
|
|
inline Keylet
|
|
escrow(uint256 const& key) noexcept
|
|
{
|
|
return {ltESCROW, key};
|
|
}
|
|
|
|
/**
|
|
* A PaymentChannel
|
|
*/
|
|
Keylet
|
|
payChannel(AccountID const& src, AccountID const& dst, SeqProxy const& seq) noexcept;
|
|
|
|
/**
|
|
* NFT page keylets
|
|
*
|
|
* Unlike objects whose ledger identifiers are produced by hashing data,
|
|
* NFT page identifiers are composite identifiers, consisting of the owner's
|
|
* 160-bit AccountID, followed by a 96-bit value that determines which NFT
|
|
* tokens are candidates for that page.
|
|
*/
|
|
/**
|
|
* @{.
|
|
*/
|
|
/**
|
|
* A keylet for the owner's first possible NFT page.
|
|
*/
|
|
Keylet
|
|
nftokenPageMin(AccountID const& owner);
|
|
|
|
/**
|
|
* A keylet for the owner's last possible NFT page.
|
|
*/
|
|
Keylet
|
|
nftokenPageMax(AccountID const& owner);
|
|
|
|
Keylet
|
|
nftokenPage(Keylet const& k, uint256 const& token);
|
|
/**
|
|
* @}.
|
|
*/
|
|
|
|
/**
|
|
* An offer from an account to buy or sell an NFT
|
|
*/
|
|
Keylet
|
|
nftokenOffer(AccountID const& owner, SeqProxy const& seq);
|
|
|
|
inline Keylet
|
|
nftokenOffer(uint256 const& offer)
|
|
{
|
|
return {ltNFTOKEN_OFFER, offer};
|
|
}
|
|
|
|
/**
|
|
* The directory of buy offers for the specified NFT
|
|
*/
|
|
Keylet
|
|
nftBuys(uint256 const& id) noexcept;
|
|
|
|
/**
|
|
* The directory of sell offers for the specified NFT
|
|
*/
|
|
Keylet
|
|
nftSells(uint256 const& id) noexcept;
|
|
|
|
/**
|
|
* AMM entry
|
|
*/
|
|
Keylet
|
|
amm(Asset const& issue1, Asset const& issue2, std::uint8_t curveType = 0) noexcept;
|
|
|
|
Keylet
|
|
amm(uint256 const& amm) noexcept;
|
|
|
|
/**
|
|
* A keylet for Delegate object
|
|
*/
|
|
Keylet
|
|
delegate(AccountID const& account, AccountID const& authorizedAccount) noexcept;
|
|
|
|
Keylet
|
|
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType);
|
|
|
|
// `seq` is stored as `sfXChainClaimID` in the object
|
|
Keylet
|
|
xChainClaimID(STXChainBridge const& bridge, std::uint64_t const seq);
|
|
|
|
// `seq` is stored as `sfXChainAccountCreateCount` in the object
|
|
Keylet
|
|
xChainCreateAccountClaimID(STXChainBridge const& bridge, std::uint64_t const seq);
|
|
|
|
Keylet
|
|
did(AccountID const& account) noexcept;
|
|
|
|
Keylet
|
|
oracle(AccountID const& account, std::uint32_t const documentID) noexcept;
|
|
|
|
Keylet
|
|
credential(AccountID const& subject, AccountID const& issuer, Slice const& credType) noexcept;
|
|
|
|
inline Keylet
|
|
credential(uint256 const& key) noexcept
|
|
{
|
|
return {ltCREDENTIAL, key};
|
|
}
|
|
|
|
Keylet
|
|
mptokenIssuance(MPTID const& issuanceID) noexcept;
|
|
|
|
inline Keylet
|
|
mptokenIssuance(uint256 const& issuanceKey)
|
|
{
|
|
return {ltMPTOKEN_ISSUANCE, issuanceKey};
|
|
}
|
|
|
|
Keylet
|
|
tokenIssuance(AccountID const& issuer, Currency const& currency) noexcept;
|
|
|
|
inline Keylet
|
|
tokenIssuance(uint256 const& key)
|
|
{
|
|
return {ltTOKEN_ISSUANCE, key};
|
|
}
|
|
|
|
Keylet
|
|
mptoken(MPTID const& issuanceID, AccountID const& holder) noexcept;
|
|
|
|
inline Keylet
|
|
mptoken(uint256 const& mptokenKey)
|
|
{
|
|
return {ltMPTOKEN, mptokenKey};
|
|
}
|
|
|
|
Keylet
|
|
mptoken(uint256 const& issuanceKey, AccountID const& holder) noexcept;
|
|
|
|
Keylet
|
|
vault(AccountID const& owner, SeqProxy const& seq) noexcept;
|
|
|
|
inline Keylet
|
|
vault(uint256 const& vaultKey)
|
|
{
|
|
return {ltVAULT, vaultKey};
|
|
}
|
|
|
|
Keylet
|
|
loanBroker(AccountID const& owner, SeqProxy const& seq) noexcept;
|
|
|
|
inline Keylet
|
|
loanBroker(uint256 const& key)
|
|
{
|
|
return {ltLOAN_BROKER, key};
|
|
}
|
|
|
|
Keylet
|
|
loan(uint256 const& loanBrokerID, SeqProxy const& loanSeq) noexcept;
|
|
|
|
inline Keylet
|
|
loan(uint256 const& key)
|
|
{
|
|
return {ltLOAN, key};
|
|
}
|
|
|
|
Keylet
|
|
couponSchedule(uint192 const& mptIssuanceID) noexcept;
|
|
|
|
inline Keylet
|
|
couponSchedule(uint256 const& scheduleKey)
|
|
{
|
|
return {ltCOUPON_SCHEDULE, scheduleKey};
|
|
}
|
|
|
|
Keylet
|
|
permissionedDomain(AccountID const& account, SeqProxy const& seq) noexcept;
|
|
|
|
Keylet
|
|
permissionedDomain(uint256 const& domainID) noexcept;
|
|
|
|
Keylet
|
|
contractSource(uint256 const& contractHash) noexcept;
|
|
|
|
Keylet
|
|
contract(uint256 const& contractHash, AccountID const& owner, std::uint32_t seq) noexcept;
|
|
|
|
inline Keylet
|
|
contract(uint256 const& contractID)
|
|
{
|
|
return {ltCONTRACT, contractID};
|
|
}
|
|
|
|
Keylet
|
|
contractData(AccountID const& owner, AccountID const& contractAccount) noexcept;
|
|
|
|
Keylet
|
|
passkeyList(AccountID const& account) noexcept;
|
|
|
|
/**
|
|
* A ballot owned by `owner`, keyed by the creating transaction sequence.
|
|
*/
|
|
Keylet
|
|
ballot(AccountID const& owner, std::uint32_t seq) noexcept;
|
|
|
|
inline Keylet
|
|
ballot(uint256 const& ballotID)
|
|
{
|
|
return {ltBALLOT, ballotID};
|
|
}
|
|
|
|
/**
|
|
* A voter's cast on the ballot identified by `ballotID`.
|
|
*/
|
|
Keylet
|
|
ballotVote(uint256 const& ballotID, AccountID const& voter) noexcept;
|
|
|
|
inline Keylet
|
|
ballotVote(uint256 const& key)
|
|
{
|
|
return {ltBALLOT_VOTE, key};
|
|
}
|
|
/**
|
|
* A concentrated liquidity AMM position.
|
|
*/
|
|
Keylet
|
|
ammPosition(uint256 const& ammID, AccountID const& owner, std::uint32_t seq) noexcept;
|
|
|
|
inline Keylet
|
|
ammPosition(uint256 const& key)
|
|
{
|
|
return {ltAMM_POSITION, key};
|
|
}
|
|
|
|
/**
|
|
* A concentrated liquidity AMM tick.
|
|
* Uses structured (non-hashed) keys for ordered SHAMap traversal.
|
|
* High 192 bits: pool scope (from ammID hash).
|
|
* Low 64 bits: encoded tick index (offset binary, big-endian).
|
|
*/
|
|
Keylet
|
|
ammTick(uint256 const& ammID, std::int32_t tickIndex) noexcept;
|
|
|
|
inline Keylet
|
|
ammTick(uint256 const& key)
|
|
{
|
|
return {ltAMM_TICK, key};
|
|
}
|
|
|
|
/**
|
|
* Base key for a CL pool's tick range (low 64 bits zeroed).
|
|
*/
|
|
Keylet
|
|
ammTickBase(uint256 const& ammID) noexcept;
|
|
|
|
/**
|
|
* End key for a CL pool's tick range (low 64 bits all 1s).
|
|
*/
|
|
Keylet
|
|
ammTickEnd(uint256 const& ammID) noexcept;
|
|
|
|
/**
|
|
* A 256-tick presence bitmap window for a CL pool.
|
|
* Keylet structure mirrors `ammTick`: high 192 bits derive from a pool-scoped
|
|
* hash, low 64 bits encode the word index (big-endian) so range walks via
|
|
* SHAMap succ/pred yield the next-higher / next-lower word.
|
|
*/
|
|
Keylet
|
|
ammTickBitmapWord(uint256 const& ammID, std::uint16_t wordIndex) noexcept;
|
|
|
|
inline Keylet
|
|
ammTickBitmapWord(uint256 const& key)
|
|
{
|
|
return {ltAMM_TICK_BITMAP, key};
|
|
}
|
|
|
|
/**
|
|
* Base key for a CL pool's tick-bitmap range (low 64 bits zeroed).
|
|
*/
|
|
Keylet
|
|
ammTickBitmapBase(uint256 const& ammID) noexcept;
|
|
|
|
/**
|
|
* End key for a CL pool's tick-bitmap range (low 64 bits all 1s).
|
|
*/
|
|
Keylet
|
|
ammTickBitmapEnd(uint256 const& ammID) noexcept;
|
|
|
|
/**
|
|
* A single bin within a CtBinned AMM pool. Bins are keyed by signed
|
|
* bin ID, offset-encoded into the low 64 bits of the keylet so SHAMap
|
|
* range walks yield consecutive bins in price order.
|
|
*/
|
|
Keylet
|
|
ammBin(uint256 const& ammID, std::int32_t binID) noexcept;
|
|
|
|
/**
|
|
* Lookup a bin SLE by its raw key (used by transactors that have a
|
|
* stored issuance / bin reference).
|
|
*/
|
|
Keylet
|
|
ammBin(uint256 const& key) noexcept;
|
|
|
|
/**
|
|
* Base / end keys for a binned AMM's bin-SLE range. Bins for the
|
|
* same AMM are contiguous in SHAMap order (high 192 bits are an
|
|
* ammID-scoped hash; low 64 bits offset-encode the bin ID), so
|
|
* `view.succ(bin_at(binID).key, ammBinEnd(ammID).key)` jumps to the
|
|
* next populated bin in O(log n) regardless of gap size.
|
|
*/
|
|
Keylet
|
|
ammBinBase(uint256 const& ammID) noexcept;
|
|
|
|
Keylet
|
|
ammBinEnd(uint256 const& ammID) noexcept;
|
|
|
|
/**
|
|
* A single LP's holding record in a single bin. Phase 5 will replace
|
|
* this with a fungible MPT issuance per bin.
|
|
*/
|
|
Keylet
|
|
ammBinHolding(uint256 const& ammID, AccountID const& owner, std::int32_t binID) noexcept;
|
|
|
|
Keylet
|
|
ammBinHolding(uint256 const& key) noexcept;
|
|
|
|
Keylet
|
|
subscription(AccountID const& account, AccountID const& dest, std::uint32_t seq) noexcept;
|
|
|
|
inline Keylet
|
|
subscription(uint256 const& key) noexcept
|
|
{
|
|
return {ltSUBSCRIPTION, key};
|
|
}
|
|
} // namespace keylet
|
|
|
|
// Everything below is deprecated and should be removed in favor of keylets:
|
|
|
|
uint256
|
|
getBookBase(Book const& book);
|
|
|
|
uint256
|
|
getQualityNext(uint256 const& uBase);
|
|
|
|
// VFALCO This name could be better
|
|
std::uint64_t
|
|
getQuality(uint256 const& uBase);
|
|
|
|
template <class... KeyletParams>
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
|
|
struct KeyletDesc
|
|
{
|
|
std::function<Keylet(KeyletParams...)> function;
|
|
json::StaticString expectedLEName;
|
|
bool includeInTests{};
|
|
};
|
|
|
|
// This list should include all of the keylet functions that take a single AccountID parameter.
|
|
extern std::array<KeyletDesc<AccountID const&>, 6> const kDirectAccountKeylets;
|
|
|
|
MPTID
|
|
makeMptID(std::uint32_t const sequence, AccountID const& account);
|
|
|
|
} // namespace xrpl
|