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:143
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.