Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Mint.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * Mint.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 "../core/stdafx.hpp"
134 
135 #include "Mint.hpp"
136 #include "MintLucre.hpp"
137 
138 #include "../core/crypto/OTAsymmetricKey.hpp"
139 #include "../core/OTAccount.hpp"
140 #include "../core/util/OTFolders.hpp"
141 #include "../core/OTLog.hpp"
142 #include "../core/OTMessage.hpp"
143 #include "../core/OTStorage.hpp"
144 
145 #include <irrxml/irrXML.hpp>
146 
147 #if defined(OT_CASH_USING_LUCRE)
148 #endif
149 
150 namespace opentxs
151 {
152 
153 // static
155 {
156  Mint* pMint = nullptr;
157 
158 #if defined(OT_CASH_USING_LUCRE)
159  pMint = new MintLucre;
160 #elif defined(OT_CASH_USING_MAGIC_MONEY)
161  // pMint = new Mint_MagicMoney;
162  otErr << __FUCNTION__ << ": Open-Transactions doesn't support Magic Money "
163  "by Pr0duct Cypher (yet), "
164  << "so it's impossible to instantiate a mint.\n";
165 #else
166  otErr
167  << __FUNCTION__
168  << ": Open-Transactions isn't built with any digital cash algorithms, "
169  << "so it's impossible to instantiate a mint.\n";
170 #endif
171  return pMint;
172 }
173 
174 // static
175 Mint* Mint::MintFactory(const OTString& strServerID,
176  const OTString& strAssetTypeID)
177 {
178  Mint* pMint = nullptr;
179 
180 #if defined(OT_CASH_USING_LUCRE)
181  pMint = new MintLucre(strServerID, strAssetTypeID);
182 #elif defined(OT_CASH_USING_MAGIC_MONEY)
183  // pMint = new OTMint_MagicMoney;
184  otErr << __FUNCTION__ << ": Open-Transactions doesn't support Magic Money "
185  "by Pr0duct Cypher (yet), "
186  << "so it's impossible to instantiate a mint.\n";
187 #else
188  otErr
189  << __FUNCTION__
190  << ": Open-Transactions isn't built with any digital cash algorithms, "
191  << "so it's impossible to instantiate a mint.\n";
192 #endif
193  return pMint;
194 }
195 
196 // static
197 Mint* Mint::MintFactory(const OTString& strServerID,
198  const OTString& strServerNymID,
199  const OTString& strAssetTypeID)
200 {
201  Mint* pMint = nullptr;
202 
203 #if defined(OT_CASH_USING_LUCRE)
204  pMint = new MintLucre(strServerID, strServerNymID, strAssetTypeID);
205 #elif defined(OT_CASH_USING_MAGIC_MONEY)
206  // pMint = new OTMint_MagicMoney;
207  otErr << __FUNCTION__ << ": Open-Transactions doesn't support Magic Money "
208  "by Pr0duct Cypher (yet), "
209  << "so it's impossible to instantiate a mint.\n";
210 #else
211  otErr
212  << __FUNCTION__
213  << ": Open-Transactions isn't built with any digital cash algorithms, "
214  << "so it's impossible to instantiate a mint.\n";
215 #endif
216  return pMint;
217 }
218 
219 // SUBCLASSES OF OTMINT FOR EACH DIGITAL CASH ALGORITHM.
220 
221 #if defined(OT_CASH_USING_MAGIC_MONEY)
222 // Todo: Someday...
223 #endif // Magic Money
224 
225 // Verify the current date against the VALID FROM / EXPIRATION dates.
226 // (As opposed to tokens, which are verified against the valid from/to dates.)
227 bool Mint::Expired() const
228 {
229  const time64_t CURRENT_TIME = OTTimeGetCurrentTime();
230 
231  if ((CURRENT_TIME >= m_VALID_FROM) && (CURRENT_TIME <= m_EXPIRATION))
232  return false;
233  else
234  return true;
235 }
236 
238 {
239  while (!m_mapPublic.empty()) {
240  OTASCIIArmor* pArmor = m_mapPublic.begin()->second;
241  m_mapPublic.erase(m_mapPublic.begin());
242  delete pArmor;
243  pArmor = nullptr;
244  }
245  while (!m_mapPrivate.empty()) {
246  OTASCIIArmor* pArmor = m_mapPrivate.begin()->second;
247  m_mapPrivate.erase(m_mapPrivate.begin());
248  delete pArmor;
249  pArmor = nullptr;
250  }
251 }
252 
253 // If you want to load a certain Mint from string, then
254 // you will call LoadContractFromString() (say). Well this Releases the
255 // contract,
256 // before loading it, which calls InitMint() to zero out all the important
257 // pieces of
258 // data.
259 //
261 {
263 
265 
266  if (m_pReserveAcct) {
267  delete m_pReserveAcct;
268  m_pReserveAcct = nullptr;
269  }
270 }
271 
273 {
274  Release_Mint();
275 
276  ot_super::Release(); // I overrode the parent, so now I give him a chance to
277  // clean up.
278 
279  InitMint();
280 }
281 
283 {
284  Release_Mint();
285 
286  if (nullptr != m_pKeyPublic) {
287  delete m_pKeyPublic;
288  m_pKeyPublic = nullptr;
289  }
290  else
291  otErr << __FUNCTION__ << ": the logic: if (nullptr != m_pKeyPublic) "
292  "failed, though it NEVER should. "
293  "(That pointer should never be nullptr.)\n";
294 }
295 
297 {
298  m_strContractType.Set("MINT");
299 
301 
303  false; // Determines whether it serializes private keys (no if false)
304 
305  // Mints expire and new ones are rotated in.
306  // All tokens have the same series, and validity dates,
307  // of the mint that created them.
308  m_nSeries = 0;
312 
313  m_pReserveAcct = nullptr;
314 }
315 
316 Mint::Mint(const OTString& strServerID, const OTString& strServerNymID,
317  const OTString& strAssetTypeID)
318  : ot_super(strAssetTypeID)
319  , m_ServerID(strServerID)
320  , m_ServerNymID(strServerNymID)
321  , m_pKeyPublic(OTAsymmetricKey::KeyFactory())
322  , m_AssetID(strAssetTypeID)
323  , m_nDenominationCount(0)
324  , m_bSavePrivateKeys(false)
325  , m_nSeries(0)
326  , m_VALID_FROM(OT_TIME_ZERO)
327  , m_VALID_TO(OT_TIME_ZERO)
328  , m_EXPIRATION(OT_TIME_ZERO)
329  , m_pReserveAcct(nullptr)
330 {
332  m_strFilename.Format("%s%s%s", strServerID.Get(), OTLog::PathSeparator(),
333  strAssetTypeID.Get());
334 
335  InitMint();
336 }
337 
338 Mint::Mint(const OTString& strServerID, const OTString& strAssetTypeID)
339  : ot_super(strAssetTypeID)
340  , m_ServerID(strServerID)
341  , m_pKeyPublic(OTAsymmetricKey::KeyFactory())
342  , m_AssetID(strAssetTypeID)
343  , m_nDenominationCount(0)
344  , m_bSavePrivateKeys(false)
345  , m_nSeries(0)
346  , m_VALID_FROM(OT_TIME_ZERO)
347  , m_VALID_TO(OT_TIME_ZERO)
348  , m_EXPIRATION(OT_TIME_ZERO)
349  , m_pReserveAcct(nullptr)
350 {
352  m_strFilename.Format("%s%s%s", strServerID.Get(), OTLog::PathSeparator(),
353  strAssetTypeID.Get());
354 
355  InitMint();
356 }
357 
359  : ot_super()
360  , m_pKeyPublic(OTAsymmetricKey::KeyFactory())
361  , m_nDenominationCount(0)
362  , m_bSavePrivateKeys(false)
363  , m_nSeries(0)
364  , m_VALID_FROM(OT_TIME_ZERO)
365  , m_VALID_TO(OT_TIME_ZERO)
366  , m_EXPIRATION(OT_TIME_ZERO)
367  , m_pReserveAcct(nullptr)
368 {
369  InitMint();
370 }
371 
373 {
374  otOut << "Mint::LoadContract OVERRIDE.\n";
375  return LoadMint();
376 }
377 
378 bool Mint::LoadMint(const char* szAppend) // todo: server should
379  // always pass something
380  // here. client never
381  // should. Enforcement?
382 {
384 
385  const OTString strServerID(m_ServerID), strAssetTypeID(m_AssetID);
386 
387  if (!m_strFilename.Exists()) {
388  if (nullptr != szAppend)
389  m_strFilename.Format("%s%s%s%s", strServerID.Get(),
390  OTLog::PathSeparator(), // server appends ".1"
391  // or ".PUBLIC" here.
392  strAssetTypeID.Get(), szAppend);
393  else
395  "%s%s%s", strServerID.Get(), OTLog::PathSeparator(),
396  strAssetTypeID.Get()); // client uses only asset ID, no append.
397  }
398 
399  OTString strFilename;
400  if (nullptr != szAppend)
401  strFilename.Format("%s%s", strAssetTypeID.Get(),
402  szAppend); // server side
403  else
404  strFilename = strAssetTypeID.Get(); // client side
405 
406  const char* szFolder1name = OTFolders::Mint().Get(); // "mints"
407  const char* szFolder2name = strServerID.Get(); // "mints/SERVER_ID"
408  const char* szFilename =
409  strFilename.Get(); // "mints/SERVER_ID/ASSET_TYPE_ID<szAppend>"
410 
411  if (!OTDB::Exists(szFolder1name, szFolder2name, szFilename)) {
412  otOut << "Mint::LoadMint: File does not exist: " << szFolder1name
413  << OTLog::PathSeparator() << szFolder2name
414  << OTLog::PathSeparator() << szFilename << "\n";
415  return false;
416  }
417 
418  std::string strFileContents(
419  OTDB::QueryPlainString(szFolder1name, szFolder2name,
420  szFilename)); // <=== LOADING FROM DATA STORE.
421 
422  if (strFileContents.length() < 2) {
423  otErr << "Mint::LoadMint: Error reading file: " << szFolder1name
424  << OTLog::PathSeparator() << szFolder2name
425  << OTLog::PathSeparator() << szFilename << "\n";
426  return false;
427  }
428 
429  // NOTE: No need to worry about the OT ARMORED file format, since
430  // LoadContractFromString already handles that internally.
431 
432  OTString strRawFile(strFileContents.c_str());
433 
434  bool bSuccess = LoadContractFromString(
435  strRawFile); // Note: This handles OT ARMORED file format.
436 
437  return bSuccess;
438 }
439 
440 bool Mint::SaveMint(const char* szAppend)
441 {
443 
444  const OTString strServerID(m_ServerID), strAssetTypeID(m_AssetID);
445 
446  if (!m_strFilename.Exists()) {
447  if (nullptr != szAppend)
448  m_strFilename.Format("%s%s%s%s", strServerID.Get(),
449  OTLog::PathSeparator(), // server side
450  strAssetTypeID.Get(), szAppend);
451  else
452  m_strFilename.Format("%s%s%s", strServerID.Get(),
454  strAssetTypeID.Get()); // client side
455  }
456 
457  OTString strFilename;
458  if (nullptr != szAppend)
459  strFilename.Format("%s%s", strAssetTypeID.Get(), szAppend);
460  else
461  strFilename = strAssetTypeID.Get();
462 
463  const char* szFolder1name = OTFolders::Mint().Get();
464  const char* szFolder2name = strServerID.Get();
465  const char* szFilename = strFilename.Get();
466 
467  OTString strRawFile;
468 
469  if (!SaveContractRaw(strRawFile)) {
470  otErr << "Mint::SaveMint: Error saving Mintfile (to string):\n"
471  << szFolder1name << OTLog::PathSeparator() << szFolder2name
472  << OTLog::PathSeparator() << szFilename << "\n";
473  return false;
474  }
475 
476  OTString strFinal;
477  OTASCIIArmor ascTemp(strRawFile);
478 
479  if (false ==
480  ascTemp.WriteArmoredString(strFinal, m_strContractType.Get())) {
481  otErr << "Mint::SaveMint: Error saving mint (failed writing armored "
482  "string):\n" << szFolder1name << OTLog::PathSeparator()
483  << szFolder2name << OTLog::PathSeparator() << szFilename << "\n";
484  return false;
485  }
486 
487  bool bSaved =
488  OTDB::StorePlainString(strFinal.Get(), szFolder1name, szFolder2name,
489  szFilename); // <=== SAVING TO LOCAL DATA STORE.
490  if (!bSaved) {
491  if (nullptr != szAppend)
492  otErr << "Mint::SaveMint: Error writing to file: " << szFolder1name
493  << OTLog::PathSeparator() << szFolder2name
494  << OTLog::PathSeparator() << szFilename << szAppend << "\n";
495  else
496  otErr << "Mint::SaveMint: Error writing to file: " << szFolder1name
497  << OTLog::PathSeparator() << szFolder2name
498  << OTLog::PathSeparator() << szFilename << "\n";
499 
500  return false;
501  }
502 
503  return true;
504 }
505 
506 // Make sure this contract checks out. Very high level.
507 // Verifies ID and signature.
508 bool Mint::VerifyMint(const OTPseudonym& theOperator)
509 {
510  // Make sure that the supposed Contract ID that was set is actually
511  // a hash of the contract file, signatures and all.
512  if (!VerifyContractID()) {
513  otErr << "Error comparing Mint ID to Asset Contract ID in "
514  "Mint::VerifyMint\n";
515  return false;
516  }
517  else if (!VerifySignature(theOperator)) {
518  otErr << "Error verifying signature on mint in Mint::VerifyMint.\n";
519  return false;
520  }
521 
522  otLog3 << "\nWe now know that...\n"
523  "1) The Asset Contract ID matches the Mint ID loaded from the "
524  "Mint file.\n"
525  "2) The SIGNATURE VERIFIED.\n\n";
526  return true;
527 }
528 
529 // Unlike other contracts, which calculate their ID from a hash of the file
530 // itself, a mint has
531 // the same ID as its Asset Contract. When we open the Mint file, we read the
532 // Asset Type ID
533 // from it and then verify that it matches what we were expecting from the asset
534 // type.
536 {
537  // I use the == operator here because there is no != operator at this time.
538  // That's why you see the ! outside the parenthesis.
539  if (!(m_ID == m_AssetID)) {
540  OTString str1(m_ID), str2(m_AssetID);
541 
542  otErr << "\nMint ID does NOT match Asset Type ID in "
543  "Mint::VerifyContractID.\n" << str1 << "\n" << str2 << "\n";
544  // "\nRAW FILE:\n--->" << m_strRawFile << "<---"
545  return false;
546  }
547  else {
548  OTString str1(m_ID);
549  otInfo << "\nMint ID *SUCCESSFUL* match to Asset Contract ID:\n" << str1
550  << "\n\n";
551  return true;
552  }
553 }
554 
555 // The mint has a different key pair for each denomination.
556 // Pass in the actual denomination such as 5, 10, 20, 50, 100...
557 bool Mint::GetPrivate(OTASCIIArmor& theArmor, int64_t lDenomination)
558 {
559  for (auto& it : m_mapPrivate) {
560  OTASCIIArmor* pArmor = it.second;
561  OT_ASSERT_MSG(nullptr != pArmor,
562  "nullptr mint pointer in Mint::GetPrivate.\n");
563  // if this denomination (say, 50) matches the one passed in
564  if (it.first == lDenomination) {
565  theArmor.Set(*pArmor);
566  return true;
567  }
568  }
569  return false;
570 }
571 
572 // The mint has a different key pair for each denomination.
573 // Pass in the actual denomination such as 5, 10, 20, 50, 100...
574 bool Mint::GetPublic(OTASCIIArmor& theArmor, int64_t lDenomination)
575 {
576  for (auto& it : m_mapPublic) {
577  OTASCIIArmor* pArmor = it.second;
578  OT_ASSERT_MSG(nullptr != pArmor,
579  "nullptr mint pointer in Mint::GetPublic.\n");
580  // if this denomination (say, 50) matches the one passed in
581  if (it.first == lDenomination) {
582  theArmor.Set(*pArmor);
583  return true;
584  }
585  }
586 
587  return false;
588 }
589 
590 // If you need to withdraw a specific amount, pass it in here and the
591 // mint will return the largest denomination that is equal to or smaller
592 // than the amount.
593 // Then you can subtract the denomination from the amount and call this method
594 // again, and again, until it reaches 0, in order to create all the necessary
595 // tokens to reach the full withdrawal amount.
596 int64_t Mint::GetLargestDenomination(int64_t lAmount)
597 {
598  for (int32_t nIndex = GetDenominationCount() - 1; nIndex >= 0; nIndex--) {
599  int64_t lDenom = GetDenomination(nIndex);
600 
601  if (lDenom <= lAmount) return lDenom;
602  }
603 
604  return 0;
605 }
606 
607 // If you call GetDenominationCount, you can then use this method
608 // to look up a denomination by index.
609 // You could also iterate through them by index.
610 int64_t Mint::GetDenomination(int32_t nIndex)
611 {
612  // index out of bounds.
613  if (nIndex > (m_nDenominationCount - 1)) {
614  return 0;
615  }
616 
617  int32_t nIterateIndex = 0;
618 
619  for (auto it = m_mapPublic.begin(); it != m_mapPublic.end();
620  ++it, nIterateIndex++) {
621  OTASCIIArmor* pArmor = it->second;
622  OT_ASSERT_MSG(nullptr != pArmor,
623  "nullptr mint pointer in Mint::GetDenomination.\n");
624 
625  if (nIndex == nIterateIndex) return it->first;
626  }
627 
628  return 0;
629 }
630 
631 // The default behavior of this function does NOT save the private keys. It only
632 // serializes the public keys, and it is safe to send the object to the client.
633 // If the server needs to save the private keys, then call SetSavePrivateKeys()
634 // first.
636 {
637  OT_ASSERT(nullptr != m_pKeyPublic);
638 
639  OTString SERVER_ID(m_ServerID), SERVER_NYM_ID(m_ServerNymID),
640  ASSET_ID(m_AssetID), CASH_ACCOUNT_ID(m_CashAccountID);
641 
642  int64_t lFrom = OTTimeGetSecondsFromTime(m_VALID_FROM);
643  int64_t lTo = OTTimeGetSecondsFromTime(m_VALID_TO);
644  int64_t lExpiration = OTTimeGetSecondsFromTime(m_EXPIRATION);
645 
646  // I release this because I'm about to repopulate it.
648 
649  m_xmlUnsigned.Concatenate("<?xml version=\"%s\"?>\n\n", "1.0");
650 
651  m_xmlUnsigned.Concatenate("<mint version=\"%s\"\n"
652  " serverID=\"%s\"\n"
653  " serverNymID=\"%s\"\n"
654  " assetTypeID=\"%s\"\n"
655  " cashAcctID=\"%s\"\n"
656  " series=\"%d\"\n"
657  " expiration=\"%" PRId64 "\"\n"
658  " validFrom=\"%" PRId64 "\"\n"
659  " validTo=\"%" PRId64 "\""
660  " >\n\n",
661  m_strVersion.Get(), SERVER_ID.Get(),
662  SERVER_NYM_ID.Get(), ASSET_ID.Get(),
663  CASH_ACCOUNT_ID.Get(), m_nSeries, lExpiration,
664  lFrom, lTo);
665 
666  OTASCIIArmor armorPublicKey;
667  m_pKeyPublic->GetPublicKey(armorPublicKey);
668  m_xmlUnsigned.Concatenate("<mintPublicKey>\n%s</mintPublicKey>\n\n",
669  armorPublicKey.Get());
670 
671  if (m_nDenominationCount) {
672  if (m_bSavePrivateKeys) {
673  m_bSavePrivateKeys = false; // reset this back to false again. Use
674  // SetSavePrivateKeys() to set it true.
675 
676  for (auto& it : m_mapPrivate) {
677  OTASCIIArmor* pArmor = it.second;
678  OT_ASSERT_MSG(nullptr != pArmor, "nullptr private mint pointer "
679  "in "
680  "Mint::UpdateContents.\n");
681 
683  "<mintPrivateInfo denomination=\"%lld\">\n"
684  "%s</mintPrivateInfo>\n\n",
685  it.first, pArmor->Get());
686  }
687  }
688  for (auto& it : m_mapPublic) {
689  OTASCIIArmor* pArmor = it.second;
691  nullptr != pArmor,
692  "nullptr public mint pointer in Mint::UpdateContents.\n");
693 
694  m_xmlUnsigned.Concatenate("<mintPublicInfo denomination=\"%lld\">\n"
695  "%s</mintPublicInfo>\n\n",
696  it.first, pArmor->Get());
697  }
698  }
699 
700  m_xmlUnsigned.Concatenate("</mint>\n");
701 }
702 
703 // return -1 if error, 0 if nothing, and 1 if the node was processed.
705 {
706  OT_ASSERT(nullptr != m_pKeyPublic);
707 
708  int32_t nReturnVal = 0;
709 
710  const OTString strNodeName(xml->getNodeName());
711 
712  // Here we call the parent class first.
713  // If the node is found there, or there is some error,
714  // then we just return either way. But if it comes back
715  // as '0', then nothing happened, and we'll continue executing.
716  //
717  // -- Note you can choose not to call the parent if
718  // you don't want to use any of those xml tags.
719  // As I do below, in the case of OTAccount.
720  // if (nReturnVal = ot_super::ProcessXMLNode(xml))
721  // return nReturnVal;
722 
723  if (strNodeName.Compare("mint")) {
724  OTString strServerID, strServerNymID, strAssetID, strCashAcctID;
725 
726  m_strVersion = xml->getAttributeValue("version");
727  strServerID = xml->getAttributeValue("serverID");
728  strServerNymID = xml->getAttributeValue("serverNymID");
729  strAssetID = xml->getAttributeValue("assetTypeID");
730  strCashAcctID = xml->getAttributeValue("cashAcctID");
731 
732  m_nSeries = atoi(xml->getAttributeValue("series"));
733  m_EXPIRATION =
734  OTTimeGetTimeFromSeconds(xml->getAttributeValue("expiration"));
735 
736  const OTString str_valid_from = xml->getAttributeValue("validFrom");
737  const OTString str_valid_to = xml->getAttributeValue("validTo");
738 
739  m_VALID_FROM = OTTimeGetTimeFromSeconds(str_valid_from.ToLong());
740  m_VALID_TO = OTTimeGetTimeFromSeconds(str_valid_to.ToLong());
741 
742  m_ServerID.SetString(strServerID);
743  m_ServerNymID.SetString(strServerNymID);
744  m_AssetID.SetString(strAssetID);
745  m_CashAccountID.SetString(strCashAcctID);
746 
747  if (m_pReserveAcct) {
748  delete m_pReserveAcct;
749  m_pReserveAcct = nullptr;
750  }
751 
752  // Every Mint has its own cash account. Here we load ours so it's ready
753  // for transactions.
754  if (strCashAcctID.Exists())
757 
758  int64_t nValidFrom = OTTimeGetSecondsFromTime(m_VALID_FROM);
759  int64_t nValidTo = OTTimeGetSecondsFromTime(m_VALID_TO);
760  int64_t nExpiration = OTTimeGetSecondsFromTime(m_EXPIRATION);
761 
762  otWarn <<
763  // "\n===> Loading XML for mint into memory structures..."
764  "\n\nMint version: " << m_strVersion
765  << "\n Server ID: " << strServerID
766  << "\n Asset Type ID: " << strAssetID
767  << "\n Cash Acct ID: " << strCashAcctID << "\n"
768  ""
769  << ((m_pReserveAcct != nullptr) ? "SUCCESS" : "FAILURE")
770  << " loading Cash Account into memory for pointer: "
771  "Mint::m_pReserveAcct\n"
772  " Series: " << m_nSeries << "\n Expiration: " << nExpiration
773  << "\n Valid From: " << nValidFrom << "\n Valid To: " << nValidTo
774  << "\n";
775 
776  nReturnVal = 1;
777  }
778  else if (strNodeName.Compare("mintPublicKey")) {
779  OTASCIIArmor armorPublicKey;
780 
781  if (!OTContract::LoadEncodedTextField(xml, armorPublicKey) ||
782  !armorPublicKey.Exists()) {
783  otErr << "Error in Mint::ProcessXMLNode: mintPublicKey field "
784  "without value.\n";
785  return (-1); // error condition
786  }
787  else {
789  armorPublicKey); // todo check this for failure.
790  }
791 
792  return 1;
793  }
794  else if (strNodeName.Compare("mintPrivateInfo")) {
795  int64_t lDenomination = atol(xml->getAttributeValue("denomination"));
796 
797  OTASCIIArmor* pArmor = new OTASCIIArmor;
798 
799  OT_ASSERT(nullptr != pArmor);
800 
801  if (!OTContract::LoadEncodedTextField(xml, *pArmor) ||
802  !pArmor->Exists()) {
803  otErr << "Error in Mint::ProcessXMLNode: mintPrivateInfo field "
804  "without value.\n";
805 
806  delete pArmor;
807  pArmor = nullptr;
808 
809  return (-1); // error condition
810  }
811  else {
812  m_mapPrivate[lDenomination] = pArmor;
813  }
814 
815  return 1;
816  }
817  else if (strNodeName.Compare("mintPublicInfo")) {
818  int64_t lDenomination = atol(xml->getAttributeValue("denomination"));
819 
820  OTASCIIArmor* pArmor = new OTASCIIArmor;
821 
822  OT_ASSERT(nullptr != pArmor);
823 
824  if (!OTContract::LoadEncodedTextField(xml, *pArmor) ||
825  !pArmor->Exists()) {
826  otErr << "Error in Mint::ProcessXMLNode: mintPublicInfo field "
827  "without value.\n";
828 
829  delete pArmor;
830  pArmor = nullptr;
831 
832  return (-1); // error condition
833  }
834  else {
835  m_mapPublic[lDenomination] = pArmor;
836  m_nDenominationCount++; // Whether client or server, both sides have
837  // public. Each public denomination should
838  // increment this count.
839  }
840 
841  return 1;
842  }
843 
844  return nReturnVal;
845 }
846 
847 /*
848  // Just make sure theMessage has these members populated:
849  //
850  // theMessage.m_strNymID;
851  // theMessage.m_strAssetID;
852  // theMessage.m_strServerID;
853 
854  // static method (call it without an instance, using notation:
855  OTAccount::GenerateNewAccount)
856  OTAccount * OTAccount::GenerateNewAccount( const OTIdentifier & theUserID,
857  const OTIdentifier & theServerID,
858  const OTPseudonym & theServerNym,
859  const OTMessage & theMessage,
860  const OTAccount::AccountType
861  eAcctType=OTAccount::simple)
862 
863 
864  // The above method uses this one internally...
865  bool OTAccount::GenerateNewAccount(const OTPseudonym & theServer, const
866  OTMessage & theMessage,
867  const OTAccount::AccountType
868  eAcctType=OTAccount::simple)
869 
870 
871  OTAccount * pAcct = nullptr;
872  pAcct = OTAccount::LoadExistingAccount(ACCOUNT_ID, SERVER_ID);
873  */
874 
875 // Lucre step 1: generate new mint
876 // Make sure the issuer here has a private key
877 // theMint.GenerateNewMint(nSeries, VALID_FROM, VALID_TO, ASSET_ID, m_nymServer,
878 // 1, 5, 10, 20, 50, 100, 500, 1000, 10000, 100000);
879 void Mint::GenerateNewMint(int32_t nSeries, time64_t VALID_FROM,
880  time64_t VALID_TO, time64_t MINT_EXPIRATION,
881  const OTIdentifier& theAssetID,
882  const OTIdentifier& theServerID,
883  OTPseudonym& theNotary, int64_t nDenom1,
884  int64_t nDenom2, int64_t nDenom3, int64_t nDenom4,
885  int64_t nDenom5, int64_t nDenom6, int64_t nDenom7,
886  int64_t nDenom8, int64_t nDenom9, int64_t nDenom10)
887 {
888  Release();
889 
890  m_AssetID = theAssetID;
891  m_ServerID = theServerID;
892 
893  OTIdentifier SERVER_NYM_ID(theNotary);
894  m_ServerNymID = SERVER_NYM_ID;
895 
896  m_nSeries = nSeries;
897  m_VALID_FROM = VALID_FROM;
898  m_VALID_TO = VALID_TO;
899  m_EXPIRATION = MINT_EXPIRATION;
900 
901  // Normally asset accounts are created based on an incoming message,
902  // so I'm just simulating that in order to make sure it gets its
903  // necessary input values, such as asset type, server ID, etc.
904  OTMessage theMessage;
905  SERVER_NYM_ID.GetString(theMessage.m_strNymID);
906  theAssetID.GetString(theMessage.m_strAssetID);
907  theServerID.GetString(theMessage.m_strServerID);
908 
909  /* OTAccount::
910  GenerateNewAccount(const OTIdentifier & theUserID, const OTIdentifier &
911  theServerID,
912  const OTPseudonym & theServerNym, const OTMessage &
913  theMessage,
914  const AccountType eAcctType=simple);
915  */
917  SERVER_NYM_ID, theServerID, theNotary, theMessage, OTAccount::mint);
918 
919  if (m_pReserveAcct) {
921  otOut << "Successfully created cash reserve account for new mint.\n";
922  }
923  else {
924  otErr << "Error creating cash reserve account for new mint.\n";
925  }
926 
927  if (nDenom1) {
928  AddDenomination(theNotary,
929  nDenom1); // int32_t nPrimeLength default = 1024
930  }
931  if (nDenom2) {
932  AddDenomination(theNotary,
933  nDenom2); // int32_t nPrimeLength default = 1024
934  }
935  if (nDenom3) {
936  AddDenomination(theNotary,
937  nDenom3); // int32_t nPrimeLength default = 1024
938  }
939  if (nDenom4) {
940  AddDenomination(theNotary,
941  nDenom4); // int32_t nPrimeLength default = 1024
942  }
943  if (nDenom5) {
944  AddDenomination(theNotary,
945  nDenom5); // int32_t nPrimeLength default = 1024
946  }
947  if (nDenom6) {
948  AddDenomination(theNotary,
949  nDenom6); // int32_t nPrimeLength default = 1024
950  }
951  if (nDenom7) {
952  AddDenomination(theNotary,
953  nDenom7); // int32_t nPrimeLength default = 1024
954  }
955  if (nDenom8) {
956  AddDenomination(theNotary,
957  nDenom8); // int32_t nPrimeLength default = 1024
958  }
959  if (nDenom9) {
960  AddDenomination(theNotary,
961  nDenom9); // int32_t nPrimeLength default = 1024
962  }
963  if (nDenom10) {
964  AddDenomination(theNotary,
965  nDenom10); // int32_t nPrimeLength default = 1024
966  }
967 }
968 
969 bool Mint::SaveContractWallet(std::ofstream&) const
970 {
971  return true;
972 }
973 
974 } // namespace opentxs
static EXPORT const OTString & Mint()
Definition: OTFolders.cpp:323
EXPORT bool StorePlainString(std::string strContents, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:698
int32_t m_nSeries
Definition: Mint.hpp:186
void ReleaseDenominations()
Definition: Mint.cpp:237
time64_t m_EXPIRATION
Definition: Mint.hpp:196
static EXPORT Mint * MintFactory()
Definition: Mint.cpp:154
OTAccount * m_pReserveAcct
Definition: Mint.hpp:202
bool GetPrivate(OTASCIIArmor &theArmor, int64_t lDenomination)
Definition: Mint.cpp:557
virtual bool AddDenomination(OTPseudonym &theNotary, int64_t lDenomination, int32_t nPrimeLength=1024)=0
EXPORT bool Expired() const
Definition: Mint.cpp:227
EXPORT void GenerateNewMint(int32_t nSeries, time64_t VALID_FROM, time64_t VALID_TO, time64_t MINT_EXPIRATION, const OTIdentifier &theAssetID, const OTIdentifier &theServerID, OTPseudonym &theNotary, int64_t nDenom1=0, int64_t nDenom2=0, int64_t nDenom3=0, int64_t nDenom4=0, int64_t nDenom5=0, int64_t nDenom6=0, int64_t nDenom7=0, int64_t nDenom8=0, int64_t nDenom9=0, int64_t nDenom10=0)
Definition: Mint.cpp:879
EXPORT int64_t ToLong() const
Definition: OTString.cpp:702
static EXPORT OTAccount * GenerateNewAccount(const OTIdentifier &userId, const OTIdentifier &serverId, const OTPseudonym &serverNym, const OTMessage &message, AccountType acctType=simple, int64_t stashTransNum=0)
Definition: OTAccount.cpp:531
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
EXPORT bool VerifyMint(const OTPseudonym &theOperator)
Definition: Mint.cpp:508
virtual bool SaveContractWallet(std::ofstream &ofs) const
Definition: Mint.cpp:969
OTLOG_IMPORT OTLogStream otOut
virtual void Release()
Definition: Mint.cpp:272
OTString m_strAssetID
Definition: OTMessage.hpp:203
void Release_Mint()
Definition: Mint.cpp:260
OTLOG_IMPORT OTLogStream otLog3
EXPORT bool SaveContractRaw(OTString &strOutput) const
void InitMint()
Definition: Mint.cpp:296
time64_t OTTimeGetTimeFromSeconds(int64_t seconds)
Definition: Common.hpp:215
virtual void UpdateContents()
Definition: Mint.cpp:635
OTIdentifier m_ServerNymID
Definition: Mint.hpp:169
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
int64_t time64_t
Definition: Common.hpp:209
EXPORT bool WriteArmoredString(OTString &strOutput, const std::string str_type, bool bEscaped=false) const
EXPORT bool SaveMint(const char *szAppend=nullptr)
Definition: Mint.cpp:440
virtual EXPORT ~Mint()
Definition: Mint.cpp:282
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
Definition: Mint.cpp:704
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT void SetString(const char *szString)
EXPORT int64_t GetLargestDenomination(int64_t lAmount)
Definition: Mint.cpp:596
EXPORT bool SetPublicKey(const OTASCIIArmor &strKey)
EXPORT void Format(const char *fmt,...)
Definition: OTString.cpp:1319
bool GetPublic(OTASCIIArmor &theArmor, int64_t lDenomination)
Definition: Mint.cpp:574
OTIdentifier m_ServerID
Definition: Mint.hpp:167
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
Definition: OTString.cpp:1055
time64_t OTTimeGetCurrentTime()
Definition: Common.hpp:211
virtual bool LoadContract()
Definition: Mint.cpp:372
EXPORT std::string QueryPlainString(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:728
EXPORT bool GetPublicKey(OTASCIIArmor &strKey) const
static EXPORT bool LoadEncodedTextField(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
OTIdentifier m_CashAccountID
Definition: Mint.hpp:199
mapOfArmor m_mapPrivate
Definition: Mint.hpp:160
#define OT_ASSERT(x)
Definition: Assert.hpp:150
int32_t GetDenominationCount() const
Definition: Mint.hpp:282
OTIdentifier m_AssetID
Definition: Mint.hpp:174
OTString m_strContractType
Definition: OTContract.hpp:178
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
OTLOG_IMPORT OTLogStream otInfo
OTIdentifier m_ID
Definition: OTContract.hpp:172
virtual EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
Definition: OTContract.cpp:317
OTAsymmetricKey * m_pKeyPublic
Definition: Mint.hpp:172
OTString m_strServerID
Definition: OTMessage.hpp:191
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
OTLOG_IMPORT OTLogStream otWarn
EXPORT const char * Get() const
Definition: OTString.cpp:1045
int32_t m_nDenominationCount
Definition: Mint.hpp:176
OTLOG_IMPORT OTLogStream otErr
time64_t m_VALID_FROM
Definition: Mint.hpp:192
virtual EXPORT void Release()
Definition: OTContract.cpp:277
bool m_bSavePrivateKeys
Definition: Mint.hpp:180
virtual bool VerifyContractID() const
Definition: Mint.cpp:535
EXPORT void GetString(OTString &theStr) const
virtual EXPORT bool VerifySignature(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
Definition: OTContract.cpp:818
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
EXPORT bool LoadContractFromString(const OTString &theStr)
EXPORT bool LoadMint(const char *szAppend=nullptr)
Definition: Mint.cpp:378
#define OT_TIME_ZERO
Definition: Common.hpp:180
virtual EXPORT void Release()
Definition: OTData.cpp:257
mapOfArmor m_mapPublic
Definition: Mint.hpp:164
static EXPORT OTAccount * LoadExistingAccount(const OTIdentifier &accountId, const OTIdentifier &serverId)
Definition: OTAccount.cpp:480
virtual EXPORT void Release()
Definition: OTString.cpp:765
time64_t m_VALID_TO
Definition: Mint.hpp:194
int64_t GetDenomination(int32_t nIndex)
Definition: Mint.cpp:610
OTString m_strFoldername
Definition: OTContract.hpp:169