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/contract.h>
21 #include <ripple/ledger/TxMeta.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/json/to_string.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>
32 TxMeta::TxMeta (uint256 const& txid,
33  std::uint32_t ledger, T const& data, CtorHelper)
34  : mTransactionID (txid)
35  , mLedger (ledger)
36  , mNodes (sfAffectedNodes, 32)
37 {
38  SerialIter sit (makeSlice(data));
39 
40  STObject obj(sit, sfMetadata);
43  mNodes = * dynamic_cast<STArray*> (&obj.getField (sfAffectedNodes));
44 
47 }
48 
49 TxMeta::TxMeta (uint256 const& txid, std::uint32_t ledger, STObject const& obj)
50  : mTransactionID (txid)
51  , mLedger (ledger)
52  , mNodes (obj.getFieldArray (sfAffectedNodes))
53 {
56 
57  auto affectedNodes = dynamic_cast <STArray const*>
59  assert (affectedNodes);
60  if (affectedNodes)
61  mNodes = *affectedNodes;
62 
65 }
66 
67 TxMeta::TxMeta (uint256 const& txid,
68  std::uint32_t ledger,
69  Blob const& vec)
70  : TxMeta (txid, ledger, vec, CtorHelper ())
71 {
72 }
73 
74 TxMeta::TxMeta (uint256 const& txid,
75  std::uint32_t ledger,
76  std::string const& data)
77  : TxMeta (txid, ledger, data, CtorHelper ())
78 {
79 }
80 
81 bool TxMeta::isNodeAffected (uint256 const& node) const
82 {
83  for (auto const& n : mNodes)
84  {
85  if (n.getFieldH256 (sfLedgerIndex) == node)
86  return true;
87  }
88 
89  return false;
90 }
91 
92 void TxMeta::setAffectedNode (uint256 const& node, 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 ((it.getFName () == sfCreatedNode) ? sfNewFields : sfFinalFields);
125 
126  if (index != -1)
127  {
128  const STObject* inner = dynamic_cast<const STObject*> (&it.peekAtIndex (index));
129  assert(inner);
130  if (inner)
131  {
132  for (auto const& field : *inner)
133  {
134  if (auto sa = dynamic_cast<STAccount const*> (&field))
135  {
136  assert (! sa->isDefault());
137  if (! sa->isDefault())
138  list.insert(sa->value());
139  }
140  else if ((field.getFName () == sfLowLimit) || (field.getFName () == sfHighLimit) ||
141  (field.getFName () == sfTakerPays) || (field.getFName () == sfTakerGets))
142  {
143  const STAmount* lim = dynamic_cast<const STAmount*> (&field);
144 
145  if (lim != nullptr)
146  {
147  auto issuer = lim->getIssuer ();
148 
149  if (issuer.isNonZero ())
150  list.insert(issuer);
151  }
152  else
153  {
154  JLOG (j.fatal()) << "limit is not amount "
155  << field.getJson (JsonOptions::none);
156  }
157  }
158  }
159  }
160  }
161  }
162 
163  return list;
164 }
165 
167 {
168  uint256 index = node->key();
169  for (auto& n : mNodes)
170  {
171  if (n.getFieldH256 (sfLedgerIndex) == index)
172  return n;
173  }
174  mNodes.push_back (STObject (type));
175  STObject& obj = mNodes.back ();
176 
177  assert (obj.getFName () == type);
178  obj.setFieldH256 (sfLedgerIndex, index);
179  obj.setFieldU16 (sfLedgerEntryType, node->getFieldU16 (sfLedgerEntryType));
180 
181  return obj;
182 }
183 
185 {
186  for (auto& n : mNodes)
187  {
188  if (n.getFieldH256 (sfLedgerIndex) == node)
189  return n;
190  }
191  assert (false);
192  Throw<std::runtime_error> ("Affected node not found");
193  return *(mNodes.begin()); // Silence compiler warning.
194 }
195 
196 const STObject& TxMeta::peekAffectedNode (uint256 const& node) const
197 {
198  for (auto const& n : mNodes)
199  {
200  if (n.getFieldH256 (sfLedgerIndex) == node)
201  return n;
202  }
203 
204  Throw<std::runtime_error> ("Affected node not found");
205  return *(mNodes.begin()); // Silence compiler warning.
206 }
207 
208 void TxMeta::init (uint256 const& id, std::uint32_t ledger)
209 {
210  mTransactionID = id;
211  mLedger = ledger;
213  mDelivered = boost::optional <STAmount> ();
214 }
215 
216 void TxMeta::swap (TxMeta& s) noexcept
217 {
218  assert ((mTransactionID == s.mTransactionID) && (mLedger == s.mLedger));
219  mNodes.swap (s.mNodes);
220 }
221 
222 bool TxMeta::thread (STObject& node, uint256 const& prevTxID, std::uint32_t prevLgrID)
223 {
224  if (node.getFieldIndex (sfPreviousTxnID) == -1)
225  {
226  assert (node.getFieldIndex (sfPreviousTxnLgrSeq) == -1);
227  node.setFieldH256 (sfPreviousTxnID, prevTxID);
228  node.setFieldU32 (sfPreviousTxnLgrSeq, prevLgrID);
229  return true;
230  }
231 
232  assert (node.getFieldH256 (sfPreviousTxnID) == prevTxID);
233  assert (node.getFieldU32 (sfPreviousTxnLgrSeq) == prevLgrID);
234  return false;
235 }
236 
237 static bool compare (const STObject& o1, const STObject& o2)
238 {
240 }
241 
243 {
244  STObject metaData (sfTransactionMetaData);
245  assert (mResult != 255);
248  metaData.emplace_back (mNodes);
249  if (hasDeliveredAmount ())
251  return metaData;
252 }
253 
254 void TxMeta::addRaw (Serializer& s, TER result, std::uint32_t index)
255 {
256  mResult = TERtoInt (result);
257  mIndex = index;
258  assert ((mResult == 0) || ((mResult > 100) && (mResult <= 255)));
259 
260  mNodes.sort (compare);
261 
262  getAsObject ().add (s);
263 }
264 
265 } // ripple
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:312
ripple::TxMeta::mResult
int mResult
Definition: TxMeta.h:139
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:199
ripple::sfTransactionIndex
const SF_U32 sfTransactionIndex(access, STI_UINT32, 28, "TransactionIndex")
Definition: SField.h:365
std::string
STL class.
std::shared_ptr< STLedgerEntry >
ripple::STObject::setFieldU16
void setFieldU16(SField const &field, std::uint16_t)
Definition: STObject.cpp:596
ripple::sfPreviousTxnLgrSeq
const SF_U32 sfPreviousTxnLgrSeq(access, STI_UINT32, 5, "PreviousTxnLgrSeq", SField::sMD_DeleteFinal)
Definition: SField.h:341
ripple::sfLedgerEntryType
const SF_U16 sfLedgerEntryType(access, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never)
Definition: SField.h:330
ripple::sfLedgerIndex
const SF_U256 sfLedgerIndex(access, STI_HASH256, 6, "LedgerIndex")
Definition: SField.h:406
ripple::TxMeta::getAsObject
STObject getAsObject() const
Definition: TxMeta.cpp:242
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:321
ripple::sfDeliveredAmount
const SF_Amount sfDeliveredAmount(access, STI_AMOUNT, 18, "DeliveredAmount")
Definition: SField.h:437
std::vector< unsigned char >
ripple::STObject::getFieldU8
unsigned char getFieldU8(SField const &field) const
Definition: STObject.cpp:502
ripple::sfNewFields
const SField sfNewFields(access, STI_OBJECT, 8, "NewFields")
Definition: SField.h:485
ripple::TxMeta::TxMeta
TxMeta()
Definition: TxMeta.h:47
ripple::sfTakerPays
const SF_Amount sfTakerPays(access, STI_AMOUNT, 4, "TakerPays")
Definition: SField.h:426
ripple::STArray::push_back
void push_back(STObject const &object)
Definition: STArray.h:95
ripple::TxMeta::mIndex
std::uint32_t mIndex
Definition: TxMeta.h:138
ripple::TERtoInt
constexpr TERUnderlyingType TERtoInt(TELcodes v)
Definition: TER.h:289
ripple::TxMeta::CtorHelper
Definition: TxMeta.h:40
ripple::TxMeta::isNodeAffected
bool isNodeAffected(uint256 const &) const
Definition: TxMeta.cpp:81
ripple::sfFinalFields
const SField sfFinalFields(access, STI_OBJECT, 7, "FinalFields")
Definition: SField.h:484
ripple::sfHighLimit
const SF_Amount sfHighLimit(access, STI_AMOUNT, 7, "HighLimit")
Definition: SField.h:429
ripple::TxMeta::swap
void swap(TxMeta &) noexcept
Definition: TxMeta.cpp:216
ripple::sfLowLimit
const SF_Amount sfLowLimit(access, STI_AMOUNT, 6, "LowLimit")
Definition: SField.h:428
ripple::TxMeta::mNodes
STArray mNodes
Definition: TxMeta.h:143
ripple::TxMeta
Definition: TxMeta.h:33
ripple::base_uint< 256 >
ripple::STArray::begin
iterator begin()
Definition: STArray.h:105
ripple::TxMeta::mTransactionID
uint256 mTransactionID
Definition: TxMeta.h:136
ripple::TxMeta::mLedger
std::uint32_t mLedger
Definition: TxMeta.h:137
ripple::STObject::setFieldU8
void setFieldU8(SField const &field, unsigned char)
Definition: STObject.cpp:591
ripple::STObject::setFieldAmount
void setFieldAmount(SField const &field, STAmount const &)
Definition: STObject.cpp:642
ripple::compare
int compare(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition: base_uint.h:439
ripple::JsonOptions::none
@ none
ripple::STObject::setFieldH256
void setFieldH256(SField const &field, uint256 const &)
Definition: STObject.cpp:616
ripple::TERSubset< CanCvtToTER >
ripple::STArray
Definition: STArray.h:28
ripple::TxMeta::addRaw
void addRaw(Serializer &, TER, std::uint32_t index)
Definition: TxMeta.cpp:254
ripple::TxMeta::init
void init(uint256 const &transactionID, std::uint32_t ledger)
Definition: TxMeta.cpp:208
ripple::TxMeta::mDelivered
boost::optional< STAmount > mDelivered
Definition: TxMeta.h:141
ripple::STAmount
Definition: STAmount.h:42
ripple::sfTransactionMetaData
const SField sfTransactionMetaData(access, STI_OBJECT, 2, "TransactionMetaData")
Definition: SField.h:479
ripple::SerialIter
Definition: Serializer.h:311
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:60
std::uint32_t
ripple::sfCreatedNode
const SField sfCreatedNode(access, STI_OBJECT, 3, "CreatedNode")
Definition: SField.h:480
ripple::STArray::sort
void sort(bool(*compare)(const STObject &o1, const STObject &o2))
Definition: STArray.cpp:171
ripple::STArray::back
STObject & back()
Definition: STArray.h:84
ripple::TxMeta::thread
static bool thread(STObject &node, uint256 const &prevTxID, std::uint32_t prevLgrID)
Definition: TxMeta.cpp:222
ripple::STAmount::getIssuer
AccountID const & getIssuer() const
Definition: STAmount.h:160
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:326
ripple::STObject::emplace_back
std::size_t emplace_back(Args &&... args)
Definition: STObject.h:371
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:367
ripple::STObject::add
virtual void add(Serializer &s) const override
Definition: STObject.h:343
ripple::TxMeta::getAffectedNode
STObject & getAffectedNode(SLE::ref node, SField const &type)
Definition: TxMeta.cpp:166
ripple::SField
Identifies fields.
Definition: SField.h:112
ripple::STObject::getField
STBase & getField(SField const &field)
Definition: STObject.cpp:351
ripple::sfAffectedNodes
const SField sfAffectedNodes(access, STI_ARRAY, 8, "AffectedNodes")
Definition: SField.h:500
ripple::STObject::isFieldPresent
bool isFieldPresent(SField const &field) const
Definition: STObject.cpp:392
ripple::TxMeta::hasDeliveredAmount
bool hasDeliveredAmount() const
Definition: TxMeta.h:128
ripple::TxMeta::setDeliveredAmount
void setDeliveredAmount(STAmount const &delivered)
Definition: TxMeta.h:117
ripple::sfTransactionResult
const SF_U8 sfTransactionResult(access, STI_UINT8, 3, "TransactionResult")
Definition: SField.h:326
ripple::sfTakerGets
const SF_Amount sfTakerGets(access, STI_AMOUNT, 5, "TakerGets")
Definition: SField.h:427
ripple::TxMeta::getDeliveredAmount
STAmount getDeliveredAmount() const
Definition: TxMeta.h:122
ripple::STObject::getFieldU32
std::uint32_t getFieldU32(SField const &field) const
Definition: STObject.cpp:512
ripple::STObject::setFieldU32
void setFieldU32(SField const &field, std::uint32_t)
Definition: STObject.cpp:601
ripple::TxMeta::peekAffectedNode
const STObject & peekAffectedNode(uint256 const &) const
Definition: TxMeta.cpp:196
ripple::TxMeta::setAffectedNode
void setAffectedNode(uint256 const &, SField const &type, std::uint16_t nodeType)
Definition: TxMeta.cpp:92
ripple::STObject::getFieldAmount
STAmount const & getFieldAmount(SField const &field) const
Definition: STObject.cpp:549
ripple::sfPreviousTxnID
const SF_U256 sfPreviousTxnID(access, STI_HASH256, 5, "PreviousTxnID", SField::sMD_DeleteFinal)
Definition: SField.h:405
ripple::STObject::getFieldH256
uint256 getFieldH256(SField const &field) const
Definition: STObject.cpp:532
string