xrpld
Loading...
Searching...
No Matches
TxMeta.cpp
1#include <xrpl/protocol/TxMeta.h>
2
3#include <xrpl/basics/Blob.h>
4#include <xrpl/basics/Slice.h>
5#include <xrpl/basics/base_uint.h>
6#include <xrpl/basics/contract.h>
7#include <xrpl/beast/utility/instrumentation.h>
8#include <xrpl/protocol/AccountID.h>
9#include <xrpl/protocol/Indexes.h>
10#include <xrpl/protocol/LedgerFormats.h>
11#include <xrpl/protocol/SField.h>
12#include <xrpl/protocol/STAccount.h>
13#include <xrpl/protocol/STAmount.h>
14#include <xrpl/protocol/STLedgerEntry.h>
15#include <xrpl/protocol/STObject.h>
16#include <xrpl/protocol/Serializer.h>
17#include <xrpl/protocol/TER.h>
18#include <xrpl/protocol/UintTypes.h>
19
20#include <boost/container/flat_set.hpp>
21
22#include <cstdint>
23#include <flat_set>
24#include <limits>
25#include <stdexcept>
26
27namespace xrpl {
28
29TxMeta::TxMeta(UInt256 const& txid, std::uint32_t ledger, STObject const& obj)
30 : transactionID_(txid)
31 , ledgerSeq_(ledger)
32 , index_(obj.getFieldU32(sfTransactionIndex))
33 , result_(obj.getFieldU8(sfTransactionResult))
34 , nodes_([&obj] {
35 auto const affectedNodes = dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
36 XRPL_ASSERT(affectedNodes, "xrpl::TxMeta::TxMeta(STObject) : type cast succeeded");
37 return affectedNodes != nullptr ? *affectedNodes : obj.getFieldArray(sfAffectedNodes);
38 }())
39{
40 setAdditionalFields(obj);
41}
42
43TxMeta::TxMeta(UInt256 const& txid, std::uint32_t ledger, Blob const& vec)
44 : transactionID_(txid), ledgerSeq_(ledger), nodes_(sfAffectedNodes, 32)
45{
46 SerialIter sit(makeSlice(vec));
47
48 STObject const obj(sit, sfMetadata);
49 result_ = obj.getFieldU8(sfTransactionResult);
50 index_ = obj.getFieldU32(sfTransactionIndex);
51 nodes_ = obj.getFieldArray(sfAffectedNodes);
52
54}
55
56TxMeta::TxMeta(UInt256 const& transactionID, std::uint32_t ledger)
57 : transactionID_(transactionID)
58 , ledgerSeq_(ledger)
59 , index_(std::numeric_limits<std::uint32_t>::max())
60 , result_(255)
61 , nodes_(sfAffectedNodes)
62{
63 nodes_.reserve(32);
64}
65
66void
67TxMeta::setAffectedNode(UInt256 const& node, SField const& type, std::uint16_t nodeType)
68{
69 // make sure the node exists and force its type
70 for (auto& n : nodes_)
71 {
72 if (n.getFieldH256(sfLedgerIndex) == node)
73 {
74 n.setFName(type);
75 n.setFieldU16(sfLedgerEntryType, nodeType);
76 return;
77 }
78 }
79
80 nodes_.pushBack(STObject(type));
81 STObject& obj = nodes_.back();
82
83 XRPL_ASSERT(obj.getFName() == type, "xrpl::TxMeta::setAffectedNode : field type match");
84 obj.setFieldH256(sfLedgerIndex, node);
85 obj.setFieldU16(sfLedgerEntryType, nodeType);
86}
87
88boost::container::flat_set<AccountID>
90{
91 boost::container::flat_set<AccountID> list;
92 list.reserve(10);
93
94 // This code should match the behavior of the JS method:
95 // Meta#getAffectedAccounts
96 for (auto const& node : nodes_)
97 {
98 int const index =
99 node.getFieldIndex((node.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
100
101 if (index != -1)
102 {
103 auto const* inner = dynamic_cast<STObject const*>(&node.peekAtIndex(index));
104 XRPL_ASSERT(inner, "xrpl::getAffectedAccounts : STObject type cast succeeded");
105 if (inner != nullptr)
106 {
107 for (auto const& field : *inner)
108 {
109 if (auto sa = dynamic_cast<STAccount const*>(&field))
110 {
111 XRPL_ASSERT(!sa->isDefault(), "xrpl::getAffectedAccounts : account is set");
112 if (!sa->isDefault())
113 list.insert(sa->value());
114 }
115 else if (
116 (field.getFName() == sfLowLimit) || (field.getFName() == sfHighLimit) ||
117 (field.getFName() == sfTakerPays) || (field.getFName() == sfTakerGets))
118 {
119 auto lim = dynamic_cast<STAmount const*>(&field);
120 XRPL_ASSERT(
121 lim,
122 "xrpl::getAffectedAccounts : STAmount type cast "
123 "succeeded");
124
125 if (lim != nullptr)
126 {
127 auto issuer = lim->getIssuer();
128
129 if (issuer.isNonZero())
130 list.insert(issuer);
131 }
132 }
133 else if (field.getFName() == sfMPTokenIssuanceID)
134 {
135 auto mptID = dynamic_cast<STBitString<192> const*>(&field);
136 if (mptID != nullptr)
137 {
138 auto issuer = MPTIssue(mptID->value()).getIssuer();
139
140 if (issuer.isNonZero())
141 list.insert(issuer);
142 }
143 }
144 }
145 }
146 }
147 }
148
149 return list;
150}
151
152std::flat_set<MPTID>
154{
155 std::flat_set<MPTID> list;
156
157 for (auto const& it : nodes_)
158 {
159 int const index =
160 it.getFieldIndex((it.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
161
162 if (index != -1)
163 {
164 auto inner = dynamic_cast<STObject const*>(&it.peekAtIndex(index));
165 XRPL_ASSERT(inner, "xrpl::getAffectedMPTs : STObject type cast succeeded");
166 if (inner != nullptr)
167 {
168 // An MPTokenIssuance entry does not store its own issuance id;
169 // the id is derived from the issuer and the sequence that
170 // created the issuance.
171 if (it.getFieldU16(sfLedgerEntryType) == ltMPTOKEN_ISSUANCE)
172 {
173 list.insert(
174 makeMptID(inner->getFieldU32(sfSequence), inner->getAccountID(sfIssuer)));
175 }
176
177 for (auto const& field : *inner)
178 {
179 if (auto mptID = dynamic_cast<STBitString<192> const*>(&field);
180 field.getFName() == sfMPTokenIssuanceID && (mptID != nullptr))
181 {
182 list.insert(mptID->value());
183 }
184 else if (
185 auto amount = dynamic_cast<STAmount const*>(&field);
186 (amount != nullptr) && amount->holds<MPTIssue>())
187 {
188 list.insert(amount->get<MPTIssue>().getMptID());
189 }
190 }
191 }
192 }
193 }
194
195 return list;
196}
197
200{
201 UInt256 const index = node->key();
202 for (auto& n : nodes_)
203 {
204 if (n.getFieldH256(sfLedgerIndex) == index)
205 return n;
206 }
207 nodes_.pushBack(STObject(type));
208 STObject& obj = nodes_.back();
209
210 XRPL_ASSERT(
211 obj.getFName() == type, "xrpl::TxMeta::getAffectedNode(SLE::Ref) : field type match");
212 obj.setFieldH256(sfLedgerIndex, index);
213 obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType));
214
215 return obj;
216}
217
220{
221 for (auto& n : nodes_)
222 {
223 if (n.getFieldH256(sfLedgerIndex) == node)
224 return n;
225 }
226 // LCOV_EXCL_START
227 UNREACHABLE("xrpl::TxMeta::getAffectedNode(UInt256) : node not found");
228 Throw<std::runtime_error>("Affected node not found");
229 return *(nodes_.begin()); // Silence compiler warning.
230 // LCOV_EXCL_STOP
231}
232
235{
236 STObject metaData(sfTransactionMetaData);
237 XRPL_ASSERT(result_ != 255, "xrpl::TxMeta::getAsObject : result_ is set");
238 metaData.setFieldU8(sfTransactionResult, result_);
239 metaData.setFieldU32(sfTransactionIndex, index_);
240 metaData.emplaceBack(nodes_);
241 if (deliveredAmount_.has_value())
242 metaData.setFieldAmount(sfDeliveredAmount, *deliveredAmount_);
243
244 if (parentBatchID_.has_value())
245 metaData.setFieldH256(sfParentBatchID, *parentBatchID_);
246
247 return metaData;
248}
249
250void
252{
253 result_ = TERtoInt(result);
254 index_ = index;
255 XRPL_ASSERT(
256 (result_ == 0) || ((result_ > 100) && (result_ <= 255)),
257 "xrpl::TxMeta::addRaw : valid TER input");
258
259 nodes_.sort([](STObject const& o1, STObject const& o2) {
260 return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex);
261 });
262
263 getAsObject().add(s);
264}
265
266} // namespace xrpl
constexpr MPTID const & getMptID() const
Definition MPTIssue.h:43
AccountID const & getIssuer() const
Definition MPTIssue.cpp:29
Identifies fields.
Definition SField.h:132
constexpr bool holds() const noexcept
Definition STAmount.h:478
SField const & getFName() const
Definition STBase.cpp:120
std::shared_ptr< STLedgerEntry > const & Ref
void setFieldU8(SField const &field, unsigned char)
Definition STObject.cpp:731
UInt256 getFieldH256(SField const &field) const
Definition STObject.cpp:631
unsigned char getFieldU8(SField const &field) const
Definition STObject.cpp:589
std::uint32_t getFieldU32(SField const &field) const
Definition STObject.cpp:601
void setFieldU32(SField const &field, std::uint32_t)
Definition STObject.cpp:743
std::size_t emplaceBack(Args &&... args)
Definition STObject.h:1012
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:688
void setFieldAmount(SField const &field, STAmount const &)
Definition STObject.cpp:803
void add(Serializer &s) const override
Definition STObject.cpp:123
void setFieldU16(SField const &field, std::uint16_t)
Definition STObject.cpp:737
STBase const * peekAtPField(SField const &field) const
Definition STObject.cpp:437
void setFieldH256(SField const &field, UInt256 const &)
Definition STObject.cpp:767
boost::container::flat_set< AccountID > getAffectedAccounts() const
Return a list of accounts affected by this transaction.
Definition TxMeta.cpp:89
TxMeta(UInt256 const &transactionID, std::uint32_t ledger)
Definition TxMeta.cpp:56
UInt256 transactionID_
Definition TxMeta.h:124
void setAdditionalFields(STObject const &obj)
Definition TxMeta.h:93
STObject & getAffectedNode(SLE::Ref node, SField const &type)
Definition TxMeta.cpp:199
std::optional< STAmount > deliveredAmount_
Definition TxMeta.h:129
STArray nodes_
Definition TxMeta.h:132
int result_
Definition TxMeta.h:127
std::flat_set< MPTID > getAffectedMPTs() const
Definition TxMeta.cpp:153
void addRaw(Serializer &, TER, std::uint32_t index)
Definition TxMeta.cpp:251
std::optional< UInt256 > parentBatchID_
Definition TxMeta.h:130
STObject getAsObject() const
Definition TxMeta.cpp:234
void setAffectedNode(UInt256 const &, SField const &type, std::uint16_t nodeType)
Definition TxMeta.cpp:67
std::uint32_t index_
Definition TxMeta.h:126
std::uint32_t ledgerSeq_
Definition TxMeta.h:125
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
Slice makeSlice(std::array< T, N > const &a)
Definition Slice.h:228
BaseUInt< 256 > UInt256
Definition base_uint.h:580
MPTID makeMptID(std::uint32_t const sequence, AccountID const &account)
Definition Indexes.cpp:206
constexpr TERUnderlyingType TERtoInt(TELcodes v)
Definition TER.h:386
TERSubset< CanCvtToTER > TER
Definition TER.h:654
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition Blob.h:11
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52