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 }
193 }
194 }
195 }
196
197 return list;
198}
199
202{
203 uint256 index = node->key();
204 for (auto& n : mNodes)
205 {
206 if (n.getFieldH256(sfLedgerIndex) == index)
207 return n;
208 }
210 STObject& obj = mNodes.back();
211
212 XRPL_ASSERT(
213 obj.getFName() == type,
214 "ripple::TxMeta::getAffectedNode(SLE::ref) : field type match");
215 obj.setFieldH256(sfLedgerIndex, index);
216 obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType));
217
218 return obj;
219}
220
223{
224 for (auto& n : mNodes)
225 {
226 if (n.getFieldH256(sfLedgerIndex) == node)
227 return n;
228 }
229 UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found");
230 Throw<std::runtime_error>("Affected node not found");
231 return *(mNodes.begin()); // Silence compiler warning.
232}
233
236{
237 STObject metaData(sfTransactionMetaData);
238 XRPL_ASSERT(mResult != 255, "ripple::TxMeta::getAsObject : result is set");
239 metaData.setFieldU8(sfTransactionResult, mResult);
240 metaData.setFieldU32(sfTransactionIndex, mIndex);
241 metaData.emplace_back(mNodes);
242 if (hasDeliveredAmount())
243 metaData.setFieldAmount(sfDeliveredAmount, getDeliveredAmount());
244
245 if (hasParentBatchId())
246 metaData.setFieldH256(sfParentBatchID, getParentBatchId());
247
248 return metaData;
249}
250
251void
253{
254 mResult = TERtoInt(result);
255 mIndex = index;
256 XRPL_ASSERT(
257 (mResult == 0) || ((mResult > 100) && (mResult <= 255)),
258 "ripple::TxMeta::addRaw : valid TER input");
259
260 mNodes.sort([](STObject const& o1, STObject const& o2) {
261 return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex);
262 });
263
264 getAsObject().add(s);
265}
266
267} // namespace ripple
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:235
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:252
STObject & getAffectedNode(SLE::ref node, SField const &type)
Definition: TxMeta.cpp:201
bool hasParentBatchId() const
Definition: TxMeta.h:152
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
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:369
@ transactionID
transaction plus signature to give transaction ID
STL namespace.