Files
rippled/src/libxrpl/ledger/CanonicalTXSet.cpp
2026-04-17 16:43:49 +00:00

85 lines
2.3 KiB
C++

#include <xrpl/ledger/CanonicalTXSet.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STTx.h>
#include <cstring>
#include <memory>
#include <utility>
namespace xrpl {
bool
operator<(CanonicalTXSet::Key const& lhs, CanonicalTXSet::Key const& rhs)
{
if (lhs.account_ < rhs.account_)
return true;
if (lhs.account_ > rhs.account_)
return false;
if (lhs.seqProxy_ < rhs.seqProxy_)
return true;
if (lhs.seqProxy_ > rhs.seqProxy_)
return false;
return lhs.txId_ < rhs.txId_;
}
uint256
CanonicalTXSet::accountKey(AccountID const& account)
{
uint256 ret = beast::zero;
memcpy(ret.begin(), account.begin(), account.size());
ret ^= salt_;
return ret;
}
void
CanonicalTXSet::insert(std::shared_ptr<STTx const> const& txn)
{
map_.insert(
std::make_pair(
Key(accountKey(txn->getAccountID(sfAccount)),
txn->getSeqProxy(),
txn->getTransactionID()),
txn));
}
std::shared_ptr<STTx const>
CanonicalTXSet::popAcctTransaction(std::shared_ptr<STTx const> const& tx)
{
// Determining the next viable transaction for an account with Tickets:
//
// 1. Prioritize transactions with Sequences over transactions with
// Tickets.
//
// 2. For transactions not using Tickets, look for consecutive Sequence
// numbers. For transactions using Tickets, don't worry about
// consecutive Sequence numbers. Tickets can process out of order.
//
// 3. After handling all transactions with Sequences, return Tickets
// with the lowest Ticket ID first.
std::shared_ptr<STTx const> result;
uint256 const effectiveAccount{accountKey(tx->getAccountID(sfAccount))};
auto const seqProxy = tx->getSeqProxy();
Key const after(effectiveAccount, seqProxy, beast::zero);
auto const itrNext{map_.lower_bound(after)};
if (itrNext != map_.end() && itrNext->first.getAccount() == effectiveAccount &&
(!itrNext->second->getSeqProxy().isSeq() ||
itrNext->second->getSeqProxy().value() == seqProxy.value() + 1))
{
result = std::move(itrNext->second);
map_.erase(itrNext);
}
return result;
}
} // namespace xrpl