Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTItem.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTItem.cpp
4  *
5  */
6 
7 /************************************************************
8  -----BEGIN PGP SIGNED MESSAGE-----
9  Hash: SHA1
10 
11  * OPEN TRANSACTIONS
12  *
13  * Financial Cryptography and Digital Cash
14  * Library, Protocol, API, Server, CLI, GUI
15  *
16  * -- Anonymous Numbered Accounts.
17  * -- Untraceable Digital Cash.
18  * -- Triple-Signed Receipts.
19  * -- Cheques, Vouchers, Transfers, Inboxes.
20  * -- Basket Currencies, Markets, Payment Plans.
21  * -- Signed, XML, Ricardian-style Contracts.
22  * -- Scripted smart contracts.
23  *
24  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
25  *
26  * EMAIL:
28  *
29  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
30  *
31  * KEY FINGERPRINT (PGP Key in license file):
32  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
33  *
34  * OFFICIAL PROJECT WIKI(s):
35  * https://github.com/FellowTraveler/Moneychanger
36  * https://github.com/FellowTraveler/Open-Transactions/wiki
37  *
38  * WEBSITE:
39  * http://www.OpenTransactions.org/
40  *
41  * Components and licensing:
42  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
43  * -- otlib.........A class library.......LICENSE:...LAGPLv3
44  * -- otapi.........A client API..........LICENSE:...LAGPLv3
45  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
46  * -- otserver......Server Application....LICENSE:....AGPLv3
47  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
48  *
49  * All of the above OT components were designed and written by
50  * Fellow Traveler, with the exception of Moneychanger, which
51  * was contracted out to Vicky C ([email protected]).
52  * The open-source community has since actively contributed.
53  *
54  * -----------------------------------------------------
55  *
56  * LICENSE:
57  * This program is free software: you can redistribute it
58  * and/or modify it under the terms of the GNU Affero
59  * General Public License as published by the Free Software
60  * Foundation, either version 3 of the License, or (at your
61  * option) any later version.
62  *
63  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
64  * section 7: (This paragraph applies only to the LAGPLv3
65  * components listed above.) If you modify this Program, or
66  * any covered work, by linking or combining it with other
67  * code, such other code is not for that reason alone subject
68  * to any of the requirements of the GNU Affero GPL version 3.
69  * (==> This means if you are only using the OT API, then you
70  * don't have to open-source your code--only your changes to
71  * Open-Transactions itself must be open source. Similar to
72  * LGPLv3, except it applies to software-as-a-service, not
73  * just to distributing binaries.)
74  *
75  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
76  * used by Open Transactions: This program is released under
77  * the AGPL with the additional exemption that compiling,
78  * linking, and/or using OpenSSL is allowed. The same is true
79  * for any other open source libraries included in this
80  * project: complete waiver from the AGPL is hereby granted to
81  * compile, link, and/or use them with Open-Transactions,
82  * according to their own terms, as long as the rest of the
83  * Open-Transactions terms remain respected, with regard to
84  * the Open-Transactions code itself.
85  *
86  * Lucre License:
87  * This code is also "dual-license", meaning that Ben Lau-
88  * rie's license must also be included and respected, since
89  * the code for Lucre is also included with Open Transactions.
90  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
91  * The Laurie requirements are light, but if there is any
92  * problem with his license, simply remove the Lucre code.
93  * Although there are no other blind token algorithms in Open
94  * Transactions (yet. credlib is coming), the other functions
95  * will continue to operate.
96  * See Lucre on Github: https://github.com/benlaurie/lucre
97  * -----------------------------------------------------
98  * You should have received a copy of the GNU Affero General
99  * Public License along with this program. If not, see:
100  * http://www.gnu.org/licenses/
101  *
102  * If you would like to use this software outside of the free
103  * software license, please contact FellowTraveler.
104  * (Unfortunately many will run anonymously and untraceably,
105  * so who could really stop them?)
106  *
107  * DISCLAIMER:
108  * This program is distributed in the hope that it will be
109  * useful, but WITHOUT ANY WARRANTY; without even the implied
110  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
111  * PURPOSE. See the GNU Affero General Public License for
112  * more details.
113 
114  -----BEGIN PGP SIGNATURE-----
115  Version: GnuPG v1.4.9 (Darwin)
116 
117  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
118  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
119  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
120  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
121  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
122  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
123  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
124  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
125  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
126  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
127  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
128  kamH0Y/n11lCvo1oQxM+
129  =uSzz
130  -----END PGP SIGNATURE-----
131  **************************************************************/
132 
133 #include "stdafx.hpp"
134 
135 #include "OTItem.hpp"
136 #include "OTAccount.hpp"
137 #include "OTCheque.hpp"
138 #include "OTLedger.hpp"
139 #include "OTLog.hpp"
140 #include "OTPseudonym.hpp"
141 #include "OTStorage.hpp"
142 
143 #include <irrxml/irrXML.hpp>
144 
145 #include <memory>
146 
147 // Server-side.
148 //
149 // By the time this is called, I know that the item, AND this balance item
150 // (this)
151 // both have the correct user id, server id, account id, and transaction id, and
152 // they have been signed properly by the owner.
153 //
154 // So what do I need to verify in this function?
155 //
156 // -- That the transactions on THE_NYM (server-side), minus the current
157 // transaction number being processed,
158 // are all still there.
159 // -- If theMessageNym is missing certain numbers that I expected to find on
160 // him, that means he is trying to
161 // trick the server into signing a new agreement where he is no longer
162 // responsible for those numbers. They must
163 // all be there.
164 // -- If theMessageNym has ADDED certain numbers that I DIDN'T expect to find on
165 // him, then he's trying to trick
166 // me into allowing him to add those numbers to his receipt -- OR it could
167 // mean that certain numbers were already
168 // removed on my side (such as the opening # for a cron item like a market
169 // offer that has already been closed),
170 // but the client-side isn't aware of this yet, and so he is trying to sign
171 // off on formerly-good numbers that
172 // have since expired. This shouldn't happen IF the client has been properly
173 // notified about these numbers before
174 // sending his request. Such notifications are dropped into the Nymbox AND
175 // related asset account inboxes.
176 //
177 
178 namespace opentxs
179 {
180 
182  OTTransaction& TARGET_TRANSACTION,
183  bool bIsRealTransaction) // Sometimes
184  // the trans#
185  // is 0 (like
186 // when processing Nymbox)
187 {
189  otOut << __FUNCTION__
190  << ": wrong item type. Expected OTItem::transactionStatement.\n";
191  return false;
192  }
193 
194  //
195  // So if the caller was planning to remove a number, or clear a receipt from
196  // the inbox, he'll have to do
197  // so first before calling this function, and then ADD IT AGAIN if this
198  // function fails. (Because the new
199  // Balance Agreement is always the user signing WHAT THE NEW VERSION WILL BE
200  // AFTER THE TRANSACTION IS PROCESSED.)
201  //
202  const OTString SERVER_ID(GetPurportedServerID());
203 
204  OTPseudonym theRemovedNym;
205 
206  if (bIsRealTransaction) // Sometimes my "transaction number" is 0 since
207  // we're accepting numbers from the Nymbox (which is
208  // done by message, not transaction.)
209  { // In such cases, there's no point in checking the server-side to "make
210  // sure it has number 0!" (because it won't.)
211  bool bIWasFound =
212  THE_NYM.VerifyIssuedNum(SERVER_ID, GetTransactionNum());
213 
214  if (!bIWasFound) {
215  otOut << __FUNCTION__ << ": Transaction# (" << GetTransactionNum()
216  << ") doesn't appear on Nym's issued list.\n";
217  return false;
218  }
219 
220  // In the case that this is a real transaction, it must be a
221  // cancelCronItem, payment plan or
222  // market offer (since the other transaction types require a balance
223  // statement, not a transaction
224  // statement.) Also this might not be a transaction at all, but in that
225  // case we won't enter this
226  // block anyway.
227  //
228  switch (TARGET_TRANSACTION.GetType()) {
229  // In the case of cancelCronItem(), we'd expect, if success, the number
230  // would be removed, so we have
231  // to remove it now, to simulate success for the verification. Then we
232  // add it again afterwards, before
233  // returning.
234  //
236  // Only adding it to theRemovedNym here since VerifyIssuedNum() is
237  // called just above.
238  // (Don't want to "add it back" if it wasn't there in the first
239  // place!)
240  //
241  if (THE_NYM.RemoveIssuedNum(SERVER_ID,
242  GetTransactionNum())) // doesn't save.
243  theRemovedNym.AddIssuedNum(SERVER_ID, GetTransactionNum());
244  else
245  otOut << "OTItem::VerifyTransactionStatemen: Expected THE_NYM "
246  "to have trans# " << GetTransactionNum()
247  << " but didn't find it.\n";
248  break;
249 
250  // IN the case of the offer/plan, we do NOT want to remove from issued
251  // list. That only happens when
252  // the plan or offer is removed from Cron and closed. As the plan or
253  // offer continues processing,
254  // the user is responsible for its main transaction number until he
255  // signs off on final closing,
256  // after many receipts have potentially been received.
257  //
261  // THE_NYM.RemoveIssuedNum(SERVER_ID,
262  // GetTransactionNum()); // commented out, explained just
263  // above.
264  break;
265  default:
266  otErr << "OTItem::VerifyTransactionStatement: Unexpected "
267  "transaction type.\n";
268  break;
269  }
270 
271  // Client side will NOT remove from issued list in this case (market
272  // offer, payment plan, which are
273  // the only transactions that use a transactionStatement, which is
274  // otherwise used for Nymbox.)
275  }
276 
277  // VERIFY that the Nyms have a matching list of transaction numbers...
278 
279  bool bSuccess = false;
280 
281  OTString strMessageNym;
282 
283  GetAttachment(strMessageNym);
284  OTPseudonym theMessageNym;
285 
286  if ((strMessageNym.GetLength() > 2) &&
287  theMessageNym.LoadFromString(strMessageNym)) {
288  // If success, I know the server-side copy of the user's Nym (THE_NYM)
289  // has the same number
290  // of transactions as the message nym, and that EVERY ONE OF THEM was
291  // found individually.
292  //
293  bSuccess = THE_NYM.VerifyIssuedNumbersOnNym(
294  theMessageNym); // <==== ************************************
295  }
296 
297  // NOW let's set things back how they were before, so we can RETURN.
298  //
299  if (bIsRealTransaction) {
300  switch (TARGET_TRANSACTION.GetType()) {
302  // Should only actually iterate once, in this case.
303  for (int32_t i = 0;
304  i < theRemovedNym.GetIssuedNumCount(GetPurportedServerID());
305  i++) {
306  int64_t lTemp =
307  theRemovedNym.GetIssuedNum(GetPurportedServerID(), i);
308 
309  if (i > 0)
310  otErr << "OTItem::VerifyTransactionStatement: THIS SHOULD "
311  "NOT HAPPEN.\n";
312  else if (false ==
313  THE_NYM.AddIssuedNum(SERVER_ID,
314  lTemp)) // doesn't save.
315  otErr << "Failed adding issued number back to THE_NYM in "
316  "OTItem::VerifyTransactionStatement.\n";
317  }
318  break;
319 
323  default:
324  // THE_NYM.RemoveIssuedNum(SERVER_ID,
325  // GetTransactionNum()); // commented out, explained just
326  // above.
327  break;
328  }
329  }
330 
331  // Might want to consider saving the Nym here.
332  // Also want to save the latest signed receipt, since it VERIFIES.
333  // Or maybe let caller decide?
334 
335  return bSuccess;
336 }
337 
338 // Server-side.
339 //
340 // By the time this is called, I know that the item, AND this balance item
341 // (this)
342 // both have the correct user id, server id, account id, and transaction id, and
343 // they have been signed properly by the owner.
344 //
345 // So what do I need to verify in this function?
346 //
347 // 1) That THE_ACCOUNT.GetBalance() + lActualAdjustment equals the amount in
348 // GetAmount().
349 //
350 // 2) That the inbox transactions and outbox transactions match up to the list
351 // of sub-items
352 // on THIS balance item.
353 //
354 // 3) That the transactions on the Nym, minus the current transaction number
355 // being processed,
356 // are all still there.
357 //
359  int64_t lActualAdjustment, OTPseudonym& THE_NYM, OTLedger& THE_INBOX,
360  OTLedger& THE_OUTBOX, const OTAccount& THE_ACCOUNT,
361  OTTransaction& TARGET_TRANSACTION,
362  int64_t lOutboxTrnsNum) // Only used in the case of transfer,
363  // where the user
364 { // doesn't know the outbox trans# in advance, so he sends
365  if (GetType() != OTItem::balanceStatement) // a dummy number (currently '1')
366  // which we verify against
367  { // the actual outbox trans# successfully, only in that special case.
368  otOut << "OTItem::" << __FUNCTION__ << ": wrong item type.\n";
369  return false;
370  }
371 
372  // We need to verify:
373  //
374  // 1) That THE_ACCOUNT.GetBalance() + lActualAdjustment equals the amount in
375  // GetAmount().
376 
377  if ((THE_ACCOUNT.GetBalance() + lActualAdjustment) !=
378  GetAmount()) // GetAmount() contains what the balance WOULD
379  // be AFTER successful transaction.
380  {
381  otOut << "OTItem::" << __FUNCTION__
382  << ": This balance statement has a value of " << GetAmount()
383  << ", but expected "
384  << (THE_ACCOUNT.GetBalance() + lActualAdjustment)
385  << ". "
386  "(Acct balance of " << THE_ACCOUNT.GetBalance()
387  << " plus actualAdjustment of " << lActualAdjustment << ".)\n";
388  return false;
389  }
390 
391  // 2) That the inbox transactions and outbox transactions match up to the
392  // list of sub-items
393  // on THIS balance item.
394 
395  int32_t nInboxItemCount = 0, nOutboxItemCount = 0;
396 
397  const char* szInbox = "Inbox";
398  const char* szOutbox = "Outbox";
399 
400  const char* pszLedgerType = nullptr;
401 
402  // otWarn << "OTItem::VerifyBalanceStatement: (ENTERING LOOP)... INBOX
403  // COUNT: %d\n"
404  // "# of inbox/outbox items on this balance statement:
405  // %d\n",
406  // THE_INBOX.GetTransactionCount(), GetItemCount());
407 
408  for (int32_t i = 0; i < GetItemCount(); i++) {
409  OTItem* pSubItem = GetItem(i);
410  OT_ASSERT(nullptr != pSubItem);
411  // otWarn << "OTItem::VerifyBalanceStatement: TOP OF LOOP (through
412  // sub-items).......\n");
413 
414  int64_t lReceiptAmountMultiplier = 1; // needed for outbox items.
415 
416  OTLedger* pLedger = nullptr;
417 
418  switch (pSubItem->GetType()) {
426  nInboxItemCount++;
427  pLedger = &THE_INBOX;
428  pszLedgerType = szInbox;
429 
430  // otWarn << "OTItem::VerifyBalanceStatement: Subitem is
431  // Inbox receipt item (NOT pending transfer)....\n");
432 
433  case OTItem::transfer:
434  break;
435  default: {
436  OTString strItemType;
437  GetTypeString(strItemType);
438  otWarn << "OTItem::" << __FUNCTION__ << ": Ignoring " << strItemType
439  << " item in balance statement while verifying it against "
440  "inbox.\n";
441  }
442  continue;
443  }
444 
445  switch (pSubItem->GetType()) {
446  case OTItem::transfer:
447  if (pSubItem->GetAmount() < 0) // it's an outbox item
448  {
449  // otWarn << "OTItem::VerifyBalanceStatement:
450  // Subitem is pending transfer (in outbox)....\n");
451 
452  lReceiptAmountMultiplier =
453  -1; // transfers out always reduce your balance.
454  nOutboxItemCount++;
455  pLedger = &THE_OUTBOX;
456  pszLedgerType = szOutbox;
457  }
458  else {
459  // otWarn << "OTItem::VerifyBalanceStatement:
460  // Subitem is pending transfer (in inbox)....\n");
461 
462  lReceiptAmountMultiplier =
463  1; // transfers in always increase your balance.
464  nInboxItemCount++;
465  pLedger = &THE_INBOX;
466  pszLedgerType = szInbox;
467  }
468  break;
470  // Here: If there is a finalReceipt on this balance statement, then ALL
471  // the other
472  // related receipts in the inbox (with same "reference to" value) had
473  // better ALSO
474  // be on the same balance statement!
475 
476  // HMM that is true, but NOT HERE... That's only true when PROCESSING
477  // the final Receipt
478  // from the inbox (in that case, all the marketReceipts must also be
479  // processed with it.)
480  // But here, I am looping through the inbox report, and there happens to
481  // be a finalReceipt
482  // on it. (Which doesn't mean necessarily that it's being processed
483  // out...)
485 
491  lReceiptAmountMultiplier = 1;
492  break;
493  default:
494  otErr << "OTItem::" << __FUNCTION__
495  << ": Bad Subitem type (SHOULD NEVER HAPPEN)....\n";
496 
497  continue; // This will never happen, due to the first continue above
498  // in the first switch.
499  }
500 
501  OTTransaction* pTransaction = nullptr;
502 
503  // In the special case of account transfer, the user has put an outbox
504  // transaction
505  // into his balance agreement with the special number '1', since he has
506  // no idea what
507  // actual number will be generated on the server side (for the outbox)
508  // when his
509  // message is received by the server.
510  //
511  // When that happens (ONLY in account transfer) then lOutboxTrnsNum will
512  // be passed
513  // in with the new transaction number chosen by the server (a real
514  // number, like 18736
515  // or whatever, instead of the default of 0 that will otherwise be
516  // passed in here.)
517  //
518  // Therefore, if lOutboxTrnsNum is larger than 0, AND if we're on an
519  // outbox item,
520  // then we can expect lOutboxTrnsNum to contain an actual transaction
521  // number, and
522  // we can expect there is a CHANCE that the sub-item will be trans# 1.
523  // (It might
524  // NOT be number 1, since there may be other outbox items-we're looping
525  // through them
526  // right now in this block.) So we'll check to see if this is the '1'
527  // and if so,
528  // we'll look up pTransaction from the outbox using the real transaction
529  // number,
530  // instead of '1' which of course would not find it (since the version
531  // in the ledger
532  // contains the ACTUAL number now, since the server just issued it.)
533  //
534  if ((lOutboxTrnsNum > 0) && (&THE_OUTBOX == pLedger) &&
535  (pSubItem->GetTransactionNum() == 1)) // TODO use a constant for
536  // this 1.
537  {
538  otLog3 << "OTItem::" << __FUNCTION__
539  << ": Subitem is new Outbox Transaction... retrieving by "
540  "special ID: " << lOutboxTrnsNum << "\n";
541 
542  pTransaction = pLedger->GetTransaction(lOutboxTrnsNum);
543  }
544  else {
545  otLog4 << "OTItem::" << __FUNCTION__
546  << ": Subitem is normal Transaction... retrieving by ID: "
547  << pSubItem->GetTransactionNum() << "\n";
548 
549  pTransaction =
550  pLedger->GetTransaction(pSubItem->GetTransactionNum());
551  }
552 
553  // Make sure that the transaction number of each sub-item is found
554  // on the appropriate ledger (inbox or outbox).
555  if (nullptr == pTransaction) {
556  otOut << "OTItem::" << __FUNCTION__ << ": Expected "
557  << pszLedgerType << " transaction (serv " << lOutboxTrnsNum
558  << ", client " << pSubItem->GetTransactionNum()
559  << ") "
560  "not found. (Amount " << pSubItem->GetAmount() << ".)\n";
561  return false;
562  }
563  // pTransaction is set below this point.
564 
565  if (pSubItem->GetReferenceToNum() !=
566  pTransaction->GetReferenceToNum()) {
567  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
568  << " transaction (" << pSubItem->GetTransactionNum()
569  << ") mismatch Reference Num: "
570  << pSubItem->GetReferenceToNum() << ", expected "
571  << pTransaction->GetReferenceToNum() << "\n";
572  return false;
573  }
574 
575  if (pSubItem->GetRawNumberOfOrigin() !=
576  pTransaction->GetRawNumberOfOrigin()) {
577  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
578  << " transaction (" << pSubItem->GetTransactionNum()
579  << ") mismatch Origin Num: "
580  << pSubItem->GetRawNumberOfOrigin() << ", expected "
581  << pTransaction->GetRawNumberOfOrigin() << "\n";
582 
583  // THE BELOW STUFF IS JUST FOR DEBUGGING PURPOSES.
584  // ERASE IT.
585 
586  /*
587  OTString strTempType;
588  pSubItem->GetTypeString(strTempType);
589 
590  int64_t lTempAmount = pSubItem->GetAmount();
591 
592  OTIdentifier ACCOUNT_ID, SERVER_ID, USER_ID;
593 
594  ACCOUNT_ID = pSubItem->GetPurportedAccountID();
595  SERVER_ID = pSubItem->GetPurportedServerID();
596  USER_ID = pSubItem->GetUserID();
597 
598  const OTString strAccountID(ACCOUNT_ID), strServerID(SERVER_ID),
599  strUserID(USER_ID);
600 
601 
602  int64_t lTempNumOfOrigin = pSubItem->GetNumberOfOrigin();
603  int64_t lTempTransNum = pSubItem->GetTransactionNum();
604  int64_t lTempRefNum = pSubItem->GetReferenceToNum();
605  int64_t lTempClosingNum = pSubItem->GetClosingNum();
606 
607 
608  const OTString strTrans(*pTransaction);
609  otOut << "OTItem::%s: %s transaction (%lld) mismatch Origin Num:
610  %lld, expected %lld\n\nTRANSACTION:\n%s\n\n"
611  "SubItem Type: %s Amount: %lld\nAccount: %s\nServer:
612  %s\nUser: %s\n"
613  " Number of Origin: %lld\n Transaction Num: %lld\n In
614  Reference To: %lld\n Closing Num: %d\n",
615  __FUNCTION__, pszLedgerType,
616  pSubItem->GetTransactionNum(),
617  pSubItem->GetRawNumberOfOrigin(),
618  pTransaction->GetRawNumberOfOrigin(),
619  strTrans.Get(),
620  strTempType.Get(), lTempAmount, strAccountID.Get(),
621  strServerID.Get(), strUserID.Get(),
622  lTempNumOfOrigin, lTempTransNum, lTempRefNum,
623  lTempClosingNum
624  );
625  */
626  return false;
627  }
628 
629  int64_t lTransactionAmount = pTransaction->GetReceiptAmount();
630  lTransactionAmount *= lReceiptAmountMultiplier;
631 
632  if (pSubItem->GetAmount() != lTransactionAmount) {
633  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
634  << " transaction (" << pSubItem->GetTransactionNum()
635  << ") "
636  "amounts don't match: report amount is "
637  << pSubItem->GetAmount() << ", but expected "
638  << lTransactionAmount
639  << ". Trans Receipt Amt: " << pTransaction->GetReceiptAmount()
640  << " (GetAmount() == " << GetAmount() << ".)\n";
641  return false;
642  }
643 
644  if ((pSubItem->GetType() == OTItem::transfer) &&
645  (pTransaction->GetType() != OTTransaction::pending)) {
646  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
647  << " transaction (" << pSubItem->GetTransactionNum()
648  << ") wrong type. (transfer block)\n";
649  return false;
650  }
651 
652  if ((pSubItem->GetType() == OTItem::chequeReceipt) &&
653  (pTransaction->GetType() != OTTransaction::chequeReceipt)) {
654  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
655  << " transaction (" << pSubItem->GetTransactionNum()
656  << ") wrong type. (chequeReceipt block)\n";
657  return false;
658  }
659 
660  if ((pSubItem->GetType() == OTItem::voucherReceipt) &&
661  (pTransaction->GetType() != OTTransaction::voucherReceipt)) {
662  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
663  << " transaction (" << pSubItem->GetTransactionNum()
664  << ") wrong type. (voucherReceipt block)\n";
665  return false;
666  }
667 
668  if ((pSubItem->GetType() == OTItem::marketReceipt) &&
669  (pTransaction->GetType() != OTTransaction::marketReceipt)) {
670  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
671  << " transaction (" << pSubItem->GetTransactionNum()
672  << ") wrong type. (marketReceipt block)\n";
673  return false;
674  }
675 
676  if ((pSubItem->GetType() == OTItem::paymentReceipt) &&
677  (pTransaction->GetType() != OTTransaction::paymentReceipt)) {
678  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
679  << " transaction (" << pSubItem->GetTransactionNum()
680  << ") wrong type. (paymentReceipt block)\n";
681  return false;
682  }
683 
684  if ((pSubItem->GetType() == OTItem::transferReceipt) &&
685  (pTransaction->GetType() != OTTransaction::transferReceipt)) {
686  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
687  << " transaction (" << pSubItem->GetTransactionNum()
688  << ") wrong type. (transferReceipt block)\n";
689  return false;
690  }
691 
692  if ((pSubItem->GetType() == OTItem::basketReceipt) &&
693  ((pTransaction->GetType() != OTTransaction::basketReceipt) ||
694  (pSubItem->GetClosingNum() != pTransaction->GetClosingNum()))) {
695  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
696  << " transaction (" << pSubItem->GetTransactionNum()
697  << ") wrong type or closing num ("
698  << pSubItem->GetClosingNum() << "). "
699  "(basketReceipt block)\n";
700  return false;
701  }
702 
703  if ((pSubItem->GetType() == OTItem::finalReceipt) &&
704  ((pTransaction->GetType() != OTTransaction::finalReceipt) ||
705  (pSubItem->GetClosingNum() != pTransaction->GetClosingNum()))) {
706  otOut << "OTItem::" << __FUNCTION__ << ": " << pszLedgerType
707  << " transaction (" << pSubItem->GetTransactionNum()
708  << ") wrong type or closing num ("
709  << pSubItem->GetClosingNum() << "). "
710  "(finalReceipt block)\n";
711  return false;
712  }
713  }
714 
715  // By this point, I have an accurate count of the inbox items, and outbox
716  // items, represented
717  // by this. let's compare those counts to the actual inbox and outbox on my
718  // side:
719 
720  if ((nInboxItemCount != THE_INBOX.GetTransactionCount()) ||
721  (nOutboxItemCount != THE_OUTBOX.GetTransactionCount())) {
722  otOut << "OTItem::" << __FUNCTION__
723  << ": Inbox or Outbox mismatch in expected transaction count.\n"
724  " --- THE_INBOX count: " << THE_INBOX.GetTransactionCount()
725  << " --- THE_OUTBOX count: " << THE_OUTBOX.GetTransactionCount()
726  << "\n"
727  "--- nInboxItemCount count: " << nInboxItemCount
728  << " --- nOutboxItemCount count: " << nOutboxItemCount << "\n\n";
729 
730  return false;
731  }
732 
733  // Now I KNOW that the inbox and outbox counts are the same, AND I know that
734  // EVERY transaction number
735  // on the balance item (this) was also found in the inbox or outbox,
736  // wherever it was expected to be found.
737  // I also know:
738  // the amount was correct,
739  // the "in reference to" number was correct,
740  // and the type was correct.
741  //
742  // So if the caller was planning to remove a number, or clear a receipt from
743  // the inbox, he'll have to do
744  // so first before calling this function, and then ADD IT AGAIN if this
745  // function fails. (Because the new
746  // Balance Agreement is always the user signing WHAT THE NEW VERSION WILL BE
747  // AFTER THE TRANSACTION IS PROCESSED.
748  // Thus, if the transaction fails to process, the action hasn't really
749  // happened, so need to add it back again.)
750 
751  // 3) Also need to verify the transactions on the Nym, against the
752  // transactions stored on this
753  // (in a message Nym attached to this.) Check for presence of each, then
754  // compare count, like above.
755 
756  OTPseudonym theRemovedNym;
757 
758  OTString SERVER_ID(GetPurportedServerID());
759 
760  // GetTransactionNum() is the ID for this balance agreement, THUS it's also
761  // the ID
762  // for whatever actual transaction is being attempted. If that ID is not
763  // verified as
764  // on my issued list, then the whole transaction is invalid (not
765  // authorized.)
766  //
767  bool bIWasFound = THE_NYM.VerifyIssuedNum(SERVER_ID, GetTransactionNum());
768 
769  if (!bIWasFound) {
770  otOut << "OTItem::" << __FUNCTION__ << ": Transaction has # that "
771  "doesn't appear on Nym's issued "
772  "list.\n";
773  return false;
774  }
775 
776  // BELOW THIS POINT, WE *KNOW* THE ISSUED NUM IS CURRENTLY ON THE LIST...
777  //
778  // (SO I CAN remove it and add it again, KNOWING that I'm never re-adding a
779  // num that wasn't there in the first place.
780 
781  // For process inbox, deposit, and withdrawal, the client will remove from
782  // issued list as soon as he
783  // receives my acknowledgment OR rejection. He expects server (me) to
784  // remove, so he signs a balance
785  // agreement to that effect. (With the number removed from issued list.)
786  //
787  // Therefore, to verify the balance agreement, we remove it on our side as
788  // well, so that they will match.
789  // The picture thus formed is what would be correct assuming a successful
790  // transaction. That way if
791  // the transaction goes through, we have our signed receipt showing the new
792  // state of things (without
793  // which we would not permit the transaction to go through :)
794  //
795  // This allows the client side to then ACTUALLY remove the number when they
796  // receive our response,
797  // as well as permits me (server) to actually remove from issued list.
798  //
799  // If ANYTHING ELSE fails during this verify process (other than
800  // processInbox, deposit, and withdraw)
801  // then we have to ADD THE # AGAIN since we still don't have a valid
802  // signature on that number. So
803  // you'll see this code repeated a few times in reverse, down inside this
804  // function. For example,
805  //
806  switch (TARGET_TRANSACTION.GetType()) {
813  // We DID verify the issued num (above) but I'm still just being safe
814  // here...
815  // ... since theRemovedNym contains numbers being re-added, just wanna
816  // make sure
817  // they were there in the first place.
818  //
819  if (THE_NYM.RemoveIssuedNum(SERVER_ID,
820  GetTransactionNum())) // doesn't save.
821  theRemovedNym.AddIssuedNum(SERVER_ID, GetTransactionNum());
822  break;
823 
828  // These, assuming success, do NOT remove an issued number. So no need
829  // to anticipate setting up the list that way, to get a match.
830  break;
831  default:
832  // Error
833  otErr << "OTItem::" << __FUNCTION__
834  << ": wrong target transaction type: "
835  << TARGET_TRANSACTION.GetTypeString() << "\n";
836  break;
837  }
838  int32_t nNumberOfTransactionNumbers1 = 0; // The Nym on this side
839  int32_t nNumberOfTransactionNumbers2 = 0; // The Message Nym.
840 
841  OTString strMessageNym;
842 
843  // First, loop through the Nym on my side, and count how many numbers total
844  // he has...
845  //
846  for (auto& it : THE_NYM.GetMapIssuedNum()) {
847  std::string strServerID = it.first;
848  dequeOfTransNums* pDeque = it.second;
849  OT_ASSERT(nullptr != pDeque);
850 
851  const OTIdentifier theServerID(strServerID.c_str());
852 
853  if (!(pDeque->empty()) && (theServerID == GetPurportedServerID())) {
854  nNumberOfTransactionNumbers1 +=
855  static_cast<int32_t>(pDeque->size());
856  break; // There's only one, in this loop, that would/could/should
857  // match. (Therefore, break after finding it.)
858  }
859  } // for
860 
861  // Next, loop through theMessageNym, and count his numbers as well...
862  // But ALSO verify that each one exists on THE_NYM, so that each individual
863  // number is checked.
864  GetAttachment(strMessageNym);
865  OTPseudonym theMessageNym;
866 
867  if ((strMessageNym.GetLength() > 2) &&
868  theMessageNym.LoadFromString(strMessageNym)) {
869  for (auto& it : theMessageNym.GetMapIssuedNum()) {
870  std::string strServerID = it.first;
871  dequeOfTransNums* pDeque = it.second;
872  OT_ASSERT(nullptr != pDeque);
873 
874  const OTIdentifier theServerID(strServerID.c_str());
875  const OTString OTstrServerID(theServerID);
876 
877  if (!(pDeque->empty()) && (theServerID == GetPurportedServerID())) {
878  nNumberOfTransactionNumbers2 +=
879  static_cast<int32_t>(pDeque->size());
880 
881  for (uint32_t i = 0; i < pDeque->size(); i++) {
882  int64_t lTransactionNumber = pDeque->at(i);
883  if (false ==
884  THE_NYM.VerifyIssuedNum(OTstrServerID,
885  lTransactionNumber)) // FAILURE
886  {
887  otOut << "OTItem::" << __FUNCTION__
888  << ": Issued transaction # " << lTransactionNumber
889  << " from Message Nym not found on this side.\n";
890 
891  // I have to do this whenever I RETURN :-(
892  switch (TARGET_TRANSACTION.GetType()) {
899  // Should only actually iterate once, in this case.
900  for (int32_t i = 0;
901  i < theRemovedNym.GetIssuedNumCount(
903  i++) {
904  int64_t lTemp = theRemovedNym.GetIssuedNum(
905  GetPurportedServerID(), i);
906 
907  if (i > 0)
908  otErr << "OTItem::" << __FUNCTION__
909  << ": THIS SHOULD NOT HAPPEN.\n";
910  else if (false ==
911  THE_NYM.AddIssuedNum(
912  SERVER_ID, lTemp)) // doesn't save.
913  otErr << "OTItem::" << __FUNCTION__
914  << ": Failed adding issued number "
915  "back to THE_NYM.\n";
916  }
917  break;
918 
923  break;
924  default:
925  // Error
926  otErr << "OTItem::" << __FUNCTION__
927  << ": wrong target transaction type: "
928  << TARGET_TRANSACTION.GetTypeString() << "\n";
929  break;
930  }
931 
932  return false;
933  }
934  } // for (numbers for a specific server.)
935  break; // Only one server ID should match, so we can break after
936  // finding it.
937  } // If the server ID matches
938  } // for (deques of numbers for each server)
939  }
940 
941  // Finally, verify that the counts match...
942  if (nNumberOfTransactionNumbers1 != nNumberOfTransactionNumbers2) {
943  otOut << "OTItem::" << __FUNCTION__
944  << ": Transaction # Count mismatch: "
945  << nNumberOfTransactionNumbers1 << " and "
946  << nNumberOfTransactionNumbers2 << "\n";
947 
948  // I have to do this whenever I RETURN :-(
949  switch (TARGET_TRANSACTION.GetType()) {
956  // Should only actually iterate once, in this case.
957  for (int32_t i = 0;
958  i < theRemovedNym.GetIssuedNumCount(GetPurportedServerID());
959  i++) {
960  int64_t lTemp =
961  theRemovedNym.GetIssuedNum(GetPurportedServerID(), i);
962 
963  if (i > 0)
964  otErr << "OTItem::" << __FUNCTION__
965  << ": THIS SHOULD NOT HAPPEN.\n";
966  else if (false ==
967  THE_NYM.AddIssuedNum(SERVER_ID,
968  lTemp)) // doesn't save.
969  otErr << "OTItem::" << __FUNCTION__
970  << ": Failed adding issued number back to THE_NYM.\n";
971  }
972  break;
973 
978  break;
979  default:
980  // Error
981  otErr << "OTItem::" << __FUNCTION__
982  << ": wrong target transaction type: "
983  << TARGET_TRANSACTION.GetTypeString() << "\n";
984  break;
985  }
986 
987  return false;
988  }
989 
990  // By this point, I know the local Nym has the same number of transactions
991  // as the message nym, and that
992  // EVERY ONE OF THEM was found individually.
993 
994  // Might want to consider saving the Nym here.
995  // Also want to save the latest signed receipt, since it VERIFIES.
996  // Or maybe let caller decide?
997 
998  // I have to do this whenever I RETURN :-(
999  // EVEN IF SUCCESS, we have only succeeded to verify the balance statement.
1000  // We must still go on to verify the transaction itself, and ONLY THEN will
1001  // we (possibly) remove the issued number from the list. And the decision
1002  // will
1003  // change from situation to situation, depending on the instrument.
1004  // Therefore I add it back here as well. We only fiddled with it in the
1005  // first place
1006  // in order to verify the balance statement. Done. So now let the other
1007  // pieces decide
1008  // their own logic from there.
1009  //
1010  switch (TARGET_TRANSACTION.GetType()) {
1017  // Should only actually iterate once, in this case.
1018  for (int32_t i = 0;
1019  i < theRemovedNym.GetIssuedNumCount(GetPurportedServerID()); i++) {
1020  int64_t lTemp =
1021  theRemovedNym.GetIssuedNum(GetPurportedServerID(), i);
1022 
1023  if (i > 0)
1024  otErr << "OTItem::" << __FUNCTION__
1025  << ": THIS SHOULD NOT HAPPEN.\n";
1026  else if (false ==
1027  THE_NYM.AddIssuedNum(SERVER_ID, lTemp)) // doesn't save.
1028  otErr << "OTItem::" << __FUNCTION__
1029  << ": Failed adding issued number back to THE_NYM.\n";
1030  }
1031  break;
1032 
1037  break;
1038  default:
1039  // Error
1040  otErr << "OTItem::" << __FUNCTION__
1041  << ": wrong target transaction type: "
1042  << TARGET_TRANSACTION.GetTypeString() << "\n";
1043  break;
1044  }
1045 
1046  return true;
1047 }
1048 
1049 // You have to allocate the item on the heap and then pass it in as a reference.
1050 // OTTransaction will take care of it from there and will delete it in
1051 // destructor.
1052 void OTItem::AddItem(OTItem& theItem)
1053 {
1054  m_listItems.push_back(&theItem);
1055 }
1056 
1057 // While processing a transaction, you may wish to query it for items of a
1058 // certain type.
1059 OTItem* OTItem::GetItem(int32_t nIndex)
1060 {
1061  int32_t nTempIndex = (-1);
1062 
1063  for (auto& it : m_listItems) {
1064  OTItem* pItem = it;
1065  OT_ASSERT(nullptr != pItem);
1066 
1067  nTempIndex++; // first iteration this becomes 0 here.
1068 
1069  if (nTempIndex == nIndex) return pItem;
1070  }
1071 
1072  return nullptr;
1073 }
1074 
1075 // While processing an item, you may wish to query it for sub-items
1076 OTItem* OTItem::GetItemByTransactionNum(int64_t lTransactionNumber)
1077 {
1078  for (auto& it : m_listItems) {
1079  OTItem* pItem = it;
1080  OT_ASSERT(nullptr != pItem);
1081 
1082  if (pItem->GetTransactionNum() == lTransactionNumber) return pItem;
1083  }
1084 
1085  return nullptr;
1086 }
1087 
1088 // Count the number of items that are IN REFERENCE TO some transaction#.
1089 //
1090 // Might want to change this so that it only counts ACCEPTED receipts.
1091 //
1092 int32_t OTItem::GetItemCountInRefTo(int64_t lReference)
1093 {
1094  int32_t nCount = 0;
1095 
1096  for (auto& it : m_listItems) {
1097  OTItem* pItem = it;
1098  OT_ASSERT(nullptr != pItem);
1099 
1100  if (pItem->GetReferenceToNum() == lReference) nCount++;
1101  }
1102 
1103  return nCount;
1104 }
1105 
1106 // The final receipt item MAY be present, and co-relates to others that share
1107 // its "in reference to" value. (Others such as marketReceipts and
1108 // paymentReceipts.)
1109 //
1111 {
1112  for (auto& it : m_listItems) {
1113  OTItem* pItem = it;
1114  OT_ASSERT(nullptr != pItem);
1115 
1116  if (OTItem::finalReceipt != pItem->GetType()) continue;
1117  if (pItem->GetReferenceToNum() == lReferenceNumber) return pItem;
1118  }
1119 
1120  return nullptr;
1121 }
1122 
1123 // For "OTItem::acceptTransaction"
1124 //
1126 {
1127  return m_Numlist.Add(theAddition);
1128 }
1129 
1130 // Need to know the transaction number of the ORIGINAL transaction? Call this.
1131 // virtual
1133 {
1134 
1135  if (0 == m_lNumberOfOrigin) {
1136  switch (GetType()) {
1137  case acceptPending: // this item is a client-side acceptance of a
1138  // pending transfer
1139  case rejectPending: // this item is a client-side rejection of a pending
1140  // transfer
1141  case acceptCronReceipt: // this item is a client-side acceptance of a
1142  // cron receipt in his inbox.
1143  case acceptItemReceipt: // this item is a client-side acceptance of an
1144  // item receipt in his inbox.
1145  case disputeCronReceipt: // this item is a client dispute of a cron
1146  // receipt in his inbox.
1147  case disputeItemReceipt: // this item is a client dispute of an item
1148  // receipt in his inbox.
1149 
1150  case acceptFinalReceipt: // this item is a client-side acceptance of a
1151  // final receipt in his inbox. (All related
1152  // receipts must also be closed!)
1153  case acceptBasketReceipt: // this item is a client-side acceptance of a
1154  // basket receipt in his inbox.
1155  case disputeFinalReceipt: // this item is a client-side rejection of a
1156  // final receipt in his inbox. (All related
1157  // receipts must also be closed!)
1158  case disputeBasketReceipt: // this item is a client-side rejection of a
1159  // basket receipt in his inbox.
1160 
1161  otErr << __FUNCTION__ << ": In this case, you can't calculate the "
1162  "origin number, you must set it "
1163  "explicitly.\n";
1164  // Comment this out later so people can't use it to crash the
1165  // server:
1166  OT_FAIL_MSG("In this case, you can't calculate the origin number, "
1167  "you must set it explicitly.");
1168  break;
1169  default:
1170  break;
1171  }
1172 
1174  }
1175 
1176  return m_lNumberOfOrigin;
1177 }
1178 
1179 // virtual
1181 {
1182  switch (GetType()) {
1183  case acceptTransaction: // this item is a client-side acceptance of a
1184  // transaction number (a blank) in my Nymbox
1185  case atAcceptTransaction: // server reply
1186  case acceptMessage: // this item is a client-side acceptance of a message in
1187  // my Nymbox
1188  case atAcceptMessage: // server reply
1189  case acceptNotice: // this item is a client-side acceptance of a server
1190  // notification in my Nymbox
1191  case atAcceptNotice: // server reply
1192  case replyNotice: // server notice of a reply that nym should have already
1193  // received as a response to a request. (Copy dropped in
1194  // nymbox.)
1195  case successNotice: // server notice dropped into nymbox as result of a
1196  // transaction# being successfully signed out.
1197  case notice: // server notice dropped into nymbox as result of a smart
1198  // contract processing.
1199  case transferReceipt: // Currently don't create an OTItem for transfer
1200  // receipt in inbox. Used only for inbox report.
1201  case chequeReceipt: // Currently don't create an OTItem for cheque receipt
1202  // in inbox. Used only for inbox report.
1203  case voucherReceipt: // Currently don't create an OTItem for voucher receipt
1204  // in inbox. Used only for inbox report.
1205 
1206  SetNumberOfOrigin(0); // Not applicable.
1207  break;
1208 
1209  case acceptPending: // this item is a client-side acceptance of a pending
1210  // transfer
1211  case rejectPending: // this item is a client-side rejection of a pending
1212  // transfer
1213  case acceptCronReceipt: // this item is a client-side acceptance of a cron
1214  // receipt in his inbox.
1215  case acceptItemReceipt: // this item is a client-side acceptance of an item
1216  // receipt in his inbox.
1217  case disputeCronReceipt: // this item is a client dispute of a cron receipt
1218  // in his inbox.
1219  case disputeItemReceipt: // this item is a client dispute of an item receipt
1220  // in his inbox.
1221 
1222  case acceptFinalReceipt: // this item is a client-side acceptance of a final
1223  // receipt in his inbox. (All related receipts must
1224  // also be closed!)
1225  case acceptBasketReceipt: // this item is a client-side acceptance of a
1226  // basket receipt in his inbox.
1227  case disputeFinalReceipt: // this item is a client-side rejection of a final
1228  // receipt in his inbox. (All related receipts
1229  // must also be closed!)
1230  case disputeBasketReceipt: // this item is a client-side rejection of a
1231  // basket receipt in his inbox.
1232 
1233  otErr << __FUNCTION__ << ": In this case, you can't calculate the "
1234  "origin number, you must set it explicitly.\n";
1235  SetNumberOfOrigin(0); // Not applicable.
1236  // Comment this out later so people can't use it to crash the server:
1237  OT_FAIL_MSG("In this case, you can't calculate the origin number, you "
1238  "must set it explicitly.");
1239  break;
1240 
1241  case marketReceipt: // server receipt dropped into inbox as result of market
1242  // trading. Also used in inbox report.
1243  case paymentReceipt: // server receipt dropped into an inbox as result of
1244  // payment occuring. Also used in inbox report.
1245  case finalReceipt: // server receipt dropped into inbox / nymbox as result
1246  // of cron item expiring or being canceled.
1247  case basketReceipt: // server receipt dropped into inbox as result of a
1248  // basket exchange.
1249 
1250  SetNumberOfOrigin(GetReferenceToNum()); // pending is in
1251  // reference to the
1252  // original
1253  // transfer.
1254  break;
1255 
1256  case depositCheque: // this item is a request to deposit a cheque.
1257  {
1258  OTCheque theCheque;
1259  OTString strAttachment;
1260  GetAttachment(strAttachment);
1261 
1262  if (!theCheque.LoadContractFromString(strAttachment))
1263  otErr << __FUNCTION__ << ": ERROR loading cheque from string:\n"
1264  << strAttachment << "\n";
1265  else
1266  SetNumberOfOrigin(theCheque.GetTransactionNum());
1267  } break;
1268 
1269  case atDepositCheque: // this item is a server response to that request.
1270  case atAcceptPending: // server reply to acceptPending.
1271  case atRejectPending: // server reply to rejectPending.
1272  case atAcceptCronReceipt: // this item is a server reply to that acceptance.
1273  case atAcceptItemReceipt: // this item is a server reply to that acceptance.
1274  case atDisputeCronReceipt: // Server reply to dispute message.
1275  case atDisputeItemReceipt: // Server reply to dispute message.
1276  case atAcceptFinalReceipt: // server reply
1277  case atAcceptBasketReceipt: // server reply
1278  case atDisputeFinalReceipt: // server reply
1279  case atDisputeBasketReceipt: // server reply
1280  {
1281  OTString strReference;
1282  GetReferenceString(strReference);
1283 
1284  // "In reference to" number is my original deposit trans#, which I use
1285  // here to load my
1286  // original depositCheque item, which I use to get the cheque, which
1287  // contains the number
1288  // of origin as its transaction number.
1289  //
1290  std::unique_ptr<OTItem> pOriginalItem(OTItem::CreateItemFromString(
1291  strReference, GetPurportedServerID(), GetReferenceToNum()));
1292  OT_ASSERT(nullptr != pOriginalItem);
1293 
1294  if (((m_Type == atDepositCheque) &&
1295  (OTItem::depositCheque != pOriginalItem->GetType())) ||
1296  ((m_Type == atAcceptPending) &&
1297  (OTItem::acceptPending != pOriginalItem->GetType())) ||
1298  ((m_Type == atRejectPending) &&
1299  (OTItem::rejectPending != pOriginalItem->GetType())) ||
1300  ((m_Type == atAcceptCronReceipt) &&
1301  (OTItem::acceptCronReceipt != pOriginalItem->GetType())) ||
1302  ((m_Type == atAcceptItemReceipt) &&
1303  (OTItem::acceptItemReceipt != pOriginalItem->GetType())) ||
1304  ((m_Type == atDisputeCronReceipt) &&
1305  (OTItem::disputeCronReceipt != pOriginalItem->GetType())) ||
1306  ((m_Type == atDisputeItemReceipt) &&
1307  (OTItem::disputeItemReceipt != pOriginalItem->GetType())) ||
1308  ((m_Type == atAcceptFinalReceipt) &&
1309  (OTItem::acceptFinalReceipt != pOriginalItem->GetType())) ||
1310  ((m_Type == atAcceptBasketReceipt) &&
1311  (OTItem::acceptBasketReceipt != pOriginalItem->GetType())) ||
1312  ((m_Type == atDisputeFinalReceipt) &&
1313  (OTItem::disputeFinalReceipt != pOriginalItem->GetType())) ||
1315  (OTItem::disputeBasketReceipt != pOriginalItem->GetType()))) {
1316  OTString strType;
1317  pOriginalItem->GetTypeString(strType);
1318  otErr << __FUNCTION__
1319  << ": ERROR: Wrong item type as 'in reference to' string on "
1320  << strType << " item.\n";
1321  SetNumberOfOrigin(0);
1322  return;
1323  }
1324 
1325  // Else:
1326  SetNumberOfOrigin(pOriginalItem->GetNumberOfOrigin());
1327  } break;
1328 
1329  // FEEs
1330  case serverfee: // this item is a fee from the transaction server (per
1331  // contract)
1332  case atServerfee:
1333  case issuerfee: // this item is a fee from the issuer (per contract)
1334  case atIssuerfee:
1335 
1336  // INFO (BALANCE, HASH, etc) these are still all messages with replies.
1337  case balanceStatement: // this item is a statement of balance. (For asset
1338  // account.)
1339  case atBalanceStatement:
1340  case transactionStatement: // this item is a transaction statement. (For Nym
1341  // -- which numbers are assigned to him.)
1343 
1344  // TRANSFER
1345  case transfer: // This item is an outgoing transfer, probably part of an
1346  // outoing transaction.
1347  case atTransfer: // Server reply.
1348 
1349  // CASH WITHDRAWAL / DEPOSIT
1350  case withdrawal: // this item is a cash withdrawal (of chaumian blinded
1351  // tokens)
1352  case atWithdrawal:
1353  case deposit: // this item is a cash deposit (of a purse containing blinded
1354  // tokens.)
1355  case atDeposit:
1356 
1357  // CHEQUES AND VOUCHERS
1358  case withdrawVoucher: // this item is a request to purchase a voucher (a
1359  // cashier's cheque)
1360  case atWithdrawVoucher:
1361 
1362  // PAYING DIVIDEND ON SHARES OF STOCK
1363  case payDividend: // this item is a request to pay a dividend.
1364  case atPayDividend: // the server reply to that request.
1365 
1366  // TRADING ON MARKETS
1367  case marketOffer: // this item is an offer to be put on a market.
1368  case atMarketOffer: // server reply or updated notification regarding a
1369  // market offer.
1370 
1371  // PAYMENT PLANS
1372  case paymentPlan: // this item is a new payment plan
1373  case atPaymentPlan: // server reply or updated notification regarding a
1374  // payment plan.
1375 
1376  // SMART CONTRACTS
1377  case smartContract: // this item is a new smart contract
1378  case atSmartContract: // server reply or updated notification regarding a
1379  // smart contract.
1380 
1381  // CANCELLING: Market Offers and Payment Plans.
1382  case cancelCronItem: // this item is intended to cancel a market offer or
1383  // payment plan.
1384  case atCancelCronItem: // reply from the server regarding said cancellation.
1385 
1386  // EXCHANGE IN/OUT OF A BASKET CURRENCY
1387  case exchangeBasket: // this item is an exchange in/out of a basket
1388  // currency.
1389  case atExchangeBasket: // reply from the server regarding said exchange.
1390 
1391  default:
1393  break;
1394  } // switch
1395 }
1396 
1397 void OTItem::GetAttachment(OTString& theStr) const
1398 {
1399  m_ascAttachment.GetString(theStr);
1400 }
1401 
1402 void OTItem::SetAttachment(const OTString& theStr)
1403 {
1404  m_ascAttachment.SetString(theStr);
1405 }
1406 
1407 #define MINIMUM_CLEARTEXT_SIZE_OTASCIIARMOR 100
1408 
1409 #define OTASSCIIARMOR_PADDING_TEXT \
1410  " IGNORE -- NOTE PADDING -- IGNORE -- NOTE PADDING \nIGNORE -- NOTE " \
1411  "PADDING -- IGNORE -- NOTE PADDING \n"
1412 
1413 void OTItem::SetNote(const OTString& theStr)
1414 {
1415  if (theStr.Exists() && theStr.GetLength() > 2) {
1416  OTString theString(theStr);
1419 
1420  theString.Concatenate(strPadding);
1421  }
1422 
1423  m_ascNote.SetString(theString);
1424  }
1425  else {
1426  m_ascNote.Release();
1427  }
1428 }
1429 
1430 void OTItem::GetNote(OTString& theStr) const
1431 {
1432  if (m_ascNote.GetLength() > 2) {
1433  m_ascNote.GetString(theStr);
1434 
1436  theStr.Truncate(theStr.GetLength() -
1438  }
1439  else {
1440  theStr.Release();
1441  }
1442 }
1443 
1444 // Let's say you have created a transaction, and you are creating an item to put
1445 // into it.
1446 // Well in that case, you don't care to verify that the real IDs match the
1447 // purported IDs, since
1448 // you are creating this item yourself, not verifying it from someone else.
1449 // Use this function to create the new Item before you add it to your new
1450 // Transaction.
1452  const OTTransaction& theOwner, OTItem::itemType theType,
1453  const OTIdentifier* pDestinationAcctID)
1454 {
1455  OTItem* pItem =
1456  new OTItem(theOwner.GetUserID(), theOwner, theType, pDestinationAcctID);
1457 
1458  if (pItem) {
1459  pItem->SetPurportedAccountID(theOwner.GetPurportedAccountID());
1460  pItem->SetPurportedServerID(theOwner.GetPurportedServerID());
1461  return pItem;
1462  }
1463  return nullptr;
1464 }
1465 
1466 // Sometimes I don't know user ID of the originator, or the account ID of the
1467 // originator,
1468 // until after I have loaded the item. It's simply impossible to set those
1469 // values ahead
1470 // of time, sometimes. In those cases, we set the values appropriately but then
1471 // we need
1472 // to verify that the user ID is actually the owner of the AccountID. TOdo that.
1474  const OTIdentifier& theServerID,
1475  int64_t lTransactionNumber)
1476 {
1477  if (!strItem.Exists()) {
1478  otErr << "OTItem::CreateItemFromString: strItem is empty. (Expected an "
1479  "item.)\n";
1480  return nullptr;
1481  }
1482 
1483  OTItem* pItem = new OTItem();
1484 
1485  // So when it loads its own server ID, we can compare to this one.
1486  pItem->SetRealServerID(theServerID);
1487 
1488  // This loads up the purported account ID and the user ID.
1489  if (pItem->LoadContractFromString(strItem)) {
1490  const OTIdentifier& ACCOUNT_ID = pItem->GetPurportedAccountID();
1491  pItem->SetRealAccountID(ACCOUNT_ID); // I do this because it's all we've
1492  // got in this case. It's what's in
1493  // the
1494  // xml, so it must be right. If it's a lie, the signature will fail or
1495  // the
1496  // user will not show as the owner of that account. But remember, the
1497  // server
1498  // sent the message in the first place.
1499 
1500  pItem->SetTransactionNum(lTransactionNumber);
1501 
1502  if (pItem->VerifyContractID()) // this compares purported and real
1503  // account IDs, as well as server IDs.
1504  {
1505  return pItem;
1506  }
1507  else {
1508  delete pItem;
1509  pItem = nullptr;
1510  }
1511  }
1512 
1513  return nullptr;
1514 }
1515 
1517 {
1518  m_lAmount = 0; // Accounts default to ZERO. They can only change that
1519  // amount by receiving from another account.
1521  m_Status =
1522  OTItem::request; // (Unless an issuer account, which can create currency
1523  m_lNewOutboxTransNum = 0; // When the user puts a "1" in his outbox for a
1524  // balance agreement (since he doesn't know what
1525  // trans# the actual outbox item
1526  // will have if the transaction is successful, since the server hasn't
1527  // issued it yet) then the balance receipt will have 1 in
1528  // the user's portion for that outbox transaction, and the balance receipt
1529  // will also have, say, #34 (the actual number) here
1530  // in this variable, in the server's reply portion of that same receipt.
1531 
1533 
1534  m_strContractType = "TRANSACTION ITEM"; // CONTRACT, MESSAGE, TRANSACTION,
1535  // LEDGER, TRANSACTION ITEM
1536 }
1537 
1538 // this one is private (I hope to keep it that way.)
1539 // probvably not actually. If I end up back here, it's because
1540 // sometimes I dont' WANT to assign the stuff, but leave it blank
1541 // because I'm about to load it.
1543  : OTTransactionType()
1544  , m_lAmount(0)
1545  , m_Type(OTItem::error_state)
1546  , m_Status(OTItem::request)
1547  , m_lNewOutboxTransNum(0)
1548  , m_lClosingTransactionNo(0)
1549 {
1550  InitItem();
1551 }
1552 
1553 // From owner we can get acct ID, server ID, and transaction Num
1554 OTItem::OTItem(const OTIdentifier& theUserID, const OTTransaction& theOwner)
1555  : OTTransactionType(theUserID, theOwner.GetRealAccountID(),
1556  theOwner.GetRealServerID(),
1557  theOwner.GetTransactionNum())
1558  , m_lAmount(0)
1559  , m_Type(OTItem::error_state)
1560  , m_Status(OTItem::request)
1561  , m_lNewOutboxTransNum(0)
1562  , m_lClosingTransactionNo(0)
1563 {
1564  InitItem();
1565 }
1566 
1567 // From owner we can get acct ID, server ID, and transaction Num
1568 OTItem::OTItem(const OTIdentifier& theUserID, const OTItem& theOwner)
1569  : OTTransactionType(theUserID, theOwner.GetRealAccountID(),
1570  theOwner.GetRealServerID(),
1571  theOwner.GetTransactionNum())
1572  , m_lAmount(0)
1573  , m_Type(OTItem::error_state)
1574  , m_Status(OTItem::request)
1575  , m_lNewOutboxTransNum(0)
1576  , m_lClosingTransactionNo(0)
1577 {
1578  InitItem();
1579 }
1580 
1581 OTItem::OTItem(const OTIdentifier& theUserID, const OTTransaction& theOwner,
1582  OTItem::itemType theType, const OTIdentifier* pDestinationAcctID)
1583  : OTTransactionType(theUserID, theOwner.GetRealAccountID(),
1584  theOwner.GetRealServerID(),
1585  theOwner.GetTransactionNum())
1586  , m_lAmount(0)
1587  , m_Type(OTItem::error_state)
1588  , m_Status(OTItem::request)
1589  , m_lNewOutboxTransNum(0)
1590  , m_lClosingTransactionNo(0)
1591 {
1592  InitItem();
1593 
1594  m_Type = theType; // This has to be below the InitItem() call that appears
1595  // just above
1596 
1597  // Most transactions items don't HAVE a "to" account, just a primary
1598  // account.
1599  // (If you deposit, or withdraw, you don't need a "to" account.)
1600  // But for the ones that do, you can pass the "to" account's ID in
1601  // as a pointer, and we'll set that too....
1602  if (nullptr != pDestinationAcctID) {
1603  m_AcctToID = *pDestinationAcctID;
1604  }
1605 }
1606 
1608 {
1609  Release_Item();
1610 }
1611 
1613 {
1614  Release_Item();
1615 
1617 }
1618 
1620 {
1621  ReleaseItems();
1622 
1623  m_AcctToID.Release();
1624  m_lAmount = 0;
1627 }
1628 
1630 {
1631 
1632  while (!m_listItems.empty()) {
1633  OTItem* pItem = m_listItems.front();
1634  m_listItems.pop_front();
1635  delete pItem;
1636  }
1637 }
1638 
1640 {
1642 
1643  if (strType.Compare("transfer"))
1644  theType = OTItem::transfer;
1645  else if (strType.Compare("atTransfer"))
1646  theType = OTItem::atTransfer;
1647 
1648  else if (strType.Compare("acceptTransaction"))
1649  theType = OTItem::acceptTransaction;
1650  else if (strType.Compare("atAcceptTransaction"))
1651  theType = OTItem::atAcceptTransaction;
1652 
1653  else if (strType.Compare("acceptMessage"))
1654  theType = OTItem::acceptMessage;
1655  else if (strType.Compare("atAcceptMessage"))
1656  theType = OTItem::atAcceptMessage;
1657 
1658  else if (strType.Compare("acceptNotice"))
1659  theType = OTItem::acceptNotice;
1660  else if (strType.Compare("atAcceptNotice"))
1661  theType = OTItem::atAcceptNotice;
1662 
1663  else if (strType.Compare("acceptPending"))
1664  theType = OTItem::acceptPending;
1665  else if (strType.Compare("atAcceptPending"))
1666  theType = OTItem::atAcceptPending;
1667  else if (strType.Compare("rejectPending"))
1668  theType = OTItem::rejectPending;
1669  else if (strType.Compare("atRejectPending"))
1670  theType = OTItem::atRejectPending;
1671 
1672  else if (strType.Compare("acceptCronReceipt"))
1673  theType = OTItem::acceptCronReceipt;
1674  else if (strType.Compare("atAcceptCronReceipt"))
1675  theType = OTItem::atAcceptCronReceipt;
1676  else if (strType.Compare("disputeCronReceipt"))
1677  theType = OTItem::disputeCronReceipt;
1678  else if (strType.Compare("atDisputeCronReceipt"))
1679  theType = OTItem::atDisputeCronReceipt;
1680  else if (strType.Compare("acceptItemReceipt"))
1681  theType = OTItem::acceptItemReceipt;
1682  else if (strType.Compare("atAcceptItemReceipt"))
1683  theType = OTItem::atAcceptItemReceipt;
1684  else if (strType.Compare("disputeItemReceipt"))
1685  theType = OTItem::disputeItemReceipt;
1686  else if (strType.Compare("atDisputeItemReceipt"))
1687  theType = OTItem::atDisputeItemReceipt;
1688 
1689  else if (strType.Compare("acceptFinalReceipt"))
1690  theType = OTItem::acceptFinalReceipt;
1691  else if (strType.Compare("atAcceptFinalReceipt"))
1692  theType = OTItem::atAcceptFinalReceipt;
1693  else if (strType.Compare("disputeFinalReceipt"))
1694  theType = OTItem::disputeFinalReceipt;
1695  else if (strType.Compare("atDisputeFinalReceipt"))
1697 
1698  else if (strType.Compare("acceptBasketReceipt"))
1699  theType = OTItem::acceptBasketReceipt;
1700  else if (strType.Compare("atAcceptBasketReceipt"))
1702  else if (strType.Compare("disputeBasketReceipt"))
1703  theType = OTItem::disputeBasketReceipt;
1704  else if (strType.Compare("atDisputeBasketReceipt"))
1706 
1707  else if (strType.Compare("serverfee"))
1708  theType = OTItem::serverfee;
1709  else if (strType.Compare("atServerfee"))
1710  theType = OTItem::atServerfee;
1711  else if (strType.Compare("issuerfee"))
1712  theType = OTItem::issuerfee;
1713  else if (strType.Compare("atIssuerfee"))
1714  theType = OTItem::atIssuerfee;
1715 
1716  else if (strType.Compare("balanceStatement"))
1717  theType = OTItem::balanceStatement;
1718  else if (strType.Compare("atBalanceStatement"))
1719  theType = OTItem::atBalanceStatement;
1720  else if (strType.Compare("transactionStatement"))
1721  theType = OTItem::transactionStatement;
1722  else if (strType.Compare("atTransactionStatement"))
1724 
1725  else if (strType.Compare("withdrawal"))
1726  theType = OTItem::withdrawal;
1727  else if (strType.Compare("atWithdrawal"))
1728  theType = OTItem::atWithdrawal;
1729  else if (strType.Compare("deposit"))
1730  theType = OTItem::deposit;
1731  else if (strType.Compare("atDeposit"))
1732  theType = OTItem::atDeposit;
1733 
1734  else if (strType.Compare("withdrawVoucher"))
1735  theType = OTItem::withdrawVoucher;
1736  else if (strType.Compare("atWithdrawVoucher"))
1737  theType = OTItem::atWithdrawVoucher;
1738  else if (strType.Compare("depositCheque"))
1739  theType = OTItem::depositCheque;
1740  else if (strType.Compare("atDepositCheque"))
1741  theType = OTItem::atDepositCheque;
1742 
1743  else if (strType.Compare("payDividend"))
1744  theType = OTItem::payDividend;
1745  else if (strType.Compare("atPayDividend"))
1746  theType = OTItem::atPayDividend;
1747 
1748  else if (strType.Compare("marketOffer"))
1749  theType = OTItem::marketOffer;
1750  else if (strType.Compare("atMarketOffer"))
1751  theType = OTItem::atMarketOffer;
1752 
1753  else if (strType.Compare("paymentPlan"))
1754  theType = OTItem::paymentPlan;
1755  else if (strType.Compare("atPaymentPlan"))
1756  theType = OTItem::atPaymentPlan;
1757 
1758  else if (strType.Compare("smartContract"))
1759  theType = OTItem::smartContract;
1760  else if (strType.Compare("atSmartContract"))
1761  theType = OTItem::atSmartContract;
1762 
1763  else if (strType.Compare("cancelCronItem"))
1764  theType = OTItem::cancelCronItem;
1765  else if (strType.Compare("atCancelCronItem"))
1766  theType = OTItem::atCancelCronItem;
1767 
1768  else if (strType.Compare("exchangeBasket"))
1769  theType = OTItem::exchangeBasket;
1770  else if (strType.Compare("atExchangeBasket"))
1771  theType = OTItem::atExchangeBasket;
1772 
1773  else if (strType.Compare("chequeReceipt"))
1774  theType = OTItem::chequeReceipt;
1775  else if (strType.Compare("voucherReceipt"))
1776  theType = OTItem::voucherReceipt;
1777  else if (strType.Compare("marketReceipt"))
1778  theType = OTItem::marketReceipt;
1779  else if (strType.Compare("paymentReceipt"))
1780  theType = OTItem::paymentReceipt;
1781  else if (strType.Compare("transferReceipt"))
1782  theType = OTItem::transferReceipt;
1783 
1784  else if (strType.Compare("finalReceipt"))
1785  theType = OTItem::finalReceipt;
1786  else if (strType.Compare("basketReceipt"))
1787  theType = OTItem::basketReceipt;
1788 
1789  else if (strType.Compare("replyNotice"))
1790  theType = OTItem::replyNotice;
1791  else if (strType.Compare("successNotice"))
1792  theType = OTItem::successNotice;
1793  else if (strType.Compare("notice"))
1794  theType = OTItem::notice;
1795 
1796  else
1797  theType = OTItem::error_state;
1798 
1799  return theType;
1800 }
1801 
1802 // return -1 if error, 0 if nothing, and 1 if the node was processed.
1804 {
1805  if (!strcmp("item", xml->getNodeName())) {
1806  OTString strType, strStatus;
1807 
1808  strType = xml->getAttributeValue("type");
1809  strStatus = xml->getAttributeValue("status");
1810 
1811  // Type
1812  m_Type = GetItemTypeFromString(strType); // just above.
1813 
1814  // Status
1815  if (strStatus.Compare("request"))
1817  else if (strStatus.Compare("acknowledgement"))
1819  else if (strStatus.Compare("rejection"))
1821  else
1823 
1824  OTString strAcctFromID, strAcctToID, strServerID, strUserID,
1825  strOutboxNewTransNum;
1826 
1827  strAcctFromID = xml->getAttributeValue("fromAccountID");
1828  strAcctToID = xml->getAttributeValue("toAccountID");
1829  strServerID = xml->getAttributeValue("serverID");
1830  strUserID = xml->getAttributeValue("userID");
1831 
1832  strOutboxNewTransNum = xml->getAttributeValue("outboxNewTransNum");
1833 
1834  if (strOutboxNewTransNum.Exists())
1835  m_lNewOutboxTransNum = atol(strOutboxNewTransNum.Get());
1836 
1837  // an OTTransaction::blank may now contain 20 or 100 new numbers.
1838  // Therefore, the OTItem::acceptTransaction must contain the same list,
1839  // otherwise you haven't actually SIGNED for the list, have you!
1840  //
1842  const OTString strTotalList =
1843  xml->getAttributeValue("totalListOfNumbers");
1844  m_Numlist.Release();
1845 
1846  if (strTotalList.Exists())
1847  m_Numlist.Add(strTotalList); // (Comma-separated list of numbers
1848  // now becomes std::set<int64_t>.)
1849  }
1850 
1851  OTIdentifier ACCOUNT_ID(strAcctFromID), SERVER_ID(strServerID),
1852  DESTINATION_ACCOUNT(strAcctToID), USER_ID(strUserID);
1853 
1854  SetPurportedAccountID(ACCOUNT_ID); // OTTransactionType::m_AcctID the
1855  // PURPORTED Account ID
1856  SetPurportedServerID(SERVER_ID); // OTTransactionType::m_AcctServerID
1857  // the PURPORTED Server ID
1858  SetDestinationAcctID(DESTINATION_ACCOUNT);
1859  SetUserID(USER_ID);
1860 
1861  if (!m_bLoadSecurely) {
1862  SetRealAccountID(ACCOUNT_ID);
1863  SetRealServerID(SERVER_ID);
1864  }
1865 
1866  OTString strTemp;
1867 
1868  strTemp = xml->getAttributeValue("numberOfOrigin");
1869  if (strTemp.Exists()) SetNumberOfOrigin(atol(strTemp.Get()));
1870 
1871  strTemp = xml->getAttributeValue("transactionNum");
1872  if (strTemp.Exists()) SetTransactionNum(atol(strTemp.Get()));
1873 
1874  strTemp = xml->getAttributeValue("inReferenceTo");
1875  if (strTemp.Exists()) SetReferenceToNum(atol(strTemp.Get()));
1876 
1877  m_lAmount = atol(xml->getAttributeValue("amount"));
1878 
1879  otLog3 << "Loaded transaction Item, transaction num "
1880  << GetTransactionNum()
1881  << ", In Reference To: " << GetReferenceToNum()
1882  << ", type: " << strType << ", status: " << strStatus << "\n";
1883  // "fromAccountID:\n%s\n UserID:\n%s\n toAccountID:\n%s\n
1884  // serverID:\n%s\n----------\n",
1885  // strAcctFromID.Get(), strUserID.Get(),
1886  // strAcctToID.Get(), strServerID.Get()
1887 
1888  return 1;
1889  }
1890  else if (!strcmp("note", xml->getNodeName())) {
1892  otErr << "Error in OTItem::ProcessXMLNode: note field without "
1893  "value.\n";
1894  return (-1); // error condition
1895  }
1896 
1897  return 1;
1898  }
1899  else if (!strcmp("inReferenceTo", xml->getNodeName())) {
1900  if (false ==
1902  otErr << "Error in OTItem::ProcessXMLNode: inReferenceTo field "
1903  "without value.\n";
1904  return (-1); // error condition
1905  }
1906 
1907  return 1;
1908  }
1909  else if (!strcmp("attachment", xml->getNodeName())) {
1911  otErr << "Error in OTItem::ProcessXMLNode: attachment field "
1912  "without value.\n";
1913  return (-1); // error condition
1914  }
1915 
1916  return 1;
1917  }
1918  else if (!strcmp("transactionReport", xml->getNodeName())) {
1919  if ((OTItem::balanceStatement == m_Type) ||
1921  // Notice it initializes with the wrong transaction number, in this
1922  // case.
1923  // That's okay, because I'm setting it below with
1924  // pItem->SetTransactionNum...
1925  OTItem* pItem = new OTItem(GetUserID(), *this); // But I've also got
1926  // ITEM types with
1927  // the same names...
1928  // That way, it will translate the string and set the type
1929  // correctly.
1930  OT_ASSERT(nullptr != pItem); // That way I can use each item to
1931  // REPRESENT an inbox transaction
1932 
1933  // Type
1934  OTString strType;
1935  strType = xml->getAttributeValue(
1936  "type"); // it's reading a TRANSACTION type: chequeReceipt,
1937  // voucherReceipt, marketReceipt, or paymentReceipt.
1938  // But I also have the same names for item types.
1939 
1941  strType)); // It's actually translating a transaction type to an
1942  // item type. (Same names in the case of the 3
1943  // receipts that matter for inbox reports for balance
1944  // agreements.)
1945 
1946  pItem->SetAmount(atol(xml->getAttributeValue("adjustment")));
1947 
1948  // Status
1949  pItem->SetStatus(OTItem::acknowledgement); // I don't need this, but
1950  // I'd rather it not say
1951  // error state. This way
1952  // if it changes to
1953  // error_state later, I
1954  // know I had a problem.
1955 
1956  OTString strAccountID, strServerID, strUserID;
1957 
1958  strAccountID = xml->getAttributeValue("accountID");
1959  strServerID = xml->getAttributeValue("serverID");
1960  strUserID = xml->getAttributeValue("userID");
1961 
1962  OTIdentifier ACCOUNT_ID(strAccountID), SERVER_ID(strServerID),
1963  USER_ID(strUserID);
1964 
1965  pItem->SetPurportedAccountID(
1966  ACCOUNT_ID); // OTTransactionType::m_AcctID the PURPORTED
1967  // Account ID
1968  pItem->SetPurportedServerID(
1969  SERVER_ID); // OTTransactionType::m_AcctServerID the PURPORTED
1970  // Server ID
1971  pItem->SetUserID(USER_ID);
1972 
1973  OTString strTemp;
1974 
1975  strTemp = xml->getAttributeValue("numberOfOrigin");
1976  if (strTemp.Exists()) pItem->SetNumberOfOrigin(atol(strTemp.Get()));
1977 
1978  strTemp = xml->getAttributeValue("transactionNum");
1979  if (strTemp.Exists()) pItem->SetTransactionNum(atol(strTemp.Get()));
1980 
1981  strTemp = xml->getAttributeValue("inReferenceTo");
1982  if (strTemp.Exists()) pItem->SetReferenceToNum(atol(strTemp.Get()));
1983 
1984  strTemp = xml->getAttributeValue(
1985  "closingTransactionNum"); // only used in the inbox report for
1986  // balance agreement.
1987  if (strTemp.Exists()) pItem->SetClosingNum(atol(strTemp.Get()));
1988 
1989  AddItem(*pItem); // <======= adding to list.
1990 
1991  otLog3 << "Loaded transactionReport Item, transaction num "
1992  << pItem->GetTransactionNum()
1993  << ", In Reference To: " << pItem->GetReferenceToNum()
1994  << ", type: " << strType << "\n";
1995  // "fromAccountID:\n%s\n UserID:\n%s\n
1996  // toAccountID:\n%s\n serverID:\n%s\n----------\n",
1997  // strAcctFromID.Get(), strUserID.Get(),
1998  // strAcctToID.Get(), strServerID.Get()
1999  }
2000  else {
2001  otErr << "Outbox hash in item wrong type (expected "
2002  "balanceStatement or atBalanceStatement.\n";
2003  }
2004 
2005  return 1;
2006  }
2007 
2008  return 0;
2009 }
2010 
2011 // Used in balance agreement, part of the inbox report.
2012 int64_t OTItem::GetClosingNum() const
2013 {
2014  return m_lClosingTransactionNo;
2015 }
2016 
2017 void OTItem::SetClosingNum(int64_t lClosingNum)
2018 {
2019  m_lClosingTransactionNo = lClosingNum;
2020 }
2021 
2023 {
2024  switch (theType) {
2025  case OTItem::transfer:
2026  strType.Set("transfer");
2027  break;
2029  strType.Set("acceptTransaction");
2030  break;
2031  case OTItem::acceptMessage:
2032  strType.Set("acceptMessage");
2033  break;
2034  case OTItem::acceptNotice:
2035  strType.Set("acceptNotice");
2036  break;
2037  case OTItem::acceptPending:
2038  strType.Set("acceptPending");
2039  break;
2040  case OTItem::rejectPending:
2041  strType.Set("rejectPending");
2042  break;
2044  strType.Set("acceptCronReceipt");
2045  break;
2047  strType.Set("disputeCronReceipt");
2048  break;
2050  strType.Set("acceptItemReceipt");
2051  break;
2053  strType.Set("disputeItemReceipt");
2054  break;
2056  strType.Set("acceptFinalReceipt");
2057  break;
2059  strType.Set("acceptBasketReceipt");
2060  break;
2062  strType.Set("disputeFinalReceipt");
2063  break;
2065  strType.Set("disputeBasketReceipt");
2066  break;
2067  case OTItem::serverfee:
2068  strType.Set("serverfee");
2069  break;
2070  case OTItem::issuerfee:
2071  strType.Set("issuerfee");
2072  break;
2073  case OTItem::withdrawal:
2074  strType.Set("withdrawal");
2075  break;
2076  case OTItem::deposit:
2077  strType.Set("deposit");
2078  break;
2080  strType.Set("withdrawVoucher");
2081  break;
2082  case OTItem::depositCheque:
2083  strType.Set("depositCheque");
2084  break;
2085  case OTItem::payDividend:
2086  strType.Set("payDividend");
2087  break;
2088  case OTItem::marketOffer:
2089  strType.Set("marketOffer");
2090  break;
2091  case OTItem::paymentPlan:
2092  strType.Set("paymentPlan");
2093  break;
2094  case OTItem::smartContract:
2095  strType.Set("smartContract");
2096  break;
2098  strType.Set("balanceStatement");
2099  break;
2101  strType.Set("transactionStatement");
2102  break;
2103 
2105  strType.Set("cancelCronItem");
2106  break;
2108  strType.Set("exchangeBasket");
2109  break;
2110 
2112  strType.Set("atCancelCronItem");
2113  break;
2115  strType.Set("atExchangeBasket");
2116  break;
2117 
2118  case OTItem::chequeReceipt: // used for inbox statements in balance
2119  // agreement.
2120  strType.Set("chequeReceipt");
2121  break;
2122  case OTItem::voucherReceipt: // used for inbox statements in balance
2123  // agreement.
2124  strType.Set("voucherReceipt");
2125  break;
2126  case OTItem::marketReceipt: // used as market receipt, and also for inbox
2127  // statement containing market receipt will use
2128  // this as well.
2129  strType.Set("marketReceipt");
2130  break;
2131  case OTItem::paymentReceipt: // used as payment receipt, also used in inbox
2132  // statement as payment receipt.
2133  strType.Set("paymentReceipt");
2134  break;
2135  case OTItem::transferReceipt: // used in inbox statement as transfer
2136  // receipt.
2137  strType.Set("transferReceipt");
2138  break;
2139 
2140  case OTItem::finalReceipt: // used for final receipt. Also used in inbox
2141  // statement as final receipt. (For expiring or
2142  // cancelled Cron Item.)
2143  strType.Set("finalReceipt");
2144  break;
2145  case OTItem::basketReceipt: // used in inbox statement as basket receipt.
2146  // (For exchange.)
2147  strType.Set("basketReceipt");
2148  break;
2149 
2150  case OTItem::notice: // used in Nymbox statement as notification from
2151  // server.
2152  strType.Set("notice");
2153  break;
2154  case OTItem::replyNotice: // some server replies (to your request) have a
2155  // copy dropped into your nymbox, to make sure you
2156  // received it.
2157  strType.Set("replyNotice");
2158  break;
2159  case OTItem::successNotice: // used in Nymbox statement as notification from
2160  // server of successful sign-out of a trans#.
2161  strType.Set("successNotice");
2162  break;
2163 
2164  case OTItem::atTransfer:
2165  strType.Set("atTransfer");
2166  break;
2168  strType.Set("atAcceptTransaction");
2169  break;
2171  strType.Set("atAcceptMessage");
2172  break;
2174  strType.Set("atAcceptNotice");
2175  break;
2177  strType.Set("atAcceptPending");
2178  break;
2180  strType.Set("atRejectPending");
2181  break;
2183  strType.Set("atAcceptCronReceipt");
2184  break;
2186  strType.Set("atDisputeCronReceipt");
2187  break;
2189  strType.Set("atAcceptItemReceipt");
2190  break;
2192  strType.Set("atDisputeItemReceipt");
2193  break;
2194 
2196  strType.Set("atAcceptFinalReceipt");
2197  break;
2199  strType.Set("atAcceptBasketReceipt");
2200  break;
2202  strType.Set("atDisputeFinalReceipt");
2203  break;
2205  strType.Set("atDisputeBasketReceipt");
2206  break;
2207 
2208  case OTItem::atServerfee:
2209  strType.Set("atServerfee");
2210  break;
2211  case OTItem::atIssuerfee:
2212  strType.Set("atIssuerfee");
2213  break;
2214  case OTItem::atWithdrawal:
2215  strType.Set("atWithdrawal");
2216  break;
2217  case OTItem::atDeposit:
2218  strType.Set("atDeposit");
2219  break;
2221  strType.Set("atWithdrawVoucher");
2222  break;
2224  strType.Set("atDepositCheque");
2225  break;
2226  case OTItem::atPayDividend:
2227  strType.Set("atPayDividend");
2228  break;
2229  case OTItem::atMarketOffer:
2230  strType.Set("atMarketOffer");
2231  break;
2232  case OTItem::atPaymentPlan:
2233  strType.Set("atPaymentPlan");
2234  break;
2236  strType.Set("atSmartContract");
2237  break;
2239  strType.Set("atBalanceStatement");
2240  break;
2242  strType.Set("atTransactionStatement");
2243  break;
2244 
2245  default:
2246  strType.Set("error-unknown");
2247  break;
2248  }
2249 }
2250 
2251 void OTItem::UpdateContents() // Before transmission or serialization, this is
2252  // where the ledger saves its contents
2253 {
2254  OTString strListOfBlanks; // IF this item is "acceptTransaction" then this
2255  // will serialize the list of transaction numbers
2256  // being accepted. (They now support multiple
2257  // numbers.)
2258 
2259  switch (m_Type) {
2261  if (m_Numlist.Count() >
2262  0) // This is always 0, except for OTItem::acceptTransaction.
2263  {
2264  OTString strNumbers;
2265  if (true == m_Numlist.Output(strNumbers))
2266  strListOfBlanks.Format(" totalListOfNumbers=\"%s\"\n",
2267  strNumbers.Get());
2268  else // (False just means m_Numlist was empty.)
2269  strListOfBlanks.Set("");
2270  }
2271  }
2272  default:
2273  break;
2274  }
2275 
2276  OTString strFromAcctID(GetPurportedAccountID()),
2277  strToAcctID(GetDestinationAcctID()),
2278  strServerID(GetPurportedServerID()), strType, strStatus,
2279  strUserID(GetUserID());
2280 
2281  GetStringFromType(m_Type, strType);
2282 
2283  switch (m_Status) {
2284  case OTItem::request:
2285  strStatus.Set("request");
2286  break;
2288  strStatus.Set("acknowledgement");
2289  break;
2290  case OTItem::rejection:
2291  strStatus.Set("rejection");
2292  break;
2293  default:
2294  strStatus.Set("error-unknown");
2295  break;
2296  }
2297 
2298  // I release this because I'm about to repopulate it.
2300 
2301  if (m_lNewOutboxTransNum > 0)
2303  "<item type=\"%s\"\n status=\"%s\"\n"
2304  " outboxNewTransNum=\"%lld\"\n" // only used in server reply item:
2305  // atBalanceStatement. In cases
2306  // where the statement includes a
2307  // new outbox item, this variable is
2308  // used to transport the new
2309  // transaction number (generated on
2310  // server side for that new outbox
2311  // item) back to the client, so the
2312  // client knows the transaction
2313  // number to verify when he is
2314  // verifying the outbox against the
2315  // last signed receipt.
2316  " numberOfOrigin=\"%lld\"\n"
2317  " transactionNum=\"%lld\"\n"
2318  " serverID=\"%s\"\n"
2319  " userID=\"%s\"\n"
2320  " fromAccountID=\"%s\"\n"
2321  " toAccountID=\"%s\"\n"
2322  " inReferenceTo=\"%lld\"\n"
2323  " amount=\"%lld\" >\n\n",
2324  strType.Get(), strStatus.Get(), m_lNewOutboxTransNum,
2325  GetRawNumberOfOrigin(), // GetRaw so it doesn't calculate.
2326  GetTransactionNum(), strServerID.Get(), strUserID.Get(),
2327  strFromAcctID.Get(), strToAcctID.Get(), GetReferenceToNum(),
2328  m_lAmount);
2329  else
2331  "<item type=\"%s\"\n status=\"%s\"\n"
2332  " numberOfOrigin=\"%lld\"\n"
2333  " transactionNum=\"%lld\"\n%s"
2334  " serverID=\"%s\"\n"
2335  " userID=\"%s\"\n"
2336  " fromAccountID=\"%s\"\n"
2337  " toAccountID=\"%s\"\n"
2338  " inReferenceTo=\"%lld\"\n"
2339  " amount=\"%lld\" >\n\n",
2340  strType.Get(), strStatus.Get(),
2341  GetRawNumberOfOrigin(), // GetRaw so it doesn't calculate.
2342  GetTransactionNum(), strListOfBlanks.Get(), strServerID.Get(),
2343  strUserID.Get(), strFromAcctID.Get(), strToAcctID.Get(),
2345 
2346  if (m_ascNote.GetLength() > 2) {
2347  m_xmlUnsigned.Concatenate("<note>\n%s</note>\n\n", m_ascNote.Get());
2348  }
2349 
2350  if (m_ascInReferenceTo.GetLength() > 2) {
2351  m_xmlUnsigned.Concatenate("<inReferenceTo>\n%s</inReferenceTo>\n\n",
2353  }
2354 
2355  if (m_ascAttachment.GetLength() > 2) {
2356  m_xmlUnsigned.Concatenate("<attachment>\n%s</attachment>\n\n",
2357  m_ascAttachment.Get());
2358  }
2359 
2360  if ((OTItem::balanceStatement == m_Type) ||
2362 
2363  // loop through the sub-items (only used for balance agreement.)
2364  //
2365  for (auto& it : m_listItems) {
2366  OTItem* pItem = it;
2367  OT_ASSERT(nullptr != pItem);
2368 
2369  OTString strAcctID(pItem->GetPurportedAccountID()),
2370  strServerID(pItem->GetPurportedServerID()),
2371  strUserID(pItem->GetUserID());
2372 
2373  OTString strReceiptType;
2374  GetStringFromType(pItem->GetType(), strReceiptType);
2375 
2377  "<transactionReport type=\"%s\"\n"
2378  " adjustment=\"%lld\"\n"
2379  " accountID=\"%s\"\n"
2380  " userID=\"%s\"\n"
2381  " serverID=\"%s\"\n"
2382  " numberOfOrigin=\"%lld\"\n"
2383  " transactionNum=\"%lld\"\n"
2384  " closingTransactionNum=\"%lld\"\n"
2385  " inReferenceTo=\"%lld\" />\n\n",
2386  strReceiptType.Exists() ? strReceiptType.Get() : "error_state",
2387  pItem->GetAmount(), strAcctID.Get(), strUserID.Get(),
2388  strServerID.Get(), pItem->GetRawNumberOfOrigin(),
2389  pItem->GetTransactionNum(), pItem->GetClosingNum(),
2390  pItem->GetReferenceToNum());
2391  }
2392  }
2393 
2394  m_xmlUnsigned.Concatenate("</item>\n");
2395 }
2396 
2397 bool OTItem::SaveContractWallet(std::ofstream&) const
2398 {
2399  return true;
2400 }
2401 
2402 } // namespace opentxs
void AddItem(OTItem &theItem)
Definition: OTItem.cpp:1052
void Truncate(uint32_t index)
Definition: OTString.cpp:1193
EXPORT int32_t GetIssuedNumCount(const OTIdentifier &theServerID) const
EXPORT void GetReferenceString(OTString &theStr) const
OTLOG_IMPORT OTLogStream otLog4
void SetAmount(int64_t lAmount)
Definition: OTItem.hpp:479
OTIdentifier m_AcctToID
Definition: OTItem.hpp:352
EXPORT bool VerifyIssuedNumbersOnNym(OTPseudonym &THE_NYM)
virtual void Release()
Definition: OTItem.cpp:1612
int32_t GetTransactionCount() const
Definition: OTLedger.hpp:332
int64_t m_lAmount
Definition: OTItem.hpp:354
virtual bool SaveContractWallet(std::ofstream &ofs) const
Definition: OTItem.cpp:2397
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
Definition: OTItem.cpp:1473
EXPORT void SetNumberOfOrigin(int64_t lTransactionNum)
OTItem * GetItem(int32_t nIndex)
Definition: OTItem.cpp:1059
void ReleaseItems()
Definition: OTItem.cpp:1629
EXPORT bool LoadFromString(const OTString &strNym, OTString::Map *pMapCredentials=nullptr, OTString *pstrReason=nullptr, const OTPassword *pImportPassword=nullptr)
EXPORT void GetAttachment(OTString &theStr) const
Definition: OTItem.cpp:1397
EXPORT bool VerifyTransactionStatement(OTPseudonym &THE_NYM, OTTransaction &TARGET_TRANSACTION, bool bIsRealTransaction=true)
Definition: OTItem.cpp:181
void SetTransactionNum(int64_t lTransactionNum)
int64_t GetTransactionNum() const
void InitItem()
Definition: OTItem.cpp:1516
EXPORT void Release()
Definition: OTNumList.cpp:465
EXPORT int64_t GetBalance() const
Definition: OTAccount.cpp:664
EXPORT bool VerifyIssuedNum(const OTString &strServerID, const int64_t &lTransNum) const
EXPORT bool AddBlankNumbersToItem(const OTNumList &theAddition)
Definition: OTItem.cpp:1125
EXPORT bool VerifyBalanceStatement(int64_t lActualAdjustment, OTPseudonym &THE_NYM, OTLedger &THE_INBOX, OTLedger &THE_OUTBOX, const OTAccount &THE_ACCOUNT, OTTransaction &TARGET_TRANSACTION, int64_t lOutboxTrnsNum=0)
Definition: OTItem.cpp:358
OTLOG_IMPORT OTLogStream otOut
void SetRealAccountID(const OTIdentifier &theID)
EXPORT void GetNote(OTString &theStr) const
Definition: OTItem.cpp:1430
OTLOG_IMPORT OTLogStream otLog3
EXPORT void SetAttachment(const OTString &theStr)
Definition: OTItem.cpp:1402
EXPORT uint32_t GetLength() const
Definition: OTString.cpp:1040
virtual ~OTItem()
Definition: OTItem.cpp:1607
OTItem::itemType GetItemTypeFromString(const OTString &strType)
Definition: OTItem.cpp:1639
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
void SetRealServerID(const OTIdentifier &theID)
OTItem * GetFinalReceiptItemByReferenceNum(int64_t lReferenceNumber)
Definition: OTItem.cpp:1110
static EXPORT OTItem * CreateItemFromTransaction(const OTTransaction &theOwner, OTItem::itemType theType, const OTIdentifier *pDestinationAcctID=nullptr)
Definition: OTItem.cpp:1451
OTItem * GetItemByTransactionNum(int64_t lTransactionNumber)
Definition: OTItem.cpp:1076
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT bool SetString(const OTString &theData, bool bLineBreaks=true)
listOfItems m_listItems
Definition: OTItem.hpp:356
const char * GetTypeString() const
int64_t GetClosingNum() const
Definition: OTItem.cpp:2012
EXPORT void Format(const char *fmt,...)
Definition: OTString.cpp:1319
void SetStatus(const OTItem::itemStatus &theVal)
Definition: OTItem.hpp:463
void SetDestinationAcctID(const OTIdentifier &theID)
Definition: OTItem.hpp:491
#define MINIMUM_CLEARTEXT_SIZE_OTASCIIARMOR
Definition: OTItem.cpp:1407
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
virtual EXPORT void CalculateNumberOfOrigin()
Definition: OTItem.cpp:1180
const OTIdentifier & GetPurportedServerID() const
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
Definition: OTString.cpp:1055
int64_t m_lNewOutboxTransNum
Definition: OTItem.hpp:363
void SetClosingNum(int64_t lClosingNum)
Definition: OTItem.cpp:2017
static EXPORT bool LoadEncodedTextField(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
int64_t GetAmount() const
Definition: OTItem.hpp:475
EXPORT bool Output(std::set< int64_t > &theOutput) const
Definition: OTNumList.cpp:430
EXPORT int64_t GetClosingNum() const
EXPORT bool RemoveIssuedNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, const int64_t &lTransNum, bool bSave)
std::deque< int64_t > dequeOfTransNums
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTString m_strContractType
Definition: OTContract.hpp:178
const OTIdentifier & GetDestinationAcctID() const
Definition: OTItem.hpp:487
mapOfTransNums & GetMapIssuedNum()
void Release_Item()
Definition: OTItem.cpp:1619
EXPORT int32_t Count() const
Definition: OTNumList.cpp:460
#define OTASSCIIARMOR_PADDING_TEXT
Definition: OTItem.cpp:1409
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
itemStatus m_Status
Definition: OTItem.hpp:362
EXPORT void SetNote(const OTString &theStr)
Definition: OTItem.cpp:1413
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
EXPORT int64_t GetReferenceToNum() const
OTLOG_IMPORT OTLogStream otWarn
EXPORT const char * Get() const
Definition: OTString.cpp:1045
void SetUserID(const OTIdentifier &theID)
transactionType GetType() const
OTLOG_IMPORT OTLogStream otErr
const OTIdentifier & GetPurportedAccountID() const
EXPORT int64_t GetReceiptAmount()
EXPORT int64_t GetTransactionNum() const
EXPORT void SetReferenceToNum(int64_t lTransactionNum)
int32_t GetItemCountInRefTo(int64_t lReference)
Definition: OTItem.cpp:1092
void SetPurportedServerID(const OTIdentifier &theID)
virtual void UpdateContents()
Definition: OTItem.cpp:2251
virtual EXPORT bool VerifyContractID() const
int32_t GetItemCount() const
Definition: OTItem.hpp:413
EXPORT bool Contains(const char *compare) const
Definition: OTString.cpp:1137
OTASCIIArmor m_ascAttachment
Definition: OTItem.hpp:437
static EXPORT void GetStringFromType(OTItem::itemType theType, OTString &strType)
Definition: OTItem.cpp:2022
OTItem::itemType GetType() const
Definition: OTItem.hpp:467
int64_t m_lClosingTransactionNo
Definition: OTItem.hpp:376
const OTIdentifier & GetUserID() const
EXPORT bool GetString(OTString &theData, bool bLineBreaks=true) const
EXPORT bool LoadContractFromString(const OTString &theStr)
EXPORT int64_t GetIssuedNum(const OTIdentifier &theServerID, int32_t nIndex) const
virtual EXPORT void Release()
Definition: OTData.cpp:257
void GetTypeString(OTString &strType) const
Definition: OTItem.hpp:504
void SetType(OTItem::itemType theType)
Definition: OTItem.hpp:471
EXPORT bool AddIssuedNum(const OTString &strServerID, const int64_t &lTransNum)
virtual EXPORT int64_t GetNumberOfOrigin()
Definition: OTItem.cpp:1132
itemType m_Type
Definition: OTItem.hpp:360
void SetPurportedAccountID(const OTIdentifier &theID)
virtual EXPORT void Release()
Definition: OTString.cpp:765
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
Definition: OTItem.cpp:1803
EXPORT OTTransaction * GetTransaction(OTTransaction::transactionType theType)
Definition: OTLedger.cpp:1215
EXPORT int64_t GetRawNumberOfOrigin() const
OTASCIIArmor m_ascNote
Definition: OTItem.hpp:434