Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTAgreement.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTAgreement.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 "recurring/OTAgreement.hpp"
136 #include "cron/OTCron.hpp"
137 
138 #include "OTAccount.hpp"
139 #include "OTLedger.hpp"
140 #include "OTLog.hpp"
141 #include "OTPseudonym.hpp"
142 
143 #include <irrxml/irrXML.hpp>
144 
145 // OTAgreement is derived from OTCronItem. It handles re-occuring billing.
146 
147 namespace opentxs
148 {
149 
151  bool bSuccessMsg, OTPseudonym& theServerNym,
152  const OTIdentifier& theServerID, const int64_t& lNewTransactionNumber,
153  // const int64_t& lInReferenceTo,
154  // // Each party has its own opening trans #.
155  const OTString& strReference, OTString* pstrNote, OTString* pstrAttachment,
156  OTPseudonym* pActualNym) const
157 {
158  bool bSuccess =
159  true; // Success is defined as ALL parties receiving a notice
160 
161  OTPseudonym theRecipientNym; // Don't use this... use the pointer just
162  // below.
163  OTPseudonym* pRecipient = nullptr;
164 
165  if (theServerNym.CompareID(GetRecipientUserID())) {
166  pRecipient = &theServerNym; // Just in case the recipient Nym is also
167  // the server Nym.
168  }
169  else if ((nullptr != pActualNym) &&
170  pActualNym->CompareID(GetRecipientUserID())) {
171  pRecipient = pActualNym;
172  }
173 
174  if (nullptr == pRecipient) {
175  const OTIdentifier NYM_ID(GetRecipientUserID());
176  theRecipientNym.SetIdentifier(NYM_ID);
177 
178  if (!theRecipientNym.LoadPublicKey()) {
179  const OTString strNymID(NYM_ID);
180  otErr << __FUNCTION__
181  << ": Failure loading Recipient's public key: " << strNymID
182  << "\n";
183  return false;
184  }
185  else if (theRecipientNym.VerifyPseudonym() &&
186  theRecipientNym.LoadSignedNymfile(
187  theServerNym)) // ServerNym here is merely the signer on
188  // this file.
189  {
190  pRecipient = &theRecipientNym; // <=====
191  }
192  else {
193  const OTString strNymID(NYM_ID);
194  otErr << __FUNCTION__
195  << ": Failure verifying Recipient's public key or loading "
196  "signed nymfile: " << strNymID << "\n";
197  return false;
198  }
199  }
200  // BY THIS POINT, the Recipient Nym is definitely loaded up and we have
201  // a pointer to him (pRecipient.)
202 
203  OTPseudonym theSenderNym; // Don't use this... use the pointer just below.
204  OTPseudonym* pSender = nullptr;
205 
206  if (theServerNym.CompareID(GetSenderUserID())) {
207  pSender = &theServerNym; // Just in case the Sender Nym is also the
208  // server Nym.
209  }
210  else if ((nullptr != pActualNym) &&
211  pActualNym->CompareID(GetSenderUserID())) {
212  pSender = pActualNym;
213  }
214 
215  if (nullptr == pSender) {
216  const OTIdentifier NYM_ID(GetSenderUserID());
217  theSenderNym.SetIdentifier(NYM_ID);
218 
219  if (!theSenderNym.LoadPublicKey()) {
220  const OTString strNymID(NYM_ID);
221  otErr << __FUNCTION__
222  << ": Failure loading Sender's public key: " << strNymID
223  << "\n";
224  return false;
225  }
226  else if (theSenderNym.VerifyPseudonym() &&
227  theSenderNym.LoadSignedNymfile(theServerNym)) // ServerNym
228  // here is
229  // merely the
230  // signer on
231  // this file.
232  {
233  pSender = &theSenderNym; // <=====
234  }
235  else {
236  const OTString strNymID(NYM_ID);
237  otErr << __FUNCTION__ << ": Failure verifying Sender's public key "
238  "or loading signed nymfile: " << strNymID
239  << "\n";
240  return false;
241  }
242  }
243  // BY THIS POINT, the Sender Nym is definitely loaded up and we have
244  // a pointer to him (pSender.)
245 
246  // (pRecipient and pSender are both good pointers by this point.)
247 
248  // Sender
250  bSuccessMsg, // "success" notice? or "failure" notice?
251  theServerNym, theServerID, GetSenderUserID(), lNewTransactionNumber,
252  GetTransactionNum(), // in reference to
253  strReference, pstrNote, pstrAttachment, pSender))
254  bSuccess = false;
255  // Notice I don't break here -- I still allow it to try to notice ALL
256  // parties, even if one fails.
257 
258  // Recipient
260  bSuccessMsg, // "success" notice? or "failure" notice?
261  theServerNym, theServerID, GetRecipientUserID(),
262  lNewTransactionNumber,
263  GetRecipientOpeningNum(), // in reference to
264  strReference, pstrNote, pstrAttachment, pRecipient))
265  bSuccess = false;
266 
267  return bSuccess;
268 }
269 
270 // static
272  bool bSuccessMsg, // Nym receives an OTItem::acknowledgment or
273  // OTItem::rejection.
274  OTPseudonym& theServerNym, const OTIdentifier& SERVER_ID,
275  const OTIdentifier& USER_ID, const int64_t& lNewTransactionNumber,
276  const int64_t& lInReferenceTo, const OTString& strReference,
277  OTString* pstrNote, OTString* pstrAttachment, OTPseudonym* pActualNym)
278 {
279  OTLedger theLedger(USER_ID, USER_ID, SERVER_ID);
280 
281  // Inbox will receive notification of something ALREADY DONE.
282  //
283  bool bSuccessLoading = theLedger.LoadNymbox();
284 
285  if (true == bSuccessLoading)
286  bSuccessLoading = theLedger.VerifyAccount(theServerNym);
287  else
288  bSuccessLoading = theLedger.GenerateLedger(
289  USER_ID, SERVER_ID, OTLedger::nymbox, true); // bGenerateFile=true
290 
291  if (!bSuccessLoading) {
292  otErr << __FUNCTION__ << ": Failed loading or generating a nymbox. "
293  "(FAILED WRITING RECEIPT!!) \n";
294  return false;
295  }
296 
298  theLedger, OTTransaction::notice, lNewTransactionNumber);
299 
300  if (nullptr !=
301  pTransaction) // The above has an OT_ASSERT within, but I just
302  // like to check my pointers.
303  {
304  // The nymbox will get a receipt with the new transaction ID.
305  // That receipt has an "in reference to" field containing the original
306  // OTScriptable
307 
308  // Set up the transaction items (each transaction may have multiple
309  // items... but not in this case.)
310  //
311  OTItem* pItem1 =
313  OT_ASSERT(nullptr != pItem1); // This may be unnecessary, I'll have to
314  // check CreateItemFromTransaction. I'll
315  // leave it for now.
316 
317  pItem1->SetStatus(
318  bSuccessMsg ? OTItem::acknowledgement
319  : OTItem::rejection); // ACKNOWLEDGMENT or REJECTION ?
320 
321  //
322  // Here I make sure that the receipt (the nymbox notice) references the
323  // transaction number that the trader originally used to issue the cron
324  // item...
325  // This number is used to match up offers to trades, and used to track
326  // all cron items.
327  // (All Cron items require a transaction from the user to add them to
328  // Cron in the
329  // first place.)
330  //
331  pTransaction->SetReferenceToNum(lInReferenceTo);
332 
333  // The reference on the transaction probably contains a the original
334  // cron item or entity contract.
335  // Versus the updated item (which, if it exists, is stored on the pItem1
336  // just below.)
337  //
338  pTransaction->SetReferenceString(strReference);
339 
340  // The notice ITEM's NOTE probably contains the UPDATED SCRIPTABLE
341  // (usually a CRON ITEM. But maybe soon: Entity.)
342  if (nullptr != pstrNote) {
343  pItem1->SetNote(*pstrNote); // in markets, this is updated trade.
344  }
345 
346  // Nothing is special stored here so far for OTTransaction::notice, but
347  // the option is always there.
348  //
349  if (nullptr != pstrAttachment) {
350  pItem1->SetAttachment(*pstrAttachment);
351  }
352 
353  // sign the item
354  //
355  pItem1->SignContract(theServerNym);
356  pItem1->SaveContract();
357 
358  // the Transaction "owns" the item now and will handle cleaning it up.
359  pTransaction->AddItem(*pItem1);
360 
361  pTransaction->SignContract(theServerNym);
362  pTransaction->SaveContract();
363 
364  // Here the transaction we just created is actually added to the ledger.
365  theLedger.AddTransaction(*pTransaction);
366 
367  // Release any signatures that were there before (They won't
368  // verify anymore anyway, since the content has changed.)
369  theLedger.ReleaseSignatures();
370 
371  // Sign and save.
372  theLedger.SignContract(theServerNym);
373  theLedger.SaveContract();
374 
375  // TODO: Better rollback capabilities in case of failures here:
376 
377  OTIdentifier theNymboxHash;
378 
379  // Save nymbox to storage. (File, DB, wherever it goes.)
380  theLedger.SaveNymbox(&theNymboxHash);
381 
382  // Corresponds to the AddTransaction() call just above. These
383  // are stored in a separate file now.
384  //
385  pTransaction->SaveBoxReceipt(theLedger);
386 
387  // Update the NymboxHash (in the nymfile.)
388  //
389  const OTIdentifier ACTUAL_NYM_ID = USER_ID;
390  OTPseudonym theActualNym; // unused unless it's really not already
391  // loaded. (use pActualNym.)
392 
393  // We couldn't find the Nym among those already loaded--so we have to
394  // load
395  // it ourselves (so we can update its NymboxHash value.)
396 
397  if (nullptr == pActualNym) {
398  if (theServerNym.CompareID(ACTUAL_NYM_ID))
399  pActualNym = &theServerNym;
400 
401  else {
402  theActualNym.SetIdentifier(ACTUAL_NYM_ID);
403 
404  if (!theActualNym.LoadPublicKey()) // Note: this step
405  // may be unnecessary
406  // since we are only
407  // updating his
408  // Nymfile, not his
409  // key.
410  {
411  OTString strNymID(ACTUAL_NYM_ID);
412  otErr << __FUNCTION__
413  << ": Failure loading public key for Nym: "
414  << strNymID << ". "
415  "(To update his NymboxHash.) \n";
416  }
417  else if (theActualNym.VerifyPseudonym() && // this line may be
418  // unnecessary.
419  theActualNym.LoadSignedNymfile(
420  theServerNym)) // ServerNym here is not
421  // theActualNym's identity, but
422  // merely the signer on this file.
423  {
424  otLog3 << __FUNCTION__ << ": Loading actual Nym, since he "
425  "wasn't already loaded. (To "
426  "update his NymboxHash.)\n";
427  pActualNym = &theActualNym; // <=====
428  }
429  else {
430  OTString strNymID(ACTUAL_NYM_ID);
431  otErr << __FUNCTION__
432  << ": Failure loading or verifying Actual Nym public "
433  "key: " << strNymID
434  << ". "
435  "(To update his NymboxHash.)\n";
436  }
437  }
438  }
439 
440  // By this point we've made every possible effort to get the proper Nym
441  // loaded,
442  // so that we can update his NymboxHash appropriately.
443  //
444  if (nullptr != pActualNym) {
445  pActualNym->SetNymboxHashServerSide(theNymboxHash);
446  pActualNym->SaveSignedNymfile(theServerNym);
447  }
448 
449  // Really this true should be predicated on ALL the above functions
450  // returning true.
451  // Right?
452  //
453  return true; // Really this true should be predicated on ALL the above
454  // functions returning true. Right?
455  }
456  else
457  otErr << __FUNCTION__ << ": Failed trying to create Nymbox.\n";
458 
459  return false; // unreachable.
460 }
461 
462 // Overrides from OTTrackable.
463 bool OTAgreement::HasTransactionNum(const int64_t& lInput) const
464 {
465  if (lInput == GetTransactionNum()) return true;
466 
467  const size_t nSizeClosing = m_dequeClosingNumbers.size();
468 
469  for (size_t nIndex = 0; nIndex < nSizeClosing; ++nIndex) {
470  if (lInput == m_dequeClosingNumbers.at(nIndex)) return true;
471  }
472 
473  const size_t nSizeRecipient = m_dequeRecipientClosingNumbers.size();
474 
475  for (size_t nIndex = 0; nIndex < nSizeRecipient; ++nIndex) {
476  if (lInput == m_dequeRecipientClosingNumbers.at(nIndex)) return true;
477  }
478 
479  return false;
480 }
481 
483 {
484 
485  if (GetTransactionNum() > 0) numlistOutput.Add(GetTransactionNum());
486 
487  const size_t nSizeClosing = m_dequeClosingNumbers.size();
488 
489  for (size_t nIndex = 0; nIndex < nSizeClosing; ++nIndex) {
490  const int64_t lTemp = m_dequeClosingNumbers.at(nIndex);
491  if (lTemp > 0) numlistOutput.Add(lTemp);
492  }
493 
494  const size_t nSizeRecipient = m_dequeRecipientClosingNumbers.size();
495 
496  for (size_t nIndex = 0; nIndex < nSizeRecipient; ++nIndex) {
497  const int64_t lTemp = m_dequeRecipientClosingNumbers.at(nIndex);
498  if (lTemp > 0) numlistOutput.Add(lTemp);
499  }
500 }
501 
502 // Used to be I could just call pAgreement->VerifySignature(theNym), which is
503 // what
504 // I still call here, inside this function. But that's a special case -- an
505 // override
506 // from the OTScriptable / OTSmartContract version, which verifies parties and
507 // agents, etc.
508 //
510  OTPseudonym&, // Not needed in this override.
511  mapOfNyms*) const
512 {
513  return VerifySignature(theNym);
514 }
515 
516 // This is an override. See note above.
517 //
519  OTAccount& theAccount) const
520 {
521  return theAccount.VerifyOwner(theNym);
522 }
523 
524 // This is called by OTCronItem::HookRemovalFromCron
525 // (After calling this method, HookRemovalFromCron then calls
526 // onRemovalFromCron.)
527 //
529  const int64_t& lNewTransactionNumber,
530  OTPseudonym& theOriginator,
531  OTPseudonym* pRemover)
532 {
533 
534  OTCron* pCron = GetCron();
535  OT_ASSERT(nullptr != pCron);
536 
537  OTPseudonym* pServerNym = pCron->GetServerNym();
538  OT_ASSERT(nullptr != pServerNym);
539 
540  const char* szFunc = "OTAgreement::onFinalReceipt";
541 
542  // The finalReceipt Item's ATTACHMENT contains the UPDATED Cron Item.
543  // (With the SERVER's signature on it!)
544  //
545  OTString strUpdatedCronItem(*this);
546  OTString* pstrAttachment = &strUpdatedCronItem;
547 
548  const OTString strOrigCronItem(theOrigCronItem);
549 
550  OTPseudonym theRecipientNym; // Don't use this... use the pointer just
551  // below.
552 
553  // The Nym who is actively requesting to remove a cron item will be passed
554  // in as pRemover.
555  // However, sometimes there is no Nym... perhaps it just expired and
556  // pRemover is nullptr.
557  // The originating Nym (if different than remover) is loaded up. Otherwise
558  // the originator
559  // pointer just pointers to *pRemover.
560  //
561  OTPseudonym* pRecipient = nullptr;
562 
563  if (pServerNym->CompareID(GetRecipientUserID())) {
564  pRecipient = pServerNym; // Just in case the recipient Nym is also the
565  // server Nym.
566  }
567  //
568  // If pRemover is NOT nullptr, and he has the Recipient's ID...
569  // then set the pointer accordingly.
570  //
571  else if ((nullptr != pRemover) &&
572  (true == pRemover->CompareID(GetRecipientUserID()))) {
573  pRecipient = pRemover; // <======== now both pointers are set (to same
574  // Nym). DONE!
575  }
576 
577  if (nullptr == pRecipient) {
578  // GetSenderUserID() should be the same on THIS (updated version of the
579  // same cron item)
580  // but for whatever reason, I'm checking the userID on the original
581  // version. Sue me.
582  //
583  const OTIdentifier NYM_ID(GetRecipientUserID());
584 
585  theRecipientNym.SetIdentifier(NYM_ID);
586 
587  if (!theRecipientNym.LoadPublicKey()) {
588  const OTString strNymID(NYM_ID);
589  otErr << szFunc << ": Failure loading Recipient's public key:\n"
590  << strNymID << "\n";
591  }
592  else if (theRecipientNym.VerifyPseudonym() &&
593  theRecipientNym.LoadSignedNymfile(*pServerNym)) // ServerNym
594  // here is
595  // merely the
596  // signer on
597  // this file.
598  {
599  pRecipient = &theRecipientNym; // <=====
600  }
601  else {
602  const OTString strNymID(NYM_ID);
603  otErr << szFunc << ": Failure verifying Recipient's public key or "
604  "loading signed nymfile: " << strNymID << "\n";
605  }
606  }
607 
608  // First, we are closing the transaction number ITSELF, of this cron item,
609  // as an active issued number on the originating nym. (Changing it to
610  // CLOSED.)
611  //
612  // Second, we're verifying the CLOSING number, and using it as the closing
613  // number
614  // on the FINAL RECEIPT (with that receipt being "InReferenceTo"
615  // GetTransactionNum())
616  //
617  const int64_t lRecipientOpeningNumber = GetRecipientOpeningNum();
618  const int64_t lRecipientClosingNumber = GetRecipientClosingNum();
619 
620  const int64_t lSenderOpeningNumber = theOrigCronItem.GetTransactionNum();
621 
622  const int64_t lSenderClosingNumber =
623  (theOrigCronItem.GetCountClosingNumbers() > 0)
624  ? theOrigCronItem.GetClosingTransactionNoAt(0)
625  : 0; // index 0 is closing number for sender, since
626  // GetTransactionNum() is his opening #.
627 
628  const OTString strServerID(GetServerID());
629 
630  OTPseudonym theActualNym; // unused unless it's really not already loaded.
631  // (use pActualNym.)
632 
633  //
634  if ((lSenderOpeningNumber > 0) &&
635  theOriginator.VerifyIssuedNum(strServerID, lSenderOpeningNumber)) {
636 
637  OTPseudonym* pActualNym = nullptr; // use this. DON'T use theActualNym.
638 
639  // The Nym (server side) stores a list of all opening and closing cron
640  // #s.
641  // So when the number is released from the Nym, we also take it off that
642  // list.
643  //
644  std::set<int64_t>& theIDSet = theOriginator.GetSetOpenCronItems();
645  theIDSet.erase(lSenderOpeningNumber);
646 
647  // the RemoveIssued call means the original transaction# (to find this
648  // cron item on cron) is now CLOSED.
649  // But the Transaction itself is still OPEN. How? Because the CLOSING
650  // number is still signed out.
651  // The closing number is also USED, since the NotarizePaymentPlan or
652  // NotarizeMarketOffer call, but it
653  // remains ISSUED, until the final receipt itself is accepted during a
654  // process inbox.
655  //
656  theOriginator.RemoveIssuedNum(*pServerNym, strServerID,
657  lSenderOpeningNumber,
658  false); // bSave=false
659  theOriginator.SaveSignedNymfile(*pServerNym);
660 
661  const OTIdentifier& ACTUAL_NYM_ID = GetSenderUserID();
662 
663  if ((nullptr != pServerNym) && pServerNym->CompareID(ACTUAL_NYM_ID))
664  pActualNym = pServerNym;
665  else if (theOriginator.CompareID(ACTUAL_NYM_ID))
666  pActualNym = &theOriginator;
667  else if ((nullptr != pRemover) && pRemover->CompareID(ACTUAL_NYM_ID))
668  pActualNym = pRemover;
669 
670  else // We couldn't find the Nym among those already loaded--so we have
671  // to load
672  { // it ourselves (so we can update its NymboxHash value.)
673  theActualNym.SetIdentifier(ACTUAL_NYM_ID);
674 
675  if (!theActualNym.LoadPublicKey()) // Note: this step may be
676  // unnecessary since we
677  // are only updating his
678  // Nymfile, not his key.
679  {
680  OTString strNymID(ACTUAL_NYM_ID);
681  otErr << szFunc
682  << ": Failure loading public key for Nym : " << strNymID
683  << ". "
684  "(To update his NymboxHash.) \n";
685  }
686  else if (theActualNym.VerifyPseudonym() && // this line may be
687  // unnecessary.
688  theActualNym.LoadSignedNymfile(
689  *pServerNym)) // ServerNym here is not theActualNym's
690  // identity, but merely the signer on
691  // this file.
692  {
693  otLog3
694  << szFunc
695  << ": Loading actual Nym, since he wasn't already loaded. "
696  "(To update his NymboxHash.)\n";
697  pActualNym = &theActualNym; // <=====
698  }
699  else {
700  OTString strNymID(ACTUAL_NYM_ID);
701  otErr
702  << szFunc
703  << ": Failure loading or verifying Actual Nym public key: "
704  << strNymID << ". "
705  "(To update his NymboxHash.)\n";
706  }
707  }
708 
709  if (!DropFinalReceiptToNymbox(GetSenderUserID(), lNewTransactionNumber,
710  strOrigCronItem, nullptr, pstrAttachment,
711  pActualNym)) {
712  otErr << szFunc
713  << ": Failure dropping sender final receipt into nymbox.\n";
714  }
715  }
716  else {
717  otErr << szFunc << ": Failure verifying sender's opening number.\n";
718  }
719 
720  if ((lSenderClosingNumber > 0) &&
721  theOriginator.VerifyIssuedNum(strServerID, lSenderClosingNumber)) {
722  // In this case, I'm passing nullptr for pstrNote, since there is no
723  // note.
724  // (Additional information would normally be stored in the note.)
725  //
726  if (false ==
728  GetSenderUserID(), GetSenderAcctID(), lNewTransactionNumber,
729  lSenderClosingNumber, // The closing transaction number to put
730  // on the receipt.
731  strOrigCronItem, nullptr,
732  pstrAttachment)) // pActualAcct=nullptr by default. (This call
733  // will
734  // load it up and update its inbox hash.)
735  otErr << szFunc
736  << ": Failure dropping receipt into sender's inbox.\n";
737 
738  // This part below doesn't happen until theOriginator ACCEPTS the final
739  // receipt (when processing his inbox.)
740  //
741  // theOriginator.RemoveIssuedNum(strServerID, lSenderClosingNumber,
742  // true); //bSave=false
743  }
744  else {
745  otErr << szFunc
746  << ": Failed verifying "
747  "lSenderClosingNumber=theOrigCronItem."
748  "GetClosingTransactionNoAt(0)>0 && "
749  "theOriginator.VerifyTransactionNum(lSenderClosingNumber)\n";
750  }
751 
752  //
753  if ((nullptr != pRecipient) && (lRecipientOpeningNumber > 0) &&
754  pRecipient->VerifyIssuedNum(strServerID, lRecipientOpeningNumber)) {
755  // The Nym (server side) stores a list of all opening and closing cron
756  // #s.
757  // So when the number is released from the Nym, we also take it off that
758  // list.
759  //
760  std::set<int64_t>& theIDSet = pRecipient->GetSetOpenCronItems();
761  theIDSet.erase(lRecipientOpeningNumber);
762 
763  // the RemoveIssued call means the original transaction# (to find this
764  // cron item on cron) is now CLOSED.
765  // But the Transaction itself is still OPEN. How? Because the CLOSING
766  // number is still signed out.
767  // The closing number is also USED, since the NotarizePaymentPlan or
768  // NotarizeMarketOffer call, but it
769  // remains ISSUED, until the final receipt itself is accepted during a
770  // process inbox.
771  //
772  pRecipient->RemoveIssuedNum(*pServerNym, strServerID,
773  lRecipientOpeningNumber,
774  false); // bSave=false
775  // pRecipient->SaveSignedNymfile(*pServerNym); // Moved lower.
776 
777  if (false ==
779  GetRecipientUserID(), lNewTransactionNumber, strOrigCronItem,
780  nullptr, pstrAttachment,
781  pRecipient)) // NymboxHash is updated here in pRecipient.
782  {
783  otErr
784  << szFunc
785  << ": Failure dropping recipient final receipt into nymbox.\n";
786  }
787 
788  // Saving both the Removed Issued Number, as well as the new NymboxHash.
789  // NOTE: Todo: if the NymboxHash WAS updated (as it should have been)
790  // then
791  // it was probably saved at that time. Below is therefore a redundant
792  // save.
793  // Need to fix by making certain objects savable and dirty, and then let
794  // them
795  // autosave before destruction, IF they are dirty.
796  //
797  pRecipient->SaveSignedNymfile(*pServerNym);
798  }
799  else {
800  otErr << szFunc
801  << ": Failed verifying "
802  "lRecipientClosingNumber="
803  "GetRecipientClosingTransactionNoAt(1)>0 && "
804  "pRecipient->VerifyTransactionNum(lRecipientClosingNumber) && "
805  "VerifyIssuedNum(lRecipientOpeningNumber)\n";
806  }
807 
808  //
809  if ((nullptr != pRecipient) && (lRecipientClosingNumber > 0) &&
810  pRecipient->VerifyIssuedNum(strServerID, lRecipientClosingNumber)) {
813  lNewTransactionNumber,
814  lRecipientClosingNumber, // The closing transaction
815  // number to put on the
816  // receipt.
817  strOrigCronItem, nullptr, pstrAttachment))
818  otErr << szFunc
819  << ": Failure dropping receipt into recipient's inbox.\n";
820 
821  // This part below doesn't happen until pRecipient ACCEPTs the final
822  // receipt (when processing his inbox.)
823  //
824  // pRecipient->RemoveIssuedNum(strServerID,
825  // lRecipientClosingNumber, true); //bSave=false
826  }
827  else {
828  otErr << szFunc
829  << ": Failed verifying "
830  "lRecipientClosingNumber="
831  "GetRecipientClosingTransactionNoAt(1)>0 && "
832  "pRecipient->VerifyTransactionNum(lRecipientClosingNumber) && "
833  "VerifyIssuedNum(lRecipientOpeningNumber)\n";
834  }
835 
836  // QUESTION: Won't there be Cron Items that have no asset account at all?
837  // In which case, there'd be no need to drop a final receipt, but I don't
838  // think
839  // that's the case, since you have to use a transaction number to get onto
840  // cron
841  // in the first place.
842 }
843 
844 /*
845  inline const OTIdentifier& GetRecipientAcctID() const { return
846  m_RECIPIENT_ACCT_ID; }
847  inline const OTIdentifier& GetRecipientUserID() const { return
848  m_RECIPIENT_USER_ID; }
849  */
850 
851 bool OTAgreement::IsValidOpeningNumber(const int64_t& lOpeningNum) const
852 {
853  if (GetRecipientOpeningNum() == lOpeningNum) return true;
854 
855  return ot_super::IsValidOpeningNumber(lOpeningNum);
856 }
857 
859 {
860  // Not much needed here.
861  // Actually: Todo: (unless it goes in payment plan code) need to set
862  // receipts
863  // in inboxes, and close out the closing transaction numbers.
864  //
865 }
866 
867 // You usually wouldn't want to use this, since if the transaction failed, the
868 // opening number
869 // is already burned and gone. But there might be cases where it's not, and you
870 // want to retrieve it.
871 // So I added this function.
872 //
874 {
875  // since we overrode the parent, we give it a chance to harvest also.
876  // IF theNym is the original sender, the opening number will be harvested
877  // inside this call.
878  //
880 
881  // The Nym is the original recipient. (If Compares true).
882  // IN CASES where GetTransactionNum() isn't already burned, we can harvest
883  // it here.
884  //
885  if (theNym.CompareID(GetRecipientUserID())) {
886  // This function will only "add it back" if it was really there in the
887  // first place.
888  // (Verifies it is on issued list first, before adding to available
889  // list.)
890  //
891  const bool bClawedBack = theNym.ClawbackTransactionNumber(
892  GetServerID(), GetRecipientOpeningNum(), true); // bSave=true
893 
894  if (!bClawedBack) {
895  // otErr << "OTAgreement::HarvestOpeningNumber: Number
896  // (%lld) failed as issued. (Thus didn't bother 'adding it
897  // back'.)\n", GetRecipientOpeningNum());
898  }
899  }
900 
901  // NOTE: if the message failed (transaction never actually ran) then the
902  // sender AND recipient
903  // can both reclaim their opening numbers. But if the message SUCCEEDED and
904  // the transaction FAILED,
905  // then only the recipient can claim his opening number -- the sender's is
906  // already burned. So then,
907  // what if you mistakenly call this function and pass the sender, when that
908  // number is already burned?
909  // There's nothing this function can do, because we have no way of telling,
910  // from inside here,
911  // whether the message succeeded or not, and whether the transaction
912  // succeeded or not. Therefore,
913  // ==> we MUST rely on the CALLER to know this, and to avoid calling this
914  // function in the first place,
915  // if he's sitting on a sender with a failed transaction.
916 }
917 
918 // Used for adding transaction numbers back to a Nym, after deciding not to use
919 // this agreement
920 // or failing in trying to use it. Client side.
921 //
923 {
924  // Since we overrode the parent, we give it a chance to harvest also.
925  // If theNym is the sender, then his closing numbers will be harvested
926  // inside here. But what if the transaction was a success? The numbers
927  // will still be harvested, since they are still on the sender's issued
928  // list, but they should not have been harvested, regardless, since the
929  // transaction was a success and the server therefore has them marked as
930  // "used." So clearly you cannot just blindly call this function unless
931  // you know beforehand whether the message and transaction were a success.
932  //
934 
935  // The Nym is the original recipient. (If Compares true).
936  // FYI, if Nym is the original sender, then the above call will handle him.
937  //
938  // GetTransactionNum() is burned, but we can harvest the closing
939  // numbers from the "Closing" list, which is only for the sender's numbers.
940  // Subclasses will have to override this function for recipients, etc.
941  //
942  if (theNym.CompareID(GetRecipientUserID())) {
943  // otOut << "%s: Harvesting RECIPIENT...\n", __FUNCTION__);
944 
945  // This function will only "add it back" if it was really there in the
946  // first place.
947  // (Verifies it is on issued list first, before adding to available
948  // list.)
949  //
950  const bool bClawedBack = theNym.ClawbackTransactionNumber(
951  GetServerID(), GetRecipientClosingNum(), true); // bSave=true
952 
953  if (!bClawedBack) {
954  // otErr << "OTAgreement::HarvestClosingNumbers: Number
955  // (%lld) failed as issued. (Thus didn't bother 'adding it
956  // back'.)\n", GetRecipientClosingTransactionNoAt(i));
957  }
958  }
959 }
960 
961 int64_t OTAgreement::GetOpeningNumber(const OTIdentifier& theNymID) const
962 {
963  const OTIdentifier& theRecipientNymID = GetRecipientUserID();
964 
965  if (theNymID == theRecipientNymID) return GetRecipientOpeningNum();
966  // else...
967  return ot_super::GetOpeningNumber(theNymID);
968 }
969 
970 int64_t OTAgreement::GetClosingNumber(const OTIdentifier& theAcctID) const
971 {
972  const OTIdentifier& theRecipientAcctID = GetRecipientAcctID();
973 
974  if (theAcctID == theRecipientAcctID) return GetRecipientClosingNum();
975  // else...
976  return ot_super::GetClosingNumber(theAcctID);
977 }
978 
980 {
981  return (GetRecipientCountClosingNumbers() > 0)
983  : 0; // todo stop hardcoding.
984 }
985 
987 {
988  return (GetRecipientCountClosingNumbers() > 1)
990  : 0; // todo stop hardcoding.
991 }
992 
993 // These are for finalReceipt
994 // The Cron Item stores a list of these closing transaction numbers,
995 // used for closing a transaction.
996 //
997 
999 {
1000  OT_ASSERT_MSG(
1001  (nIndex < m_dequeRecipientClosingNumbers.size()),
1002  "OTAgreement::GetClosingTransactionNoAt: index out of bounds.");
1003 
1004  return m_dequeRecipientClosingNumbers.at(nIndex);
1005 }
1006 
1008 {
1009  return static_cast<int32_t>(m_dequeRecipientClosingNumbers.size());
1010 }
1011 
1013  const int64_t& lClosingTransactionNo)
1014 {
1015  m_dequeRecipientClosingNumbers.push_back(lClosingTransactionNo);
1016 }
1017 
1018 // OTCron calls this regularly, which is my chance to expire, etc.
1019 // Child classes will override this, AND call it (to verify valid date range.)
1021 {
1022  // END DATE --------------------------------
1023  // First call the parent's version (which this overrides) so it has
1024  // a chance to check its stuff. Currently it checks IsExpired().
1025  if (!ot_super::ProcessCron())
1026  return false; // It's expired or flagged--removed it from Cron.
1027 
1028  // START DATE --------------------------------
1029  // Okay, so it's NOT expired. But might not have reached START DATE yet...
1030  // (If not expired, yet current date is not verified, that means it hasn't
1031  // ENTERED the date range YET.)
1032  //
1033  if (!VerifyCurrentDate())
1034  return true; // The Trade is not yet valid, so we return. BUT, we return
1035  // true, so it will stay on Cron until it BECOMES valid.
1036 
1037  // Process my Agreement-specific stuff
1038  // below.--------------------------------
1039 
1040  return true;
1041 }
1042 
1046 {
1047  // You don't just go willy-nilly and remove a cron item from a market unless
1048  // you check first
1049  // and make sure the Nym who requested it actually has said number (or a
1050  // related closing number)
1051  // signed out to him on his last receipt...
1052  //
1053  if (true == ot_super::CanRemoveItemFromCron(theNym)) return true;
1054 
1055  const OTString strServerID(GetServerID());
1056 
1057  // Usually the Nym is the originator. (Meaning GetTransactionNum() on this
1058  // agreement
1059  // is still verifiable as an issued number on theNum, and belongs to him.)
1060  // In that case,
1061  // the above call will discover this, and return true.
1062  // In other cases, theNym has the right to Remove the item even though
1063  // theNym didn't originate it.
1064  // (Like if he is the recipient -- not the sender -- in a payment plan.) We
1065  // check such things
1066  // HERE in this function (see below.)
1067  //
1068  if (!theNym.CompareID(GetRecipientUserID())) {
1069  otOut << "OTAgreement::" << __FUNCTION__
1070  << " Weird: Nym tried to remove agreement (payment plan), even "
1071  "though he apparently wasn't the sender OR recipient.\n";
1072  return false;
1073  }
1074  else if (GetRecipientCountClosingNumbers() < 2) {
1075  otOut << "OTAgreement::" << __FUNCTION__
1076  << ": Weird: Recipient tried to remove agreement "
1077  "(or payment plan); expected 2 closing numbers to be "
1078  "available--that weren't."
1079  " (Found " << GetRecipientCountClosingNumbers() << ").\n";
1080  return false;
1081  }
1082 
1083  if (false ==
1084  theNym.VerifyIssuedNum(strServerID, GetRecipientClosingNum())) {
1085  otOut << "OTAgreement::" << __FUNCTION__ << ": Recipient Closing "
1086  "number didn't verify (for "
1087  "removal from cron).\n";
1088  return false;
1089  }
1090 
1091  // By this point, we KNOW theNym is the sender, and we KNOW there are the
1092  // proper number of transaction
1093  // numbers available to close. We also know that this cron item really was
1094  // on the cron object, since
1095  // that is where it was looked up from, when this function got called! So
1096  // I'm pretty sure, at this point,
1097  // to authorize removal, as long as the transaction num is still issued to
1098  // theNym (this check here.)
1099  //
1100  return theNym.VerifyIssuedNum(strServerID, GetRecipientOpeningNum());
1101 
1102  // Normally this will be all we need to check. The originator will have the
1103  // transaction
1104  // number signed-out to him still, if he is trying to close it. BUT--in some
1105  // cases, someone
1106  // who is NOT the originator can cancel. Like in a payment plan, the sender
1107  // is also the depositor,
1108  // who would normally be the person cancelling the plan. But technically,
1109  // the RECIPIENT should
1110  // also have the ability to cancel that payment plan. BUT: the transaction
1111  // number isn't signed
1112  // out to the RECIPIENT... In THAT case, the below VerifyIssuedNum() won't
1113  // work! In those cases,
1114  // expect that the special code will be in the subclasses override of this
1115  // function. (OTPaymentPlan::CanRemoveItem() etc)
1116 
1117  // P.S. If you override this function, MAKE SURE to call the parent
1118  // (OTCronItem::CanRemoveItem) first,
1119  // for the VerifyIssuedNum call above. Only if that fails, do you need to
1120  // dig deeper...
1121 }
1122 
1124 {
1125  // Compare OTAgreement specific info here.
1126 
1128  (GetRecipientAcctID() == rhs.GetRecipientAcctID()) &&
1129  (GetRecipientUserID() == rhs.GetRecipientUserID()) &&
1130  // ( m_dequeClosingNumbers == rhs.m_dequeClosingNumbers ) && //
1131  // The merchant wouldn't know the customer's trans#s.
1132  // (Thus wouldn't expect them to be set in BOTH versions...)
1135  // ( GetTransactionNum() == rhs.GetTransactionNum() ) && //
1136  // (commented out for same reason as above.)
1137  // ( GetSenderAcctID() == rhs.GetSenderAcctID() ) && //
1138  // Same here -- we should let the merchant leave these blank,
1139  // ( GetSenderUserID() == rhs.GetSenderUserID() ) && //
1140  // and then allow the customer to add them in his version,
1141  (GetAssetID() == rhs.GetAssetID()) && // (and this Compare function
1142  // still still verify it.)
1143  (GetServerID() == rhs.GetServerID()) &&
1144  (GetValidFrom() == rhs.GetValidFrom()) &&
1145  (GetValidTo() == rhs.GetValidTo()))
1146  return true;
1147 
1148  return false;
1149 }
1150 
1151 // THIS FUNCTION IS CALLED BY THE MERCHANT
1152 //
1153 // (lMerchantTransactionNumber, lMerchantClosingNumber are set internally in
1154 // this call, from MERCHANT_NYM.)
1156  const OTString& strConsideration,
1157  time64_t VALID_FROM,
1158  time64_t VALID_TO) // VALID_TO is a
1159  // length here.
1160  // (i.e. it's
1161  // ADDED to
1162  // valid_from)
1163 {
1164 
1165  OTIdentifier id_MERCHANT_NYM;
1166  MERCHANT_NYM.GetIdentifier(id_MERCHANT_NYM);
1167 
1168  if (GetRecipientUserID() != id_MERCHANT_NYM) {
1169  otOut << __FUNCTION__ << ": Merchant has wrong NymID (should be same "
1170  "as RecipientUserID.)\n";
1171  return false;
1172  }
1173  else if (GetRecipientUserID() == GetSenderUserID()) {
1174  otOut << __FUNCTION__ << ": Error: Sender and recipient have the same "
1175  "Nym ID (not allowed.)\n";
1176  return false;
1177  }
1178  else if (MERCHANT_NYM.GetTransactionNumCount(GetServerID()) <
1179  2) // Need opening and closing numbers (that's 2)...
1180  {
1181  otOut << __FUNCTION__ << ": Failure. You need at least 2 transaction "
1182  "numbers available to do this.\n";
1183  return false;
1184  }
1185 
1186  // Set the CREATION DATE
1187  //
1188  const time64_t CURRENT_TIME = OTTimeGetCurrentTime();
1189 
1190  // Set the Creation Date.
1191  SetCreationDate(CURRENT_TIME);
1192 
1193  // Putting this above here so I don't have to put the transaction numbers
1194  // back if this fails:
1195 
1196  // VALID_FROM
1197  //
1198  // The default "valid from" time is NOW.
1199  if (OT_TIME_ZERO >= VALID_FROM) // if it's 0 or less, set to current time.
1200  SetValidFrom(CURRENT_TIME);
1201  else // Otherwise use whatever was passed in.
1202  SetValidFrom(VALID_FROM);
1203 
1204  // VALID_TO
1205  //
1206  // The default "valid to" time is 0 (which means no expiration date / cancel
1207  // anytime.)
1208  if (OT_TIME_ZERO == VALID_TO) // VALID_TO is 0
1209  {
1210  SetValidTo(VALID_TO); // Keep it at zero then, so it won't expire.
1211  }
1212  else if (OT_TIME_ZERO < VALID_TO) // VALID_TO is ABOVE zero...
1213  {
1215  GetValidFrom(), OTTimeGetSecondsFromTime(VALID_TO))); // Set it to
1216  // itself +
1217  // valid_from.
1218  }
1219  else // VALID_TO is a NEGATIVE number... Error.
1220  {
1221  int64_t lValidTo = OTTimeGetSecondsFromTime(VALID_TO);
1222  otErr << __FUNCTION__ << ": Negative value for valid_to: " << lValidTo
1223  << "\n";
1224 
1225  return false;
1226  }
1227 
1228  // Since we'll be needing 2 transaction numbers to do this, let's grab
1229  // 'em...
1230  //
1231  OTString strServerID(GetServerID());
1232 
1233  int64_t lTransactionNumber = 0, lClosingTransactionNo = 0;
1234 
1235  if (MERCHANT_NYM.GetTransactionNumCount(GetServerID()) <
1236  2) // Need opening and closing numbers (that's 2)...
1237  {
1238  otOut << __FUNCTION__ << ": Failure. You need at least 2 transaction "
1239  "numbers available to do this.\n";
1240  return false;
1241  }
1242  else if (false ==
1243  MERCHANT_NYM.GetNextTransactionNum(MERCHANT_NYM, strServerID,
1244  lTransactionNumber)) {
1245  otErr << __FUNCTION__
1246  << ": Error: Strangely unable to get a transaction number.\n";
1247  return false;
1248  }
1249  else if (false ==
1250  MERCHANT_NYM.GetNextTransactionNum(MERCHANT_NYM, strServerID,
1251  lClosingTransactionNo)) {
1252  otErr << __FUNCTION__ << ": Error: Strangely unable to get a closing "
1253  "transaction number.\n";
1254  MERCHANT_NYM.AddTransactionNum(MERCHANT_NYM, strServerID,
1255  lTransactionNumber, true); // bSave=true
1256  // (Since the first one was successful, we just put it back before
1257  // returning.)
1258  return false;
1259  }
1260 
1261  // At this point we now have 2 transaction numbers...
1262  // We can't return without either USING THEM, or PUTTING THEM BACK.
1263  //
1264 
1265  // Set the Transaction Number and the Closing transaction number... (for
1266  // merchant / recipient.)
1267  //
1268  AddRecipientClosingTransactionNo(lTransactionNumber);
1269  AddRecipientClosingTransactionNo(lClosingTransactionNo);
1270  // (They just both go onto this same list.)
1271 
1272  // Set the Consideration memo...
1273  m_strConsideration.Set(strConsideration);
1274 
1275  otLog4 << "Successfully performed SetProposal.\n";
1276  return true;
1277 }
1278 
1279 // THIS FUNCTION IS CALLED BY THE CUSTOMER
1280 //
1281 // (Transaction number and closing number are retrieved from Nym at this time.)
1282 bool OTAgreement::Confirm(OTPseudonym& PAYER_NYM, OTPseudonym* pMERCHANT_NYM,
1283  const OTIdentifier* p_id_MERCHANT_NYM)
1284 {
1285 
1286  OTIdentifier id_PAYER_NYM;
1287  PAYER_NYM.GetIdentifier(id_PAYER_NYM);
1288 
1289  if (GetRecipientUserID() == GetSenderUserID()) {
1290  otOut << __FUNCTION__ << ": Error: Sender and recipient have the same "
1291  "Nym ID (not allowed.)\n";
1292  return false;
1293  }
1294  else if ((nullptr != p_id_MERCHANT_NYM) &&
1295  (GetRecipientUserID() != *p_id_MERCHANT_NYM)) {
1296  otOut << __FUNCTION__ << ": Merchant has wrong NymID (should be same "
1297  "as RecipientUserID.)\n";
1298  return false;
1299  }
1300  else if ((nullptr != pMERCHANT_NYM) &&
1301  (GetRecipientUserID() != pMERCHANT_NYM->GetConstID())) {
1302  otOut << __FUNCTION__ << ": Merchant has wrong NymID (should be same "
1303  "as RecipientUserID.)\n";
1304  return false;
1305  }
1306  else if (GetSenderUserID() != id_PAYER_NYM) {
1307  otOut << __FUNCTION__
1308  << ": Payer has wrong NymID (should be same as SenderUserID.)\n";
1309  return false;
1310  }
1311  else if (PAYER_NYM.GetTransactionNumCount(GetServerID()) <
1312  2) // Need opening and closing numbers (that's 2)...
1313  {
1314  otOut << __FUNCTION__ << ": Failure. You need at least 2 transaction "
1315  "numbers available to do this.\n";
1316  return false;
1317  }
1318  else if (GetRecipientCountClosingNumbers() < 2) {
1319  otOut << __FUNCTION__ << ": Failure. (The merchant was supposed to "
1320  "attach 2 transaction numbers.)\n";
1321  return false;
1322  }
1323 
1324  // This is the single reason why MERCHANT_NYM was even passed in here!
1325  // Supposedly merchant has already signed. Let's verify this!!
1326  //
1327  if ((nullptr != pMERCHANT_NYM) &&
1328  (false == VerifySignature(*pMERCHANT_NYM))) {
1329  otOut << __FUNCTION__ << ": Merchant's signature failed to verify.\n";
1330  return false;
1331  }
1332 
1333  // Now that we KNOW the merchant signed it... SAVE MERCHANT's COPY.
1334  // Let's save a copy of the one the merchant signed, before changing it and
1335  // re-signing it,
1336  // (to add my own transaction numbers...)
1337  //
1338  OTString strTemp;
1339  SaveContractRaw(strTemp);
1340  SetMerchantSignedCopy(strTemp);
1341 
1342  // The payer has to submit TWO transaction numbers in order to activate this
1343  // agreement...
1344  //
1345  OTString strServerID(GetServerID());
1346  int64_t lTransactionNumber = 0, lClosingTransactionNo = 0;
1347 
1348  if (false ==
1349  PAYER_NYM.GetNextTransactionNum(PAYER_NYM, strServerID,
1350  lTransactionNumber)) {
1351  otErr << __FUNCTION__
1352  << ": Error: Strangely unable to get a transaction number.\n";
1353  return false;
1354  }
1355  else if (false ==
1356  PAYER_NYM.GetNextTransactionNum(PAYER_NYM, strServerID,
1357  lClosingTransactionNo)) {
1358  otErr << __FUNCTION__ << ": Error: Strangely unable to get a closing "
1359  "transaction number.\n";
1360  PAYER_NYM.AddTransactionNum(PAYER_NYM, strServerID, lTransactionNumber,
1361  true); // bSave=true
1362  // (Since the first one was successful, we just put it back before
1363  // returning.)
1364  return false;
1365  }
1366 
1367  // At this point we now HAVE 2 transaction numbers (for payer / sender)...
1368  // We can't return without USING THEM or PUTTING THEM BACK.
1369  //
1370 
1371  SetTransactionNum(lTransactionNumber); // Set the Transaction Number
1373  lClosingTransactionNo); // and the Closing Number (both for sender)...
1374 
1375  // CREATION DATE was set in the Merchant's proposal, and it's RESET here in
1376  // the Confirm.
1377  // This way, (since we still have the original proposal) we can see BOTH
1378  // times.
1379  //
1380  time64_t CURRENT_TIME = OTTimeGetCurrentTime();
1381  // Set the Creation Date.
1382  SetCreationDate(CURRENT_TIME);
1383 
1384  otLog4 << __FUNCTION__ << "(): Success!\n";
1385 
1386  return true;
1387 }
1388 
1389 // (Make sure to set Creation date here.)
1390 // THIS FUNCTION IS DEPRECATED
1391 //
1392 /*
1393 bool OTAgreement::SetAgreement(const int64_t& lTransactionNum, const
1394 OTString& strConsideration,
1395  const time64_t& VALID_FROM=0, const time64_t
1396 & VALID_TO=0)
1397 {
1398  // Set the Transaction Number...
1399  SetTransactionNum(lTransactionNum);
1400 
1401  // Set the Consideration memo...
1402  m_strConsideration.Set(strConsideration);
1403 
1404 
1405 
1406  time64_t CURRENT_TIME = OTTimeGetCurrentTime();
1407 
1408  // Set the Creation Date.
1409  SetCreationDate(CURRENT_TIME);
1410 
1411 
1412 
1413  // The default "valid from" time is NOW.
1414  if (0 >= VALID_FROM) // if it's 0 or less, set to current time.
1415  SetValidFrom(CURRENT_TIME);
1416  else // Otherwise use whatever was passed in.
1417  SetValidFrom(VALID_FROM);
1418 
1419 
1420 
1421  // The default "valid to" time is 0 (which means no expiration date / cancel
1422 anytime.)
1423  if (0 == VALID_TO) // VALID_TO is 0
1424  {
1425  SetValidTo(VALID_TO); // Keep it at zero then, so it won't expire.
1426  }
1427  else if (0 < VALID_TO) // VALID_TO is ABOVE zero...
1428  {
1429  if (VALID_TO < VALID_FROM) // If Valid-To date is EARLIER than
1430 Valid-From date...
1431  {
1432  int64_t lValidTo = VALID_TO, lValidFrom = VALID_FROM;
1433  otErr << "VALID_TO is earlier than VALID_FROM in SetAgreement: %lld,
1434 %lld\n", lValidTo, lValidFrom);
1435  return false;
1436  }
1437 
1438  SetValidTo(VALID_TO); // Set it to whatever it is, since it is now
1439 validated as higher than Valid-From.
1440  }
1441  else // VALID_TO is a NEGATIVE number... Error.
1442  {
1443  int64_t lValidTo = VALID_TO;
1444  otErr << "Negative value for valid_to in SetAgreement: %lld\n",
1445 lValidTo);
1446  return false;
1447  }
1448 
1449 
1450 
1451  otLog4 << "Successfully performed SetAgreement()\n");
1452 
1453  return true;
1454 }
1455 */
1456 
1458  : ot_super()
1459 {
1460  InitAgreement();
1461 }
1462 
1464  const OTIdentifier& ASSET_ID)
1465  : ot_super(SERVER_ID, ASSET_ID)
1466 {
1467  InitAgreement();
1468 }
1469 
1471  const OTIdentifier& ASSET_ID,
1472  const OTIdentifier& SENDER_ACCT_ID,
1473  const OTIdentifier& SENDER_USER_ID,
1474  const OTIdentifier& RECIPIENT_ACCT_ID,
1475  const OTIdentifier& RECIPIENT_USER_ID)
1476  : ot_super(SERVER_ID, ASSET_ID, SENDER_ACCT_ID, SENDER_USER_ID)
1477 {
1478  InitAgreement();
1479 
1480  SetRecipientAcctID(RECIPIENT_ACCT_ID);
1481  SetRecipientUserID(RECIPIENT_USER_ID);
1482 }
1483 
1485 {
1487 }
1488 
1490 {
1491  m_strContractType = "AGREEMENT";
1492 }
1493 
1495 {
1496  // If there were any dynamically allocated objects, clean them up here.
1497  //
1498  m_RECIPIENT_ACCT_ID.Release();
1499  m_RECIPIENT_USER_ID.Release();
1500 
1503 
1505 }
1506 
1507 // the framework will call this at the right time.
1508 //
1510 {
1512 
1513  ot_super::Release(); // since I've overridden the base class (OTCronItem),
1514  // so I call it now...
1515 
1516  // Then I call this to re-initialize everything
1517  InitAgreement();
1518 }
1519 
1521 {
1522  // See OTPaymentPlan::UpdateContents.
1523 }
1524 
1525 // return -1 if error, 0 if nothing, and 1 if the node was processed.
1527 {
1528  int32_t nReturnVal = 0;
1529 
1530  // Here we call the parent class first.
1531  // If the node is found there, or there is some error,
1532  // then we just return either way. But if it comes back
1533  // as '0', then nothing happened, and we'll continue executing.
1534  //
1535  // -- Note you can choose not to call the parent if
1536  // you don't want to use any of those xml tags.
1537  // As I do below, in the case of OTAccount.
1538  if (0 != (nReturnVal = ot_super::ProcessXMLNode(xml))) return nReturnVal;
1539 
1540  if (!strcmp("agreement", xml->getNodeName())) {
1541  m_strVersion = xml->getAttributeValue("version");
1542  SetTransactionNum(atol(xml->getAttributeValue("transactionNum")));
1543 
1544  const OTString strCreation = xml->getAttributeValue("creationDate");
1545  int64_t tCreation = strCreation.ToLong();
1546 
1548 
1549  const OTString str_valid_from = xml->getAttributeValue("validFrom");
1550  const OTString str_valid_to = xml->getAttributeValue("validTo");
1551 
1552  int64_t tValidFrom = str_valid_from.ToLong();
1553  int64_t tValidTo = str_valid_to.ToLong();
1554 
1557 
1558  const OTString strServerID(xml->getAttributeValue("serverID")),
1559  strAssetTypeID(xml->getAttributeValue("assetTypeID")),
1560  strSenderAcctID(xml->getAttributeValue("senderAcctID")),
1561  strSenderUserID(xml->getAttributeValue("senderUserID")),
1562  strRecipientAcctID(xml->getAttributeValue("recipientAcctID")),
1563  strRecipientUserID(xml->getAttributeValue("recipientUserID")),
1564  strCanceled(xml->getAttributeValue("canceled")),
1565  strCancelerUserID(xml->getAttributeValue("cancelerUserID"));
1566 
1567  if (strCanceled.Exists() && strCanceled.Compare("true")) {
1568  m_bCanceled = true;
1569 
1570  if (strCancelerUserID.Exists())
1571  m_pCancelerNymID->SetString(strCancelerUserID);
1572  // else log
1573  }
1574  else {
1575  m_bCanceled = false;
1577  }
1578 
1579  const OTIdentifier SERVER_ID(strServerID), ASSET_ID(strAssetTypeID),
1580  SENDER_ACCT_ID(strSenderAcctID), SENDER_USER_ID(strSenderUserID),
1581  RECIPIENT_ACCT_ID(strRecipientAcctID),
1582  RECIPIENT_USER_ID(strRecipientUserID);
1583 
1584  SetServerID(SERVER_ID);
1585  SetAssetID(ASSET_ID);
1586  SetSenderAcctID(SENDER_ACCT_ID);
1587  SetSenderUserID(SENDER_USER_ID);
1588  SetRecipientAcctID(RECIPIENT_ACCT_ID);
1589  SetRecipientUserID(RECIPIENT_USER_ID);
1590 
1591  otWarn << "\n\n" << (m_bCanceled ? "Canceled a" : "A")
1592  << "greement. Transaction Number: " << m_lTransactionNum << "\n";
1593 
1594  otInfo << " Creation Date: " << tCreation
1595  << " Valid From: " << tValidFrom << "\n Valid To: " << tValidTo
1596  << "\n"
1597  " AssetTypeID: " << strAssetTypeID
1598  << "\n ServerID: " << strServerID
1599  << "\n"
1600  " senderAcctID: " << strSenderAcctID
1601  << "\n senderUserID: " << strSenderUserID
1602  << "\n "
1603  " recipientAcctID: " << strRecipientAcctID
1604  << "\n recipientUserID: " << strRecipientUserID << "\n ";
1605 
1606  nReturnVal = 1;
1607  }
1608  else if (!strcmp("consideration", xml->getNodeName())) {
1609  if (false ==
1611  otErr << "Error in OTPaymentPlan::ProcessXMLNode: consideration "
1612  "field without value.\n";
1613  return (-1); // error condition
1614  }
1615 
1616  nReturnVal = 1;
1617  }
1618  else if (!strcmp("merchantSignedCopy", xml->getNodeName())) {
1619  if (false ==
1621  otErr << "Error in OTPaymentPlan::ProcessXMLNode: "
1622  "merchant_signed_copy field without value.\n";
1623  return (-1); // error condition
1624  }
1625 
1626  nReturnVal = 1;
1627  }
1628 
1629  // std::deque<int64_t> m_dequeRecipientClosingNumbers; // Numbers used
1630  // for CLOSING a transaction. (finalReceipt.)
1631  else if (!strcmp("closingRecipientNumber", xml->getNodeName())) {
1632  OTString strClosingNumber = xml->getAttributeValue("value");
1633 
1634  if (strClosingNumber.Exists()) {
1635  const int64_t lClosingNumber = atol(strClosingNumber.Get());
1636 
1637  AddRecipientClosingTransactionNo(lClosingNumber);
1638  }
1639  else {
1640  otErr << "Error in OTAgreement::ProcessXMLNode: "
1641  "closingRecipientNumber field without value.\n";
1642  return (-1); // error condition
1643  }
1644 
1645  nReturnVal = 1;
1646  }
1647 
1648  return nReturnVal;
1649 }
1650 
1651 bool OTAgreement::SaveContractWallet(std::ofstream&) const
1652 {
1653  return true;
1654 }
1655 
1656 } // namespace opentxs
virtual int64_t GetOpeningNumber(const OTIdentifier &theNymID) const
OTLOG_IMPORT OTLogStream otLog4
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
static EXPORT OTTransaction * GenerateTransaction(const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, transactionType theType, int64_t lTransactionNum=0)
void SetRecipientUserID(const OTIdentifier &USER_ID)
EXPORT int32_t GetRecipientCountClosingNumbers() const
virtual void onRemovalFromCron()
const OTIdentifier & GetSenderUserID() const
EXPORT bool ClawbackTransactionNumber(const OTIdentifier &theServerID, const int64_t &lTransClawback, bool bSave=false, OTPseudonym *pSIGNER_NYM=nullptr)
EXPORT int64_t GetRecipientClosingTransactionNoAt(uint32_t nIndex) const
EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
virtual void Release()
EXPORT bool SetProposal(OTPseudonym &MERCHANT_NYM, const OTString &strConsideration, time64_t VALID_FROM=OT_TIME_ZERO, time64_t VALID_TO=OT_TIME_ZERO)
time64_t GetValidTo() const
void SetMerchantSignedCopy(const OTString &strMerchantCopy)
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
virtual void HarvestOpeningNumber(OTPseudonym &theNym)
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
EXPORT bool SaveContract()
EXPORT bool VerifyIssuedNum(const OTString &strServerID, const int64_t &lTransNum) const
time64_t OTTimeAddTimeInterval(time64_t lhs, int64_t rhs)
Definition: Common.hpp:238
EXPORT int64_t ToLong() const
Definition: OTString.cpp:702
void AddRecipientClosingTransactionNo(const int64_t &lClosingTransactionNo)
EXPORT bool GetNextTransactionNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, int64_t &lTransNum, bool bSave=true)
const OTIdentifier & GetAssetID() const
EXPORT bool AddTransaction(OTTransaction &theTransaction)
Definition: OTLedger.cpp:1194
OTLOG_IMPORT OTLogStream otOut
virtual bool CanRemoveItemFromCron(OTPseudonym &theNym)
Definition: OTCronItem.cpp:700
std::map< std::string, OTPseudonym * > mapOfNyms
Definition: OTWallet.hpp:161
EXPORT bool SendNoticeToAllParties(bool bSuccessMsg, OTPseudonym &theServerNym, const OTIdentifier &theServerID, const int64_t &lNewTransactionNumber, const OTString &strReference, OTString *pstrNote=nullptr, OTString *pstrAttachment=nullptr, OTPseudonym *pActualNym=nullptr) const
OTLOG_IMPORT OTLogStream otLog3
EXPORT void SetAttachment(const OTString &theStr)
Definition: OTItem.cpp:1402
EXPORT bool SaveContractRaw(OTString &strOutput) const
void SetValidTo(time64_t TIME_TO)
time64_t OTTimeGetTimeFromSeconds(int64_t seconds)
Definition: Common.hpp:215
void SetAssetID(const OTIdentifier &ASSET_ID)
EXPORT bool LoadSignedNymfile(OTPseudonym &SIGNER_NYM)
OTString m_strMerchantSignedCopy
void SetRecipientAcctID(const OTIdentifier &ACCT_ID)
virtual bool CanRemoveItemFromCron(OTPseudonym &theNym)
virtual bool CompareAgreement(const OTAgreement &rhs) const
virtual int64_t GetClosingNumber(const OTIdentifier &theAcctID) const
int64_t time64_t
Definition: Common.hpp:209
EXPORT bool VerifyCurrentDate()
EXPORT void SetNymboxHashServerSide(const OTIdentifier &theInput)
EXPORT int32_t GetTransactionNumCount(const OTIdentifier &theServerID) const
void SetCreationDate(const time64_t &CREATION_DATE)
Definition: OTCronItem.hpp:264
EXPORT int64_t GetRecipientOpeningNum() const
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 void ReleaseSignatures()
Definition: OTContract.cpp:989
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT void SetString(const char *szString)
EXPORT void SetIdentifier(const OTIdentifier &theIdentifier)
virtual void HarvestOpeningNumber(OTPseudonym &theNym)
const OTIdentifier & GetServerID() const
void SetStatus(const OTItem::itemStatus &theVal)
Definition: OTItem.hpp:463
time64_t GetValidFrom() const
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 bool Compare(const char *compare) const
Definition: OTString.cpp:1102
EXPORT int32_t GetCountClosingNumbers() const
Definition: OTCronItem.cpp:676
EXPORT bool VerifyOwner(const OTPseudonym &candidate) const
Definition: OTAccount.cpp:463
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 bool AddTransactionNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, int64_t lTransNum, bool bSave)
virtual bool SaveContractWallet(std::ofstream &ofs) const
EXPORT bool Confirm(OTPseudonym &PAYER_NYM, OTPseudonym *pMERCHANT_NYM=nullptr, const OTIdentifier *p_id_MERCHANT_NYM=nullptr)
static EXPORT bool LoadEncodedTextField(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
EXPORT bool RemoveIssuedNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, const int64_t &lTransNum, bool bSave)
virtual bool ProcessCron()
void SetTransactionNum(int64_t lTransactionNum)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
virtual bool HasTransactionNum(const int64_t &lInput) const
OTString m_strContractType
Definition: OTContract.hpp:178
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
EXPORT int64_t GetRecipientClosingNum() const
static EXPORT OTLedger * GenerateLedger(const OTIdentifier &theUserID, const OTIdentifier &theAcctID, const OTIdentifier &theServerID, ledgerType theType, bool bCreateFile=false)
Definition: OTLedger.cpp:946
OTLOG_IMPORT OTLogStream otInfo
EXPORT bool CompareID(const OTIdentifier &theIdentifier) const
virtual void UpdateContents()
void SetSenderAcctID(const OTIdentifier &ACCT_ID)
EXPORT bool SaveNymbox(OTIdentifier *pNymboxHash=nullptr)
Definition: OTLedger.cpp:801
virtual bool VerifyNymAsAgent(OTPseudonym &theNym, OTPseudonym &theSignerNym, mapOfNyms *pmap_ALREADY_LOADED=nullptr) const
EXPORT void SetNote(const OTString &theStr)
Definition: OTItem.cpp:1413
EXPORT bool SaveBoxReceipt(int64_t lLedgerType)
OTLOG_IMPORT OTLogStream otWarn
EXPORT const char * Get() const
Definition: OTString.cpp:1045
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
Definition: OTContract.cpp:484
void SetServerID(const OTIdentifier &SERVER_ID)
OTLOG_IMPORT OTLogStream otErr
virtual EXPORT int64_t GetOpeningNumber(const OTIdentifier &theNymID) const
virtual void onFinalReceipt(OTCronItem &theOrigCronItem, const int64_t &lNewTransactionNumber, OTPseudonym &theOriginator, OTPseudonym *pRemover)
EXPORT void SetReferenceToNum(int64_t lTransactionNum)
OTIdentifier * m_pCancelerNymID
Definition: OTCronItem.hpp:177
EXPORT const OTIdentifier & GetConstID() const
virtual EXPORT void HarvestClosingNumbers(OTPseudonym &theNym)
OTPseudonym * GetServerNym() const
Definition: OTCron.hpp:303
virtual EXPORT bool VerifySignature(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
Definition: OTContract.cpp:818
const OTIdentifier & GetRecipientUserID() const
const OTIdentifier & GetSenderAcctID() const
virtual bool IsValidOpeningNumber(const int64_t &lOpeningNum) const
std::set< int64_t > & GetSetOpenCronItems()
virtual void GetAllTransactionNumbers(OTNumList &numlistOutput) const
const OTIdentifier & GetRecipientAcctID() const
std::deque< int64_t > m_dequeRecipientClosingNumbers
bool DropFinalReceiptToNymbox(const OTIdentifier &USER_ID, const int64_t &lNewTransactionNumber, const OTString &strOrigCronItem, OTString *pstrNote=nullptr, OTString *pstrAttachment=nullptr, OTPseudonym *pActualNym=nullptr)
void SetSenderUserID(const OTIdentifier &USER_ID)
static EXPORT bool DropServerNoticeToNymbox(bool bSuccessMsg, OTPseudonym &theServerNym, const OTIdentifier &SERVER_ID, const OTIdentifier &USER_ID, const int64_t &lNewTransactionNumber, const int64_t &lInReferenceTo, const OTString &strReference, 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
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
virtual int64_t GetClosingNumber(const OTIdentifier &theAcctID) const
virtual bool VerifyNymAsAgentForAccount(OTPseudonym &theNym, OTAccount &theAccount) const
virtual EXPORT void Release()
Definition: OTString.cpp:765
virtual void Release()
EXPORT void AddItem(OTItem &theItem)
EXPORT bool SaveSignedNymfile(OTPseudonym &SIGNER_NYM)