Files
rippled/src/libxrpl/protocol/TxMeta.cpp
Bart 1eb0fdac65 refactor: Rename ripple namespace to xrpl (#5982)
This change renames all occurrences of `namespace ripple` and `ripple::` to `namespace xrpl` and `xrpl::`, respectively, as well as the names of test suites. It also provides a script to allow developers to replicate the changes in their local branch or fork to avoid conflicts.
2025-12-11 16:51:49 +00:00

233 lines
6.9 KiB
C++

#include <xrpl/basics/Blob.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STAccount.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxMeta.h>
#include <boost/container/flat_set.hpp>
#include <cstdint>
#include <stdexcept>
#include <string>
namespace xrpl {
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
: transactionID_(txid)
, ledgerSeq_(ledger)
, nodes_(obj.getFieldArray(sfAffectedNodes))
{
result_ = obj.getFieldU8(sfTransactionResult);
index_ = obj.getFieldU32(sfTransactionIndex);
auto affectedNodes =
dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
XRPL_ASSERT(
affectedNodes, "xrpl::TxMeta::TxMeta(STObject) : type cast succeeded");
if (affectedNodes)
nodes_ = *affectedNodes;
setAdditionalFields(obj);
}
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
: transactionID_(txid), ledgerSeq_(ledger), nodes_(sfAffectedNodes, 32)
{
SerialIter sit(makeSlice(vec));
STObject obj(sit, sfMetadata);
result_ = obj.getFieldU8(sfTransactionResult);
index_ = obj.getFieldU32(sfTransactionIndex);
nodes_ = obj.getFieldArray(sfAffectedNodes);
setAdditionalFields(obj);
}
TxMeta::TxMeta(uint256 const& transactionID, std::uint32_t ledger)
: transactionID_(transactionID)
, ledgerSeq_(ledger)
, index_(std::numeric_limits<std::uint32_t>::max())
, result_(255)
, nodes_(sfAffectedNodes)
{
nodes_.reserve(32);
}
void
TxMeta::setAffectedNode(
uint256 const& node,
SField const& type,
std::uint16_t nodeType)
{
// make sure the node exists and force its type
for (auto& n : nodes_)
{
if (n.getFieldH256(sfLedgerIndex) == node)
{
n.setFName(type);
n.setFieldU16(sfLedgerEntryType, nodeType);
return;
}
}
nodes_.push_back(STObject(type));
STObject& obj = nodes_.back();
XRPL_ASSERT(
obj.getFName() == type,
"xrpl::TxMeta::setAffectedNode : field type match");
obj.setFieldH256(sfLedgerIndex, node);
obj.setFieldU16(sfLedgerEntryType, nodeType);
}
boost::container::flat_set<AccountID>
TxMeta::getAffectedAccounts() const
{
boost::container::flat_set<AccountID> list;
list.reserve(10);
// This code should match the behavior of the JS method:
// Meta#getAffectedAccounts
for (auto const& node : nodes_)
{
int index = node.getFieldIndex(
(node.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
if (index != -1)
{
auto const* inner =
dynamic_cast<STObject const*>(&node.peekAtIndex(index));
XRPL_ASSERT(
inner,
"xrpl::getAffectedAccounts : STObject type cast succeeded");
if (inner)
{
for (auto const& field : *inner)
{
if (auto sa = dynamic_cast<STAccount const*>(&field))
{
XRPL_ASSERT(
!sa->isDefault(),
"xrpl::getAffectedAccounts : account is set");
if (!sa->isDefault())
list.insert(sa->value());
}
else if (
(field.getFName() == sfLowLimit) ||
(field.getFName() == sfHighLimit) ||
(field.getFName() == sfTakerPays) ||
(field.getFName() == sfTakerGets))
{
auto lim = dynamic_cast<STAmount const*>(&field);
XRPL_ASSERT(
lim,
"xrpl::getAffectedAccounts : STAmount type cast "
"succeeded");
if (lim != nullptr)
{
auto issuer = lim->getIssuer();
if (issuer.isNonZero())
list.insert(issuer);
}
}
else if (field.getFName() == sfMPTokenIssuanceID)
{
auto mptID =
dynamic_cast<STBitString<192> const*>(&field);
if (mptID != nullptr)
{
auto issuer = MPTIssue(mptID->value()).getIssuer();
if (issuer.isNonZero())
list.insert(issuer);
}
}
}
}
}
}
return list;
}
STObject&
TxMeta::getAffectedNode(SLE::ref node, SField const& type)
{
uint256 index = node->key();
for (auto& n : nodes_)
{
if (n.getFieldH256(sfLedgerIndex) == index)
return n;
}
nodes_.push_back(STObject(type));
STObject& obj = nodes_.back();
XRPL_ASSERT(
obj.getFName() == type,
"xrpl::TxMeta::getAffectedNode(SLE::ref) : field type match");
obj.setFieldH256(sfLedgerIndex, index);
obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType));
return obj;
}
STObject&
TxMeta::getAffectedNode(uint256 const& node)
{
for (auto& n : nodes_)
{
if (n.getFieldH256(sfLedgerIndex) == node)
return n;
}
// LCOV_EXCL_START
UNREACHABLE("xrpl::TxMeta::getAffectedNode(uint256) : node not found");
Throw<std::runtime_error>("Affected node not found");
return *(nodes_.begin()); // Silence compiler warning.
// LCOV_EXCL_STOP
}
STObject
TxMeta::getAsObject() const
{
STObject metaData(sfTransactionMetaData);
XRPL_ASSERT(result_ != 255, "xrpl::TxMeta::getAsObject : result_ is set");
metaData.setFieldU8(sfTransactionResult, result_);
metaData.setFieldU32(sfTransactionIndex, index_);
metaData.emplace_back(nodes_);
if (deliveredAmount_.has_value())
metaData.setFieldAmount(sfDeliveredAmount, *deliveredAmount_);
if (parentBatchID_.has_value())
metaData.setFieldH256(sfParentBatchID, *parentBatchID_);
return metaData;
}
void
TxMeta::addRaw(Serializer& s, TER result, std::uint32_t index)
{
result_ = TERtoInt(result);
index_ = index;
XRPL_ASSERT(
(result_ == 0) || ((result_ > 100) && (result_ <= 255)),
"xrpl::TxMeta::addRaw : valid TER input");
nodes_.sort([](STObject const& o1, STObject const& o2) {
return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex);
});
getAsObject().add(s);
}
} // namespace xrpl