Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTServer.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTServer.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 "OTServer.hpp"
134 #include "ClientConnection.hpp"
135 #include "ConfigLoader.hpp"
136 #include "Macros.hpp"
137 #include "ServerSettings.hpp"
138 #include "PayDividendVisitor.hpp"
139 #include "Helpers.hpp"
140 
141 #include <opentxs/ext/OTPayment.hpp>
142 #include <opentxs/cash/Purse.hpp>
143 #include <opentxs/cash/Token.hpp>
144 #include <opentxs/basket/Basket.hpp>
149 #include <opentxs/core/OTCheque.hpp>
154 #include <opentxs/core/OTLedger.hpp>
155 #include <opentxs/core/OTLog.hpp>
168 
169 #include <irrxml/irrXML.hpp>
170 
171 #include <string>
172 #include <map>
173 #include <memory>
174 #include <fstream>
175 #include <time.h>
176 
177 #ifndef WIN32
178 #include <unistd.h>
179 #endif
180 
181 #define SERVER_CONFIG_KEY "server"
182 #define SERVER_DATA_DIR "server_data"
183 #define SERVER_LOGFILE_FILENAME "log-server.log"
184 #define SERVER_PASSWORD_FOLDER ""
185 #define SERVER_PID_FILENAME "ot.pid"
186 
187 namespace opentxs
188 {
189 
190 namespace
191 {
192 
193 void askInteractively(std::string& strContract, std::string& strServerID,
194  std::string& strCert, std::string& strNymID,
195  std::string& strCachedKey)
196 {
197  const char* szInstructions =
198  "\n\n ==> WARNING: Main file not found. To create it, continue this "
199  "process now...\n\n"
200  "REQUIREMENTS: You must already have a wallet, where you have created "
201  "one Nym.\n"
202  "This will be a temporary wallet only, for the purpose of generating "
203  "the server\n"
204  "nym and the master key for that server nym. You can erase the "
205  "contents of the\n"
206  "~/.ot/client_data folder once we are done with this process, and the "
207  "OT client\n"
208  "will just create a fresh wallet to replace it. In other words, don't "
209  "continue\n"
210  "to use the temporary wallet as a REAL wallet, since it contains the "
211  "master\n"
212  "key and private key for your new server nym. We're using a temporary "
213  "client-side\n"
214  "wallet for the convenience of generating the server nym--we'll copy "
215  "it over to \n"
216  "the server side, and then we'll wipe the temp wallet and start with a "
217  "fresh one\n"
218  "once this process is done.\n"
219  "(FYI, you can decode an armored wallet by using the 'opentxs decode' "
220  "command.)\n"
221  "-- You must also have the new Server Nym's \"NymID\", which should be "
222  "found in the\nwallet.\n"
223  "-- When you have created your server Nym (using your temp wallet) you "
224  "will want to\n"
225  "copy the credentials from the temp wallet to your new server:\n"
226  " cp -R ~/.ot/client_data/credentials ~/.ot/server_data/ \n"
227  "-- You must already have a signed server contract. (*** To get one, "
228  "copy the\n"
229  "UNSIGNED version of the sample server contract, which is named "
230  "'localhost.xml',\n"
231  "and then change the tags as you see fit. Then use the same Nym, the "
232  "server Nym,\n"
233  "to sign the server contract, via the 'opentxs newserver' "
234  "command.***)\n"
235  "You must also have the server ID for the above contract, which the "
236  "newserver\n"
237  "command will output at the same time it outputs the newly-signed "
238  "server contract.\n"
239  "=> Note that the Nym who signs the server contract MUST be the same "
240  "Nym that you\n"
241  "provide HERE, for this process now...)\n"
242  "-- Finally, you must provide the cached key from the same wallet "
243  "where you brought\n"
244  "the Nym from (In this case, be careful to only copy the "
245  "base64-encoded portion\n"
246  "of the cached key from the wallet, and not the XML tags around it!) "
247  "We\n"
248  "recommend you create a blank wallet entirely for this purpose (of "
249  "generating\n"
250  "that cached key and server Nym, to be used for your new OT server.) "
251  "Then erase it\nonce this process is done.\n"
252  " ==> WARNING: Main file not found. To create it, continue this "
253  "process now...\n";
254 
255  OTLog::Output(0, szInstructions);
256  OTLog::Output(0, "Enter the ServerID for your server contract: ");
257  strServerID = OT_CLI_ReadLine();
258  OTLog::Output(0, "Enter the Server User ID (the NymID of the Nym who "
259  "signed the server contract): ");
260  strNymID = OT_CLI_ReadLine();
261  OTLog::Output(0, "Paste the cached key (ONLY the base64-encoded portion) "
262  "below, from wallet.xml for that Nym.\n"
263  "Terminate with '~' on a line by itself.\n\n");
264 
265  strCachedKey = OT_CLI_ReadUntilEOF();
266  OTLog::Output(0, "Paste the contents of the server Nym's certfile, "
267  "including public/PRIVATE, below.\n"
268  "NOTE: LEAVE THIS BLANK unless you REALLY want to use the "
269  "OLD system. If you leave this\n"
270  "blank (preferred), it will instead use the new "
271  "credentials system. (Just make sure\n"
272  "you copied over the \"credentials\" folder, as described "
273  "above, since we're about to\n"
274  "use it, if you leave this blank.)\n"
275  "Terminate with '~' on a line by itself.\n\n");
276 
277  strCert = OT_CLI_ReadUntilEOF();
278  // signed server contract
279  OTLog::Output(0, "Paste the complete, signed, server contract below. (You "
280  "must already have it.)\n"
281  "Terminate with '~' on a line by itself.\n\n");
282 
283  strContract = OT_CLI_ReadUntilEOF();
284 }
285 
286 } // namespace
287 
288 #ifdef _WIN32
289 int32_t OTCron::__trans_refill_amount =
290  500; // The number of transaction numbers Cron will grab for itself, when it
291  // gets low, before each round.
292 int32_t OTCron::__cron_ms_between_process = 10000; // The number of milliseconds
293  // (ideally) between each
294  // "Cron Process" event.
295 int32_t OTCron::__cron_max_items_per_nym = 10; // The maximum number of cron
296 // items any given Nym can have
297 // active at the same time.
298 #endif
299 
301 {
302  OTLog::vOutput(1, "OTServer::ActivateCron: %s \n",
303  m_Cron.ActivateCron() ? "(STARTED)" : "FAILED");
304 }
305 
312 {
313  if (!m_Cron.IsActivated()) return;
314 
315  bool bAddedNumbers = false;
316 
317  // Cron requires transaction numbers in order to process.
318  // So every time before I call Cron.Process(), I make sure to replenish
319  // first.
320  while (m_Cron.GetTransactionCount() < OTCron::GetCronRefillAmount()) {
321  int64_t lTransNum = 0;
322  bool bSuccess = transactor_.issueNextTransactionNumber(
323  m_nymServer, lTransNum, false);
324 
325  if (bSuccess) {
326  m_Cron.AddTransactionNumber(lTransNum);
327  bAddedNumbers = true;
328  }
329  else
330  break;
331  }
332 
333  if (bAddedNumbers) {
334  m_Cron.SaveCron();
335  }
336 
337  m_Cron.ProcessCronItems(); // This needs to be called regularly for trades,
338  // markets, payment plans, etc to process.
339 
340  // NOTE: TODO: OTHER RE-OCCURRING SERVER FUNCTIONS CAN GO HERE AS WELL!!
341  //
342  // Such as sweeping server accounts after expiration dates, etc.
343 }
344 
346 {
347  return m_nymServer;
348 }
349 
351 {
352  return m_bShutdownFlag;
353 }
354 
356  : mainFile_(this)
357  , notary_(this)
358  , transactor_(this)
359  , userCommandProcessor_(this)
360  , m_bReadOnly(false)
361  , m_bShutdownFlag(false)
362  , m_pServerContract()
363 {
364 }
365 
367 {
368  // PID -- Set it to 0 in the lock file so the next time we run OT, it knows
369  // there isn't
370  // another copy already running (otherwise we might wind up with two copies
371  // trying to write
372  // to the same data folder simultaneously, which could corrupt the data...)
373  //
374  // OTLog::vError("m_strDataPath: %s\n", m_strDataPath.Get());
375  // OTLog::vError("SERVER_PID_FILENAME: %s\n", SERVER_PID_FILENAME);
376 
377  OTString strDataPath;
378  const bool bGetDataFolderSuccess = OTDataFolder::Get(strDataPath);
379  if (!m_bReadOnly && bGetDataFolderSuccess) {
380  OTString strPIDPath;
381  OTPaths::AppendFile(strPIDPath, strDataPath, SERVER_PID_FILENAME);
382 
383  std::ofstream pid_outfile(strPIDPath.Get());
384 
385  if (pid_outfile.is_open()) {
386  uint32_t the_pid = 0;
387  pid_outfile << the_pid;
388  pid_outfile.close();
389  }
390  else
391  OTLog::vError("Failed trying to open data locking file (to wipe "
392  "PID back to 0): %s\n",
393  strPIDPath.Get());
394  }
395 }
396 
397 void OTServer::Init(bool readOnly)
398 {
399  m_bReadOnly = readOnly;
400 
402  OTLog::vError("Unable to Init data folders!");
403  OT_FAIL;
404  }
405  if (!ConfigLoader::load(m_strWalletFilename)) {
406  OTLog::vError("Unable to Load Config File!");
407  OT_FAIL;
408  }
409 
410  OTString dataPath;
411  bool bGetDataFolderSuccess = OTDataFolder::Get(dataPath);
412 
413  // PID -- Make sure we're not running two copies of OT on the same data
414  // simultaneously here.
415  if (bGetDataFolderSuccess) {
416  // If we want to WRITE to the data location, then we can't be in
417  // read-only mode.
418  if (!readOnly) {
419  // 1. READ A FILE STORING THE PID. (It will already exist, if OT is
420  // already running.)
421  //
422  // We open it for reading first, to see if it already exists. If it
423  // does, we read the number. 0 is fine, since we overwrite with 0 on
424  // shutdown. But any OTHER number means OT is still running. Or it
425  // means it was killed while running and didn't shut down properly,
426  // and that you need to delete the pid file by hand before running
427  // OT again. (This is all for the purpose of preventing two copies
428  // of OT running at the same time and corrupting the data folder.)
429  //
430  OTString strPIDPath;
431  OTPaths::AppendFile(strPIDPath, dataPath, SERVER_PID_FILENAME);
432 
433  std::ifstream pid_infile(strPIDPath.Get());
434 
435  // 2. (IF FILE EXISTS WITH ANY PID INSIDE, THEN DIE.)
436  if (pid_infile.is_open()) {
437  uint32_t old_pid = 0;
438  pid_infile >> old_pid;
439  pid_infile.close();
440 
441  // There was a real PID in there.
442  if (old_pid != 0) {
443  uint64_t lPID = old_pid;
445  "\n\n\nIS OPEN-TRANSACTIONS ALREADY RUNNING?\n\n"
446  "I found a PID (%llu) in the data lock file, located "
447  "at: %s\n\n"
448  "If the OT process with PID %llu is truly not running "
449  "anymore, "
450  "then just ERASE THAT FILE and then RESTART.\n",
451  lPID, strPIDPath.Get(), lPID);
452  exit(-1);
453  }
454  // Otherwise, though the file existed, the PID within was 0.
455  // (Meaning the previous instance of OT already set it to 0 as
456  // it was shutting down.)
457  }
458  // Next let's record our PID to the same file, so other copies of OT
459  // can't trample on US.
460 
461  // 3. GET THE CURRENT (ACTUAL) PROCESS ID.
462  uint64_t the_pid = 0;
463 
464 #ifdef _WIN32
465  the_pid = GetCurrentProcessId();
466 #else
467  the_pid = getpid();
468 #endif
469 
470  // 4. OPEN THE FILE IN WRITE MODE, AND SAVE THE PID TO IT.
471  std::ofstream pid_outfile(strPIDPath.Get());
472 
473  if (pid_outfile.is_open()) {
474  pid_outfile << the_pid;
475  pid_outfile.close();
476  }
477  else {
478  OTLog::vError("Failed trying to open data locking file (to "
479  "store PID %llu): %s\n",
480  the_pid, strPIDPath.Get());
481  }
482  }
483  }
485 
486  // Load up the transaction number and other OTServer data members.
487  bool mainFileExists = m_strWalletFilename.Exists()
488  ? OTDB::Exists(".", m_strWalletFilename.Get())
489  : false;
490 
491  if (!mainFileExists) {
492  if (readOnly) {
494  "Error: Main file non-existent (%s). "
495  "Plus, unable to create, since read-only flag is set.\n",
496  m_strWalletFilename.Get());
497  OT_FAIL;
498  }
499  else {
500  std::string strContract;
501  std::string strServerID;
502  std::string strCert;
503  std::string strNymID;
504  std::string strCachedKey;
505  askInteractively(strContract, strServerID, strCert, strNymID,
506  strCachedKey);
507  mainFileExists = mainFile_.CreateMainFile(
508  strContract, strServerID, strCert, strNymID, strCachedKey);
509  }
510  }
511 
512  if (mainFileExists) {
513  if (!mainFile_.LoadMainFile(readOnly)) {
514  OTLog::vError("Error in Loading Main File!\n");
515  OT_FAIL;
516  }
517  }
518 
519  // With the Server's private key loaded, and the latest transaction number
520  // loaded, and all the various other data (contracts, etc) the server is now
521  // ready for operation!
522 }
523 
524 // msg, the request msg from payer, which is attached WHOLE to the Nymbox
525 // receipt. contains payment already.
526 // or pass pPayment instead: we will create our own msg here (with payment
527 // inside) to be attached to the receipt.
528 // szCommand for passing payDividend (as the message command instead of
529 // sendUserInstrument, the default.)
530 bool OTServer::SendInstrumentToNym(
531  const OTIdentifier& SERVER_ID, const OTIdentifier& SENDER_USER_ID,
532  const OTIdentifier& RECIPIENT_USER_ID,
533  OTMessage* pMsg, // the request msg from payer, which is attached
534  // WHOLE to the Nymbox receipt. contains payment
535  // already.
536  const OTPayment* pPayment, // or pass this instead: we will create
537  // our own msg here (with message
538  // inside) to be attached to the
539  // receipt.
540  const char* szCommand)
541 {
543  !((nullptr == pMsg) && (nullptr == pPayment)),
544  "pMsg and pPayment -- these can't BOTH be nullptr.\n"); // must provide
545  // one
546  // or the other.
548  !((nullptr != pMsg) && (nullptr != pPayment)),
549  "pMsg and pPayment -- these can't BOTH be not-nullptr.\n"); // can't
550  // provide
551  // both.
552  OT_ASSERT_MSG((nullptr == pPayment) ||
553  ((nullptr != pPayment) && pPayment->IsValid()),
554  "OTServer::SendInstrumentToNym: You can only pass a valid "
555  "payment here.");
556  // If a payment was passed in (for us to use it to construct pMsg, which is
557  // nullptr in the case where payment isn't nullptr)
558  // Then we grab it in string form, so we can pass it on...
559  OTString strPayment;
560  if (nullptr != pPayment) {
561  const bool bGotPaymentContents =
562  pPayment->GetPaymentContents(strPayment);
563  if (!bGotPaymentContents)
564  OTLog::vError("%s: Error GetPaymentContents Failed", __FUNCTION__);
565  }
566  const bool bDropped = DropMessageToNymbox(
567  SERVER_ID, SENDER_USER_ID, RECIPIENT_USER_ID,
569  (nullptr != pMsg) ? nullptr : &strPayment, szCommand);
570 
571  return bDropped;
572 }
573 
574 // Can't be static (transactor_.issueNextTransactionNumber is called...)
575 //
576 // About pMsg...
577 // (Normally) when you send a cheque to someone, you encrypt it inside an
578 // envelope, and that
579 // envelope is attached to a OTMessage (sendUserInstrument) and sent to the
580 // server. The server
581 // takes your entire OTMessage and attaches it to an instrumentNotice
582 // (OTTransaction) which is
583 // added to the recipient's Nymbox.
584 // In that case, just pass the pointer to the incoming message here as pMsg, and
585 // the OT Server
586 // will attach it as described.
587 // But let's say you are paying a dividend. The server can't just attach your
588 // dividend request in
589 // that case. Normally the recipient's cheque is already in the request. But
590 // with a dividend, there
591 // could be a thousand recipients, and their individual vouchers are only
592 // generated and sent AFTER
593 // the server receives the "pay dividend" request.
594 // Therefore in that case, nullptr would be passed for pMsg, meaning that inside
595 // this function we have
596 // to generate our own OTMessage "from the server" instead of "from the sender".
597 // After all, the server's
598 // private key is the only signer we have in here. And the recipient will be
599 // expecting to have to
600 // open a message, so we must create one to give him. So if pMsg is nullptr,
601 // then
602 // this function will
603 // create a message "from the server", containing the instrument, and drop it
604 // into the recipient's nymbox
605 // as though it were some incoming message from a normal user.
606 // This message, in the case of payDividend, should be an "@payDividend"
607 // message, "from" the server
608 // and "to" the recipient. The payment instrument must be attached to that new
609 // message, and therefore it
610 // must be passed into this function.
611 // Of course, if pMsg was not nullptr, that means the message (and instrument
612 // inside of it) already exist,
613 // so no instrument would need to be passed. But if pMsg IS nullptr, that means
614 // the
615 // msg must be generated,
616 // and thus the instrument MUST be passed in, so that that can be done.
617 // Therefore the instrument will sometimes be passed in, and sometimes not.
618 // Therefore the instrument must
619 // be passed as a pointer.
620 //
621 // Conclusion: if pMsg is passed in, then pass a null instrument. (Since the
622 // instrument is already on pMsg.)
623 // (And since the instrument defaults to nullptr, this makes pMsg
624 // the final argument in the call.)
625 // but if pMsg is nullptr, then you must pass the payment instrument as
626 // the
627 // next argument. (So pMsg can be created with it.)
628 // Note: you cannot pass BOTH, or the instrument will simply be ignored, since
629 // it's already assumed to be in pMsg.
630 // You might ask: what about the original request then, doesn't the recipient
631 // get a copy of that? Well, maybe we
632 // pass it in here and attach it to the new message. Or maybe we just set it as
633 // the voucher memo.
634 //
635 bool OTServer::DropMessageToNymbox(const OTIdentifier& SERVER_ID,
636  const OTIdentifier& SENDER_USER_ID,
637  const OTIdentifier& RECIPIENT_USER_ID,
639  OTMessage* pMsg, const OTString* pstrMessage,
640  const char* szCommand) // If you pass
641  // something here, it
642  // will
643 // replace pMsg->m_strCommand below
644 {
646  !((nullptr == pMsg) && (nullptr == pstrMessage)),
647  "pMsg and pstrMessage -- these can't BOTH be nullptr.\n"); // must
648  // provide
649  // one or the
650  // other.
652  !((nullptr != pMsg) && (nullptr != pstrMessage)),
653  "pMsg and pstrMessage -- these can't BOTH be not-nullptr.\n"); // can't
654  // provide
655  // both.
656  const char* szFunc = "OTServer::DropMessageToNymbox";
657  int64_t lTransNum = 0;
658  const bool bGotNextTransNum =
659  transactor_.issueNextTransactionNumber(m_nymServer, lTransNum, false);
660 
661  if (!bGotNextTransNum) {
663  "%s: Error: failed trying to get next transaction number.\n");
664  return false;
665  }
666  switch (theType) {
668  break;
670  break;
671  default:
673  "%s: Unexpected transactionType passed here (expected message "
674  "or instrumentNotice.)\n",
675  szFunc);
676  return false;
677  }
678  // If pMsg was not already passed in here, then
679  // create pMsg using pstrMessage.
680  //
681  std::unique_ptr<OTMessage> theMsgAngel;
682 
683  if (nullptr == pMsg) // we have to create it ourselves.
684  {
685  pMsg = new OTMessage;
686  theMsgAngel.reset(pMsg);
687  if (nullptr != szCommand)
688  pMsg->m_strCommand = szCommand;
689  else {
690  switch (theType) {
692  pMsg->m_strCommand = "sendUserMessage";
693  break;
695  pMsg->m_strCommand = "sendUserInstrument";
696  break;
697  default:
698  break; // should never happen.
699  }
700  }
701  pMsg->m_strServerID = m_strServerID;
702  pMsg->m_bSuccess = true;
703  SENDER_USER_ID.GetString(pMsg->m_strNymID);
704  RECIPIENT_USER_ID.GetString(pMsg->m_strNymID2); // set the recipient ID
705  // in pMsg to match our
706  // recipient ID.
707  // Load up the recipient's public key (so we can encrypt the envelope
708  // to him that will contain the payment instrument.)
709  //
710  OTPseudonym nymRecipient(RECIPIENT_USER_ID);
711 
712  bool bLoadedNym =
713  nymRecipient.LoadPublicKey(); // Old style (deprecated.) But this
714  // function calls the new style,
715  // LoadCredentials, at the top.
716  // Eventually we'll just call that
717  // here directly.
718  if (!bLoadedNym) {
720  "%s: Failed trying to load public key for recipient.\n",
721  szFunc);
722  return false;
723  }
724  else if (!nymRecipient.VerifyPseudonym()) {
725  OTLog::vError("%s: Failed trying to verify Nym for recipient.\n",
726  szFunc);
727  return false;
728  }
729  const OTAsymmetricKey& thePubkey = nymRecipient.GetPublicEncrKey();
730  // Wrap the message up into an envelope and attach it to pMsg.
731  //
732  OTEnvelope theEnvelope;
733 
734  pMsg->m_ascPayload.Release();
735 
736  if ((nullptr != pstrMessage) && pstrMessage->Exists() &&
737  theEnvelope.Seal(thePubkey, *pstrMessage) && // Seal pstrMessage
738  // into theEnvelope,
739  // using nymRecipient's
740  // public key.
741  theEnvelope.GetAsciiArmoredData(
742  pMsg->m_ascPayload)) // Grab the sealed version as
743  // base64-encoded string, into
744  // pMsg->m_ascPayload.
745  {
746  pMsg->SignContract(m_nymServer);
747  pMsg->SaveContract();
748  }
749  else {
751  "%s: Failed trying to seal envelope containing message "
752  "(or while grabbing the base64-encoded result.)\n",
753  szFunc);
754  return false;
755  }
756 
757  // By this point, pMsg is all set up, signed and saved. Its payload
758  // contains
759  // the envelope (as base64) containing the encrypted message.
760  }
761  // else // pMsg was passed in, so it's not nullptr. No need to create it
762  // ourselves like above. (pstrMessage should be nullptr anyway in this
763  // case.)
764  // {
765  // // Apparently no need to do anything in here at all.
766  // }
767  // Grab a string copy of pMsg.
768  //
769  const OTString strInMessage(*pMsg);
770  OTLedger theLedger(RECIPIENT_USER_ID, RECIPIENT_USER_ID,
771  SERVER_ID); // The recipient's Nymbox.
772  // Drop in the Nymbox
773  if ((theLedger.LoadNymbox() && // I think this loads the box receipts too,
774  // since I didn't call "LoadNymboxNoVerify"
775  // theLedger.VerifyAccount(m_nymServer) && // This loads
776  // all the Box Receipts, which is unnecessary.
777  theLedger.VerifyContractID() && // Instead, we'll verify the IDs and
778  // Signature only.
779  theLedger.VerifySignature(m_nymServer))) {
780  // Create the instrumentNotice to put in the Nymbox.
781  OTTransaction* pTransaction =
782  OTTransaction::GenerateTransaction(theLedger, theType, lTransNum);
783 
784  if (nullptr != pTransaction) // The above has an OT_ASSERT within, but I
785  // just like to check my pointers.
786  {
787  // NOTE: todo: SHOULD this be "in reference to" itself? The reason,
788  // I assume we are doing this
789  // is because there is a reference STRING so "therefore" there must
790  // be a reference # as well. Eh?
791  // Anyway, it must be understood by those involved that a message is
792  // stored inside. (Which has no transaction #.)
793 
794  pTransaction->SetReferenceToNum(lTransNum); // <====== Recipient
795  // RECEIVES entire
796  // incoming message as
797  // string here, which
798  // includes the sender
799  // user ID,
800  pTransaction->SetReferenceString(
801  strInMessage); // and has an OTEnvelope in the payload. Message
802  // is signed by sender, and envelope is encrypted
803  // to recipient.
804 
805  pTransaction->SignContract(m_nymServer);
806  pTransaction->SaveContract();
807  theLedger.AddTransaction(*pTransaction); // Add the message
808  // transaction to the
809  // nymbox. (It will
810  // cleanup.)
811 
812  theLedger.ReleaseSignatures();
813  theLedger.SignContract(m_nymServer);
814  theLedger.SaveContract();
815  theLedger.SaveNymbox(); // We don't grab the Nymbox hash here, since
816  // nothing important changed (just a message
817  // was sent.)
818 
819  // Any inbox/nymbox/outbox ledger will only itself contain
820  // abbreviated versions of the receipts, including their hashes.
821  //
822  // The rest is stored separately, in the box receipt, which is
823  // created
824  // whenever a receipt is added to a box, and deleted after a receipt
825  // is removed from a box.
826  //
827  pTransaction->SaveBoxReceipt(theLedger);
828 
829  return true;
830  }
831  else // should never happen
832  {
833  const OTString strRecipientUserID(RECIPIENT_USER_ID);
835  "%s: Failed while trying to generate transaction in order to "
836  "add a message to Nymbox: %s\n",
837  szFunc, strRecipientUserID.Get());
838  }
839  }
840  else {
841  const OTString strRecipientUserID(RECIPIENT_USER_ID);
842  OTLog::vError("%s: Failed while trying to load or verify Nymbox: %s\n",
843  szFunc, strRecipientUserID.Get());
844  }
845 
846  return false;
847 }
848 
849 bool OTServer::GetConnectInfo(OTString& strHostname, int32_t& nPort) const
850 {
851  if (!m_pServerContract) return false;
852 
853  return m_pServerContract->GetConnectInfo(strHostname, nPort);
854 }
855 
856 } // namespace opentxs
static EXPORT void vError(const char *szError,...)
Definition: OTLog.cpp:800
EXPORT void AddTransactionNumber(const int64_t &lTransactionNum)
Definition: OTCron.cpp:415
#define SERVER_PID_FILENAME
Definition: OTServer.cpp:185
static EXPORT OTTransaction * GenerateTransaction(const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, transactionType theType, int64_t lTransactionNum=0)
static EXPORT void Output(int32_t nVerbosity, const char *szOutput)
Definition: OTLog.cpp:710
EXPORT bool SaveCron()
Definition: OTCron.cpp:179
bool IsFlaggedForShutdown() const
Definition: OTServer.cpp:350
bool issueNextTransactionNumber(OTPseudonym &nym, int64_t &txNumber, bool storeNumber=true)
Definition: Transactor.cpp:211
#define OTDB_DEFAULT_PACKER
Definition: OTStorage.hpp:167
EXPORT bool InitDefaultStorage(StorageType eStoreType, PackType ePackType)
Definition: OTStorage.cpp:491
bool GetConnectInfo(OTString &hostname, int32_t &port) const
Definition: OTServer.cpp:849
static EXPORT bool IsInitialized()
EXPORT bool Exists() const
Definition: OTString.cpp:1035
static bool load(OTString &walletFilename)
bool LoadMainFile(bool readOnly=false)
Definition: MainFile.cpp:380
EXPORT void Init(bool readOnly=false)
Definition: OTServer.cpp:397
EXPORT void ActivateCron()
Definition: OTServer.cpp:300
EXPORT bool GetPaymentContents(OTString &strOutput) const
Definition: OTPayment.hpp:323
EXPORT void ProcessCronItems()
Definition: OTCron.cpp:648
const OTPseudonym & GetServerNym() const
Definition: OTServer.cpp:345
EXPORT std::string OT_CLI_ReadLine()
Definition: Helpers.hpp:144
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
bool ActivateCron()
Definition: OTCron.hpp:225
#define OT_FAIL
Definition: Assert.hpp:139
EXPORT OTServer()
Definition: OTServer.cpp:355
EXPORT const char * Get() const
Definition: OTString.cpp:1045
bool IsActivated() const
Definition: OTCron.hpp:221
EXPORT bool IsValid() const
Definition: OTPayment.hpp:301
EXPORT int32_t GetTransactionCount() const
Definition: OTCron.cpp:408
EXPORT ~OTServer()
Definition: OTServer.cpp:366
static int32_t GetCronRefillAmount()
Definition: OTCron.hpp:205
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
bool CreateMainFile(const std::string &strContract, const std::string &strServerID, const std::string &strCert, const std::string &strNymID, const std::string &strCachedKey)
Definition: MainFile.cpp:279
#define OTDB_DEFAULT_STORAGE
Definition: OTStorage.hpp:169
static EXPORT bool AppendFile(OTString &out_strPath, const OTString &strBasePath, const OTString &strFileName)
Definition: OTPaths.cpp:1245
EXPORT std::string OT_CLI_ReadUntilEOF()
Definition: Helpers.hpp:156
static EXPORT void vOutput(int32_t nVerbosity, const char *szOutput,...)
Definition: OTLog.cpp:768
static EXPORT OTString Get()