Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Token.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * Token.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 "Token.hpp"
136 #include "Mint.hpp"
137 #include "Purse.hpp"
138 
139 #if defined(OT_CASH_USING_LUCRE)
140 #include "TokenLucre.hpp"
141 #endif
142 
143 #include "../core/crypto/OTEnvelope.hpp"
144 #include "../core/crypto/OTNymOrSymmetricKey.hpp"
145 #include "../core/util/OTFolders.hpp"
146 #include "../core/OTLog.hpp"
147 #include "../core/OTStorage.hpp"
148 
149 #include <irrxml/irrXML.hpp>
150 
151 namespace opentxs
152 {
153 
154 // The current implementation for withdrawals (using Lucre) requires only a
155 // single proto-token
156 // to be sent, signed, and returned. Only the ID of the token is blinded.
157 //
158 // But this library supports sending up to N proto-tokens. Even though only 1 is
159 // required, this
160 // lib supports sending 5 or 100 or 1000, if other protocols (such as Cham) are
161 // later added.
162 
163 // todo: make this configurable. Or configured in the contract.
164 // Then the server can be configured with the contract parameters that it is
165 // willing to accept.
166 // Each server operator may have different standards about the contracts they
167 // are willing to
168 // process, and the prices for notarizing each.
169 //
170 // You may want to set it up as 1 out of 100
171 // or 1 out of 500
172 // or 1 out of 5
173 // Basically this number determines how many blinded prototokens must be sent to
174 // the
175 // server in order for the server to accept the withdrawal request and sign one
176 // of them.
177 // (more prototokens == more resource cost, but more security.)
179 
181 {
183 }
184 
185 // Lucre, in fact, only sends a single blinded token, and the bank signs it
186 // blind and returns it.
187 // With Chaum, I thought the bank had to open some of the proto-tokens to verify
188 // the amount was
189 // correct, etc. But now I realize that was probably just a metaphor used for
190 // news interviews.
191 //
192 // With Lucre, only the ID is blinded. The bank can already see the amount--it's
193 // not blinded. So
194 // there's no need to verify it. The client can send an ill-formed token if he
195 // wishes, but only
196 // hurts himself.
197 //
198 // Problem is, the bank can still falsely refuse a coin. So I have wrapped Lucre
199 // in my own protocol
200 // which includes signed receipts from the bank. Also, since the bank must store
201 // the spent tokens
202 // (at least until they expire) then the bank can be asked to produce the
203 // deposit receipt which
204 // has the customer's signature on it who deposited that cash, if it indeed has
205 // already been spent.
206 
208 {
209  // m_lDenomination = 0;
210  // m_nTokenCount = 0;
211  // m_nChosenIndex = 0;
212  // m_nSeries = 0;
213  // m_State = blankToken;
214  // m_bSavePrivateKeys = false;
215 
216  m_strContractType.Set("CASH TOKEN"); // todo internationalization.
217 }
218 
220  : ot_super()
221  , m_bPasswordProtected(false)
222  , m_lDenomination(0)
223  , m_nTokenCount(0)
224  , m_nChosenIndex(0)
225  , m_nSeries(0)
226  , m_State(blankToken)
227  , m_bSavePrivateKeys(false)
228 {
229  InitToken();
230 }
231 
232 // int64_t m_lDenomination;
233 // int32_t m_nTokenCount;
234 // int32_t m_nChosenIndex;
235 // int32_t m_nSeries;
236 // tokenState m_State;
237 // bool m_bSavePrivateKeys; // Determines whether it serializes
238 // private keys 1 time (yes if true)
239 
240 Token::Token(const OTIdentifier& SERVER_ID, const OTIdentifier& ASSET_ID)
241  : ot_super(SERVER_ID, ASSET_ID)
242  , m_bPasswordProtected(false)
243  , m_lDenomination(0)
244  , m_nTokenCount(0)
245  , m_nChosenIndex(0)
246  , m_nSeries(0)
247  , m_State(blankToken)
248  , m_bSavePrivateKeys(false)
249 {
250  InitToken();
251 
252  // m_ServerID and m_AssetTypeID are now in the parent class (OTInstrument)
253  // So they are initialized there now.
254 }
255 
256 Token::Token(const Purse& thePurse)
257  : ot_super()
258  , m_bPasswordProtected(false)
259  , m_lDenomination(0)
260  , m_nTokenCount(0)
261  , m_nChosenIndex(0)
262  , m_nSeries(0)
263  , m_State(blankToken)
264  , m_bSavePrivateKeys(false)
265 {
266  InitToken();
267 
268  // These are in the parent class, OTInstrument.
269  // I set them here because the "Purse" argument only exists
270  // in this subclass constructor, not the base.
271  m_ServerID = thePurse.GetServerID();
272  m_AssetTypeID = thePurse.GetAssetID();
273 }
274 
276 {
277 
280 
281  // InitToken();
282 
284 }
285 
287 {
288  Release_Token();
289 
290  ot_super::Release(); // since I've overridden the base class, I call it
291  // now...
292 }
293 
295 {
296  Release_Token();
297 
298  m_bPasswordProtected = false;
299 
300  // todo: optimization (probably just remove these here.)
301  m_lDenomination = 0;
302  // m_nTokenCount = 0; // this happens in ReleasePrototokens. (Called
303  // by Release_Token above.)
304  m_nChosenIndex = 0;
305  m_nSeries = 0;
307  m_bSavePrivateKeys = false;
308 }
309 
311 {
312  for (auto& it : m_mapPublic) {
313  OTASCIIArmor* pPrototoken = it.second;
315  nullptr != pPrototoken,
316  "nullptr OTASCIIArmor pointer in Token::ReleasePrototokens.");
317 
318  delete pPrototoken;
319  pPrototoken = nullptr;
320  }
321 
322  for (auto& it : m_mapPrivate) {
323  OTASCIIArmor* pPrototoken = it.second;
325  nullptr != pPrototoken,
326  "nullptr OTASCIIArmor pointer in Token::ReleasePrototokens.");
327 
328  delete pPrototoken;
329  pPrototoken = nullptr;
330  }
331 
332  m_mapPublic.clear();
333  m_mapPrivate.clear();
334 
335  m_nTokenCount = 0;
336 }
337 
338 // TODO: save the private request tokens to the wallet here...
339 bool Token::SaveContractWallet(std::ofstream&) const
340 {
341  // mapOfPrototokens m_mapPrivate; // The elements are accessed [0..N].
342  // mapPublic[2] corresponds to map_Private[2], etc.
343 
344  return true;
345 }
346 
347 // static -- class factory.
348 //
350  const OTIdentifier& SERVER_ID,
351  const OTIdentifier& ASSET_ID)
352 {
353  Token* pToken = nullptr;
354 
355 #if defined(OT_CASH_USING_LUCRE)
356  if (strFirstLine.Contains("-----BEGIN SIGNED CASH-----")) // this string is
357  // 27 chars long.
358  {
359  pToken = new Token_Lucre(SERVER_ID, ASSET_ID);
360  OT_ASSERT(nullptr != pToken);
361  }
362  else if (strFirstLine.Contains(
363  "-----BEGIN SIGNED CASH TOKEN-----")) // this string is 33
364  // chars long.
365  {
366  pToken = new Token_Lucre(SERVER_ID, ASSET_ID);
367  OT_ASSERT(nullptr != pToken);
368  }
369  else if (strFirstLine.Contains(
370  "-----BEGIN SIGNED LUCRE CASH TOKEN-----")) // this string is
371  // 39 chars long.
372  {
373  pToken = new Token_Lucre(SERVER_ID, ASSET_ID);
374  OT_ASSERT(nullptr != pToken);
375  }
376 #else
377  otErr << __FUNCTION__ << ": Open-Transactions is not built for any digital "
378  "cash algorithms. (Failure.)";
379 #endif // defined (OT_CASH_USING_LUCRE)
380 
381  return pToken;
382 }
383 
385  const Purse& thePurse)
386 {
387  Token* pToken = nullptr;
388 
389 #if defined(OT_CASH_USING_LUCRE)
390  if (strFirstLine.Contains("-----BEGIN SIGNED CASH-----")) // this string is
391  // 27 chars long.
392  {
393  pToken = new Token_Lucre(thePurse);
394  OT_ASSERT(nullptr != pToken);
395  }
396  else if (strFirstLine.Contains(
397  "-----BEGIN SIGNED CASH TOKEN-----")) // this string is 33
398  // chars long.
399  {
400  pToken = new Token_Lucre(thePurse);
401  OT_ASSERT(nullptr != pToken);
402  }
403  else if (strFirstLine.Contains(
404  "-----BEGIN SIGNED LUCRE CASH TOKEN-----")) // this string is
405  // 39 chars long.
406  {
407  pToken = new Token_Lucre(thePurse);
408  OT_ASSERT(nullptr != pToken);
409  }
410 #else
411  otErr << __FUNCTION__ << ": Open-Transactions is not built for any digital "
412  "cash algorithms. (Failure.)";
413 #endif // defined (OT_CASH_USING_LUCRE)
414 
415  return pToken;
416 }
417 
419 {
420  Token* pToken = nullptr;
421 
422 #if defined(OT_CASH_USING_LUCRE)
423  pToken = new Token_Lucre(thePurse);
424  OT_ASSERT(nullptr != pToken);
425 #else
426  otErr << __FUNCTION__ << ": Open-Transactions is not built for any digital "
427  "cash algorithms. (Failure.)";
428 #endif // defined (OT_CASH_USING_LUCRE)
429 
430  return pToken;
431 }
432 
434 {
435  Token* pToken = nullptr;
436 
437 #if defined(OT_CASH_USING_LUCRE)
438  if (strFirstLine.Contains("-----BEGIN SIGNED CASH-----")) // this string is
439  // 27 chars long.
440  {
441  pToken = new Token_Lucre;
442  OT_ASSERT(nullptr != pToken);
443  }
444  else if (strFirstLine.Contains(
445  "-----BEGIN SIGNED CASH TOKEN-----")) // this string is 33
446  // chars long.
447  {
448  pToken = new Token_Lucre;
449  OT_ASSERT(nullptr != pToken);
450  }
451  else if (strFirstLine.Contains(
452  "-----BEGIN SIGNED LUCRE CASH TOKEN-----")) // this string is
453  // 39 chars long.
454  {
455  pToken = new Token_Lucre;
456  OT_ASSERT(nullptr != pToken);
457  }
458 #else
459  otErr << __FUNCTION__ << ": Open-Transactions is not built for any digital "
460  "cash algorithms. (Failure.)";
461 #endif // defined (OT_CASH_USING_LUCRE)
462 
463  return pToken;
464 }
465 
466 // static -- class factory.
467 //
468 Token* Token::TokenFactory(OTString strInput, const OTIdentifier& SERVER_ID,
469  const OTIdentifier& ASSET_ID)
470 {
471  // const char * szFunc = "Token::TokenFactory";
472 
473  OTString strContract, strFirstLine; // output for the below function.
474  const bool bProcessed =
475  OTContract::DearmorAndTrim(strInput, strContract, strFirstLine);
476 
477  if (bProcessed) {
478  Token* pToken =
479  Token::LowLevelInstantiate(strFirstLine, SERVER_ID, ASSET_ID);
480 
481  // The string didn't match any of the options in the factory.
482  if (nullptr == pToken) return nullptr;
483 
484  // Does the contract successfully load from the string passed in?
485  if (pToken->LoadContractFromString(strContract))
486  return pToken;
487  else
488  delete pToken;
489  }
490 
491  return nullptr;
492 }
493 
494 Token* Token::TokenFactory(OTString strInput, const Purse& thePurse)
495 {
496  // const char * szFunc = "Token::TokenFactory";
497 
498  OTString strContract, strFirstLine; // output for the below function.
499  const bool bProcessed =
500  OTContract::DearmorAndTrim(strInput, strContract, strFirstLine);
501 
502  if (bProcessed) {
503  Token* pToken = Token::LowLevelInstantiate(strFirstLine, thePurse);
504 
505  // The string didn't match any of the options in the factory.
506  if (nullptr == pToken) return nullptr;
507 
508  // Does the contract successfully load from the string passed in?
509  if (pToken->LoadContractFromString(strContract))
510  return pToken;
511  else
512  delete pToken;
513  }
514 
515  return nullptr;
516 }
517 
519 {
520  // const char * szFunc = "Token::TokenFactory";
521 
522  OTString strContract, strFirstLine; // output for the below function.
523  const bool bProcessed =
524  OTContract::DearmorAndTrim(strInput, strContract, strFirstLine);
525 
526  if (bProcessed) {
527  Token* pToken = Token::LowLevelInstantiate(strFirstLine);
528 
529  // The string didn't match any of the options in the factory.
530  if (nullptr == pToken) return nullptr;
531 
532  // Does the contract successfully load from the string passed in?
533  if (pToken->LoadContractFromString(strContract))
534  return pToken;
535  else
536  delete pToken;
537  }
538 
539  return nullptr;
540 }
541 
542 // Note: ALL failures will return true, even if the token has NOT already been
543 // spent, and the failure was actually due to a directory creation error. Why,
544 // you might ask? Because no matter WHAT is causing the failure, any return of
545 // false is a signal that the token is SAFE TO ACCEPT AS TENDER. If there was a
546 // temporary file system error, someone could suddenly deposit the same token
547 // over and over again and this method would return "false" (Token is "not
548 // already
549 // spent.")
550 //
551 // We simply cannot risk that, so false is not returned unless execution reaches
552 // the very bottom of this method. Every other error acts as if the token is
553 // no good, for security reasons. If the token really IS good, the user can
554 // submit
555 // it again later and it will work.
556 //
557 bool Token::IsTokenAlreadySpent(OTString& theCleartextToken)
558 {
559  OTString strAssetID(GetAssetID());
560 
561  // Calculate the filename (a hash of the Lucre cleartext token ID)
562  OTIdentifier theTokenHash;
563  theTokenHash.CalculateDigest(theCleartextToken);
564 
565  // Grab the new hash into a string (for use as a filename)
566  OTString strTokenHash(theTokenHash);
567 
568  OTString strAssetFolder;
569  strAssetFolder.Format("%s.%d", strAssetID.Get(), GetSeries());
570 
571  bool bTokenIsPresent = OTDB::Exists(
572  OTFolders::Spent().Get(), strAssetFolder.Get(), strTokenHash.Get());
573 
574  if (bTokenIsPresent) {
575  otOut << "\nToken::IsTokenAlreadySpent: Token was already spent: "
576  << OTFolders::Spent() << OTLog::PathSeparator() << strAssetFolder
577  << OTLog::PathSeparator() << strTokenHash << "\n";
578  return true; // all errors must return true in this function.
579  // But this is not an error. Token really WAS already
580  } // spent, and this true is for real. The others are just
581  // for security reasons because of this one.
582 
583  // This is the ideal case: the token was NOT already spent, it was good,
584  // so we can return false and the depositor can be credited appropriately.
585  // IsTokenAlreadySpent? NO-it was NOT already spent. You can only POSSIBLY
586  // get a false out of this method if you actually reached the bottom (here.)
587  return false;
588 }
589 
590 bool Token::RecordTokenAsSpent(OTString& theCleartextToken)
591 {
592  OTString strAssetID(GetAssetID());
593 
594  // Calculate the filename (a hash of the Lucre cleartext token ID)
595  OTIdentifier theTokenHash;
596  theTokenHash.CalculateDigest(theCleartextToken);
597 
598  // Grab the new hash into a string (for use as a filename)
599  OTString strTokenHash(theTokenHash);
600 
601  OTString strAssetFolder;
602  strAssetFolder.Format("%s.%d", strAssetID.Get(), GetSeries());
603 
604  // See if the spent token file ALREADY EXISTS...
605  bool bTokenIsPresent = OTDB::Exists(
606  OTFolders::Spent().Get(), strAssetFolder.Get(), strTokenHash.Get());
607 
608  // If so, we're trying to record a token that was already recorded...
609  if (bTokenIsPresent) {
610  otErr << "Token::RecordTokenAsSpent: Trying to record token as spent,"
611  " but it was already recorded: " << OTFolders::Spent()
612  << OTLog::PathSeparator() << strAssetFolder
613  << OTLog::PathSeparator() << strTokenHash << "\n";
614  return false;
615  }
616 
617  // FINISHED:
618  //
619  // We actually save the token itself into the file, which is named based
620  // on a hash of the Lucre data.
621  // The success of that operation is also now the success of this one.
622 
623  OTString strFinal;
624  OTASCIIArmor ascTemp(m_strRawFile);
625 
626  if (false ==
627  ascTemp.WriteArmoredString(strFinal, m_strContractType.Get())) {
628  otErr << "Token::RecordTokenAsSpent: Error recording token as "
629  "spent (failed writing armored string):\n"
630  << OTFolders::Spent() << OTLog::PathSeparator() << strAssetFolder
631  << OTLog::PathSeparator() << strTokenHash << "\n";
632  return false;
633  }
634 
635  const bool bSaved =
637  strAssetFolder.Get(), strTokenHash.Get());
638  if (!bSaved) {
639  otErr << "Token::RecordTokenAsSpent: Error saving file: "
640  << OTFolders::Spent() << OTLog::PathSeparator() << strAssetFolder
641  << OTLog::PathSeparator() << strTokenHash << "\n";
642  }
643 
644  return bSaved;
645 }
646 
647 // OTSymmetricKey:
648 // static bool CreateNewKey(OTString & strOutput, const OTString *
649 // pstrDisplay=nullptr, const OTPassword * pAlreadyHavePW=nullptr);
650 //
651 // static bool Encrypt(const OTString & strKey,
652 // const OTString & strPlaintext, OTString & strOutput, const
653 // OTString * pstrDisplay=nullptr,
654 // const bool bBookends=true, const OTPassword *
655 // pAlreadyHavePW=nullptr);
656 //
657 // static bool Decrypt(const OTString & strKey, OTString & strCiphertext,
658 // OTString & strOutput, const OTString *
659 // pstrDisplay=nullptr,
660 // const OTPassword * pAlreadyHavePW=nullptr);
661 
662 // OTEnvelope:
663 // bool Encrypt(const OTString & theInput, OTSymmetricKey & theKey, const
664 // OTPassword & thePassword);
665 // bool Decrypt( OTString & theOutput, const OTSymmetricKey & theKey, const
666 // OTPassword & thePassword);
667 
668 // OTNym_or_SymmetricKey:
669 // const OTPseudonym * GetNym() const { return m_pNym; }
670 // const OTSymmetricKey * GetKey() const { return m_pKey; }
671 // const OTPassword * GetPassword() const { return m_pPassword; } // for
672 // symmetric key (optional)
673 // bool IsNym() const { return (nullptr != m_pNym); }
674 // bool IsKey() const { return (nullptr != m_pKey); }
675 // bool HasPassword() const { return (nullptr != m_pPassword); } // for
676 // symmetric
677 // key (optional)
678 
679 /*
680  NOTE: OTNym_or_SymmetricKey is passed in here as a reference.
681  Normally, you might pass in a Nym, or a SymmetricKey, and OTNym_or_SymmetricKey
682  is able to construct itself from either one. This can be convenient. However,
683  if
684  you don't use an OTPassword when you construct the OTNym_or_SymmetricKey, and
685  it needs
686  one internally for its symmetric key, then it will create one and store it, and
687  delete it
688  upon destruction.
689  Therefore it can be useful to pass the SAME OTNym_or_SymmetricKey into a
690  function multiple
691  times (say, during a loop) since it is storing its password internally, and
692  this makes that PW
693  available to every call, without having to create it EACH TIME (forcing user to
694  enter passphrase
695  EACH TIME as well...)
696  So... what if you would rather just instantiate the passphrase at a higher
697  level, and then just
698  pass it in to this function each time? That way you get the same functionality,
699  but WITHOUT forcing
700  the caller to instantiate the OTNym_or_SymmetricKey himself unless he has to do
701  so. Otherwise he could
702  just pass a Nym. (This isn't currently possible since I'm passing a reference.)
703  You can still actually instantiate the passphrase at a higher level, and then
704  just use that each time
705  you call Token::ReassignOwnership (instantiating a OTNym_or_SymmetricKey to
706  call it, and passing in
707  the existing passphrase pointer to it on construction.)
708  Therefore: I'm leaving the reference. In most cases, I would remove it. But
709  since ReassignOwnership has
710  such a specific "doing these in a loop" use-case, then might as well just
711  instantiate the OTNym_or_SymmetricKey
712  once (in the caller) and then just pass the same one in here a bunch of times,
713  without having to construct
714  anything each time.
715  */
717  OTNym_or_SymmetricKey& oldOwner, // must be private, if a Nym.
718  OTNym_or_SymmetricKey& newOwner) // can be public, if a Nym.
719 {
720  const char* szFunc = "Token::ReassignOwnership";
721  const OTString strDisplay(szFunc);
722 
723  bool bSuccess = true;
724 
725  if (!oldOwner.CompareID(newOwner)) // only re-assign if they don't ALREADY
726  // have the same owner.
727  {
728  OTEnvelope theEnvelope(m_ascSpendable);
729  OTString theString; // output from opening/decrypting (and eventually
730  // input for sealing/encrypting) envelope.
731 
732  // Remember, OTPurse can store its own internal symmetric key, for cases
733  // where the purse is "password protected" instead of belonging to a
734  // specific Nym.
735  // Therefore the old or new "owner" might actually be a symmetric key.
736  // Decrypt/Open the Envelope into theString
737  //
738  bSuccess =
739  oldOwner.Open_or_Decrypt(theEnvelope, theString, &strDisplay);
740  if (bSuccess) {
741  OTEnvelope theNewEnvelope;
742  bSuccess = newOwner.Seal_or_Encrypt(theNewEnvelope, theString,
743  &strDisplay);
744  if (bSuccess)
745  bSuccess = theNewEnvelope.GetAsciiArmoredData(m_ascSpendable);
746  }
747  }
748  return bSuccess;
749 }
750 
752  OTString& theString) const
753 {
754  const char* szFunc = "Token::GetSpendableString";
755 
756  if (m_ascSpendable.Exists()) {
757  OTEnvelope theEnvelope(m_ascSpendable);
758 
759  // Decrypt the Envelope into strContents
760  const OTString strDisplay(szFunc);
761 
762  if (theOwner.Open_or_Decrypt(theEnvelope, theString, &strDisplay))
763  return true;
764  }
765  else
766  otErr << szFunc << ": m_ascSpendable is empty... (failure.)\n";
767 
768  return false;
769 }
770 
772 {
773  if (m_State == Token::spendableToken) m_strContractType.Set("CASH TOKEN");
774 
775  OTString ASSET_TYPE_ID(m_AssetTypeID), SERVER_ID(m_ServerID);
776 
777  OTString strState;
778  switch (m_State) {
779  case Token::blankToken:
780  strState.Set("blankToken");
781  break;
782  case Token::protoToken:
783  strState.Set("protoToken");
784  break;
785  case Token::signedToken:
786  strState.Set("signedToken");
787  break;
789  strState.Set("spendableToken");
790  break;
792  strState.Set("verifiedToken");
793  break;
794  default:
795  strState.Set("errorToken");
796  break;
797  }
798 
799  int64_t lFrom = OTTimeGetSecondsFromTime(m_VALID_FROM);
800  int64_t lTo = OTTimeGetSecondsFromTime(m_VALID_TO);
801 
802  // I release this because I'm about to repopulate it.
804 
805  m_xmlUnsigned.Concatenate("<?xml version=\"%s\"?>\n\n", "1.0");
806 
808  "<token\n version=\"%s\"\n state=\"%s\"\n denomination=\"%lld\"\n"
809  " assetTypeID=\"%s\"\n"
810  " serverID=\"%s\"\n"
811  " series=\"%d\"\n"
812  " validFrom=\"%" PRId64 "\"\n"
813  " validTo=\"%" PRId64 "\""
814  " >\n\n",
815  m_strVersion.Get(), strState.Get(), GetDenomination(),
816  ASSET_TYPE_ID.Get(), SERVER_ID.Get(), m_nSeries, lFrom, lTo);
817 
818  // signed tokens, as well as spendable tokens, both carry a TokenID
819  // (The spendable token contains the unblinded version.)
821  m_xmlUnsigned.Concatenate("<tokenID>\n%s</tokenID>\n\n",
822  m_ascSpendable.Get());
823  }
824 
825  // Only signedTokens carry the signature, which is discarded in spendable
826  // tokens.
827  // (Because it is not used past the unblinding stage anyway, and because it
828  // could
829  // be used to track the token.)
830  if (Token::signedToken == m_State) {
831  m_xmlUnsigned.Concatenate("<tokenSignature>\n%s</tokenSignature>\n\n",
832  m_Signature.Get());
833  }
834 
836  m_nTokenCount) {
838  "<protopurse count=\"%d\" chosenIndex=\"%d\">\n\n", m_nTokenCount,
840 
841  for (auto& it : m_mapPublic) {
842  OTASCIIArmor* pPrototoken = it.second;
843  OT_ASSERT(nullptr != pPrototoken);
844 
845  m_xmlUnsigned.Concatenate("<prototoken>\n%s</prototoken>\n\n",
846  pPrototoken->Get());
847  }
848  m_xmlUnsigned.Concatenate("</protopurse>\n\n");
849  }
850 
851  if (m_bSavePrivateKeys) {
852  m_bSavePrivateKeys = false; // set it back to false;
853 
854  m_xmlUnsigned.Concatenate("<privateProtopurse>\n\n");
855 
856  for (auto& it : m_mapPrivate) {
857  OTASCIIArmor* pPrototoken = it.second;
858  OT_ASSERT(nullptr != pPrototoken);
859 
861  "<privatePrototoken>\n%s</privatePrototoken>\n\n",
862  pPrototoken->Get());
863  }
864  m_xmlUnsigned.Concatenate("</privateProtopurse>\n\n");
865  }
866 
867  m_xmlUnsigned.Concatenate("</token>\n");
868 }
869 
870 // return -1 if error, 0 if nothing, and 1 if the node was processed.
872 {
873  static int32_t nPublicTokenCount = 0;
874  static int32_t nPrivateTokenCount = 0;
875 
876  int32_t nReturnVal = 0;
877 
878  const OTString strNodeName(xml->getNodeName());
879 
880  // Here we call the parent class first.
881  // If the node is found there, or there is some error,
882  // then we just return either way. But if it comes back
883  // as '0', then nothing happened, and we'll continue executing.
884  //
885  // -- Note you can choose not to call the parent if
886  // you don't want to use any of those xml tags.
887  // As I do below, in the case of OTAccount.
888  // if (nReturnVal = OTContract::ProcessXMLNode(xml))
889  // return nReturnVal;
890 
891  if (strNodeName.Compare("token")) {
892  OTString strState;
893 
894  m_strVersion = xml->getAttributeValue("version");
895  strState = xml->getAttributeValue("state");
896 
897  m_nSeries = atoi(xml->getAttributeValue("series"));
898 
899  const OTString str_from = xml->getAttributeValue("validFrom");
900  const OTString str_to = xml->getAttributeValue("validTo");
901 
902  int64_t tFrom = str_from.ToLong();
903  int64_t tTo = str_to.ToLong();
904 
907 
908  SetDenomination(atol(xml->getAttributeValue("denomination")));
909 
910  if (strState.Compare("blankToken"))
912  else if (strState.Compare("protoToken"))
914  else if (strState.Compare("signedToken"))
916  else if (strState.Compare("spendableToken"))
918  else if (strState.Compare("verifiedToken"))
920  else
922 
924  m_strContractType.Set("CASH TOKEN");
925 
926  OTString strAssetTypeID(xml->getAttributeValue("assetTypeID")),
927  strServerID(xml->getAttributeValue("serverID"));
928 
929  m_AssetTypeID.SetString(strAssetTypeID);
930  m_ServerID.SetString(strServerID);
931 
932  otLog4 <<
933  // "\n===> Loading XML for token into memory structures..."
934  "\n\nToken State: " << strState
935  << "\n Denomination: " << GetDenomination()
936  << "\n"
937  " AssetTypeID: " << strAssetTypeID
938  << "\nServerID: " << strServerID << "\n";
939 
940  nReturnVal = 1;
941  }
942  else if (strNodeName.Compare("tokenID")) {
944  otErr << "Error in Token::ProcessXMLNode: token ID without "
945  "value.\n";
946  return (-1); // error condition
947  }
948 
949  return 1;
950  }
951  else if (strNodeName.Compare("tokenSignature")) {
953  otErr << "Error in Token::ProcessXMLNode: token Signature "
954  "without value.\n";
955  return (-1); // error condition
956  }
957 
958  return 1;
959  }
960  else if (strNodeName.Compare("protopurse")) { // TODO for security, if the
961  // count here doesn't match
962  // what's loaded up, that
963  // should be part of
964  // what is verified in each token when it's verified..
965  m_nTokenCount = atoi(xml->getAttributeValue("count"));
966  m_nChosenIndex = atoi(xml->getAttributeValue("chosenIndex"));
967 
968  nPublicTokenCount = 0;
969 
970  return 1;
971  }
972  else if (strNodeName.Compare("prototoken")) {
973  OTASCIIArmor* pArmoredPrototoken = new OTASCIIArmor;
974  OT_ASSERT(nullptr != pArmoredPrototoken);
975 
976  if (!OTContract::LoadEncodedTextField(xml, *pArmoredPrototoken) ||
977  !pArmoredPrototoken->Exists()) {
978  otErr << "Error in Token::ProcessXMLNode: prototoken field "
979  "without value.\n";
980 
981  delete pArmoredPrototoken;
982  pArmoredPrototoken = nullptr;
983 
984  return (-1); // error condition
985  }
986  else {
987  m_mapPublic[nPublicTokenCount] = pArmoredPrototoken;
988  nPublicTokenCount++;
989  }
990 
991  return 1;
992  }
993  else if (strNodeName.Compare("privateProtopurse")) {
994  nPrivateTokenCount = 0;
995 
996  return 1;
997  }
998  else if (strNodeName.Compare("privatePrototoken")) {
999  OTASCIIArmor* pArmoredPrototoken = new OTASCIIArmor;
1000  OT_ASSERT(nullptr != pArmoredPrototoken);
1001 
1002  if (!OTContract::LoadEncodedTextField(xml, *pArmoredPrototoken) ||
1003  !pArmoredPrototoken->Exists()) {
1004  otErr << "Error in Token::ProcessXMLNode: privatePrototoken "
1005  "field without value.\n";
1006 
1007  delete pArmoredPrototoken;
1008  pArmoredPrototoken = nullptr;
1009 
1010  return (-1); // error condition
1011  }
1012  else {
1013  m_mapPrivate[nPrivateTokenCount] = pArmoredPrototoken;
1014  nPrivateTokenCount++;
1015 
1016  otLog4 << "Loaded prototoken and adding to m_mapPrivate at index: "
1017  << nPrivateTokenCount - 1 << "\n";
1018  }
1019 
1020  return 1;
1021  }
1022 
1023  return nReturnVal;
1024 }
1025 
1026 /*
1027 
1028  enum tokenState {
1029  blankToken,
1030  protoToken,
1031  signedToken,
1032  spendableToken,
1033  verifiedToken,
1034  errorToken
1035  };
1036 
1037  */
1038 
1039 bool Token::GetPrototoken(OTASCIIArmor& ascPrototoken, int32_t nTokenIndex)
1040 {
1041  // out of bounds. For a count 10 element array, index 10 is out of bounds.
1042  // thus if attempted index is equal or larger to the count, out of bounds.
1043  if (nTokenIndex >= m_nTokenCount) {
1044  return false;
1045  }
1046 
1047  for (auto& it : m_mapPublic) {
1048  OTASCIIArmor* pPrototoken = it.second;
1049  OT_ASSERT(nullptr != pPrototoken);
1050 
1051  const bool bSuccess = (nTokenIndex == it.first);
1052 
1053  if (bSuccess) {
1054  ascPrototoken.Set(*pPrototoken);
1055 
1056  return true;
1057  }
1058  }
1059  return false;
1060 }
1061 
1063  int32_t nTokenIndex)
1064 {
1065  // out of bounds. For a count 10 element array, index 10 is out of bounds.
1066  // thus if attempted index is equal or larger to the count, out of bounds.
1067  if (nTokenIndex >= m_nTokenCount) {
1068  return false;
1069  }
1070 
1071  for (auto& it : m_mapPrivate) {
1072  OTASCIIArmor* pPrototoken = it.second;
1073  OT_ASSERT(nullptr != pPrototoken);
1074 
1075  bool bSuccess = (nTokenIndex == it.first);
1076 
1077  if (bSuccess) {
1078  ascPrototoken.Set(*pPrototoken);
1079  return true;
1080  }
1081  }
1082  return false;
1083 }
1084 
1085 // static
1087  const OTPseudonym& theNym,
1088  Mint& theMint,
1089  int64_t lDenomination,
1090  int32_t nTokenCount)
1091 {
1092  Token* pToken = Token::LowLevelInstantiate(thePurse); // already asserts.
1093  OT_ASSERT(nullptr != pToken); // Just for good measure.
1094 
1095  const bool bGeneratedRequest = pToken->GenerateTokenRequest(
1096  theNym, theMint, lDenomination, nTokenCount);
1097 
1098  if (!bGeneratedRequest) {
1099  otErr << __FUNCTION__ << ": Failed trying to generate token request.\n";
1100  delete pToken;
1101  pToken = nullptr;
1102  }
1103 
1104  return pToken;
1105 }
1106 
1107 inline bool Token::ChooseIndex(const int32_t nIndex)
1108 {
1109  if (nIndex > (m_nTokenCount - 1) || nIndex < 0)
1110  return false;
1111  else {
1112  m_nChosenIndex = nIndex;
1113  return true;
1114  }
1115 }
1116 
1117 // The Mint has signed the token, and is sending it back to the client.
1118 // (we're near Lucre step 3 with this function)
1119 void Token::SetSignature(const OTASCIIArmor& theSignature, int32_t nTokenIndex)
1120 {
1121  // The server sets the signature, and then sends the token back to the
1122  // client. We release all these prototokens before doing so, because there's
1123  // no point in sending them all back to the client again, who already has
1124  // them anyway.
1125  // This is important because otherwise I wouldn't release, because the
1126  // client
1127  // still has to look up the private coin in order to unblind. But we're not
1128  // on the client if we're signing -- we're on the server -- who doesn't have
1129  // those private coins anyway.
1131 
1132  // We now officially have the bank's signature on this token.
1133  m_Signature.Set(theSignature);
1134 
1135  // otErr << "DEBUG Token::SetSignature. nTokenIndex is %d.\nm_Signature
1136  // is:\n%s\n"
1137  // "-------------------------------------\n",
1138  // nTokenIndex, m_Signature.Get());
1139 
1140  // We have to flag which index was signed by the mint, so that
1141  // the client knows which private coin to use for unblinding.
1142  // (Once the coin is unblinded, it will be ready to spend.)
1143  ChooseIndex(nTokenIndex);
1144 
1146 }
1147 
1148 bool Token::GetSignature(OTASCIIArmor& theSignature) const
1149 {
1150  theSignature = m_Signature;
1151 
1152  return true;
1153 }
1154 
1155 // **** VERIFY THE TOKEN WHEN REDEEMED AT THE SERVER
1156 // Lucre step 5: token verifies when it is redeemed by merchant.
1157 // IMPORTANT: while stored on the client side, the tokens are
1158 // encrypted to the client side nym. But when he redeems them to
1159 // the server, he re-encrypts them first to the SERVER's public nym.
1160 // So by the time it comes to verify, we are opening this envelope
1161 // with the Server's Nym.
1162 bool Token::VerifyToken(OTPseudonym& theNotary, Mint& theMint)
1163 {
1164  // otErr << "%s <bank info> <coin>\n",argv[0]);
1165 
1166  if (Token::spendableToken != m_State) {
1167  otErr << "Expected spendable token in Token::VerifyToken\n";
1168 
1169  return false;
1170  }
1171 
1172  // _OT_Lucre_Dumper setDumper; // OTMint::VerifyToken already does this.
1173  // Unnecessary here?
1174 
1175  // load the bank and coin info into the bios
1176  // The Mint private info is encrypted in m_ascPrivate. So I need to extract
1177  // that
1178  // first before I can use it.
1179  OTEnvelope theEnvelope(m_ascSpendable);
1180 
1181  OTString strContents; // output from opening the envelope.
1182  // Decrypt the Envelope into strContents
1183  if (!theEnvelope.Open(theNotary, strContents))
1184  return false; // todo log error, etc.
1185 
1186  // Verify that the series is correct...
1187  // (Otherwise, someone passed us the wrong Mint and the
1188  // thing won't verify anyway, since we'd have the wrong keys.)
1189  if (m_nSeries != theMint.GetSeries() ||
1190  // Someone might, however, in a clever attack, choose to leave
1191  // the series intact, but change the expiration dates, so that the
1192  // mint keys continue to work properly for this token, but then
1193  // when we check the date, it APPEARS good, when really the dates
1194  // were altered! To prevent this, we explicitly verify the series
1195  // information on the token against the same info on the mint,
1196  // BEFORE checking the date.
1197  m_VALID_FROM != theMint.GetValidFrom() ||
1198  m_VALID_TO != theMint.GetValidTo()) {
1199  otOut << "Token series information doesn't match Mint series "
1200  "information!\n";
1201  return false;
1202  }
1203 
1204  // Verify whether token has expired...expiration date is validated here.
1205  // We know the series is correct or the key wouldn't verify below... and
1206  // we know that the dates are correct because we compared them against the
1207  // mint of that series above. So now we just make sure that the CURRENT date
1208  // and time is within the range described on the token.
1209  if (!VerifyCurrentDate()) {
1210  otOut << "Token is expired!\n";
1211  return false;
1212  }
1213 
1214  // pass the cleartext Lucre spendable coin data to the Mint to be verified.
1215  if (theMint.VerifyToken(theNotary, strContents,
1216  GetDenomination())) // Here's the boolean output:
1217  // coin is verified!
1218  {
1219  otOut << "Token verified!\n";
1220  return true;
1221  }
1222  else {
1223  otOut << "Bad coin!\n";
1224  return false;
1225  }
1226 }
1227 
1228 // SUBCLASSES OF OTTOKEN FOR EACH DIGITAL CASH ALGORITHM.
1229 
1230 #if defined(OT_CASH_USING_MAGIC_MONEY)
1231 // Todo: Someday...
1232 #endif // Magic Money
1233 
1234 } // namespace opentxs
int32_t m_nChosenIndex
Definition: Token.hpp:246
EXPORT bool StorePlainString(std::string strContents, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:698
OTLOG_IMPORT OTLogStream otLog4
virtual EXPORT void Release()
static EXPORT int32_t GetMinimumPrototokenCount()
Definition: Token.cpp:180
EXPORT bool GetPrototoken(OTASCIIArmor &ascPrototoken, int32_t nTokenIndex)
Definition: Token.cpp:1039
EXPORT void ReleasePrototokens()
Definition: Token.cpp:310
EXPORT bool CalculateDigest(const OTData &dataInput)
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
Definition: Token.cpp:871
OTASCIIArmor m_Signature
Definition: Token.hpp:227
static EXPORT bool DearmorAndTrim(const OTString &strInput, OTString &strOutput, OTString &strFirstLine)
Definition: OTContract.cpp:158
int32_t m_nSeries
Definition: Token.hpp:268
EXPORT bool GetSignature(OTASCIIArmor &theSignature) const
Definition: Token.cpp:1148
const int32_t Token__nMinimumPrototokenCount
Definition: Token.cpp:178
EXPORT int64_t ToLong() const
Definition: OTString.cpp:702
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
int32_t GetSeries() const
Definition: Token.hpp:368
const OTIdentifier & GetAssetID() const
virtual bool SaveContractWallet(std::ofstream &ofs) const
Definition: Token.cpp:339
OTLOG_IMPORT OTLogStream otOut
static EXPORT Token * LowLevelInstantiate(const Purse &thePurse)
Definition: Token.cpp:418
virtual EXPORT bool VerifyToken(OTPseudonym &theNotary, OTString &theCleartextToken, int64_t lDenomination)=0
const OTIdentifier & GetAssetID() const
Definition: Purse.hpp:335
EXPORT bool GetSpendableString(OTNym_or_SymmetricKey theOwner, OTString &theString) const
Definition: Token.cpp:751
time64_t OTTimeGetTimeFromSeconds(int64_t seconds)
Definition: Common.hpp:215
EXPORT bool Open(const OTPseudonym &theRecipient, OTString &theOutput, const OTPasswordData *pPWData=nullptr)
Definition: OTEnvelope.cpp:581
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
EXPORT Token()
Definition: Token.cpp:219
EXPORT bool VerifyCurrentDate()
EXPORT bool WriteArmoredString(OTString &strOutput, const std::string str_type, bool bEscaped=false) const
bool m_bSavePrivateKeys
Definition: Token.hpp:270
int32_t GetSeries() const
Definition: Mint.hpp:214
EXPORT bool GetPrivatePrototoken(OTASCIIArmor &ascPrototoken, int32_t nTokenIndex)
Definition: Token.cpp:1062
EXPORT bool Exists() const
Definition: OTString.cpp:1035
void SetDenomination(int64_t lVal)
Definition: Token.hpp:413
EXPORT void SetString(const char *szString)
EXPORT bool VerifyToken(OTPseudonym &theNotary, Mint &theMint)
Definition: Token.cpp:1162
EXPORT void Format(const char *fmt,...)
Definition: OTString.cpp:1319
virtual void UpdateContents()
Definition: Token.cpp:771
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
static EXPORT Token * InstantiateAndGenerateTokenRequest(const Purse &thePurse, const OTPseudonym &theNym, Mint &theMint, int64_t lDenomination, int32_t nTokenCount=Token::GetMinimumPrototokenCount())
Definition: Token.cpp:1086
time64_t GetValidTo() const
Definition: Mint.hpp:222
EXPORT bool Seal_or_Encrypt(OTEnvelope &outputEnvelope, const OTString &strInput, const OTString *pstrDisplay=nullptr)
virtual EXPORT bool GenerateTokenRequest(const OTPseudonym &theNym, Mint &theMint, int64_t lDenomination, int32_t nTokenCount=Token::GetMinimumPrototokenCount())=0
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
Definition: OTString.cpp:1055
EXPORT void SetSignature(const OTASCIIArmor &theSignature, int32_t nTokenIndex)
Definition: Token.cpp:1119
static EXPORT bool LoadEncodedTextField(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
EXPORT bool GetAsciiArmoredData(OTASCIIArmor &theArmoredText, bool bLineBreaks=true) const
Definition: OTEnvelope.cpp:162
int64_t GetDenomination() const
Definition: Token.hpp:409
virtual void Release()
Definition: Token.cpp:286
EXPORT bool IsTokenAlreadySpent(OTString &theCleartextToken)
Definition: Token.cpp:557
#define OT_ASSERT(x)
Definition: Assert.hpp:150
mapOfPrototokens m_mapPrivate
Definition: Token.hpp:240
EXPORT bool RecordTokenAsSpent(OTString &theCleartextToken)
Definition: Token.cpp:590
OTString m_strContractType
Definition: OTContract.hpp:178
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
time64_t GetValidFrom() const
Definition: Mint.hpp:218
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
bool m_bPasswordProtected
Definition: Token.hpp:221
void InitToken()
Definition: Token.cpp:207
OTASCIIArmor m_ascSpendable
Definition: Token.hpp:224
int32_t m_nTokenCount
Definition: Token.hpp:244
EXPORT const char * Get() const
Definition: OTString.cpp:1045
EXPORT bool ReassignOwnership(OTNym_or_SymmetricKey &oldOwner, OTNym_or_SymmetricKey &newOwner)
Definition: Token.cpp:716
OTLOG_IMPORT OTLogStream otErr
mapOfPrototokens m_mapPublic
Definition: Token.hpp:237
OTIdentifier m_AssetTypeID
EXPORT void Release_Token()
Definition: Token.cpp:275
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
EXPORT bool CompareID(const OTNym_or_SymmetricKey &rhs) const
tokenState m_State
Definition: Token.hpp:269
EXPORT bool Contains(const char *compare) const
Definition: OTString.cpp:1137
static EXPORT Token * TokenFactory(OTString strInput)
Definition: Token.cpp:518
int64_t m_lDenomination
Definition: Token.hpp:230
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
EXPORT bool LoadContractFromString(const OTString &theStr)
static EXPORT const OTString & Spent()
Definition: OTFolders.cpp:375
virtual EXPORT ~Token()
Definition: Token.cpp:294
virtual EXPORT void Release()
Definition: OTString.cpp:765
bool ChooseIndex(int32_t nIndex)
Definition: Token.cpp:1107
EXPORT bool Open_or_Decrypt(const OTEnvelope &inputEnvelope, OTString &strOutput, const OTString *pstrDisplay=nullptr)
const OTIdentifier & GetServerID() const
Definition: Purse.hpp:331