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
42TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
43 : transactionID_(txid)
44 , ledgerSeq_(ledger)
45 , nodes_(obj.getFieldArray(sfAffectedNodes))
46{
47 result_ = obj.getFieldU8(sfTransactionResult);
48 index_ = obj.getFieldU32(sfTransactionIndex);
49
50 auto affectedNodes =
51 dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
52 XRPL_ASSERT(
53 affectedNodes,
54 "ripple::TxMeta::TxMeta(STObject) : type cast succeeded");
55 if (affectedNodes)
56 nodes_ = *affectedNodes;
57
59}
60
61TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
62 : transactionID_(txid), ledgerSeq_(ledger), nodes_(sfAffectedNodes, 32)
63{
64 SerialIter sit(makeSlice(vec));
65
66 STObject obj(sit, sfMetadata);
67 result_ = obj.getFieldU8(sfTransactionResult);
68 index_ = obj.getFieldU32(sfTransactionIndex);
69 nodes_ = obj.getFieldArray(sfAffectedNodes);
70
72}
73
75 : transactionID_(transactionID)
76 , ledgerSeq_(ledger)
77 , index_(std::numeric_limits<std::uint32_t>::max())
78 , result_(255)
79 , nodes_(sfAffectedNodes)
80{
81 nodes_.reserve(32);
82}
83
84void
86 uint256 const& node,
87 SField const& type,
88 std::uint16_t nodeType)
89{
90 // make sure the node exists and force its type
91 for (auto& n : nodes_)
92 {
93 if (n.getFieldH256(sfLedgerIndex) == node)
94 {
95 n.setFName(type);
96 n.setFieldU16(sfLedgerEntryType, nodeType);
97 return;
98 }
99 }
100
102 STObject& obj = nodes_.back();
103
104 XRPL_ASSERT(
105 obj.getFName() == type,
106 "ripple::TxMeta::setAffectedNode : field type match");
107 obj.setFieldH256(sfLedgerIndex, node);
108 obj.setFieldU16(sfLedgerEntryType, nodeType);
109}
110
111boost::container::flat_set<AccountID>
113{
114 boost::container::flat_set<AccountID> list;
115 list.reserve(10);
116
117 // This code should match the behavior of the JS method:
118 // Meta#getAffectedAccounts
119 for (auto const& node : nodes_)
120 {
121 int index = node.getFieldIndex(
122 (node.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
123
124 if (index != -1)
125 {
126 auto const* inner =
127 dynamic_cast<STObject const*>(&node.peekAtIndex(index));
128 XRPL_ASSERT(
129 inner,
130 "ripple::getAffectedAccounts : STObject type cast succeeded");
131 if (inner)
132 {
133 for (auto const& field : *inner)
134 {
135 if (auto sa = dynamic_cast<STAccount const*>(&field))
136 {
137 XRPL_ASSERT(
138 !sa->isDefault(),
139 "ripple::getAffectedAccounts : account is set");
140 if (!sa->isDefault())
141 list.insert(sa->value());
142 }
143 else if (
144 (field.getFName() == sfLowLimit) ||
145 (field.getFName() == sfHighLimit) ||
146 (field.getFName() == sfTakerPays) ||
147 (field.getFName() == sfTakerGets))
148 {
149 auto lim = dynamic_cast<STAmount const*>(&field);
150 XRPL_ASSERT(
151 lim,
152 "ripple::getAffectedAccounts : STAmount type cast "
153 "succeeded");
154
155 if (lim != nullptr)
156 {
157 auto issuer = lim->getIssuer();
158
159 if (issuer.isNonZero())
160 list.insert(issuer);
161 }
162 }
163 else if (field.getFName() == sfMPTokenIssuanceID)
164 {
165 auto mptID =
166 dynamic_cast<STBitString<192> const*>(&field);
167 if (mptID != nullptr)
168 {
169 auto issuer = MPTIssue(mptID->value()).getIssuer();
170
171 if (issuer.isNonZero())
172 list.insert(issuer);
173 }
174 }
175 }
176 }
177 }
178 }
179
180 return list;
181}
182
185{
186 uint256 index = node->key();
187 for (auto& n : nodes_)
188 {
189 if (n.getFieldH256(sfLedgerIndex) == index)
190 return n;
191 }
193 STObject& obj = nodes_.back();
194
195 XRPL_ASSERT(
196 obj.getFName() == type,
197 "ripple::TxMeta::getAffectedNode(SLE::ref) : field type match");
198 obj.setFieldH256(sfLedgerIndex, index);
199 obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType));
200
201 return obj;
202}
203
206{
207 for (auto& n : nodes_)
208 {
209 if (n.getFieldH256(sfLedgerIndex) == node)
210 return n;
211 }
212 // LCOV_EXCL_START
213 UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found");
214 Throw<std::runtime_error>("Affected node not found");
215 return *(nodes_.begin()); // Silence compiler warning.
216 // LCOV_EXCL_STOP
217}
218
221{
222 STObject metaData(sfTransactionMetaData);
223 XRPL_ASSERT(result_ != 255, "ripple::TxMeta::getAsObject : result_ is set");
224 metaData.setFieldU8(sfTransactionResult, result_);
225 metaData.setFieldU32(sfTransactionIndex, index_);
226 metaData.emplace_back(nodes_);
228 metaData.setFieldAmount(sfDeliveredAmount, *deliveredAmount_);
229
230 if (parentBatchID_.has_value())
231 metaData.setFieldH256(sfParentBatchID, *parentBatchID_);
232
233 return metaData;
234}
235
236void
238{
239 result_ = TERtoInt(result);
240 index_ = index;
241 XRPL_ASSERT(
242 (result_ == 0) || ((result_ > 100) && (result_ <= 255)),
243 "ripple::TxMeta::addRaw : valid TER input");
244
245 nodes_.sort([](STObject const& o1, STObject const& o2) {
246 return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex);
247 });
248
249 getAsObject().add(s);
250}
251
252} // namespace ripple
AccountID const & getIssuer() const
Definition MPTIssue.cpp:40
Identifies fields.
Definition SField.h:146
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:143
unsigned char getFieldU8(SField const &field) const
Definition STObject.cpp:603
STArray const & getFieldArray(SField const &field) const
Definition STObject.cpp:702
STBase const * peekAtPField(SField const &field) const
Definition STObject.cpp:457
void setFieldH256(SField const &field, uint256 const &)
Definition STObject.cpp:775
std::uint32_t getFieldU32(SField const &field) const
Definition STObject.cpp:615
void setFieldU16(SField const &field, std::uint16_t)
Definition STObject.cpp:751
void setFieldU8(SField const &field, unsigned char)
Definition STObject.cpp:745
void add(Serializer &s) const override
Definition STObject.cpp:141
void setFieldAmount(SField const &field, STAmount const &)
Definition STObject.cpp:811
void setFieldU32(SField const &field, std::uint32_t)
Definition STObject.cpp:757
std::size_t emplace_back(Args &&... args)
Definition STObject.h:981
uint256 getFieldH256(SField const &field) const
Definition STObject.cpp:645
std::optional< uint256 > parentBatchID_
Definition TxMeta.h:134
std::optional< STAmount > deliveredAmount_
Definition TxMeta.h:133
std::uint32_t index_
Definition TxMeta.h:130
STArray nodes_
Definition TxMeta.h:136
TxMeta(uint256 const &transactionID, std::uint32_t ledger)
Definition TxMeta.cpp:74
void setAffectedNode(uint256 const &, SField const &type, std::uint16_t nodeType)
Definition TxMeta.cpp:85
STObject getAsObject() const
Definition TxMeta.cpp:220
void setAdditionalFields(STObject const &obj)
Definition TxMeta.h:100
boost::container::flat_set< AccountID > getAffectedAccounts() const
Return a list of accounts affected by this transaction.
Definition TxMeta.cpp:112
void addRaw(Serializer &, TER, std::uint32_t index)
Definition TxMeta.cpp:237
STObject & getAffectedNode(SLE::ref node, SField const &type)
Definition TxMeta.cpp:184
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:375
@ transactionID
transaction plus signature to give transaction ID
STL namespace.
T has_value(T... args)