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 template <class T>
31  uint256 const& txid,
32  std::uint32_t ledger,
33  T const& data,
34  CtorHelper)
35  : mTransactionID(txid), mLedger(ledger), mNodes(sfAffectedNodes, 32)
36 {
37  SerialIter sit(makeSlice(data));
38 
39  STObject obj(sit, sfMetadata);
42  mNodes = *dynamic_cast<STArray*>(&obj.getField(sfAffectedNodes));
43 
46 }
47 
48 TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
49  : mTransactionID(txid)
50  , mLedger(ledger)
51  , mNodes(obj.getFieldArray(sfAffectedNodes))
52 {
55 
56  auto affectedNodes =
57  dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
58  assert(affectedNodes);
59  if (affectedNodes)
60  mNodes = *affectedNodes;
61 
64 }
65 
66 TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
67  : TxMeta(txid, ledger, vec, CtorHelper())
68 {
69 }
70 
72  uint256 const& txid,
73  std::uint32_t ledger,
74  std::string const& data)
75  : TxMeta(txid, ledger, data, CtorHelper())
76 {
77 }
78 
79 TxMeta::TxMeta(uint256 const& transactionID, std::uint32_t ledger)
80  : mTransactionID(transactionID)
81  , mLedger(ledger)
82  , mIndex(static_cast<std::uint32_t>(-1))
83  , mResult(255)
84  , mNodes(sfAffectedNodes)
85 {
86  mNodes.reserve(32);
87 }
88 
89 void
91  uint256 const& node,
92  SField const& type,
93  std::uint16_t nodeType)
94 {
95  // make sure the node exists and force its type
96  for (auto& n : mNodes)
97  {
98  if (n.getFieldH256(sfLedgerIndex) == node)
99  {
100  n.setFName(type);
101  n.setFieldU16(sfLedgerEntryType, nodeType);
102  return;
103  }
104  }
105 
106  mNodes.push_back(STObject(type));
107  STObject& obj = mNodes.back();
108 
109  assert(obj.getFName() == type);
110  obj.setFieldH256(sfLedgerIndex, node);
111  obj.setFieldU16(sfLedgerEntryType, nodeType);
112 }
113 
114 boost::container::flat_set<AccountID>
116 {
117  boost::container::flat_set<AccountID> list;
118  list.reserve(10);
119 
120  // This code should match the behavior of the JS method:
121  // Meta#getAffectedAccounts
122  for (auto const& it : mNodes)
123  {
124  int index = it.getFieldIndex(
125  (it.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
126 
127  if (index != -1)
128  {
129  const STObject* inner =
130  dynamic_cast<const STObject*>(&it.peekAtIndex(index));
131  assert(inner);
132  if (inner)
133  {
134  for (auto const& field : *inner)
135  {
136  if (auto sa = dynamic_cast<STAccount const*>(&field))
137  {
138  assert(!sa->isDefault());
139  if (!sa->isDefault())
140  list.insert(sa->value());
141  }
142  else if (
143  (field.getFName() == sfLowLimit) ||
144  (field.getFName() == sfHighLimit) ||
145  (field.getFName() == sfTakerPays) ||
146  (field.getFName() == sfTakerGets))
147  {
148  const STAmount* lim =
149  dynamic_cast<const STAmount*>(&field);
150 
151  if (lim != nullptr)
152  {
153  auto issuer = lim->getIssuer();
154 
155  if (issuer.isNonZero())
156  list.insert(issuer);
157  }
158  else
159  {
160  JLOG(j.fatal()) << "limit is not amount "
161  << field.getJson(JsonOptions::none);
162  }
163  }
164  }
165  }
166  }
167  }
168 
169  return list;
170 }
171 
172 STObject&
174 {
175  uint256 index = node->key();
176  for (auto& n : mNodes)
177  {
178  if (n.getFieldH256(sfLedgerIndex) == index)
179  return n;
180  }
181  mNodes.push_back(STObject(type));
182  STObject& obj = mNodes.back();
183 
184  assert(obj.getFName() == type);
185  obj.setFieldH256(sfLedgerIndex, index);
186  obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType));
187 
188  return obj;
189 }
190 
191 STObject&
193 {
194  for (auto& n : mNodes)
195  {
196  if (n.getFieldH256(sfLedgerIndex) == node)
197  return n;
198  }
199  assert(false);
200  Throw<std::runtime_error>("Affected node not found");
201  return *(mNodes.begin()); // Silence compiler warning.
202 }
203 
204 STObject
206 {
208  assert(mResult != 255);
211  metaData.emplace_back(mNodes);
212  if (hasDeliveredAmount())
214  return metaData;
215 }
216 
217 void
219 {
220  mResult = TERtoInt(result);
221  mIndex = index;
222  assert((mResult == 0) || ((mResult > 100) && (mResult <= 255)));
223 
224  mNodes.sort([](STObject const& o1, STObject const& o2) {
226  });
227 
228  getAsObject().add(s);
229 }
230 
231 } // namespace ripple
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
ripple::TxMeta::mResult
int mResult
Definition: TxMeta.h:128
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:626
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:421
ripple::TxMeta::getAsObject
STObject getAsObject() const
Definition: TxMeta.cpp:205
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:115
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:453
std::vector< unsigned char >
ripple::STObject::getFieldU8
unsigned char getFieldU8(SField const &field) const
Definition: STObject.cpp:520
ripple::sfNewFields
const SField sfNewFields(access, STI_OBJECT, 8, "NewFields")
Definition: SField.h:501
ripple::sfTakerPays
const SF_Amount sfTakerPays(access, STI_AMOUNT, 4, "TakerPays")
Definition: SField.h:442
ripple::STArray::push_back
void push_back(STObject const &object)
Definition: STArray.h:102
ripple::TxMeta::mIndex
std::uint32_t mIndex
Definition: TxMeta.h:127
ripple::TERtoInt
constexpr TERUnderlyingType TERtoInt(TELcodes v)
Definition: TER.h:283
ripple::TxMeta::TxMeta
TxMeta(uint256 const &txID, std::uint32_t ledger, T const &data, CtorHelper)
Definition: TxMeta.cpp:30
ripple::TxMeta::CtorHelper
Definition: TxMeta.h:35
ripple::sfFinalFields
const SField sfFinalFields(access, STI_OBJECT, 7, "FinalFields")
Definition: SField.h:500
ripple::sfHighLimit
const SF_Amount sfHighLimit(access, STI_AMOUNT, 7, "HighLimit")
Definition: SField.h:445
ripple::sfLowLimit
const SF_Amount sfLowLimit(access, STI_AMOUNT, 6, "LowLimit")
Definition: SField.h:444
ripple::TxMeta::mNodes
STArray mNodes
Definition: TxMeta.h:132
ripple::TxMeta
Definition: TxMeta.h:32
ripple::base_uint< 256 >
ripple::STArray::begin
iterator begin()
Definition: STArray.h:114
ripple::STObject::setFieldU8
void setFieldU8(SField const &field, unsigned char)
Definition: STObject.cpp:620
ripple::STObject::setFieldAmount
void setFieldAmount(SField const &field, STAmount const &)
Definition: STObject.cpp:680
ripple::JsonOptions::none
@ none
ripple::STObject::setFieldH256
void setFieldH256(SField const &field, uint256 const &)
Definition: STObject.cpp:650
ripple::TERSubset< CanCvtToTER >
ripple::STArray
Definition: STArray.h:28
ripple::TxMeta::addRaw
void addRaw(Serializer &, TER, std::uint32_t index)
Definition: TxMeta.cpp:218
ripple::STAmount
Definition: STAmount.h:42
ripple::sfTransactionMetaData
const SField sfTransactionMetaData(access, STI_OBJECT, 2, "TransactionMetaData")
Definition: SField.h:495
ripple::SerialIter
Definition: Serializer.h:308
ripple::HashPrefix::transactionID
@ transactionID
transaction plus signature to give transaction ID
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:496
ripple::STArray::sort
void sort(bool(*compare)(const STObject &o1, const STObject &o2))
Definition: STArray.cpp:164
ripple::STArray::back
STObject & back()
Definition: STArray.h:83
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:39
ripple::STAccount
Definition: STAccount.h:29
ripple::STObject::emplace_back
std::size_t emplace_back(Args &&... args)
Definition: STObject.h:384
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:374
ripple::STObject::add
virtual void add(Serializer &s) const override
Definition: STObject.h:351
ripple::TxMeta::getAffectedNode
STObject & getAffectedNode(SLE::ref node, SField const &type)
Definition: TxMeta.cpp:173
ripple::SField
Identifies fields.
Definition: SField.h:109
ripple::STObject::getField
STBase & getField(SField const &field)
Definition: STObject.cpp:357
ripple::sfAffectedNodes
const SField sfAffectedNodes(access, STI_ARRAY, 8, "AffectedNodes")
Definition: SField.h:516
std
STL namespace.
ripple::STObject::isFieldPresent
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:401
ripple::TxMeta::hasDeliveredAmount
bool hasDeliveredAmount() const
Definition: TxMeta.h:119
ripple::TxMeta::setDeliveredAmount
void setDeliveredAmount(STAmount const &delivered)
Definition: TxMeta.h:106
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:443
ripple::TxMeta::getDeliveredAmount
STAmount getDeliveredAmount() const
Definition: TxMeta.h:112
ripple::STObject::getFieldU32
std::uint32_t getFieldU32(SField const &field) const
Definition: STObject.cpp:532
ripple::STObject::setFieldU32
void setFieldU32(SField const &field, std::uint32_t)
Definition: STObject.cpp:632
ripple::TxMeta::setAffectedNode
void setAffectedNode(uint256 const &, SField const &type, std::uint16_t nodeType)
Definition: TxMeta.cpp:90
ripple::STObject::getFieldAmount
STAmount const & getFieldAmount(SField const &field) const
Definition: STObject.cpp:576
ripple::STArray::reserve
void reserve(std::size_t n)
Definition: STArray.h:154
ripple::STObject::getFieldH256
uint256 getFieldH256(SField const &field) const
Definition: STObject.cpp:556
string