Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTCronItem.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTCronItem.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 
137 #include "trade/OTTrade.hpp"
138 #include "cron/OTCronItem.hpp"
139 #include "cron/OTCron.hpp"
140 #include "util/OTFolders.hpp"
141 #include "OTLedger.hpp"
142 #include "OTLog.hpp"
143 #include "OTPseudonym.hpp"
144 #include "OTStorage.hpp"
145 
146 #include <irrxml/irrXML.hpp>
147 
148 #include <memory>
149 
150 // Base class for OTTrade and OTAgreement and OTPaymentPlan.
151 // OTCron contains lists of these for regular processing.
152 
153 // static -- class factory.
154 //
155 // I just realized, I don't have to use this only for CronItems.
156 // If I wanted to, I could put ANY Open-Transactions class in here,
157 // if there was some need for it, and it would work just fine right here.
158 // Like if I wanted to have different Token types for different cash
159 // algorithms. All I have to do is change the return type.
160 //
161 
162 namespace opentxs
163 {
164 
166 {
167  static char buf[45] = "";
168 
169  if (!strCronItem.Exists()) {
170  otErr << __FUNCTION__
171  << ": Empty string was passed in (returning nullptr.)\n";
172  return nullptr;
173  }
174 
175  OTString strContract(strCronItem);
176 
177  if (!strContract.DecodeIfArmored(false)) {
178  otErr << __FUNCTION__ << ": Input string apparently was encoded and "
179  "then failed decoding. Contents: \n"
180  << strCronItem << "\n";
181  return nullptr;
182  }
183 
184  strContract.reset(); // for sgets
185  buf[0] = 0; // probably unnecessary.
186  bool bGotLine = strContract.sgets(buf, 40);
187 
188  if (!bGotLine) return nullptr;
189 
190  OTString strFirstLine(buf);
191  // set the "file" pointer within this string back to index 0.
192  strContract.reset();
193 
194  // Now I feel pretty safe -- the string I'm examining is within
195  // the first 45 characters of the beginning of the contract, and
196  // it will NOT contain the escape "- " sequence. From there, if
197  // it contains the proper sequence, I will instantiate that type.
198  if (!strFirstLine.Exists() || strFirstLine.Contains("- -")) return nullptr;
199 
200  // By this point we know already that it's not escaped.
201  // BUT it might still be ARMORED!
202 
203  std::unique_ptr<OTCronItem> pItem;
204  // this string is 35 chars long.
205  if (strFirstLine.Contains("-----BEGIN SIGNED PAYMENT PLAN-----")) {
206  pItem.reset(new OTPaymentPlan());
207  }
208  // this string is 28 chars long.
209  else if (strFirstLine.Contains("-----BEGIN SIGNED TRADE-----")) {
210  pItem.reset(new OTTrade());
211  }
212  // this string is 36 chars long.
213  else if (strFirstLine.Contains("-----BEGIN SIGNED SMARTCONTRACT-----")) {
214  pItem.reset(new OTSmartContract());
215  }
216  else {
217  return nullptr;
218  }
219 
220  // Does the contract successfully load from the string passed in?
221  if (pItem->LoadContractFromString(strContract)) {
222  return pItem.release();
223  }
224  return nullptr;
225 }
226 
227 OTCronItem* OTCronItem::LoadCronReceipt(const int64_t& lTransactionNum)
228 {
229  OTString strFilename;
230  strFilename.Format("%lld.crn", lTransactionNum);
231 
232  const char* szFoldername = OTFolders::Cron().Get();
233  const char* szFilename = strFilename.Get();
234 
235  if (!OTDB::Exists(szFoldername, szFilename)) {
236  otErr << "OTCronItem::" << __FUNCTION__
237  << ": File does not exist: " << szFoldername
238  << OTLog::PathSeparator() << szFilename << "\n";
239  return nullptr;
240  }
241 
242  OTString strFileContents(OTDB::QueryPlainString(
243  szFoldername, szFilename)); // <=== LOADING FROM DATA STORE.
244 
245  if (strFileContents.GetLength() < 2) {
246  otErr << "OTCronItem::" << __FUNCTION__
247  << ": Error reading file: " << szFoldername
248  << OTLog::PathSeparator() << szFilename << "\n";
249  return nullptr;
250  }
251  else
252  // NOTE: NewCronItem can handle the normal cron item contracts, as well
253  // as the OT ARMORED version
254  // (It will decode the armor before instantiating the contract.)
255  // Therefore there's no need HERE in
256  // THIS function to do any decoding...
257  //
258  return OTCronItem::NewCronItem(strFileContents);
259 }
260 
261 // static
263  const int64_t& lTransactionNum,
264  const OTIdentifier& serverID) // Client-side only.
265 {
266  OTString strFilename, strServerID(serverID);
267  strFilename.Format("%lld.crn", lTransactionNum);
268 
269  const char* szFoldername = OTFolders::Cron().Get();
270  const char* szFilename = strFilename.Get();
271 
272  if (!OTDB::Exists(szFoldername, strServerID.Get(), szFilename)) {
273  otErr << "OTCronItem::" << __FUNCTION__
274  << ": File does not exist: " << szFoldername
275  << OTLog::PathSeparator() << strServerID << OTLog::PathSeparator()
276  << szFilename << "\n";
277  return nullptr;
278  }
279 
280  OTString strFileContents(
281  OTDB::QueryPlainString(szFoldername, strServerID.Get(),
282  szFilename)); // <=== LOADING FROM DATA STORE.
283 
284  if (strFileContents.GetLength() < 2) {
285  otErr << "OTCronItem::" << __FUNCTION__
286  << ": Error reading file: " << szFoldername
287  << OTLog::PathSeparator() << strServerID << OTLog::PathSeparator()
288  << szFilename << "\n";
289  return nullptr;
290  }
291  else
292  // NOTE: NewCronItem can handle the normal cron item contracts, as well
293  // as the OT ARMORED version
294  // (It will decode the armor before instantiating the contract.)
295  // Therefore there's no need HERE in
296  // THIS function to do any decoding...
297  //
298  return OTCronItem::NewCronItem(strFileContents);
299 }
300 
301 // static
302 // Client-side only.
304  const OTIdentifier& nymID,
305  const OTIdentifier& serverID)
306 {
307  const char* szFoldername = OTFolders::Cron().Get();
308 
309  output.Release();
310 
311  // We need to load up the local list of active (recurring) transactions.
312  //
313  OTString strListFilename(nymID), strServerID(serverID);
314  strListFilename.Concatenate(".lst"); // nymID.lst
315 
316  if (OTDB::Exists(szFoldername, strServerID.Get(), strListFilename.Get())) {
317  // Load up existing list, if it exists.
318  //
319  OTString strNumlist(OTDB::QueryPlainString(
320  szFoldername, strServerID.Get(), strListFilename.Get()));
321 
322  if (strNumlist.Exists()) {
323  if (false ==
324  strNumlist.DecodeIfArmored(false)) // bEscapedIsAllowed=true by
325  // default.
326  {
327  otErr << __FUNCTION__
328  << ": List of recurring transactions; string apparently "
329  "was encoded "
330  "and then failed decoding. Contents: \n" << strNumlist
331  << "\n";
332  return false;
333  }
334  else
335  output.Add(strNumlist);
336  }
337  }
338 
339  return true;
340 }
341 
342 // static
343 // Client-side only.
344 bool OTCronItem::EraseActiveCronReceipt(const int64_t& lTransactionNum,
345  const OTIdentifier& nymID,
346  const OTIdentifier& serverID)
347 {
348  OTString strFilename, strServerID(serverID);
349  strFilename.Format("%lld.crn", lTransactionNum);
350 
351  const char* szFoldername = OTFolders::Cron().Get();
352  const char* szFilename = strFilename.Get();
353 
354  // Before we remove the cron item receipt itself, first we need to load up
355  // the local list of active (recurring) transactions, and remove the number
356  // from that list. Otherwise the GUI will continue thinking the transaction
357  // is active in cron.
358  //
359  OTString strListFilename(nymID);
360  strListFilename.Concatenate(".lst"); // nymID.lst
361 
362  if (OTDB::Exists(szFoldername, strServerID.Get(), strListFilename.Get())) {
363  // Load up existing list, to remove the transaction num from it.
364  //
365  OTNumList numlist;
366 
367  OTString strNumlist(OTDB::QueryPlainString(
368  szFoldername, strServerID.Get(), strListFilename.Get()));
369 
370  if (strNumlist.Exists()) {
371  if (false ==
372  strNumlist.DecodeIfArmored(false)) // bEscapedIsAllowed=true by
373  // default.
374  {
375  otErr << __FUNCTION__
376  << ": List of recurring transactions; string apparently "
377  "was encoded "
378  "and then failed decoding. Contents: \n" << strNumlist
379  << "\n";
380  }
381  else
382  numlist.Add(strNumlist);
383  }
384 
385  strNumlist.Release();
386 
387  if (numlist.Count() > 0) numlist.Remove(lTransactionNum);
388 
389  if (0 == numlist.Count()) {
390  if (!OTDB::EraseValueByKey(szFoldername, strServerID.Get(),
391  strListFilename.Get())) {
392  otOut << "OTCronItem::" << __FUNCTION__
393  << ": FYI, failure erasing recurring IDs file: "
394  << szFoldername << OTLog::PathSeparator() << strServerID
395  << OTLog::PathSeparator() << strListFilename << "\n";
396  }
397  }
398  else {
399  numlist.Output(strNumlist);
400 
401  OTString strFinal;
402  OTASCIIArmor ascTemp(strNumlist);
403 
404  if (false ==
405  ascTemp.WriteArmoredString(
406  strFinal, "ACTIVE CRON ITEMS")) // todo hardcoding
407  {
408  otErr << "OTCronItem::" << __FUNCTION__
409  << ": Error re-saving recurring IDs (failed writing "
410  "armored string): " << szFoldername
411  << OTLog::PathSeparator() << strServerID
412  << OTLog::PathSeparator() << strListFilename << "\n";
413  return false;
414  }
415  else {
416  bool bSaved = OTDB::StorePlainString(
417  strFinal.Get(), szFoldername, strServerID.Get(),
418  strListFilename.Get());
419 
420  if (!bSaved) {
421  otErr << "OTCronItem::" << __FUNCTION__
422  << ": Error re-saving recurring IDs: " << szFoldername
423  << OTLog::PathSeparator() << strServerID
424  << OTLog::PathSeparator() << strListFilename << "\n";
425  return false;
426  }
427  }
428  }
429  }
430 
431  // Now that the list is updated, let's go ahead and erase the actual cron
432  // item itself.
433  //
434  if (!OTDB::Exists(szFoldername, strServerID.Get(), szFilename)) {
435  otErr << "OTCronItem::" << __FUNCTION__
436  << ": File does not exist: " << szFoldername
437  << OTLog::PathSeparator() << strServerID << OTLog::PathSeparator()
438  << szFilename << "\n";
439  return false;
440  }
441 
442  if (!OTDB::EraseValueByKey(szFoldername, strServerID.Get(), szFilename)) {
443  otErr << "OTCronItem::" << __FUNCTION__
444  << ": Error erasing file: " << szFoldername
445  << OTLog::PathSeparator() << strServerID << OTLog::PathSeparator()
446  << szFilename << "\n";
447  return false;
448  }
449 
450  return true;
451 }
452 
454  const OTIdentifier& theNymID) // Client-side only.
455 {
456  const int64_t lOpeningNum = GetOpeningNumber(theNymID);
457 
458  OTString strFilename, strServerID(GetServerID());
459  strFilename.Format("%lld.crn", lOpeningNum);
460 
461  const char* szFoldername = OTFolders::Cron().Get(); // cron
462  const char* szFilename = strFilename.Get(); // cron/TRANSACTION_NUM.crn
463 
464  if (OTDB::Exists(szFoldername, strServerID.Get(), szFilename)) {
465  otInfo << "OTCronItem::" << __FUNCTION__
466  << ": Cron Record already exists for transaction "
467  << GetTransactionNum() << " " << szFoldername
468  << OTLog::PathSeparator() << strServerID
469  << OTLog::PathSeparator() << szFilename << ", "
470  "overwriting.\n";
471  // NOTE: We could just return here. But what if the record we have is
472  // corrupted somehow?
473  // Might as well just write it there again, so I let this continue
474  // running.
475  }
476  else // It wasn't there already, so we need to save the number in our
477  // local list of trans nums.
478  {
479  OTString strListFilename(theNymID);
480  strListFilename.Concatenate(".lst"); // nymID.lst
481  OTNumList numlist;
482 
483  if (OTDB::Exists(szFoldername, strServerID.Get(),
484  strListFilename.Get())) {
485  // Load up existing list, to add the new transaction num to it.
486  //
487  OTString strNumlist(OTDB::QueryPlainString(
488  szFoldername, strServerID.Get(), strListFilename.Get()));
489 
490  if (strNumlist.Exists()) {
491  if (false ==
492  strNumlist.DecodeIfArmored(false)) // bEscapedIsAllowed=true
493  // by default.
494  {
495  otErr << __FUNCTION__
496  << ": Input string apparently was encoded and then"
497  " failed decoding. Contents: \n" << strNumlist
498  << "\n";
499  }
500  else
501  numlist.Add(strNumlist);
502  }
503  }
504 
505  numlist.Add(lOpeningNum);
506 
507  OTString strNumlist;
508 
509  if (numlist.Output(strNumlist)) {
510  OTString strFinal;
511  OTASCIIArmor ascTemp(strNumlist);
512 
513  if (false ==
514  ascTemp.WriteArmoredString(
515  strFinal, "ACTIVE CRON ITEMS")) // todo hardcoding
516  {
517  otErr << "OTCronItem::" << __FUNCTION__
518  << ": Error saving recurring IDs (failed writing armored "
519  "string): " << szFoldername << OTLog::PathSeparator()
520  << strServerID << OTLog::PathSeparator()
521  << strListFilename << "\n";
522  return false;
523  }
524 
525  bool bSaved = OTDB::StorePlainString(strFinal.Get(), szFoldername,
526  strServerID.Get(),
527  strListFilename.Get());
528 
529  if (!bSaved) {
530  otErr << "OTCronItem::" << __FUNCTION__
531  << ": Error saving recurring IDs: " << szFoldername
532  << OTLog::PathSeparator() << strServerID
533  << OTLog::PathSeparator() << strListFilename << "\n";
534  return false;
535  }
536  }
537  }
538 
539  OTString strFinal;
540  OTASCIIArmor ascTemp(m_strRawFile);
541 
542  if (false ==
543  ascTemp.WriteArmoredString(strFinal, m_strContractType.Get())) {
544  otErr << "OTCronItem::" << __FUNCTION__
545  << ": Error saving file (failed writing armored string): "
546  << szFoldername << OTLog::PathSeparator() << strServerID
547  << OTLog::PathSeparator() << szFilename << "\n";
548  return false;
549  }
550 
551  bool bSaved = OTDB::StorePlainString(strFinal.Get(), szFoldername,
552  strServerID.Get(), szFilename);
553 
554  if (!bSaved) {
555  otErr << "OTCronItem::" << __FUNCTION__
556  << ": Error saving file: " << szFoldername
557  << OTLog::PathSeparator() << strServerID << OTLog::PathSeparator()
558  << szFilename << "\n";
559  return false;
560  }
561 
562  return bSaved;
563 }
564 
565 // When first adding anything to Cron, a copy needs to be saved in a folder
566 // somewhere.
567 // (Just for our records.) For example, before I start updating the status on
568 // any Trade,
569 // I have already saved the user's original Trade object (from his request) to a
570 // folder.
571 // Now I have the freedom to ReleaseSignatures on the Trade and re-sign it with
572 // the
573 // server's Nym as it updates over time. The user cannot challenge the Trade
574 // because
575 // the server has the original copy on file and sends it with all receipts.
576 
578 {
579  OTString strFilename;
580  strFilename.Format("%lld.crn", GetTransactionNum());
581 
582  const char* szFoldername = OTFolders::Cron().Get(); // cron
583  const char* szFilename = strFilename.Get(); // cron/TRANSACTION_NUM.crn
584 
585  if (OTDB::Exists(szFoldername, szFilename)) {
586  otErr << "OTCronItem::" << __FUNCTION__
587  << ": Cron Record already exists for transaction "
588  << GetTransactionNum() << " " << szFoldername
589  << OTLog::PathSeparator() << szFilename
590  << ",\n"
591  "yet inexplicably attempted to record it again.\n";
592  return false;
593  }
594 
595  OTString strFinal;
596  OTASCIIArmor ascTemp(m_strRawFile);
597 
598  if (false ==
599  ascTemp.WriteArmoredString(strFinal, m_strContractType.Get())) {
600  otErr << "OTCronItem::" << __FUNCTION__
601  << ": Error saving file (failed writing armored string): "
602  << szFoldername << OTLog::PathSeparator() << szFilename << "\n";
603  return false;
604  }
605 
606  bool bSaved =
607  OTDB::StorePlainString(strFinal.Get(), szFoldername, szFilename);
608 
609  if (!bSaved) {
610  otErr << "OTCronItem::" << __FUNCTION__
611  << ": Error saving file: " << szFoldername
612  << OTLog::PathSeparator() << szFilename << "\n";
613  return false;
614  }
615 
616  return bSaved;
617 }
618 
619 bool OTCronItem::SetDateRange(time64_t VALID_FROM, time64_t VALID_TO)
620 {
621  // Set the CREATION DATE
622  //
623  const time64_t CURRENT_TIME = OTTimeGetCurrentTime();
624 
625  // Set the Creation Date.
626  SetCreationDate(CURRENT_TIME);
627 
628  // VALID_FROM
629  //
630  // The default "valid from" time is NOW.
631  if (OT_TIME_ZERO >= VALID_FROM) // if it's 0 or less, set to current time.
632  SetValidFrom(CURRENT_TIME);
633  else // Otherwise use whatever was passed in.
634  SetValidFrom(VALID_FROM);
635 
636  // VALID_TO
637  //
638  // The default "valid to" time is 0 (which means no expiration date / cancel
639  // anytime.)
640  if (OT_TIME_ZERO == VALID_TO) // VALID_TO is 0
641  {
642  SetValidTo(VALID_TO); // Keep it at zero then, so it won't expire.
643  }
644  else if (OT_TIME_ZERO < VALID_TO) // VALID_TO is ABOVE zero...
645  {
646  if (VALID_TO <
647  VALID_FROM) // If Valid-To date is EARLIER than Valid-From date...
648  {
649  int64_t lValidTo = OTTimeGetSecondsFromTime(VALID_TO);
650  int64_t lValidFrom = OTTimeGetSecondsFromTime(VALID_FROM);
651  otErr << "OTCronItem::" << __FUNCTION__ << ": VALID_TO ("
652  << lValidTo << ") is earlier than VALID_FROM (" << lValidFrom
653  << ")\n";
654  return false;
655  }
656 
657  SetValidTo(VALID_TO); // Set it to whatever it is, since it is now
658  // validated as higher than Valid-From.
659  }
660  else // VALID_TO is a NEGATIVE number... Error.
661  {
662  int64_t lValidTo = OTTimeGetSecondsFromTime(VALID_TO);
663  otErr << "OTCronItem::" << __FUNCTION__
664  << ": Negative value for valid_to: " << lValidTo << "\n";
665 
666  return false;
667  }
668 
669  return true;
670 }
671 
672 // These are for finalReceipt
673 // The Cron Item stores a list of these closing transaction numbers,
674 // used for closing a transaction.
675 //
677 {
678  return static_cast<int32_t>(m_dequeClosingNumbers.size());
679 }
680 
681 int64_t OTCronItem::GetClosingTransactionNoAt(uint32_t nIndex) const
682 {
683  if (m_dequeClosingNumbers.size() <= nIndex) {
684  otErr << __FUNCTION__ << ": "
685  << "nIndex"
686  << " is equal or larger than m_dequeClosingNumbers.size()!\n";
687  OT_FAIL;
688  }
689 
690  return m_dequeClosingNumbers.at(nIndex);
691 }
692 
693 void OTCronItem::AddClosingTransactionNo(const int64_t& lClosingTransactionNo)
694 {
695  m_dequeClosingNumbers.push_back(lClosingTransactionNo);
696 }
697 
701 {
702  // You don't just go willy-nilly and remove a cron item from a market unless
703  // you check first
704  // and make sure the Nym who requested it actually has said number (or a
705  // related closing number)
706  // signed out to him on his last receipt...
707  //
708  if (!theNym.CompareID(GetSenderUserID())) {
709  otLog5 << "OTCronItem::CanRemoveItem: theNym is not the originator of "
710  "this CronItem. "
711  "(He could be a recipient though, so this is normal.)\n";
712  return false;
713  }
714 
715  // By this point, that means theNym is DEFINITELY the originator (sender)...
716  else if (GetCountClosingNumbers() < 1) {
717  otOut << "Weird: Sender tried to remove a cron item; expected at least "
718  "1 closing number to be available"
719  "--that wasn't. (Found " << GetCountClosingNumbers() << ").\n";
720  return false;
721  }
722 
723  const OTString strServerID(GetServerID());
724 
725  if (!theNym.VerifyIssuedNum(strServerID, GetClosingNum())) {
726  otOut << "OTCronItem::CanRemoveItemFromCron: Closing number didn't "
727  "verify (for removal from cron).\n";
728  return false;
729  }
730 
731  // By this point, we KNOW theNym is the sender, and we KNOW there are the
732  // proper number of transaction
733  // numbers available to close. We also know that this cron item really was
734  // on the cron object, since
735  // that is where it was looked up from, when this function got called! So
736  // I'm pretty sure, at this point,
737  // to authorize removal, as long as the transaction num is still issued to
738  // theNym (this check here.)
739  //
740  return theNym.VerifyIssuedNum(strServerID, GetOpeningNum());
741 
742  // Normally this will be all we need to check. The originator will have the
743  // transaction
744  // number signed-out to him still, if he is trying to close it. BUT--in some
745  // cases, someone
746  // who is NOT the originator can cancel. Like in a payment plan, the sender
747  // is also the depositor,
748  // who would normally be the person cancelling the plan. But technically,
749  // the RECIPIENT should
750  // also have the ability to cancel that payment plan. BUT: the transaction
751  // number isn't signed
752  // out to the RECIPIENT... In THAT case, the below VerifyIssuedNum() won't
753  // work! In those cases,
754  // expect that the special code will be in the subclasses override of this
755  // function. (OTPaymentPlan::CanRemoveItem() etc)
756 
757  // P.S. If you override this function, maybe call the parent
758  // (OTCronItem::CanRemoveItem) first,
759  // for the VerifyIssuedNum call above. Only if that fails, do you need to
760  // dig deeper...
761 }
762 
763 // OTCron calls this regularly, which is my chance to expire, etc.
764 // Child classes will override this, AND call it (to verify valid date range.)
765 //
766 // Return False: REMOVE this Cron Item from Cron.
767 // Return True: KEEP this Cron Item on Cron (for now.)
768 //
770 {
771  OT_ASSERT(nullptr != m_pCron);
772 
773  if (IsFlaggedForRemoval()) {
774  otLog3 << "Cron: Flagged for removal: " << m_strContractType << ".\n";
775  return false;
776  }
777 
778  // I call IsExpired() here instead of VerifyCurrentDate(). The Cron Item
779  // will stay on
780  // Cron even if it is NOT YET valid. But once it actually expires, this will
781  // remove it.
782  if (IsExpired()) {
783  otLog3 << "Cron: Expired " << m_strContractType << ".\n";
784  return false;
785  }
786 
787  // As far as this code is concerned, the item can stay on cron for now.
788  // Return true.
789  return true;
790 }
791 
792 // OTCron calls this when a cron item is added.
793 // bForTheFirstTime=true means that this cron item is being
794 // activated for the very first time. (Versus being re-added
795 // to cron after a server reboot.)
796 //
797 void OTCronItem::HookActivationOnCron(OTPseudonym*, // sometimes nullptr.
798  bool bForTheFirstTime)
799 {
800  // Put anything else in here, that needs to be done in the
801  // cron item base class, upon activation. (This executes
802  // no matter what, even if onActivate() is overridden.)
803 
804  if (bForTheFirstTime) onActivate(); // Subclasses may override this.
805  //
806  // MOST NOTABLY,
807  // OTSmartContract overrides this, so it can allow the SCRIPT
808  // a chance to hook onActivate() as well.
809 }
810 
811 // OTCron calls this when a cron item is removed
812 // This gives each item a chance to drop a final receipt,
813 // and clean up any memory, before being destroyed.
814 //
816  int64_t newTransactionNo)
817 {
818  OTPseudonym* pServerNym = serverNym_;
819  OT_ASSERT(nullptr != pServerNym);
820 
821  // Generate new transaction number for these new inbox receipts.
822  //
823  const int64_t lNewTransactionNumber = newTransactionNo;
824 
825  // OT_ASSERT(lNewTransactionNumber > 0); // this can be my reminder.
826  if (0 == lNewTransactionNumber) {
827  otErr << "OTCronItem::HookRemovalFromCron: ** ERROR Final receipt not "
828  "added to inbox, since no "
829  "transaction numbers were available!\n";
830  }
831  else {
832  // Everytime a payment processes, or a trade, then a receipt is put in
833  // the user's inbox.
834  // This contains a copy of the current payment or trade (which took
835  // money from the user's acct.)
836  //
837  // ==> So I increment the payment count each time before dropping the
838  // receipt. (I also use a fresh
839  // transaction number when I put it into the inbox.) That way, the user
840  // will never get the same
841  // receipt for the same plan twice. It cannot take funds from his
842  // account, without a new payment
843  // count and a new transaction number on a new receipt. Until the user
844  // accepts the receipt out
845  // of his inbox with a new balance agreement, the existing receipts can
846  // be added up and compared
847  // to the last balance agreement, to verify the current balance. Every
848  // receipt from a processing
849  // payment will have the user's authorization, signature, and terms, as
850  // well as the update in balances
851  // due to the payment, signed by the server.
852 
853  // In the case of the FINAL RECEIPT, I do NOT increment the count, so
854  // you can see it will have the same
855  // payment count as the last paymentReceipt. (if there were 5
856  // paymentReceipts, from 1 to 5, then the
857  // finalReceipt will also be 5. This is evidence of what the last
858  // paymentReceipt WAS.)
859 
860  // The TRANSACTION will be dropped into the INBOX with "In Reference To"
861  // information,
862  // containing the ORIGINAL SIGNED REQUEST.
863  //
864  OTCronItem* pOrigCronItem =
866  // OTCronItem::LoadCronReceipt loads the original version with the
867  // user's signature.
868  // (Updated versions, as processing occurs, are signed by the server.)
869  OT_ASSERT(nullptr != pOrigCronItem);
870  std::unique_ptr<OTCronItem> theCronItemAngel(pOrigCronItem);
871 
872  // Note: elsewhere, we verify the Nym's signature. But in this place, we
873  // verify the SERVER's
874  // signature. (The server signed the cron receipt just before it was
875  // first saved, so it has two signatures on it.)
876  //
877  {
878  bool bValidSignture = pOrigCronItem->VerifySignature(*pServerNym);
879  if (!bValidSignture) {
880  otErr << __FUNCTION__ << ": Failure verifying signature of "
881  "server on Cron Item!\n";
882  OT_FAIL;
883  return;
884  }
885  }
886 
887  // I now have a String copy of the original CronItem...
888  const OTString strOrigCronItem(*pOrigCronItem);
889 
890  OTPseudonym theOriginatorNym; // Don't use this... use the pointer just
891  // below.
892 
893  // The Nym who is actively requesting to remove a cron item will be
894  // passed in as pRemover.
895  // However, sometimes there is no Nym... perhaps it just expired and
896  // pRemover is nullptr.
897  // The originating Nym (if different than remover) is loaded up.
898  // Otherwise the originator
899  // pointer just pointers to *pRemover.
900  //
901  OTPseudonym* pOriginator = nullptr;
902 
903  if (pServerNym->CompareID(pOrigCronItem->GetSenderUserID())) {
904  pOriginator = pServerNym; // Just in case the originator Nym is also
905  // the server Nym.
906  } // This MIGHT be unnecessary, since pRemover is(I think) already
907  // transmogrified
908  // ******************************************************* to pServer
909  // earlier, if they share the same ID.
910  //
911  // If pRemover is NOT nullptr, and he has the Originator's ID...
912  // then set the pointer accordingly.
913  //
914  else if ((nullptr != pRemover) &&
915  (true ==
916  pRemover->CompareID(pOrigCronItem->GetSenderUserID()))) {
917  pOriginator = pRemover; // <======== now both pointers are set (to
918  // same Nym). DONE!
919  }
920 
921  // At this point, pRemover MIGHT be set, or nullptr. (And that's that --
922  // pRemover may always be nullptr.)
923  //
924  // if pRemover IS set, then pOriginator MIGHT point to it as well. (If
925  // the IDs match. Done above.)
926  // pOriginator might also still be nullptr. (If pRemover is nullptr,
927  // then
928  // pOriginator DEFINITELY is.)
929  // pRemover is loaded (or not). Next let's make SURE pOriginator is
930  // loaded, if it wasn't already...
931  //
932  if (nullptr == pOriginator) {
933  // GetSenderUserID() should be the same on THIS (updated version of
934  // the same cron item)
935  // but for whatever reason, I'm checking the userID on the original
936  // version. Sue me.
937  //
938  const OTIdentifier NYM_ID(pOrigCronItem->GetSenderUserID());
939 
940  theOriginatorNym.SetIdentifier(NYM_ID);
941 
942  if (!theOriginatorNym.LoadPublicKey()) {
943  OTString strNymID(NYM_ID);
944  otErr << "OTCronItem::HookRemovalFromCron: Failure loading "
945  "Sender's public key:\n" << strNymID << "\n";
946  }
947  else if (theOriginatorNym.VerifyPseudonym() &&
948  theOriginatorNym.LoadSignedNymfile(
949  *pServerNym)) // ServerNym here is merely the signer
950  // on this file.
951  {
952  pOriginator = &theOriginatorNym; // <=====
953  }
954  else {
955  OTString strNymID(NYM_ID);
956  otErr << "OTCronItem::HookRemovalFromCron: Failure verifying "
957  "Sender's"
958  " public key or loading signed nymfile: " << strNymID
959  << "\n";
960  }
961  }
962 
963  // pOriginator should NEVER be nullptr by this point, unless there was
964  // an
965  // ERROR in the above block.
966  // We even loaded the guy from storage, if we had to.
967  //
968  if (nullptr != pOriginator) {
969  // Drop the FINAL RECEIPT(s) into the user's inbox(es)!!
970  // Pass in strOrigCronItem and lNewTransactionNumber which were
971  // obtained above.
972  //
973  onFinalReceipt(*pOrigCronItem, lNewTransactionNumber, *pOriginator,
974  pRemover);
975  }
976  else {
977  otErr << "MAJOR ERROR in OTCronItem::HookRemovalFromCron!! Failed "
978  "loading Originator Nym for Cron Item.\n";
979  }
980  }
981 
982  // Remove corresponding offer from market, if applicable.
983  //
985 }
986 
987 // This function is overridden in OTTrade, OTAgreement, and OTSmartContract.
988 //
989 // I'm put a default implementation here "Just Because."
990 //
991 // This is called by HookRemovalFromCron().
992 //
994  const int64_t& lNewTransactionNumber,
995  OTPseudonym& theOriginator,
996  OTPseudonym* pRemover) // may already point to
997  // theOriginator... or
998  // someone else...
999 {
1000  OTPseudonym* pServerNym = serverNym_;
1001  OT_ASSERT(nullptr != pServerNym);
1002 
1003  // The finalReceipt Item's ATTACHMENT contains the UPDATED Cron Item.
1004  // (With the SERVER's signature on it!)
1005  //
1006  OTString strUpdatedCronItem(*this);
1007  OTString* pstrAttachment = &strUpdatedCronItem;
1008 
1009  const OTString strOrigCronItem(theOrigCronItem);
1010 
1011  // First, we are closing the transaction number ITSELF, of this cron item,
1012  // as an active issued number on the originating nym. (Changing it to
1013  // CLOSED.)
1014  //
1015  // Second, we're verifying the CLOSING number, and using it as the closing
1016  // number
1017  // on the FINAL RECEIPT (with that receipt being "InReferenceTo"
1018  // GetTransactionNum())
1019  //
1020  const int64_t lOpeningNumber = theOrigCronItem.GetOpeningNum();
1021  const int64_t lClosingNumber = theOrigCronItem.GetClosingNum();
1022 
1023  const OTString strServerID(GetServerID());
1024 
1025  OTPseudonym theActualNym; // unused unless it's really not already loaded.
1026  // (use pActualNym.)
1027 
1028  // I'm ASSUMING here that pRemover is also theOriginator.
1029  //
1030  // REMEMBER: Most subclasses will override this method, and THEY
1031  // are the cases where pRemover is someone other than theOriginator.
1032  // That's why they have a different version of onFinalReceipt.
1033  //
1034  if ((lOpeningNumber > 0) &&
1035  theOriginator.VerifyIssuedNum(strServerID, lOpeningNumber)) {
1036  // The Nym (server side) stores a list of all opening and closing cron
1037  // #s.
1038  // So when the number is released from the Nym, we also take it off that
1039  // list.
1040  //
1041  std::set<int64_t>& theIDSet = theOriginator.GetSetOpenCronItems();
1042  theIDSet.erase(lOpeningNumber);
1043 
1044  theOriginator.RemoveIssuedNum(*pServerNym, strServerID, lOpeningNumber,
1045  false); // bSave=false
1046  theOriginator.SaveSignedNymfile(*pServerNym);
1047 
1048  // the RemoveIssued call means the original transaction# (to find this
1049  // cron item on cron) is now CLOSED.
1050  // But the Transaction itself is still OPEN. How? Because the CLOSING
1051  // number is still signed out.
1052  // The closing number is also USED, since the NotarizePaymentPlan or
1053  // NotarizeMarketOffer call, but it
1054  // remains ISSUED, until the final receipt itself is accepted during a
1055  // process inbox.
1056  //
1057  const OTIdentifier& ACTUAL_NYM_ID = GetSenderUserID();
1058  OTPseudonym* pActualNym = nullptr; // use this. DON'T use theActualNym.
1059 
1060  if ((nullptr != pServerNym) && pServerNym->CompareID(ACTUAL_NYM_ID))
1061  pActualNym = pServerNym;
1062  else if (theOriginator.CompareID(ACTUAL_NYM_ID))
1063  pActualNym = &theOriginator;
1064  else if ((nullptr != pRemover) && pRemover->CompareID(ACTUAL_NYM_ID))
1065  pActualNym = pRemover;
1066 
1067  else // We couldn't find the Nym among those already loaded--so we have
1068  // to load
1069  { // it ourselves (so we can update its NymboxHash value.)
1070  theActualNym.SetIdentifier(ACTUAL_NYM_ID);
1071 
1072  if (!theActualNym.LoadPublicKey()) // Note: this step may be
1073  // unnecessary since we
1074  // are only updating his
1075  // Nymfile, not his key.
1076  {
1077  OTString strNymID(ACTUAL_NYM_ID);
1078  otErr << __FUNCTION__
1079  << ": Failure loading public key for Nym: " << strNymID
1080  << ". (To update his NymboxHash.) \n";
1081  }
1082  else if (theActualNym.VerifyPseudonym() && // this line may be
1083  // unnecessary.
1084  theActualNym.LoadSignedNymfile(
1085  *pServerNym)) // ServerNym here is not theActualNym's
1086  // identity, but merely the signer on
1087  // this file.
1088  {
1089  otLog3
1090  << __FUNCTION__
1091  << ": Loading actual Nym, since he wasn't already loaded. "
1092  "(To update his NymboxHash.)\n";
1093  pActualNym = &theActualNym; // <=====
1094  }
1095  else {
1096  OTString strNymID(ACTUAL_NYM_ID);
1097  otErr
1098  << __FUNCTION__
1099  << ": Failure loading or verifying Actual Nym public key: "
1100  << strNymID << ". (To update his NymboxHash.)\n";
1101  }
1102  }
1103 
1104  if (!DropFinalReceiptToNymbox(GetSenderUserID(), lNewTransactionNumber,
1105  strOrigCronItem, nullptr, // note
1106  pstrAttachment, pActualNym)) {
1107  otErr << __FUNCTION__
1108  << ": Failure dropping finalReceipt to Nymbox.\n";
1109  }
1110  }
1111  else {
1112  otErr << __FUNCTION__ << ": Failed doing "
1113  "VerifyIssuedNum(theOrigCronItem."
1114  "GetTransactionNum())\n";
1115  }
1116 
1117  if ((lClosingNumber > 0) &&
1118  theOriginator.VerifyIssuedNum(strServerID, lClosingNumber)) {
1119  // SENDER only. (CronItem has no recipient. That's in the subclass.)
1120  //
1122  GetSenderUserID(), GetSenderAcctID(), lNewTransactionNumber,
1123  lClosingNumber, // The closing transaction number to
1124  // put on the receipt.
1125  strOrigCronItem, nullptr, // note
1126  pstrAttachment)) // pActualAcct = nullptr by default.
1127  // (This call will load it up in order
1128  // to update the inbox hash.)
1129  otErr << __FUNCTION__ << ": Failure dropping receipt into inbox.\n";
1130 
1131  // In this case, I'm passing nullptr for pstrNote, since there is no
1132  // note.
1133  // (Additional information would normally be stored in the note.)
1134 
1135  // This part below doesn't happen until you ACCEPT the final receipt
1136  // (when processing your inbox.)
1137  //
1138  // theOriginator.RemoveIssuedNum(strServerID, lClosingNumber,
1139  // true); //bSave=false
1140  }
1141  else {
1142  otErr << __FUNCTION__
1143  << ": Failed verifying "
1144  "lClosingNumber=theOrigCronItem.GetClosingTransactionNoAt(0)>"
1145  "0 && "
1146  "theOriginator.VerifyTransactionNum(lClosingNumber)\n";
1147  }
1148 
1149  // QUESTION: Won't there be Cron Items that have no asset account at all?
1150  // In which case, there'd be no need to drop a final receipt, but I don't
1151  // think
1152  // that's the case, since you have to use a transaction number to get onto
1153  // cron
1154  // in the first place.
1155 }
1156 
1157 // This is the "DROPS FINAL RECEIPT" function.
1158 // "Final Receipts" are used by Cron Items, as the last receipt for a given
1159 // transaction number.
1160 //
1162  const OTIdentifier& USER_ID, const OTIdentifier& ACCOUNT_ID,
1163  const int64_t& lNewTransactionNumber, const int64_t& lClosingNumber,
1164  const OTString& strOrigCronItem, OTString* pstrNote,
1165  OTString* pstrAttachment, OTAccount* pActualAcct)
1166 {
1167  OTPseudonym* pServerNym = serverNym_;
1168  OT_ASSERT(nullptr != pServerNym);
1169 
1170  const char* szFunc = "OTCronItem::DropFinalReceiptToInbox";
1171 
1172  std::unique_ptr<OTAccount> theDestAcctGuardian;
1173 
1174  // Load the inbox in case it already exists.
1175  OTLedger theInbox(USER_ID, ACCOUNT_ID, GetServerID());
1176 
1177  // Inbox will receive notification of something ALREADY DONE.
1178  bool bSuccessLoading = theInbox.LoadInbox();
1179 
1180  // ...or generate it otherwise...
1181 
1182  if (true == bSuccessLoading)
1183  bSuccessLoading = theInbox.VerifyAccount(*pServerNym);
1184  else
1185  otErr << szFunc << ": ERROR loading inbox ledger.\n";
1186  // otErr << szFunc << ": ERROR loading inbox ledger.\n";
1187  // else
1188  // bSuccessLoading = theInbox.GenerateLedger(ACCOUNT_ID,
1189  // GetServerID(), OTLedger::inbox, true); // bGenerateFile=true
1190 
1191  if (!bSuccessLoading) {
1192  otErr << szFunc << ": ERROR loading or generating an inbox. (FAILED "
1193  "WRITING RECEIPT!!) \n";
1194  return false;
1195  }
1196  else {
1197  // Start generating the receipts
1198 
1200  theInbox, OTTransaction::finalReceipt, lNewTransactionNumber);
1201  // (No need to OT_ASSERT on the above transaction since it occurs in
1202  // GenerateTransaction().)
1203 
1204  // The inbox will get a receipt with the new transaction ID.
1205  // That receipt has an "in reference to" field containing the original
1206  // cron item.
1207 
1208  // set up the transaction items (each transaction may have multiple
1209  // items... but not in this case.)
1210  OTItem* pItem1 =
1212 
1213  // This may be unnecessary, I'll have to check
1214  // CreateItemFromTransaction. I'll leave it for now.
1215  OT_ASSERT(nullptr != pItem1);
1216 
1218 
1219  //
1220  // Here I make sure that the receipt (the inbox notice) references the
1221  // transaction number that the trader originally used to issue the cron
1222  // item...
1223  // This number is used to match up offers to trades, and used to track
1224  // all cron items.
1225  // (All Cron items require a transaction from the user to add them to
1226  // Cron in the
1227  // first place.)
1228  //
1229  const int64_t lOpeningNum = GetOpeningNumber(USER_ID);
1230 
1231  pTrans1->SetReferenceToNum(lOpeningNum);
1232  pTrans1->SetNumberOfOrigin(lOpeningNum);
1233  // pItem1-> SetReferenceToNum(lOpeningNum);
1234 
1235  // The reference on the transaction contains an OTCronItem, in this
1236  // case.
1237  // The original cron item, versus the updated cron item (which is stored
1238  // on the finalReceipt item just below here.)
1239  //
1240  pTrans1->SetReferenceString(strOrigCronItem);
1241 
1242  pTrans1->SetClosingNum(lClosingNumber); // This transaction is the
1243  // finalReceipt for
1244  // GetTransactionNum(), as
1245  // lClosingNumber.
1246  // pItem1-> SetClosingNum(lClosingNumber);
1247  //
1248  // NOTE: I COULD look up the closing number by doing a call to
1249  // GetClosingNumber(ACCOUNT_ID);
1250  // But that is already taken care of where it matters, and passed in
1251  // here properly already, so it
1252  // would be superfluous.
1253 
1254  // The finalReceipt ITEM's NOTE contains the UPDATED CRON ITEM.
1255  //
1256  if (nullptr != pstrNote) {
1257  pItem1->SetNote(*pstrNote); // in markets, this is updated trade.
1258  }
1259 
1260  // Also set the ** UPDATED OFFER ** as the ATTACHMENT on the ** item.**
1261  // (With the SERVER's signature on it!) // in markets, this is updated
1262  // offer.
1263  //
1264  if (nullptr != pstrAttachment) {
1265  pItem1->SetAttachment(*pstrAttachment);
1266  }
1267 
1268  // sign the item
1269 
1270  pItem1->SignContract(*pServerNym);
1271  pItem1->SaveContract();
1272 
1273  // the Transaction "owns" the item now and will handle cleaning it up.
1274  pTrans1->AddItem(*pItem1);
1275 
1276  pTrans1->SignContract(*pServerNym);
1277  pTrans1->SaveContract();
1278 
1279  // Here the transaction we just created is actually added to the ledger.
1280  theInbox.AddTransaction(*pTrans1);
1281 
1282  // Release any signatures that were there before (They won't
1283  // verify anymore anyway, since the content has changed.)
1284  theInbox.ReleaseSignatures();
1285 
1286  // Sign and save.
1287  theInbox.SignContract(*pServerNym);
1288  theInbox.SaveContract();
1289 
1290  // TODO: Better rollback capabilities in case of failures here:
1291 
1292  if (nullptr == pActualAcct) // no asset account was passed in as already
1293  // loaded, so let's load it ourselves then.
1294  {
1295  pActualAcct =
1297  theDestAcctGuardian.reset(pActualAcct);
1298  }
1299 
1300  // Save inbox to storage. (File, DB, wherever it goes.)
1301  //
1302  if (nullptr != pActualAcct) {
1303  OT_ASSERT(ACCOUNT_ID == pActualAcct->GetPurportedAccountID());
1304 
1305  if (pActualAcct->VerifyAccount(*pServerNym)) {
1306  pActualAcct->SaveInbox(theInbox);
1307  pActualAcct->SaveAccount(); // inbox hash has changed here, so
1308  // we save the account to reflect
1309  // that change.
1310  }
1311  else {
1312  otErr << szFunc
1313  << ": Failed: pActualAcct->VerifyAccount(*pServerNym)\n";
1314  }
1315  }
1316  else // todo: would the account EVER be null here? Should never be.
1317  // Therefore should we save the inbox here?
1318  {
1319  theInbox.SaveInbox();
1320  }
1321 
1322  // Notice above, if the account loads but fails to verify, then we do
1323  // not save the Inbox.
1324  // Todo: ponder wisdom of that decision.
1325 
1326  // Corresponds to the AddTransaction() just above.
1327  // Details are stored in separate file these days.
1328  //
1329  pTrans1->SaveBoxReceipt(theInbox);
1330 
1331  return true; // Really this true should be predicated on ALL the above
1332  // functions returning true. Right?
1333  } // ...Right?
1334 }
1335 
1336 // Done: IF ACTUAL NYM is NOT passed below, then need to LOAD HIM UP (so we can
1337 // update his NymboxHash after we update the Nymbox.)
1338 
1339 // The final receipt doesn't have a closing number in the Nymbox, only in the
1340 // Inbox.
1341 // That's because in the Nymbox, it's just a notice, and it's not there to
1342 // enforce anything.
1343 // If you get one in your Nymbox, it's just so that you know to removed its "in
1344 // ref to" number
1345 // from your issued list (so your balance agreements will work :P)
1346 //
1348  const int64_t& lNewTransactionNumber,
1349  const OTString& strOrigCronItem,
1350  OTString* pstrNote,
1351  OTString* pstrAttachment,
1352  OTPseudonym* pActualNym)
1353 {
1354  OTPseudonym* pServerNym = serverNym_;
1355  OT_ASSERT(nullptr != pServerNym);
1356 
1357  const char* szFunc =
1358  "OTCronItem::DropFinalReceiptToNymbox"; // RESUME!!!!!!!
1359 
1360  OTLedger theLedger(USER_ID, USER_ID, GetServerID());
1361 
1362  // Inbox will receive notification of something ALREADY DONE.
1363  bool bSuccessLoading = theLedger.LoadNymbox();
1364 
1365  // ...or generate it otherwise...
1366 
1367  if (true == bSuccessLoading)
1368  bSuccessLoading = theLedger.VerifyAccount(*pServerNym);
1369  else
1370  otErr << szFunc << ": Unable to load Nymbox.\n";
1371  // else
1372  // bSuccessLoading = theLedger.GenerateLedger(USER_ID,
1373  // GetServerID(), OTLedger::nymbox, true); // bGenerateFile=true
1374 
1375  if (!bSuccessLoading) {
1376  otErr << szFunc << ": ERROR loading or generating a nymbox. (FAILED "
1377  "WRITING RECEIPT!!) \n";
1378  return false;
1379  }
1380 
1382  theLedger, OTTransaction::finalReceipt, lNewTransactionNumber);
1383 
1384  if (nullptr !=
1385  pTransaction) // The above has an OT_ASSERT within, but I just
1386  // like to check my pointers.
1387  {
1388  // The nymbox will get a receipt with the new transaction ID.
1389  // That receipt has an "in reference to" field containing the original
1390  // cron item.
1391 
1392  // set up the transaction items (each transaction may have multiple
1393  // items... but not in this case.)
1395  *pTransaction, OTItem::finalReceipt);
1396 
1397  // This may be unnecessary, I'll have to check
1398  // CreateItemFromTransaction. I'll leave it for now.
1399  OT_ASSERT(nullptr != pItem1);
1400 
1402 
1403  const int64_t lOpeningNumber = GetOpeningNumber(USER_ID);
1404 
1405  // Here I make sure that the receipt (the nymbox notice) references the
1406  // transaction number that the trader originally used to issue the cron
1407  // item...
1408  // This number is used to match up offers to trades, and used to track
1409  // all cron items.
1410  // (All Cron items require a transaction from the user to add them to
1411  // Cron in the
1412  // first place.)
1413 
1414  pTransaction->SetReferenceToNum(
1415  lOpeningNumber); // Notice this same number is set twice (again just
1416  // below), so might be an opportunity to store
1417  // something else in one of them.
1418 
1419  // The reference on the transaction contains an OTCronItem, in this
1420  // case.
1421  // The original cron item, versus the updated cron item (which is stored
1422  // on the finalReceipt item just below here.)
1423  //
1424  pTransaction->SetReferenceString(strOrigCronItem);
1425 
1426  // Normally in the Inbox, the "Closing Num" is set to the closing
1427  // number, in reference to the opening number. (on a finalReceipt)
1428  // But in the NYMBOX, we are sending the Opening Number in that spot.
1429  // The purpose is so the client side will know not to use that
1430  // opening number as a valid transaction # in its transaction statements
1431  // and balance statements, since the number is now gone.
1432  // Otherwise the Nym wouldn't know any better, and he'd keep signing for
1433  // it, and therefore his balance agreements would start to fail.
1434 
1435  pTransaction->SetClosingNum(lOpeningNumber); // This transaction is the
1436  // finalReceipt for
1437  // GetTransactionNum().
1438  // (Which is also the
1439  // original transaction
1440  // number.)
1441 
1442  // The finalReceipt ITEM's NOTE contains the UPDATED CRON ITEM.
1443  //
1444  if (nullptr != pstrNote) {
1445  pItem1->SetNote(*pstrNote); // in markets, this is updated trade.
1446  }
1447 
1448  // Also set the ** UPDATED OFFER ** as the ATTACHMENT on the ** item.**
1449  // (With the SERVER's signature on it!) // in markets, this is updated
1450  // offer.
1451  //
1452  if (nullptr != pstrAttachment) {
1453  pItem1->SetAttachment(*pstrAttachment);
1454  }
1455 
1456  // sign the item
1457 
1458  pItem1->SignContract(*pServerNym);
1459  pItem1->SaveContract();
1460 
1461  // the Transaction "owns" the item now and will handle cleaning it up.
1462  pTransaction->AddItem(*pItem1);
1463 
1464  pTransaction->SignContract(*pServerNym);
1465  pTransaction->SaveContract();
1466 
1467  // Here the transaction we just created is actually added to the ledger.
1468  theLedger.AddTransaction(*pTransaction);
1469 
1470  // Release any signatures that were there before (They won't
1471  // verify anymore anyway, since the content has changed.)
1472  theLedger.ReleaseSignatures();
1473 
1474  // Sign and save.
1475  theLedger.SignContract(*pServerNym);
1476  theLedger.SaveContract();
1477 
1478  // TODO: Better rollback capabilities in case of failures here:
1479 
1480  OTIdentifier theNymboxHash;
1481 
1482  // Save nymbox to storage. (File, DB, wherever it goes.)
1483  theLedger.SaveNymbox(&theNymboxHash);
1484 
1485  // This corresponds to the AddTransaction() call just above.
1486  // These are stored in a separate file now.
1487  //
1488  pTransaction->SaveBoxReceipt(theLedger);
1489 
1490  // Update the NymboxHash (in the nymfile.)
1491  //
1492 
1493  const OTIdentifier ACTUAL_NYM_ID = USER_ID;
1494  OTPseudonym theActualNym; // unused unless it's really not already
1495  // loaded. (use pActualNym.)
1496 
1497  // We couldn't find the Nym among those already loaded--so we have to
1498  // load
1499  // it ourselves (so we can update its NymboxHash value.)
1500 
1501  if (nullptr == pActualNym) {
1502  if ((nullptr != pServerNym) && pServerNym->CompareID(ACTUAL_NYM_ID))
1503  pActualNym = pServerNym;
1504 
1505  else {
1506  theActualNym.SetIdentifier(ACTUAL_NYM_ID);
1507 
1508  if (!theActualNym.LoadPublicKey()) // Note: this step
1509  // may be unnecessary
1510  // since we are only
1511  // updating his
1512  // Nymfile, not his
1513  // key.
1514  {
1515  OTString strNymID(ACTUAL_NYM_ID);
1516  otErr << szFunc << ": Failure loading public key for Nym: "
1517  << strNymID << ". "
1518  "(To update his NymboxHash.) \n";
1519  }
1520  else if (theActualNym.VerifyPseudonym() && // this line may be
1521  // unnecessary.
1522  theActualNym.LoadSignedNymfile(
1523  *pServerNym)) // ServerNym here is not
1524  // theActualNym's identity, but
1525  // merely the signer on this file.
1526  {
1527  otLog3 << szFunc << ": Loading actual Nym, since he wasn't "
1528  "already loaded. "
1529  "(To update his NymboxHash.)\n";
1530  pActualNym = &theActualNym; // <=====
1531  }
1532  else {
1533  OTString strNymID(ACTUAL_NYM_ID);
1534  otErr << szFunc << ": Failure loading or verifying Actual "
1535  "Nym public key: " << strNymID
1536  << ". "
1537  "(To update his NymboxHash.)\n";
1538  }
1539  }
1540  }
1541 
1542  // By this point we've made every possible effort to get the proper Nym
1543  // loaded,
1544  // so that we can update his NymboxHash appropriately.
1545  //
1546  if (nullptr != pActualNym) {
1547  pActualNym->SetNymboxHashServerSide(theNymboxHash);
1548  pActualNym->SaveSignedNymfile(*pServerNym);
1549  }
1550 
1551  // Really this true should be predicated on ALL the above functions
1552  // returning true.
1553  // Right?
1554  //
1555  return true;
1556  }
1557  else
1558  otErr << szFunc << ": Failed trying to create finalReceipt.\n";
1559 
1560  return false; // unreachable.
1561 }
1562 
1564 {
1565  return GetTransactionNum();
1566 }
1567 
1569 {
1571  : 0; // todo stop hardcoding.
1572 }
1573 
1574 bool OTCronItem::IsValidOpeningNumber(const int64_t& lOpeningNum) const
1575 {
1576  if (GetOpeningNum() == lOpeningNum) return true;
1577 
1578  return false;
1579 }
1580 
1581 int64_t OTCronItem::GetOpeningNumber(const OTIdentifier& theNymID) const
1582 {
1583  const OTIdentifier& theSenderNymID = GetSenderUserID();
1584 
1585  if (theNymID == theSenderNymID) return GetOpeningNum();
1586 
1587  return 0;
1588 }
1589 
1590 int64_t OTCronItem::GetClosingNumber(const OTIdentifier& theAcctID) const
1591 {
1592  const OTIdentifier& theSenderAcctID = GetSenderAcctID();
1593 
1594  if (theAcctID == theSenderAcctID) return GetClosingNum();
1595 
1596  return 0;
1597 }
1598 
1599 // You usually wouldn't want to use this, since if the transaction failed, the
1600 // opening number
1601 // is already burned and gone. But there might be cases where it's not, and you
1602 // want to retrieve it.
1603 // So I added this function for those cases. In most cases, you will prefer
1604 // HarvestClosingNumbers().
1605 //
1606 // client-side
1607 //
1609 {
1610  // The Nym is the original sender. (If Compares true).
1611  // IN CASES where GetTransactionNum() isn't already burned, we can harvest
1612  // it here.
1613  // Subclasses will have to override this function for recipients, etc.
1614  //
1615  if (theNym.CompareID(GetSenderUserID())) {
1616  // This function will only "add it back" if it was really there in the
1617  // first place.
1618  // (Verifies it is on issued list first, before adding to available
1619  // list.)
1620  //
1622  true); // bSave=true
1623  }
1624 
1625  // NOTE: if the message failed (transaction never actually ran) then the
1626  // sender AND recipient
1627  // can both reclaim their opening numbers. But if the message SUCCEEDED and
1628  // the transaction FAILED,
1629  // then only the recipient can claim his opening number -- the sender's is
1630  // already burned. So then,
1631  // what if you mistakenly call this function and pass the sender, when that
1632  // number is already burned?
1633  // There's nothing this function can do, because we have no way of telling,
1634  // from inside here,
1635  // whether the message succeeded or not, and whether the transaction
1636  // succeeded or not. Therefore
1637  // we MUST rely on the CALLER to know this, and to avoid calling this
1638  // function in the first place,
1639  // if he's sitting on a sender with a failed transaction.
1640 }
1641 
1642 // This is a good default implementation.
1643 // Also, some subclasses override this, but they STILL CALL IT.
1644 //
1646 {
1647  // The Nym is the original sender. (If Compares true).
1648  // GetTransactionNum() is usually already burned, but we can harvest the
1649  // closing
1650  // numbers from the "Closing" list, which is only for the sender's numbers.
1651  // Subclasses will have to override this function for recipients, etc.
1652  //
1653  if (theNym.CompareID(GetSenderUserID())) {
1654  for (int32_t i = 0; i < GetCountClosingNumbers(); i++) {
1655  // This function will only "add it back" if it was really there in
1656  // the first place.
1657  // (Verifies it is on issued list first, before adding to available
1658  // list.)
1659  //
1660  const bool bClawedBack = theNym.ClawbackTransactionNumber(
1662  (i == (GetCountClosingNumbers() - 1)
1663  ? true
1664  : false)); // bSave=true only on the last iteration.
1665  if (!bClawedBack) {
1666  // otErr << "OTCronItem::HarvestClosingNumbers:
1667  // Number (%lld) failed as issued. (Thus didn't bother 'adding
1668  // it back'.)\n",
1669  // GetClosingTransactionNoAt(i));
1670  }
1671  }
1672  }
1673 }
1674 
1676  : ot_super()
1677  , m_pCron(nullptr)
1678  , serverNym_(nullptr)
1679  , serverId_(nullptr)
1680  , m_CREATION_DATE(OT_TIME_ZERO)
1681  , m_LAST_PROCESS_DATE(OT_TIME_ZERO)
1682  , m_PROCESS_INTERVAL(1)
1683  , // Default for any cron item is to execute once per second.
1684  m_pCancelerNymID(new OTIdentifier)
1685  , m_bCanceled(false)
1686  , m_bRemovalFlag(false)
1687 {
1688  InitCronItem();
1689 }
1690 
1692  const OTIdentifier& ASSET_ID)
1693  : ot_super(SERVER_ID, ASSET_ID)
1694  , m_pCron(nullptr)
1695  , serverNym_(nullptr)
1696  , serverId_(nullptr)
1697  , m_CREATION_DATE(OT_TIME_ZERO)
1698  , m_LAST_PROCESS_DATE(OT_TIME_ZERO)
1699  , m_PROCESS_INTERVAL(1)
1700  , // Default for any cron item is to execute once per second.
1701  m_pCancelerNymID(new OTIdentifier)
1702  , m_bCanceled(false)
1703  , m_bRemovalFlag(false)
1704 {
1705  InitCronItem();
1706 }
1707 
1709  const OTIdentifier& ASSET_ID,
1710  const OTIdentifier& ACCT_ID, const OTIdentifier& USER_ID)
1711  : ot_super(SERVER_ID, ASSET_ID, ACCT_ID, USER_ID)
1712  , m_pCron(nullptr)
1713  , serverNym_(nullptr)
1714  , serverId_(nullptr)
1715  , m_CREATION_DATE(OT_TIME_ZERO)
1716  , m_LAST_PROCESS_DATE(OT_TIME_ZERO)
1717  , m_PROCESS_INTERVAL(1)
1718  , // Default for any cron item is to execute once per second.
1719  m_pCancelerNymID(new OTIdentifier)
1720  , m_bCanceled(false)
1721  , m_bRemovalFlag(false)
1722 
1723 {
1724  InitCronItem();
1725 }
1726 
1728 {
1729  if (!IsCanceled()) {
1730  theOutput.Release();
1731  return false;
1732  }
1733 
1734  theOutput = *m_pCancelerNymID;
1735  return true;
1736 }
1737 
1738 // When canceling a cron item before it has been activated, use this.
1739 //
1741 {
1742  OT_ASSERT(nullptr != m_pCancelerNymID);
1743 
1744  if (IsCanceled()) return false;
1745 
1746  m_bCanceled = true;
1747  *m_pCancelerNymID = theCancelerNym.GetConstID();
1748 
1750  SignContract(theCancelerNym);
1751  SaveContract();
1752 
1753  return true;
1754 }
1755 
1757 {
1758  m_strContractType.Set("CRONITEM"); // in practice should never appear. Child
1759  // classes will overwrite.
1760 }
1761 
1763 {
1764  m_dequeClosingNumbers.clear();
1765 }
1766 
1768 {
1769  Release_CronItem();
1770 
1771  // If there were any dynamically allocated objects, clean them up here.
1772  //
1773  if (nullptr != m_pCancelerNymID) delete m_pCancelerNymID;
1774  m_pCancelerNymID = nullptr;
1775 }
1776 
1778 {
1779  m_CREATION_DATE = OT_TIME_ZERO;
1780  m_LAST_PROCESS_DATE = OT_TIME_ZERO;
1781  m_PROCESS_INTERVAL = 1;
1782 
1784 
1785  m_bRemovalFlag = false;
1786  m_bCanceled = false;
1788 }
1789 
1791 {
1792  Release_CronItem();
1793 
1794  ot_super::Release(); // since I've overridden the base class, I call it
1795  // now...
1796 }
1797 
1798 // return -1 if error, 0 if nothing, and 1 if the node was processed.
1800 {
1801  int32_t nReturnVal = 0;
1802 
1803  // Here we call the parent class first.
1804  // If the node is found there, or there is some error,
1805  // then we just return either way. But if it comes back
1806  // as '0', then nothing happened, and we'll continue executing.
1807  //
1808  // -- Note you can choose not to call the parent if
1809  // you don't want to use any of those xml tags.
1810  //
1811 
1812  nReturnVal = ot_super::ProcessXMLNode(xml);
1813 
1814  if (nReturnVal !=
1815  0) // -1 is error, and 1 is "found it". Either way, return.
1816  return nReturnVal; // 0 means "nothing happened, keep going."
1817 
1818  const OTString strNodeName(xml->getNodeName());
1819 
1820  if (strNodeName.Compare("closingTransactionNumber")) {
1821  OTString strClosingNumber = xml->getAttributeValue("value");
1822 
1823  if (strClosingNumber.Exists()) {
1824  const int64_t lClosingNumber = atol(strClosingNumber.Get());
1825 
1826  AddClosingTransactionNo(lClosingNumber);
1827  }
1828  else {
1829  otErr << "Error in OTCronItem::ProcessXMLNode: "
1830  "closingTransactionNumber field without value.\n";
1831  return (-1); // error condition
1832  }
1833 
1834  nReturnVal = 1;
1835  }
1836 
1837  return nReturnVal;
1838 }
1839 
1840 } // namespace opentxs
EXPORT bool StorePlainString(std::string strContents, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:698
virtual int64_t GetOpeningNumber(const OTIdentifier &theNymID) const
static EXPORT OTTransaction * GenerateTransaction(const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, transactionType theType, int64_t lTransactionNum=0)
EXPORT void SetNumberOfOrigin(int64_t lTransactionNum)
EXPORT bool IsCanceled() const
Definition: OTCronItem.hpp:324
const OTIdentifier & GetSenderUserID() const
EXPORT bool ClawbackTransactionNumber(const OTIdentifier &theServerID, const int64_t &lTransClawback, bool bSave=false, OTPseudonym *pSIGNER_NYM=nullptr)
EXPORT bool SaveCronReceipt()
Definition: OTCronItem.cpp:577
virtual void HarvestClosingNumbers(OTPseudonym &theNym)
void SetValidFrom(time64_t TIME_FROM)
virtual EXPORT bool VerifyAccount(const OTPseudonym &theNym)
Definition: OTLedger.cpp:187
int64_t GetTransactionNum() const
virtual bool IsValidOpeningNumber(const int64_t &lOpeningNum) const
EXPORT void Release()
Definition: OTNumList.cpp:465
virtual void HarvestOpeningNumber(OTPseudonym &theNym)
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
EXPORT bool SaveActiveCronReceipt(const OTIdentifier &theNymID)
Definition: OTCronItem.cpp:453
EXPORT bool SaveContract()
EXPORT bool VerifyIssuedNum(const OTString &strServerID, const int64_t &lTransNum) const
EXPORT bool Remove(const int64_t &theValue)
Definition: OTNumList.cpp:309
void HookRemovalFromCron(OTPseudonym *pRemover, int64_t newTransactionNo)
Definition: OTCronItem.cpp:815
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
EXPORT bool LoadInbox()
Definition: OTLedger.cpp:463
static EXPORT OTCronItem * LoadCronReceipt(const int64_t &lTransactionNum)
Definition: OTCronItem.cpp:227
bool IsFlaggedForRemoval() const
Definition: OTCronItem.hpp:238
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
EXPORT bool AddTransaction(OTTransaction &theTransaction)
Definition: OTLedger.cpp:1194
OTLOG_IMPORT OTLogStream otOut
virtual bool CanRemoveItemFromCron(OTPseudonym &theNym)
Definition: OTCronItem.cpp:700
EXPORT bool IsExpired()
OTLOG_IMPORT OTLogStream otLog3
EXPORT void SetAttachment(const OTString &theStr)
Definition: OTItem.cpp:1402
virtual void onFinalReceipt(OTCronItem &theOrigCronItem, const int64_t &lNewTransactionNumber, OTPseudonym &theOriginator, OTPseudonym *pRemover)
Definition: OTCronItem.cpp:993
EXPORT uint32_t GetLength() const
Definition: OTString.cpp:1040
void SetValidTo(time64_t TIME_TO)
EXPORT bool LoadSignedNymfile(OTPseudonym &SIGNER_NYM)
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
int64_t time64_t
Definition: Common.hpp:209
EXPORT void SetNymboxHashServerSide(const OTIdentifier &theInput)
EXPORT bool WriteArmoredString(OTString &strOutput, const std::string str_type, bool bEscaped=false) const
void SetCreationDate(const time64_t &CREATION_DATE)
Definition: OTCronItem.hpp:264
EXPORT bool LoadNymbox()
Definition: OTLedger.cpp:482
EXPORT int64_t GetClosingTransactionNoAt(uint32_t nIndex) const
Definition: OTCronItem.cpp:681
EXPORT bool VerifyPseudonym() const
static EXPORT OTItem * CreateItemFromTransaction(const OTTransaction &theOwner, OTItem::itemType theType, const OTIdentifier *pDestinationAcctID=nullptr)
Definition: OTItem.cpp:1451
EXPORT bool DecodeIfArmored(bool escapedIsAllowed=true)
Definition: OTString.cpp:1212
EXPORT void ReleaseSignatures()
Definition: OTContract.cpp:989
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT void SetIdentifier(const OTIdentifier &theIdentifier)
const OTIdentifier & GetServerID() const
EXPORT void Format(const char *fmt,...)
Definition: OTString.cpp:1319
void SetStatus(const OTItem::itemStatus &theVal)
Definition: OTItem.hpp:463
EXPORT bool LoadPublicKey()
EXPORT void SetReferenceString(const OTString &theStr)
bool DropFinalReceiptToInbox(const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID, const int64_t &lNewTransactionNumber, const int64_t &lClosingNumber, const OTString &strOrigCronItem, OTString *pstrNote=nullptr, OTString *pstrAttachment=nullptr, OTAccount *pActualAcct=nullptr)
EXPORT int32_t GetCountClosingNumbers() const
Definition: OTCronItem.cpp:676
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
Definition: OTString.cpp:1055
time64_t OTTimeGetCurrentTime()
Definition: Common.hpp:211
virtual bool ProcessCron()
Definition: OTCronItem.cpp:769
EXPORT void SetClosingNum(int64_t lClosingNum)
EXPORT bool GetCancelerID(OTIdentifier &theOutput) const
EXPORT std::string QueryPlainString(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:728
EXPORT bool Output(std::set< int64_t > &theOutput) const
Definition: OTNumList.cpp:430
EXPORT bool RemoveIssuedNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, const int64_t &lTransNum, bool bSave)
bool sgets(char *buffer, uint32_t size)
Definition: OTString.cpp:1380
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT bool SetDateRange(time64_t VALID_FROM=OT_TIME_ZERO, time64_t VALID_TO=OT_TIME_ZERO)
Definition: OTCronItem.cpp:619
OTString m_strContractType
Definition: OTContract.hpp:178
EXPORT bool EraseValueByKey(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:843
OTLOG_IMPORT OTLogStream otInfo
EXPORT bool CompareID(const OTIdentifier &theIdentifier) const
EXPORT int32_t Count() const
Definition: OTNumList.cpp:460
static EXPORT bool EraseActiveCronReceipt(const int64_t &lTransactionNum, const OTIdentifier &nymID, const OTIdentifier &serverID)
Definition: OTCronItem.cpp:344
static EXPORT bool GetActiveCronTransNums(OTNumList &output, const OTIdentifier &nymID, const OTIdentifier &serverID)
Definition: OTCronItem.cpp:303
#define OT_FAIL
Definition: Assert.hpp:139
EXPORT bool CancelBeforeActivation(OTPseudonym &theCancelerNym)
EXPORT bool SaveNymbox(OTIdentifier *pNymboxHash=nullptr)
Definition: OTLedger.cpp:801
EXPORT int64_t GetClosingNum() const
static EXPORT OTCronItem * LoadActiveCronReceipt(const int64_t &lTransactionNum, const OTIdentifier &serverID)
Definition: OTCronItem.cpp:262
EXPORT void SetNote(const OTString &theStr)
Definition: OTItem.cpp:1413
EXPORT int64_t GetOpeningNum() const
EXPORT bool SaveBoxReceipt(int64_t lLedgerType)
EXPORT const char * Get() const
Definition: OTString.cpp:1045
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
Definition: OTContract.cpp:484
EXPORT bool SaveInbox(OTLedger &box, OTIdentifier *hash=nullptr)
Definition: OTAccount.cpp:260
OTLOG_IMPORT OTLogStream otErr
const OTIdentifier & GetPurportedAccountID() const
virtual bool VerifyAccount(const OTPseudonym &theNym)
EXPORT void SetReferenceToNum(int64_t lTransactionNum)
OTIdentifier * m_pCancelerNymID
Definition: OTCronItem.hpp:177
EXPORT const OTIdentifier & GetConstID() const
virtual EXPORT bool VerifySignature(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
Definition: OTContract.cpp:818
const OTIdentifier & GetSenderAcctID() const
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
static EXPORT const OTString & Cron()
Definition: OTFolders.cpp:311
EXPORT bool Contains(const char *compare) const
Definition: OTString.cpp:1137
std::set< int64_t > & GetSetOpenCronItems()
bool DropFinalReceiptToNymbox(const OTIdentifier &USER_ID, const int64_t &lNewTransactionNumber, const OTString &strOrigCronItem, OTString *pstrNote=nullptr, OTString *pstrAttachment=nullptr, OTPseudonym *pActualNym=nullptr)
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
EXPORT void AddClosingTransactionNo(const int64_t &lClosingTransactionNo)
Definition: OTCronItem.cpp:693
std::deque< int64_t > m_dequeClosingNumbers
Definition: OTCronItem.hpp:169
#define OT_TIME_ZERO
Definition: Common.hpp:180
virtual EXPORT void Release()
Definition: OTData.cpp:257
EXPORT bool SaveAccount()
Definition: OTAccount.cpp:379
virtual int64_t GetClosingNumber(const OTIdentifier &theAcctID) const
static EXPORT OTAccount * LoadExistingAccount(const OTIdentifier &accountId, const OTIdentifier &serverId)
Definition: OTAccount.cpp:480
void HookActivationOnCron(OTPseudonym *pActivator, bool bForTheFirstTime=false)
Definition: OTCronItem.cpp:797
virtual EXPORT void Release()
Definition: OTString.cpp:765
virtual void Release()
virtual void Release()
static EXPORT OTCronItem * NewCronItem(const OTString &strCronItem)
Definition: OTCronItem.cpp:165
EXPORT void AddItem(OTItem &theItem)
EXPORT bool SaveSignedNymfile(OTPseudonym &SIGNER_NYM)
virtual void onRemovalFromCron()
Definition: OTCronItem.hpp:199
virtual void onActivate()
Definition: OTCronItem.hpp:190
OTLOG_IMPORT OTLogStream otLog5
EXPORT bool SaveInbox(OTIdentifier *pInboxHash=nullptr)
Definition: OTLedger.cpp:836