Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTCron.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTCron.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 "cron/OTCron.hpp"
134 #include "crypto/OTASCIIArmor.hpp"
135 #include "cron/OTCronItem.hpp"
136 #include "util/OTFolders.hpp"
137 #include "OTLog.hpp"
138 #include "trade/OTMarket.hpp"
139 #include "util/Timer.hpp"
140 
141 #include <irrxml/irrXML.hpp>
142 
143 #include <memory>
144 
145 // Note: these are only code defaults -- the values are actually loaded from
146 // ~/.ot/server.cfg.
147 
148 namespace opentxs
149 {
150 
151 int32_t OTCron::__trans_refill_amount =
152  500; // The number of transaction numbers Cron will grab for itself, when it
153  // gets low, before each round.
154 int32_t OTCron::__cron_ms_between_process = 10000; // The number of milliseconds
155  // (ideally) between each
156  // "Cron Process" event.
157 
158 int32_t OTCron::__cron_max_items_per_nym = 10; // The maximum number of cron
159  // items any given Nym can have
160  // active at the same time.
161 
162 // Make sure Server Nym is set on this cron object before loading or saving,
163 // since it's
164 // used for signing and verifying..
166 {
167  const char* szFoldername = OTFolders::Cron().Get();
168  const char* szFilename = "OT-CRON.crn"; // todo stop hardcoding filenames.
169 
170  OT_ASSERT(nullptr != GetServerNym());
171 
172  bool bSuccess = LoadContract(szFoldername, szFilename);
173 
174  if (bSuccess) bSuccess = VerifySignature(*(GetServerNym()));
175 
176  return bSuccess;
177 }
178 
180 {
181  const char* szFoldername = OTFolders::Cron().Get();
182  const char* szFilename = "OT-CRON.crn"; // todo stop hardcoding filenames.
183 
184  OT_ASSERT(nullptr != GetServerNym());
185 
187 
188  // Sign it, save it internally to string, and then save that out to the
189  // file.
190  if (!SignContract(*m_pServerNym) || !SaveContract() ||
191  !SaveContract(szFoldername, szFilename)) {
192  otErr << "Error saving main Cronfile:\n" << szFoldername
193  << OTLog::PathSeparator() << szFilename << "\n";
194  return false;
195  }
196  else
197  return true;
198 }
199 
200 // Loops through ALL markets, and calls pMarket->GetNym_OfferList(NYM_ID,
201 // *pOfferList) for each.
202 // Returns a list of all the offers that a specific Nym has on all the markets.
203 //
205  const OTIdentifier& NYM_ID, int32_t& nOfferCount)
206 {
207  nOfferCount = 0; // Outputs the number of offers on this nym.
208 
209  std::unique_ptr<OTDB::OfferListNym> pOfferList(
210  dynamic_cast<OTDB::OfferListNym*>(
212 
213  for (auto& it : m_mapMarkets) {
214  OTMarket* pMarket = it.second;
215  OT_ASSERT(nullptr != pMarket);
216 
217  int32_t nNymOfferCount = 0;
218 
219  if (false ==
220  pMarket->GetNym_OfferList(NYM_ID, *pOfferList,
221  nNymOfferCount)) // appends to
222  // *pOfferList,
223  // each
224  // iteration.
225  {
226  // may wish to add a log later. Anyway, keep iterationg and
227  // appending, then send back whatever we have.
228  }
229  else // Success!
230  nOfferCount += nNymOfferCount;
231  }
232 
233  // Now pack the list into strOutput...
234  if (nOfferCount == 0)
235  return true; // Success, but 0 offers being returned. (List is empty.)
236 
237  else if (nOfferCount > 0) {
239  OT_ASSERT(nullptr != pStorage);
240 
241  OTDB::OTPacker* pPacker =
242  pStorage->GetPacker(); // No need to check for failure, since this
243  // already ASSERTS. No need to cleanup
244  // either.
245 
246  std::unique_ptr<OTDB::PackedBuffer> pBuffer(
247  pPacker->Pack(*pOfferList)); // Now we PACK our nym's offer list.
248 
249  if (nullptr == pBuffer) {
250  otErr
251  << "Failed packing pOfferList in OTCron::GetNym_OfferList. \n";
252  return false;
253  }
254 
255  // Now we need to translate pBuffer into strOutput.
256 
257  const uint8_t* pUint = static_cast<const uint8_t*>(pBuffer->GetData());
258  const size_t theSize = pBuffer->GetSize();
259 
260  if ((nullptr != pUint) || (theSize < 2)) {
261  OTData theData(pUint, static_cast<uint32_t>(theSize));
262 
263  // This function will base64 ENCODE theData,
264  // and then Set() that as the string contents.
265  ascOutput.SetData(theData);
266 
267  return true;
268  }
269  else
270  otErr << "Null returned, or bad size, while getting buffer data in "
271  "OTCron::GetNym_OfferList.\n";
272  }
273  else
274  otErr
275  << "Error: Less-than-zero nOfferCount in OTCron::GetNym_OfferList: "
276  << nOfferCount << ".\n";
277 
278  return false;
279 }
280 
281 bool OTCron::GetMarketList(OTASCIIArmor& ascOutput, int32_t& nMarketCount)
282 {
283  nMarketCount = 0; // This parameter is set to zero here, and incremented in
284  // the loop below.
285 
286  OTMarket* pMarket = nullptr;
287 
288  std::unique_ptr<OTDB::MarketList> pMarketList(
289  dynamic_cast<OTDB::MarketList*>(
291 
292  for (auto& it : m_mapMarkets) {
293  pMarket = it.second;
294  OT_ASSERT(nullptr != pMarket);
295 
296  std::unique_ptr<OTDB::MarketData> pMarketData(
297  dynamic_cast<OTDB::MarketData*>(
299 
300  const OTIdentifier MARKET_ID(*pMarket);
301  const OTString str_MARKET_ID(MARKET_ID);
302  const OTString str_ServerID(pMarket->GetServerID());
303  const OTString str_ASSET_ID(pMarket->GetAssetID());
304  const OTString str_CURRENCY_ID(pMarket->GetCurrencyID());
305 
306  pMarketData->server_id = str_ServerID.Get();
307  pMarketData->market_id = str_MARKET_ID.Get();
308  pMarketData->asset_type_id = str_ASSET_ID.Get();
309  pMarketData->currency_type_id = str_CURRENCY_ID.Get();
310  // --------------------------------------------
311  const int64_t& lScale = pMarket->GetScale();
312 
313  pMarketData->scale = to_string<int64_t>(lScale);
314 
315  const uint64_t theCurrentBid = pMarket->GetHighestBidPrice();
316  const uint64_t theCurrentAsk = pMarket->GetLowestAskPrice();
317 
318  pMarketData->current_bid = to_string<uint64_t>(theCurrentBid);
319  pMarketData->current_ask = to_string<uint64_t>(theCurrentAsk);
320 
321  const int64_t& lLastSalePrice = pMarket->GetLastSalePrice();
322  const int64_t& lTotalAvailableAssets =
323  pMarket->GetTotalAvailableAssets();
324 
325  pMarketData->total_assets = to_string<int64_t>(lTotalAvailableAssets);
326  pMarketData->last_sale_price = to_string<int64_t>(lLastSalePrice);
327 
328  pMarketData->last_sale_date = pMarket->GetLastSaleDate();
329 
330  const mapOfOffers::size_type theBidCount = pMarket->GetBidCount();
331  const mapOfOffers::size_type theAskCount = pMarket->GetAskCount();
332 
333  pMarketData->number_bids =
334  to_string<mapOfOffers::size_type>(theBidCount);
335  pMarketData->number_asks =
336  to_string<mapOfOffers::size_type>(theAskCount);
337 
338  // In the past 24 hours.
339  // (I'm not collecting this data yet, (maybe never), so these values
340  // aren't set at all.)
341  //
342  // pMarketData->volume_trades = ???;
343  // pMarketData->volume_assets = ???;
344  // pMarketData->volume_currency = ???;
345  //
346  // pMarketData->recent_highest_bid = ???;
347  // pMarketData->recent_lowest_ask = ???;
348 
349  // *pMarketData is CLONED at this time (I'm still responsible to
350  // delete.)
351  // That's also why I add it here, below: So the data is set right before
352  // the cloning occurs.
353  //
354  pMarketList->AddMarketData(*pMarketData);
355  nMarketCount++;
356  }
357 
358  // Now pack the list into strOutput...
359  if (0 == nMarketCount) {
360  return true; // Success, but the list contains 0 markets.
361  }
362  else if (nMarketCount > 0) {
364  OT_ASSERT(nullptr != pStorage);
365 
366  OTDB::OTPacker* pPacker =
367  pStorage->GetPacker(); // No need to check for failure, since this
368  // already ASSERTS. No need to cleanup
369  // either.
370 
371  std::unique_ptr<OTDB::PackedBuffer> pBuffer(
372  pPacker->Pack(*pMarketList)); // Now we PACK our market list.
373 
374  if (nullptr == pBuffer) {
375  otErr << "Failed packing pMarketList in OTCron::GetMarketList. \n";
376  return false;
377  }
378 
379  // --------------------------------------------------------
380 
381  // Now we need to translate pBuffer into strOutput.
382 
383  const uint8_t* pUint = static_cast<const uint8_t*>(pBuffer->GetData());
384  const size_t theSize = pBuffer->GetSize();
385 
386  if ((theSize > 0) && (nullptr != pUint)) {
387  OTData theData(pUint, static_cast<uint32_t>(theSize));
388 
389  // This function will base64 ENCODE theData,
390  // and then Set() that as the string contents.
391  ascOutput.SetData(theData);
392  // bool bSuccessSetData = false;
393  // bSuccessSetData = ascOutput.SetData(theData);
394 
395  return true;
396  }
397  else
398  otErr << "OTCron::GetMarketList: 0 size, or null return value, "
399  "while getting raw data from packed buffer.\n";
400  }
401  else
402  otErr << "OTCron::GetMarketList: nMarketCount is less than zero: "
403  << nMarketCount << ".\n";
404 
405  return false;
406 }
407 
409 {
410  if (m_listTransactionNumbers.empty()) return 0;
411 
412  return static_cast<int32_t>(m_listTransactionNumbers.size());
413 }
414 
415 void OTCron::AddTransactionNumber(const int64_t& lTransactionNum)
416 {
417  m_listTransactionNumbers.push_back(lTransactionNum);
418 }
419 
420 // Once this starts returning 0, OTCron can no longer process trades and
421 // payment plans until the server object replenishes this list.
423 {
424  if (m_listTransactionNumbers.empty()) return 0;
425 
426  int64_t lTransactionNum = m_listTransactionNumbers.front();
427 
428  m_listTransactionNumbers.pop_front();
429 
430  return lTransactionNum;
431 }
432 
433 // return -1 if error, 0 if nothing, and 1 if the node was processed.
435 {
436  OT_ASSERT(nullptr != GetServerNym());
437 
438  int32_t nReturnVal = 0;
439 
440  // Here we call the parent class first.
441  // If the node is found there, or there is some error,
442  // then we just return either way. But if it comes back
443  // as '0', then nothing happened, and we'll continue executing.
444  //
445  // -- Note you can choose not to call the parent if
446  // you don't want to use any of those xml tags.
447  // As I do below, in the case of OTAccount.
448  // if (nReturnVal = OTContract::ProcessXMLNode(xml))
449  // return nReturnVal;
450 
451  if (!strcmp("cron", xml->getNodeName())) {
452  m_strVersion = xml->getAttributeValue("version");
453 
454  const OTString strServerID(xml->getAttributeValue("serverID"));
455 
456  m_SERVER_ID.SetString(strServerID);
457 
458  otOut << "\n\nLoading OTCron for ServerID: " << strServerID << "\n";
459 
460  nReturnVal = 1;
461  }
462  else if (!strcmp("transactionNum", xml->getNodeName())) {
463  const int64_t lTransactionNum = atol(xml->getAttributeValue("value"));
464 
465  otWarn << "Transaction Number " << lTransactionNum
466  << " available for Cron.\n";
467 
468  AddTransactionNumber(lTransactionNum); // This doesn't save to disk.
469  // Make sure to save Cron when it
470  // changes.
471 
472  nReturnVal = 1;
473  }
474  else if (!strcmp("cronItem", xml->getNodeName())) {
475  const OTString str_date_added = xml->getAttributeValue("dateAdded");
476  const int64_t lDateAdded =
477  (!str_date_added.Exists() ? 0 : str_date_added.ToLong());
478  const time64_t tDateAdded = OTTimeGetTimeFromSeconds(lDateAdded);
479 
480  OTString strData;
481 
482  if (!OTContract::LoadEncodedTextField(xml, strData) ||
483  !strData.Exists()) {
484  otErr << "Error in OTCron::ProcessXMLNode: cronItem field without "
485  "value.\n";
486  return (-1); // error condition
487  }
488  else {
489  OTCronItem* pItem = OTCronItem::NewCronItem(strData);
490 
491  if (nullptr == pItem) {
492  otErr << "Unable to create cron item from data in cron file.\n";
493  return (-1);
494  }
495 
496  // Why not do this here (when loading from storage), as well as when
497  // first adding the item to cron,
498  // and thus save myself the trouble of verifying the signature EVERY
499  // ITERATION of ProcessCron().
500  //
501  if (!pItem->VerifySignature(*m_pServerNym)) {
502  otErr << "OTCron::ProcessXMLNode: ERROR SECURITY: Server "
503  "signature failed to "
504  "verify on a cron item while loading: "
505  << pItem->GetTransactionNum() << "\n";
506  delete pItem;
507  pItem = nullptr;
508  return (-1);
509  }
510  else if (AddCronItem(*pItem, nullptr,
511  false, // bSaveReceipt=false. The receipt is
512  // only saved once: When item FIRST
513  // added to cron...
514  tDateAdded)) { // ...But here, the item was
515  // ALREADY in cron, and is
516  // merely being loaded from
517  // disk.
518  // Thus, it would be wrong to try to create the "original
519  // record" as if it were brand
520  // new and still had the user's signature on it. (Once added to
521  // Cron, the signatures are
522  // released and the SERVER signs it from there. That's why the
523  // user's version is saved
524  // as a receipt in the first place -- so we have a record of the
525  // user's authorization.)
526  otInfo << "Successfully loaded cron item and added to list.\n";
527  }
528  else {
529  otErr << "OTCron::ProcessXMLNode: Though loaded / verified "
530  "successfully, "
531  "unable to add cron item (from cron file) to cron "
532  "list.\n";
533  delete pItem;
534  pItem = nullptr;
535  return (-1);
536  }
537  }
538 
539  nReturnVal = 1;
540  }
541  else if (!strcmp("market", xml->getNodeName())) {
542  const OTString strMarketID(xml->getAttributeValue("marketID"));
543  const OTString strAssetID(xml->getAttributeValue("assetID"));
544  const OTString strCurrencyID(xml->getAttributeValue("currencyID"));
545 
546  const int64_t lScale = atol(xml->getAttributeValue("marketScale"));
547 
548  const OTIdentifier ASSET_ID(strAssetID), CURRENCY_ID(strCurrencyID);
549 
550  otWarn << "Loaded cron entry for Market:\n" << strMarketID << ".\n";
551 
552  // LoadMarket() needs this info to do its thing.
553  OTMarket* pMarket =
554  new OTMarket(m_SERVER_ID, ASSET_ID, CURRENCY_ID, lScale);
555 
556  OT_ASSERT(nullptr != pMarket);
557 
558  pMarket->SetCronPointer(
559  *this); // This way every Market has a pointer to Cron.
560 
561  // AddMarket normally saves to file, but we don't want that when
562  // we're LOADING from file, now do we?
563  if (!pMarket->LoadMarket() ||
564  !pMarket->VerifySignature(*GetServerNym()) ||
565  !AddMarket(*pMarket, false)) // bSaveFile=false: don't save this
566  // file WHILE loading it!!!
567  {
568  otErr << "Somehow error while loading, verifying, or adding market "
569  "while loading Cron file.\n";
570  delete pMarket;
571  pMarket = nullptr;
572  return (-1);
573  }
574  else {
575  otWarn << "Loaded market entry from cronfile, and also loaded the "
576  "market file itself.\n";
577  }
578  nReturnVal = 1;
579  }
580 
581  return nReturnVal;
582 }
583 
585 {
586  // I release this because I'm about to repopulate it.
588 
589  m_xmlUnsigned.Concatenate("<?xml version=\"%s\"?>\n\n", "1.0");
590 
591  const OTString SERVER_ID(m_SERVER_ID);
592 
593  m_xmlUnsigned.Concatenate("<cron\n version=\"%s\"\n"
594  " serverID=\"%s\""
595  " >\n\n",
596  m_strVersion.Get(), SERVER_ID.Get());
597 
598  // Save the Market entries (the markets themselves are saved in a markets
599  // folder.)
600  for (auto& it : m_mapMarkets) {
601  OTMarket* pMarket = it.second;
602  OT_ASSERT(nullptr != pMarket);
603 
604  OTIdentifier MARKET_ID(*pMarket);
605  OTString str_MARKET_ID(MARKET_ID);
606 
607  OTString str_ASSET_ID(pMarket->GetAssetID());
608  OTString str_CURRENCY_ID(pMarket->GetCurrencyID());
609 
610  m_xmlUnsigned.Concatenate("<market\n marketID=\"%s\"\n"
611  " assetID=\"%s\"\n"
612  " currencyID=\"%s\"\n"
613  " marketScale=\"%lld\""
614  " />\n\n",
615  str_MARKET_ID.Get(), str_ASSET_ID.Get(),
616  str_CURRENCY_ID.Get(), pMarket->GetScale());
617  }
618 
619  // Save the Cron Items
620  for (auto& it : m_multimapCronItems) {
621  OTCronItem* pItem = it.second;
622  OT_ASSERT(nullptr != pItem);
623 
624  time64_t tDateAdded = it.first;
625  int64_t lDateAdded = OTTimeGetSecondsFromTime(tDateAdded);
626 
627  OTString strItem(
628  *pItem); // Extract the cron item contract into string form.
629  OTASCIIArmor ascItem(strItem); // Base64-encode that for storage.
630 
631  m_xmlUnsigned.Concatenate("<cronItem dateAdded=\"%" PRId64
632  "\" >\n%s</cronItem>\n\n",
633  lDateAdded, ascItem.Get());
634  }
635 
636  // Save the transaction numbers.
637  //
638  for (auto& lTransactionNumber : m_listTransactionNumbers) {
639  m_xmlUnsigned.Concatenate("<transactionNum value=\"%lld\" />\n\n",
640  lTransactionNumber);
641  } // for
642 
643  m_xmlUnsigned.Concatenate("</cron>\n");
644 }
645 
646 // Make sure to call this regularly so the CronItems get a chance to process and
647 // expire.
649 {
650 
651  if (!m_bIsActivated) {
652  otErr << "OTCron::ProcessCronItems: Not activated yet. (Skipping.)\n";
653  return;
654  }
655 
656  // CRON RUNS ON A TIMER...
657  static Timer tCron(true);
658  static double cron_tick1 = tCron.getElapsedTimeInMilliSec();
659  double cron_tick2 = tCron.getElapsedTimeInMilliSec();
660  const int64_t cron_elapsed = static_cast<int64_t>(cron_tick2 - cron_tick1);
661 
662  if (cron_elapsed <= OTCron::GetCronMsBetweenProcess()) {
663  return;
664  }
665  cron_tick1 = tCron.getElapsedTimeInMilliSec();
666 
667  const int32_t nTwentyPercent = OTCron::GetCronRefillAmount() / 5;
668  if (GetTransactionCount() <= nTwentyPercent) {
669  otErr << "WARNING: Cron has fewer than 20 percent of its normal "
670  "transaction number count available since the previous round! "
671  "\n"
672  "That is, " << GetTransactionCount()
673  << " are currently available, with a max of "
674  << OTCron::GetCronRefillAmount() << ", meaning "
676  << " were used in the last round alone!!! \n"
677  "SKIPPING THE CRON ITEMS THAT WERE SCHEDULED FOR THIS "
678  "ROUND!!!\n\n";
679  return;
680  }
681  bool bNeedToSave = false;
682 
683  // loop through the cron items and tell each one to ProcessCron().
684  // If the item returns true, that means leave it on the list. Otherwise,
685  // if it returns false, that means "it's done: remove it."
686  for (auto it = m_multimapCronItems.begin();
687  it != m_multimapCronItems.end();) {
688  if (GetTransactionCount() <= nTwentyPercent) {
689  otErr << "WARNING: Cron has fewer than 20 percent of its normal "
690  "transaction "
691  "number count available since the previous cron item "
692  "alone! \n"
693  "That is, " << GetTransactionCount()
694  << " are currently available, with a max of "
695  << OTCron::GetCronRefillAmount() << ", meaning "
697  << " were used in the current round alone!!! \n"
698  "SKIPPING THE REMAINDER OF THE CRON ITEMS THAT WERE "
699  "SCHEDULED FOR THIS ROUND!!!\n\n";
700  break;
701  }
702  OTCronItem* pItem = it->second;
703  OT_ASSERT(nullptr != pItem);
704  otInfo << "OTCron::" << __FUNCTION__
705  << ": Processing item number: " << pItem->GetTransactionNum()
706  << " \n";
707 
708  if (pItem->ProcessCron()) {
709  it++;
710  continue;
711  }
713  otOut << "OTCron::" << __FUNCTION__
714  << ": Removing cron item: " << pItem->GetTransactionNum() << "\n";
715  it = m_multimapCronItems.erase(it);
716  auto it_map = FindItemOnMap(pItem->GetTransactionNum());
717  OT_ASSERT(m_mapCronItems.end() != it_map);
718  m_mapCronItems.erase(it_map);
719 
720  delete pItem;
721  pItem = nullptr;
722 
723  bNeedToSave = true;
724  }
725  if (bNeedToSave) SaveCron();
726 }
727 
728 // OTCron IS responsible for cleaning up theItem, and takes ownership.
729 // So make SURE it is allocated on the HEAP before you pass it in here, and
730 // also make sure to delete it again if this call fails!
731 bool OTCron::AddCronItem(OTCronItem& theItem, OTPseudonym* pActivator,
732  bool bSaveReceipt, time64_t tDateAdded)
733 {
734  OT_ASSERT(nullptr != GetServerNym());
735 
736  // See if there's something else already there with the same transaction
737  // number.
738  OTCronItem* pCronItem = GetItemByOfficialNum(theItem.GetTransactionNum());
739 
740  // If it's not already on the list, then add it...
741  if (nullptr == pCronItem) {
742  // If I've been instructed to save the receipt, and theItem did NOT
743  // successfully save the receipt,
744  // then return false.
745  //
746  // This will happen if filesystem problems, but it will also happen if
747  // the cron item WAS ALREADY THERE.
748  // I don't want to save over it. If I'm trying to save over one that is
749  // already there, then THAT is the
750  // real problem.
751  //
752  if (bSaveReceipt &&
753  (!theItem.SignContract(*GetServerNym()) || // Notice the server adds
754  // its signature
755  // before saving the cron receipt to local
756  // storage. This way, the server can
757  // verify its own signature later, as
758  // evidence the file hasn't been tampered
759  // with. (BOTH signatures are there
760  // now--user's and server's.)
761  !theItem.SaveContract() || !theItem.SaveCronReceipt())) {
762  otErr << __FUNCTION__ << ": Error saving receipt while adding new "
763  "CronItem to Cron.\n";
764  return false;
765  }
766 
767  // Insert to the MAP (by Transaction Number)
768  //
769  m_mapCronItems.insert(std::pair<int64_t, OTCronItem*>(
770  theItem.GetTransactionNum(), &theItem));
771 
772  // Insert to the MULTIMAP (by Date)
773  //
774  m_multimapCronItems.insert(
775  m_multimapCronItems.upper_bound(tDateAdded),
776  std::pair<time64_t, OTCronItem*>(tDateAdded, &theItem));
777 
778  theItem.SetCronPointer(*this);
779  theItem.setServerNym(m_pServerNym);
780  theItem.setServerId(&m_SERVER_ID);
781 
782  bool bSuccess = true;
783 
784  theItem.HookActivationOnCron(
785  pActivator, // (OTPseudonym* pActivator) // sometimes nullptr.
786  bSaveReceipt); // If merely being reloaded after server reboot, this
787  // is false.
788  // But if actually being activated for the first time, then this is
789  // true.
790 
791  // When an item is added to Cron for the first time, a copy of it is
792  // saved to the
793  // cron folder, and it has the user's original signature on it. (If it's
794  // a Trade,
795  // it also contains an Offer with the user's original signature.) This
796  // occurs
797  // wherever this function is called with bSaveReceipt=true.
798  //
799  if (bSaveReceipt) // This executes only the first time that an item is
800  // added to Cron.
801  // (versus when it's just being reloaded from file and added back to
802  // the internal list.)
803  {
804  // Now that a copy of the cronitem is safely stored, I can release
805  // the signature on it
806  // and sign it with the Server's Nym instead. That way I can use the
807  // server to verify
808  // all cron and market-related activity from here on out.
809  // theItem.ReleaseSignatures();
810  // theItem.SignContract(*GetServerNym()); // THIS IS NOW
811  // DONE ABOVE. See if (bSaveReceipt) ...
812  // theItem.SaveContract();
813 
814  // Since we added an item to the Cron, we SAVE it.
815  bSuccess = SaveCron();
816 
817  if (bSuccess)
818  otOut << __FUNCTION__
819  << ": New CronItem has been added to Cron: "
820  << theItem.GetTransactionNum() << "\n";
821  else
822  otErr << __FUNCTION__
823  << ": Error saving while adding new CronItem to Cron: "
824  << theItem.GetTransactionNum() << "\n";
825  }
826 
827  return bSuccess;
828  }
829  // Otherwise, if it was already there, log an error.
830  else {
831  otErr << __FUNCTION__
832  << ": Failed attempt to add CronItem with pre-existing "
833  "transaction number: " << theItem.GetTransactionNum() << "\n";
834  }
835 
836  return false;
837 }
838 
839 bool OTCron::RemoveCronItem(int64_t lTransactionNum,
840  OTPseudonym& theRemover) // if returns false, item
841  // wasn't found.
842 {
843  // See if there's a cron item with that transaction number.
844  auto it_map = FindItemOnMap(lTransactionNum);
845 
846  // If it's not already on the list, then there's nothing to remove.
847  if (m_mapCronItems.end() == it_map) {
848  otErr << __FUNCTION__
849  << ": Attempt to remove non-existent CronItem from OTCron. "
850  "Transaction #: " << lTransactionNum << "\n";
851  }
852 
853  // Otherwise, if it WAS already there, remove it properly.
854  else {
855  OTCronItem* pItem = it_map->second;
856  // OT_ASSERT(nullptr != pItem); // Already done in FindItemOnMap.
857 
858  // We have to remove it from the multimap as well.
859  auto it_multimap = FindItemOnMultimap(lTransactionNum);
860  OT_ASSERT(m_multimapCronItems.end() !=
861  it_multimap); // If found on map, MUST be on multimap also.
862 
863  pItem->HookRemovalFromCron(&theRemover, GetNextTransactionNumber());
864 
865  m_mapCronItems.erase(it_map); // Remove from MAP.
866  m_multimapCronItems.erase(it_multimap); // Remove from MULTIMAP.
867 
868  delete pItem;
869 
870  // An item has been removed from Cron. SAVE.
871  return SaveCron();
872  }
873 
874  return false;
875 }
876 
877 // Look up a transaction by transaction number and see if it is in the map.
878 // If it is, return an iterator to it, otherwise return m_mapCronItems.end()
879 //
880 // Note: only the "official" transaction number will work here.
881 // If the cron item contains multiple opening numbers, the only one
882 // that will work in this function is the "official" one, the one that
883 // belongs to the Nym who actually activated this Cron Item.
884 //
885 mapOfCronItems::iterator OTCron::FindItemOnMap(int64_t lTransactionNum)
886 {
887  // See if there's something there with lTransactionNum
888  // as its "official" number.
889  //
890  auto itt = m_mapCronItems.find(lTransactionNum);
891 
892  if (itt != m_mapCronItems.end()) // Found it!
893  {
894  OTCronItem* pItem = itt->second;
895  OT_ASSERT((nullptr != pItem));
896  OT_ASSERT(pItem->GetTransactionNum() == lTransactionNum);
897 
898  return itt;
899  }
900 
901  return itt;
902 }
903 
904 // Look up a transaction by transaction number and see if it is in the multimap.
905 // If it is, return an iterator to it, otherwise return
906 // m_multimapCronItems.end()
907 //
908 // Note: only the "official" transaction number will work here.
909 // If the cron item contains multiple opening numbers, the only one
910 // that will work in this function is the "official" one, the one that
911 // belongs to the Nym who actually activated this Cron Item.
912 //
913 multimapOfCronItems::iterator OTCron::FindItemOnMultimap(
914  int64_t lTransactionNum)
915 {
916  auto itt = m_multimapCronItems.begin();
917 
918  while (m_multimapCronItems.end() != itt) {
919  OTCronItem* pItem = itt->second;
920  OT_ASSERT((nullptr != pItem));
921 
922  if (pItem->GetTransactionNum() == lTransactionNum) break;
923 
924  ++itt;
925  }
926 
927  return itt;
928 }
929 
930 // Look up a transaction by transaction number and see if it is in the map.
931 // If it is, return a pointer to it, otherwise return nullptr.
932 //
933 // Note: only the "official" transaction number will work here.
934 // If the cron item contains multiple opening numbers, the only one
935 // that will work in this function is the "official" one, the one that
936 // belongs to the Nym who actually activated this Cron Item.
937 //
938 OTCronItem* OTCron::GetItemByOfficialNum(int64_t lTransactionNum)
939 {
940  // See if there's something there with lTransactionNum
941  // as its "official" number.
942  //
943  auto itt = m_mapCronItems.find(lTransactionNum);
944 
945  if (itt != m_mapCronItems.end()) // Found it!
946  {
947  OTCronItem* pItem = itt->second;
948  OT_ASSERT((nullptr != pItem));
949  OT_ASSERT(pItem->GetTransactionNum() == lTransactionNum);
950 
951  return pItem;
952  }
953 
954  return nullptr;
955 }
956 
957 // Look up a transaction by opening number and see if it is in the map.
958 // If it is, return a pointer to it, otherwise return nullptr.
959 //
960 // Note: The "official" transaction number for a cron item belongs
961 // to to the Nym who activated it. But there are several "valid"
962 // opening numbers, each belonging to a different Nym who signed the
963 // Cron Item.
964 //
965 // This function searches based on any valid opening number, not necessarily
966 // by the one "official" number.
967 //
969 {
970  // See if there's something there with that transaction number.
971  auto itt = m_mapCronItems.find(lOpeningNum);
972 
973  if (itt == m_mapCronItems.end()) {
974  // We didn't find it as the "official" number, so let's loop
975  // through the cron items one-by-one and see if it's a valid
976  // opening number. (We searched for the "official" number first,
977  // since it will often be the right one, and avoids doing this
978  // longer search. Basically for optimization purposes.)
979  //
980  for (auto& it : m_mapCronItems) {
981  OTCronItem* pItem = it.second;
982  OT_ASSERT((nullptr != pItem));
983 
984  if (pItem->IsValidOpeningNumber(lOpeningNum)) // Todo optimization.
985  // Probably can remove
986  // this check.
987  return pItem;
988  }
989  }
990  // Found it!
991  else {
992  OTCronItem* pItem = itt->second;
993  OT_ASSERT((nullptr != pItem));
995  lOpeningNum)); // Todo optimization. Probably can remove this check.
996 
997  return pItem;
998  }
999 
1000  return nullptr;
1001 }
1002 
1003 // OTCron IS responsible for cleaning up theMarket, and takes ownership.
1004 // So make SURE it is allocated on the HEAP before you pass it in here, and
1005 // also make sure to delete it again if this call fails!
1006 bool OTCron::AddMarket(OTMarket& theMarket, bool bSaveMarketFile)
1007 {
1008  OT_ASSERT(nullptr != GetServerNym());
1009 
1010  theMarket.SetCronPointer(
1011  *this); // This way every Market has a pointer to Cron.
1012 
1013  OTIdentifier MARKET_ID(theMarket);
1014  OTString str_MARKET_ID(MARKET_ID);
1015  std::string std_MARKET_ID = str_MARKET_ID.Get();
1016 
1017  // See if there's something else already there with the same market ID.
1018  auto it = m_mapMarkets.find(std_MARKET_ID);
1019 
1020  // If it's not already on the list, then add it...
1021  if (it == m_mapMarkets.end()) {
1022  // If I've been instructed to save the market, and Cron did NOT
1023  // successfully save the market
1024  // (to its own file), then return false. This will happen if
1025  // filesystem problems.
1026  if (bSaveMarketFile && !theMarket.SaveMarket()) {
1027  otErr
1028  << "Error saving market file while adding new Market to Cron:\n"
1029  << std_MARKET_ID << "\n";
1030  return false;
1031  }
1032 
1033  m_mapMarkets[std_MARKET_ID] = &theMarket;
1034 
1035  bool bSuccess = true;
1036 
1037  // When Cron serializes, it stores a list of all its markets in the main
1038  // cron file.
1039  // The actual markets themselves serialize separately to the market
1040  // folder.
1041  //
1042  if (bSaveMarketFile) // This executes only the first time that a market
1043  // is added to Cron.
1044  // (versus when it's just being reloaded from file and added back to
1045  // the internal list.)
1046  {
1047  // Since we added a market to the Cron, we SAVE it.
1048  bSuccess = SaveCron(); // If we're loading from file, and
1049  // bSaveMarketFile is false, I don't want to
1050  // save here. that's why it's in this block.
1051 
1052  if (bSuccess)
1053  otLog3 << "New Market has been added to Cron.\n";
1054  else
1055  otErr << "Error saving while adding new Market to Cron.\n";
1056  }
1057 
1058  return bSuccess;
1059  }
1060  // Otherwise, if it was already there, log an error.
1061  else {
1062  otErr << "Attempt to add Market that was already there: "
1063  << std_MARKET_ID << "\n";
1064  }
1065 
1066  return false;
1067 }
1068 
1069 // Create it if it's not there.
1071  const OTIdentifier& CURRENCY_ID,
1072  const int64_t& lScale)
1073 {
1074  OTMarket* pMarket =
1075  new OTMarket(GetServerID(), ASSET_ID, CURRENCY_ID, lScale);
1076 
1077  OT_ASSERT(nullptr != pMarket);
1078 
1079  OTIdentifier MARKET_ID(*pMarket);
1080 
1081  OTMarket* pExistingMarket = GetMarket(MARKET_ID);
1082 
1083  // If it was already there, there's no need to create it.
1084  if (nullptr != pExistingMarket) {
1085  delete pMarket;
1086  pMarket = nullptr;
1087  return pExistingMarket;
1088  }
1089 
1090  // If we got this far, it means the Market does NOT already exist in this
1091  // Cron.
1092  // So let's add it...
1093  bool bAdded = AddMarket(
1094  *pMarket, true); // bool bSaveMarketFile=true, since it was created new.
1095 
1096  if (bAdded) {
1097  otOut << "New market created and added to Cron.\n";
1098  }
1099  else {
1100  otErr << "Error trying to add new market to Cron.\n";
1101  delete pMarket;
1102  pMarket = nullptr;
1103  }
1104 
1105  return pMarket;
1106 }
1107 
1108 // Look up a transaction by transaction number and see if it is in the ledger.
1109 // If it is, return a pointer to it, otherwise return nullptr.
1111 {
1112  OTString str_MARKET_ID(MARKET_ID);
1113  std::string std_MARKET_ID = str_MARKET_ID.Get();
1114 
1115  // See if there's something there with that transaction number.
1116  auto it = m_mapMarkets.find(std_MARKET_ID);
1117 
1118  if (it == m_mapMarkets.end()) {
1119  // nothing found.
1120  return nullptr;
1121  }
1122  // Found it!
1123  else {
1124  OTMarket* pMarket = it->second;
1125 
1126  OT_ASSERT((nullptr != pMarket));
1127 
1128  const OTIdentifier LOOP_MARKET_ID(*pMarket);
1129  const OTString str_LOOP_MARKET_ID(LOOP_MARKET_ID);
1130 
1131  if (MARKET_ID == LOOP_MARKET_ID)
1132  return pMarket;
1133  else
1134  otErr << "Expected Market with ID:\n" << std_MARKET_ID
1135  << "\n but found " << str_LOOP_MARKET_ID << "\n";
1136  }
1137 
1138  return nullptr;
1139 }
1140 
1142  : ot_super()
1143  , m_bIsActivated(false)
1144  , m_pServerNym(nullptr) // just here for convenience, not responsible to
1145  // cleanup this pointer.
1146 {
1147  InitCron();
1148  otLog3 << "OTCron::OTCron: Finished calling InitCron 0.\n";
1149 }
1150 
1151 OTCron::OTCron(const OTIdentifier& SERVER_ID)
1152  : ot_super()
1153  , m_bIsActivated(false)
1154  , m_pServerNym(nullptr) // just here for convenience, not responsible to
1155  // cleanup this pointer.
1156 {
1157  InitCron();
1158  SetServerID(SERVER_ID);
1159  otLog3 << "OTCron::OTCron: Finished calling InitCron 1.\n";
1160 }
1161 
1162 OTCron::OTCron(const char* szFilename)
1163  : ot_super()
1164  , m_bIsActivated(false)
1165  , m_pServerNym(nullptr) // just here for convenience, not responsible to
1166  // cleanup this pointer.
1167 {
1168  OT_ASSERT(nullptr != szFilename);
1169  InitCron();
1170 
1172  m_strFilename.Set(szFilename);
1173  otLog3 << "OTCron::OTCron: Finished calling InitCron 2.\n";
1174 }
1175 
1177 {
1178  Release_Cron();
1179 
1180  m_pServerNym = nullptr;
1181 }
1182 
1184 {
1185  m_strContractType = "CRON";
1186 }
1187 
1189 {
1190  Release_Cron();
1191 
1193 }
1194 
1196 {
1197  // If there were any dynamically allocated objects, clean them up here.
1198 
1199  while (!m_multimapCronItems.empty()) {
1200  auto it = m_multimapCronItems.begin();
1201  m_multimapCronItems.erase(it);
1202 
1203  // We don't delete the pItem in here, since these are the
1204  // same pItems being deleted in the next block.
1205  }
1206 
1207  while (!m_mapCronItems.empty()) {
1208  OTCronItem* pItem = m_mapCronItems.begin()->second;
1209  auto it = m_mapCronItems.begin();
1210  m_mapCronItems.erase(it);
1211  delete pItem;
1212  pItem = nullptr;
1213  }
1214 
1215  while (!m_mapMarkets.empty()) {
1216  OTMarket* pMarket = m_mapMarkets.begin()->second;
1217  auto it = m_mapMarkets.begin();
1218  m_mapMarkets.erase(it);
1219  delete pMarket;
1220  pMarket = nullptr;
1221  }
1222 }
1223 
1224 bool OTCron::SaveContractWallet(std::ofstream&) const
1225 {
1226  return true;
1227 }
1228 
1229 } // namespace opentxs
OTMarket * GetOrCreateMarket(const OTIdentifier &ASSET_ID, const OTIdentifier &CURRENCY_ID, const int64_t &lScale)
Definition: OTCron.cpp:1070
EXPORT Storage * GetDefaultStorage()
Definition: OTStorage.cpp:480
EXPORT void AddTransactionNumber(const int64_t &lTransactionNum)
Definition: OTCron.cpp:415
int64_t GetNextTransactionNumber()
Definition: OTCron.cpp:422
EXPORT Storable * CreateObject(StoredObjectType eType)
Definition: OTStorage.cpp:530
Definition: Timer.hpp:31
virtual void UpdateContents()
Definition: OTCron.cpp:584
EXPORT double getElapsedTimeInMilliSec()
Definition: Timer.cpp:111
void SetServerID(const OTIdentifier &SERVER_ID)
Definition: OTCron.hpp:289
EXPORT bool SaveCron()
Definition: OTCron.cpp:179
EXPORT bool SaveCronReceipt()
Definition: OTCronItem.cpp:577
PackedBuffer * Pack(Storable &inObj)
Definition: OTStorage.cpp:930
int64_t GetTransactionNum() const
virtual bool IsValidOpeningNumber(const int64_t &lOpeningNum) const
bool GetNym_OfferList(const OTIdentifier &NYM_ID, OTDB::OfferListNym &theOutputList, int32_t &nNymOfferCount)
Definition: OTMarket.cpp:310
EXPORT bool SaveContract()
EXPORT int64_t ToLong() const
Definition: OTString.cpp:702
void HookRemovalFromCron(OTPseudonym *pRemover, int64_t newTransactionNo)
Definition: OTCronItem.cpp:815
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
EXPORT bool AddCronItem(OTCronItem &theItem, OTPseudonym *pActivator, bool bSaveReceipt, time64_t tDateAdded)
Definition: OTCron.cpp:731
virtual bool SaveContractWallet(std::ofstream &ofs) const
Definition: OTCron.cpp:1224
mapOfOffers::size_type GetBidCount()
Definition: OTMarket.hpp:243
EXPORT OTCronItem * GetItemByOfficialNum(int64_t lTransactionNum)
Definition: OTCron.cpp:938
OTLOG_IMPORT OTLogStream otOut
const OTIdentifier & GetCurrencyID() const
Definition: OTMarket.hpp:268
const OTIdentifier & GetServerID() const
Definition: OTCron.hpp:293
OTLOG_IMPORT OTLogStream otLog3
int64_t GetLowestAskPrice()
Definition: OTMarket.cpp:934
time64_t OTTimeGetTimeFromSeconds(int64_t seconds)
Definition: Common.hpp:215
const OTIdentifier & GetServerID() const
Definition: OTMarket.hpp:272
EXPORT OTCronItem * GetItemByValidOpeningNum(int64_t lOpeningNum)
Definition: OTCron.cpp:968
EXPORT mapOfCronItems::iterator FindItemOnMap(int64_t lTransactionNum)
Definition: OTCron.cpp:885
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
int64_t time64_t
Definition: Common.hpp:209
const OTIdentifier & GetAssetID() const
Definition: OTMarket.hpp:264
EXPORT void ReleaseSignatures()
Definition: OTContract.cpp:989
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT void SetString(const char *szString)
EXPORT OTCron()
Definition: OTCron.cpp:1141
void SetCronPointer(OTCron &theCron)
Definition: OTCronItem.hpp:246
EXPORT multimapOfCronItems::iterator FindItemOnMultimap(int64_t lTransactionNum)
Definition: OTCron.cpp:913
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
Definition: OTString.cpp:1055
virtual bool ProcessCron()
Definition: OTCronItem.cpp:769
EXPORT void ProcessCronItems()
Definition: OTCron.cpp:648
bool AddMarket(OTMarket &theMarket, bool bSaveMarketFile=true)
Definition: OTCron.cpp:1006
void InitCron()
Definition: OTCron.cpp:1183
EXPORT bool LoadCron()
Definition: OTCron.cpp:165
static EXPORT bool LoadEncodedTextField(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
virtual void Release()
Definition: OTCron.cpp:1188
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTString m_strContractType
Definition: OTContract.hpp:178
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
Definition: OTCron.cpp:434
OTLOG_IMPORT OTLogStream otInfo
virtual EXPORT bool LoadContract()
virtual EXPORT ~OTCron()
Definition: OTCron.cpp:1176
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
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 Release_Cron()
Definition: OTCron.cpp:1195
const int64_t & GetScale() const
Definition: OTMarket.hpp:277
OTLOG_IMPORT OTLogStream otErr
void setServerNym(OTPseudonym *serverNym)
Definition: OTCronItem.hpp:297
mapOfOffers::size_type GetAskCount()
Definition: OTMarket.hpp:247
EXPORT OTPacker * GetPacker(PackType ePackType=OTDB_DEFAULT_PACKER)
Definition: OTStorage.cpp:2103
void setServerId(OTIdentifier *serverId)
Definition: OTCronItem.hpp:301
virtual EXPORT void Release()
Definition: OTContract.cpp:277
EXPORT int32_t GetTransactionCount() const
Definition: OTCron.cpp:408
OTPseudonym * GetServerNym() const
Definition: OTCron.hpp:303
int64_t GetHighestBidPrice()
Definition: OTMarket.cpp:919
virtual EXPORT bool VerifySignature(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
Definition: OTContract.cpp:818
static int32_t GetCronRefillAmount()
Definition: OTCron.hpp:205
static EXPORT const OTString & Cron()
Definition: OTFolders.cpp:311
EXPORT bool SetData(const OTData &theData, bool bLineBreaks=true)
EXPORT bool GetMarketList(OTASCIIArmor &ascOutput, int32_t &nMarketCount)
Definition: OTCron.cpp:281
EXPORT bool GetNym_OfferList(OTASCIIArmor &ascOutput, const OTIdentifier &NYM_ID, int32_t &nOfferCount)
Definition: OTCron.cpp:204
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
int64_t GetTotalAvailableAssets()
Definition: OTMarket.cpp:294
const int64_t & GetLastSalePrice()
Definition: OTMarket.hpp:287
EXPORT OTMarket * GetMarket(const OTIdentifier &MARKET_ID)
Definition: OTCron.cpp:1110
const std::string & GetLastSaleDate()
Definition: OTMarket.hpp:298
static int32_t GetCronMsBetweenProcess()
Definition: OTCron.hpp:196
void HookActivationOnCron(OTPseudonym *pActivator, bool bForTheFirstTime=false)
Definition: OTCronItem.cpp:797
virtual EXPORT void Release()
Definition: OTString.cpp:765
void SetCronPointer(OTCron &theCron)
Definition: OTMarket.hpp:313
static EXPORT OTCronItem * NewCronItem(const OTString &strCronItem)
Definition: OTCronItem.cpp:165
EXPORT bool RemoveCronItem(int64_t lTransactionNum, OTPseudonym &theRemover)
Definition: OTCron.cpp:839
OTString m_strFoldername
Definition: OTContract.hpp:169