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
61TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
62 : mTransactionID(txid)
63 , mLedger(ledger)
64 , mNodes(obj.getFieldArray(sfAffectedNodes))
65{
66 mResult = obj.getFieldU8(sfTransactionResult);
67 mIndex = obj.getFieldU32(sfTransactionIndex);
68
69 auto affectedNodes =
70 dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
71 XRPL_ASSERT(
72 affectedNodes,
73 "ripple::TxMeta::TxMeta(STObject) : type cast succeeded");
74 if (affectedNodes)
75 mNodes = *affectedNodes;
76
77 if (obj.isFieldPresent(sfDeliveredAmount))
78 setDeliveredAmount(obj.getFieldAmount(sfDeliveredAmount));
79}
80
81TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
82 : TxMeta(txid, ledger, vec, CtorHelper())
83{
84}
85
87 uint256 const& txid,
88 std::uint32_t ledger,
89 std::string const& data)
90 : TxMeta(txid, ledger, data, CtorHelper())
91{
92}
93
95 : mTransactionID(transactionID)
96 , mLedger(ledger)
97 , mIndex(static_cast<std::uint32_t>(-1))
98 , mResult(255)
99 , mNodes(sfAffectedNodes)
100{
101 mNodes.reserve(32);
102}
103
104void
106 uint256 const& node,
107 SField const& type,
108 std::uint16_t nodeType)
109{
110 // make sure the node exists and force its type
111 for (auto& n : mNodes)
112 {
113 if (n.getFieldH256(sfLedgerIndex) == node)
114 {
115 n.setFName(type);
116 n.setFieldU16(sfLedgerEntryType, nodeType);
117 return;
118 }
119 }
120
122 STObject& obj = mNodes.back();
123
124 XRPL_ASSERT(
125 obj.getFName() == type,
126 "ripple::TxMeta::setAffectedNode : field type match");
127 obj.setFieldH256(sfLedgerIndex, node);
128 obj.setFieldU16(sfLedgerEntryType, nodeType);
129}
130
131boost::container::flat_set<AccountID>
133{
134 boost::container::flat_set<AccountID> list;
135 list.reserve(10);
136
137 // This code should match the behavior of the JS method:
138 // Meta#getAffectedAccounts
139 for (auto const& it : mNodes)
140 {
141 int index = it.getFieldIndex(
142 (it.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
143
144 if (index != -1)
145 {
146 auto inner = dynamic_cast<STObject const*>(&it.peekAtIndex(index));
147 XRPL_ASSERT(
148 inner,
149 "ripple::getAffectedAccounts : STObject type cast succeeded");
150 if (inner)
151 {
152 for (auto const& field : *inner)
153 {
154 if (auto sa = dynamic_cast<STAccount const*>(&field))
155 {
156 XRPL_ASSERT(
157 !sa->isDefault(),
158 "ripple::getAffectedAccounts : account is set");
159 if (!sa->isDefault())
160 list.insert(sa->value());
161 }
162 else if (
163 (field.getFName() == sfLowLimit) ||
164 (field.getFName() == sfHighLimit) ||
165 (field.getFName() == sfTakerPays) ||
166 (field.getFName() == sfTakerGets))
167 {
168 auto lim = dynamic_cast<STAmount const*>(&field);
169 XRPL_ASSERT(
170 lim,
171 "ripple::getAffectedAccounts : STAmount type cast "
172 "succeeded");
173
174 if (lim != nullptr)
175 {
176 auto issuer = lim->getIssuer();
177
178 if (issuer.isNonZero())
179 list.insert(issuer);
180 }
181 }
182 }
183 }
184 }
185 }
186
187 return list;
188}
189
192{
193 uint256 index = node->key();
194 for (auto& n : mNodes)
195 {
196 if (n.getFieldH256(sfLedgerIndex) == index)
197 return n;
198 }
200 STObject& obj = mNodes.back();
201
202 XRPL_ASSERT(
203 obj.getFName() == type,
204 "ripple::TxMeta::getAffectedNode(SLE::ref) : field type match");
205 obj.setFieldH256(sfLedgerIndex, index);
206 obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType));
207
208 return obj;
209}
210
213{
214 for (auto& n : mNodes)
215 {
216 if (n.getFieldH256(sfLedgerIndex) == node)
217 return n;
218 }
219 UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found");
220 Throw<std::runtime_error>("Affected node not found");
221 return *(mNodes.begin()); // Silence compiler warning.
222}
223
226{
227 STObject metaData(sfTransactionMetaData);
228 XRPL_ASSERT(mResult != 255, "ripple::TxMeta::getAsObject : result is set");
229 metaData.setFieldU8(sfTransactionResult, mResult);
230 metaData.setFieldU32(sfTransactionIndex, mIndex);
231 metaData.emplace_back(mNodes);
232 if (hasDeliveredAmount())
233 metaData.setFieldAmount(sfDeliveredAmount, getDeliveredAmount());
234 return metaData;
235}
236
237void
239{
240 mResult = TERtoInt(result);
241 mIndex = index;
242 XRPL_ASSERT(
243 (mResult == 0) || ((mResult > 100) && (mResult <= 255)),
244 "ripple::TxMeta::addRaw : valid TER input");
245
246 mNodes.sort([](STObject const& o1, STObject const& o2) {
247 return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex);
248 });
249
250 getAsObject().add(s);
251}
252
253} // namespace ripple
Identifies fields.
Definition: SField.h:144
void sort(bool(*compare)(const STObject &o1, const STObject &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
const STBase * 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:961
uint256 getFieldH256(SField const &field) const
Definition: STObject.cpp:645
TxMeta(uint256 const &txID, std::uint32_t ledger, T const &data, CtorHelper)
Definition: TxMeta.cpp:43
STArray mNodes
Definition: TxMeta.h:141
bool hasDeliveredAmount() const
Definition: TxMeta.h:128
STAmount getDeliveredAmount() const
Definition: TxMeta.h:119
void setAffectedNode(uint256 const &, SField const &type, std::uint16_t nodeType)
Definition: TxMeta.cpp:105
STObject getAsObject() const
Definition: TxMeta.cpp:225
void setDeliveredAmount(STAmount const &delivered)
Definition: TxMeta.h:113
std::uint32_t mIndex
Definition: TxMeta.h:136
boost::container::flat_set< AccountID > getAffectedAccounts() const
Return a list of accounts affected by this transaction.
Definition: TxMeta.cpp:132
void addRaw(Serializer &, TER, std::uint32_t index)
Definition: TxMeta.cpp:238
STObject & getAffectedNode(SLE::ref node, SField const &type)
Definition: TxMeta.cpp:191
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:353
@ transactionID
transaction plus signature to give transaction ID
STL namespace.