rippled
Loading...
Searching...
No Matches
TxMeta.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpl/basics/Blob.h>
21#include <xrpl/basics/base_uint.h>
22#include <xrpl/basics/contract.h>
23#include <xrpl/beast/utility/instrumentation.h>
24#include <xrpl/protocol/AccountID.h>
25#include <xrpl/protocol/SField.h>
26#include <xrpl/protocol/STAccount.h>
27#include <xrpl/protocol/STAmount.h>
28#include <xrpl/protocol/STLedgerEntry.h>
29#include <xrpl/protocol/STObject.h>
30#include <xrpl/protocol/Serializer.h>
31#include <xrpl/protocol/TER.h>
32#include <xrpl/protocol/TxMeta.h>
33
34#include <boost/container/flat_set.hpp>
35
36#include <cstdint>
37#include <stdexcept>
38#include <string>
39
40namespace ripple {
41
42template <class T>
44 uint256 const& txid,
45 std::uint32_t ledger,
46 T const& data,
48 : mTransactionID(txid), mLedger(ledger), mNodes(sfAffectedNodes, 32)
49{
50 SerialIter sit(makeSlice(data));
51
52 STObject obj(sit, sfMetadata);
53 mResult = obj.getFieldU8(sfTransactionResult);
54 mIndex = obj.getFieldU32(sfTransactionIndex);
55 mNodes = *dynamic_cast<STArray*>(&obj.getField(sfAffectedNodes));
56
57 if (obj.isFieldPresent(sfDeliveredAmount))
58 setDeliveredAmount(obj.getFieldAmount(sfDeliveredAmount));
59
60 if (obj.isFieldPresent(sfParentBatchID))
61 setParentBatchId(obj.getFieldH256(sfParentBatchID));
62}
63
64TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
65 : mTransactionID(txid)
66 , mLedger(ledger)
67 , mNodes(obj.getFieldArray(sfAffectedNodes))
68{
69 mResult = obj.getFieldU8(sfTransactionResult);
70 mIndex = obj.getFieldU32(sfTransactionIndex);
71
72 auto affectedNodes =
73 dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
74 XRPL_ASSERT(
75 affectedNodes,
76 "ripple::TxMeta::TxMeta(STObject) : type cast succeeded");
77 if (affectedNodes)
78 mNodes = *affectedNodes;
79
80 if (obj.isFieldPresent(sfDeliveredAmount))
81 setDeliveredAmount(obj.getFieldAmount(sfDeliveredAmount));
82
83 if (obj.isFieldPresent(sfParentBatchID))
84 setParentBatchId(obj.getFieldH256(sfParentBatchID));
85}
86
87TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
88 : TxMeta(txid, ledger, vec, CtorHelper())
89{
90}
91
93 uint256 const& txid,
94 std::uint32_t ledger,
95 std::string const& data)
96 : TxMeta(txid, ledger, data, CtorHelper())
97{
98}
99
101 uint256 const& transactionID,
102 std::uint32_t ledger,
103 std::optional<uint256> parentBatchId)
104 : mTransactionID(transactionID)
105 , mLedger(ledger)
106 , mIndex(static_cast<std::uint32_t>(-1))
107 , mResult(255)
108 , mParentBatchId(parentBatchId)
109 , mNodes(sfAffectedNodes)
110{
111 mNodes.reserve(32);
112}
113
114void
116 uint256 const& node,
117 SField const& type,
118 std::uint16_t nodeType)
119{
120 // make sure the node exists and force its type
121 for (auto& n : mNodes)
122 {
123 if (n.getFieldH256(sfLedgerIndex) == node)
124 {
125 n.setFName(type);
126 n.setFieldU16(sfLedgerEntryType, nodeType);
127 return;
128 }
129 }
130
132 STObject& obj = mNodes.back();
133
134 XRPL_ASSERT(
135 obj.getFName() == type,
136 "ripple::TxMeta::setAffectedNode : field type match");
137 obj.setFieldH256(sfLedgerIndex, node);
138 obj.setFieldU16(sfLedgerEntryType, nodeType);
139}
140
141boost::container::flat_set<AccountID>
143{
144 boost::container::flat_set<AccountID> list;
145 list.reserve(10);
146
147 // This code should match the behavior of the JS method:
148 // Meta#getAffectedAccounts
149 for (auto const& it : mNodes)
150 {
151 int index = it.getFieldIndex(
152 (it.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
153
154 if (index != -1)
155 {
156 auto inner = dynamic_cast<STObject const*>(&it.peekAtIndex(index));
157 XRPL_ASSERT(
158 inner,
159 "ripple::getAffectedAccounts : STObject type cast succeeded");
160 if (inner)
161 {
162 for (auto const& field : *inner)
163 {
164 if (auto sa = dynamic_cast<STAccount const*>(&field))
165 {
166 XRPL_ASSERT(
167 !sa->isDefault(),
168 "ripple::getAffectedAccounts : account is set");
169 if (!sa->isDefault())
170 list.insert(sa->value());
171 }
172 else if (
173 (field.getFName() == sfLowLimit) ||
174 (field.getFName() == sfHighLimit) ||
175 (field.getFName() == sfTakerPays) ||
176 (field.getFName() == sfTakerGets))
177 {
178 auto lim = dynamic_cast<STAmount const*>(&field);
179 XRPL_ASSERT(
180 lim,
181 "ripple::getAffectedAccounts : STAmount type cast "
182 "succeeded");
183
184 if (lim != nullptr)
185 {
186 auto issuer = lim->getIssuer();
187
188 if (issuer.isNonZero())
189 list.insert(issuer);
190 }
191 }
192 else if (field.getFName() == sfMPTokenIssuanceID)
193 {
194 auto mptID =
195 dynamic_cast<STBitString<192> const*>(&field);
196 if (mptID != nullptr)
197 {
198 auto issuer = MPTIssue(mptID->value()).getIssuer();
199
200 if (issuer.isNonZero())
201 list.insert(issuer);
202 }
203 }
204 }
205 }
206 }
207 }
208
209 return list;
210}
211
214{
215 uint256 index = node->key();
216 for (auto& n : mNodes)
217 {
218 if (n.getFieldH256(sfLedgerIndex) == index)
219 return n;
220 }
222 STObject& obj = mNodes.back();
223
224 XRPL_ASSERT(
225 obj.getFName() == type,
226 "ripple::TxMeta::getAffectedNode(SLE::ref) : field type match");
227 obj.setFieldH256(sfLedgerIndex, index);
228 obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType));
229
230 return obj;
231}
232
235{
236 for (auto& n : mNodes)
237 {
238 if (n.getFieldH256(sfLedgerIndex) == node)
239 return n;
240 }
241 UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found");
242 Throw<std::runtime_error>("Affected node not found");
243 return *(mNodes.begin()); // Silence compiler warning.
244}
245
248{
249 STObject metaData(sfTransactionMetaData);
250 XRPL_ASSERT(mResult != 255, "ripple::TxMeta::getAsObject : result is set");
251 metaData.setFieldU8(sfTransactionResult, mResult);
252 metaData.setFieldU32(sfTransactionIndex, mIndex);
253 metaData.emplace_back(mNodes);
254 if (hasDeliveredAmount())
255 metaData.setFieldAmount(sfDeliveredAmount, getDeliveredAmount());
256
257 if (hasParentBatchId())
258 metaData.setFieldH256(sfParentBatchID, getParentBatchId());
259
260 return metaData;
261}
262
263void
265{
266 mResult = TERtoInt(result);
267 mIndex = index;
268 XRPL_ASSERT(
269 (mResult == 0) || ((mResult > 100) && (mResult <= 255)),
270 "ripple::TxMeta::addRaw : valid TER input");
271
272 mNodes.sort([](STObject const& o1, STObject const& o2) {
273 return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex);
274 });
275
276 getAsObject().add(s);
277}
278
279} // namespace ripple
AccountID const & getIssuer() const
Definition MPTIssue.cpp:40
Identifies fields.
Definition SField.h:144
void sort(bool(*compare)(STObject const &o1, STObject const &o2))
Definition STArray.cpp:197
void reserve(std::size_t n)
Definition STArray.h:266
void push_back(STObject const &object)
Definition STArray.h:212
STObject & back()
Definition STArray.h:193
iterator begin()
Definition STArray.h:224
SField const & getFName() const
Definition STBase.cpp:141
unsigned char getFieldU8(SField const &field) const
Definition STObject.cpp:603
STBase const * peekAtPField(SField const &field) const
Definition STObject.cpp:457
void setFieldH256(SField const &field, uint256 const &)
Definition STObject.cpp:759
std::uint32_t getFieldU32(SField const &field) const
Definition STObject.cpp:615
void setFieldU16(SField const &field, std::uint16_t)
Definition STObject.cpp:735
void setFieldU8(SField const &field, unsigned char)
Definition STObject.cpp:729
void add(Serializer &s) const override
Definition STObject.cpp:141
void setFieldAmount(SField const &field, STAmount const &)
Definition STObject.cpp:789
STBase & getField(SField const &field)
Definition STObject.cpp:440
STAmount const & getFieldAmount(SField const &field) const
Definition STObject.cpp:665
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:484
void setFieldU32(SField const &field, std::uint32_t)
Definition STObject.cpp:741
std::size_t emplace_back(Args &&... args)
Definition STObject.h:972
uint256 getFieldH256(SField const &field) const
Definition STObject.cpp:645
uint256 getParentBatchId() const
Definition TxMeta.h:143
TxMeta(uint256 const &txID, std::uint32_t ledger, T const &data, CtorHelper)
Definition TxMeta.cpp:43
STArray mNodes
Definition TxMeta.h:166
bool hasDeliveredAmount() const
Definition TxMeta.h:131
STAmount getDeliveredAmount() const
Definition TxMeta.h:122
void setAffectedNode(uint256 const &, SField const &type, std::uint16_t nodeType)
Definition TxMeta.cpp:115
STObject getAsObject() const
Definition TxMeta.cpp:247
void setDeliveredAmount(STAmount const &delivered)
Definition TxMeta.h:116
std::uint32_t mIndex
Definition TxMeta.h:160
void setParentBatchId(uint256 const &parentBatchId)
Definition TxMeta.h:137
boost::container::flat_set< AccountID > getAffectedAccounts() const
Return a list of accounts affected by this transaction.
Definition TxMeta.cpp:142
void addRaw(Serializer &, TER, std::uint32_t index)
Definition TxMeta.cpp:264
STObject & getAffectedNode(SLE::ref node, SField const &type)
Definition TxMeta.cpp:213
bool hasParentBatchId() const
Definition TxMeta.h:152
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition Slice.h:244
constexpr TERUnderlyingType TERtoInt(TELcodes v)
Definition TER.h:371
@ transactionID
transaction plus signature to give transaction ID
STL namespace.