Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTPseudonym.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTPseudonym.cpp
4  *
5  */
6 
7 /************************************************************
8  -----BEGIN PGP SIGNED MESSAGE-----
9  Hash: SHA1
10 
11  * OPEN TRANSACTIONS
12  *
13  * Financial Cryptography and Digital Cash
14  * Library, Protocol, API, Server, CLI, GUI
15  *
16  * -- Anonymous Numbered Accounts.
17  * -- Untraceable Digital Cash.
18  * -- Triple-Signed Receipts.
19  * -- Cheques, Vouchers, Transfers, Inboxes.
20  * -- Basket Currencies, Markets, Payment Plans.
21  * -- Signed, XML, Ricardian-style Contracts.
22  * -- Scripted smart contracts.
23  *
24  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
25  *
26  * EMAIL:
28  *
29  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
30  *
31  * KEY FINGERPRINT (PGP Key in license file):
32  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
33  *
34  * OFFICIAL PROJECT WIKI(s):
35  * https://github.com/FellowTraveler/Moneychanger
36  * https://github.com/FellowTraveler/Open-Transactions/wiki
37  *
38  * WEBSITE:
39  * http://www.OpenTransactions.org/
40  *
41  * Components and licensing:
42  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
43  * -- otlib.........A class library.......LICENSE:...LAGPLv3
44  * -- otapi.........A client API..........LICENSE:...LAGPLv3
45  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
46  * -- otserver......Server Application....LICENSE:....AGPLv3
47  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
48  *
49  * All of the above OT components were designed and written by
50  * Fellow Traveler, with the exception of Moneychanger, which
51  * was contracted out to Vicky C ([email protected]).
52  * The open-source community has since actively contributed.
53  *
54  * -----------------------------------------------------
55  *
56  * LICENSE:
57  * This program is free software: you can redistribute it
58  * and/or modify it under the terms of the GNU Affero
59  * General Public License as published by the Free Software
60  * Foundation, either version 3 of the License, or (at your
61  * option) any later version.
62  *
63  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
64  * section 7: (This paragraph applies only to the LAGPLv3
65  * components listed above.) If you modify this Program, or
66  * any covered work, by linking or combining it with other
67  * code, such other code is not for that reason alone subject
68  * to any of the requirements of the GNU Affero GPL version 3.
69  * (==> This means if you are only using the OT API, then you
70  * don't have to open-source your code--only your changes to
71  * Open-Transactions itself must be open source. Similar to
72  * LGPLv3, except it applies to software-as-a-service, not
73  * just to distributing binaries.)
74  *
75  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
76  * used by Open Transactions: This program is released under
77  * the AGPL with the additional exemption that compiling,
78  * linking, and/or using OpenSSL is allowed. The same is true
79  * for any other open source libraries included in this
80  * project: complete waiver from the AGPL is hereby granted to
81  * compile, link, and/or use them with Open-Transactions,
82  * according to their own terms, as long as the rest of the
83  * Open-Transactions terms remain respected, with regard to
84  * the Open-Transactions code itself.
85  *
86  * Lucre License:
87  * This code is also "dual-license", meaning that Ben Lau-
88  * rie's license must also be included and respected, since
89  * the code for Lucre is also included with Open Transactions.
90  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
91  * The Laurie requirements are light, but if there is any
92  * problem with his license, simply remove the Lucre code.
93  * Although there are no other blind token algorithms in Open
94  * Transactions (yet. credlib is coming), the other functions
95  * will continue to operate.
96  * See Lucre on Github: https://github.com/benlaurie/lucre
97  * -----------------------------------------------------
98  * You should have received a copy of the GNU Affero General
99  * Public License along with this program. If not, see:
100  * http://www.gnu.org/licenses/
101  *
102  * If you would like to use this software outside of the free
103  * software license, please contact FellowTraveler.
104  * (Unfortunately many will run anonymously and untraceably,
105  * so who could really stop them?)
106  *
107  * DISCLAIMER:
108  * This program is distributed in the hope that it will be
109  * useful, but WITHOUT ANY WARRANTY; without even the implied
110  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
111  * PURPOSE. See the GNU Affero General Public License for
112  * more details.
113 
114  -----BEGIN PGP SIGNATURE-----
115  Version: GnuPG v1.4.9 (Darwin)
116 
117  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
118  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
119  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
120  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
121  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
122  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
123  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
124  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
125  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
126  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
127  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
128  kamH0Y/n11lCvo1oQxM+
129  =uSzz
130  -----END PGP SIGNATURE-----
131  **************************************************************/
132 
133 #include "stdafx.hpp"
134 
135 #include "OTPseudonym.hpp"
136 #include "crypto/OTCredential.hpp"
137 #include "util/OTFolders.hpp"
138 #include "OTLedger.hpp"
139 #include "OTLog.hpp"
140 #include "OTMessage.hpp"
141 #include "crypto/OTPassword.hpp"
142 #include "crypto/OTPasswordData.hpp"
143 #include "crypto/OTSignedFile.hpp"
144 #include "OTStorage.hpp"
145 #include "crypto/OTSubkey.hpp"
146 #include "crypto/OTSymmetricKey.hpp"
147 
148 #include <irrxml/irrXML.hpp>
149 
150 #include <algorithm>
151 #include <fstream>
152 #include <memory>
153 
154 // static
155 
156 namespace opentxs
157 {
158 
160  const OTString* pstrName,
161  const char* szFuncName)
162 {
163  const char* szFunc =
164  (nullptr != szFuncName) ? szFuncName : "OTPseudonym::LoadPublicNym";
165 
166  const OTString strNymID(NYM_ID);
167 
168  // If name is empty, construct one way,
169  // else construct a different way.
170  //
171  OTPseudonym* pNym = ((nullptr == pstrName) || !pstrName->Exists())
172  ? (new OTPseudonym(NYM_ID))
173  : (new OTPseudonym(*pstrName, strNymID, strNymID));
174  OT_ASSERT_MSG(nullptr != pNym,
175  "OTPseudonym::LoadPublicNym: Error allocating memory.\n");
176 
177  bool bLoadedKey =
178  pNym->LoadPublicKey(); // Deprecated. Only used for old-style Nyms.
179  // Eventually, remove this. Currently
180  // LoadPublicKey calls LoadCredentials, which is
181  // what we should be calling, once the nym's own
182  // keypair is eliminated.
183 
184  // First load the public key
185  if (!bLoadedKey)
186  otWarn << __FUNCTION__ << ": " << szFunc
187  << ": Unable to find nym: " << strNymID << "\n";
188  else if (!pNym->VerifyPseudonym())
189  otErr << __FUNCTION__ << ": " << szFunc
190  << ": Security: Failure verifying Nym: " << strNymID << "\n";
191  else if (!pNym->LoadSignedNymfile(*pNym)) {
192  otLog4 << "OTPseudonym::LoadPublicNym " << szFunc
193  << ": Usually normal: There's no Nymfile (" << strNymID
194  << "), though there IS a public "
195  "key, which checks out. It's probably just someone else's "
196  "Nym. (So I'm still returning this Nym to "
197  "the caller so he can still use the public key.)\n";
198  return pNym;
199  }
200  else // success
201  return pNym;
202 
203  delete pNym;
204  pNym = nullptr;
205 
206  return nullptr;
207 }
208 
209 /*
210 
211  Normally when I read someone ELSE'S public key, I DON'T have their Nymfile.
212  Therefore I don't HAVE any of their credentials, I only have the NymID and the
213  public key itself. Which was fine before, since you hashed the public key to
214  verify the NymID -- and if it matched, then all was good.
215 
216  But let's say I'm reading a public key from a key credential... the hash of
217  that key
218  (or credential) is NOT necessarily the hash of the Nym's ID. So how can I
219  verify it?
220 
221  Normally I read from: ~/.ot/client_data/pubkeys/NYM_ID (for the public key
222  for that Nym.)
223 
224  Instead I want to read up all available credentials for that Nym.
225  Let's say their IDs are stored in: ~/.ot/client_data/pubkeys/NYM_ID.cred
226  And the credentials themselves:
227  ~/.ot/client_data/pubkeys/credentials/NYM_ID/CREDENTIAL_ID
228 
229  So let's say I have a NymID and I need to load his credentials and use his keys
230  to verify
231  the Nym and also to send him messages, verify his signatures on instruments,
232  etc.
233 
234  pNym->LoadPublicKey() should load the UNSIGNED Nymfile from:
235  ~/.ot/client_data/pubkeys/NYM_ID.cred
236  Which, in the course of loading, should automatically load all its credentials
237  from
238  ~/.ot/client_data/pubkeys/credentials/NYM_ID/CREDENTIAL_ID
239 
240  From there, we call VerifyPseudonym, which verifies all the credentials
241  internally, including
242  their signatures, and which verifies them against their source, which can also
243  be hashed to
244  reproduce the NymID.
245 
246  ...SINCE all the credentials verify AGAINST THEIR SOURCE, and the source hashes
247  to form the NymID,
248  then the Nym is therefore self-verifying, without having to sign the nymfile
249  itself (for public nyms.)
250  If I want to sign it anyway, well I will need a private Nym to sign it with, I
251  cannot sign it with
252  only a public Nym. So I will have to pass the signer in if I want to do that.
253  But it's unnecessary,
254  and in fact it's also unnecessary for private Nyms, (or is it?) because all the
255  credentials ARE signed
256  contracts already, and since they all ultimately verify to their source.
257 
258  Therefore this eliminates LoadSignedNymfile? And SaveSignedNymFile? Or augments
259  -- since we will be backwards compatible...
260 
261  I'll load the local Nym's credential list and the public nym's credential list
262  from the same
263  place: ~/.ot/client_data/credentials/NYM_ID.cred
264  EITHER WAY I'll load the actual credentials, each from
265  ~/.ot/client_data/credentials/NYM_ID/CRED_ID
266  Then for the local Nym, I'll load his Nymfile like normal from
267  ~/.ot/client_data/nyms/NYM_ID
268  (For public Nyms, I don't need to load a Nymfile or anything else -- the
269  credentials are all there is.)
270 
271  But I still want my Nymfile itself signed, so people can't mess with my
272  transaction numbers.
273  What it comes down to is, I must put the credential list in a separate file,
274  load it, verify it,
275  and then use it to verify the signature on the Nymfile which contains
276  everything else. So the
277  "LoadSignedNymfile" process isn't going to change for the Nymfile itself, and I
278  will have the credential
279  list in a separate file, just like the certs were in a separate file in the
280  original system (for the
281  same reasons.)
282 
283  */
284 
285 // static
287  bool bChecking,
288  const OTString* pstrName,
289  const char* szFuncName,
290  const OTPasswordData* pPWData,
291  const OTPassword* pImportPassword)
292 {
293  const char* szFunc =
294  (nullptr != szFuncName) ? szFuncName : "OTPseudonym::LoadPrivateNym";
295 
296  if (NYM_ID.IsEmpty()) return nullptr;
297 
298  const OTString strNymID(NYM_ID);
299 
300  // If name is empty, construct one way,
301  // else construct a different way.
302  //
303  OTPseudonym* pNym = ((nullptr == pstrName) || !pstrName->Exists())
304  ? (new OTPseudonym(NYM_ID))
305  : (new OTPseudonym(*pstrName, strNymID, strNymID));
306  OT_ASSERT_MSG(nullptr != pNym,
307  "OTPseudonym::LoadPrivateNym: Error allocating memory.\n");
308 
309  OTPasswordData thePWData(OT_PW_DISPLAY);
310  if (nullptr == pPWData) pPWData = &thePWData;
311 
312  bool bLoadedKey = pNym->Loadx509CertAndPrivateKey(
313  bChecking, pPWData,
314  pImportPassword); // old style. (Deprecated.) Eventually remove this.
315  //*** Right now Loadx509CertAndPrivateKey calls LoadCredentials at its top,
316  // which is what we should be calling here. But that function handles
317  // old-style Nyms too, so we keep it around until we lose those. //
318  //<====================
319 
320  // Error loading x509CertAndPrivateKey.
321  if (!bLoadedKey)
323  bChecking ? 1 : 0,
324  "%s: %s: (%s: is %s). Unable to load credentials, "
325  "cert and private key for: %s (maybe this nym doesn't exist?)\n",
326  __FUNCTION__, szFunc, "bChecking", bChecking ? "true" : "false",
327  strNymID.Get());
328  // success loading x509CertAndPrivateKey,
329  // failure verifying pseudonym public key.
330  else if (!pNym->VerifyPseudonym()) // <====================
331  otErr << __FUNCTION__ << " " << szFunc
332  << ": Failure verifying Nym public key: " << strNymID << "\n";
333  // success verifying pseudonym public key.
334  // failure loading signed nymfile.
335  else if (!pNym->LoadSignedNymfile(*pNym)) // Unlike with public key,
336  // with private key we DO
337  // expect nymfile to be
338  // here.
339  otErr << __FUNCTION__ << " " << szFunc
340  << ": Failure calling LoadSignedNymfile: " << strNymID << "\n";
341  else // ultimate success.
342  return pNym;
343 
344  delete pNym;
345  pNym = nullptr;
346 
347  return nullptr;
348 }
349 
350 // pstrSourceForNymID if left nullptr, will use the Nym's public key (OT's
351 // original
352 // method.)
353 // Since that is already the Nym's ID (hash of public key) then providing the
354 // Nym's public
355 // key here will naturally hash to the correct ID and thus is the logical
356 // default action.
357 //
358 // But pstrSourceForNymID might contain a Bitcoin or Namecoin address, or the DN
359 // info from
360 // a traditional Certificate Authority, or a Freenet or Tor or I2P URL, or
361 // indeed any URL
362 // at all... We will also continue to support a simple public key, and by
363 // default, if none
364 // is provided, we will use the Nym's own public key as the source, and if the
365 // credential
366 // contents are not provided, the public cert or public key in full raw text
367 // shall be placed
368 // in this field.
369 //
370 // In the case of a traditional CA-issued cert, you would pass the unique issuer
371 // and subject DN
372 // info into the pstrSourceForNymID parameter (where the hash of that data
373 // results in the NymID,
374 // so you should only do it with a brand-new Nym in that case, since it will
375 // change the NymID.
376 // So for the API for creating new Nyms, we will force it that way in the
377 // interface to keep things
378 // safe, but at this low of a level, the power exists.) Continuing that same
379 // example, you would
380 // pass your actual public cert as pstrCredentialContents.
381 //
382 // If pstrSourceForNymID was a URL, then perhaps pstrCredentialContents would
383 // contain the contents
384 // located at that URL. As long as the contents of the string
385 // pstrCredentialContents can also
386 // be found at pstrSourceForNymID (or a list of hashes of similar strings...)
387 // then the master
388 // credential will verify. So for example, at the URL you might just post the
389 // same public cert,
390 // or you might have some OTCredential serialized string that contains the Nym
391 // ID, the Master
392 // credential IDs and subcredential IDs that are valid and invalid.
393 //
394 // Thought: Seems that there are three ways of exporting the OTCredential: as
395 // IDs only, as IDs
396 // with public keys, and as IDs with public keys and private keys.
397 //
398 // hash of pstrSourceForNymID is the NymID, and hash of pstrCredentialContents
399 // is the credential ID for this new master credential.
400 //
402  OTString& strOutputMasterCredID,
403  const OTString* pstrSourceForNymID, // If nullptr, it uses the Nym's
404  // (presumed) existing source
405  // as the source.
406  const int32_t nBits, // Ignored unless pmapPrivate is nullptr.
407  const OTString::Map* pmapPrivate, // If nullptr, then the keys are
408  // generated in here.
409  const OTString::Map* pmapPublic, // In the case of key credentials,
410  // public is optional since it can
411  // already be derived from
412  // private. For now we pass it
413  // through... May eliminate this
414  // parameter later if not needed.
415  const OTPasswordData* pPWData, // Pass in the string to show users here,
416  // if/when asking for the passphrase.
417  bool bChangeNymID) // Must be explicitly set to true, to change
418  // the Nym's ID. Other restrictions also
419  // apply... must be your first master
420  // credential. Must have no accounts.
421  // Basically can only be used for brand-new
422  // Nyms in circumstances where it's assumed
423  // the Nym's ID is in the process of being
424  // generated anyway. Should never be used on
425  // some existing Nym who is already in the
426  // wallet and who may even have accounts
427  // somewhere already.
428 {
429  const OTString* pstrSourceToUse = nullptr;
430  OTString strTempSource; // Used sometimes.
431 
432  const OTString::Map* pmapActualPrivate = nullptr;
433  const OTString::Map* pmapActualPublic = nullptr;
434 
435  OTString::Map mapPrivate, mapPublic; // Used sometimes.
436 
437  // If keys are passed in, then those are the keys we're meant to use for the
438  // credential.
439  //
440  // Note: if the Nym is self-signed, then his "source" is his public key,
441  // which can thus
442  // never change (because it would change his ID.) We only allow this in the
443  // case where a
444  // Nym is first being created.
445  //
446  // But if the Nym has a real source (such as a URL, or Namecoin address,
447  // etc) then he should
448  // be able to create new credentials, and should BOTH be able to generate
449  // keys on the spot,
450  // OR pass in keys to use that were generated before this function was
451  // called.
452  //
453  // Therefore here, we choose to use the keys passed in--if they were
454  // passed--and otherwise
455  // we generate the keys.
456  //
457  OT_ASSERT(nullptr != m_pkeypair);
458 
459  if (nullptr == pmapPrivate) // If no keys were passed in...
460  {
461  // That means to use (or generate) my existing keypair as the signing
462  // key,
463  // and generate the other two keypairs also.
464 
465  const size_t sizeMapPublic = mapPublic.size();
466  const size_t sizeMapPrivate = mapPrivate.size();
467 
468  OTString strReason, strPublicError, strPrivateError;
469 
470  // Nym already has a keypair. (Use it as the signing key.)
471  //
472  // NOTE: We only want to do this if the Nym doesn't already have any
473  // credentials.
474  // Presumably if there are already credentials, then we want any NEW
475  // credentials to
476  // have their own keys. Only when there are none (meaning, we are
477  // currently creating
478  // the FIRST one) do we want to use the existing keypair. Otherwise we
479  // want to generate
480  // a new signing key.
481  //
482  // Exception: "Presumably if there are already credentials, then we want
483  // any NEW credentials
484  // to have their own keys" ==> If it's a self-signed Nym, then EVEN if
485  // there are existing
486  // credentials, we want to use the existing signing key, since in that
487  // case, all credentials
488  // would have the same signing key, which is also the Nym ID source (we
489  // cannot ever change it,
490  // since that would also change the Nym's ID. That is the drawback of
491  // self-signed Nyms.)
492  //
493  // Therefore we need to check here to see if the Nym is self-signed:
494  //
495  OTIdentifier theSelfSignedNymID;
496  m_pkeypair->CalculateID(theSelfSignedNymID);
497 
498  if ((m_mapCredentials.empty() ||
499  CompareID(theSelfSignedNymID)) && // If there AREN'T any
500  // credentials yet, or if
501  // the Nym is self-signed,
502  (HasPublicKey() || // and if we have a keypair already, use it
503  LoadPublicKey())) // to create the first credential.
504  {
505  strReason.Set("Using existing signing key for new master "
506  "credential (preserving existing Nym keypair.)");
507  strPublicError.Set("In %s, line %d: Failed using existing public "
508  "key as public signing key in "
509  "OTPseudonym::%s.\n");
510  strPrivateError.Set("In %s, line %d: Failed using existing private "
511  "key as private signing key in "
512  "OTPseudonym::%s.\n");
513  }
514  else // GENERATE A NEW KEYPAIR.
515  {
516  const bool bCreateKeySigning = m_pkeypair->MakeNewKeypair(nBits);
517  OT_ASSERT(bCreateKeySigning);
518 
519  m_pkeypair->SaveAndReloadBothKeysFromTempFile(); // Keys won't be
520  // right until this
521  // happens.
522  // (Necessary evil
523  // until better
524  // fix.) Todo:
525  // eliminate need
526  // to do this.
527 
528  strReason.Set("Generating signing key for new master credential.");
529  strPublicError.Set("In %s, line %d: Failed creating public signing "
530  "key in OTPseudonym::%s.\n");
531  strPrivateError.Set("In %s, line %d: Failed creating private "
532  "signing key in OTPseudonym::%s.\n");
533  }
534 
535  // SIGNING KEY
536  //
537  OTString strPublicKey, strPrivateCert;
538 
539  const bool b1 = m_pkeypair->GetPublicKey(
540  strPublicKey, false); // bEscaped=true by default.
541  const bool b2 = m_pkeypair->SaveCertAndPrivateKeyToString(
542  strPrivateCert, &strReason);
543 
544  if (b1 && b2) {
545  mapPublic.insert(
546  std::pair<std::string, std::string>("S", strPublicKey.Get()));
547  mapPrivate.insert(
548  std::pair<std::string, std::string>("S", strPrivateCert.Get()));
549  }
550 
551  if (!b1 || !(mapPublic.size() > sizeMapPublic)) {
552  OTLog::vError(strPublicError.Get(), __FILE__, __LINE__,
553  __FUNCTION__);
554  return false;
555  }
556 
557  if (!b2 || !(mapPrivate.size() > sizeMapPrivate)) {
558  OTLog::vError(strPrivateError.Get(), __FILE__, __LINE__,
559  __FUNCTION__);
560  return false;
561  }
562  // *************************************************************************************8
563  // Whether the Nym already had a keypair, and we used it as the signing
564  // key,
565  // or whether we generated the signing key on the spot, either way we
566  // still
567  // need to generate the other two keys.
568  //
569  // Create 2 keypairs here (for authentication and for encryption.)
570  //
571  // Use the public/private data for all 3 keypairs onto mapPublic and
572  // mapPrivate.
573  //
574 
575  OTKeypair keyAuth, keyEncr; // (The signing keypair already exists by
576  // this point. These are the other two we
577  // need.)
578 
579  const bool bCreateKeyAuth = keyAuth.MakeNewKeypair();
580  const bool bCreateKeyEncr = keyEncr.MakeNewKeypair();
581 
582  OT_ASSERT(bCreateKeyAuth && bCreateKeyEncr);
583 
584  keyAuth.SaveAndReloadBothKeysFromTempFile(); // Keys won't be right
585  // until this happens.
586  keyEncr.SaveAndReloadBothKeysFromTempFile(); // (Necessary evil until
587  // better fix.) Todo:
588  // eliminate need to do
589  // this.
590 
591  strPublicKey.Release();
592  strPrivateCert.Release();
593 
594  const bool b3 = keyAuth.GetPublicKey(
595  strPublicKey, false); // bEscaped=true by default.
596  const bool b4 =
597  keyAuth.SaveCertAndPrivateKeyToString(strPrivateCert, &strReason);
598 
599  if (b3 && b4) {
600  mapPublic.insert(
601  std::pair<std::string, std::string>("A", strPublicKey.Get()));
602  mapPrivate.insert(
603  std::pair<std::string, std::string>("A", strPrivateCert.Get()));
604  }
605 
606  strPublicKey.Release();
607  strPrivateCert.Release();
608 
609  const bool b5 = keyEncr.GetPublicKey(
610  strPublicKey, false); // bEscaped=true by default.
611  const bool b6 =
612  keyEncr.SaveCertAndPrivateKeyToString(strPrivateCert, &strReason);
613 
614  if (b5 && b6) {
615  mapPublic.insert(
616  std::pair<std::string, std::string>("E", strPublicKey.Get()));
617  mapPrivate.insert(
618  std::pair<std::string, std::string>("E", strPrivateCert.Get()));
619  }
620 
621  if (!(mapPublic.size() >= (sizeMapPublic + 3))) {
622  otErr
623  << "In " << __FILE__ << ", line " << __LINE__
624  << ": Failed adding (auth or encr) public keys in OTPseudonym::"
625  << __FUNCTION__ << ".\n";
626  return false;
627  }
628 
629  if (!(mapPrivate.size() >= (sizeMapPrivate + 3))) {
630  otErr << "In " << __FILE__ << ", line " << __LINE__
631  << ": Failed adding (auth or encr) private keys in "
632  "OTPseudonym::" << __FUNCTION__ << ".\n";
633  return false;
634  }
635 
636  pmapActualPrivate = &mapPrivate;
637  pmapActualPublic = &mapPublic;
638 
639  } // A private key wasn't passed in.
640 
641  // A keypair WAS passed in...
642  //
643  else {
644  // If keys were passed in, then we're going to use those to create the
645  // new credential.
646  //
647  pmapActualPrivate = pmapPrivate;
648  pmapActualPublic = pmapPublic;
649 
650  // Therefore in that case, the Nym had better not be self-signed, since
651  // if he was,
652  // he couldn't change the key (since his NymID is a hash of the public
653  // key.)
654  //
655  // Thus the Nym should have some other source besides his own key, or at
656  // least he
657  // should be a new Nym being created.
658  }
659  //
660  // SOURCE
661  //
662  // A source was passed in. We know it's not a public key, since its hash
663  // will not match the existing
664  // Nym ID. (Only the existing public key will match that when hashed, and
665  // you can use that by passing nullptr
666  // already, which is the following block.) Therefore it must be one of the
667  // other choices: a Freenet/I2P/Tor URL,
668  // or indeed any URL at all, a Bitcoin address, a Namecoin address (which is
669  // actually a form of URL also.)
670  // Or of course, the Issuer/Subject DN info from a traditionally-issued
671  // cert. In which case we are low-level
672  // enough that we will potentially change the NymID here based on that
673  // option. But we won't do that for a public
674  // key, unless you pass nullptr.
675  //
676  if ((nullptr != pstrSourceForNymID) &&
677  pstrSourceForNymID->Exists()) // A source was passed in.
678  {
679  // -- Perhaps he already has a source, in which case he one he already
680  // has should match the
681  // one that was passed in. (If one was.)
682  // -- Or perhaps he doesn't have a source, in which case one SHOULD have
683  // been passed in.
684  // -- Assuming that's the case, that's what we'll use.
685  // -- But if he doesn't have one, AND one wasn't passed in, then we will
686  // just created a self-signed Nym.
687  //
688  pstrSourceToUse = pstrSourceForNymID;
689 
690  if (!bChangeNymID && m_strSourceForNymID.Exists() &&
691  !pstrSourceForNymID->Compare(m_strSourceForNymID)) {
692  otErr << "In " << __FILE__ << ", line " << __LINE__
693  << ", OTPseudonym::" << __FUNCTION__
694  << ": The Nym already has a source, but a different "
695  "source was passed in (they should be identical, since "
696  "you can't change a Nym's "
697  "source without changing his ID.)\n";
698  return false;
699  }
700  }
701  else // No source was passed in. That means use the existing one if it
702  // exists,
703  { // or otherwise create it based on the key (self-signed Nym.)
704  //
705  if (m_strSourceForNymID.Exists()) // Use existing source.
706  strTempSource = m_strSourceForNymID;
707  // No source exists (nor was one passed in.) Thus create it based on the
708  // signing key (self-signed Nym.)
709  else if ((HasPublicKey() || LoadPublicKey()))
710  m_pkeypair->GetPublicKey(strTempSource); // bEscaped=true by
711  // default. Todo: someday
712  // change this to false.
713  // (It will invalidate
714  // existing NymIDs.)
715  else {
716  otErr << "In " << __FILE__ << ", line " << __LINE__
717  << ", OTPseudonym::" << __FUNCTION__
718  << ": Error: The Nym had no ID source, nor were we able "
719  "to derive one from his (non-existent) public key.\n";
720  return false;
721  }
722 
723  pstrSourceToUse = &strTempSource;
724 
725  // Hash the purported source, and see if it matches the existing NymID.
726  //
727  OTIdentifier theTempID;
728  theTempID.CalculateDigest(*pstrSourceToUse);
729  // m_pkeypair->CalculateID(theTempID);
730 
731  if (!bChangeNymID && !CompareID(theTempID)) {
732  OTString strNymID;
733  GetIdentifier(strNymID);
734 
735  OTIdentifier theKeypairNymID;
736  m_pkeypair->CalculateID(theKeypairNymID);
737 
738  const OTString strKeypairNymID(theKeypairNymID),
739  strCalculatedNymID(theTempID);
740 
741  otOut << __FUNCTION__
742  << ": No NymID Source was passed in, so I tried to use the "
743  "existing source (or if that was missing, the existing "
744  "public key) for "
745  "the Nym, but hashing that failed to produce the Nym's "
746  "ID. Meaning the Nym must have "
747  "some other source already, which needs to be passed into "
748  "this function, for it to work on this Nym.\n"
749  "NOTE: Pass 'bChangeNymID' into this function as true, if "
750  "you want to override this behavior.\n"
751  "NYM ID: " << strNymID
752  << " \n KEY PAIR CALCULATED ID: " << strKeypairNymID
753  << " \n CONTENTS CALCULATED ID: " << strCalculatedNymID
754  << " \n NYM ID SOURCE: " << pstrSourceToUse->Get() << "\n";
755  return false;
756  }
757  }
758 
759  // By this point, pstrSourceToUse is good to go, and calculates to the
760  // correct ID for this Nym.
761  // Also by this point, the Nym's source and ID are both definitely set and
762  // correct (before this function is even called.)
763  // Also by this point, pmapActualPrivate and pmapActualPublic are each set
764  // with their 3 keys.
765 
766  OT_ASSERT(nullptr != pstrSourceToUse);
767 
768  // See if there are any other master credentials already. If there are, make
769  // sure they have the same source string calculated above.
770  //
771  if (!m_mapCredentials.empty()) {
772  for (auto& it : m_mapCredentials) {
773  OTCredential* pCredential = it.second;
774  OT_ASSERT(nullptr != pCredential);
775 
776  if (false ==
777  pstrSourceToUse->Compare(pCredential->GetSourceForNymID())) {
778  otOut << __FUNCTION__
779  << ": Attempt to add new master credential failed to "
780  "match the NymID Source on an existing master "
781  "credential.\n";
782  return false;
783  }
784  }
785 
786  // bChangeNymID only works if we are adding the FIRST credential. You
787  // can't be changing
788  // a Nym's ID if he already has credentials, since we only made that
789  // possible in the first
790  // place to make it possible to add the first credential.
791  //
792  if (bChangeNymID) {
793  otErr << __FUNCTION__
794  << ": Failure: cannot change NymID for Nym who "
795  "already has credentials.\n";
796  return false;
797  }
798  }
799 
800  // Can't change the NymID if it's already registered at a server somewhere.
801  //
802  if (bChangeNymID && (!m_mapRequestNum.empty())) {
803  otErr << __FUNCTION__ << ": Failure: cannot change NymID for Nym who "
804  "already is registered at "
805  "transaction servers.\n";
806  return false;
807  }
808 
809  OT_ASSERT(nullptr != pmapActualPrivate);
810  OT_ASSERT(nullptr != pmapActualPublic);
811 
812  // Create a new master credential, and set its source string (which also
813  // sets
814  // the NymID).
815  //
817  *pstrSourceToUse, nBits, pmapActualPrivate, pmapActualPublic, pPWData);
818 
819  if (nullptr == pMaster) // Below this block, pMaster must be cleaned up.
820  {
821  otErr << __FUNCTION__ << ": Failed trying to create a new master "
822  "credential, while calling "
823  "OTCredential::CreateMaster.\n";
824  return false;
825  }
826 
827  // NOTE: The only way to verify a Master Credential is to go to its source
828  // (for its NymID)
829  // and see if the Master Credential ID is posted at that source. And since
830  // the Master Credential
831  // ID cannot possibly be known before the Master Credential is created and
832  // hashed, there is no
833  // way that Credential's ID could have already been posted at that source.
834  // Therefore it's
835  // impossible for the Credential to verify against the source at this time.
836  // (Although it must
837  // verify by the time the credential is registered at any OT server.)
838 
839  // We can still verify the credential internally, however. (Everything but
840  // the source.)
841  //
842  OTString strNymID;
843  GetIdentifier(strNymID);
844 
845  if (!pMaster->VerifyInternally()) {
846  OTIdentifier theTempID;
847  theTempID.CalculateDigest(*pstrSourceToUse);
848  const OTString strTempID(theTempID);
849  otErr << __FUNCTION__
850  << ": Failed trying to verify the new master credential.\n"
851  "Nym ID: " << strNymID << "\nHash of Source: " << strTempID
852  << "\n Source: " << pstrSourceToUse->Get() << "\n";
853  delete pMaster;
854  pMaster = nullptr;
855  return false;
856  }
857 
858  // OTFolders::Credential() is for private credentials (I've created.)
859  // OTFolders::Pubcred() is for public credentials (I've downloaded.)
860  // ...(FYI.)
861  //
862  if (OTDB::Exists(OTFolders::Credential().Get(), strNymID.Get(),
863  pMaster->GetMasterCredID().Get())) {
864  otErr << __FUNCTION__
865  << ": Failure: Apparently there is already a credential stored "
866  "for this ID (even though this is a new master credential, "
867  "just generated.)\n";
868  delete pMaster;
869  pMaster = nullptr;
870  return false;
871  }
872 
873  // It's already signed (inside CreateMaster) but it's still not added to the
874  // Nym,
875  // or saved to local storage. So let's do that next...
876  //
877  OTString strFoldername, strFilename;
878  strFoldername.Format("%s%s%s", OTFolders::Credential().Get(),
879  OTLog::PathSeparator(), strNymID.Get());
880  strFilename.Format("%s", pMaster->GetMasterCredID().Get());
881  const bool bSaved =
882  const_cast<OTMasterkey&>(pMaster->GetMasterkey())
883  .SaveContract(strFoldername.Get(), strFilename.Get());
884 
885  if (!bSaved) {
886  otErr << __FUNCTION__ << ": Failed trying to save new master "
887  "credential to local storage.\n";
888  delete pMaster;
889  pMaster = nullptr;
890  return false;
891  }
892 
893  m_mapCredentials.insert(std::pair<std::string, OTCredential*>(
894  pMaster->GetMasterCredID().Get(), pMaster));
895  strOutputMasterCredID = pMaster->GetMasterCredID();
896 
897  m_strSourceForNymID = *pstrSourceToUse; // This may be superfluous.
898  // (Or may just go inside the
899  // below block.)
900 
901  if (bChangeNymID) {
902  m_nymID.CalculateDigest(m_strSourceForNymID);
903  }
904  //
905  // Todo: someday we'll add "source" and "altLocation" to CreateNym
906  // (currently the public key is just assumed to be the source.)
907  // When that time comes, we'll need to set the altLocation here as
908  // well, since it will be optional whenever there is a source involved.
909 
911 
912  return true;
913 }
914 
916  const OTIdentifier& idMasterCredential,
917  int32_t nBits, // Ignored unless pmapPrivate is nullptr.
918  const OTString::Map* pmapPrivate, // If nullptr, then the keys are
919  // generated in here.
920  const OTPasswordData* pPWData, OTString* pstrNewID)
921 {
922  const OTString strMasterCredID(idMasterCredential);
923 
924  auto it = m_mapCredentials.find(strMasterCredID.Get());
925 
926  if (it == m_mapCredentials.end()) // Didn't find it.
927  {
928  otOut << __FUNCTION__ << ": Failed trying to add key credential to "
929  "nonexistent master credential.\n";
930  return false;
931  }
932 
933  OTCredential* pMaster = it->second;
934  OT_ASSERT(nullptr != pMaster);
935 
936  OTSubkey* pSubkey = nullptr;
937  const bool bAdded =
938  pMaster->AddNewSubkey(nBits, pmapPrivate, pPWData, &pSubkey);
939 
940  if (!bAdded) {
941  otOut
942  << __FUNCTION__
943  << ": Failed trying to add key credential to master credential.\n";
944  return false;
945  }
946  OT_ASSERT(nullptr != pSubkey);
947 
948  if (!pSubkey->VerifyInternally()) {
949 
950  otErr << "NYM::ADD_NEW_SUBKEY: 2.5 \n";
951 
952  otErr << __FUNCTION__
953  << ": Failed trying to verify the new key credential.\n";
954  // todo: remove it again, since it failed to verify.
955  return false;
956  }
957 
958  // It's already signed (inside AddNewSubkey) but it's still not added to the
959  // Nym,
960  // or saved to local storage. So let's do that next...
961  //
962  OTString strNymID, strSubkeyID;
963  GetIdentifier(strNymID);
964  pSubkey->GetIdentifier(strSubkeyID);
965 
966  // OTFolders::Credential() is for private credentials (I've created.)
967  // OTFolders::Pubcred() is for public credentials (I've downloaded.)
968  //
969  if (OTDB::Exists(OTFolders::Credential().Get(), strNymID.Get(),
970  strSubkeyID.Get())) {
971  otErr << __FUNCTION__
972  << ": Failure: Apparently there is already a credential stored "
973  "for this ID (even though this is a new credential, just "
974  "generated.)\n";
975  return false;
976  }
977 
978  OTString strFoldername, strFilename;
979  strFoldername.Format("%s%s%s", OTFolders::Credential().Get(),
980  OTLog::PathSeparator(), strNymID.Get());
981  strFilename.Format("%s", strSubkeyID.Get());
982  const bool bSaved =
983  pSubkey->SaveContract(strFoldername.Get(), strFilename.Get());
984  if (!bSaved) {
985  otErr
986  << __FUNCTION__
987  << ": Failed trying to save new key credential to local storage.\n";
988  return false;
989  }
990 
992 
993  if (nullptr != pstrNewID) *pstrNewID = strSubkeyID;
994 
995  return true;
996 }
997 
999  const OTIdentifier& idMasterCredential,
1000  const OTString::Map* pmapPrivate, // If nullptr, then the keys are
1001  // generated in here.
1002  const OTString::Map* pmapPublic, // In the case of key credentials,
1003  // public is optional since it can
1004  // already be derived from
1005  // private. For now we pass it
1006  // through... May eliminate this
1007  // parameter later if not needed.
1008  const OTPasswordData* pPWData)
1009 {
1010  const OTString strMasterCredID(idMasterCredential);
1011 
1012  auto it = m_mapCredentials.find(strMasterCredID.Get());
1013 
1014  if (it == m_mapCredentials.end()) // Didn't find it.
1015  {
1016  otOut << __FUNCTION__ << ": Failed trying to add subcredential to "
1017  "nonexistent master credential.\n";
1018  return false;
1019  }
1020 
1021  OTCredential* pMaster = it->second;
1022  OT_ASSERT(nullptr != pMaster);
1023 
1024  OTSubcredential* pSubcredential = nullptr;
1025  const bool bAdded = pMaster->AddNewSubcredential(*pmapPrivate, *pmapPublic,
1026  pPWData, &pSubcredential);
1027 
1028  if (!bAdded) {
1029  otOut << __FUNCTION__
1030  << ": Failed trying to add subcredential to master credential.\n";
1031  return false;
1032  }
1033  OT_ASSERT(nullptr != pSubcredential);
1034 
1035  if (!pSubcredential->VerifyInternally()) {
1036  otErr << __FUNCTION__
1037  << ": Failed trying to verify the new subcredential.\n";
1038  // todo: remove it again, since it failed to verify.
1039  return false;
1040  }
1041 
1042  // It's already signed (inside AddNewSubcredential) but it's still not added
1043  // to the Nym,
1044  // or saved to local storage. So let's do that next...
1045  //
1046  OTString strNymID, strSubcredentialID;
1047  GetIdentifier(strNymID);
1048  pSubcredential->GetIdentifier(strSubcredentialID);
1049 
1050  if (OTDB::Exists(OTFolders::Credential().Get(), strNymID.Get(),
1051  strSubcredentialID.Get())) {
1052  otErr << __FUNCTION__
1053  << ": Failure: Apparently there is already a credential stored "
1054  "for this ID (even though this is a new credential, just "
1055  "generated.)\n";
1056  return false;
1057  }
1058 
1059  OTString strFoldername, strFilename;
1060  strFoldername.Format("%s%s%s", OTFolders::Credential().Get(),
1061  OTLog::PathSeparator(), strNymID.Get());
1062  strFilename.Format("%s", strSubcredentialID.Get());
1063  const bool bSaved =
1064  pSubcredential->SaveContract(strFoldername.Get(), strFilename.Get());
1065  if (!bSaved) {
1066  otErr
1067  << __FUNCTION__
1068  << ": Failed trying to save new subcredential to local storage.\n";
1069  return false;
1070  }
1071 
1073 
1074  return true;
1075 }
1076 
1081 void OTPseudonym::AddMail(OTMessage& theMessage) // a mail message is a form of
1082  // transaction, transported via
1083  // Nymbox
1084 {
1085  m_dequeMail.push_front(&theMessage);
1086 }
1087 
1090 {
1091  return static_cast<int32_t>(m_dequeMail.size());
1092 }
1093 
1094 // Look up a piece of mail by index.
1095 // If it is, return a pointer to it, otherwise return nullptr.
1097 {
1098  const uint32_t uIndex = nIndex;
1099 
1100  // Out of bounds.
1101  if (m_dequeMail.empty() || (nIndex < 0) || (uIndex >= m_dequeMail.size()))
1102  return nullptr;
1103 
1104  return m_dequeMail.at(nIndex);
1105 }
1106 
1107 bool OTPseudonym::RemoveMailByIndex(int32_t nIndex) // if false, mail
1108  // index was bad.
1109 {
1110  const uint32_t uIndex = nIndex;
1111 
1112  // Out of bounds.
1113  if (m_dequeMail.empty() || (nIndex < 0) || (uIndex >= m_dequeMail.size()))
1114  return false;
1115 
1116  OTMessage* pMessage = m_dequeMail.at(nIndex);
1117 
1118  OT_ASSERT(nullptr != pMessage);
1119 
1120  m_dequeMail.erase(m_dequeMail.begin() + nIndex);
1121 
1122  delete pMessage;
1123 
1124  return true;
1125 }
1126 
1128 {
1129  while (GetMailCount() > 0) RemoveMailByIndex(0);
1130 }
1131 
1136 void OTPseudonym::AddOutmail(OTMessage& theMessage) // a mail message is a form
1137  // of transaction,
1138  // transported via Nymbox
1139 {
1140  m_dequeOutmail.push_front(&theMessage);
1141 }
1142 
1145 {
1146  return static_cast<int32_t>(m_dequeOutmail.size());
1147 }
1148 
1149 // Look up a transaction by transaction number and see if it is in the ledger.
1150 // If it is, return a pointer to it, otherwise return nullptr.
1152 {
1153  const uint32_t uIndex = nIndex;
1154 
1155  // Out of bounds.
1156  if (m_dequeOutmail.empty() || (nIndex < 0) ||
1157  (uIndex >= m_dequeOutmail.size()))
1158  return nullptr;
1159 
1160  return m_dequeOutmail.at(nIndex);
1161 }
1162 
1163 bool OTPseudonym::RemoveOutmailByIndex(int32_t nIndex) // if false,
1164  // outmail index
1165  // was bad.
1166 {
1167  const uint32_t uIndex = nIndex;
1168 
1169  // Out of bounds.
1170  if (m_dequeOutmail.empty() || (nIndex < 0) ||
1171  (uIndex >= m_dequeOutmail.size()))
1172  return false;
1173 
1174  OTMessage* pMessage = m_dequeOutmail.at(nIndex);
1175 
1176  OT_ASSERT(nullptr != pMessage);
1177 
1178  m_dequeOutmail.erase(m_dequeOutmail.begin() + nIndex);
1179 
1180  delete pMessage;
1181 
1182  return true;
1183 }
1184 
1186 {
1187  while (GetOutmailCount() > 0) RemoveOutmailByIndex(0);
1188 }
1189 
1194 void OTPseudonym::AddOutpayments(OTMessage& theMessage) // a payments message is
1195  // a form of
1196  // transaction,
1197  // transported via
1198  // Nymbox
1199 {
1200  m_dequeOutpayments.push_front(&theMessage);
1201 }
1202 
1205 {
1206  return static_cast<int32_t>(m_dequeOutpayments.size());
1207 }
1208 
1209 // Look up a transaction by transaction number and see if it is in the ledger.
1210 // If it is, return a pointer to it, otherwise return nullptr.
1212 {
1213  const uint32_t uIndex = nIndex;
1214 
1215  // Out of bounds.
1216  if (m_dequeOutpayments.empty() || (nIndex < 0) ||
1217  (uIndex >= m_dequeOutpayments.size()))
1218  return nullptr;
1219 
1220  return m_dequeOutpayments.at(nIndex);
1221 }
1222 
1223 // if this function returns false, outpayments index was bad.
1224 bool OTPseudonym::RemoveOutpaymentsByIndex(int32_t nIndex, bool bDeleteIt)
1225 {
1226  const uint32_t uIndex = nIndex;
1227 
1228  // Out of bounds.
1229  if (m_dequeOutpayments.empty() || (nIndex < 0) ||
1230  (uIndex >= m_dequeOutpayments.size())) {
1231  otErr << __FUNCTION__
1232  << ": Error: Index out of bounds: signed: " << nIndex
1233  << " unsigned: " << uIndex << " (size is "
1234  << m_dequeOutpayments.size() << ").\n";
1235  return false;
1236  }
1237 
1238  OTMessage* pMessage = m_dequeOutpayments.at(nIndex);
1239  OT_ASSERT(nullptr != pMessage);
1240 
1241  m_dequeOutpayments.erase(m_dequeOutpayments.begin() + uIndex);
1242 
1243  if (bDeleteIt) delete pMessage;
1244 
1245  return true;
1246 }
1247 
1249 {
1251 }
1252 
1253 // Instead of a "balance statement", some messages require a "transaction
1254 // statement".
1255 // Whenever the number of transactions changes, you must sign the new list so
1256 // you
1257 // aren't responsible for cleared transactions, for example. Or so you server
1258 // will
1259 // allow you to take responsibility for a new transaction number (only if you've
1260 // signed off on it!)
1261 //
1262 // There will have to be another version of this function for when you don't
1263 // have
1264 // a transaction (like a processNymbox!) Otherwise you would need a transaction
1265 // number
1266 // in order to do a processNymbox. This function therefore is available in that
1267 // incarnation
1268 // even when you don't have a transaction number. It'll just attach the balance
1269 // item to
1270 // the message directly.
1271 //
1273 {
1274  if ((theOwner.GetUserID() != m_nymID)) {
1275  otErr << "OTPseudonym::" << __FUNCTION__
1276  << ": Transaction has wrong owner (expected to match nym).\n";
1277  return nullptr;
1278  }
1279 
1280  // theOwner is the depositPaymentPlan, activateSmartContract, or marketOffer
1281  // that triggered the need for this transaction statement.
1282  // since it uses up a transaction number, I will be sure to remove that one
1283  // from my list before signing the list.
1284  OTItem* pBalanceItem = OTItem::CreateItemFromTransaction(
1285  theOwner, OTItem::transactionStatement); // <=== transactionStatement
1286  // type, with user ID, server
1287  // ID, transaction ID.
1288 
1289  // The above has an ASSERT, so this this will never actually happen.
1290  if (nullptr == pBalanceItem) return nullptr;
1291 
1292  // COPY THE ISSUED TRANSACTION NUMBERS FROM THE NYM
1293 
1294  OTPseudonym theMessageNym;
1295 
1296  theMessageNym.HarvestIssuedNumbers(
1297  theOwner.GetPurportedServerID(),
1298  *this /*unused in this case, not saving to disk*/, *this,
1299  false); // bSave = false;
1300 
1301  switch (theOwner.GetType()) {
1303  if (theOwner.GetTransactionNum() > 0) {
1304  theMessageNym.RemoveIssuedNum(
1305  theOwner.GetRealServerID(),
1306  theOwner.GetTransactionNum()); // a transaction number is being
1307  // used, and REMOVED from my list
1308  // of responsibility,
1309  theMessageNym.RemoveTransactionNum(
1310  theOwner.GetRealServerID(),
1311  theOwner.GetTransactionNum()); // so I want the new signed list
1312  // to reflect that number has
1313  // been REMOVED.
1314  }
1315  break;
1316 
1317  // Transaction Statements usually only have a transaction number in the case
1318  // of market offers and
1319  // payment plans, in which case the number should NOT be removed, and
1320  // remains in play until
1321  // final closure from Cron.
1325  default:
1326  break;
1327  }
1328 
1329  // What about cases where no number is being used? (Such as processNymbox)
1330  // Perhaps then if this function is even called, it's with a 0-number
1331  // transaction, in which
1332  // case the above Removes probably won't hurt anything. Todo.
1333 
1334  OTString strMessageNym(theMessageNym); // Okay now we have the transaction
1335  // numbers in this MessageNym string.
1336 
1337  pBalanceItem->SetAttachment(strMessageNym); // <======== This is where the
1338  // server will read the
1339  // transaction numbers from (A
1340  // nym in item.m_ascAttachment)
1341 
1342  pBalanceItem->SignContract(*this); // <=== Sign, save, and return.
1343  // OTTransactionType needs to weasel in a
1344  // "date signed" variable.
1345  pBalanceItem->SaveContract();
1346 
1347  return pBalanceItem;
1348 }
1349 
1351  const OTString* pstrReason)
1352 {
1353  return m_pkeypair->SaveCertAndPrivateKeyToString(strOutput, pstrReason);
1354 }
1355 
1357  const OTString* pstrReason)
1358 {
1359 
1360  OTString strOutput;
1361  const bool bSuccess =
1362  m_pkeypair->SaveAndReloadBothKeysFromTempFile(&strOutput, pstrReason);
1363 
1364  //
1365  // At this point, the Nym's private key is set, and its public key is also
1366  // set.
1367  // So the object in memory is good to go.
1368  // Now we just need to create some files, especially where the keys are
1369  // stored,
1370  // since the Nym normally never writes to those files (just reads.)
1371  //
1372  if (bSuccess) {
1373 
1374  // NYM ID based on SOURCE
1375  //
1376  if (m_strSourceForNymID.Exists())
1377  m_nymID.CalculateDigest(m_strSourceForNymID);
1378 
1379  // (or) NYM ID based on PUBLIC SIGNING KEY
1380  //
1381  else if (!SetIdentifierByPubkey()) {
1382  otErr << __FUNCTION__ << ": Error calculating Nym ID (as a digest "
1383  "of Nym's public (signing) key.)\n";
1384  return false;
1385  }
1386 
1387  // If we set the ID based on the public key (above block),
1388  // then we should set the source to contain that public key.
1389  else {
1390  OTString strTempSource;
1391  m_pkeypair->GetPublicKey(strTempSource); // bEscaped=true by default
1392 
1393  SetNymIDSource(strTempSource);
1394  }
1395 
1396  const OTString strFilenameByID(m_nymID); // FILENAME based on NYM ID
1397 
1398  if (bCreateFile &&
1399  (false ==
1400  OTDB::StorePlainString(strOutput.Get(), OTFolders::Cert().Get(),
1401  strFilenameByID.Get()))) // Store as actual
1402  // Nym ID this time
1403  // instead of
1404  // temp.nym
1405  {
1406  otErr << __FUNCTION__
1407  << ": Failure storing cert for new nym: " << strFilenameByID
1408  << "\n";
1409  return false;
1410  }
1411  }
1412 
1413  return bSuccess;
1414 }
1415 
1416 // use this to actually generate a new key pair and assorted nym files.
1417 //
1418 bool OTPseudonym::GenerateNym(int32_t nBits, bool bCreateFile, // By default, it
1419  // creates the various
1420  // nym files
1421  // and certs in local storage. (Pass false when
1422  // creating a temp Nym, like for OTPurse.)
1423  std::string str_id_source,
1424  std::string str_alt_location)
1425 {
1426 
1427  OT_ASSERT(nullptr != m_pkeypair);
1428 
1429  if (m_pkeypair->MakeNewKeypair(nBits)) {
1430  OTString strSource(str_id_source), strAltLocation(str_alt_location);
1431 
1432  SetNymIDSource(strSource);
1433  SetAltLocation(strAltLocation);
1434 
1435  OTString strReason("Creating new Nym."); // NOTE:
1436  // Savex509CertAndPrivateKey
1437  // sets the ID and sometimes if
1438  // necessary, the source.
1439  bool bSaved = Savex509CertAndPrivateKey(
1440  bCreateFile,
1441  &strReason); // Todo: remove this. Credentials code will supercede.
1442 
1443  if (bSaved && bCreateFile) {
1444  bSaved = SaveSignedNymfile(*this); // Now we'll generate the
1445  // NymFile as well!
1446  // (bCreateFile will be
1447  // false for temp Nyms..)
1448  }
1449 
1450  if (bCreateFile && !bSaved)
1451  otErr << __FUNCTION__
1452  << ": Failed trying to save new Nym's cert or nymfile.\n";
1453  else {
1454  // NEW CREDENTIALS CODE!
1455  // We've added a parameter to this function so you can pass in the
1456  // SOURCE for
1457  // the Nym (which is what is hashed to produce the NymID.) The
1458  // source could be a Bitcoin
1459  // address, a URL, the Subject/Issuer DN info from a
1460  // traditionally-issued certificate authority,
1461  // or a public key. (OT originally was written to hash a public key
1462  // to form the NymID -- so we
1463  // will just continue to support that as an option.)
1464  //
1465  // If the SOURCE parameter is not passed, we will assume by default
1466  // that the Nym has an existing one,
1467  // or uses its own public key as its source. This will become the
1468  // first master credential, which can
1469  // then be used to issue keyCredentials and other types of
1470  // subCredentials.
1471  //
1472  // UPDATE: Huh? I STILL need to be able to pass in a source, and
1473  // STILL have it generate the key,
1474  // so I can't have it ONLY pass in the source when there's no key --
1475  // because sometimes I want to
1476  // pass the source and ALSO use the key that was generated. (Just,
1477  // in that case, we want it to
1478  // use the hash of that source as the NymID, instead of the hash of
1479  // the public key.)
1480  // (I will update AddNewMasterCredential so it allows that.)
1481  //
1482  OTString strMasterCredID;
1483 
1484  const bool bAddedMaster = AddNewMasterCredential(
1485  strMasterCredID,
1486  (str_id_source.size() > 0) ? &strSource : nullptr, nBits);
1487 
1488  if (bAddedMaster && strMasterCredID.Exists() &&
1489  (GetMasterCredentialCount() > 0)) {
1490  const OTIdentifier theMasterCredID(strMasterCredID);
1491  const bool bAddedSubkey = AddNewSubkey(theMasterCredID);
1492 
1493  if (bAddedSubkey) {
1494  bSaved = SaveCredentialList();
1495  }
1496  else {
1497  bSaved = false;
1498  otErr << __FUNCTION__ << ": Failed trying to add new "
1499  "keyCredential to new Master "
1500  "credential.\n";
1501  }
1502  }
1503  else {
1504  bSaved = false;
1505  otErr << __FUNCTION__ << ": Failed trying to add new master "
1506  "credential to new Nym.\n";
1507  }
1508  }
1509 
1510  return bSaved;
1511  }
1512 
1513  return false;
1514 }
1515 
1517 {
1518  OT_ASSERT(nullptr != m_pkeypair);
1519 
1520  const bool bCalculated = m_pkeypair->CalculateID(
1521  m_nymID); // OTAsymmetricKey::CalculateID only works with public keys.
1522 
1523  if (!bCalculated) {
1524  otErr << __FUNCTION__ << ": Error calculating Nym ID in "
1525  "OTAsymmetricKey::CalculateID().\n";
1526  return false;
1527  }
1528 
1529  return true;
1530 }
1531 
1532 // If an ID is passed in, that means remove all numbers FOR THAT SERVER ID.
1533 // If passed in, and current map doesn't match, then skip it (continue).
1534 
1535 #ifndef CLEAR_MAP_AND_DEQUE
1536 #define CLEAR_MAP_AND_DEQUE(the_map) \
1537  for (auto& it : the_map) { \
1538  if ((nullptr != pstrServerID) && (str_ServerID != it.first)) continue; \
1539  dequeOfTransNums* pDeque = (it.second); \
1540  OT_ASSERT(nullptr != pDeque); \
1541  if (!(pDeque->empty())) pDeque->clear(); \
1542  }
1543 #endif // CLEAR_MAP_AND_DEQUE
1544 
1545 // Sometimes for testing I need to clear out all the transaction numbers from a
1546 // nym.
1547 // So I added this method to make such a thing easy to do.
1548 //
1549 void OTPseudonym::RemoveAllNumbers(const OTString* pstrServerID,
1550  bool bRemoveHighestNum) // Some callers
1551  // don't want
1552  // to wipe
1553 // the highest num. Some do.
1554 {
1555  std::string str_ServerID(pstrServerID ? pstrServerID->Get() : "");
1556 
1557  // These use str_ServerID (above)
1558  //
1559  CLEAR_MAP_AND_DEQUE(m_mapIssuedNum)
1560  CLEAR_MAP_AND_DEQUE(m_mapTransNum)
1561  CLEAR_MAP_AND_DEQUE(m_mapTentativeNum)
1562  CLEAR_MAP_AND_DEQUE(m_mapAcknowledgedNum)
1563 
1564  std::list<mapOfHighestNums::iterator> listOfHighestNums;
1565  std::list<mapOfIdentifiers::iterator> listOfNymboxHash;
1566  std::list<mapOfIdentifiers::iterator> listOfInboxHash;
1567  std::list<mapOfIdentifiers::iterator> listOfOutboxHash;
1568  std::list<mapOfIdentifiers::iterator> listOfRecentHash;
1569 
1570  if (bRemoveHighestNum) {
1571  for (auto it(m_mapHighTransNo.begin()); it != m_mapHighTransNo.end();
1572  ++it) {
1573  if ((nullptr != pstrServerID) &&
1574  (str_ServerID != it->first)) // If passed in, and current it
1575  // doesn't match, then skip it
1576  // (continue).
1577  continue;
1578 
1579  listOfHighestNums.push_back(it);
1580  }
1581  }
1582 
1583  for (auto it(m_mapNymboxHash.begin()); it != m_mapNymboxHash.end(); ++it) {
1584  if ((nullptr != pstrServerID) &&
1585  (str_ServerID != it->first)) // If passed in, and current it doesn't
1586  // match, then skip it (continue).
1587  continue;
1588 
1589  listOfNymboxHash.push_back(it);
1590  }
1591 
1592  // This is mapped to acct_id, not server_id.
1593  // (So we just wipe them all.)
1594  for (auto it(m_mapInboxHash.begin()); it != m_mapInboxHash.end(); ++it) {
1595  listOfInboxHash.push_back(it);
1596  }
1597 
1598  // This is mapped to acct_id, not server_id.
1599  // (So we just wipe them all.)
1600  for (auto it(m_mapOutboxHash.begin()); it != m_mapOutboxHash.end(); ++it) {
1601  listOfOutboxHash.push_back(it);
1602  }
1603 
1604  for (auto it(m_mapRecentHash.begin()); it != m_mapRecentHash.end(); ++it) {
1605  if ((nullptr != pstrServerID) &&
1606  (str_ServerID != it->first)) // If passed in, and current it doesn't
1607  // match, then skip it (continue).
1608  continue;
1609 
1610  listOfRecentHash.push_back(it);
1611  }
1612 
1613  while (!listOfHighestNums.empty()) {
1614  m_mapHighTransNo.erase(listOfHighestNums.back());
1615  listOfHighestNums.pop_back();
1616  }
1617  while (!listOfNymboxHash.empty()) {
1618  m_mapNymboxHash.erase(listOfNymboxHash.back());
1619  listOfNymboxHash.pop_back();
1620  }
1621  while (!listOfInboxHash.empty()) {
1622  m_mapInboxHash.erase(listOfInboxHash.back());
1623  listOfInboxHash.pop_back();
1624  }
1625  while (!listOfOutboxHash.empty()) {
1626  m_mapOutboxHash.erase(listOfOutboxHash.back());
1627  listOfOutboxHash.pop_back();
1628  }
1629  while (!listOfRecentHash.empty()) {
1630  m_mapRecentHash.erase(listOfRecentHash.back());
1631  listOfRecentHash.pop_back();
1632  }
1633 }
1634 
1635 // OTIdentifier m_NymboxHash; // (Server-side) Hash of the
1636 // Nymbox
1637 // mapOfIdentifiers m_mapNymboxHash; // (Client-side) Hash of Nymbox
1638 // (OTIdentifier) mapped by ServerID (std::string)
1639 
1641  const OTIdentifier& theServerID, OTIdentifier& theOutput) // server-side
1642 {
1643  if (m_NymboxHash.IsEmpty()) {
1644  OTLedger theNymbox(m_nymID, m_nymID, theServerID);
1645 
1646  if (theNymbox.LoadNymbox() && theNymbox.CalculateNymboxHash(theOutput))
1647  return true;
1648  }
1649 
1650  return false;
1651 }
1652 
1654  const OTIdentifier& theInput) // server-side
1655 {
1656  m_NymboxHash = theInput;
1657 }
1658 
1659 bool OTPseudonym::GetNymboxHash(const std::string& server_id,
1660  OTIdentifier& theOutput) const // client-side
1661 {
1662  return GetHash(m_mapNymboxHash, server_id, theOutput);
1663 }
1664 
1665 bool OTPseudonym::SetNymboxHash(const std::string& server_id,
1666  const OTIdentifier& theInput) // client-side
1667 {
1668  return SetHash(m_mapNymboxHash, server_id, theInput);
1669 }
1670 
1671 bool OTPseudonym::GetRecentHash(const std::string& server_id,
1672  OTIdentifier& theOutput) const // client-side
1673 {
1674  return GetHash(m_mapRecentHash, server_id, theOutput);
1675 }
1676 
1677 bool OTPseudonym::SetRecentHash(const std::string& server_id,
1678  const OTIdentifier& theInput) // client-side
1679 {
1680  return SetHash(m_mapRecentHash, server_id, theInput);
1681 }
1682 
1683 bool OTPseudonym::GetInboxHash(const std::string& acct_id,
1684  OTIdentifier& theOutput) const // client-side
1685 {
1686  return GetHash(m_mapInboxHash, acct_id, theOutput);
1687 }
1688 
1689 bool OTPseudonym::SetInboxHash(const std::string& acct_id,
1690  const OTIdentifier& theInput) // client-side
1691 {
1692  return SetHash(m_mapInboxHash, acct_id, theInput);
1693 }
1694 
1695 bool OTPseudonym::GetOutboxHash(const std::string& acct_id,
1696  OTIdentifier& theOutput) const // client-side
1697 {
1698  return GetHash(m_mapOutboxHash, acct_id, theOutput);
1699 }
1700 
1701 bool OTPseudonym::SetOutboxHash(const std::string& acct_id,
1702  const OTIdentifier& theInput) // client-side
1703 {
1704  return SetHash(m_mapOutboxHash, acct_id, theInput);
1705 }
1706 
1707 bool OTPseudonym::GetHash(const mapOfIdentifiers& the_map,
1708  const std::string& str_id,
1709  OTIdentifier& theOutput) const // client-side
1710 {
1711  bool bRetVal =
1712  false; // default is false: "No, I didn't find a hash for that id."
1713  theOutput.Release();
1714 
1715  // The Pseudonym has a map of its recent hashes, one for each server
1716  // (nymbox) or account (inbox/outbox).
1717  // For Server Bob, with this Pseudonym, I might have hash lkjsd987345lkj.
1718  // For but Server Alice, I might have hash 98345jkherkjghdf98gy.
1719  // (Same Nym, but different hash for each server, as well as inbox/outbox
1720  // hashes for each asset acct.)
1721  //
1722  // So let's loop through all the hashes I have, and if the ID on the map
1723  // passed in
1724  // matches the [server|acct] ID that was passed in, then return TRUE.
1725  //
1726  for (const auto& it : the_map) {
1727  if (str_id == it.first) {
1728  // The call has succeeded
1729  bRetVal = true;
1730  theOutput = it.second;
1731  break;
1732  }
1733  }
1734 
1735  return bRetVal;
1736 }
1737 
1738 bool OTPseudonym::SetHash(mapOfIdentifiers& the_map, const std::string& str_id,
1739  const OTIdentifier& theInput) // client-side
1740 {
1741  bool bSuccess = false;
1742 
1743  auto find_it = the_map.find(str_id);
1744 
1745  if (the_map.end() != find_it) // found something for that str_id
1746  {
1747  // The call has succeeded
1748  the_map.erase(find_it);
1749  the_map[str_id] = theInput;
1750  bSuccess = true;
1751  }
1752 
1753  // If I didn't find it in the list above (whether the list is empty or
1754  // not....)
1755  // that means it does not exist. (So create it.)
1756  //
1757  if (!bSuccess) {
1758  the_map[str_id] = theInput;
1759  bSuccess = true;
1760  }
1761  // if (bSuccess)
1762  // {
1763  // SaveSignedNymfile(SIGNER_NYM);
1764  // }
1765 
1766  return bSuccess;
1767 }
1768 
1769 void OTPseudonym::RemoveReqNumbers(const OTString* pstrServerID)
1770 {
1771  const std::string str_ServerID(pstrServerID ? pstrServerID->Get() : "");
1772 
1773  for (auto it(m_mapRequestNum.begin()); it != m_mapRequestNum.end(); ++it) {
1774  if ((nullptr != pstrServerID) &&
1775  (str_ServerID != it->first)) // If passed in, and current it doesn't
1776  // match, then skip it (continue).
1777  continue;
1778 
1779  m_mapRequestNum.erase(it);
1780  }
1781 }
1782 
1783 // You can't go using a Nym at a certain server, if it's not registered there...
1784 // BTW -- if you have never called GetRequest(), then this will wrongly return
1785 // false!
1786 // But as long as you call getRequest() upon successsful registration (or
1787 // whenever) this
1788 // function will return an accurate answer after that point, and forever.
1789 //
1790 bool OTPseudonym::IsRegisteredAtServer(const OTString& strServerID) const
1791 {
1792  bool bRetVal = false; // default is return false: "No, I'm NOT registered at
1793  // that Server."
1794  std::string strID = strServerID.Get();
1795 
1796  // The Pseudonym has a map of the request numbers for different servers.
1797  // For Server Bob, with this Pseudonym, I might be on number 34.
1798  // For but Server Alice, I might be on number 59.
1799  //
1800  // So let's loop through all the numbers I have, and if the server ID on the
1801  // map
1802  // matches the Server ID that was passed in, then return TRUE.
1803  for (auto& it : m_mapRequestNum) {
1804  if (strID == it.first) {
1805  // The call has succeeded
1806  bRetVal = true;
1807 
1808  break;
1809  }
1810  }
1811 
1812  return bRetVal;
1813 }
1814 
1815 // Removes Request Num for specific server
1816 // (Like if Nym has deleted his account on that server...)
1817 // Caller is responsible to save Nym after this.
1818 //
1820 {
1821  bool bRetVal = false; // default is return false: "No, I'm NOT registered at
1822  // that Server."
1823  std::string strID = strServerID.Get();
1824 
1825  // The Pseudonym has a map of the request numbers for different servers.
1826  // For Server Bob, with this Pseudonym, I might be on number 34.
1827  // For but Server Alice, I might be on number 59.
1828  //
1829  // So let's loop through all the numbers I have, and if the server ID on the
1830  // map
1831  // matches the Server ID that was passed in, then delete that one.
1832  //
1833  for (auto it(m_mapRequestNum.begin()); it != m_mapRequestNum.end(); ++it) {
1834  if (strID == it->first) {
1835  // The call has succeeded
1836  bRetVal = true;
1837  m_mapRequestNum.erase(it);
1838  break;
1839  }
1840  }
1841 
1842  return bRetVal;
1843 }
1844 
1845 #ifndef WIPE_MAP_AND_DEQUE
1846 #define WIPE_MAP_AND_DEQUE(the_map) \
1847  while (!the_map.empty()) { \
1848  dequeOfTransNums* pDeque = the_map.begin()->second; \
1849  OT_ASSERT(nullptr != pDeque); \
1850  the_map.erase(the_map.begin()); \
1851  delete pDeque; \
1852  pDeque = nullptr; \
1853  }
1854 #endif // WIPE_MAP_AND_DEQUE
1855 
1857 {
1858  WIPE_MAP_AND_DEQUE(m_mapTransNum)
1859  WIPE_MAP_AND_DEQUE(m_mapIssuedNum)
1860  WIPE_MAP_AND_DEQUE(m_mapTentativeNum)
1861  WIPE_MAP_AND_DEQUE(m_mapAcknowledgedNum)
1862 }
1863 
1864 /*
1865  ResyncWithServer:
1866 
1867 -- OTIdentifier m_NymboxHash; // (Server-side) Hash of the
1868 Nymbox
1869 
1870 -- mapOfIdentifiers m_mapNymboxHash; // (Client-side) Hash of latest
1871 DOWNLOADED Nymbox (OTIdentifier) mapped by ServerID (std::string)
1872 -- mapOfIdentifiers m_mapRecentHash; // (Client-side) Hash of Nymbox
1873 according to Server, based on some recent reply. (May be newer...)
1874 
1875 -- mapOfIdentifiers m_mapInboxHash;
1876 -- mapOfIdentifiers m_mapOutboxHash;
1877 
1878 -- dequeOfMail m_dequeMail; // Any mail messages received by this
1879 Nym. (And not yet deleted.)
1880 -- dequeOfMail m_dequeOutmail; // Any mail messages sent by this
1881 Nym. (And not yet deleted.)
1882 -- dequeOfMail m_dequeOutpayments; // Any outoing payments sent by
1883 this Nym. (And not yet deleted.) (payments screen.)
1884 
1885 -- mapOfRequestNums m_mapRequestNum; // Whenever this user makes a request
1886 to a transaction server
1887 
1888 ** mapOfTransNums m_mapTransNum; // Each Transaction Request must be
1889 accompanied by a fresh transaction #,
1890 ** mapOfTransNums m_mapIssuedNum; // If the server has issued me
1891 (1,2,3,4,5) and I have already used 1-3,
1892 ** mapOfTransNums m_mapTentativeNum;
1893 
1894 ** mapOfHighestNums m_mapHighTransNo; // Mapped, a single int64_t to each
1895 server (just like request numbers are.)
1896 
1897 -- mapOfTransNums m_mapAcknowledgedNum; // request numbers are stored
1898 here.
1899 
1900  // (SERVER side)
1901 -- std::set<int64_t> m_setOpenCronItems; // Until these Cron Items are closed
1902 out, the server-side Nym keeps a list of them handy.
1903 
1904  // (SERVER side)
1905  // Using strings here to avoid juggling memory crap.
1906 -- std::set<std::string> m_setAccounts; // A list of asset account IDs.
1907 Server side only (client side uses wallet; has multiple servers.)
1908 
1909  // (SERVER side.)
1910 -- int64_t m_lUsageCredits; // Server-side. The usage credits available
1911 for this Nym. Infinite if negative.
1912 
1913  */
1914 
1915 /*
1916  OTPseudonym::RemoveAllNumbers affects (**): (-- means doesn't affect)
1917 
1918 -- OTIdentifier m_NymboxHash; // (Server-side) Hash of the
1919 Nymbox
1920 
1921 ** mapOfIdentifiers m_mapNymboxHash; // (Client-side) Hash of latest
1922 DOWNLOADED Nymbox (OTIdentifier) mapped by ServerID (std::string)
1923 ** mapOfIdentifiers m_mapRecentHash; // (Client-side) Hash of Nymbox
1924 according to Server, based on some recent reply. (May be newer...)
1925 
1926 ** mapOfIdentifiers m_mapInboxHash;
1927 ** mapOfIdentifiers m_mapOutboxHash;
1928 
1929 -- dequeOfMail m_dequeMail; // Any mail messages received by this
1930 Nym. (And not yet deleted.)
1931 -- dequeOfMail m_dequeOutmail; // Any mail messages sent by this
1932 Nym. (And not yet deleted.)
1933 -- dequeOfMail m_dequeOutpayments; // Any outoing payments sent by
1934 this Nym. (And not yet deleted.) (payments screen.)
1935 
1936 -- mapOfRequestNums m_mapRequestNum;
1937 
1938 ** mapOfTransNums m_mapTransNum;
1939 ** mapOfTransNums m_mapIssuedNum;
1940 ** mapOfTransNums m_mapTentativeNum;
1941 
1942 ** mapOfHighestNums m_mapHighTransNo; // Mapped, a single int64_t to each
1943 server (just like request numbers are.)
1944 
1945 ** mapOfTransNums m_mapAcknowledgedNum; // request nums are stored.
1946 
1947  // (SERVER side)
1948 -- std::set<int64_t> m_setOpenCronItems; // Until these Cron Items are closed
1949 out, the server-side Nym keeps a list of them handy.
1950 
1951  // (SERVER side)
1952 -- std::set<std::string> m_setAccounts; // A list of asset account IDs.
1953 Server side only (client side uses wallet; has multiple servers.)
1954 
1955  // (SERVER side.)
1956 -- int64_t m_lUsageCredits; // Server-side. The usage credits available
1957 for this Nym. Infinite if negative.
1958 
1959 
1960 
1961  CLEAR_MAP_AND_DEQUE(m_mapIssuedNum)
1962  CLEAR_MAP_AND_DEQUE(m_mapTransNum)
1963  CLEAR_MAP_AND_DEQUE(m_mapTentativeNum)
1964  CLEAR_MAP_AND_DEQUE(m_mapAcknowledgedNum)
1965 
1966  m_mapHighTransNo.erase(listOfHighestNums.back());
1967  m_mapNymboxHash.erase(listOfNymboxHash.back());
1968  m_mapRecentHash.erase(listOfRecentHash.back());
1969 
1970 */
1971 
1972 // ** ResyncWithServer **
1973 //
1974 // Not for normal use! (Since you should never get out of sync with the server
1975 // in the first place.)
1976 // However, in testing, or if some bug messes up some data, or whatever, and you
1977 // absolutely need to
1978 // re-sync with a server, and you trust that server not to lie to you, then this
1979 // function will do the trick.
1980 // NOTE: Before calling this, you need to do a getNymbox() to download the
1981 // latest Nymbox, and you need to do
1982 // a createUserAccount() to download the server's copy of your Nym. You then
1983 // need to load that Nymbox from
1984 // local storage, and you need to load the server's message Nym out of the
1985 // @createUserAccount reply, so that
1986 // you can pass both of those objects into this function, which must assume that
1987 // those pieces were already done
1988 // just prior to this call.
1989 //
1991  const OTPseudonym& theMessageNym)
1992 {
1993  bool bSuccess = true;
1994 
1995  const OTIdentifier& theServerID = theNymbox.GetRealServerID();
1996  const OTString strServerID(theServerID);
1997  const OTString strNymID(m_nymID);
1998 
1999  const int32_t nIssuedNumCount =
2000  theMessageNym.GetIssuedNumCount(theServerID);
2001  const int32_t nTransNumCount =
2002  theMessageNym.GetTransactionNumCount(theServerID);
2003 
2004  // Remove all issued, transaction, and tentative numbers for a specific
2005  // server ID,
2006  // as well as all acknowledgedNums, and the highest transaction number for
2007  // that serverID,
2008  // from *this nym. Leave our record of the highest trans num received from
2009  // that server,
2010  // since we will want to just keep it when re-syncing. (Server doesn't store
2011  // that anyway.)
2012  //
2013  RemoveAllNumbers(&strServerID, false); // bRemoveHighestNum=true by
2014  // default. But in this case, I
2015  // keep it.
2016 
2017  // Any issued or trans numbers we add to *this from theMessageNym, are also
2018  // added here so
2019  // they can be used to update the "highest number" record (at the bottom of
2020  // this function.)
2021  //
2022  std::set<int64_t> setTransNumbers;
2023 
2024  // Now that *this has no issued or transaction numbers for theServerID, we
2025  // add
2026  // them back again from theMessageNym. (So they will match, and be 'N
2027  // SYNC!!!)
2028  //
2029  // Copy the issued and transaction numbers from theMessageNym onto *this.
2030  //
2031  for (int32_t n1 = 0; n1 < nIssuedNumCount; ++n1) {
2032  const int64_t lNum = theMessageNym.GetIssuedNum(theServerID, n1);
2033 
2034  if (!AddIssuedNum(strServerID, lNum)) // Add to list of
2035  // numbers that
2036  // haven't been
2037  // closed yet.
2038  {
2039  otErr << "OTPseudonym::ResyncWithServer: Failed trying to add "
2040  "IssuedNum (" << lNum << ") onto *this nym: " << strNymID
2041  << ", for server: " << strServerID << "\n";
2042  bSuccess = false;
2043  }
2044  else {
2045  setTransNumbers.insert(lNum);
2046 
2047  otWarn << "OTPseudonym::ResyncWithServer: Added IssuedNum (" << lNum
2048  << ") onto *this nym: " << strNymID
2049  << ", for server: " << strServerID << " \n";
2050  }
2051  }
2052 
2053  for (int32_t n2 = 0; n2 < nTransNumCount; ++n2) {
2054  const int64_t lNum = theMessageNym.GetTransactionNum(theServerID, n2);
2055 
2056  if (!AddTransactionNum(strServerID, lNum)) // Add to list of
2057  // available-to-use
2058  // numbers.
2059  {
2060  otErr << "OTPseudonym::ResyncWithServer: Failed trying to add "
2061  "TransactionNum (" << lNum
2062  << ") onto *this nym: " << strNymID
2063  << ", for server: " << strServerID << "\n";
2064  bSuccess = false;
2065  }
2066  else {
2067  setTransNumbers.insert(lNum);
2068 
2069  otWarn << "OTPseudonym::ResyncWithServer: Added TransactionNum ("
2070  << lNum << ") onto *this nym: " << strNymID
2071  << ", for server: " << strServerID << " \n";
2072  }
2073  }
2074 
2075  // We already cleared all tentative numbers from *this (above in
2076  // RemoveAllNumbers). Next, loop through theNymbox and add Tentative numbers
2077  // to *this based on each successNotice in the Nymbox. This way, when the
2078  // notices
2079  // are processed, they will succeed because the Nym will believe he was
2080  // expecting them.
2081  //
2082  for (auto& it : theNymbox.GetTransactionMap()) {
2083  OTTransaction* pTransaction = it.second;
2084  OT_ASSERT(nullptr != pTransaction);
2085  // OTString strTransaction(*pTransaction);
2086  // otErr << "TRANSACTION CONTENTS:\n%s\n", strTransaction.Get());
2087 
2088  // (a new; ALREADY just added transaction number.)
2090  pTransaction->GetType())) // if !successNotice
2091  continue;
2092 
2093  const int64_t lNum =
2094  pTransaction->GetReferenceToNum(); // successNotice is inRefTo the
2095  // new transaction # that should
2096  // be on my tentative list.
2097 
2098  if (!AddTentativeNum(strServerID, lNum)) // Add to list of
2099  // tentatively-being-added
2100  // numbers.
2101  {
2102  otErr << "OTPseudonym::ResyncWithServer: Failed trying to add "
2103  "TentativeNum (" << lNum
2104  << ") onto *this nym: " << strNymID
2105  << ", for server: " << strServerID << "\n";
2106  bSuccess = false;
2107  }
2108  else
2109  otWarn << "OTPseudonym::ResyncWithServer: Added TentativeNum ("
2110  << lNum << ") onto *this nym: " << strNymID
2111  << ", for server: " << strServerID << " \n";
2112  // There's no "else insert to setTransNumbers" here, like the other two
2113  // blocks above.
2114  // Why not? Because setTransNumbers is for updating the Highest Trans
2115  // Num record on this Nym,
2116  // and the Tentative Numbers aren't figured into that record until AFTER
2117  // they are accepted
2118  // from the Nymbox. So I leave them out, since this function is
2119  // basically setting us up to
2120  // successfully process the Nymbox, which will then naturally update the
2121  // highest num record
2122  // based on the tentatives, as it's removing them from the tentative
2123  // list and adding them to
2124  // the "available" transaction list (and issued.)
2125  }
2126 
2127  const std::string strID = strServerID.Get();
2128 
2129  for (auto& it_high_num : m_mapHighTransNo) {
2130  // We found it!
2131  if (strID == it_high_num.first) {
2132  // See if any numbers on the set are higher, and if so, update the
2133  // record to match.
2134  //
2135  for (auto& it : setTransNumbers) {
2136  const int64_t lTransNum = it;
2137 
2138  // Grab a copy of the old highest trans number
2139  const int64_t lOldHighestNumber = it_high_num.second;
2140 
2141  if (lTransNum > lOldHighestNumber) // Did we find a bigger one?
2142  {
2143  // Then update the Nym's record!
2144  m_mapHighTransNo[it_high_num.first] = lTransNum;
2145  otWarn
2146  << "OTPseudonym::ResyncWithServer: Updated HighestNum ("
2147  << lTransNum << ") record on *this nym: " << strNymID
2148  << ", for server: " << strServerID << " \n";
2149  }
2150  }
2151 
2152  // We only needed to do this for the one server, so we can break
2153  // now.
2154  break;
2155  }
2156  }
2157 
2158  return (SaveSignedNymfile(*this) && bSuccess);
2159 }
2160 
2161 /*
2162 typedef std::deque<int64_t> dequeOfTransNums;
2163 typedef std::map<std::string, dequeOfTransNums *> mapOfTransNums;
2164 */
2165 
2166 // Verify whether a certain transaction number appears on a certain list.
2167 //
2169  const OTString& strServerID,
2170  const int64_t& lTransNum) const
2171 {
2172  std::string strID = strServerID.Get();
2173 
2174  // The Pseudonym has a deque of transaction numbers for each servers.
2175  // These deques are mapped by Server ID.
2176  //
2177  // So let's loop through all the deques I have, and if the server ID on the
2178  // map
2179  // matches the Server ID that was passed in, then find the transaction
2180  // number on
2181  // that list, and then return true. Else return false.
2182  //
2183  for (auto& it : THE_MAP) {
2184  // if the ServerID passed in matches the serverID for the current deque
2185  if (strID == it.first) {
2186  dequeOfTransNums* pDeque = (it.second);
2187  OT_ASSERT(nullptr != pDeque);
2188 
2189  if (!(pDeque->empty())) // there are some numbers for that server ID
2190  {
2191  // Let's loop through them and see if the culprit is there
2192  for (uint32_t i = 0; i < pDeque->size(); i++) {
2193  // Found it!
2194  if (lTransNum == pDeque->at(i)) {
2195  return true;
2196  }
2197  }
2198  }
2199  break;
2200  }
2201  }
2202 
2203  return false;
2204 }
2205 
2206 // On the server side: A user has submitted a specific transaction number.
2207 // Remove it from his file so he can't use it again.
2209  OTPseudonym& SIGNER_NYM,
2210  const OTString& strServerID,
2211  const int64_t& lTransNum)
2212 {
2213  bool bRetVal = RemoveGenericNum(THE_MAP, strServerID, lTransNum);
2214 
2215  if (bRetVal) {
2216  SaveSignedNymfile(SIGNER_NYM);
2217  }
2218 
2219  return bRetVal;
2220 }
2221 
2222 // This function is a little lower level, and doesn't worry about saving. Used
2223 // internally.
2224 // Returns true IF it successfully finds and removes the number. Otherwise
2225 // returns false.
2226 //
2228  const OTString& strServerID,
2229  const int64_t& lTransNum)
2230 {
2231  bool bRetVal = false;
2232  std::string strID = strServerID.Get();
2233 
2234  // The Pseudonym has a deque of transaction numbers for each servers.
2235  // These deques are mapped by Server ID.
2236  //
2237  // So let's loop through all the deques I have, and if the server ID on the
2238  // map
2239  // matches the Server ID that was passed in, then find the transaction
2240  // number on
2241  // that list, and then remove it, and return true. Else return false.
2242  //
2243  for (auto& it : THE_MAP) {
2244  // if the ServerID passed in matches the serverID for the current deque
2245  if (strID == it.first) {
2246  dequeOfTransNums* pDeque = (it.second);
2247 
2248  OT_ASSERT(nullptr != pDeque);
2249 
2250  if (!(pDeque->empty())) // there are some numbers for that server ID
2251  {
2252  // Let's loop through them and see if the culprit is there
2253  for (uint32_t i = 0; i < pDeque->size(); i++) {
2254  // Found it!
2255  if (lTransNum == pDeque->at(i)) {
2256  pDeque->erase(pDeque->begin() + i);
2257  bRetVal = true;
2258  break;
2259  }
2260  }
2261  }
2262  break;
2263  }
2264  }
2265 
2266  return bRetVal;
2267 }
2268 
2269 // No signer needed for this one, and save is false.
2270 // This version is ONLY for cases where we're not saving inside this function.
2272  const OTString& strServerID, int64_t lTransNum)
2273 {
2274  bool bSuccessFindingServerID = false, bSuccess = false;
2275  std::string strID = strServerID.Get();
2276 
2277  // The Pseudonym has a deque of transaction numbers for each server.
2278  // These deques are mapped by Server ID.
2279  //
2280  // So let's loop through all the deques I have, and if the server ID on the
2281  // map
2282  // matches the Server ID that was passed in, then add the transaction
2283  // number.
2284  //
2285  for (auto& it : THE_MAP) {
2286  // if the ServerID passed in matches the serverID for the current deque
2287  if (strID == it.first) {
2288  dequeOfTransNums* pDeque = (it.second);
2289  OT_ASSERT(nullptr != pDeque);
2290 
2291  auto iter = std::find(pDeque->begin(), pDeque->end(), lTransNum);
2292 
2293  if (iter == pDeque->end()) // Only add it if it's not already there.
2294  // No duplicates!
2295  pDeque->push_front(lTransNum);
2296 
2297  bSuccess = true;
2298  bSuccessFindingServerID = true;
2299 
2300  break;
2301  }
2302  }
2303 
2304  // Apparently there is not yet a deque stored for this specific serverID.
2305  // Fine. Let's create it then, and then add the transaction num to that new
2306  // deque.
2307  if (!bSuccessFindingServerID) {
2308  dequeOfTransNums* pDeque = new dequeOfTransNums;
2309 
2310  OT_ASSERT(nullptr != pDeque);
2311 
2312  THE_MAP[strID] = pDeque;
2313  pDeque->push_front(lTransNum);
2314  bSuccess = true;
2315  }
2316 
2317  return bSuccess;
2318 }
2319 
2320 // Returns count of transaction numbers available for a given server.
2321 //
2323  const OTIdentifier& theServerID) const
2324 {
2325  int32_t nReturnValue = 0;
2326 
2327  const OTString strServerID(theServerID);
2328  std::string strID = strServerID.Get();
2329 
2330  dequeOfTransNums* pDeque = nullptr;
2331 
2332  // The Pseudonym has a deque of transaction numbers for each server.
2333  // These deques are mapped by Server ID.
2334  //
2335  // So let's loop through all the deques I have, and if the server ID on the
2336  // map
2337  // matches the Server ID that was passed in, then we found the right server.
2338  for (auto& it : THE_MAP) {
2339  // if the ServerID passed in matches the serverID for the current deque
2340  if (strID == it.first) {
2341  pDeque = (it.second);
2342  OT_ASSERT(nullptr != pDeque);
2343 
2344  break;
2345  }
2346  }
2347 
2348  // We found the right server, so let's count the transaction numbers
2349  // that this nym has already stored for it.
2350  if (nullptr != pDeque) {
2351  nReturnValue = static_cast<int32_t>(pDeque->size());
2352  }
2353 
2354  return nReturnValue;
2355 }
2356 
2357 // by index.
2359  const OTIdentifier& theServerID,
2360  int32_t nIndex) const
2361 {
2362  int64_t lRetVal = 0;
2363 
2364  const OTString strServerID(theServerID);
2365  std::string strID = strServerID.Get();
2366 
2367  // The Pseudonym has a deque of numbers for each server.
2368  // These deques are mapped by Server ID.
2369  //
2370  // So let's loop through all the deques I have, and if the server ID on the
2371  // maps matches the Server ID that was passed in, then find the number on
2372  // that list, and then return it.
2373  //
2374  for (auto& it : THE_MAP) {
2375  // if the ServerID passed in matches the serverID for the current deque
2376  if (strID == it.first) {
2377  dequeOfTransNums* pDeque = (it.second);
2378  OT_ASSERT(nullptr != pDeque);
2379 
2380  if (!(pDeque->empty())) // there are some numbers for that server ID
2381  {
2382  // Let's loop through them and see if the culprit is there
2383  for (uint32_t i = 0; i < pDeque->size(); i++) {
2384  // Found it!
2385  if ((uint32_t)nIndex == i) {
2386  lRetVal = pDeque->at(i); // <==== Got the number here.
2387  break;
2388  }
2389  }
2390  }
2391  break;
2392  }
2393  }
2394 
2395  return lRetVal;
2396 }
2397 
2398 // by index.
2399 int64_t OTPseudonym::GetTentativeNum(const OTIdentifier& theServerID,
2400  int32_t nIndex) const
2401 {
2402  return GetGenericNum(m_mapTentativeNum, theServerID, nIndex);
2403 }
2404 
2405 // by index.
2406 int64_t OTPseudonym::GetIssuedNum(const OTIdentifier& theServerID,
2407  int32_t nIndex) const
2408 {
2409  return GetGenericNum(m_mapIssuedNum, theServerID, nIndex);
2410 }
2411 
2412 // by index.
2414  int32_t nIndex) const
2415 {
2416  return GetGenericNum(m_mapTransNum, theServerID, nIndex);
2417 }
2418 
2419 // by index.
2421  int32_t nIndex) const
2422 {
2423  return GetGenericNum(m_mapAcknowledgedNum, theServerID, nIndex);
2424 }
2425 
2426 // TRANSACTION NUM
2427 
2428 // On the server side: A user has submitted a specific transaction number.
2429 // Verify whether he actually has a right to use it.
2431  const OTString& strServerID, const int64_t& lTransNum) const // doesn't save
2432 {
2433  return VerifyGenericNum(m_mapTransNum, strServerID, lTransNum);
2434 }
2435 
2436 // On the server side: A user has submitted a specific transaction number.
2437 // Remove it from his file so he can't use it again.
2439  const OTString& strServerID,
2440  const int64_t& lTransNum) // saves
2441 {
2442  return RemoveGenericNum(m_mapTransNum, SIGNER_NYM, strServerID, lTransNum);
2443 }
2444 
2446  const int64_t& lTransNum) // doesn't
2447  // save.
2448 {
2449  return RemoveGenericNum(m_mapTransNum, strServerID, lTransNum);
2450 }
2451 
2452 // Returns count of transaction numbers available for a given server.
2453 //
2455  const OTIdentifier& theServerID) const
2456 {
2457  return GetGenericNumCount(m_mapTransNum, theServerID);
2458 }
2459 
2460 // No signer needed for this one, and save is false.
2461 // This version is ONLY for cases where we're not saving inside this function.
2463  int64_t lTransNum) // doesn't save
2464 {
2465  return AddGenericNum(m_mapTransNum, strServerID, lTransNum);
2466 }
2467 
2468 // ISSUED NUM
2469 
2470 // On the server side: A user has submitted a specific transaction number.
2471 // Verify whether it was issued to him and still awaiting final closing.
2472 bool OTPseudonym::VerifyIssuedNum(const OTString& strServerID,
2473  const int64_t& lTransNum) const
2474 {
2475  return VerifyGenericNum(m_mapIssuedNum, strServerID, lTransNum);
2476 }
2477 
2478 // On the server side: A user has accepted a specific receipt.
2479 // Remove it from his file so he's not liable for it anymore.
2481  const OTString& strServerID,
2482  const int64_t& lTransNum) // saves
2483 {
2484  return RemoveGenericNum(m_mapIssuedNum, SIGNER_NYM, strServerID, lTransNum);
2485 }
2486 
2487 bool OTPseudonym::RemoveIssuedNum(const OTString& strServerID,
2488  const int64_t& lTransNum) // doesn't save
2489 {
2490  return RemoveGenericNum(m_mapIssuedNum, strServerID, lTransNum);
2491 }
2492 
2493 // Returns count of transaction numbers not yet cleared for a given server.
2494 //
2495 int32_t OTPseudonym::GetIssuedNumCount(const OTIdentifier& theServerID) const
2496 {
2497  return GetGenericNumCount(m_mapIssuedNum, theServerID);
2498 }
2499 
2500 // No signer needed for this one, and save is false.
2501 // This version is ONLY for cases where we're not saving inside this function.
2502 bool OTPseudonym::AddIssuedNum(const OTString& strServerID,
2503  const int64_t& lTransNum) // doesn't save.
2504 {
2505  return AddGenericNum(m_mapIssuedNum, strServerID, lTransNum);
2506 }
2507 
2508 // TENTATIVE NUM
2509 
2510 // On the server side: A user has submitted a specific transaction number.
2511 // Verify whether it was issued to him and still awaiting final closing.
2513  const int64_t& lTransNum) const
2514 {
2515  return VerifyGenericNum(m_mapTentativeNum, strServerID, lTransNum);
2516 }
2517 
2518 // On the server side: A user has accepted a specific receipt.
2519 // Remove it from his file so he's not liable for it anymore.
2521  const OTString& strServerID,
2522  const int64_t& lTransNum) // saves
2523 {
2524  return RemoveGenericNum(m_mapTentativeNum, SIGNER_NYM, strServerID,
2525  lTransNum);
2526 }
2527 
2529  const int64_t& lTransNum) // doesn't save
2530 {
2531  return RemoveGenericNum(m_mapTentativeNum, strServerID, lTransNum);
2532 }
2533 
2534 // Returns count of transaction numbers not yet cleared for a given server.
2535 //
2536 int32_t OTPseudonym::GetTentativeNumCount(const OTIdentifier& theServerID) const
2537 {
2538  return GetGenericNumCount(m_mapTentativeNum, theServerID);
2539 }
2540 
2541 // No signer needed for this one, and save is false.
2542 // This version is ONLY for cases where we're not saving inside this function.
2543 bool OTPseudonym::AddTentativeNum(const OTString& strServerID,
2544  const int64_t& lTransNum) // doesn't save.
2545 {
2546  return AddGenericNum(m_mapTentativeNum, strServerID, lTransNum);
2547 }
2548 
2549 // ACKNOWLEDGED NUM
2550 
2551 // These are actually used for request numbers, so both sides can determine
2552 // which
2553 // replies are already acknowledged. Used purely for optimization, to avoid
2554 // downloading
2555 // a large number of box receipts (specifically the replyNotices.)
2556 
2557 // Client side: See if I've already seen the server's reply to a certain request
2558 // num.
2559 // Server side: See if I've already seen the client's acknowledgment of a reply
2560 // I sent.
2561 //
2563  const int64_t& lRequestNum) const
2564 {
2565  return VerifyGenericNum(m_mapAcknowledgedNum, strServerID, lRequestNum);
2566 }
2567 
2568 // On client side: server acknowledgment has been spotted in a reply message, so
2569 // I can remove it from my ack list.
2570 // On server side: client has removed acknowledgment from his list (as evident
2571 // since its sent with client messages), so server can remove it as well.
2572 //
2574  const OTString& strServerID,
2575  const int64_t& lRequestNum) // saves
2576 {
2577  return RemoveGenericNum(m_mapAcknowledgedNum, SIGNER_NYM, strServerID,
2578  lRequestNum);
2579 }
2580 
2582  const int64_t& lRequestNum) // doesn't
2583  // save
2584 {
2585  return RemoveGenericNum(m_mapAcknowledgedNum, strServerID, lRequestNum);
2586 }
2587 
2588 // Returns count of request numbers that the client has already seen the reply
2589 // to
2590 // (Or in the case of server-side, the list of request numbers that the client
2591 // has
2592 // told me he has already seen the reply to.)
2593 //
2595  const OTIdentifier& theServerID) const
2596 {
2597  return GetGenericNumCount(m_mapAcknowledgedNum, theServerID);
2598 }
2599 
2600 #ifndef OT_MAX_ACK_NUMS
2601 #define OT_MAX_ACK_NUMS 100
2602 #endif
2603 
2604 // No signer needed for this one, and save is false.
2605 // This version is ONLY for cases where we're not saving inside this function.
2607  const int64_t& lRequestNum) // doesn't
2608  // save.
2609 {
2610  // We're going to call AddGenericNum, but first, let's enforce a cap on the
2611  // total
2612  // number of ackNums allowed...
2613  //
2614  std::string strID = strServerID.Get();
2615 
2616  // The Pseudonym has a deque of transaction numbers for each server.
2617  // These deques are mapped by Server ID.
2618  //
2619  // So let's loop through all the deques I have, and if the server ID on the
2620  // map
2621  // matches the Server ID that was passed in, then we'll pop the size of the
2622  // deque
2623  // down to our max size (off the back) before then calling AddGenericNum
2624  // which will
2625  // push the new request number onto the front.
2626  //
2627  for (auto& it : m_mapAcknowledgedNum) {
2628  // if the ServerID passed in matches the serverID for the current deque
2629  if (strID == it.first) {
2630  dequeOfTransNums* pDeque = (it.second);
2631  OT_ASSERT(nullptr != pDeque);
2632 
2633  while (pDeque->size() > OT_MAX_ACK_NUMS) {
2634  pDeque->pop_back(); // This fixes knotwork's issue where he had
2635  // thousands of ack nums somehow never
2636  // getting cleared out. Now we have a MAX
2637  // and always keep it clean otherwise.
2638  }
2639  break;
2640  }
2641  }
2642 
2643  return AddGenericNum(m_mapAcknowledgedNum, strServerID,
2644  lRequestNum); // <=== Here we finally add the new
2645  // request number, the actual purpose of
2646  // this function.
2647 }
2648 
2649 // HIGHER LEVEL...
2650 
2651 // Client side: We have received a new trans num from server. Store it.
2652 // Now the server uses this too, for storing these numbers so it can verify them
2653 // later.
2654 //
2656  OTPseudonym& SIGNER_NYM, const OTString& strServerID, int64_t lTransNum,
2657  bool bSave) // SAVE OR NOT (your choice) High-Level.
2658 {
2659  bool bSuccess1 = AddTransactionNum(
2660  strServerID,
2661  lTransNum); // Add to list of available-to-use, outstanding numbers.
2662  bool bSuccess2 =
2663  AddIssuedNum(strServerID, lTransNum); // Add to list of numbers that
2664  // haven't been closed yet.
2665 
2666  if (bSuccess1 && !bSuccess2)
2667  RemoveGenericNum(m_mapTransNum, strServerID, lTransNum);
2668  else if (bSuccess2 && !bSuccess1)
2669  RemoveGenericNum(m_mapIssuedNum, strServerID, lTransNum);
2670 
2671  if (bSuccess1 && bSuccess2 && bSave)
2672  bSave = SaveSignedNymfile(SIGNER_NYM);
2673  else
2674  bSave = true; // so the return at the bottom calculates correctly.
2675 
2676  return (bSuccess1 && bSuccess2 && bSave);
2677 }
2678 
2679 // Client side: We have received a server's successful reply to a processNymbox
2680 // accepting a specific new transaction number(s).
2681 // Or, if the reply was lost, then we still found out later that the acceptance
2682 // was successful, since a notice is still dropped
2683 // into the Nymbox. Either way, this function removes the Tentative number,
2684 // right before calling the above AddTransactionNum()
2685 // in order to make it available for the Nym's use on actual transactions.
2686 //
2688  const OTString& strServerID,
2689  const int64_t& lTransNum,
2690  bool bSave) // SAVE OR NOT (your choice)
2691  // High-Level.
2692 {
2693  bool bSuccess = RemoveTentativeNum(
2694  strServerID, lTransNum); // Remove from list of numbers that haven't
2695  // been made available for use yet, though
2696  // they're "tentative"...
2697 
2698  if (bSuccess && bSave)
2699  bSave = SaveSignedNymfile(SIGNER_NYM);
2700  else
2701  bSave = true; // so the return at the bottom calculates correctly.
2702 
2703  return (bSuccess && bSave);
2704 }
2705 
2706 // Client side: We have accepted a certain receipt. Remove the transaction
2707 // number from my list of issued numbers.
2708 // The server uses this too, also for keeping track of issued numbers, and
2709 // removes them around same time as client.
2710 // (When receipt is accepted.) Also, There is no "RemoveTransactionNum" at this
2711 // level since GetNextTransactionNum handles that.
2712 //
2714  const OTString& strServerID,
2715  const int64_t& lTransNum,
2716  bool bSave) // SAVE OR NOT (your choice)
2717  // High-Level.
2718 {
2719  bool bSuccess =
2720  RemoveIssuedNum(strServerID, lTransNum); // Remove from list of numbers
2721  // that are still signed out.
2722 
2723  if (bSuccess && bSave)
2724  bSave = SaveSignedNymfile(SIGNER_NYM);
2725  else
2726  bSave = true; // so the return at the bottom calculates correctly.
2727 
2728  return (bSuccess && bSave);
2729 }
2730 
2731 // Client keeps track of server replies it's already seen.
2732 // Server keeps track of these client acknowledgments.
2733 // (Server also removes from Nymbox, any acknowledged message
2734 // that wasn't already on his list based on request num.)
2735 // Server already removes from his list, any number the client
2736 // has removed from his.
2737 // This is all purely for optimization, since it allows us to avoid
2738 // downloading all the box receipts that contain replyNotices.
2739 //
2741  const OTString& strServerID,
2742  const int64_t& lRequestNum,
2743  bool bSave) // SAVE OR NOT (your choice)
2744  // High-Level.
2745 {
2746  bool bSuccess = RemoveAcknowledgedNum(
2747  strServerID,
2748  lRequestNum); // Remove from list of acknowledged request numbers.
2749 
2750  if (bSuccess && bSave)
2751  bSave = SaveSignedNymfile(SIGNER_NYM);
2752  else
2753  bSave = true; // so the return at the bottom calculates correctly.
2754 
2755  return (bSuccess && bSave);
2756 }
2757 
2766  OTPseudonym& SIGNER_NYM,
2767  OTPseudonym& theOtherNym,
2768  bool bSave)
2769 {
2770  int64_t lTransactionNumber = 0;
2771 
2772  std::set<int64_t> setInput, setOutputGood, setOutputBad;
2773 
2774  for (auto& it : theOtherNym.GetMapIssuedNum()) {
2775  std::string strServerID = it.first;
2776  dequeOfTransNums* pDeque = it.second;
2777 
2778  OT_ASSERT(nullptr != pDeque);
2779 
2780  OTString OTstrServerID = strServerID.c_str();
2781  const OTIdentifier theTempID(OTstrServerID);
2782 
2783  if (!(pDeque->empty()) &&
2784  (theServerID == theTempID)) // only for the matching serverID.
2785  {
2786  for (uint32_t i = 0; i < pDeque->size(); i++) {
2787  lTransactionNumber = pDeque->at(i);
2788 
2789  // If number wasn't already on issued list, then add to BOTH
2790  // lists.
2791  // Otherwise do nothing (it's already on the issued list, and no
2792  // longer
2793  // valid on the available list--thus shouldn't be re-added there
2794  // anyway.)
2795  //
2796  if ((true == VerifyTentativeNum(
2797  OTstrServerID,
2798  lTransactionNumber)) && // If I've actually
2799  // requested this
2800  // number and waiting
2801  // on it...
2802  (false ==
2803  VerifyIssuedNum(OTstrServerID,
2804  lTransactionNumber)) // and if it's not
2805  // already on my
2806  // issued list...
2807  )
2808  setInput.insert(lTransactionNumber);
2809  }
2810  break; // We found it! Might as well break out.
2811  }
2812  } // for
2813 
2814  // Looks like we found some numbers to harvest
2815  // (tentative numbers we had already been waiting for,
2816  // yet hadn't processed onto our issued list yet...)
2817  //
2818  if (!setInput.empty()) {
2819  const OTString strServerID(theServerID), strNymID(m_nymID);
2820 
2821  int64_t lViolator = UpdateHighestNum(
2822  SIGNER_NYM, strServerID, setInput, setOutputGood,
2823  setOutputBad); // bSave=false (saved below already, if necessary)
2824 
2825  // NOTE: Due to the possibility that a server reply could be processed
2826  // twice (due to redundancy
2827  // for the purposes of preventing syncing issues) then we expect we
2828  // might get numbers in here
2829  // that are below our "last highest num" (due to processing the same
2830  // numbers twice.) Therefore
2831  // we don't need to assume an error in this case. UpdateHighestNum() is
2832  // already smart enough to
2833  // only update based on the good numbers, while ignoring the bad (i.e.
2834  // already-processed) ones.
2835  // Thus we really only have a problem if we receive a (-1), which would
2836  // mean an error occurred.
2837  // Also, the above call will log an FYI that it is skipping any numbers
2838  // below the line, so no need
2839  // to log more in the case of lViolater being >0 but less than the 'last
2840  // highest number.'
2841  //
2842  if ((-1) == lViolator)
2843  otErr << "OTPseudonym::HarvestTransactionNumbers"
2844  << ": ERROR: UpdateHighestNum() returned (-1), "
2845  "which is an error condition. "
2846  "(Should never happen.)\nNym ID: " << strNymID << " \n";
2847  else {
2848  // We only remove-tentative-num/add-transaction-num for the numbers
2849  // that were above our 'last highest number'.
2850  // The contents of setOutputBad are thus ignored for these purposes.
2851  //
2852  for (auto& it : setOutputGood) {
2853  const int64_t lNoticeNum = it;
2854 
2855  // We already know it's on the TentativeNum list, since we
2856  // checked that in the above for loop.
2857  // We also already know that it's not on the issued list, since
2858  // we checked that as well.
2859  // That's why the below calls just ASSUME those things already.
2860  //
2862  strServerID, lNoticeNum); // doesn't save (but saved below)
2863  AddTransactionNum(SIGNER_NYM, strServerID, lNoticeNum,
2864  false); // bSave = false (but saved below...)
2865  }
2866 
2867  // We save regardless of whether any removals or additions are made,
2868  // because data was
2869  // updated in UpdateHighestNum regardless.
2870  //
2871  if (bSave) SaveSignedNymfile(SIGNER_NYM);
2872  }
2873  }
2874 }
2875 
2876 // OtherNym is used as container for us to send server list of issued
2877 // transaction numbers.
2878 // NOTE: in more recent times, a class has been added for managing lists of
2879 // numbers. But
2880 // we didn't have that back when this was written.
2881 //
2882 // The above function is good for accepting new numbers onto my list, numbers
2883 // that I already
2884 // tried to sign for and are thus waiting in my tentative list. When calling
2885 // that function,
2886 // I am trying to accept those new numbers (the ones I was expecting already),
2887 // and NO other
2888 // numbers.
2889 //
2890 // Whereas with the below function, I am adding as "available" all the numbers
2891 // that I didn't
2892 // already have issued to me, REGARDLESS of tentative status. Why would I do
2893 // this? Well,
2894 // perhaps a temp nym is being used during some calculations, and I want to copy
2895 // all the numbers
2896 // over to the temp nym, period, regardless of his tentative list, because he
2897 // has no tentative
2898 // list, because he's not a nym in the first place.
2899 //
2901  OTPseudonym& SIGNER_NYM,
2902  OTPseudonym& theOtherNym, bool bSave)
2903 {
2904  bool bChangedTheNym = false;
2905  int64_t lTransactionNumber = 0;
2906 
2907  for (auto& it : theOtherNym.GetMapIssuedNum()) {
2908  std::string strServerID = it.first;
2909  dequeOfTransNums* pDeque = it.second;
2910 
2911  OT_ASSERT(nullptr != pDeque);
2912 
2913  OTString OTstrServerID =
2914  ((strServerID.size()) > 0 ? strServerID.c_str() : "");
2915  const OTIdentifier theTempID(OTstrServerID);
2916 
2917  if (!(pDeque->empty()) && (theServerID == theTempID)) {
2918  for (uint32_t i = 0; i < pDeque->size(); i++) {
2919  lTransactionNumber = pDeque->at(i);
2920 
2921  // If number wasn't already on issued list, then add to BOTH
2922  // lists.
2923  // Otherwise do nothing (it's already on the issued list, and no
2924  // longer
2925  // valid on the available list--thus shouldn't be re-added there
2926  // anyway.)
2927  //
2928  if (false ==
2929  VerifyIssuedNum(OTstrServerID, lTransactionNumber)) {
2931  SIGNER_NYM, OTstrServerID, lTransactionNumber,
2932  false); // bSave = false (but saved below...)
2933  bChangedTheNym = true;
2934  }
2935  }
2936  break; // We found it! Might as well break out.
2937  }
2938  } // for
2939 
2940  if (bChangedTheNym && bSave) {
2941  SaveSignedNymfile(SIGNER_NYM);
2942  }
2943 }
2944 
2952  const OTIdentifier& theServerID,
2953  const int64_t& lTransClawback, // the number being clawed back.
2954  bool bSave, // false because you might call this function 10
2955  // times in a loop, and not want to save EVERY
2956  // iteration.
2957  OTPseudonym* pSIGNER_NYM)
2958 {
2959  if (nullptr == pSIGNER_NYM) pSIGNER_NYM = this;
2960  // Below this point, pSIGNER_NYM is definitely a good pointer.
2961 
2962  const OTString strServerID(theServerID);
2963 
2964  // Only re-add the transaction number if it's already on my issued list.
2965  // (Otherwise, why am I "adding it back again" if I never had it in the
2966  // first place? Doesn't sound like a real clawback situation in that case.)
2967  //
2968  if (true == VerifyIssuedNum(strServerID, lTransClawback)) {
2969  AddTransactionNum(*pSIGNER_NYM, strServerID, lTransClawback, bSave);
2970  return true;
2971  }
2972 
2973  return false;
2974 }
2975 
2981  const OTString& strServerID,
2982  int64_t& lTransNum, bool bSave)
2983 {
2984  bool bRetVal = false;
2985  std::string strID = strServerID.Get();
2986 
2987  // The Pseudonym has a deque of transaction numbers for each server.
2988  // These deques are mapped by Server ID.
2989  //
2990  // So let's loop through all the deques I have, and if the server ID on the
2991  // map
2992  // matches the Server ID that was passed in, then send out the transaction
2993  // number.
2994  //
2995  for (auto& it : m_mapTransNum) {
2996  // if the ServerID passed in matches the serverID for the current deque
2997  if (strID == it.first) {
2998  dequeOfTransNums* pDeque = (it.second);
2999  OT_ASSERT(nullptr != pDeque);
3000 
3001  if (!(pDeque->empty())) {
3002  lTransNum = pDeque->front();
3003 
3004  pDeque->pop_front();
3005 
3006  // The call has succeeded
3007  bRetVal = true;
3008  }
3009  break;
3010  }
3011  }
3012 
3013  if (bRetVal && bSave) {
3014  if (!SaveSignedNymfile(SIGNER_NYM))
3015  otErr << "Error saving signed NymFile in "
3016  "OTPseudonym::GetNextTransactionNum\n";
3017  }
3018 
3019  return bRetVal;
3020 }
3021 
3022 // returns true on success, value goes into lReqNum
3023 // Make sure the Nym is LOADED before you call this,
3024 // otherwise it won't be there to get.
3025 //
3026 bool OTPseudonym::GetHighestNum(const OTString& strServerID,
3027  int64_t& lHighestNum) const
3028 {
3029  bool bRetVal = false;
3030  std::string strID = strServerID.Get();
3031 
3032  // The Pseudonym has a map of the highest transaction # it's received from
3033  // different servers.
3034  // For Server Bob, with this Pseudonym, I might be on number 34.
3035  // For but Server Alice, I might be on number 59.
3036  //
3037  // So let's loop through all the numbers I have, and if the server ID on the
3038  // map
3039  // matches the Server ID that was passed in, then send out the highest
3040  // number.
3041  //
3042  // Since the transaction number only ever gets bigger, this is a way of
3043  // preventing
3044  // the server from EVER tricking us by trying to give us a number that we've
3045  // already seen before.
3046  //
3047  for (auto& it : m_mapHighTransNo) {
3048  if (strID == it.first) {
3049  // Setup return value.
3050  lHighestNum = (it.second);
3051 
3052  // The call has succeeded
3053  bRetVal = true;
3054 
3055  break;
3056  }
3057  }
3058 
3059  return bRetVal;
3060 }
3061 
3062 // Go through setNumbers and make sure none of them is lower than the highest
3063 // number I already have for this
3064 // server. At the same time, keep a record of the largest one in the set. If
3065 // successful, that becomes the new
3066 // "highest" number I've ever received that server. Otherwise fail.
3067 // If success, returns 0. If failure, returns the number that caused us to fail
3068 // (by being lower than the last
3069 // highest number.) I should NEVER receive a new transaction number that is
3070 // lower than any I've gotten before.
3071 // They should always only get bigger. UPDATE: Unless I happen to be processing
3072 // an old receipt twice... (which
3073 // can happen, due to redundancy used for preventing syncing issues, such as
3074 // Nymbox notices.)
3075 //
3077  const OTString& strServerID,
3078  std::set<int64_t>& setNumbers,
3079  std::set<int64_t>& setOutputGood,
3080  std::set<int64_t>& setOutputBad,
3081  bool bSave)
3082 {
3083  bool bFoundServerID = false;
3084  int64_t lReturnVal = 0; // 0 is success.
3085 
3086  // First find the highest and lowest numbers out of the new set.
3087  //
3088  int64_t lHighestInSet = 0;
3089  int64_t lLowestInSet = 0;
3090 
3091  for (auto& it : setNumbers) {
3092  const int64_t lSetNum = it;
3093 
3094  if (lSetNum > lHighestInSet)
3095  lHighestInSet = lSetNum; // Set lHighestInSet to contain the highest
3096  // number out of setNumbers (input)
3097 
3098  if (0 == lLowestInSet)
3099  lLowestInSet = lSetNum; // If lLowestInSet is still 0, then set it
3100  // to the current number (happens first
3101  // iteration.)
3102  else if (lSetNum < lLowestInSet)
3103  lLowestInSet = lSetNum; // If current number is less than
3104  // lLowestInSet, then set lLowestInSet to
3105  // current Number.
3106  }
3107 
3108  // By this point, lLowestInSet contains the lowest number in setNumbers,
3109  // and lHighestInSet contains the highest number in setNumbers.
3110 
3111  //
3112  // The Pseudonym has a map of the "highest transaction numbers" for
3113  // different servers.
3114  // For Server Bob, with this Pseudonym, I might be on number 34.
3115  // For but Server Alice, I might be on number 59.
3116  //
3117  // So let's loop through all the numbers I have, and if the server ID on the
3118  // map
3119  // matches the Server ID that was passed in, then update it there (then
3120  // break.)
3121  //
3122  // Make sure to save the Pseudonym afterwards, so the new numbers are saved.
3123 
3124  std::string strID = strServerID.Get();
3125 
3126  for (auto& it : m_mapHighTransNo) {
3127  // We found the serverID key on the map?
3128  // We now know the highest trans number for that server?
3129  //
3130  if (strID == it.first) // Iterates inside this block zero times or one
3131  // time. (One if it finds it, zero if not.)
3132  {
3133  // We found it!
3134  // Presumably we ONLY found it because this Nym has been properly
3135  // loaded first.
3136  // Good job! Otherwise, the list would have been empty even though
3137  // the highest number
3138  // was sitting in the file.
3139 
3140  // Grab a copy of the old highest trans number for this server.
3141  //
3142  const int64_t lOldHighestNumber =
3143  it.second; // <=========== The previous "highest number".
3144 
3145  // Loop through the numbers passed in, and for each, see if it's
3146  // less than
3147  // the previous "highest number for this server."
3148  //
3149  // If it's less, then we can't add it (must have added it
3150  // already...)
3151  // So we add it to the bad list.
3152  // But if it's more,
3153 
3154  for (auto& it_numbers : setNumbers) {
3155  const int64_t lSetNum = it_numbers;
3156 
3157  // If the current number (this iteration) is less than or equal
3158  // to the
3159  // "old highest number", then it's not going to be added twice.
3160  // (It goes on the "bad list.")
3161  //
3162  if (lSetNum <= lOldHighestNumber) {
3163  otWarn << "OTPseudonym::UpdateHighestNum: New transaction "
3164  "number is less-than-or-equal-to "
3165  "last known 'highest trans number' record. (Must "
3166  "be seeing the same server reply for "
3167  "a second time, due to a receipt in my Nymbox.) "
3168  "FYI, last known 'highest' number received: "
3169  << lOldHighestNumber
3170  << " (Current 'violator': " << lSetNum
3171  << ") Skipping...\n";
3172  setOutputBad.insert(lSetNum);
3173  }
3174 
3175  // The current number this iteration, as it should be, is HIGHER
3176  // than any transaction
3177  // number I've ever received before. (Although sometimes old
3178  // messages will 'echo'.)
3179  // I want to replace the "highest" record with this one
3180  else {
3181  setOutputGood.insert(lSetNum);
3182  }
3183  }
3184 
3185  // Here we're making sure that all the numbers in the set are larger
3186  // than any others
3187  // that we've had before for the same server (They should only ever
3188  // get larger.)
3189  //
3190  // if (lLowestInSet <= lOldHighestNumber) // ERROR!!! The
3191  // new numbers should ALWAYS be larger than the previous ones!
3192  if ((lLowestInSet > 0) &&
3193  (lLowestInSet <= lOldHighestNumber)) // WARNING! The new numbers
3194  // should ALWAYS be larger
3195  // than the previous ones!
3196  // UPDATE: Unless we happen to be processing the same receipt
3197  // for a second time, due to redundancy in the system (for
3198  // preventing syncing errors.)
3199  lReturnVal = lLowestInSet; // We return the violator (otherwise
3200  // 0 if success).
3201 
3202  // The loop has succeeded in finding the server ID and its
3203  // associated "highest number" value.
3204  //
3205  bFoundServerID = true;
3206  break;
3207  // This main for only ever has one active iteration: the one with
3208  // the right server ID. Once we find it, we break (no matter what.)
3209  } // server ID matches.
3210  }
3211 
3212  // If we found the server ID, that means the highest number was previously
3213  // recorded.
3214  // We don't want to replace it unless we were successful in this function.
3215  // And if we
3216  // were, then we want to replace it with the new "highest number in the
3217  // set."
3218  //
3219  // IF we found the server ID for a previously recorded highestNum, and
3220  // IF this function was a success in terms of the new numbers all exceeding
3221  // that old record,
3222  // THEN ERASE that old record and replace it with the new highest number.
3223  //
3224  // Hmm: Should I require ALL new numbers to be valid? Or should I take the
3225  // valid ones,
3226  // and ignore the invalid ones?
3227  //
3228  // Update: Just found this comment from the calling function:
3229  // NOTE: Due to the possibility that a server reply could be processed twice
3230  // (due to redundancy
3231  // for the purposes of preventing syncing issues) then we expect we might
3232  // get numbers in here
3233  // that are below our "last highest num" (due to processing the same numbers
3234  // twice.) Therefore
3235  // we don't need to assume an error in this case. UpdateHighestNum() is
3236  // already smart enough to
3237  // only update based on the good numbers, while ignoring the bad (i.e.
3238  // already-processed) ones.
3239  // Thus we really only have a problem if we receive a (-1), which would mean
3240  // an error occurred.
3241  // Also, the above call will log an FYI that it is skipping any numbers
3242  // below the line, so no need
3243  // to log more in the case of lViolater being >0 but less than the 'last
3244  // highest number.'
3245  //
3246  // ===> THEREFORE, we don't need an lReturnVal of 0 in order to update the
3247  // highest record.
3248  // Instead, we just need bFoundServerID to be true, and we need
3249  // setOutputGood to not be empty
3250  // (we already know the numbers in setOutputGood are higher than the last
3251  // highest recorded trans
3252  // num... that's why they are in setOutputGood instead of setOutputBad.)
3253  //
3254  if (!setOutputGood.empty()) // There's numbers worth savin'!
3255  {
3256  if (bFoundServerID) {
3257  otOut << "OTPseudonym::UpdateHighestNum: Raising Highest Trans "
3258  "Number from " << m_mapHighTransNo[strID] << " to "
3259  << lHighestInSet << ".\n";
3260 
3261  // We KNOW it's there, so we can straight-away just
3262  // erase it and insert it afresh..
3263  //
3264  m_mapHighTransNo.erase(strID);
3265  m_mapHighTransNo.insert(
3266  std::pair<std::string, int64_t>(strID, lHighestInSet));
3267  }
3268 
3269  // If I didn't find the server in the list above (whether the list is
3270  // empty or not....)
3271  // that means the record does not yet exist. (So let's create it)--we
3272  // wouldn't even be
3273  // here unless we found valid transaction numbers and added them to
3274  // setOutputGood.
3275  // (So let's record lHighestInSet mapped to strID, just as above.)
3276  else {
3277  otOut << "OTPseudonym::UpdateHighestNum: Creating "
3278  "Highest Transaction Number entry for this server as '"
3279  << lHighestInSet << "'.\n";
3280  m_mapHighTransNo.insert(
3281  std::pair<std::string, int64_t>(strID, lHighestInSet));
3282  }
3283 
3284  // By this point either the record was created, or we were successful
3285  // above in finding it
3286  // and updating it. Either way, it's there now and potentially needs to
3287  // be saved.
3288  //
3289  if (bSave) SaveSignedNymfile(SIGNER_NYM);
3290  }
3291  else // setOutputGood was completely empty in this case...
3292  { // (So there's nothing worth saving.) A repeat message.
3293  //
3294  // Should I return a -1 here or something? Let's say it's
3295  // a redundant message...I've already harvested these numbers. So
3296  // they are ignored this time, my record of 'highest' is unimpacted,
3297  // and if I just return lReturnVal below, it will contain 0 for success
3298  // or a transaction number (the min/low violator) but even that is
3299  // considered
3300  // a "success" in the sense that some of the numbers would still
3301  // normally be
3302  // expected to have passed through.
3303  // The caller will check for -1 in case of some drastic error, but so
3304  // far I don't
3305  // see a place here for that return value.
3306  //
3307  }
3308 
3309  return lReturnVal; // Defaults to 0 (success) but above, might have been set
3310  // to "lLowestInSet" (if one was below the mark.)
3311 }
3312 
3313 // returns true on success, value goes into lReqNum
3314 // Make sure the Nym is LOADED before you call this,
3315 // otherwise it won't be there to get.
3316 // and if the request number needs to be incremented,
3317 // then make sure you call IncrementRequestNum (below)
3319  int64_t& lReqNum) const
3320 {
3321  bool bRetVal = false;
3322  std::string strID = strServerID.Get();
3323 
3324  // The Pseudonym has a map of the request numbers for different servers.
3325  // For Server Bob, with this Pseudonym, I might be on number 34.
3326  // For but Server Alice, I might be on number 59.
3327  //
3328  // So let's loop through all the numbers I have, and if the server ID on the
3329  // map
3330  // matches the Server ID that was passed in, then send out the request
3331  // number.
3332  for (auto& it : m_mapRequestNum) {
3333  if (strID == it.first) {
3334  // Setup return value.
3335  lReqNum = (it.second);
3336  // The call has succeeded
3337  bRetVal = true;
3338  break;
3339  }
3340  }
3341 
3342  return bRetVal;
3343 }
3344 
3345 // Make SURE you call SavePseudonym after you call this.
3346 // Otherwise it will increment in memory but not in the file.
3347 // In fact, I cannot allow that. I will call SavePseudonym myself.
3348 // Therefore, make SURE you fully LOAD this Pseudonym before you save it.
3349 // You don't want to overwrite what's in that file.
3350 // THEREFORE we need a better database than the filesystem.
3351 // I will research a good, free, secure database (or encrypt everything
3352 // before storing it there) and soon these "load/save" commands will use that
3353 // instead of the filesystem.
3355  const OTString& strServerID)
3356 {
3357  bool bSuccess = false;
3358 
3359  // The Pseudonym has a map of the request numbers for different servers.
3360  // For Server Bob, with this Pseudonym, I might be on number 34.
3361  // For but Server Alice, I might be on number 59.
3362  //
3363  // So let's loop through all the numbers I have, and if the server ID on the
3364  // map
3365  // matches the Server ID that was passed in, then send out the request
3366  // number and
3367  // increment it so it will be ready for the next request.
3368  //
3369  // Make sure to save the Pseudonym so the new request number is saved.
3370  std::string strID = strServerID.Get();
3371 
3372  for (auto& it : m_mapRequestNum) {
3373  if (strID == it.first) {
3374  // We found it!
3375  // Presumably we ONLY found it because this Nym has been properly
3376  // loaded first.
3377  // Good job! Otherwise, the list would have been empty even though
3378  // the request number
3379  // was sitting in the file.
3380 
3381  // Grab a copy of the old request number
3382  int64_t lOldRequestNumber = m_mapRequestNum[it.first];
3383 
3384  // Set the new request number to the old one plus one.
3385  m_mapRequestNum[it.first] = lOldRequestNumber + 1;
3386 
3387  // Now we can log BOTH, before and after... // debug here
3388  otLog4 << "Incremented Request Number from " << lOldRequestNumber
3389  << " to " << m_mapRequestNum[it.first] << ". Saving...\n";
3390 
3391  // The call has succeeded
3392  bSuccess = true;
3393  break;
3394  }
3395  }
3396 
3397  // If I didn't find it in the list above (whether the list is empty or
3398  // not....)
3399  // that means it does not exist. So create it.
3400 
3401  if (!bSuccess) {
3402  otOut << "Creating Request Number entry as '100'. Saving...\n";
3403  m_mapRequestNum[strServerID.Get()] = 100;
3404  bSuccess = true;
3405  }
3406 
3407  if (bSuccess) {
3408  SaveSignedNymfile(SIGNER_NYM);
3409  }
3410 }
3411 
3412 // if the server sends us a @getRequest
3414  const OTString& strServerID,
3415  int64_t lNewRequestNumber)
3416 {
3417  bool bSuccess = false;
3418 
3419  // The Pseudonym has a map of the request numbers for different servers.
3420  // For Server Bob, with this Pseudonym, I might be on number 34.
3421  // For but Server Alice, I might be on number 59.
3422  //
3423  // So let's loop through all the numbers I have, and if the server ID on the
3424  // map
3425  // matches the Server ID that was passed in, then send out the request
3426  // number and
3427  // increment it so it will be ready for the next request.
3428  //
3429  // Make sure to save the Pseudonym so the new request number is saved.
3430  std::string strID = strServerID.Get();
3431 
3432  for (auto& it : m_mapRequestNum) {
3433  if (strID == it.first) {
3434  // We found it!
3435  // Presumably we ONLY found it because this Nym has been properly
3436  // loaded first.
3437  // Good job! Otherwise, the list would have been empty even though
3438  // the request number
3439  // was sitting in the file.
3440 
3441  // The call has succeeded
3442  bSuccess = true;
3443 
3444  // Grab a copy of the old request number
3445  int64_t lOldRequestNumber = m_mapRequestNum[it.first];
3446 
3447  // Set the new request number to the old one plus one.
3448  m_mapRequestNum[it.first] = lNewRequestNumber;
3449 
3450  // Now we can log BOTH, before and after...
3451  otLog4 << "Updated Request Number from " << lOldRequestNumber
3452  << " to " << m_mapRequestNum[it.first] << ". Saving...\n";
3453  break;
3454  }
3455  }
3456 
3457  // If I didn't find it in the list above (whether the list is empty or
3458  // not....)
3459  // that means it does not exist. So create it.
3460 
3461  if (!bSuccess) {
3462  otOut << "Creating Request Number entry as '" << lNewRequestNumber
3463  << "'. Saving...\n";
3464  m_mapRequestNum[strServerID.Get()] = lNewRequestNumber;
3465  bSuccess = true;
3466  }
3467 
3468  if (bSuccess) {
3469  SaveSignedNymfile(SIGNER_NYM);
3470  }
3471 }
3472 
3474 {
3475  return m_mapCredentials.size();
3476 }
3477 
3479 {
3480  return m_mapRevoked.size();
3481 }
3482 
3483 /*
3484  How will VerifyPseudonym change now that we are adding credentials?
3485 
3486  Before it was easy: hash the public key, and compare the result to the NymID
3487  as it was already set by the wallet. If they match, then this really is the
3488  public
3489  key that I was expecting. (You could not change out that key without causing
3490  the ID
3491  to also change.)
3492 
3493  How are things with credentials?
3494 
3495  The public key may not directly hash to the Nym ID, but even if it did, which
3496  public key?
3497  Aren't there THREE public keys for each credential? That is, a signing,
3498  authentication, and
3499  encryption key. Which one is used as that Key ID? Perhaps all three are hashed
3500  together?
3501  And that collective three-key is only valid for a given Nym, if its credential
3502  contract is
3503  signed by a master key for that Nym. And that master key is only valid if its
3504  authority
3505  verifies properly. And the Nym's ID should be a hash somehow, of that
3506  authority. All of those
3507  things must verify in VerifyPseudonym, in the new system.
3508 
3509  Is that really true?
3510 
3511  Pseudo-code:
3512 
3513  Loop through the credentials for this Nym.
3514  For each, the authority/source string (which resolve to the NymID) should be
3515  identical.
3516  Resolve the NymID and compare it to the one that was expected.
3517  An extended version will also verify the authority itself, to see if it
3518  verifies the key.
3519  For example if this Nym is issued based on a Namecoin address, then the code
3520  would actually
3521  check Namecoin itself to verify the NymID is the same one posted there.
3522 
3523  */
3524 
3526 {
3527  // If there are credentials, then we verify the Nym via his credentials.
3528  // Otherwise we do it the old way (using the Nym's "keypair")--which is
3529  // being deprecated.
3530  //
3531  if (!m_mapCredentials.empty()) {
3532  // Verify Nym by his own credentials.
3533  for (const auto& it : m_mapCredentials) {
3534  const OTCredential* pCredential = it.second;
3535  OT_ASSERT(nullptr != pCredential);
3536 
3537  const OTIdentifier theCredentialNymID(pCredential->GetNymID());
3538  if (!CompareID(theCredentialNymID)) {
3539  OTString strNymID;
3540  GetIdentifier(strNymID);
3541  otOut << __FUNCTION__ << ": Credential NymID ("
3542  << pCredential->GetNymID()
3543  << ") doesn't match actual NymID: " << strNymID << "\n";
3544  return false;
3545  }
3546 
3547  if (!pCredential->VerifyInternally()) {
3548  otOut << __FUNCTION__ << ": Credential ("
3549  << pCredential->GetMasterCredID()
3550  << ") failed its own internal verification.\n";
3551  return false;
3552  }
3553 
3554  // Warning: time-intensive. Todo optimize: load a contract here
3555  // which verifies authorization,
3556  // based on a signature from a separate process which did an
3557  // identity lookup externally.
3558  // Once that authorization times out, then the identity verification
3559  // server can just sign
3560  // another one.
3561  //
3562  if (!pCredential->VerifyAgainstSource()) // todo optimize,
3563  // warning:
3564  // time-intensive.
3565  {
3566  otOut
3567  << __FUNCTION__
3568  << ": Credential failed against its source. Credential ID: "
3569  << pCredential->GetMasterCredID()
3570  << "\n"
3571  "NymID: " << pCredential->GetNymID()
3572  << "\nSource: " << pCredential->GetSourceForNymID() << "\n";
3573  return false;
3574  }
3575  }
3576 
3577  // NOTE: m_pkeypair needs to be phased out entirely. TODO!!
3578  // In the meantime, ::LoadPublicKey isn't setting m_pkeypair
3579  // because the key isn't actually available until AFTER the
3580  // pCredential->VerifyInternally() has occurred. Well, right
3581  // here, it just occurred (above) and so we can actually set
3582  // m_pkeypair at this point, where we couldn't do it before in
3583  // LoadPublicKey.
3584  //
3585  // The real solution is to just phase out m_pkeypair entirely. TODO!
3586  // But in the meantime, as long as there are vestiges of the code
3587  // that still use it, we need to make sure it's set, and we can
3588  // only do that here, after VerifyInternally() has finished.
3589  //
3590  // (So that's what I'm doing.)
3591  //
3592  if (!m_pkeypair->HasPublicKey()) {
3593  auto it = m_mapCredentials.begin();
3594  OT_ASSERT(m_mapCredentials.end() != it);
3595  OTCredential* pCredential = it->second;
3596  OT_ASSERT(nullptr != pCredential);
3597 
3598  OTString strSigningKey;
3599 
3600  if (const_cast<OTKeypair&>(
3601  pCredential->GetSignKeypair(&m_listRevokedIDs))
3602  .GetPublicKey(strSigningKey, false)) // bEscaped
3603  return m_pkeypair->SetPublicKey(strSigningKey,
3604  false); // bEscaped
3605  else
3606  otErr << __FUNCTION__ << ": Failed in call to "
3607  "pCredential->GetPublicSignKey()."
3608  "GetPublicKey()\n";
3609  }
3610 
3611  return true;
3612 
3613  } // If there are credentials
3614  else // Deprecated. OTPseudonym::m_pkeypair was used for encryption,
3615  // signing, and authentication.
3616  { // (Replaced by the above block, which has a map of credentials for each
3617  // Nym, with each
3618  // credential having a master key and a set of subcredentials including
3619  // subkeys.
3620  //
3621  OT_ASSERT(nullptr != m_pkeypair);
3622 
3623  OTString strPublicKey;
3624  bool bGotPublicKey = m_pkeypair->GetPublicKey(strPublicKey);
3625 
3626  if (!bGotPublicKey) {
3627  otErr << "Error getting public key in "
3628  "OTPseudonym::VerifyPseudonym.\n";
3629  return false;
3630  }
3631 
3632  OTIdentifier newID;
3633  bool bSuccessCalculateDigest = newID.CalculateDigest(strPublicKey);
3634 
3635  if (!bSuccessCalculateDigest) {
3636  otErr << "Error calculating pubkey digest.\n";
3637  return false;
3638  }
3639 
3640  // newID now contains the Hash aka Message Digest aka Fingerprint aka
3641  // "IDENTIFIER"
3642  // of the public key (in its text form, with escaped bookends.)
3643  //
3644  // Now let's compare that identifier to the one already loaded by the
3645  // wallet
3646  // and make sure they MATCH.
3647 
3648  if (m_nymID != newID) {
3649  OTString str1(m_nymID), str2(newID);
3650  otErr << "\nHashes do NOT match in OTPseudonym::VerifyPseudonym!\n"
3651  << str1 << "\n" << str2 << "\n";
3652 
3653  return false;
3654  }
3655  else {
3656  // OTString str2(newID);
3657  // otWarn << "\nNymID from wallet *SUCCESSFUL* match to hash
3658  // of Nym\'s public key:\n%s\n"
3659  // "---------------------------------------------------------------\n",
3660  // str2.Get());
3661  return true;
3662  }
3663  }
3664 }
3665 
3666 bool OTPseudonym::CompareID(const OTPseudonym& RHS) const
3667 {
3668  return RHS.CompareID(m_nymID);
3669 }
3670 
3672 {
3673  OTString nymID;
3674  GetIdentifier(nymID);
3675 
3676  OTASCIIArmor ascName;
3677 
3678  if (m_strName.Exists()) // name is in the clear in memory, and base64 in
3679  // storage.
3680  {
3681  ascName.SetString(m_strName, false); // linebreaks == false
3682  }
3683 
3684  strOutput.Concatenate("<pseudonym name=\"%s\"\n"
3685  " nymID=\"%s\" />\n\n",
3686  ascName.Get(), nymID.Get());
3687 
3688  return true;
3689 }
3690 
3691 bool OTPseudonym::SavePseudonymWallet(std::ofstream& ofs) const
3692 {
3693  OTString strOutput;
3694 
3695  if (SavePseudonymWallet(strOutput))
3696  ofs << strOutput;
3697  else
3698  return false;
3699 
3700  return true;
3701 }
3702 
3703 // This function saves the public key to a file.
3704 //
3705 bool OTPseudonym::SavePublicKey(const OTString& strPath) const
3706 {
3707  const char* szFoldername = OTFolders::Pubkey().Get();
3708  const char* szFilename = strPath.Get();
3709 
3710  OT_ASSERT(nullptr != szFoldername);
3711  OT_ASSERT(nullptr != szFilename);
3712 
3713  OT_ASSERT(nullptr != m_pkeypair);
3714 
3715  // By passing in an OTString instead of OTASCIIArmor, it knows to add the
3716  // bookends
3717  // ----- BEGIN PUBLIC KEY etc. These bookends are necessary for
3718  // OTASCIIArmor to later
3719  // read the thing back up into memory again.
3720  OTString strKey;
3721 
3722  if (m_pkeypair->GetPublicKey(strKey, false)) // false means "do not ESCAPE
3723  // the bookends"
3724  // Ie we'll get ----------- instead of - ---------
3725  {
3726  bool bStored =
3727  OTDB::StorePlainString(strKey.Get(), szFoldername, szFilename);
3728 
3729  if (!bStored) {
3730  otErr << "Failure in OTPseudonym::SavePublicKey while saving to "
3731  "storage: " << szFoldername << OTLog::PathSeparator()
3732  << szFilename << "\n";
3733  return false;
3734  }
3735  }
3736  else {
3737  otErr << "Error in OTPseudonym::SavePublicKey: unable to GetPublicKey "
3738  "from Nym\n";
3739  return false;
3740  }
3741 
3742  return true;
3743 }
3744 
3745 bool OTPseudonym::SavePublicKey(std::ofstream& ofs) const
3746 {
3747  OT_ASSERT(nullptr != m_pkeypair);
3748 
3749  // By passing in an OTString instead of OTASCIIArmor, it knows to add the
3750  // bookends
3751  // ----- BEGIN PUBLIC KEY etc. These bookends are necessary for
3752  // OTASCIIArmor to later
3753  // read the thing back up into memory again.
3754  OTString strKey;
3755 
3756  if (m_pkeypair->GetPublicKey(strKey, false)) // false means "do not ESCAPE
3757  // the bookends"
3758  // Ie we'll get ----------- instead of - ---------
3759  {
3760  strKey.WriteToFile(ofs);
3761  }
3762  else {
3763  otErr << "Error in OTPseudonym::SavePublicKey: unable to GetPublicKey "
3764  "from Nym\n";
3765  return false;
3766  }
3767 
3768  return true;
3769 }
3770 
3771 // pstrID is an output parameter.
3772 bool OTPseudonym::Server_PubKeyExists(OTString* pstrID) // Only used
3773  // on server
3774  // side.
3775 {
3776 
3777  OTString strID;
3778  if (nullptr == pstrID) {
3779  pstrID = &strID;
3780  }
3781  GetIdentifier(*pstrID);
3782 
3783  // Below this point, pstrID is a GOOD pointer, no matter what. (And no need
3784  // to delete it.)
3785 
3786  return OTDB::Exists(OTFolders::Pubkey().Get(), pstrID->Get());
3787 }
3788 
3789 // This version is run on the server side, and assumes only a Public Key.
3790 // This code reads up the file, discards the bookends, and saves only the
3791 // gibberish itself.
3793 {
3794  OT_ASSERT(nullptr != m_pkeypair);
3795 
3796  // Here we try to load credentials first (the new system) and if it's
3797  // successful, we
3798  // use that to set the public key from the credential, and then return.
3799  // Otherwise,
3800  // we run the old code.
3801  //
3802  if (LoadCredentials() && (GetMasterCredentialCount() > 0)) // New style!
3803  {
3804  // auto it = m_mapCredentials.begin();
3805  // OT_ASSERT(m_mapCredentials.end() != it);
3806  // OTCredential * pCredential = it->second;
3807  // OT_ASSERT(nullptr != pCredential);
3808 
3809  // OTString strSigningKey;
3810  //
3811  // if (const_cast<OTKeypair
3812  // &>(pCredential->GetSignKeypair(&m_listRevokedIDs)).GetPublicKey(strSigningKey,
3813  // false)) //bEscaped
3814  // return m_pkeypair->SetPublicKey(strSigningKey, false); //
3815  // bEscaped
3816  // else
3817  // otErr << "%s: Failed in call to
3818  // pCredential->GetPublicSignKey().GetPublicKey()\n", __FUNCTION__);
3819 
3820  return true;
3821 
3822  // NOTE: LoadPublicKey (this function) calls LoadCredentials (above.) On
3823  // the server side, these are
3824  // public credentials which do not contain keys, per se. Instead, it
3825  // contains a single variable which in
3826  // turn contains the master-signed version of itself which then contains
3827  // the public keys.
3828  //
3829  // That means when the credentials are first loaded, there are no public
3830  // keys loaded! Each subcredential
3831  // is signed by itself, and contains a master-signed version of itself
3832  // that's signed by the master. It's
3833  // only AFTER loading, in verification
3834  // (OTSubcredential::VerifyInternally) when we verify the master
3835  // signature
3836  // on the master-signed version, and if it all checks out, THEN we copy
3837  // the public keys from the master-signed
3838  // version up into the actual subcredential. UNTIL WE DO THAT, the
3839  // actual subcredential HAS NO PUBLIC KEYS IN IT.
3840  //
3841  // That's why the above code was having problems -- we are trying to
3842  // "GetPublicKey" when there can be no
3843  // possibility that the public key will be there.
3844  // For now I'm going to NOT set m_pkeypair, since the public key isn't
3845  // available to set onto it yet.
3846  // We want to phase out m_pkeypair anyway, but I just hope this doesn't
3847  // cause problems where it was expected
3848  // in the future, where I still need to somehow make sure it's set.
3849  // (AFTER verification, apparently.)
3850  //
3851  // Notice however, that this only happens in cases where the credentials
3852  // were actually available, so maybe it
3853  // will just work, since the below block is where we handle cases where
3854  // the credentials WEREN'T available, so
3855  // we load the old key the old way. (Meaning we definitely know that
3856  // those "old cases" will continue to work.)
3857  // Any potential problems will have to be in cases where credentials ARE
3858  // available, but the code was nonetheless
3859  // still expecting things to work the old way -- and these are precisely
3860  // the sorts of cases I probably want to
3861  // uncover, so I can convert things over...
3862  }
3863 
3864  // OLD STYLE (below.) Deprecated!
3865 
3866  OTString strID;
3867 
3868  if (!Server_PubKeyExists(&strID)) // strID will contain *this
3869  // nymID after this call.
3870  {
3871  // Code will call this in order to see if there is a PublicKey to be
3872  // loaded.
3873  // Therefore I don't want to log a big error here since we expect that
3874  // sometimes
3875  // the key won't be there.
3876  // Therefore I log at level 4, the same level as I log the successful
3877  // outcome.
3878  //
3879  otLog4 << __FUNCTION__
3880  << ": Failed load: "
3881  "Apparently this Nym doesn't exist. (Returning.)\n";
3882  return false;
3883  }
3884 
3885  const char* szFoldername = OTFolders::Pubkey().Get();
3886  const char* szFilename = strID.Get();
3887 
3888  const OTString strFoldername(szFoldername), strFilename(szFilename);
3889 
3890  // This loads up the ascii-armored Public Key.
3891  // On the client side, the entire x509 is stored in the cert folder.
3892  // (With other Nym's pubkeys stored in pubkey folder.)
3893  // On the server side, it's just the public key and stored here in pubkey
3894  // folder.
3895  //
3896  const bool bCanLoadKeyFile = OTDB::Exists(szFoldername, szFilename);
3897 
3898  if (bCanLoadKeyFile) {
3899  if (!m_pkeypair->LoadPublicKey(strFoldername, strFilename)) {
3900  otErr << __FUNCTION__ << ": Although the ascii-armored file ("
3901  << szFoldername << OTLog::PathSeparator() << szFilename
3902  << ") was read, LoadPublicKey returned false.\n";
3903  return false;
3904  }
3905  else {
3906  otLog4 << __FUNCTION__
3907  << ": Successfully loaded public key from file: "
3908  << szFoldername << OTLog::PathSeparator() << szFilename
3909  << "\n";
3910  }
3911  return true;
3912  }
3913 
3914  otInfo << __FUNCTION__ << ": Failure.\n";
3915  return false;
3916 }
3917 
3918 // DISPLAY STATISTICS
3919 
3921 {
3922  for (auto& it : m_mapRequestNum) {
3923  std::string strServerID = it.first;
3924  int64_t lRequestNumber = it.second;
3925 
3926  // Now we can log BOTH, before and after...
3927  strOutput.Concatenate("Req# is %lld for server ID: %s\n",
3928  lRequestNumber, strServerID.c_str());
3929  }
3930 
3931  for (auto& it : m_mapHighTransNo) {
3932  std::string strServerID = it.first;
3933  const int64_t lHighestNum = it.second;
3934 
3935  strOutput.Concatenate("Highest trans# was %lld for server: %s\n",
3936  lHighestNum, strServerID.c_str());
3937  }
3938 
3939  for (auto& it : m_mapIssuedNum) {
3940  std::string strServerID = it.first;
3941  dequeOfTransNums* pDeque = it.second;
3942 
3943  OT_ASSERT(nullptr != pDeque);
3944 
3945  if (!(pDeque->empty())) {
3946  strOutput.Concatenate(
3947  "---- Transaction numbers still signed out from server: %s\n",
3948  strServerID.c_str());
3949 
3950  for (uint32_t i = 0; i < pDeque->size(); i++) {
3951  int64_t lTransactionNumber = pDeque->at(i);
3952 
3953  strOutput.Concatenate(0 == i ? "%lld" : ", %lld",
3954  lTransactionNumber);
3955  }
3956  strOutput.Concatenate("\n");
3957  }
3958  } // for
3959 
3960  for (auto& it : m_mapTransNum) {
3961  std::string strServerID = it.first;
3962  dequeOfTransNums* pDeque = it.second;
3963 
3964  OT_ASSERT(nullptr != pDeque);
3965 
3966  if (!(pDeque->empty())) {
3967  strOutput.Concatenate(
3968  "---- Transaction numbers still usable on server: %s\n",
3969  strServerID.c_str());
3970 
3971  for (uint32_t i = 0; i < pDeque->size(); i++) {
3972  int64_t lTransactionNumber = pDeque->at(i);
3973  strOutput.Concatenate(0 == i ? "%lld" : ", %lld",
3974  lTransactionNumber);
3975  }
3976  strOutput.Concatenate("\n");
3977  }
3978  } // for
3979 
3980  for (auto& it : m_mapAcknowledgedNum) {
3981  std::string strServerID = it.first;
3982  dequeOfTransNums* pDeque = it.second;
3983 
3984  OT_ASSERT(nullptr != pDeque);
3985 
3986  if (!(pDeque->empty())) {
3987  strOutput.Concatenate("---- Request numbers for which Nym has "
3988  "already received a reply from server: %s\n",
3989  strServerID.c_str());
3990 
3991  for (uint32_t i = 0; i < pDeque->size(); i++) {
3992  int64_t lRequestNumber = pDeque->at(i);
3993  strOutput.Concatenate(0 == i ? "%lld" : ", %lld",
3994  lRequestNumber);
3995  }
3996  strOutput.Concatenate("\n");
3997  }
3998  } // for
3999 
4000  strOutput.Concatenate("Source for ID:\n%s\n", m_strSourceForNymID.Get());
4001  strOutput.Concatenate("Alt. location: %s\n\n", m_strAltLocation.Get());
4002 
4003  const size_t nMasterCredCount = GetMasterCredentialCount();
4004  if (nMasterCredCount > 0) {
4005  for (int32_t iii = 0; iii < static_cast<int64_t>(nMasterCredCount);
4006  ++iii) {
4007  const OTCredential* pCredential = GetMasterCredentialByIndex(iii);
4008  if (nullptr != pCredential) {
4009  strOutput.Concatenate("Credential ID: %s \n",
4010  pCredential->GetMasterCredID().Get());
4011  const size_t nSubcredentialCount =
4012  pCredential->GetSubcredentialCount();
4013 
4014  if (nSubcredentialCount > 0) {
4015  for (size_t vvv = 0; vvv < nSubcredentialCount; ++vvv) {
4016  const std::string str_subcred_id(
4017  pCredential->GetSubcredentialIDByIndex(vvv));
4018 
4019  strOutput.Concatenate(" Subcredential: %s \n",
4020  str_subcred_id.c_str());
4021  }
4022  }
4023  }
4024  }
4025  strOutput.Concatenate("%s", "\n");
4026  }
4027 
4028  strOutput.Concatenate("==> Name: %s %s\n", m_strName.Get(),
4029  m_bMarkForDeletion ? "(MARKED FOR DELETION)" : "");
4030  strOutput.Concatenate(" Version: %s\n", m_strVersion.Get());
4031 
4032  // This is used on server-side only. (Client side sees this value
4033  // by querying the server.)
4034  // Therefore since m_lUsageCredits is unused on client side, why display
4035  // it in the client API? Makes no sense.
4036  // strOutput.Concatenate("Usage Credits: %lld\n", m_lUsageCredits);
4037 
4038  strOutput.Concatenate(" Mail count: %d\n", m_dequeMail.size());
4039  strOutput.Concatenate(" Outmail count: %d\n", m_dequeOutmail.size());
4040  strOutput.Concatenate("Outpayments count: %d\n", m_dequeOutpayments.size());
4041 
4042  OTString theStringID;
4043  GetIdentifier(theStringID);
4044  strOutput.Concatenate("Nym ID: %s\n", theStringID.Get());
4045 }
4046 
4048 {
4049  if (!m_strNymfile.GetLength()) {
4050  OTString nymID;
4051  GetIdentifier(nymID);
4052  m_strNymfile.Format("%s", nymID.Get());
4053  }
4054 
4055  otInfo << "Saving nym to: " << OTFolders::Nym() << OTLog::PathSeparator()
4056  << m_strNymfile << "\n";
4057 
4058  return SavePseudonym(OTFolders::Nym().Get(), m_strNymfile.Get());
4059 }
4060 
4061 bool OTPseudonym::SavePseudonym(const char* szFoldername,
4062  const char* szFilename)
4063 {
4064  OT_ASSERT(nullptr != szFoldername);
4065  OT_ASSERT(nullptr != szFilename);
4066 
4067  OTString strNym;
4068  SavePseudonym(strNym);
4069 
4070  bool bSaved =
4071  OTDB::StorePlainString(strNym.Get(), szFoldername, szFilename);
4072  if (!bSaved)
4073  otErr << __FUNCTION__ << ": Error saving file: " << szFoldername
4074  << OTLog::PathSeparator() << szFilename << "\n";
4075 
4076  return bSaved;
4077 }
4078 
4079 bool OTPseudonym::SavePseudonym(std::ofstream& ofs)
4080 {
4081  OTString strNym;
4082  SavePseudonym(strNym);
4083 
4084  ofs << strNym;
4085 
4086  return true;
4087 }
4088 
4089 // Used when importing/exporting Nym into and out-of the sphere of the cached
4090 // key
4091 // in the wallet.
4093  bool bImporting, // bImporting=true, or false if exporting.
4094  const OTPasswordData* pPWData, const OTPassword* pImportPassword)
4095 {
4096  const OTPassword* pExportPassphrase = nullptr;
4097  std::unique_ptr<const OTPassword> thePasswordAngel;
4098 
4099  if (nullptr == pImportPassword) {
4100 
4101  // whether import/export, this display string is for the OUTSIDE OF
4102  // WALLET
4103  // portion of that process.
4104  //
4105  OTString strDisplay(
4106  nullptr != pPWData
4107  ? pPWData->GetDisplayString()
4108  : (bImporting ? "Enter passphrase for the Nym being imported."
4109  : "Enter passphrase for exported Nym."));
4110  // Circumvents the cached key.
4111  pExportPassphrase = OTSymmetricKey::GetPassphraseFromUser(
4112  &strDisplay, !bImporting); // bAskTwice is true when exporting
4113  // (since the export passphrase is being
4114  // created at that time.)
4115  thePasswordAngel.reset(pExportPassphrase);
4116 
4117  if (nullptr == pExportPassphrase) {
4118  otErr << __FUNCTION__ << ": Failed in GetPassphraseFromUser.\n";
4119  return false;
4120  }
4121 
4122  // otOut << "%s: DEBUGGING pExportPassphrase, size %d, contains: %s
4123  // \n",
4124  // __FUNCTION__,
4125  // pExportPassphrase->getPasswordSize(),
4126  // pExportPassphrase->getPassword());
4127  }
4128  else {
4129  pExportPassphrase = pImportPassword;
4130 
4131  // otOut << "%s: DEBUGGING pImportPassword, size %d, contains: %s
4132  // \n",
4133  // __FUNCTION__, pImportPassword->getPasswordSize(),
4134  // pImportPassword->getPassword());
4135  }
4136 
4137  for (auto& it : m_mapCredentials) {
4138  OTCredential* pCredential = it.second;
4139  OT_ASSERT(nullptr != pCredential);
4140 
4141  if (false ==
4142  pCredential->ReEncryptPrivateCredentials(*pExportPassphrase,
4143  bImporting))
4144  return false;
4145  }
4146 
4147  return true;
4148 }
4149 
4150 // If the Nym's source is a URL, he needs to post his valid master credential
4151 // IDs
4152 // there, so they can be verified against their source. This method is what
4153 // creates
4154 // the file which you can post at that URL. (Containing only the valid IDs, not
4155 // the revoked ones.)
4156 // Optionally it also returns the contents of the public credential files,
4157 // mapped by their
4158 // credential IDs.
4159 //
4161  OTString::Map* pmapCredFiles) const
4162 {
4163  OTString strNymID;
4164  GetIdentifier(strNymID);
4165 
4166  strCredList.Concatenate("<?xml version=\"%s\"?>\n",
4167  "2.0"); // todo hardcoding.
4168 
4169  strCredList.Concatenate("<OTuser version=\"%s\"\n"
4170  " nymID=\"%s\""
4171  ">\n\n",
4172  m_strVersion.Get(), strNymID.Get());
4173 
4174  SerializeNymIDSource(strCredList);
4175 
4176  for (auto& it : m_mapCredentials) {
4177  OTCredential* pCredential = it.second;
4178  OT_ASSERT(nullptr != pCredential);
4179 
4180  pCredential->SerializeIDs(strCredList, m_listRevokedIDs,
4181  pmapCredFiles); // bShowRevoked=false by
4182  // default, bValid=true by
4183  // default. (True since we're
4184  // looping m_mapCredentials
4185  // only, and not
4186  // m_mapRevoked.)
4187  }
4188 
4189  strCredList.Concatenate("</OTuser>\n");
4190 }
4191 
4193  OTString::Map* pmapCredFiles)
4194 {
4195  OTString strNymID;
4196  GetIdentifier(strNymID);
4197 
4198  strCredList.Concatenate("<?xml version=\"%s\"?>\n",
4199  "2.0"); // todo hardcoding.
4200 
4201  strCredList.Concatenate("<OTuser version=\"%s\"\n"
4202  " nymID=\"%s\""
4203  ">\n\n",
4204  m_strVersion.Get(), strNymID.Get());
4205 
4206  SerializeNymIDSource(strCredList);
4207 
4208  SaveCredentialsToString(strCredList, nullptr, pmapCredFiles);
4209 
4210  strCredList.Concatenate("</OTuser>\n");
4211 }
4212 
4214 {
4215 
4216  // We encode these before storing.
4217  if (m_strSourceForNymID.Exists()) {
4218  const OTASCIIArmor ascSourceForNymID(m_strSourceForNymID);
4219 
4220  if (m_strAltLocation.Exists()) {
4221  OTASCIIArmor ascAltLocation;
4222  ascAltLocation.SetString(m_strAltLocation,
4223  false); // bLineBreaks=true by default.
4224 
4225  strOutput.Concatenate(
4226  "<nymIDSource altLocation=\"%s\">\n%s</nymIDSource>\n\n",
4227  ascAltLocation.Get(), ascSourceForNymID.Get());
4228  }
4229  else
4230  strOutput.Concatenate("<nymIDSource>\n%s</nymIDSource>\n\n",
4231  ascSourceForNymID.Get());
4232  }
4233 }
4234 
4236 {
4237  OTString strNymID;
4238  GetIdentifier(strNymID);
4239 
4240  strOutput.Concatenate("<?xml version=\"%s\"?>\n",
4241  "2.0"); // todo hardcoding.
4242 
4243  strOutput.Concatenate("<OTuser version=\"%s\"\n"
4244  " nymID=\"%s\""
4245  ">\n\n",
4246  m_strVersion.Get(), strNymID.Get());
4247 
4248  SerializeNymIDSource(strOutput);
4249 
4250  SaveCredentialsToString(strOutput);
4251 
4252  strOutput.Concatenate("</OTuser>\n");
4253 }
4254 
4256 {
4257  OTString strNymID, strOutput;
4258  GetIdentifier(strNymID);
4259 
4260  SaveCredentialListToString(strOutput);
4261 
4262  if (strOutput.Exists()) {
4263  OTASCIIArmor ascOutput(strOutput);
4264  strOutput.Release();
4265  if (ascOutput.WriteArmoredString(
4266  strOutput, "CREDENTIAL LIST") && // bEscaped=false by default.
4267  strOutput.Exists()) {
4268 
4269  // Save it to local storage.
4270  OTString strFilename;
4271  strFilename.Format("%s.cred", strNymID.Get());
4272 
4273  std::string str_Folder = HasPrivateKey()
4275  : OTFolders::Pubcred().Get();
4276 
4277  if (!OTDB::StorePlainString(strOutput.Get(), str_Folder,
4278  strFilename.Get())) {
4279  otErr << __FUNCTION__ << ": Failure trying to store "
4280  << (HasPrivateKey() ? "private" : "public")
4281  << " credential list for Nym: " << strNymID << "\n";
4282  return false;
4283  }
4284 
4285  return true;
4286  }
4287  }
4288  return false;
4289 }
4290 
4291 // Use this to load the keys for a Nym (whether public or private), and then
4292 // call VerifyPseudonym, and then load the actual Nymfile using
4293 // LoadSignedNymfile.
4294 //
4295 bool OTPseudonym::LoadCredentials(bool bLoadPrivate, // Loads public credentials
4296  // by default. For
4297  // private, pass true.
4298  const OTPasswordData* pPWData,
4299  const OTPassword* pImportPassword)
4300 {
4301  OTString strReason(nullptr == pPWData ? OT_PW_DISPLAY
4302  : pPWData->GetDisplayString());
4303 
4304  ClearCredentials();
4305 
4306  OTString strNymID;
4307  GetIdentifier(strNymID);
4308 
4309  OTString strFilename;
4310  strFilename.Format("%s.cred", strNymID.Get());
4311 
4312  const char* szFoldername = bLoadPrivate ? OTFolders::Credential().Get()
4313  : OTFolders::Pubcred().Get();
4314  const char* szFilename = strFilename.Get();
4315 
4316  if (OTDB::Exists(szFoldername, szFilename)) {
4317  OTString strFileContents(
4318  OTDB::QueryPlainString(szFoldername, szFilename));
4319 
4320  // The credential list file is like the nymfile except with ONLY
4321  // credential IDs inside.
4322  // Therefore, we LOAD it like we're loading a Nymfile from string.
4323  // There's no need for
4324  // the list itself to be signed, since we verify it fully before using
4325  // it to verify the
4326  // signature on the actual nymfile.
4327  // How is the list safe not to be signed? Because the Nym ID's source
4328  // string must hash
4329  // to form the NymID, and any credential IDs on the list must be found
4330  // on a lookup to
4331  // that source. An attacker cannot add a credential without putting it
4332  // inside the source,
4333  // which the user controls, and the attacker cannot change the source
4334  // without changing
4335  // the NymID. Therefore the credential list file itself doesn't need to
4336  // be signed, for
4337  // the same reason that the public key didn't need to be signed: because
4338  // you can prove
4339  // its validity by hashing (the source string that validates the
4340  // credentials in that list,
4341  // or by hashing/ the public key for that Nym, if doing things the old
4342  // way.)
4343  //
4344  if (strFileContents.Exists() && strFileContents.DecodeIfArmored()) {
4345  const bool bLoaded = LoadFromString(
4346  strFileContents,
4347  nullptr, // map of credentials--if nullptr, it loads
4348  // them from local storage.
4349  &strReason, pImportPassword); // optional to provide a
4350  // passphrase (otherwise one is
4351  // prompted for.)
4352 
4353  // Potentially set m_pkeypair here, though it's currently set in
4354  // LoadPublicKey and Loadx509CertAndPrivateKey.
4355  // (And thus set in static calls OTPseudonym::LoadPublicNym and
4356  // LoadPrivateNym.)
4357 
4358  return bLoaded;
4359  }
4360  else {
4361  otErr << __FUNCTION__
4362  << ": Failed trying to load credential list from file: "
4363  << szFoldername << OTLog::PathSeparator() << szFilename
4364  << "\n";
4365  }
4366  }
4367 
4368  return false; // No log on failure, since often this may be used to SEE if
4369  // credentials exist.
4370  // (No need for error message every time they don't exist.)
4371 }
4372 
4374  OTString::Map* pmapPubInfo,
4375  OTString::Map* pmapPriInfo)
4376 {
4377 
4378  // IDs for revoked subcredentials are saved here.
4379  for (auto& it : m_listRevokedIDs) {
4380  std::string str_revoked_id = it;
4381  strOutput.Concatenate("<revokedCredential\n"
4382  " ID=\"%s\""
4383  "/>\n\n",
4384  str_revoked_id.c_str());
4385  }
4386 
4387  // Serialize master and sub-credentials here.
4388  for (auto& it : m_mapCredentials) {
4389  OTCredential* pCredential = it.second;
4390  OT_ASSERT(nullptr != pCredential);
4391 
4392  pCredential->SerializeIDs(
4393  strOutput, m_listRevokedIDs, pmapPubInfo, pmapPriInfo,
4394  true); // bShowRevoked=false by default (true here), bValid=true
4395  }
4396 
4397  // Serialize Revoked master credentials here, including their subkeys.
4398  for (auto& it : m_mapRevoked) {
4399  OTCredential* pCredential = it.second;
4400  OT_ASSERT(nullptr != pCredential);
4401 
4402  pCredential->SerializeIDs(
4403  strOutput, m_listRevokedIDs, pmapPubInfo, pmapPriInfo, true,
4404  false); // bShowRevoked=false by default. (Here it's true.)
4405  // bValid=true by default. Here is for revoked, so false.
4406  }
4407 }
4408 
4409 // Save the Pseudonym to a string...
4411 {
4412  OTString nymID;
4413  GetIdentifier(nymID);
4414 
4415  strNym.Concatenate("<?xml version=\"%s\"?>\n", "2.0");
4416 
4417  if (m_lUsageCredits == 0)
4418  strNym.Concatenate("<OTuser version=\"%s\"\n"
4419  " nymID=\"%s\""
4420  ">\n\n",
4421  m_strVersion.Get(), nymID.Get());
4422  else
4423  strNym.Concatenate("<OTuser version=\"%s\"\n"
4424  " nymID=\"%s\"\n"
4425  " usageCredits=\"%lld\""
4426  ">\n\n",
4427  m_strVersion.Get(), nymID.Get(), m_lUsageCredits);
4428 
4429  SerializeNymIDSource(strNym);
4430 
4431  // For now I'm saving the credential list to a separate file. (And then of
4432  // course,
4433  // each credential also gets its own file.) We load the credential list
4434  // file,
4435  // and any associated credentials, before loading the Nymfile proper.
4436  // Then we use the keys from those credentials possibly to verify the
4437  // signature on
4438  // the Nymfile (or not, in the case of the server which uses its own key.)
4439 
4440  // SaveCredentialsToString(strNym);
4441 
4442  for (auto& it : m_mapRequestNum) {
4443  std::string strServerID = it.first;
4444  int64_t lRequestNum = it.second;
4445 
4446  strNym.Concatenate("<requestNum\n"
4447  " serverID=\"%s\"\n"
4448  " currentRequestNum=\"%lld\""
4449  "/>\n\n",
4450  strServerID.c_str(), lRequestNum);
4451  }
4452 
4453  for (auto& it : m_mapHighTransNo) {
4454  std::string strServerID = it.first;
4455  int64_t lHighestNum = it.second;
4456 
4457  strNym.Concatenate("<highestTransNum\n"
4458  " serverID=\"%s\"\n"
4459  " mostRecent=\"%lld\""
4460  "/>\n\n",
4461  strServerID.c_str(), lHighestNum);
4462  }
4463 
4464  // When you delete a Nym, it just marks it.
4465  // Actual deletion occurs during maintenance sweep (targeting marked
4466  // nyms...)
4467  //
4468  if (m_bMarkForDeletion)
4469  strNym.Concatenate(
4470  "<MARKED_FOR_DELETION>\n"
4471  "%s</MARKED_FOR_DELETION>\n\n",
4472  "THIS NYM HAS BEEN MARKED FOR DELETION AT ITS OWN REQUEST");
4473 
4474  int64_t lTransactionNumber = 0;
4475 
4476  for (auto& it : m_mapTransNum) {
4477  std::string strServerID = it.first;
4478  dequeOfTransNums* pDeque = it.second;
4479 
4480  OT_ASSERT(nullptr != pDeque);
4481 
4482  // if (!(pDeque->empty()) && (strServerID.size() > 0) )
4483  // {
4484  // for (uint32_t i = 0; i < pDeque->size(); i++)
4485  // {
4486  // lTransactionNumber = pDeque->at(i);
4487  //
4488  // strNym.Concatenate("<transactionNum\n"
4489  // " serverID=\"%s\"\n"
4490  // " transactionNum=\"%lld\""
4491  // "/>\n\n",
4492  // strServerID.c_str(),
4493  // lTransactionNumber
4494  // );
4495  // }
4496  // }
4497 
4498  if (!(pDeque->empty()) && (strServerID.size() > 0)) {
4499  OTNumList theList;
4500 
4501  for (uint32_t i = 0; i < pDeque->size(); i++) {
4502  lTransactionNumber = pDeque->at(i);
4503  theList.Add(lTransactionNumber);
4504  }
4505  OTString strTemp;
4506  if ((theList.Count() > 0) && theList.Output(strTemp) &&
4507  strTemp.Exists()) {
4508  const OTASCIIArmor ascTemp(strTemp);
4509 
4510  if (ascTemp.Exists())
4511  strNym.Concatenate("<transactionNums "
4512  "serverID=\"%s\">\n%s</"
4513  "transactionNums>\n\n",
4514  strServerID.c_str(), ascTemp.Get());
4515  }
4516  }
4517  } // for
4518 
4519  lTransactionNumber = 0;
4520 
4521  for (auto& it : m_mapIssuedNum) {
4522  std::string strServerID = it.first;
4523  dequeOfTransNums* pDeque = it.second;
4524 
4525  OT_ASSERT(nullptr != pDeque);
4526 
4527  // if (!(pDeque->empty()) && (strServerID.size() > 0) )
4528  // {
4529  // for (uint32_t i = 0; i < pDeque->size(); i++)
4530  // {
4531  // lTransactionNumber = pDeque->at(i);
4532  //
4533  // strNym.Concatenate("<issuedNum\n"
4534  // " serverID=\"%s\"\n"
4535  // " transactionNum=\"%lld\""
4536  // "/>\n\n",
4537  // strServerID.c_str(),
4538  // lTransactionNumber
4539  // );
4540  // }
4541  // }
4542 
4543  if (!(pDeque->empty()) && (strServerID.size() > 0)) {
4544  OTNumList theList;
4545 
4546  for (uint32_t i = 0; i < pDeque->size(); i++) {
4547  lTransactionNumber = pDeque->at(i);
4548  theList.Add(lTransactionNumber);
4549  }
4550  OTString strTemp;
4551  if ((theList.Count() > 0) && theList.Output(strTemp) &&
4552  strTemp.Exists()) {
4553  const OTASCIIArmor ascTemp(strTemp);
4554 
4555  if (ascTemp.Exists())
4556  strNym.Concatenate(
4557  "<issuedNums serverID=\"%s\">\n%s</issuedNums>\n\n",
4558  strServerID.c_str(), ascTemp.Get());
4559  }
4560  }
4561  } // for
4562 
4563  lTransactionNumber = 0;
4564 
4565  for (auto& it : m_mapTentativeNum) {
4566  std::string strServerID = it.first;
4567  dequeOfTransNums* pDeque = it.second;
4568 
4569  OT_ASSERT(nullptr != pDeque);
4570 
4571  // if (!(pDeque->empty()) && (strServerID.size() > 0) )
4572  // {
4573  // for (uint32_t i = 0; i < pDeque->size(); i++)
4574  // {
4575  // lTransactionNumber = pDeque->at(i);
4576  //
4577  // strNym.Concatenate("<tentativeNum\n"
4578  // " serverID=\"%s\"\n"
4579  // " transactionNum=\"%lld\""
4580  // "/>\n\n",
4581  // strServerID.c_str(),
4582  // lTransactionNumber
4583  // );
4584  // }
4585  // }
4586 
4587  if (!(pDeque->empty()) && (strServerID.size() > 0)) {
4588  OTNumList theList;
4589 
4590  for (uint32_t i = 0; i < pDeque->size(); i++) {
4591  lTransactionNumber = pDeque->at(i);
4592  theList.Add(lTransactionNumber);
4593  }
4594  OTString strTemp;
4595  if ((theList.Count() > 0) && theList.Output(strTemp) &&
4596  strTemp.Exists()) {
4597  const OTASCIIArmor ascTemp(strTemp);
4598 
4599  if (ascTemp.Exists())
4600  strNym.Concatenate("<tentativeNums "
4601  "serverID=\"%s\">\n%s</"
4602  "tentativeNums>\n\n",
4603  strServerID.c_str(), ascTemp.Get());
4604  }
4605  }
4606 
4607  } // for
4608 
4609  // although mapOfTransNums is used, in this case,
4610  // request numbers are what is actually being stored.
4611  // The data structure just happened to be appropriate
4612  // in this case, with generic manipulation functions
4613  // already written, so I used that pre-existing system.
4614  //
4615  for (auto& it : m_mapAcknowledgedNum) {
4616  std::string strServerID = it.first;
4617  dequeOfTransNums* pDeque = it.second;
4618 
4619  OT_ASSERT(nullptr != pDeque);
4620 
4621  // if (!(pDeque->empty()) && (strServerID.size() > 0) )
4622  // {
4623  // for (uint32_t i = 0; i < pDeque->size(); i++)
4624  // {
4625  // const int64_t lRequestNumber = pDeque->at(i);
4626  //
4627  // strNym.Concatenate("<acknowledgedNum\n"
4628  // " serverID=\"%s\"\n"
4629  // " requestNum=\"%lld\""
4630  // "/>\n\n",
4631  // strServerID.c_str(),
4632  // lRequestNumber
4633  // );
4634  // }
4635  // }
4636 
4637  if (!(pDeque->empty()) && (strServerID.size() > 0)) {
4638  OTNumList theList;
4639 
4640  for (uint32_t i = 0; i < pDeque->size(); i++) {
4641  const int64_t lRequestNumber = pDeque->at(i);
4642  theList.Add(lRequestNumber);
4643  }
4644  OTString strTemp;
4645  if ((theList.Count() > 0) && theList.Output(strTemp) &&
4646  strTemp.Exists()) {
4647  const OTASCIIArmor ascTemp(strTemp);
4648 
4649  if (ascTemp.Exists())
4650  strNym.Concatenate(
4651  "<ackNums serverID=\"%s\">\n%s</ackNums>\n\n",
4652  strServerID.c_str(), ascTemp.Get());
4653  }
4654  }
4655 
4656  } // for
4657 
4658  if (!(m_dequeMail.empty())) {
4659  for (uint32_t i = 0; i < m_dequeMail.size(); i++) {
4660  OTMessage* pMessage = m_dequeMail.at(i);
4661  OT_ASSERT(nullptr != pMessage);
4662 
4663  OTString strMail(*pMessage);
4664 
4665  OTASCIIArmor ascMail;
4666 
4667  if (strMail.Exists()) ascMail.SetString(strMail);
4668 
4669  if (ascMail.Exists())
4670  strNym.Concatenate("<mailMessage>\n"
4671  "%s</mailMessage>\n\n",
4672  ascMail.Get());
4673  }
4674  }
4675 
4676  if (!(m_dequeOutmail.empty())) {
4677  for (uint32_t i = 0; i < m_dequeOutmail.size(); i++) {
4678  OTMessage* pMessage = m_dequeOutmail.at(i);
4679  OT_ASSERT(nullptr != pMessage);
4680 
4681  OTString strOutmail(*pMessage);
4682 
4683  OTASCIIArmor ascOutmail;
4684 
4685  if (strOutmail.Exists()) ascOutmail.SetString(strOutmail);
4686 
4687  if (ascOutmail.Exists())
4688  strNym.Concatenate("<outmailMessage>\n"
4689  "%s</outmailMessage>\n\n",
4690  ascOutmail.Get());
4691  }
4692  }
4693 
4694  if (!(m_dequeOutpayments.empty())) {
4695  for (uint32_t i = 0; i < m_dequeOutpayments.size(); i++) {
4696  OTMessage* pMessage = m_dequeOutpayments.at(i);
4697  OT_ASSERT(nullptr != pMessage);
4698 
4699  OTString strOutpayments(*pMessage);
4700 
4701  OTASCIIArmor ascOutpayments;
4702 
4703  if (strOutpayments.Exists())
4704  ascOutpayments.SetString(strOutpayments);
4705 
4706  if (ascOutpayments.Exists())
4707  strNym.Concatenate("<outpaymentsMessage>\n"
4708  "%s</outpaymentsMessage>\n\n",
4709  ascOutpayments.Get());
4710  }
4711  }
4712 
4713  // These are used on the server side.
4714  // (That's why you don't see the server ID saved here.)
4715  //
4716  if (!(m_setOpenCronItems.empty())) {
4717  for (auto& it : m_setOpenCronItems) {
4718  strNym.Concatenate("<hasOpenCronItem ID=\"%lld\" />\n\n", it);
4719  }
4720  }
4721 
4722  // These are used on the server side.
4723  // (That's why you don't see the server ID saved here.)
4724  //
4725  if (!(m_setAccounts.empty())) {
4726  for (auto& it : m_setAccounts) {
4727  strNym.Concatenate("<ownsAssetAcct ID=\"%s\" />\n\n", it.c_str());
4728  }
4729  }
4730 
4731  // client-side
4732  for (auto& it : m_mapNymboxHash) {
4733  std::string strServerID = it.first;
4734  OTIdentifier& theID = it.second;
4735 
4736  if ((strServerID.size() > 0) && !theID.IsEmpty()) {
4737  const OTString strNymboxHash(theID);
4738  strNym.Concatenate("<nymboxHashItem\n"
4739  " serverID=\"%s\"\n"
4740  " nymboxHash=\"%s\""
4741  "/>\n\n",
4742  strServerID.c_str(), strNymboxHash.Get());
4743  }
4744  } // for
4745 
4746  // client-side
4747  for (auto& it : m_mapRecentHash) {
4748  std::string strServerID = it.first;
4749  OTIdentifier& theID = it.second;
4750 
4751  if ((strServerID.size() > 0) && !theID.IsEmpty()) {
4752  const OTString strRecentHash(theID);
4753  strNym.Concatenate("<recentHashItem\n"
4754  " serverID=\"%s\"\n"
4755  " recentHash=\"%s\""
4756  "/>\n\n",
4757  strServerID.c_str(), strRecentHash.Get());
4758  }
4759  } // for
4760 
4761  // server-side
4762  if (!m_NymboxHash.IsEmpty()) {
4763  const OTString strNymboxHash(m_NymboxHash);
4764  strNym.Concatenate("<nymboxHash\n"
4765  " value=\"%s\""
4766  "/>\n\n",
4767  strNymboxHash.Get());
4768  }
4769 
4770  // client-side
4771  for (auto& it : m_mapInboxHash) {
4772  std::string strAcctID = it.first;
4773  OTIdentifier& theID = it.second;
4774 
4775  if ((strAcctID.size() > 0) && !theID.IsEmpty()) {
4776  const OTString strHash(theID);
4777  strNym.Concatenate("<inboxHashItem\n"
4778  " accountID=\"%s\"\n"
4779  " hashValue=\"%s\""
4780  "/>\n\n",
4781  strAcctID.c_str(), strHash.Get());
4782  }
4783  } // for
4784 
4785  // client-side
4786  for (auto& it : m_mapOutboxHash) {
4787  std::string strAcctID = it.first;
4788  OTIdentifier& theID = it.second;
4789 
4790  if ((strAcctID.size() > 0) && !theID.IsEmpty()) {
4791  const OTString strHash(theID);
4792  strNym.Concatenate("<outboxHashItem\n"
4793  " accountID=\"%s\"\n"
4794  " hashValue=\"%s\""
4795  "/>\n\n",
4796  strAcctID.c_str(), strHash.Get());
4797  }
4798  } // for
4799 
4800  strNym.Concatenate("</OTuser>\n");
4801 
4802  return true;
4803 }
4804 
4806 {
4807  auto iter = m_mapCredentials.find(strID.Get());
4808  OTCredential* pCredential = nullptr;
4809 
4810  if (iter != m_mapCredentials.end()) // found it
4811  pCredential = iter->second;
4812 
4813  return pCredential;
4814 }
4815 
4817 {
4818  auto iter = m_mapRevoked.find(strID.Get());
4819  OTCredential* pCredential = nullptr;
4820 
4821  if (iter != m_mapRevoked.end()) // found it
4822  pCredential = iter->second;
4823 
4824  return pCredential;
4825 }
4826 
4828  int32_t nIndex) const
4829 {
4830  if ((nIndex < 0) ||
4831  (nIndex >= static_cast<int64_t>(m_mapCredentials.size()))) {
4832  otErr << __FUNCTION__ << ": Index out of bounds: " << nIndex << "\n";
4833  }
4834  else {
4835  int32_t nLoopIndex = -1;
4836 
4837  for (const auto& it : m_mapCredentials) {
4838  const OTCredential* pCredential = it.second;
4839  OT_ASSERT(nullptr != pCredential);
4840 
4841  ++nLoopIndex; // 0 on first iteration.
4842 
4843  if (nLoopIndex == nIndex) return pCredential;
4844  }
4845  }
4846  return nullptr;
4847 }
4848 
4850  int32_t nIndex) const
4851 {
4852  if ((nIndex < 0) || (nIndex >= static_cast<int64_t>(m_mapRevoked.size()))) {
4853  otErr << __FUNCTION__ << ": Index out of bounds: " << nIndex << "\n";
4854  }
4855  else {
4856  int32_t nLoopIndex = -1;
4857 
4858  for (const auto& it : m_mapRevoked) {
4859  const OTCredential* pCredential = it.second;
4860  OT_ASSERT(nullptr != pCredential);
4861 
4862  ++nLoopIndex; // 0 on first iteration.
4863 
4864  if (nLoopIndex == nIndex) return pCredential;
4865  }
4866  }
4867  return nullptr;
4868 }
4869 
4871  const OTString& strMasterID, const OTString& strSubCredID) const
4872 {
4873  auto iter = m_mapCredentials.find(strMasterID.Get());
4874  const OTCredential* pMaster = nullptr;
4875 
4876  if (iter != m_mapCredentials.end()) // found it
4877  pMaster = iter->second;
4878 
4879  if (nullptr != pMaster) {
4880  const OTSubcredential* pSub =
4881  pMaster->GetSubcredential(strSubCredID, &m_listRevokedIDs);
4882 
4883  if (nullptr != pSub) return pSub;
4884  }
4885 
4886  return nullptr;
4887 }
4888 
4889 // Todo: if it's possible to have a revoked subcredential on a still-good
4890 // master,
4891 // this function doesn't account for that at all.
4892 //
4894  const OTString& strRevokedID, const OTString& strSubCredID) const
4895 {
4896  auto iter = m_mapRevoked.find(strRevokedID.Get());
4897  const OTCredential* pMaster = nullptr;
4898 
4899  if (iter != m_mapRevoked.end()) // found it
4900  pMaster = iter->second;
4901 
4902  if (nullptr != pMaster) {
4903  const OTSubcredential* pSub = pMaster->GetSubcredential(strSubCredID);
4904 
4905  if (nullptr != pSub) return pSub;
4906  }
4907 
4908  return nullptr;
4909 }
4910 
4911 // std::set<int64_t> m_setOpenCronItems; // Until these Cron Items are closed
4912 // out, the server-side Nym keeps a list of them handy.
4913 
4914 // std::set<std::string> m_setAccounts; // A list of asset account IDs. Server
4915 // side only (client side uses wallet; has multiple servers.)
4916 
4917 /*
4918 
4919  Enumeration for all xml nodes which are parsed by IrrXMLReader.
4920 
4921  Enumeration values:
4922 
4923  EXN_NONE No xml node. This is usually the node if you did not read
4924  anything yet.
4925  EXN_ELEMENT A xml element, like <foo>.
4926  EXN_ELEMENT_END End of an xml element, like </foo>.
4927  EXN_TEXT Text within a xml element: <foo> this is the text. </foo>.
4928  EXN_COMMENT An xml comment like <!-- I am a comment --> or a DTD
4929  definition.
4930  EXN_CDATA An xml cdata section like <![CDATA[ this is some CDATA
4931  ]]>.
4932  EXN_UNKNOWN Unknown element.
4933 
4934  Definition at line 180 of file irrXML.h.
4935 
4936  */
4937 // todo optimize
4939  const OTString& strNym,
4940  OTString::Map* pMapCredentials, // pMapCredentials can be passed,
4941  // if you prefer to use a specific
4942  // set, instead of just loading the
4943  // actual set from storage (such as
4944  // during registration, when the
4945  // credentials have been sent
4946  // inside a message.)
4947  OTString* pstrReason, const OTPassword* pImportPassword)
4948 {
4949  bool bSuccess = false;
4950 
4951  ClearAll(); // Since we are loading everything up... (credentials are NOT
4952  // cleared here. See note in OTPseudonym::ClearAll.)
4953 
4954  OTStringXML strNymXML(strNym); // todo optimize
4955  irr::io::IrrXMLReader* xml = irr::io::createIrrXMLReader(strNymXML);
4956  OT_ASSERT(nullptr != xml);
4957  std::unique_ptr<irr::io::IrrXMLReader> theCleanup(xml);
4958 
4959  // parse the file until end reached
4960  while (xml && xml->read()) {
4961 
4962  // switch(xml->getNodeType())
4963  // {
4964  // case(EXN_NONE):
4965  // otErr << "ACK NUMS: EXN_NONE -- No xml node. This is
4966  // usually the node if you did not read anything yet.\n";
4967  // break;
4968  // case(EXN_ELEMENT):
4969  // otErr << "ACK NUMS: EXN_ELEMENT -- An xml element such
4970  // as <foo>.\n";
4971  // break;
4972  // case(EXN_ELEMENT_END):
4973  // otErr << "ACK NUMS: EXN_ELEMENT_END -- End of an xml
4974  // element such as </foo>.\n";
4975  // break;
4976  // case(EXN_TEXT):
4977  // otErr << "ACK NUMS: EXN_TEXT -- Text within an xml
4978  // element: <foo> this is the text. <foo>.\n";
4979  // break;
4980  // case(EXN_COMMENT):
4981  // otErr << "ACK NUMS: EXN_COMMENT -- An xml comment like
4982  // <!-- I am a comment --> or a DTD definition.\n";
4983  // break;
4984  // case(EXN_CDATA):
4985  // otErr << "ACK NUMS: EXN_CDATA -- An xml cdata section
4986  // like <![CDATA[ this is some CDATA ]]>.\n";
4987  // break;
4988  // case(EXN_UNKNOWN):
4989  // otErr << "ACK NUMS: EXN_UNKNOWN -- Unknown
4990  // element.\n";
4991  // break;
4992  // default:
4993  // otErr << "ACK NUMS: default!! -- SHOULD NEVER
4994  // HAPPEN...\n";
4995  // break;
4996  // }
4997  // otErr << "OTPseudonym::LoadFromString: NODE DATA: %s\n",
4998  // xml->getNodeData());
4999 
5000  // strings for storing the data that we want to read out of the file
5001  //
5002  switch (xml->getNodeType()) {
5003  case irr::io::EXN_NONE:
5004  case irr::io::EXN_TEXT:
5005  case irr::io::EXN_COMMENT:
5006  case irr::io::EXN_ELEMENT_END:
5007  case irr::io::EXN_CDATA:
5008  // in this xml file, the only text which occurs is the messageText
5009  // messageText = xml->getNodeData();
5010 
5011  // switch(xml->getNodeType())
5012  // {
5013  // case(EXN_NONE):
5014  // otErr << "SKIPPING: EXN_NONE -- No xml node.
5015  // This is usually the node if you did not read anything yet.\n";
5016  // break;
5017  // case(EXN_TEXT):
5018  // otErr << "SKIPPING: EXN_TEXT -- Text within an
5019  // xml element: <foo> this is the text. <foo>.\n";
5020  // break;
5021  // case(EXN_COMMENT):
5022  // otErr << "SKIPPING: EXN_COMMENT -- An xml
5023  // comment like <!-- I am a comment --> or a DTD definition.\n";
5024  // break;
5025  // case(EXN_ELEMENT_END):
5026  // otErr << "SKIPPING: EXN_ELEMENT_END -- End of
5027  // an xml element such as </foo>.\n";
5028  // break;
5029  // case(EXN_CDATA):
5030  // otErr << "SKIPPING: EXN_CDATA -- An xml cdata
5031  // section like <![CDATA[ this is some CDATA ]]>.\n";
5032  // break;
5033  // default:
5034  // otErr << "SKIPPING: default!! -- SHOULD NEVER
5035  // HAPPEN...\n";
5036  // break;
5037  // }
5038 
5039  break;
5040  case irr::io::EXN_ELEMENT: {
5041  const OTString strNodeName = xml->getNodeName();
5042  // otErr << "PROCESSING EXN_ELEMENT: NODE NAME: %s\n",
5043  // strNodeName.Get());
5044 
5045  if (strNodeName.Compare("OTuser")) {
5046  m_strVersion = xml->getAttributeValue("version");
5047  const OTString UserNymID = xml->getAttributeValue("nymID");
5048 
5049  // Server-side only...
5050  OTString strCredits = xml->getAttributeValue("usageCredits");
5051 
5052  if (strCredits.GetLength() > 0)
5053  m_lUsageCredits = atol(strCredits.Get());
5054  else
5055  m_lUsageCredits =
5056  0; // This is the default anyway, but just being safe...
5057 
5058  // TODO: no need to set the ID again here. We already know the
5059  // ID
5060  // at this point. Better to check and compare they are the same
5061  // here.
5062  // m_nymID.SetString(UserNymID);
5063 
5064  if (UserNymID.GetLength())
5065  otLog3 << "\nLoading user, version: " << m_strVersion
5066  << " NymID:\n" << UserNymID << "\n";
5067  bSuccess = true;
5068  }
5069  else if (strNodeName.Compare("nymIDSource")) {
5070  // otLog3 << "Loading nymIDSource...\n");
5071  OTASCIIArmor ascAltLocation =
5072  xml->getAttributeValue("altLocation"); // optional.
5073  if (ascAltLocation.Exists())
5074  ascAltLocation.GetString(
5075  m_strAltLocation,
5076  false); // bLineBreaks=true by default.
5077 
5079  m_strSourceForNymID)) {
5080  otErr << "Error in " << __FILE__ << " line " << __LINE__
5081  << ": failed loading expected nymIDSource field.\n";
5082  return false; // error condition
5083  }
5084  }
5085  else if (strNodeName.Compare("revokedCredential")) {
5086  const OTString strRevokedID = xml->getAttributeValue("ID");
5087  otLog3 << "revokedCredential ID: " << strRevokedID << "\n";
5088  auto iter =
5089  std::find(m_listRevokedIDs.begin(), m_listRevokedIDs.end(),
5090  strRevokedID.Get());
5091  if (iter == m_listRevokedIDs.end()) // It's not already there,
5092  // so it's safe to add it.
5093  m_listRevokedIDs.push_back(
5094  strRevokedID.Get()); // todo optimize.
5095  }
5096  else if (strNodeName.Compare("masterCredential")) {
5097  const OTString strID = xml->getAttributeValue("ID");
5098  const OTString strValid = xml->getAttributeValue("valid");
5099  const bool bValid = strValid.Compare("true");
5100  otLog3 << "Loading " << (bValid ? "valid" : "invalid")
5101  << " masterCredential ID: " << strID << "\n";
5102  OTString strNymID;
5103  GetIdentifier(strNymID);
5104  OTCredential* pCredential = nullptr;
5105 
5106  if (nullptr == pMapCredentials) // pMapCredentials is an option
5107  // that allows you to read
5108  // credentials from the map instead
5109  // of from local storage. (While
5110  // loading the Nym...) In this
5111  // case, the option isn't being
5112  // employed...
5113  pCredential = OTCredential::LoadMaster(strNymID, strID);
5114  else // In this case, it potentially is on the map...
5115  {
5116  auto it_cred = pMapCredentials->find(strID.Get());
5117 
5118  if (it_cred ==
5119  pMapCredentials->end()) // Nope, didn't find it on the
5120  // map. But if a Map was passed,
5121  // then it SHOULD have contained
5122  // all the listed credentials
5123  // (including the one we're
5124  // trying to load now.)
5125  otErr << __FUNCTION__
5126  << ": Expected master credential (" << strID
5127  << ") on map of credentials, but couldn't find "
5128  "it. (Failure.)\n";
5129  else // Found it on the map passed in (so no need to load
5130  // from storage, we'll load from string instead.)
5131  {
5132  const OTString strMasterCredential(
5133  it_cred->second.c_str());
5134  if (strMasterCredential.Exists()) {
5135  OTPasswordData thePWData(
5136  nullptr == pstrReason
5137  ? "OTPseudonym::LoadFromString"
5138  : pstrReason->Get());
5139  pCredential = OTCredential::LoadMasterFromString(
5140  strMasterCredential, strNymID, strID,
5141  &thePWData, pImportPassword);
5142  }
5143  }
5144  }
5145 
5146  if (nullptr == pCredential) {
5147  otErr << __FUNCTION__
5148  << ": Failed trying to load Master Credential ID: "
5149  << strID << "\n";
5150  return false;
5151  }
5152  else // pCredential must be cleaned up or stored somewhere.
5153  {
5154  mapOfCredentials* pMap =
5155  bValid ? &m_mapCredentials : &m_mapRevoked;
5156  auto iter = pMap->find(strID.Get()); // todo optimize.
5157  if (iter == pMap->end()) // It's not already there, so it's
5158  // safe to add it.
5159  pMap->insert(std::pair<std::string, OTCredential*>(
5160  strID.Get(), pCredential)); // <=====
5161  else {
5162  otErr << __FUNCTION__ << ": While loading credential ("
5163  << strID << "), discovered it was already there "
5164  "on my list, or one with the exact "
5165  "same ID! Therefore, failed "
5166  "adding this newer one.\n";
5167  delete pCredential;
5168  pCredential = nullptr;
5169  return false;
5170  }
5171  }
5172  }
5173  else if (strNodeName.Compare("keyCredential")) {
5174  const OTString strID = xml->getAttributeValue("ID");
5175  const OTString strValid = xml->getAttributeValue(
5176  "valid"); // If this is false, the ID is already on
5177  // revokedCredentials list. (FYI.)
5178  const OTString strMasterCredID =
5179  xml->getAttributeValue("masterID");
5180  const bool bValid = strValid.Compare("true");
5181  otLog3 << "Loading " << (bValid ? "valid" : "invalid")
5182  << " keyCredential ID: " << strID
5183  << "\n ...For master credential: " << strMasterCredID
5184  << "\n";
5185  OTCredential* pCredential =
5186  GetMasterCredential(strMasterCredID); // no need to cleanup.
5187  if (nullptr == pCredential)
5188  pCredential = GetRevokedCredential(strMasterCredID);
5189  if (nullptr == pCredential) {
5190  otErr << __FUNCTION__
5191  << ": While loading keyCredential, failed trying to "
5192  "find expected Master Credential ID: "
5193  << strMasterCredID << "\n";
5194  return false;
5195  }
5196  else // We found the master credential that this keyCredential
5197  // belongs to.
5198  {
5199  bool bLoaded = false;
5200 
5201  if (nullptr ==
5202  pMapCredentials) // pMapCredentials is an option
5203  // that allows you to read
5204  // credentials from the map
5205  // instead of from local
5206  // storage. (While loading the
5207  // Nym...) In this case, the
5208  // option isn't being
5209  // employed...
5210  bLoaded = pCredential->LoadSubkey(strID);
5211  else // In this case, it potentially is on the map...
5212  {
5213  auto it_cred = pMapCredentials->find(strID.Get());
5214 
5215  if (it_cred ==
5216  pMapCredentials->end()) // Nope, didn't find it on
5217  // the map. But if a Map was
5218  // passed, then it SHOULD
5219  // have contained all the
5220  // listed credentials
5221  // (including the one we're
5222  // trying to load now.)
5223  otErr << __FUNCTION__
5224  << ": Expected keyCredential (" << strID
5225  << ") on map of credentials, but couldn't "
5226  "find it. (Failure.)\n";
5227  else // Found it on the map passed in (so no need to
5228  // load from storage, we'll load from string
5229  // instead.)
5230  {
5231  const OTString strSubCredential(
5232  it_cred->second.c_str());
5233  if (strSubCredential.Exists())
5234  bLoaded = pCredential->LoadSubkeyFromString(
5235  strSubCredential, strID, pImportPassword);
5236  }
5237  }
5238 
5239  if (!bLoaded) {
5240  OTString strNymID;
5241  GetIdentifier(strNymID);
5242  otErr << __FUNCTION__
5243  << ": Failed loading keyCredential " << strID
5244  << " for master credential " << strMasterCredID
5245  << " for Nym " << strNymID << ".\n";
5246  return false;
5247  }
5248  }
5249  }
5250  else if (strNodeName.Compare("subCredential")) {
5251  const OTString strID = xml->getAttributeValue("ID");
5252  const OTString strValid = xml->getAttributeValue(
5253  "valid"); // If this is false, the ID is already on
5254  // revokedCredentials list. (FYI.)
5255  const OTString strMasterCredID =
5256  xml->getAttributeValue("masterID");
5257  const bool bValid = strValid.Compare("true");
5258  otLog3 << "Loading " << (bValid ? "valid" : "invalid")
5259  << " subCredential ID: " << strID
5260  << "\n ...For master credential: " << strMasterCredID
5261  << "\n";
5262  OTCredential* pCredential =
5263  GetMasterCredential(strMasterCredID); // no need to cleanup.
5264  if (nullptr == pCredential)
5265  pCredential = GetRevokedCredential(strMasterCredID);
5266  if (nullptr == pCredential) {
5267  otErr << __FUNCTION__
5268  << ": While loading subCredential, failed trying to "
5269  "find expected Master Credential ID: "
5270  << strMasterCredID << "\n";
5271  return false;
5272  }
5273  else // We found the master credential that this subCredential
5274  // belongs to.
5275  {
5276  bool bLoaded = false;
5277 
5278  if (nullptr ==
5279  pMapCredentials) // pMapCredentials is an option
5280  // that allows you to read
5281  // credentials from the map
5282  // instead of from local
5283  // storage. (While loading the
5284  // Nym...) In this case, the
5285  // option isn't being
5286  // employed...
5287  bLoaded = pCredential->LoadSubcredential(strID);
5288  else // In this case, it potentially is on the map...
5289  {
5290  auto it_cred = pMapCredentials->find(strID.Get());
5291 
5292  if (it_cred ==
5293  pMapCredentials->end()) // Nope, didn't find it on
5294  // the map. But if a Map was
5295  // passed, then it SHOULD
5296  // have contained all the
5297  // listed credentials
5298  // (including the one we're
5299  // trying to load now.)
5300  otErr << __FUNCTION__
5301  << ": Expected subCredential (" << strID
5302  << ") on map of credentials, but couldn't "
5303  "find it. (Failure.)\n";
5304  else // Found it on the map passed in (so no need to
5305  // load from storage, we'll load from string
5306  // instead.)
5307  {
5308  const OTString strSubCredential(
5309  it_cred->second.c_str());
5310  if (strSubCredential.Exists())
5311  bLoaded =
5312  pCredential->LoadSubcredentialFromString(
5313  strSubCredential, strID,
5314  pImportPassword);
5315  }
5316  }
5317 
5318  if (!bLoaded) {
5319  OTString strNymID;
5320  GetIdentifier(strNymID);
5321  otErr << __FUNCTION__
5322  << ": Failed loading subCredential " << strID
5323  << " for master credential " << strMasterCredID
5324  << " for Nym " << strNymID << ".\n";
5325  return false;
5326  }
5327  }
5328  }
5329  else if (strNodeName.Compare("requestNum")) {
5330  const OTString ReqNumServerID =
5331  xml->getAttributeValue("serverID");
5332  const OTString ReqNumCurrent =
5333  xml->getAttributeValue("currentRequestNum");
5334 
5335  otLog3 << "\nCurrent Request Number is " << ReqNumCurrent
5336  << " for ServerID: " << ReqNumServerID << "\n";
5337 
5338  // Make sure now that I've loaded this request number, to add it
5339  // to my
5340  // internal map so that it is available for future lookups.
5341  m_mapRequestNum[ReqNumServerID.Get()] =
5342  atol(ReqNumCurrent.Get());
5343  }
5344  else if (strNodeName.Compare("nymboxHash")) {
5345  const OTString strValue = xml->getAttributeValue("value");
5346 
5347  otLog3 << "\nNymboxHash is: " << strValue << "\n";
5348 
5349  if (strValue.Exists()) m_NymboxHash.SetString(strValue);
5350  }
5351  else if (strNodeName.Compare("nymboxHashItem")) {
5352  const OTString strServerID = xml->getAttributeValue("serverID");
5353  const OTString strNymboxHash =
5354  xml->getAttributeValue("nymboxHash");
5355 
5356  otLog3 << "\nNymboxHash is " << strNymboxHash
5357  << " for ServerID: " << strServerID << "\n";
5358 
5359  // Make sure now that I've loaded this nymboxHash, to add it to
5360  // my
5361  // internal map so that it is available for future lookups.
5362  if (strServerID.Exists() && strNymboxHash.Exists()) {
5363  const OTIdentifier theID(strNymboxHash);
5364  m_mapNymboxHash[strServerID.Get()] = theID;
5365  }
5366  }
5367  else if (strNodeName.Compare("recentHashItem")) {
5368  const OTString strServerID = xml->getAttributeValue("serverID");
5369  const OTString strRecentHash =
5370  xml->getAttributeValue("recentHash");
5371 
5372  otLog3 << "\nRecentHash is " << strRecentHash
5373  << " for ServerID: " << strServerID << "\n";
5374 
5375  // Make sure now that I've loaded this RecentHash, to add it to
5376  // my
5377  // internal map so that it is available for future lookups.
5378  if (strServerID.Exists() && strRecentHash.Exists()) {
5379  const OTIdentifier theID(strRecentHash);
5380  m_mapRecentHash[strServerID.Get()] = theID;
5381  }
5382  }
5383  else if (strNodeName.Compare("inboxHashItem")) {
5384  const OTString strAccountID =
5385  xml->getAttributeValue("accountID");
5386  const OTString strHashValue =
5387  xml->getAttributeValue("hashValue");
5388 
5389  otLog3 << "\nInboxHash is " << strHashValue
5390  << " for Account ID: " << strAccountID << "\n";
5391 
5392  // Make sure now that I've loaded this InboxHash, to add it to
5393  // my
5394  // internal map so that it is available for future lookups.
5395  //
5396  if (strAccountID.Exists() && strHashValue.Exists()) {
5397  const OTIdentifier theID(strHashValue);
5398  m_mapInboxHash[strAccountID.Get()] = theID;
5399  }
5400  }
5401  else if (strNodeName.Compare("outboxHashItem")) {
5402  const OTString strAccountID =
5403  xml->getAttributeValue("accountID");
5404  const OTString strHashValue =
5405  xml->getAttributeValue("hashValue");
5406 
5407  otLog3 << "\nOutboxHash is " << strHashValue
5408  << " for Account ID: " << strAccountID << "\n";
5409 
5410  // Make sure now that I've loaded this OutboxHash, to add it to
5411  // my
5412  // internal map so that it is available for future lookups.
5413  //
5414  if (strAccountID.Exists() && strHashValue.Exists()) {
5415  const OTIdentifier theID(strHashValue);
5416  m_mapOutboxHash[strAccountID.Get()] = theID;
5417  }
5418  }
5419  else if (strNodeName.Compare("highestTransNum")) {
5420  const OTString HighNumServerID =
5421  xml->getAttributeValue("serverID");
5422  const OTString HighNumRecent =
5423  xml->getAttributeValue("mostRecent");
5424 
5425  otLog3 << "\nHighest Transaction Number ever received is "
5426  << HighNumRecent << " for ServerID: " << HighNumServerID
5427  << "\n";
5428 
5429  // Make sure now that I've loaded this highest number, to add it
5430  // to my
5431  // internal map so that it is available for future lookups.
5432  m_mapHighTransNo[HighNumServerID.Get()] =
5433  atol(HighNumRecent.Get());
5434  }
5435  else if (strNodeName.Compare("transactionNums")) {
5436  const OTString tempServerID =
5437  xml->getAttributeValue("serverID");
5438  OTString strTemp;
5439  if (!tempServerID.Exists() ||
5440  !OTContract::LoadEncodedTextField(xml, strTemp)) {
5441  otErr << __FUNCTION__
5442  << ": Error: transactionNums field without value.\n";
5443  return false; // error condition
5444  }
5445  OTNumList theNumList;
5446 
5447  if (strTemp.Exists()) theNumList.Add(strTemp);
5448 
5449  int64_t lTemp = 0;
5450  while (theNumList.Peek(lTemp)) {
5451  theNumList.Pop();
5452 
5453  otLog3 << "Transaction Number " << lTemp
5454  << " ready-to-use for ServerID: " << tempServerID
5455  << "\n";
5456  AddTransactionNum(tempServerID, lTemp); // This version
5457  // doesn't save to
5458  // disk. (Why save
5459  // to disk AS WE'RE
5460  // LOADING?)
5461  }
5462  }
5463  else if (strNodeName.Compare("issuedNums")) {
5464  const OTString tempServerID =
5465  xml->getAttributeValue("serverID");
5466  OTString strTemp;
5467  if (!tempServerID.Exists() ||
5468  !OTContract::LoadEncodedTextField(xml, strTemp)) {
5469  otErr << __FUNCTION__
5470  << ": Error: issuedNums field without value.\n";
5471  return false; // error condition
5472  }
5473  OTNumList theNumList;
5474 
5475  if (strTemp.Exists()) theNumList.Add(strTemp);
5476 
5477  int64_t lTemp = 0;
5478  while (theNumList.Peek(lTemp)) {
5479  theNumList.Pop();
5480 
5481  otLog3 << "Currently liable for issued trans# " << lTemp
5482  << " at ServerID: " << tempServerID << "\n";
5483  AddIssuedNum(tempServerID, lTemp); // This version doesn't
5484  // save to disk. (Why
5485  // save to disk AS WE'RE
5486  // LOADING?)
5487  }
5488  }
5489  else if (strNodeName.Compare("tentativeNums")) {
5490  const OTString tempServerID =
5491  xml->getAttributeValue("serverID");
5492  OTString strTemp;
5493  if (!tempServerID.Exists() ||
5494  !OTContract::LoadEncodedTextField(xml, strTemp)) {
5495  otErr << "OTPseudonym::LoadFromString: Error: "
5496  "tentativeNums field without value.\n";
5497  return false; // error condition
5498  }
5499  OTNumList theNumList;
5500 
5501  if (strTemp.Exists()) theNumList.Add(strTemp);
5502 
5503  int64_t lTemp = 0;
5504  while (theNumList.Peek(lTemp)) {
5505  theNumList.Pop();
5506 
5507  otLog3 << "Tentative: Currently awaiting success notice, "
5508  "for accepting trans# " << lTemp
5509  << " for ServerID: " << tempServerID << "\n";
5510  AddTentativeNum(tempServerID, lTemp); // This version
5511  // doesn't save to
5512  // disk. (Why save to
5513  // disk AS WE'RE
5514  // LOADING?)
5515  }
5516  }
5517  else if (strNodeName.Compare("ackNums")) {
5518  const OTString tempServerID =
5519  xml->getAttributeValue("serverID");
5520  OTString strTemp;
5521  if (!tempServerID.Exists()) {
5522  otErr << __FUNCTION__
5523  << ": Error: While loading ackNums "
5524  "field: Missing serverID. Nym contents:\n\n"
5525  << strNym << "\n\n";
5526  return false; // error condition
5527  }
5528 
5529  // xml->read(); // there should be a text field
5530  // next, with the data for the list of acknowledged numbers.
5531  // Note: I think I was forced to add this when the numlist was
5532  // empty, one time, so this may come back
5533  // to haunt me, but I want to fix it right, not kludge it.
5534 
5535  if (!OTContract::LoadEncodedTextField(xml, strTemp)) {
5536  otErr << __FUNCTION__
5537  << ": Error: ackNums field without value "
5538  "(at least, unable to LoadEncodedTextField on "
5539  "that value.)\n";
5540  return false; // error condition
5541  }
5542  OTNumList theNumList;
5543 
5544  if (strTemp.Exists()) theNumList.Add(strTemp);
5545 
5546  int64_t lTemp = 0;
5547  while (theNumList.Peek(lTemp)) {
5548  theNumList.Pop();
5549 
5550  otInfo << "Acknowledgment record exists for server reply, "
5551  "for Request Number " << lTemp
5552  << " for ServerID: " << tempServerID << "\n";
5553  AddAcknowledgedNum(tempServerID, lTemp); // This version
5554  // doesn't save to
5555  // disk. (Why save
5556  // to disk AS WE'RE
5557  // LOADING?)
5558  }
5559  }
5560 
5561  // THE BELOW FOUR ARE DEPRECATED, AND ARE REPLACED BY THE ABOVE
5562  // FOUR.
5563  else if (strNodeName.Compare("transactionNum")) {
5564  const OTString TransNumServerID =
5565  xml->getAttributeValue("serverID");
5566  const OTString TransNumAvailable =
5567  xml->getAttributeValue("transactionNum");
5568 
5569  otLog3 << "Transaction Number " << TransNumAvailable
5570  << " available for ServerID: " << TransNumServerID
5571  << "\n";
5572 
5574  TransNumServerID,
5575  atol(TransNumAvailable.Get())); // This version doesn't save
5576  // to disk. (Why save to
5577  // disk AS WE'RE LOADING?)
5578  }
5579  else if (strNodeName.Compare("issuedNum")) {
5580  const OTString TransNumServerID =
5581  xml->getAttributeValue("serverID");
5582  const OTString TransNumAvailable =
5583  xml->getAttributeValue("transactionNum");
5584 
5585  otLog3 << "Currently liable for Transaction Number "
5586  << TransNumAvailable
5587  << ", for ServerID: " << TransNumServerID << "\n";
5588 
5589  AddIssuedNum(TransNumServerID,
5590  atol(TransNumAvailable.Get())); // This version
5591  // doesn't save to
5592  // disk. (Why save
5593  // to disk AS WE'RE
5594  // LOADING?)
5595  }
5596  else if (strNodeName.Compare("tentativeNum")) {
5597  const OTString TransNumServerID =
5598  xml->getAttributeValue("serverID");
5599  const OTString TransNumAvailable =
5600  xml->getAttributeValue("transactionNum");
5601 
5602  otLog3 << "Currently waiting on server success notice, "
5603  "accepting Transaction Number " << TransNumAvailable
5604  << ", for ServerID: " << TransNumServerID << "\n";
5605 
5606  AddTentativeNum(TransNumServerID,
5607  atol(TransNumAvailable.Get())); // This version
5608  // doesn't save
5609  // to disk. (Why
5610  // save to disk
5611  // AS WE'RE
5612  // LOADING?)
5613  }
5614  else if (strNodeName.Compare("acknowledgedNum")) {
5615  const OTString AckNumServerID =
5616  xml->getAttributeValue("serverID");
5617  const OTString AckNumValue =
5618  xml->getAttributeValue("requestNum");
5619 
5620  otLog3 << "Acknowledgment record exists for server reply, for "
5621  "Request Number " << AckNumValue
5622  << ", for ServerID: " << AckNumServerID << "\n";
5623 
5624  AddAcknowledgedNum(AckNumServerID,
5625  atol(AckNumValue.Get())); // This version
5626  // doesn't save to
5627  // disk. (Why save
5628  // to disk AS WE'RE
5629  // LOADING?)
5630  }
5631  else if (strNodeName.Compare("MARKED_FOR_DELETION")) {
5632  m_bMarkForDeletion = true;
5633  otLog3 << "This nym has been MARKED_FOR_DELETION (at some "
5634  "point prior.)\n";
5635  }
5636  else if (strNodeName.Compare("hasOpenCronItem")) {
5637  OTString strID = xml->getAttributeValue("ID");
5638 
5639  if (strID.Exists()) {
5640  const int64_t lNewID = atol(strID.Get());
5641  m_setOpenCronItems.insert(lNewID);
5642  otLog3 << "This nym has an open cron item with ID: "
5643  << strID << "\n";
5644  }
5645  else
5646  otLog3 << "This nym MISSING ID when loading open cron item "
5647  "record.\n";
5648  }
5649  else if (strNodeName.Compare("ownsAssetAcct")) {
5650  OTString strID = xml->getAttributeValue("ID");
5651 
5652  if (strID.Exists()) {
5653  m_setAccounts.insert(strID.Get());
5654  otLog3 << "This nym has an asset account with the ID: "
5655  << strID << "\n";
5656  }
5657  else
5658  otLog3 << "This nym MISSING asset account ID when loading "
5659  "nym record.\n";
5660  }
5661  else if (strNodeName.Compare("mailMessage")) {
5662  OTASCIIArmor armorMail;
5663  OTString strMessage;
5664 
5665  xml->read();
5666 
5667  if (irr::io::EXN_TEXT == xml->getNodeType()) {
5668  OTString strNodeData = xml->getNodeData();
5669 
5670  // Sometimes the XML reads up the data with a prepended
5671  // newline.
5672  // This screws up my own objects which expect a consistent
5673  // in/out
5674  // So I'm checking here for that prepended newline, and
5675  // removing it.
5676  char cNewline;
5677  if (strNodeData.Exists() && strNodeData.GetLength() > 2 &&
5678  strNodeData.At(0, cNewline)) {
5679  if ('\n' == cNewline)
5680  armorMail.Set(strNodeData.Get() +
5681  1); // I know all this shit is ugly. I
5682  // refactored this in OTContract.
5683  else // unfortunately OTNym is like a "basic type" and
5684  // isn't derived from OTContract.
5685  armorMail.Set(strNodeData.Get()); // TODO:
5686  // OTContract now
5687  // has STATIC
5688  // methods for
5689  // this. (Start
5690  // using them
5691  // here...)
5692 
5693  if (armorMail.GetLength() > 2) {
5694  armorMail.GetString(strMessage,
5695  true); // linebreaks == true.
5696 
5697  if (strMessage.GetLength() > 2) {
5698  OTMessage* pMessage = new OTMessage;
5699 
5700  OT_ASSERT(nullptr != pMessage);
5701 
5702  if (pMessage->LoadContractFromString(
5703  strMessage))
5704  m_dequeMail.push_back(
5705  pMessage); // takes ownership
5706  else
5707  delete pMessage;
5708  }
5709  } // armorMail
5710  } // strNodeData
5711  } // EXN_TEXT
5712  }
5713  else if (strNodeName.Compare("outmailMessage")) {
5714  OTASCIIArmor armorMail;
5715  OTString strMessage;
5716 
5717  xml->read();
5718 
5719  if (irr::io::EXN_TEXT == xml->getNodeType()) {
5720  OTString strNodeData = xml->getNodeData();
5721 
5722  // Sometimes the XML reads up the data with a prepended
5723  // newline.
5724  // This screws up my own objects which expect a consistent
5725  // in/out
5726  // So I'm checking here for that prepended newline, and
5727  // removing it.
5728  char cNewline;
5729  if (strNodeData.Exists() && strNodeData.GetLength() > 2 &&
5730  strNodeData.At(0, cNewline)) {
5731  if ('\n' == cNewline)
5732  armorMail.Set(strNodeData.Get() + 1);
5733  else
5734  armorMail.Set(strNodeData.Get());
5735 
5736  if (armorMail.GetLength() > 2) {
5737  armorMail.GetString(strMessage,
5738  true); // linebreaks == true.
5739 
5740  if (strMessage.GetLength() > 2) {
5741  OTMessage* pMessage = new OTMessage;
5742  OT_ASSERT(nullptr != pMessage);
5743 
5744  if (pMessage->LoadContractFromString(
5745  strMessage))
5746  m_dequeOutmail.push_back(
5747  pMessage); // takes ownership
5748  else
5749  delete pMessage;
5750  }
5751  } // armorMail
5752  } // strNodeData
5753  } // EXN_TEXT
5754  } // outpayments message
5755  else if (strNodeName.Compare("outpaymentsMessage")) {
5756  OTASCIIArmor armorMail;
5757  OTString strMessage;
5758 
5759  xml->read();
5760 
5761  if (irr::io::EXN_TEXT == xml->getNodeType()) {
5762  OTString strNodeData = xml->getNodeData();
5763 
5764  // Sometimes the XML reads up the data with a prepended
5765  // newline.
5766  // This screws up my own objects which expect a consistent
5767  // in/out
5768  // So I'm checking here for that prepended newline, and
5769  // removing it.
5770  char cNewline;
5771  if (strNodeData.Exists() && strNodeData.GetLength() > 2 &&
5772  strNodeData.At(0, cNewline)) {
5773  if ('\n' == cNewline)
5774  armorMail.Set(strNodeData.Get() + 1);
5775  else
5776  armorMail.Set(strNodeData.Get());
5777 
5778  if (armorMail.GetLength() > 2) {
5779  armorMail.GetString(strMessage,
5780  true); // linebreaks == true.
5781 
5782  if (strMessage.GetLength() > 2) {
5783  OTMessage* pMessage = new OTMessage;
5784  OT_ASSERT(nullptr != pMessage);
5785 
5786  if (pMessage->LoadContractFromString(
5787  strMessage))
5788  m_dequeOutpayments.push_back(
5789  pMessage); // takes ownership
5790  else
5791  delete pMessage;
5792  }
5793  }
5794  } // strNodeData
5795  } // EXN_TEXT
5796  } // outpayments message
5797  else {
5798  // unknown element type
5799  otErr << "Unknown element type in " << __FUNCTION__ << ": "
5800  << xml->getNodeName() << "\n";
5801  bSuccess = false;
5802  }
5803  break;
5804  }
5805  default: {
5806  otLog5 << "Unknown XML type in " << __FUNCTION__ << ": "
5807  << xml->getNodeName() << "\n";
5808  break;
5809  }
5810  } // switch
5811  } // while
5812 
5813  return bSuccess;
5814 }
5815 
5817 {
5818  // Get the Nym's ID in string form
5819  OTString nymID;
5820  GetIdentifier(nymID);
5821 
5822  // Create an OTSignedFile object, giving it the filename (the ID) and the
5823  // local directory ("nyms")
5824  OTSignedFile theNymfile(OTFolders::Nym(), nymID);
5825 
5826  if (!theNymfile.LoadFile()) {
5827  otWarn << __FUNCTION__ << ": Failed loading a signed nymfile: " << nymID
5828  << "\n\n";
5829  }
5830  // We verify:
5831  //
5832  // 1. That the file even exists and loads.
5833  // 2. That the local subdir and filename match the versions inside the file.
5834  // 3. That the signature matches for the signer nym who was passed in.
5835  //
5836  else if (!theNymfile.VerifyFile()) {
5837  otErr << __FUNCTION__ << ": Failed verifying nymfile: " << nymID
5838  << "\n\n";
5839  }
5840  else if (!theNymfile.VerifySignature(SIGNER_NYM)) {
5841  OTString strSignerNymID;
5842  SIGNER_NYM.GetIdentifier(strSignerNymID);
5843  otErr << __FUNCTION__
5844  << ": Failed verifying signature on nymfile: " << nymID
5845  << "\n Signer Nym ID: " << strSignerNymID << "\n";
5846  }
5847  // NOTE: Comment out the above two blocks if you want to load a Nym without
5848  // having
5849  // to verify his information. (For development reasons. Never do that
5850  // normally.)
5851  else {
5852  otInfo
5853  << "Loaded and verified signed nymfile. Reading from string...\n";
5854 
5855  if (theNymfile.GetFilePayload().GetLength() > 0)
5856  return LoadFromString(
5857  theNymfile.GetFilePayload()); // <====== Success...
5858  else {
5859  const int64_t lLength =
5860  static_cast<int64_t>(theNymfile.GetFilePayload().GetLength());
5861 
5862  otErr << __FUNCTION__ << ": Bad length (" << lLength
5863  << ") while loading nymfile: " << nymID << "\n";
5864  }
5865  }
5866 
5867  return false;
5868 }
5869 
5871 {
5872  // Get the Nym's ID in string form
5873  OTString strNymID;
5874  GetIdentifier(strNymID);
5875 
5876  // Create an OTSignedFile object, giving it the filename (the ID) and the
5877  // local directory ("nyms")
5878  OTSignedFile theNymfile(OTFolders::Nym().Get(), strNymID);
5879  theNymfile.GetFilename(m_strNymfile);
5880 
5881  otInfo << "Saving nym to: " << m_strNymfile << "\n";
5882 
5883  // First we save this nym to a string...
5884  // Specifically, the file payload string on the OTSignedFile object.
5885  SavePseudonym(theNymfile.GetFilePayload());
5886 
5887  // Now the OTSignedFile contains the path, the filename, AND the
5888  // contents of the Nym itself, saved to a string inside the OTSignedFile
5889  // object.
5890 
5891  if (theNymfile.SignContract(SIGNER_NYM) && theNymfile.SaveContract()) {
5892  const bool bSaved = theNymfile.SaveFile();
5893 
5894  if (!bSaved) {
5895  OTString strSignerNymID;
5896  SIGNER_NYM.GetIdentifier(strSignerNymID);
5897  otErr << __FUNCTION__
5898  << ": Failed while calling theNymfile.SaveFile() for Nym "
5899  << strNymID << " using Signer Nym " << strSignerNymID << "\n";
5900  }
5901 
5902  return bSaved;
5903  }
5904  else {
5905  OTString strSignerNymID;
5906  SIGNER_NYM.GetIdentifier(strSignerNymID);
5907  otErr << __FUNCTION__
5908  << ": Failed trying to sign and save Nymfile for Nym " << strNymID
5909  << " using Signer Nym " << strSignerNymID << "\n";
5910  }
5911 
5912  return false;
5913 }
5914 
5918 {
5919  int64_t lTransactionNumber = 0; // Used in the loop below.
5920 
5921  int32_t nNumberOfTransactionNumbers1 = 0; // *this
5922  int32_t nNumberOfTransactionNumbers2 = 0; // THE_NYM.
5923 
5924  std::string strServerID;
5925 
5926  // First, loop through the Nym on my side (*this), and count how many
5927  // numbers total he has...
5928  //
5929  for (auto& it : GetMapIssuedNum()) {
5930  dequeOfTransNums* pDeque = (it.second);
5931  OT_ASSERT(nullptr != pDeque);
5932 
5933  if (!(pDeque->empty())) {
5934  nNumberOfTransactionNumbers1 +=
5935  static_cast<int32_t>(pDeque->size());
5936  }
5937  } // for
5938 
5939  // Next, loop through THE_NYM, and count his numbers as well...
5940  // But ALSO verify that each one exists on *this, so that each individual
5941  // number is checked.
5942  //
5943  for (auto& it : THE_NYM.GetMapIssuedNum()) {
5944  strServerID = it.first;
5945  dequeOfTransNums* pDeque = it.second;
5946  OT_ASSERT(nullptr != pDeque);
5947 
5948  OTString OTstrServerID = strServerID.c_str();
5949 
5950  if (!(pDeque->empty())) {
5951  for (uint32_t i = 0; i < pDeque->size(); i++) {
5952  lTransactionNumber = pDeque->at(i);
5953 
5954  // if ()
5955  {
5956  nNumberOfTransactionNumbers2++;
5957 
5958  if (false ==
5959  VerifyIssuedNum(OTstrServerID, lTransactionNumber)) {
5960  otOut << "OTPseudonym::" << __FUNCTION__
5961  << ": Issued transaction # " << lTransactionNumber
5962  << " from THE_NYM not found on *this.\n";
5963 
5964  return false;
5965  }
5966  }
5967  }
5968  }
5969  } // for
5970 
5971  // Finally, verify that the counts match...
5972  if (nNumberOfTransactionNumbers1 != nNumberOfTransactionNumbers2) {
5973  otOut << "OTPseudonym::" << __FUNCTION__
5974  << ": Issued transaction # Count mismatch: "
5975  << nNumberOfTransactionNumbers1 << " and "
5976  << nNumberOfTransactionNumbers2 << "\n";
5977 
5978  return false;
5979  }
5980 
5981  return true;
5982 }
5983 
5984 // This is client-side. It's called by VerifyTransactionReceipt and
5985 // VerifyBalanceReceipt.
5986 //
5987 // It's okay if some issued transaction #s in THE_NYM (the receipt's Nym) aren't
5988 // found on *this, (client-side Nym)
5989 // since the last balance agreement may have cleaned them out after they were
5990 // recorded in THE_NYM
5991 // (from the transaction statement receipt).
5992 //
5993 // But I should never see transaction #s APPEAR in *this that aren't in THE_NYM
5994 // on receipt, since a balance agreement
5995 // can ONLY remove numbers, not add them. So any numbers left over should still
5996 // be accounted for on the
5997 // last signed receipt (which supplied THE_NYM as that list of numbers.)
5998 //
5999 // Conclusion: Loop through *this, which is newer, and make sure ALL numbers
6000 // appear on THE_NYM.
6001 // No need to check the reverse, and no need to match the count.
6002 //
6004  OTPseudonym& THE_NYM) // THE_NYM is from the receipt.
6005 {
6006  int64_t lTransactionNumber = 0; // Used in the loop below.
6007 
6008  std::string strServerID;
6009 
6010  // First, loop through the Nym on my side (*this), and verify that all those
6011  // #s appear on the last receipt (THE_NYM)
6012  //
6013  for (auto& it : GetMapIssuedNum()) {
6014  strServerID = it.first;
6015  dequeOfTransNums* pDeque = it.second;
6016 
6017  OTString OTstrServerID = strServerID.c_str();
6018 
6019  OT_ASSERT(nullptr != pDeque);
6020 
6021  if (!(pDeque->empty())) {
6022  for (uint32_t i = 0; i < pDeque->size(); i++) {
6023  lTransactionNumber = pDeque->at(i);
6024 
6025  if (false ==
6026  THE_NYM.VerifyIssuedNum(OTstrServerID,
6027  lTransactionNumber)) {
6028  otOut << "OTPseudonym::" << __FUNCTION__
6029  << ": Issued transaction # " << lTransactionNumber
6030  << " from *this not found on THE_NYM.\n";
6031  return false;
6032  }
6033  }
6034  }
6035  } // for
6036 
6037  // Getting here means that, though issued numbers may have been removed from
6038  // my responsibility
6039  // in a subsequent balance agreement (since the transaction agreement was
6040  // signed), I know
6041  // for a fact that no numbers have been ADDED to my list of responsibility.
6042  // That's the most we can verify here, since we don't know the account
6043  // number that was
6044  // used for the last balance agreement.
6045 
6046  return true;
6047 }
6048 
6049 // Each Nym has a public key file, as well as a nym file. Why two separate
6050 // files?
6051 // Because they are often used for different purposes and are being loaded/saved
6052 // for their own reasons. The Nymfile contains the user ID, which is a hash of
6053 // the
6054 // public key, so the it knows how to find the right pubkey file (filename is
6055 // the
6056 // hash) and it knows how to validate the contents (by hashing them.) The
6057 // Nymfile
6058 // also contains the transaction numbers that have been issued to that nym, so
6059 // the server might later load it up in order to verify that a specific
6060 // transaction
6061 // number is indeed on that list (and then remove it from the list.)
6062 bool OTPseudonym::LoadNymfile(const char* szFilename)
6063 {
6064  OTString strID;
6065  GetIdentifier(strID);
6066 
6067  const char* szFoldername = OTFolders::Nym().Get();
6068  const char* szTheFilename = strID.Get();
6069 
6070  // If no filename was passed in (user might have designated one) then we
6071  // create
6072  // the filename by appending the Nym's ID to the path.
6073  if (nullptr == szFilename) {
6074  m_strNymfile = szTheFilename;
6075  }
6076  else {
6077  m_strNymfile = szFilename;
6078  }
6079 
6080  if (!OTDB::Exists(szFoldername, m_strNymfile.Get())) {
6081  otErr << __FUNCTION__ << ": File does not exist: " << szFoldername
6082  << OTLog::PathSeparator() << m_strNymfile << "\n";
6083  return false;
6084  }
6085 
6086  std::string strFileContents(OTDB::QueryPlainString(
6087  szFoldername, m_strNymfile.Get())); // <=== LOADING FROM DATA STORE.
6088 
6089  if (strFileContents.length() < 2) {
6090  otErr << __FUNCTION__ << ": Error reading file: " << szFoldername
6091  << OTLog::PathSeparator() << m_strNymfile << "\n";
6092  return false;
6093  }
6094 
6095  OTString strRawFile = strFileContents.c_str();
6096 
6097  if (strRawFile.GetLength()) return LoadFromString(strRawFile);
6098 
6099  return false;
6100 }
6101 
6103  const OTString& strInput, const OTPasswordData* pPWData,
6104  const OTPassword* pImportPassword)
6105 {
6106  OT_ASSERT(nullptr != m_pkeypair);
6107 
6108  if (!strInput.Exists()) {
6109  const OTString strID(m_nymID);
6110  otErr << __FUNCTION__ << ": strInput does not exist. (Returning "
6111  "false.) ID currently set to: " << strID
6112  << "\n";
6113  return false;
6114  }
6115 
6116  OTString strReason(nullptr == pPWData ? OT_PW_DISPLAY
6117  : pPWData->GetDisplayString());
6118 
6119  return m_pkeypair->LoadCertAndPrivateKeyFromString(strInput, &strReason,
6120  pImportPassword);
6121 }
6122 
6123 // Todo: if the above function works fine, then call it in the below function
6124 // (to reduce code bloat.)
6125 
6127  const OTPasswordData* pPWData,
6128  const OTPassword* pImportPassword)
6129 {
6130  OT_ASSERT(nullptr != m_pkeypair);
6131 
6132  OTPasswordData thePWData(OT_PW_DISPLAY);
6133  if (nullptr == pPWData) pPWData = &thePWData;
6134  OTString strReason(pPWData->GetDisplayString());
6135 
6136  // Here we try to load credentials first (the new system) and if it's
6137  // successful, we
6138  // use that to set the private/public keypair from the credential, and then
6139  // return.
6140  // Otherwise, we run the old code.
6141  //
6142  if (LoadCredentials(true, pPWData, pImportPassword) &&
6143  (GetMasterCredentialCount() > 0)) // New style!
6144  {
6145  // return true;
6146  auto it = m_mapCredentials.begin();
6147  OT_ASSERT(m_mapCredentials.end() != it);
6148  OTCredential* pCredential = it->second;
6149  OT_ASSERT(nullptr != pCredential);
6150 
6151  OTString strPubAndPrivCert;
6152 
6153  if (const_cast<OTKeypair&>(
6154  pCredential->GetSignKeypair(&m_listRevokedIDs))
6155  .SaveCertAndPrivateKeyToString(strPubAndPrivCert, &strReason,
6156  pImportPassword)) {
6157  const bool bReturnValue =
6158  m_pkeypair->LoadCertAndPrivateKeyFromString(
6159  strPubAndPrivCert, &strReason, pImportPassword);
6160 
6161  if (!bReturnValue)
6162  otErr << __FUNCTION__
6163  << ": Failed in call to m_pkeypair->SetPrivateKey.\n";
6164 
6165  return bReturnValue;
6166  }
6167  }
6168 
6169  // OLD STYLE (below) Deprecated.
6170 
6171  OTString strID(m_nymID);
6172 
6173  std::string strFoldername = OTFolders::Cert().Get();
6174  std::string strFilename = strID.Get();
6175 
6176  if (strFoldername.empty()) {
6177  otErr << __FUNCTION__ << ": Error: strFoldername is empty!";
6178  OT_FAIL;
6179  }
6180  if (strFilename.empty()) {
6181  otErr << __FUNCTION__ << ": Error: strFilename is empty!";
6182  OT_FAIL;
6183  }
6184 
6185  const bool bExists = OTDB::Exists(strFoldername, strFilename);
6186 
6187  if (!bExists) {
6188  OTLog::vOutput(bChecking ? 1 : 0,
6189  "%s: (%s: is %s). File does not exist: %s in: %s\n",
6190  __FUNCTION__, "bChecking", bChecking ? "true" : "false",
6191  strFoldername.c_str(), strFilename.c_str());
6192 
6193  return false;
6194  }
6195  else if (m_pkeypair->LoadBothKeysFromCertFile(
6196  OTFolders::Cert(), // foldername
6197  strID, // filename
6198  &strReason, pImportPassword))
6199  return true; // LoadBothKeysFromCertFile has plenty of logs, no need for
6200  // more at this time here.
6201 
6202  otErr << __FUNCTION__ << ": Failure, filename: " << strFoldername
6203  << OTLog::PathSeparator() << strFilename << "\n";
6204  return false;
6205 }
6206 
6207 // static
6209 {
6210  OTString strCredListFile;
6211  strCredListFile.Format("%s.cred", strNymID.Get());
6212 
6213  return OTDB::Exists(OTFolders::Cert().Get(),
6214  strNymID.Get()) || // Old-school.
6216  strCredListFile.Get()); // New-school.
6217 }
6218 
6219 // on the client side, this means it's a private Nym.
6221 {
6222  const OTString strID(m_nymID);
6223  return OTPseudonym::DoesCertfileExist(strID);
6224 }
6225 
6227 {
6228  OT_ASSERT(nullptr != m_pkeypair);
6229 
6230  return m_pkeypair->HasPublicKey();
6231 }
6232 
6234 {
6235  OT_ASSERT(nullptr != m_pkeypair);
6236 
6237  return m_pkeypair->HasPrivateKey();
6238 }
6239 
6240 // This version WILL handle the bookends: -----BEGIN CERTIFICATE------
6241 // It will also handle the escaped version: - -----BEGIN CERTIFICATE-----
6242 bool OTPseudonym::SetCertificate(const OTString& strCert, bool bEscaped)
6243 {
6244  OT_ASSERT(nullptr != m_pkeypair);
6245 
6246  return m_pkeypair->LoadPublicKeyFromCertString(strCert, bEscaped);
6247 }
6248 
6249 // This version WILL handle the bookends -----BEGIN PUBLIC KEY------
6250 // It will also handle the escaped version: - -----BEGIN PUBLIC KEY------
6251 bool OTPseudonym::SetPublicKey(const OTString& strKey, bool bEscaped)
6252 {
6253  OT_ASSERT(nullptr != m_pkeypair);
6254 
6255  return m_pkeypair->SetPublicKey(strKey, bEscaped);
6256 }
6257 
6258 // This version handles the ascii-armored text WITHOUT the bookends
6260 {
6261  OT_ASSERT(nullptr != m_pkeypair);
6262 
6263  return m_pkeypair->SetPublicKey(strKey);
6264 }
6265 
6266 // This version WILL handle the bookends -----BEGIN ENCRYPTED PRIVATE KEY------
6267 // It will also handle the escaped version: - -----BEGIN ENCRYPTED PRIVATE
6268 // KEY------
6269 //
6270 bool OTPseudonym::SetPrivateKey(const OTString& strKey, bool bEscaped)
6271 {
6272  OT_ASSERT(nullptr != m_pkeypair);
6273 
6274  return m_pkeypair->SetPrivateKey(strKey, bEscaped);
6275 }
6276 
6277 // This version handles the ascii-armored text WITHOUT the bookends
6278 //
6280 {
6281  OT_ASSERT(nullptr != m_pkeypair);
6282 
6283  return m_pkeypair->SetPrivateKey(strKey);
6284 }
6285 
6287 {
6288  if (!m_mapCredentials.empty()) {
6289  const OTCredential* pCredential = nullptr;
6290 
6291  for (const auto& it : m_mapCredentials) {
6292  // Todo: If we have some criteria, such as which master or
6293  // subcredential
6294  // is currently being employed by the user, we'll use that here to
6295  // skip
6296  // through this loop until we find the right one. Until then, I'm
6297  // just
6298  // going to return the first one that's valid (not null).
6299 
6300  pCredential = it.second;
6301  if (nullptr != pCredential) break;
6302  }
6303  if (nullptr == pCredential) OT_FAIL;
6304 
6305  return pCredential->GetPrivateAuthKey(&m_listRevokedIDs); // success
6306  }
6307  else {
6308  OTString strNymID;
6309  GetIdentifier(strNymID);
6310  otWarn << __FUNCTION__ << ": This nym (" << strNymID
6311  << ") has no credentials from where I can pluck a private "
6312  "AUTHENTICATION key, apparently."
6313  " Instead, using the private key on the Nym's keypair (a "
6314  "system which is being deprecated in favor of credentials,"
6315  " so it's not good that I'm having to do this here. Why are "
6316  "there no credentials on this Nym?)\n";
6317  }
6318 
6319  // else // Deprecated.
6320  {
6321  OT_ASSERT(nullptr != m_pkeypair);
6322 
6323  return m_pkeypair->GetPrivateKey();
6324  }
6325 }
6326 
6328 {
6329  if (!m_mapCredentials.empty()) {
6330  const OTCredential* pCredential = nullptr;
6331 
6332  for (const auto& it : m_mapCredentials) {
6333  // Todo: If we have some criteria, such as which master or
6334  // subcredential
6335  // is currently being employed by the user, we'll use that here to
6336  // skip
6337  // through this loop until we find the right one. Until then, I'm
6338  // just
6339  // going to return the first one that's valid (not null).
6340 
6341  pCredential = it.second;
6342  if (nullptr != pCredential) break;
6343  }
6344  if (nullptr == pCredential) OT_FAIL;
6345 
6346  return pCredential->GetPrivateEncrKey(&m_listRevokedIDs);
6347  ; // success
6348  }
6349  else {
6350  OTString strNymID;
6351  GetIdentifier(strNymID);
6352  otWarn << __FUNCTION__ << ": This nym (" << strNymID
6353  << ") has no credentials from where I can pluck a private "
6354  "ENCRYPTION key, apparently. "
6355  "Instead, using the private key on the Nym's keypair (a "
6356  "system which is being deprecated in favor of credentials, "
6357  "so it's not good that I'm having to do this here. Why are "
6358  "there no credentials on this Nym?)\n";
6359  }
6360 
6361  // else // Deprecated.
6362  {
6363  OT_ASSERT(nullptr != m_pkeypair);
6364 
6365  return m_pkeypair->GetPrivateKey();
6366  }
6367 }
6368 
6370 {
6371  if (!m_mapCredentials.empty()) {
6372  const OTCredential* pCredential = nullptr;
6373 
6374  for (const auto& it : m_mapCredentials) {
6375  // Todo: If we have some criteria, such as which master or
6376  // subcredential
6377  // is currently being employed by the user, we'll use that here to
6378  // skip
6379  // through this loop until we find the right one. Until then, I'm
6380  // just
6381  // going to return the first one that's valid (not null).
6382 
6383  pCredential = it.second;
6384  if (nullptr != pCredential) break;
6385  }
6386  if (nullptr == pCredential) OT_FAIL;
6387 
6388  return pCredential->GetPrivateSignKey(&m_listRevokedIDs); // success
6389  }
6390  else {
6391  OTString strNymID;
6392  GetIdentifier(strNymID);
6393  otWarn << __FUNCTION__ << ": This nym (" << strNymID
6394  << ") has no credentials from where I can pluck a private "
6395  "SIGNING key, apparently. Instead,"
6396  " using the private key on the Nym's keypair (a system which "
6397  "is being deprecated in favor of credentials, so it's not "
6398  "good"
6399  " that I'm having to do this here. Why are there no "
6400  "credentials on this Nym?)\n";
6401  }
6402 
6403  // else // Deprecated.
6404  {
6405  OT_ASSERT(nullptr != m_pkeypair);
6406 
6407  return m_pkeypair->GetPrivateKey();
6408  }
6409 }
6410 
6412 {
6413  if (!m_mapCredentials.empty()) {
6414  const OTCredential* pCredential = nullptr;
6415 
6416  for (const auto& it : m_mapCredentials) {
6417  // Todo: If we have some criteria, such as which master or
6418  // subcredential
6419  // is currently being employed by the user, we'll use that here to
6420  // skip
6421  // through this loop until we find the right one. Until then, I'm
6422  // just
6423  // going to return the first one that's valid (not null).
6424 
6425  pCredential = it.second;
6426  if (nullptr != pCredential) break;
6427  }
6428  if (nullptr == pCredential) OT_FAIL;
6429 
6430  return pCredential->GetPublicAuthKey(&m_listRevokedIDs); // success
6431  }
6432  else {
6433  OTString strNymID;
6434  GetIdentifier(strNymID);
6435  otWarn << __FUNCTION__ << ": This nym (" << strNymID
6436  << ") has no credentials from which I can pluck a public "
6437  "AUTHENTICATION key, unfortunately. Instead,"
6438  " using the public key on the Nym's keypair (a system which "
6439  "is being deprecated in favor of credentials, so it's not "
6440  "good"
6441  " that I'm having to do this here. Why are there no "
6442  "credentials on this Nym?)\n";
6443  }
6444 
6445  // else // Deprecated.
6446  {
6447  OT_ASSERT(nullptr != m_pkeypair);
6448 
6449  return m_pkeypair->GetPublicKey();
6450  }
6451 }
6452 
6454 {
6455  if (!m_mapCredentials.empty()) {
6456  const OTCredential* pCredential = nullptr;
6457  for (const auto& it : m_mapCredentials) {
6458  // Todo: If we have some criteria, such as which master or
6459  // subcredential
6460  // is currently being employed by the user, we'll use that here to
6461  // skip
6462  // through this loop until we find the right one. Until then, I'm
6463  // just
6464  // going to return the first one that's valid (not null).
6465 
6466  pCredential = it.second;
6467  if (nullptr != pCredential) break;
6468  }
6469  if (nullptr == pCredential) OT_FAIL;
6470 
6471  return pCredential->GetPublicEncrKey(&m_listRevokedIDs); // success
6472  }
6473  else {
6474  OTString strNymID;
6475  GetIdentifier(strNymID);
6476  otWarn << __FUNCTION__ << ": This nym (" << strNymID
6477  << ") has no credentials from which I can pluck a public "
6478  "ENCRYPTION key, unfortunately. Instead,"
6479  " using the public key on the Nym's keypair (a system which "
6480  "is being deprecated in favor of credentials, so it's not "
6481  "good"
6482  " that I'm having to do this here. Why are there no "
6483  "credentials on this Nym?)\n";
6484  }
6485 
6486  // else // Deprecated.
6487  {
6488  OT_ASSERT(nullptr != m_pkeypair);
6489 
6490  return m_pkeypair->GetPublicKey();
6491  }
6492 }
6493 
6495 {
6496  if (!m_mapCredentials.empty()) {
6497  const OTCredential* pCredential = nullptr;
6498 
6499  for (const auto& it : m_mapCredentials) {
6500  // Todo: If we have some criteria, such as which master or
6501  // subcredential
6502  // is currently being employed by the user, we'll use that here to
6503  // skip
6504  // through this loop until we find the right one. Until then, I'm
6505  // just
6506  // going to return the first one that's valid (not null).
6507 
6508  pCredential = it.second;
6509  if (nullptr != pCredential) break;
6510  }
6511  if (nullptr == pCredential) OT_FAIL;
6512 
6513  return pCredential->GetPublicSignKey(&m_listRevokedIDs); // success
6514  }
6515  else {
6516  OTString strNymID;
6517  GetIdentifier(strNymID);
6518  otWarn << __FUNCTION__ << ": This nym (" << strNymID
6519  << ") has no credentials from which I can pluck a public "
6520  "SIGNING key, unfortunately. Instead,"
6521  " using the public key on the Nym's keypair (a system which "
6522  "is being deprecated in favor of credentials, so it's not "
6523  "good"
6524  " that I'm having to do this here. Why are there no "
6525  "credentials on this Nym?)\n";
6526  }
6527 
6528  // else // Deprecated.
6529  {
6530  OT_ASSERT(nullptr != m_pkeypair);
6531 
6532  return m_pkeypair->GetPublicKey();
6533  }
6534 }
6535 
6536 // This is being called by:
6537 // OTContract::VerifySignature(const OTPseudonym& theNym, const OTSignature&
6538 // theSignature, OTPasswordData * pPWData=nullptr)
6539 //
6540 // Note: Need to change OTContract::VerifySignature so that it checks all of
6541 // these keys when verifying.
6542 //
6543 // OT uses the signature's metadata to narrow down its search for the correct
6544 // public key.
6545 // Return value is the count of public keys found that matched the metadata on
6546 // the signature.
6547 //
6549  const OTSignature& theSignature,
6550  char cKeyType) const
6551 {
6552  OT_ASSERT(nullptr != m_pkeypair);
6553 
6554  // Unfortunately, theSignature can only narrow the search down (there may be
6555  // multiple results.)
6556  int32_t nCount = 0;
6557 
6558  for (const auto& it : m_mapCredentials) {
6559  const OTCredential* pCredential = it.second;
6560  OT_ASSERT(nullptr != pCredential);
6561 
6562  const int32_t nTempCount = pCredential->GetPublicKeysBySignature(
6563  listOutput, theSignature, cKeyType);
6564  nCount += nTempCount;
6565  }
6566 
6567  return nCount;
6568 }
6569 
6570 // sets internal member based in ID passed in
6571 void OTPseudonym::SetIdentifier(const OTIdentifier& theIdentifier)
6572 {
6573  m_nymID = theIdentifier;
6574 }
6575 
6576 // sets argument based on internal member
6577 void OTPseudonym::GetIdentifier(OTIdentifier& theIdentifier) const
6578 {
6579  theIdentifier = m_nymID;
6580 }
6581 
6582 // sets internal member based in ID passed in
6583 void OTPseudonym::SetIdentifier(const OTString& theIdentifier)
6584 {
6585  m_nymID.SetString(theIdentifier);
6586 }
6587 
6588 // sets argument based on internal member
6589 void OTPseudonym::GetIdentifier(OTString& theIdentifier) const
6590 {
6591  m_nymID.GetString(theIdentifier);
6592 }
6593 
6595  : m_bMarkForDeletion(false)
6596  , m_pkeypair(new OTKeypair)
6597  , m_lUsageCredits(0)
6598 {
6599  OT_ASSERT(nullptr != m_pkeypair);
6600 
6601  Initialize();
6602 }
6603 
6605 {
6606  m_strVersion = "1.0";
6607 }
6608 
6609 OTPseudonym::OTPseudonym(const OTString& name, const OTString& filename,
6610  const OTString& nymID)
6611  : m_bMarkForDeletion(false)
6612  , m_pkeypair(new OTKeypair)
6613  , m_lUsageCredits(0)
6614 {
6615  OT_ASSERT(nullptr != m_pkeypair);
6616 
6617  Initialize();
6618 
6619  m_strName = name;
6620  m_strNymfile = filename;
6621 
6622  m_nymID.SetString(nymID);
6623 }
6624 
6626  : m_bMarkForDeletion(false)
6627  , m_pkeypair(new OTKeypair)
6628  , m_lUsageCredits(0)
6629 {
6630  OT_ASSERT(nullptr != m_pkeypair);
6631 
6632  Initialize();
6633 
6634  m_nymID = nymID;
6635 }
6636 
6638  : m_bMarkForDeletion(false)
6639  , m_pkeypair(new OTKeypair)
6640  , m_lUsageCredits(0)
6641 {
6642  OT_ASSERT(nullptr != m_pkeypair);
6643 
6644  Initialize();
6645 
6646  m_nymID.SetString(strNymID);
6647 }
6648 
6650 {
6651  m_listRevokedIDs.clear();
6652 
6653  while (!m_mapCredentials.empty()) {
6654  OTCredential* pCredential = m_mapCredentials.begin()->second;
6655  m_mapCredentials.erase(m_mapCredentials.begin());
6656  delete pCredential;
6657  pCredential = nullptr;
6658  }
6659 
6660  while (!m_mapRevoked.empty()) {
6661  OTCredential* pCredential = m_mapRevoked.begin()->second;
6662  m_mapRevoked.erase(m_mapRevoked.begin());
6663  delete pCredential;
6664  pCredential = nullptr;
6665  }
6666 }
6667 
6669 {
6670  m_mapRequestNum.clear();
6671  m_mapHighTransNo.clear();
6672 
6674  // m_mapTransNum.clear();
6675  // m_mapIssuedNum.clear();
6676  // m_mapTentativeNum.clear();
6677  // m_mapAcknowledgedNum.clear();
6678 
6679  m_mapNymboxHash.clear();
6680  m_mapRecentHash.clear();
6681  m_mapInboxHash.clear();
6682  m_mapOutboxHash.clear();
6683 
6684  m_setAccounts.clear();
6685  m_setOpenCronItems.clear();
6686 
6687  ClearMail();
6688  ClearOutmail();
6689  ClearOutpayments();
6690 
6691  // We load the Nym twice... once just to load the credentials up from the
6692  // .cred file, and a second
6693  // time to load the rest of the Nym up from the Nymfile. LoadFromString
6694  // calls ClearAll before loading,
6695  // so there's no possibility of duplicated data on the Nym. And when that
6696  // happens, we don't want the
6697  // credentials to get cleared, since we want them to still be there after
6698  // the rest of the Nym is
6699  // loaded. So this is commented out.
6700  // ClearCredentials();
6701 }
6702 
6704 {
6705 
6706  ClearAll();
6707  ClearCredentials();
6708 
6709  if (nullptr != m_pkeypair) delete m_pkeypair; // todo: else error
6710 
6711  m_pkeypair = nullptr;
6712 }
6713 
6714 } // namespace opentxs
static EXPORT void vError(const char *szError,...)
Definition: OTLog.cpp:800
EXPORT bool LoadCertAndPrivateKeyFromString(const OTString &strInput, const OTString *pstrReason=nullptr, const OTPassword *pImportPassword=nullptr)
Definition: OTKeypair.cpp:294
EXPORT int32_t GetIssuedNumCount(const OTIdentifier &theServerID) const
EXPORT bool SetPrivateKey(const OTString &strKey, bool bEscaped=true)
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
EXPORT void GetPublicCredentials(OTString &strCredList, OTString::Map *pmapCredFiles=nullptr) const
std::map< std::string, std::string > Map
Definition: OTString.hpp:162
EXPORT bool SetNymboxHash(const std::string &server_id, const OTIdentifier &theInput)
EXPORT const OTAsymmetricKey & GetPublicSignKey(const OTString::List *plistRevokedIDs=nullptr) const
EXPORT bool VerifyIssuedNumbersOnNym(OTPseudonym &THE_NYM)
static EXPORT OTPseudonym * LoadPublicNym(const OTIdentifier &NYM_ID, const OTString *pstrName=nullptr, const char *szFuncName=nullptr)
EXPORT bool SetPublicKey(const OTString &strKey, bool bEscaped=true)
std::list< OTAsymmetricKey * > listOfAsymmetricKeys
EXPORT void ClearMail()
EXPORT const OTAsymmetricKey & GetPublicKey() const
Definition: OTKeypair.cpp:229
EXPORT const char * GetDisplayString() const
EXPORT const OTSubcredential * GetSubcredential(const OTString &strSubID, const OTString::List *plistRevokedIDs=nullptr) const
EXPORT bool CalculateNymboxHash(OTIdentifier &theOutput)
Definition: OTLedger.cpp:790
EXPORT void HarvestTransactionNumbers(const OTIdentifier &theServerID, OTPseudonym &SIGNER_NYM, OTPseudonym &theOtherNym, bool bSave=true)
EXPORT const OTSubcredential * GetSubcredential(const OTString &strMasterID, const OTString &strSubCredID) const
static EXPORT bool DoesCertfileExist(const OTString &strNymID)
EXPORT const OTString & GetNymID() const
EXPORT bool CalculateDigest(const OTData &dataInput)
EXPORT OTItem * GenerateTransactionStatement(const OTTransaction &theOwner)
EXPORT bool ClawbackTransactionNumber(const OTIdentifier &theServerID, const int64_t &lTransClawback, bool bSave=false, OTPseudonym *pSIGNER_NYM=nullptr)
EXPORT bool LoadFromString(const OTString &strNym, OTString::Map *pMapCredentials=nullptr, OTString *pstrReason=nullptr, const OTPassword *pImportPassword=nullptr)
EXPORT bool SetInboxHash(const std::string &acct_id, const OTIdentifier &theInput)
EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
static EXPORT const OTString & Pubcred()
Definition: OTFolders.cpp:343
EXPORT OTString & GetFilePayload()
#define WIPE_MAP_AND_DEQUE(the_map)
EXPORT OTCredential * GetMasterCredential(const OTString &strID)
EXPORT bool SavePublicKey(const OTString &strPath) const
EXPORT bool SaveContract()
EXPORT const OTAsymmetricKey & GetPrivateAuthKey(const OTString::List *plistRevokedIDs=nullptr) const
EXPORT void GetFilename(OTString &strFilename) const
Definition: OTContract.cpp:307
EXPORT bool VerifyIssuedNum(const OTString &strServerID, const int64_t &lTransNum) const
EXPORT void AddOutmail(OTMessage &theMessage)
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
EXPORT bool AddNewSubkey(int32_t nBits=1024, const OTString::Map *pmapPrivate=nullptr, const OTPasswordData *pPWData=nullptr, OTSubkey **ppSubkey=nullptr)
static EXPORT const OTString & Pubkey()
Definition: OTFolders.cpp:347
EXPORT bool SaveAndReloadBothKeysFromTempFile(OTString *pstrOutputCert=nullptr, const OTString *pstrReason=nullptr, const OTPassword *pImportPassword=nullptr)
Definition: OTKeypair.cpp:333
EXPORT bool GetNextTransactionNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, int64_t &lTransNum, bool bSave=true)
EXPORT bool VerifyTentativeNum(const OTString &strServerID, const int64_t &lTransNum) const
static EXPORT const OTString & Nym()
Definition: OTFolders.cpp:327
EXPORT bool SetCertificate(const OTString &strCert, bool bEscaped=true)
EXPORT bool RemoveOutmailByIndex(int32_t nIndex)
EXPORT bool SavePseudonymWallet(OTString &strOutput) const
EXPORT const OTAsymmetricKey & GetPublicEncrKey() const
EXPORT bool LoadBothKeysFromCertFile(const OTString &strFoldername, const OTString &strFilename, const OTString *pstrReason=nullptr, const OTPassword *pImportPassword=nullptr)
Definition: OTKeypair.cpp:456
EXPORT int64_t GetTransactionNum(const OTIdentifier &theServerID, int32_t nIndex) const
EXPORT bool GetInboxHash(const std::string &acct_id, OTIdentifier &theOutput) const
EXPORT void GetPrivateCredentials(OTString &strCredList, OTString::Map *pmapCredFiles=nullptr)
OTLOG_IMPORT OTLogStream otOut
EXPORT bool HasPublicKey()
Definition: OTKeypair.cpp:213
EXPORT bool Server_PubKeyExists(OTString *pstrID=nullptr)
std::map< std::string, OTIdentifier > mapOfIdentifiers
EXPORT bool SaveFile()
EXPORT bool RemoveGenericNum(mapOfTransNums &THE_MAP, OTPseudonym &SIGNER_NYM, const OTString &strServerID, const int64_t &lTransNum)
EXPORT bool ReEncryptPrivateCredentials(bool bImporting, const OTPasswordData *pPWData=nullptr, const OTPassword *pImportPassword=nullptr)
OTLOG_IMPORT OTLogStream otLog3
bool RemoveTentativeNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, const int64_t &lTransNum, bool bSave)
EXPORT void SetAttachment(const OTString &theStr)
Definition: OTItem.cpp:1402
EXPORT void AddOutpayments(OTMessage &theMessage)
EXPORT bool Peek(int64_t &lPeek) const
Definition: OTNumList.cpp:285
EXPORT uint32_t GetLength() const
Definition: OTString.cpp:1040
EXPORT bool GetRecentHash(const std::string &server_id, OTIdentifier &theOutput) const
EXPORT bool AddTentativeNum(const OTString &strServerID, const int64_t &lTransNum)
EXPORT bool AddNewSubkey(const OTIdentifier &idMasterCredential, int32_t nBits=1024, const OTString::Map *pmapPrivate=nullptr, const OTPasswordData *pPWData=nullptr, OTString *pstrNewID=nullptr)
EXPORT bool LoadSignedNymfile(OTPseudonym &SIGNER_NYM)
EXPORT void SerializeNymIDSource(OTString &strOutput) const
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
EXPORT void SetNymboxHashServerSide(const OTIdentifier &theInput)
EXPORT bool WriteArmoredString(OTString &strOutput, const std::string str_type, bool bEscaped=false) const
EXPORT int32_t GetTransactionNumCount(const OTIdentifier &theServerID) const
EXPORT bool LoadNymbox()
Definition: OTLedger.cpp:482
static OTCredential * CreateMaster(const OTString &strSourceForNymID, int32_t nBits=1024, const OTString::Map *pmapPrivate=nullptr, const OTString::Map *pmapPublic=nullptr, const OTPasswordData *pPWData=nullptr)
EXPORT bool ReEncryptPrivateCredentials(const OTPassword &theExportPassword, bool bImporting)
EXPORT void HarvestIssuedNumbers(const OTIdentifier &theServerID, OTPseudonym &SIGNER_NYM, OTPseudonym &theOtherNym, bool bSave=false)
EXPORT bool VerifyPseudonym() const
static EXPORT OTItem * CreateItemFromTransaction(const OTTransaction &theOwner, OTItem::itemType theType, const OTIdentifier *pDestinationAcctID=nullptr)
Definition: OTItem.cpp:1451
static OTCredential * LoadMaster(const OTString &strNymID, const OTString &strMasterCredID, const OTPasswordData *pPWData=nullptr)
EXPORT void Initialize()
EXPORT bool DecodeIfArmored(bool escapedIsAllowed=true)
Definition: OTString.cpp:1212
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT bool SetString(const OTString &theData, bool bLineBreaks=true)
EXPORT int64_t GetGenericNum(const mapOfTransNums &THE_MAP, const OTIdentifier &theServerID, int32_t nIndex) const
std::map< std::string, dequeOfTransNums * > mapOfTransNums
EXPORT void SetString(const char *szString)
EXPORT void SetIdentifier(const OTIdentifier &theIdentifier)
EXPORT int32_t GetMailCount() const
return the number of mail items available for this Nym.
EXPORT const OTCredential * GetRevokedCredentialByIndex(int32_t nIndex) const
EXPORT void ClearOutpayments()
EXPORT bool SetPublicKey(const OTASCIIArmor &strKey)
Definition: OTKeypair.cpp:526
EXPORT void Format(const char *fmt,...)
Definition: OTString.cpp:1319
EXPORT bool AddNewSubcredential(const OTString::Map &mapPrivate, const OTString::Map &mapPublic, const OTPasswordData *pPWData=nullptr, OTSubcredential **ppSubcred=nullptr)
EXPORT int32_t GetOutpaymentsCount() const
return the number of payments items available for this Nym.
EXPORT bool LoadPublicKey()
EXPORT bool Savex509CertAndPrivateKeyToString(OTString &strOutput, const OTString *pstrReason=nullptr)
EXPORT void ClearOutmail()
static EXPORT const OTString & Credential()
Definition: OTFolders.cpp:307
static EXPORT OTPassword * GetPassphraseFromUser(const OTString *pstrDisplay=nullptr, bool bAskTwice=false)
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
EXPORT bool GetHighestNum(const OTString &strServerID, int64_t &lHighestNum) const
EXPORT int32_t GetTentativeNumCount(const OTIdentifier &theServerID) const
EXPORT bool RemoveTransactionNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, const int64_t &lTransNum)
const OTIdentifier & GetPurportedServerID() const
EXPORT const OTString & GetMasterCredID() const
#define CLEAR_MAP_AND_DEQUE(the_map)
EXPORT void Set(const char *data, uint32_t enforcedMaxLength=0)
Definition: OTString.cpp:1055
EXPORT bool VerifyTransactionStatementNumbersOnNym(OTPseudonym &THE_NYM)
EXPORT bool GenerateNym(int32_t nBits=1024, bool bCreateFile=true, std::string str_id_source="", std::string str_alt_location="")
EXPORT bool Loadx509CertAndPrivateKey(bool bChecking=false, const OTPasswordData *pPWData=nullptr, const OTPassword *pImportPassword=nullptr)
EXPORT void SaveCredentialListToString(OTString &strOutput)
EXPORT bool AddTransactionNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, int64_t lTransNum, bool bSave)
EXPORT void SaveCredentialsToString(OTString &strOutput, OTString::Map *pmapPubInfo=nullptr, OTString::Map *pmapPriInfo=nullptr)
EXPORT bool CalculateID(OTIdentifier &theOutput) const
Definition: OTKeypair.cpp:643
EXPORT std::string QueryPlainString(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:728
EXPORT int64_t GetTentativeNum(const OTIdentifier &theServerID, int32_t nIndex) const
static EXPORT bool LoadEncodedTextField(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
EXPORT const OTAsymmetricKey & GetPublicAuthKey() const
EXPORT bool SetIdentifierByPubkey()
EXPORT bool Output(std::set< int64_t > &theOutput) const
Definition: OTNumList.cpp:430
EXPORT bool GetCurrentRequestNum(const OTString &strServerID, int64_t &lReqNum) const
EXPORT int64_t UpdateHighestNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, std::set< int64_t > &setNumbers, std::set< int64_t > &setOutputGood, std::set< int64_t > &setOutputBad, bool bSave=false)
EXPORT bool RemoveIssuedNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, const int64_t &lTransNum, bool bSave)
EXPORT int32_t GetPublicKeysBySignature(listOfAsymmetricKeys &listOutput, const OTSignature &theSignature, char cKeyType= '0') const
std::deque< int64_t > dequeOfTransNums
#define OT_PW_DISPLAY
Definition: OTCallback.hpp:164
EXPORT bool VerifyGenericNum(const mapOfTransNums &THE_MAP, const OTString &strServerID, const int64_t &lTransNum) const
const OTAsymmetricKey & GetPrivateAuthKey() const
EXPORT void SetNymIDSource(const OTString &strSource)
const OTAsymmetricKey & GetPrivateEncrKey() const
EXPORT int32_t GetOutmailCount() const
return the number of mail items available for this Nym.
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT OTMessage * GetOutmailByIndex(int32_t nIndex) const
EXPORT void ReleaseTransactionNumbers()
EXPORT bool AddNewSubcredential(const OTIdentifier &idMasterCredential, const OTString::Map *pmapPrivate=nullptr, const OTString::Map *pmapPublic=nullptr, const OTPasswordData *pPWData=nullptr)
static OTCredential * LoadMasterFromString(const OTString &strInput, const OTString &strNymID, const OTString &strMasterCredID, OTPasswordData *pPWData=nullptr, const OTPassword *pImportPassword=nullptr)
EXPORT bool RemoveMailByIndex(int32_t nIndex)
EXPORT bool SetOutboxHash(const std::string &acct_id, const OTIdentifier &theInput)
EXPORT bool HasPublicKey()
EXPORT bool AddAcknowledgedNum(const OTString &strServerID, const int64_t &lRequestNum)
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
EXPORT bool RemoveAcknowledgedNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, const int64_t &lRequestNum, bool bSave)
EXPORT void SetAltLocation(const OTString &strLocation)
mapOfTransNums & GetMapIssuedNum()
OTLOG_IMPORT OTLogStream otInfo
EXPORT bool CompareID(const OTIdentifier &theIdentifier) const
EXPORT bool LoadPublicKeyFromCertString(const OTString &strCert, bool bEscaped=true, const OTString *pstrReason=nullptr, const OTPassword *pImportPassword=nullptr)
Definition: OTKeypair.cpp:409
static EXPORT OTPseudonym * LoadPrivateNym(const OTIdentifier &NYM_ID, bool bChecking=false, const OTString *pstrName=nullptr, const char *szFuncName=nullptr, const OTPasswordData *pPWData=nullptr, const OTPassword *pImportPassword=nullptr)
EXPORT int32_t Count() const
Definition: OTNumList.cpp:460
EXPORT bool IsRegisteredAtServer(const OTString &strServerID) const
EXPORT const OTAsymmetricKey & GetPrivateKey() const
Definition: OTKeypair.cpp:236
virtual EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
Definition: OTContract.cpp:317
EXPORT bool AddGenericNum(mapOfTransNums &THE_MAP, const OTString &strServerID, int64_t lTransNum)
EXPORT const OTAsymmetricKey & GetPublicAuthKey(const OTString::List *plistRevokedIDs=nullptr) const
#define OT_FAIL
Definition: Assert.hpp:139
EXPORT OTCredential * GetRevokedCredential(const OTString &strID)
EXPORT bool SetRecentHash(const std::string &server_id, const OTIdentifier &theInput)
EXPORT bool At(uint32_t index, char &c) const
Definition: OTString.cpp:1025
virtual EXPORT ~OTPseudonym()
EXPORT const OTAsymmetricKey & GetPublicSignKey() const
EXPORT bool GetNymboxHash(const std::string &server_id, OTIdentifier &theOutput) const
EXPORT bool Loadx509CertAndPrivateKeyFromString(const OTString &strInput, const OTPasswordData *pPWData=nullptr, const OTPassword *pImportPassword=nullptr)
EXPORT int64_t GetReferenceToNum() const
EXPORT bool GetOutboxHash(const std::string &acct_id, OTIdentifier &theOutput) const
EXPORT size_t GetSubcredentialCount() const
EXPORT bool HasPrivateKey()
OTLOG_IMPORT OTLogStream otWarn
EXPORT int32_t GetGenericNumCount(const mapOfTransNums &THE_MAP, const OTIdentifier &theServerID) const
EXPORT bool SavePseudonym()
EXPORT int32_t GetAcknowledgedNumCount(const OTIdentifier &theServerID) const
EXPORT const char * Get() const
Definition: OTString.cpp:1045
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
Definition: OTContract.cpp:484
transactionType GetType() const
EXPORT const OTAsymmetricKey & GetPublicEncrKey(const OTString::List *plistRevokedIDs=nullptr) const
OTLOG_IMPORT OTLogStream otErr
EXPORT const OTString & GetSourceForNymID() const
EXPORT int64_t GetTransactionNum() const
EXPORT void DisplayStatistics(OTString &strOutput)
EXPORT bool SetPrivateKey(const OTString &strKey, bool bEscaped=false)
Definition: OTKeypair.cpp:588
EXPORT void OnUpdateRequestNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID, int64_t lNewRequestNumber)
EXPORT const OTCredential * GetMasterCredentialByIndex(int32_t nIndex) const
EXPORT bool GetNymboxHashServerSide(const OTIdentifier &theServerID, OTIdentifier &theOutput)
EXPORT size_t GetRevokedCredentialCount() const
EXPORT const OTMasterkey & GetMasterkey() const
EXPORT bool HasPrivateKey()
Definition: OTKeypair.cpp:221
EXPORT bool SaveCertAndPrivateKeyToString(OTString &strOutput, const OTString *pstrReason=nullptr, const OTPassword *pImportPassword=nullptr)
Definition: OTKeypair.cpp:277
EXPORT bool RemoveOutpaymentsByIndex(int32_t nIndex, bool bDeleteIt=true)
EXPORT void RemoveReqNumbers(const OTString *pstrServerID=nullptr)
EXPORT void AddMail(OTMessage &theMessage)
EXPORT void GetString(OTString &theStr) const
virtual EXPORT bool VerifySignature(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
Definition: OTContract.cpp:818
EXPORT bool Pop()
Definition: OTNumList.cpp:297
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
EXPORT bool LoadPublicKey(const OTString &strFoldername, const OTString &strFilename)
Definition: OTKeypair.cpp:384
EXPORT bool SaveCredentialList()
#define OT_MAX_ACK_NUMS
EXPORT bool ResyncWithServer(const OTLedger &theNymbox, const OTPseudonym &theMessageNym)
EXPORT int64_t GetAcknowledgedNum(const OTIdentifier &theServerID, int32_t nIndex) const
static EXPORT const OTString & Cert()
Definition: OTFolders.cpp:299
EXPORT bool IsEmpty() const
Definition: OTData.cpp:291
const OTAsymmetricKey & GetPrivateSignKey() const
const OTIdentifier & GetUserID() const
EXPORT bool CertfileExists()
EXPORT bool GetString(OTString &theData, bool bLineBreaks=true) const
EXPORT bool LoadContractFromString(const OTString &theStr)
EXPORT void RemoveAllNumbers(const OTString *pstrServerID=nullptr, bool bRemoveHighestNum=true)
EXPORT const OTAsymmetricKey & GetPrivateEncrKey(const OTString::List *plistRevokedIDs=nullptr) const
EXPORT const OTAsymmetricKey & GetPrivateSignKey(const OTString::List *plistRevokedIDs=nullptr) const
EXPORT void SerializeIDs(OTString &strOutput, const OTString::List &listRevokedIDs, OTString::Map *pmapPubInfo=nullptr, OTString::Map *pmapPriInfo=nullptr, bool bShowRevoked=false, bool bValid=true) const
EXPORT bool LoadCredentials(bool bLoadPrivate=false, const OTPasswordData *pPWData=nullptr, const OTPassword *pImportPassword=nullptr)
EXPORT int64_t GetIssuedNum(const OTIdentifier &theServerID, int32_t nIndex) const
EXPORT const OTSubcredential * GetRevokedSubcred(const OTString &strRevokedID, const OTString &strSubCredID) const
EXPORT bool Savex509CertAndPrivateKey(bool bCreateFile=true, const OTString *pstrReason=nullptr)
EXPORT bool VerifyAgainstSource() const
EXPORT OTMessage * GetOutpaymentsByIndex(int32_t nIndex) const
EXPORT size_t GetMasterCredentialCount() const
EXPORT bool VerifyInternally() const
EXPORT bool MakeNewKeypair(int32_t nBits=1024)
Definition: OTKeypair.cpp:430
std::map< std::string, OTCredential * > mapOfCredentials
EXPORT bool AddIssuedNum(const OTString &strServerID, const int64_t &lTransNum)
EXPORT bool AddNewMasterCredential(OTString &strOutputMasterCredID, const OTString *pstrSourceForNymID=nullptr, int32_t nBits=1024, const OTString::Map *pmapPrivate=nullptr, const OTString::Map *pmapPublic=nullptr, const OTPasswordData *pPWData=nullptr, bool bChangeNymID=false)
static EXPORT void vOutput(int32_t nVerbosity, const char *szOutput,...)
Definition: OTLog.cpp:768
virtual EXPORT void Release()
Definition: OTString.cpp:765
EXPORT bool VerifyAcknowledgedNum(const OTString &strServerID, const int64_t &lRequestNum) const
void WriteToFile(std::ostream &ofs) const
Definition: OTString.cpp:1364
EXPORT const std::string GetSubcredentialIDByIndex(size_t nIndex) const
const OTIdentifier & GetRealServerID() const
EXPORT bool UnRegisterAtServer(const OTString &strServerID)
EXPORT OTMessage * GetMailByIndex(int32_t nIndex) const
EXPORT bool VerifyTransactionNum(const OTString &strServerID, const int64_t &lTransNum) const
EXPORT bool SaveSignedNymfile(OTPseudonym &SIGNER_NYM)
EXPORT bool LoadNymfile(const char *szFilename=nullptr)
EXPORT int32_t GetPublicKeysBySignature(listOfAsymmetricKeys &listOutput, const OTSignature &theSignature, char cKeyType= '0') const
EXPORT void IncrementRequestNum(OTPseudonym &SIGNER_NYM, const OTString &strServerID)
OTLOG_IMPORT OTLogStream otLog5
EXPORT bool LoadFile()
EXPORT const mapOfTransactions & GetTransactionMap() const
Definition: OTLedger.cpp:1160