rippled
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 <ripple/basics/Log.h>
21 #include <ripple/basics/contract.h>
22 #include <ripple/json/to_string.h>
23 #include <ripple/ledger/TxMeta.h>
24 #include <ripple/protocol/STAccount.h>
25 #include <string>
26 
27 namespace ripple {
28 
29 // VFALCO TODO rename class to TransactionMeta
30 
31 template <class T>
33  uint256 const& txid,
34  std::uint32_t ledger,
35  T const& data,
36  CtorHelper)
37  : mTransactionID(txid), mLedger(ledger), mNodes(sfAffectedNodes, 32)
38 {
39  SerialIter sit(makeSlice(data));
40 
41  STObject obj(sit, sfMetadata);
44  mNodes = *dynamic_cast<STArray*>(&obj.getField(sfAffectedNodes));
45 
48 }
49 
50 TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
51  : mTransactionID(txid)
52  , mLedger(ledger)
53  , mNodes(obj.getFieldArray(sfAffectedNodes))
54 {
57 
58  auto affectedNodes =
59  dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
60  assert(affectedNodes);
61  if (affectedNodes)
62  mNodes = *affectedNodes;
63 
66 }
67 
68 TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
69  : TxMeta(txid, ledger, vec, CtorHelper())
70 {
71 }
72 
74  uint256 const& txid,
75  std::uint32_t ledger,
76  std::string const& data)
77  : TxMeta(txid, ledger, data, CtorHelper())
78 {
79 }
80 
81 bool
82 TxMeta::isNodeAffected(uint256 const& node) const
83 {
84  for (auto const& n : mNodes)
85  {
86  if (n.getFieldH256(sfLedgerIndex) == node)
87  return true;
88  }
89 
90  return false;
91 }
92 
93 void
95  uint256 const& node,
96  SField const& type,
97  std::uint16_t nodeType)
98 {
99  // make sure the node exists and force its type
100  for (auto& n : mNodes)
101  {
102  if (n.getFieldH256(sfLedgerIndex) == node)
103  {
104  n.setFName(type);
105  n.setFieldU16(sfLedgerEntryType, nodeType);
106  return;
107  }
108  }
109 
110  mNodes.push_back(STObject(type));
111  STObject& obj = mNodes.back();
112 
113  assert(obj.getFName() == type);
114  obj.setFieldH256(sfLedgerIndex, node);
115  obj.setFieldU16(sfLedgerEntryType, nodeType);
116 }
117 
118 boost::container::flat_set<AccountID>
120 {
121  boost::container::flat_set<AccountID> list;
122  list.reserve(10);
123 
124  // This code should match the behavior of the JS method:
125  // Meta#getAffectedAccounts
126  for (auto const& it : mNodes)
127  {
128  int index = it.getFieldIndex(
129  (it.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
130 
131  if (index != -1)
132  {
133  const STObject* inner =
134  dynamic_cast<const STObject*>(&it.peekAtIndex(index));
135  assert(inner);
136  if (inner)
137  {
138  for (auto const& field : *inner)
139  {
140  if (auto sa = dynamic_cast<STAccount const*>(&field))
141  {
142  assert(!sa->isDefault());
143  if (!sa->isDefault())
144  list.insert(sa->value());
145  }
146  else if (
147  (field.getFName() == sfLowLimit) ||
148  (field.getFName() == sfHighLimit) ||
149  (field.getFName() == sfTakerPays) ||
150  (field.getFName() == sfTakerGets))
151  {
152  const STAmount* lim =
153  dynamic_cast<const STAmount*>(&field);
154 
155  if (lim != nullptr)
156  {
157  auto issuer = lim->getIssuer();
158 
159  if (issuer.isNonZero())
160  list.insert(issuer);
161  }
162  else
163  {
164  JLOG(j.fatal()) << "limit is not amount "
165  << field.getJson(JsonOptions::none);
166  }
167  }
168  }
169  }
170  }
171  }
172 
173  return list;
174 }
175 
176 STObject&
178 {
179  uint256 index = node->key();
180  for (auto& n : mNodes)
181  {
182  if (n.getFieldH256(sfLedgerIndex) == index)
183  return n;
184  }
185  mNodes.push_back(STObject(type));
186  STObject& obj = mNodes.back();
187 
188  assert(obj.getFName() == type);
189  obj.setFieldH256(sfLedgerIndex, index);
190  obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType));
191 
192  return obj;
193 }
194 
195 STObject&
197 {
198  for (auto& n : mNodes)
199  {
200  if (n.getFieldH256(sfLedgerIndex) == node)
201  return n;
202  }
203  assert(false);
204  Throw<std::runtime_error>("Affected node not found");
205  return *(mNodes.begin()); // Silence compiler warning.
206 }
207 
208 const STObject&
210 {
211  for (auto const& n : mNodes)
212  {
213  if (n.getFieldH256(sfLedgerIndex) == node)
214  return n;
215  }
216 
217  Throw<std::runtime_error>("Affected node not found");
218  return *(mNodes.begin()); // Silence compiler warning.
219 }
220 
221 void
223 {
224  mTransactionID = id;
225  mLedger = ledger;
227  mDelivered = boost::optional<STAmount>();
228 }
229 
230 void
231 TxMeta::swap(TxMeta& s) noexcept
232 {
233  assert((mTransactionID == s.mTransactionID) && (mLedger == s.mLedger));
234  mNodes.swap(s.mNodes);
235 }
236 
237 bool
238 TxMeta::thread(STObject& node, uint256 const& prevTxID, std::uint32_t prevLgrID)
239 {
240  if (node.getFieldIndex(sfPreviousTxnID) == -1)
241  {
242  assert(node.getFieldIndex(sfPreviousTxnLgrSeq) == -1);
243  node.setFieldH256(sfPreviousTxnID, prevTxID);
244  node.setFieldU32(sfPreviousTxnLgrSeq, prevLgrID);
245  return true;
246  }
247 
248  assert(node.getFieldH256(sfPreviousTxnID) == prevTxID);
249  assert(node.getFieldU32(sfPreviousTxnLgrSeq) == prevLgrID);
250  return false;
251 }
252 
253 static bool
254 compare(const STObject& o1, const STObject& o2)
255 {
257 }
258 
259 STObject
261 {
263  assert(mResult != 255);
266  metaData.emplace_back(mNodes);
267  if (hasDeliveredAmount())
269  return metaData;
270 }
271 
272 void
274 {
275  mResult = TERtoInt(result);
276  mIndex = index;
277  assert((mResult == 0) || ((mResult > 100) && (mResult <= 255)));
278 
280 
281  getAsObject().add(s);
282 }
283 
284 } // namespace ripple
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
ripple::TxMeta::mResult
int mResult
Definition: TxMeta.h:161
ripple::makeSlice
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:194
ripple::sfTransactionIndex
const SF_U32 sfTransactionIndex(access, STI_UINT32, 28, "TransactionIndex")
Definition: SField.h:380
std::string
STL class.
std::shared_ptr< STLedgerEntry >
ripple::STObject::setFieldU16
void setFieldU16(SField const &field, std::uint16_t)
Definition: STObject.cpp:637
ripple::sfPreviousTxnLgrSeq
const SF_U32 sfPreviousTxnLgrSeq(access, STI_UINT32, 5, "PreviousTxnLgrSeq", SField::sMD_DeleteFinal)
Definition: SField.h:356
ripple::sfLedgerEntryType
const SF_U16 sfLedgerEntryType(access, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never)
Definition: SField.h:345
ripple::sfLedgerIndex
const SF_U256 sfLedgerIndex(access, STI_HASH256, 6, "LedgerIndex")
Definition: SField.h:420
ripple::TxMeta::getAsObject
STObject getAsObject() const
Definition: TxMeta.cpp:260
ripple::TxMeta::getAffectedAccounts
boost::container::flat_set< AccountID > getAffectedAccounts(beast::Journal j) const
Return a list of accounts affected by this transaction.
Definition: TxMeta.cpp:119
ripple::sfMetadata
const SField sfMetadata(access, STI_METADATA, 257, "Metadata")
Definition: SField.h:336
ripple::sfDeliveredAmount
const SF_Amount sfDeliveredAmount(access, STI_AMOUNT, 18, "DeliveredAmount")
Definition: SField.h:451
std::vector< unsigned char >
ripple::STObject::getFieldU8
unsigned char getFieldU8(SField const &field) const
Definition: STObject.cpp:531
ripple::sfNewFields
const SField sfNewFields(access, STI_OBJECT, 8, "NewFields")
Definition: SField.h:499
ripple::TxMeta::TxMeta
TxMeta()
Definition: TxMeta.h:52
ripple::sfTakerPays
const SF_Amount sfTakerPays(access, STI_AMOUNT, 4, "TakerPays")
Definition: SField.h:440
ripple::STArray::push_back
void push_back(STObject const &object)
Definition: STArray.h:107
ripple::TxMeta::mIndex
std::uint32_t mIndex
Definition: TxMeta.h:160
ripple::TERtoInt
constexpr TERUnderlyingType TERtoInt(TELcodes v)
Definition: TER.h:283
ripple::TxMeta::CtorHelper
Definition: TxMeta.h:40
ripple::TxMeta::isNodeAffected
bool isNodeAffected(uint256 const &) const
Definition: TxMeta.cpp:82
ripple::sfFinalFields
const SField sfFinalFields(access, STI_OBJECT, 7, "FinalFields")
Definition: SField.h:498
ripple::sfHighLimit
const SF_Amount sfHighLimit(access, STI_AMOUNT, 7, "HighLimit")
Definition: SField.h:443
ripple::TxMeta::swap
void swap(TxMeta &) noexcept
Definition: TxMeta.cpp:231
ripple::sfLowLimit
const SF_Amount sfLowLimit(access, STI_AMOUNT, 6, "LowLimit")
Definition: SField.h:442
ripple::TxMeta::mNodes
STArray mNodes
Definition: TxMeta.h:165
ripple::TxMeta
Definition: TxMeta.h:33
ripple::base_uint< 256 >
ripple::STArray::begin
iterator begin()
Definition: STArray.h:119
ripple::TxMeta::mTransactionID
uint256 mTransactionID
Definition: TxMeta.h:158
ripple::TxMeta::mLedger
std::uint32_t mLedger
Definition: TxMeta.h:159
ripple::STObject::setFieldU8
void setFieldU8(SField const &field, unsigned char)
Definition: STObject.cpp:631
ripple::STObject::setFieldAmount
void setFieldAmount(SField const &field, STAmount const &)
Definition: STObject.cpp:691
ripple::compare
int compare(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:497
ripple::JsonOptions::none
@ none
ripple::STObject::setFieldH256
void setFieldH256(SField const &field, uint256 const &)
Definition: STObject.cpp:661
ripple::TERSubset< CanCvtToTER >
ripple::STArray
Definition: STArray.h:28
ripple::TxMeta::addRaw
void addRaw(Serializer &, TER, std::uint32_t index)
Definition: TxMeta.cpp:273
ripple::TxMeta::init
void init(uint256 const &transactionID, std::uint32_t ledger)
Definition: TxMeta.cpp:222
ripple::TxMeta::mDelivered
boost::optional< STAmount > mDelivered
Definition: TxMeta.h:163
ripple::STAmount
Definition: STAmount.h:42
ripple::sfTransactionMetaData
const SField sfTransactionMetaData(access, STI_OBJECT, 2, "TransactionMetaData")
Definition: SField.h:493
ripple::SerialIter
Definition: Serializer.h:368
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
ripple::sfCreatedNode
const SField sfCreatedNode(access, STI_OBJECT, 3, "CreatedNode")
Definition: SField.h:494
ripple::STArray::sort
void sort(bool(*compare)(const STObject &o1, const STObject &o2))
Definition: STArray.cpp:173
ripple::STArray::back
STObject & back()
Definition: STArray.h:88
ripple::TxMeta::thread
static bool thread(STObject &node, uint256 const &prevTxID, std::uint32_t prevLgrID)
Definition: TxMeta.cpp:238
ripple::STAmount::getIssuer
AccountID const & getIssuer() const
Definition: STAmount.h:209
ripple::STBase::getFName
SField const & getFName() const
Definition: STBase.cpp:135
ripple::Serializer
Definition: Serializer.h:43
ripple::STAccount
Definition: STAccount.h:29
ripple::STObject::getFieldIndex
int getFieldIndex(SField const &field) const
Definition: STObject.cpp:341
ripple::STObject::emplace_back
std::size_t emplace_back(Args &&... args)
Definition: STObject.h:386
ripple::STObject
Definition: STObject.h:51
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::STObject::peekAtPField
const STBase * peekAtPField(SField const &field) const
Definition: STObject.cpp:385
ripple::STObject::add
virtual void add(Serializer &s) const override
Definition: STObject.h:353
ripple::TxMeta::getAffectedNode
STObject & getAffectedNode(SLE::ref node, SField const &type)
Definition: TxMeta.cpp:177
ripple::SField
Identifies fields.
Definition: SField.h:109
ripple::STObject::getField
STBase & getField(SField const &field)
Definition: STObject.cpp:368
ripple::sfAffectedNodes
const SField sfAffectedNodes(access, STI_ARRAY, 8, "AffectedNodes")
Definition: SField.h:514
ripple::STObject::isFieldPresent
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:412
ripple::TxMeta::hasDeliveredAmount
bool hasDeliveredAmount() const
Definition: TxMeta.h:149
ripple::TxMeta::setDeliveredAmount
void setDeliveredAmount(STAmount const &delivered)
Definition: TxMeta.h:136
ripple::sfTransactionResult
const SF_U8 sfTransactionResult(access, STI_UINT8, 3, "TransactionResult")
Definition: SField.h:341
ripple::sfTakerGets
const SF_Amount sfTakerGets(access, STI_AMOUNT, 5, "TakerGets")
Definition: SField.h:441
ripple::TxMeta::getDeliveredAmount
STAmount getDeliveredAmount() const
Definition: TxMeta.h:142
ripple::STObject::getFieldU32
std::uint32_t getFieldU32(SField const &field) const
Definition: STObject.cpp:543
ripple::STObject::setFieldU32
void setFieldU32(SField const &field, std::uint32_t)
Definition: STObject.cpp:643
ripple::TxMeta::peekAffectedNode
const STObject & peekAffectedNode(uint256 const &) const
Definition: TxMeta.cpp:209
ripple::TxMeta::setAffectedNode
void setAffectedNode(uint256 const &, SField const &type, std::uint16_t nodeType)
Definition: TxMeta.cpp:94
ripple::STObject::getFieldAmount
STAmount const & getFieldAmount(SField const &field) const
Definition: STObject.cpp:587
ripple::sfPreviousTxnID
const SF_U256 sfPreviousTxnID(access, STI_HASH256, 5, "PreviousTxnID", SField::sMD_DeleteFinal)
Definition: SField.h:419
ripple::STObject::getFieldH256
uint256 getFieldH256(SField const &field) const
Definition: STObject.cpp:567
string