Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTScriptable.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTScriptable.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 "OTScriptable.hpp"
136 #include "OTAgent.hpp"
137 #include "OTBylaw.hpp"
138 #include "OTClause.hpp"
139 #include "OTLog.hpp"
140 #include "OTParty.hpp"
141 #include "OTPartyAccount.hpp"
142 #include "OTPseudonym.hpp"
143 #include "OTSmartContract.hpp"
144 
145 #include <irrxml/irrXML.hpp>
146 
147 #ifdef OT_USE_SCRIPT_CHAI
148 #include "OTScriptChai.hpp"
149 #include <chaiscript/chaiscript.hpp>
150 #ifdef OT_USE_CHAI_STDLIB
151 #include <chaiscript/chaiscript_stdlib.hpp>
152 #endif
153 #endif
154 
155 #include <memory>
156 
157 // CALLBACKS
158 //
159 // The server will call these callbacks, from time to time, and give you the
160 // opportunity to resolve its questions.
161 
162 // This script is called by the server, whenever it wants to know whether a
163 // given party is allowed to execute a specific clause.
164 //
165 #ifndef SCRIPTABLE_CALLBACK_PARTY_MAY_EXECUTE
166 #define SCRIPTABLE_CALLBACK_PARTY_MAY_EXECUTE \
167  "callback_party_may_execute_clause"
168 #endif
169 
170 namespace opentxs
171 {
172 
174 {
175  static char buf[45] = "";
176 
177  if (!strInput.Exists()) {
178  otErr << __FUNCTION__ << ": Failure: Input string is empty.\n";
179  return nullptr;
180  }
181 
182  OTString strContract(strInput);
183 
184  if (!strContract.DecodeIfArmored(false)) // bEscapedIsAllowed=true
185  // by default.
186  {
187  otErr << __FUNCTION__ << ": Input string apparently was encoded and "
188  "then failed decoding. Contents: \n"
189  << strInput << "\n";
190  return nullptr;
191  }
192 
193  // At this point, strContract contains the actual contents, whether they
194  // were originally ascii-armored OR NOT. (And they are also now trimmed,
195  // either way.)
196  //
197  strContract.reset(); // for sgets
198  buf[0] = 0; // probably unnecessary.
199  bool bGotLine = strContract.sgets(buf, 40);
200 
201  if (!bGotLine) return nullptr;
202 
203  OTCronItem* pItem = nullptr;
204 
205  OTString strFirstLine(buf);
206  strContract.reset(); // set the "file" pointer within this string back to
207  // index 0.
208 
209  // Now I feel pretty safe -- the string I'm examining is within
210  // the first 45 characters of the beginning of the contract, and
211  // it will NOT contain the escape "- " sequence. From there, if
212  // it contains the proper sequence, I will instantiate that type.
213  if (!strFirstLine.Exists() || strFirstLine.Contains("- -")) return nullptr;
214 
215  // There are actually two factories that load smart contracts. See
216  // OTCronItem.
217  //
218  else if (strFirstLine.Contains(
219  "-----BEGIN SIGNED SMARTCONTRACT-----")) // this string is 36
220  // chars long.
221  {
222  pItem = new OTSmartContract();
223  OT_ASSERT(nullptr != pItem);
224  }
225 
226  // The string didn't match any of the options in the factory.
227  if (nullptr == pItem) return nullptr;
228 
229  // Does the contract successfully load from the string passed in?
230  if (pItem->LoadContractFromString(strContract))
231  return pItem;
232  else
233  delete pItem;
234 
235  return nullptr;
236 }
237 
238 // virtual
239 void OTScriptable::SetDisplayLabel(const std::string* pstrLabel)
240 {
241  m_strLabel = (nullptr != pstrLabel) ? pstrLabel->c_str() : "";
242 }
243 
244 // VALIDATING IDENTIFIERS IN OTSCRIPTABLE.
245 //
246 // Only alphanumerics are valid, or '_' (underscore)
247 //
248 
250 {
251  return !(isalnum(c) || (c == '_'));
252 }
253 
254 // static
255 bool OTScriptable::ValidateName(std::string str_name)
256 {
257  if (str_name.size() <= 0) {
258  otErr << "OTScriptable::ValidateName: Name has zero size.\n";
259  return false;
260  }
261  else if (find_if(str_name.begin(), str_name.end(),
262  is_ot_namechar_invalid) != str_name.end()) {
263  otErr << "OTScriptable::ValidateName: Name fails validation testing: "
264  << str_name << "\n";
265  return false;
266  }
267 
268  return true;
269 }
270 
271 // OTSmartContract::RegisterOTNativeCallsWithScript OVERRIDES this, but
272 // also calls it.
273 //
275 {
276 #ifdef OT_USE_SCRIPT_CHAI
277  using namespace chaiscript;
278 
279  // In the future, this will be polymorphic.
280  // But for now, I'm forcing things...
281 
282  OTScriptChai* pScript = dynamic_cast<OTScriptChai*>(&theScript);
283 
284  if (nullptr != pScript) {
285  OT_ASSERT(nullptr != pScript->chai)
286 
287  pScript->chai->add(fun(&OTScriptable::GetTime), "get_time");
288 
289  pScript->chai->add(fun(&OTScriptable::CanExecuteClause, this),
290  "party_may_execute_clause");
291  }
292  else
293 #endif // OT_USE_SCRIPT_CHAI
294  {
295  otErr << "OTScriptable::RegisterOTNativeCallsWithScript: Failed "
296  "dynamic casting OTScript to OTScriptChai \n";
297  }
298 }
299 
300 // static
301 std::string OTScriptable::GetTime() // Returns a string, containing seconds as
302  // int32_t. (Time in seconds.)
303 {
304  const time64_t CURRENT_TIME = OTTimeGetCurrentTime();
305  const int64_t lTime = OTTimeGetSecondsFromTime(CURRENT_TIME);
306 
307  OTString strTime;
308  strTime.Format("%lld", lTime);
309  return strTime.Get();
310 }
311 
312 // The server calls this when it wants to know if a certain party is allowed to
313 // execute a specific clause.
314 // This function tries to answer that question by checking for a callback script
315 // called callback_party_may_execute_clause
316 // If the callback exists, then it calls that for the answer. Otherwise the
317 // default return value is: true
318 // Script coders may also call "party_may_execute_clause()" from within a
319 // script, which will call this function,
320 // which will trigger the script callback_party_may_execute_clause(), etc.
321 //
322 bool OTScriptable::CanExecuteClause(std::string str_party_name,
323  std::string str_clause_name)
324 {
325  OTParty* pParty = GetParty(str_party_name);
326  OTClause* pClause = GetClause(str_clause_name);
327 
328  if (nullptr == pParty) {
329  otOut << "OTScriptable::CanExecuteClause: Unable to find this party: "
330  << (str_party_name.size() > 0 ? str_party_name.c_str() : "")
331  << "\n";
332  return false;
333  }
334 
335  if (nullptr == pClause) {
336  otOut << "OTScriptable::CanExecuteClause: Unable to find this clause: "
337  << (str_clause_name.size() > 0 ? str_clause_name.c_str() : "")
338  << "\n";
339  return false;
340  }
341  // Below this point, pParty and pClause are both good.
342 
343  // ...This WILL check to see if pParty has its Opening number verified as
344  // issued.
345  // (If the opening number is > 0 then VerifyPartyAuthorization() is smart
346  // enough to verify it.)
347  //
348  // To KNOW that a party has the right to even ASK the script to cancel a
349  // contract, MEANS that
350  // (1) The party is listed as a party on the contract. (2) The party's copy
351  // of that contract
352  // is signed by the authorizing agent for that party. and (3) The opening
353  // transaction number for
354  // that party is verified as issued for authorizing agent. (2 and 3 are both
355  // performed at the same
356  // time, in VerifyPartyAuthorization(), since the agent may need to be
357  // loaded in order to verify
358  // them.) 1 is already done by this point, as it's performed above.
359  //
360  // Todo: notice this code appears in CanCancelContract() (this function) as
361  // well as
362  // OTScriptable::CanExecuteClause.
363  // Therefore I can see that THIS VERIFICATION CODE WILL GET CALLED EVERY
364  // SINGLE TIME THE SCRIPT
365  // CALLS ANY CLAUSE OR OT NATIVE FUNCTION. Since technically this only
366  // needs to be verified before the
367  // first call, and not for EVERY call during any of a script's runs, I
368  // should probably move this verification
369  // higher, such as each time the OTCronItem triggers, plus each time a party
370  // triggers a clause directly
371  // through the API (server message). As long as those are covered, I will be
372  // able to remove it from here
373  // which should be a significant improvement for performance.
374  // It will be at the bottom of those same functions that
375  // "ClearTemporaryPointers()" should finally be called.
376  //
377  // Also todo: Need to implement MOVE CONSTRUCTORS and MOVE COPY
378  // CONSTRUCTORS all over the place,
379  // once I'm sure C++0x build environments are available for all of the
380  // various OT platforms. That should
381  // be another great performance boost!
382  //
383  // NOTE (Above): When it came time to compile, I realized that OTScriptable
384  // has no pointer to Cron,
385  // nor access to any ServerNym (unless you pass it in). But I want this
386  // function to work by merely
387  // passing in 2 strings.
388  //
389  // SINCE THE PARTY IS VERIFIED ALREADY (WHEN THE SMART CONTRACT IS FIRST
390  // ACTIVATED) THEN THIS IS
391  // REDUNDANT ANYWAY.
392  //
393  // IF you ever need to use CanExecuteClause() in some circumstance where the
394  // party has NOT been verified
395  // anyway (it won't be from within some script...) then just call
396  // VerifyPartyAuthorization() yourself in
397  // that code, wherever you need to.
398 
399  //
400  // DISALLOW parties to directly execute any clauses named similarly to
401  // callbacks, hooks, or cron hooks!
402  // Only allow this for normal clauses.
403  //
404  if (str_clause_name.compare(0, 5, "cron_") == 0) // todo stop hardcoding
405  {
406  otOut << "OTScriptable::CanExecuteClause: Parties may not directly "
407  "trigger clauses beginning in cron_\n";
408  return false;
409  }
410 
411  if (str_clause_name.compare(0, 5, "hook_") == 0) // todo stop hardcoding
412  {
413  otOut << "OTScriptable::CanExecuteClause: Parties may not directly "
414  "trigger clauses beginning in hook_\n";
415  return false;
416  }
417 
418  if (str_clause_name.compare(0, 9, "callback_") == 0) // todo stop hardcoding
419  {
420  otOut << "OTScriptable::CanExecuteClause: Parties may not directly "
421  "trigger clauses beginning in callback_\n";
422  return false;
423  }
424 
425  // IF NO CALLBACK IS PROVIDED, The default answer to this function is:
426  // YES, this party MAY run this clause!
427  //
428  // But... first we check to see if this OTScriptable has a clause named:
429  // "callback_party_may_execute_clause"
430  // ...and if so, we ask the CALLBACK to make the decision instead. This way,
431  // people can define
432  // in their own scripts any rules they want about which parties may execute
433  // which clauses.
434 
435  //
436  const std::string str_CallbackName(SCRIPTABLE_CALLBACK_PARTY_MAY_EXECUTE);
437 
438  OTClause* pCallbackClause =
439  GetCallback(str_CallbackName); // See if there is a script clause
440  // registered for this callback.
441 
442  if (nullptr != pCallbackClause) // Found it!
443  {
444  otOut << "OTScriptable::CanExecuteClause: Found script for: "
445  << SCRIPTABLE_CALLBACK_PARTY_MAY_EXECUTE << ". Asking...\n";
446 
447  // The function we're IN defaults to TRUE, if there's no script
448  // available.
449  // However, if the script is available, then our default return value
450  // starts as FALSE.
451  // The script itself will then have to set it to true, if that's what it
452  // wants.
453  //
454  OTVariable param1("param_party_name", str_party_name,
456  OTVariable param2("param_clause_name", str_clause_name,
458 
459  OTVariable theReturnVal("return_val", false);
460 
461  mapOfVariables theParameters;
462  theParameters.insert(
463  std::pair<std::string, OTVariable*>("param_party_name", &param1));
464  theParameters.insert(
465  std::pair<std::string, OTVariable*>("param_clause_name", &param2));
466 
467  if (false ==
469  *pCallbackClause, theParameters,
470  theReturnVal)) // <============================================
471  {
472  otErr << "OTScriptable::CanExecuteClause: Error while running "
473  "callback script " << SCRIPTABLE_CALLBACK_PARTY_MAY_EXECUTE
474  << ", clause " << str_clause_name << " \n";
475  return false;
476  }
477  else {
478  otOut << "OTScriptable::CanExecuteClause: Success executing "
479  "callback script " << SCRIPTABLE_CALLBACK_PARTY_MAY_EXECUTE
480  << ", clause: " << str_clause_name << ".\n\n";
481 
482  return theReturnVal.CopyValueBool();
483  }
484 
485  }
486  else {
487  otOut << "OTScriptable::CanExecuteClause: Unable to find script for: "
489  << ". Therefore, default return value is: TRUE.\n";
490  }
491 
492  return true;
493 }
494 
495 // Client-side.
496 // (The server could actually load all the other nyms and accounts,
497 // and verify their transaction numbers, yadda yadda yadda. But the
498 // client can only check to see that at least a signed copy is supposedly
499 // available for every single party.)
500 //
502 {
503  bool bReturnVal = !m_mapParties.empty();
504 
505  for (auto& it : m_mapParties) {
506  OTParty* pParty = it.second;
507  OT_ASSERT(nullptr != pParty);
508 
509  if (!(pParty->GetMySignedCopy().Exists())) return false;
510  }
511 
512  return bReturnVal;
513 }
514 
516 {
517  for (auto& it : m_mapParties) {
518  OTParty* pParty = it.second;
519  OT_ASSERT(nullptr != pParty);
520 
521  pParty->ClearTemporaryPointers();
522  }
523 }
524 
525 bool OTScriptable::ExecuteCallback(OTClause& theCallbackClause,
526  mapOfVariables& theParameters,
527  OTVariable& varReturnVal)
528 {
529  const std::string str_clause_name = theCallbackClause.GetName().Exists()
530  ? theCallbackClause.GetName().Get()
531  : "";
532  OT_ASSERT(OTScriptable::ValidateName(str_clause_name));
533 
534  OTBylaw* pBylaw = theCallbackClause.GetBylaw();
535  OT_ASSERT(nullptr != pBylaw);
536 
537  // By this point, we have the clause we are executing as theCallbackClause,
538  // and we have the Bylaw it belongs to, as pBylaw.
539 
540  const std::string str_code =
541  theCallbackClause.GetCode(); // source code for the script.
542  const std::string str_language =
543  pBylaw->GetLanguage(); // language it's in. (Default is "chai")
544 
545  std::shared_ptr<OTScript> pScript = OTScriptFactory(str_language, str_code);
546 
547  //
548  // SET UP THE NATIVE CALLS, REGISTER THE PARTIES, REGISTER THE VARIABLES,
549  // AND EXECUTE THE SCRIPT.
550  //
551  if (pScript) {
552  // Register the special server-side native OT calls we make available to
553  // all scripts.
554  //
556 
557  // Register all the parties with the script.
558  for (auto& it : m_mapParties) {
559  const std::string str_party_name = it.first;
560  OTParty* pParty = it.second;
561  OT_ASSERT((nullptr != pParty) && (str_party_name.size() > 0));
562 
563  pScript->AddParty(str_party_name, *pParty);
564  }
565 
566  // Add the parameters...
567  for (auto& it : theParameters) {
568  const std::string str_var_name = it.first;
569  OTVariable* pVar = it.second;
570  OT_ASSERT((nullptr != pVar) && (str_var_name.size() > 0));
571 
572  pVar->RegisterForExecution(*pScript);
573  }
574 
575  // Also need to loop through the Variables on pBylaw and register those
576  // as well.
577  //
578  pBylaw->RegisterVariablesForExecution(*pScript); // This sets all the
579  // variables as CLEAN
580  // so we can check for
581  // dirtiness after
582  // execution.
583  //
584 
585  SetDisplayLabel(&str_clause_name);
586 
587  pScript->SetDisplayFilename(m_strLabel.Get());
588 
589  if (!pScript->ExecuteScript(&varReturnVal)) {
590  otErr << "OTScriptable::ExecuteCallback: Error while running "
591  "callback on scriptable: " << m_strLabel << "\n";
592  }
593  else {
594  otOut << "OTScriptable::ExecuteCallback: Successfully executed "
595  "callback on scriptable: " << m_strLabel << "\n\n";
596  return true;
597  }
598  }
599  else {
600  otErr << "OTScriptable::ExecuteCallback: Error instantiating script!\n";
601  }
602 
603  // NOTE: Normally after calling a script, you want to check to see if any of
604  // the persistent variables
605  // are dirty, and if important, send a notice to the parties, save an
606  // updated copy of the contract, etc.
607  // WE DON'T DO THAT FOR CALLBACKS! Why not?
608  //
609  // 1) It only matters if the variables change, if you are actually saving an
610  // updated version of the contract.
611  // (Which is more OTCronItem / OTSmartContract, which saves an updated
612  // copy of itself.) Whereas if you are
613  // NOT saving the contract with those variables in it, then why the hell
614  // would you care to notify people?
615  // 2) Since only OTCronItem / OTSmartContract actually save updated copies
616  // of themselves, they are the only ones
617  // who will ever need to notify anyone. Not EVERY OTScriptable-derived
618  // class will send notifications, but if they
619  // need to, SendNoticeToAllParties() is already available on
620  // OTScriptable.
621  //
622  // 3) MOST IMPORTANTLY: the only time a callback is currently triggered is
623  // when the script has already been activated
624  // somehow, and the only places that do that ALREADY SEND NOTICES WHEN
625  // DIRTY. In fact, if a callback actually makes
626  // the scriptable dirty, IT WILL SEND NOTICES ANYWAY, since the
627  // "ExecuteClauses()" function that CALLED the callback
628  // is also smart enough to send the notices already.
629  //
630 
631  return false;
632 }
633 
634 // TODO: Add a "Notice Number" to OTScriptable and OTVotingGroup. This
635 // increments each
636 // time a notice is sent to the parties, and will be passed in here as a
637 // parameter. The nyms
638 // will all store a map by ServerID, similar to request #, and for each, a list
639 // of notice #s
640 // mapped by the transaction # for each Cron Item the Nym has open. This way the
641 // Nym can
642 // expect to see notice #1, notice #2, etc, to make sure he didn't miss one.
643 // They can even
644 // have a protocol where each notice contains a hash of the previous one, and
645 // the users
646 // (presumably using some future p2p client) can compare hashes with little
647 // network cost.
648 // (This prevents the server from sending a false notice to one party, without
649 // having to
650 // also falsify all subsequent hashes / notices, since all future hashes will
651 // now fail to
652 // match.) The hashes can also be made public if people prefer, as a way of
653 // "publicly
654 // posting" the hash of the notice ...without in any way revealing the notice
655 // contents.
656 
658  bool bSuccessMsg, OTPseudonym& theServerNym,
659  const OTIdentifier& theServerID, const int64_t& lNewTransactionNumber,
660  // const int64_t& lInReferenceTo,
661  // // Each party has its own opening trans #.
662  const OTString& strReference, OTString* pstrNote, OTString* pstrAttachment,
663  OTPseudonym* pActualNym) const
664 {
665  bool bSuccess =
666  true; // Success is defined as ALL parties receiving a notice
667 
668  for (auto& it : m_mapParties) {
669  OTParty* pParty = it.second;
670  OT_ASSERT(nullptr != pParty);
671 
672  // If a smart contract is being canceled, it may not have been confirmed
673  // by
674  // all parties. There may be some unconfirmed parties. (Meaning there is
675  // no
676  // NymID available for those parties.) So here, we make sure we are only
677  // sending
678  // the notice to parties which have been confirmed. Those parties will
679  // have an
680  // opening transaction number that is non-zero. So for parties with a 0
681  // opening
682  // number, we skip the notice (since there won't be any NymID anyway --
683  // nowhere
684  // to send the notice even if we tried.)
685  //
686  if (0 != pParty->GetOpeningTransNo()) {
687  if (false ==
688  pParty->SendNoticeToParty(
689  bSuccessMsg, // "success" notice? or "failure" notice?
690  theServerNym, theServerID, lNewTransactionNumber,
691  // lInReferenceTo,
692  // // each party has its own opening trans #.
693  strReference, pstrNote, pstrAttachment, pActualNym))
694  bSuccess = false; // Notice I don't break here -- I still allow
695  // it to try to notice ALL parties, even if
696  // one fails.
697  }
698  }
699 
700  return bSuccess;
701 }
702 
703 // So you can tell if any persistent or important variables have CHANGED since
704 // it was last set clean.
705 //
707 {
708  bool bIsDirty = false;
709 
710  for (const auto& it : m_mapBylaws) {
711  OTBylaw* pBylaw = it.second;
712  OT_ASSERT(nullptr != pBylaw);
713 
714  if (pBylaw->IsDirty()) {
715  bIsDirty = true;
716  break;
717  }
718  }
719 
720  return bIsDirty;
721 }
722 
723 // So you can tell if ONLY the IMPORTANT variables have CHANGED since it was
724 // last set clean.
725 //
727 {
728  bool bIsDirty = false;
729 
730  for (const auto& it : m_mapBylaws) {
731  OTBylaw* pBylaw = it.second;
732  OT_ASSERT(nullptr != pBylaw);
733 
734  if (pBylaw->IsDirtyImportant()) {
735  bIsDirty = true;
736  break;
737  }
738  }
739 
740  return bIsDirty;
741 }
742 
743 // Sets the variables as clean, so you can check later and see if any have been
744 // changed (if it's DIRTY again.)
745 //
747 {
748  for (auto& it : m_mapBylaws) {
749  OTBylaw* pBylaw = it.second;
750  OT_ASSERT(nullptr != pBylaw);
751  // so we can check for dirtiness later, if it's changed.
752  pBylaw->SetAsClean();
753  }
754 }
755 
756 // Note: this maybe would have been more appropriate on OTSmartContract, since
757 // that is
758 // where the opening/closing numbers are actually USED. But still, they ARE
759 // stored HERE,
760 // so I might as well put the function here also. That way later on, if some new
761 // subclass
762 // uses those numbers, it will have access to count them as well.
763 //
764 // Returns 0 if this agent is not the authorizing agent for a party, and is also
765 // not the
766 // authorized agent for any party's accounts.
767 //
769  std::string str_agent_name) const
770 {
771  int32_t nReturnVal = 0;
772 
773  OTAgent* pAgent = GetAgent(str_agent_name);
774  if (nullptr == pAgent)
775  return nReturnVal; // (Looks like there is no agent with that name.)
776 
777  // Below this point, pAgent is good, meaning str_agent_name really IS
778  // a legit agent for this party. But that doesn't necessarily mean the
779  // agent has to supply any opening or closing transaction #s for this
780  // smart contract. That's only true if he's the AUTHORIZING agent for
781  // the party (for the opening num) or the authorized agent for any of
782  // party's accounts (for the closing number). So let's add it up...
783  //
784  if (pAgent->IsAuthorizingAgentForParty()) // true/false whether THIS agent
785  // is the authorizing agent for
786  // his party.
787  nReturnVal++;
788 
789  // Add the number of accounts, owned by this agent's party, that this agent
790  // is the authorized agent FOR.
791  //
792  nReturnVal += pAgent->GetCountAuthorizedAccts();
793 
794  return nReturnVal;
795 }
796 
797 OTPartyAccount* OTScriptable::GetPartyAccount(std::string str_acct_name) const
798 {
799  if (!OTScriptable::ValidateName(str_acct_name)) // this logs, FYI.
800  {
801  otErr << "OTScriptable::GetPartyAccount: Error: invalid name.\n";
802  return nullptr;
803  }
804 
805  for (auto& it : m_mapParties) {
806  OTParty* pParty = it.second;
807  OT_ASSERT(nullptr != pParty);
808  OTPartyAccount* pAcct = pParty->GetAccount(str_acct_name);
809  if (nullptr != pAcct) // found it.
810  return pAcct;
811  }
812  return nullptr;
813 }
814 
816  const OTIdentifier& theAcctID) const
817 {
818  for (const auto& it : m_mapParties) {
819  OTParty* pParty = it.second;
820  OT_ASSERT(nullptr != pParty);
821 
822  OTPartyAccount* pAcct = pParty->GetAccountByID(theAcctID);
823 
824  if (nullptr != pAcct) // found it.
825  return pAcct;
826  }
827 
828  return nullptr;
829 }
830 
832  const OTIdentifier& theNymID, OTAgent** ppAgent) const
833 {
834  for (const auto& it : m_mapParties) {
835  OTParty* pParty = it.second;
836  OT_ASSERT(nullptr != pParty);
837 
838  if (pParty->HasAgentByNymID(theNymID, ppAgent)) return pParty;
839  }
840  return nullptr;
841 }
842 
844  const OTIdentifier& theNymID, OTAgent** ppAgent) const
845 {
846  for (auto& it : m_mapParties) {
847  OTParty* pParty = it.second;
848  OT_ASSERT(nullptr != pParty);
849 
850  if (pParty->HasAuthorizingAgentByNymID(theNymID, ppAgent))
851  return pParty;
852  }
853  return nullptr;
854 }
855 
857  const OTIdentifier& theAcctID, OTPartyAccount** ppPartyAccount) const
858 {
859  for (auto& it : m_mapParties) {
860  OTParty* pParty = it.second;
861  OT_ASSERT(nullptr != pParty);
862 
863  if (pParty->HasAccountByID(theAcctID, ppPartyAccount)) {
864  return pParty;
865  }
866  }
867  return nullptr;
868 }
869 
871  OTAgent** ppAgent) const
872 {
873  for (auto& it : m_mapParties) {
874  OTParty* pParty = it.second;
875  OT_ASSERT(nullptr != pParty);
876 
877  if (pParty->HasAgent(theNym, ppAgent)) return pParty;
878  }
879  return nullptr;
880 }
881 
883  OTAgent** ppAgent) const
884 {
885  for (auto& it : m_mapParties) {
886  OTParty* pParty = it.second;
887  OT_ASSERT(nullptr != pParty);
888 
889  if (pParty->HasAuthorizingAgent(theNym, ppAgent)) return pParty;
890  }
891  return nullptr;
892 }
893 
895  OTAccount& theAccount, OTPartyAccount** ppPartyAccount) const
896 {
897  for (auto& it : m_mapParties) {
898  OTParty* pParty = it.second;
899  OT_ASSERT(nullptr != pParty);
900 
901  if (pParty->HasAccount(theAccount, ppPartyAccount)) {
902  return pParty;
903  }
904  }
905  return nullptr;
906 }
907 
908 void OTScriptable::RetrieveNymPointers(mapOfNyms& map_Nyms_Already_Loaded)
909 {
910  for (auto& it : m_mapParties) {
911  OTParty* pParty = it.second;
912  OT_ASSERT(nullptr != pParty);
913 
914  pParty->RetrieveNymPointers(map_Nyms_Already_Loaded);
915  }
916 }
917 
918 /*
919  -- Load up the authorizing agent's Nym, if not already loaded. (Why? To
920  verifySignature. Also, just to have
921  it loaded so I don't have to load it twice in case it's needed for verifying
922  one/some of the accts.) So really:
923  -- Verify each party, that the authorizing agent and signature are all good. (I
924  think I have this already...)
925  -- Definitely during this, need to make sure that the contents of the signed
926  version match the contents of the main version, for each signer.
927  -- Verify that the authorizing agent actually has the opening transaction # for
928  the party issued to him. (Do I have this?....)
929  */
930 
931 // OTScriptable::VerifyPartyAuthorization
932 // Similar to VerifyNymAsAgent, except it doesn't ClearTemporaryPointers.
933 // (If it has to Load the authorizing agent, then it will clear that one.)
934 // It also doesn't START with a Nym, per se, but rather starts from the Party.
935 // Though it still allows the possibility that the Nym is already loaded.
936 // I basically wrote RetrieveNymPointers() (above) so I could call it in here.
937 // This function is for cases where the Nym very well may NOT be loaded yet,
938 // BUT THAT WHETHER IT IS, OR NOT, IT *DEFINITELY* DOESN'T CLEAR OUT THE ONES
939 // THAT *ARE* THERE OTHER THAN WHICHEVER ONES IT IS FORCED TO LOAD ITSELF.
940 // (This is in contrast to VerifyNymAsAgent(), which calls
941 // ClearTemporaryPointers()
942 // religiously.)
943 //
944 // This function also verifies the opening transactions # for the party, whereas
945 // VerifyNymAsAgent doesn't. ACTUALLY WAIT -- There IS no opening transaction #
946 // except for OTCronItem-derived objects (OTSmartContract for example...)
947 // So perhaps that will have to go OUTSIDE of this function after all!
948 // Therefore I'll make a separate function for that that I can call along with
949 // this one. (Like how I do in OTSmartContract::CanCancelContract)
950 //
951 // No again -- Because it's in HERE that I actually have the authorizing agent
952 // loaded. I certainly don't want to just have to load him up again. Therefore I
953 // have to use a new rule: IN THIS FUNCTION, if the party HAS an Opening
954 // Number,
955 // THEN IT MUST VERIFY. Since the default value is 0, then that should work,
956 // since
957 // I'm always verifying the number as long as one is there.
958 //
960  OTParty& theParty, // The party that supposedly is authorized for this
961  // supposedly executed agreement.
962  OTPseudonym& theSignerNym, // For verifying signature on the authorizing
963  // Nym, when loading it
964  const OTString& strServerID, // For verifying issued num, need the serverID
965  // the # goes with.
966  mapOfNyms* pmap_ALREADY_LOADED, // If some nyms are already
967  // loaded, pass them here so we
968  // don't load them twice on
969  // accident.
970  mapOfNyms* pmap_NEWLY_LOADED, // If some nyms had to be loaded,
971  // then they will be deleted, too.
972  // UNLESS you pass a map here, in
973  // which case they will instead be
974  // added to this map. (But if you do
975  // that, then you must delete them
976  // yourself after calling this
977  // function.)
978  const bool bBurnTransNo) // In OTServer::VerifySmartContract(),
979  // it not only wants to verify the # is
980  // properly issued, but it additionally
981  // wants to see that it hasn't been USED
982  // yet -- AND it wants to burn it, so it
983  // can't be used again! This bool
984  // allows you to tell the function
985  // whether or not to do that.
986 {
987  // This function DOES assume that theParty was initially FOUND on
988  // OTScriptable.
989  // Meaning I don't have to verify that much if I got this far.
990 
991  const bool bNeedToCleanup = (nullptr == pmap_NEWLY_LOADED) ? true : false;
992 
993  // This party hasn't signed the contract??
994  //
995  if (!theParty.GetMySignedCopy().Exists()) {
996  otOut << __FUNCTION__ << ": Unable to find party's signed copy of this "
997  "contract. Has it been executed?\n";
998  return false;
999  }
1000 
1001  // By this point, we know that theParty has a signed copy of the agreement
1002  // (or of SOMETHING anyway) and we know that
1003  // we were able to find the party based on theNym as one of its agents. But
1004  // the signature still needs to be verified...
1005 
1006  // (2)
1007  // This step verifies that the party has been signed by its authorizing
1008  // agent. (Who may not be the Nym, yet might be.)
1009  //
1010  OTAgent* pAuthorizingAgent = nullptr;
1011  OTPseudonym* pAuthAgentsNym = nullptr;
1012  // In case I have to load it myself, I want it cleaned up properly.
1013  std::unique_ptr<OTPseudonym> theAgentNymAngel;
1014 
1015  // Some nyms are *already* loaded. If any were passed in, let's see if any
1016  // of them are
1017  // the authorizing agent for the contract (for this party)...
1018  //
1019  if (nullptr != pmap_ALREADY_LOADED) {
1020  // (So we don't load it twice, if it's there.)
1021  //
1022  mapOfNyms& map_Nyms_Already_Loaded = (*pmap_ALREADY_LOADED);
1023 
1024  for (auto& it : map_Nyms_Already_Loaded) {
1025  OTPseudonym* pNym = it.second;
1026  OT_ASSERT(nullptr != pNym);
1027 
1028  if (theParty.HasAuthorizingAgent(*pNym, &pAuthorizingAgent)) {
1029  pAuthAgentsNym = pNym; // Just in case
1030  break;
1031  }
1032  }
1033  // if pAuthorizingAgent != nullptr, that means the authorizing agent was
1034  // found among the map of nyms that were already loaded.
1035  }
1036 
1037  // Only if I had to load the authorizing agent myself, do I clear its
1038  // temporary pointer.
1039  // (Because it's going out of scope at the bottom of this function.)
1040  // Any other temporary pointers, I do NOT clear, but I leave them because a
1041  // script is
1042  // probably executing and may still need them.
1043  // (This function that we're in was expressly called by someone who didn't
1044  // want the
1045  // temporary nym pointers cleared just yet, for whatever reason.)
1046  //
1047  bool bHadToLoadItMyself = (nullptr == pAuthorizingAgent) ? true : false;
1048 
1049  // Still not found? Okay, let's LOAD IT UP then...
1050  //
1051  if (bHadToLoadItMyself) {
1052  // Of all of a party's Agents, the "authorizing agent" is the one who
1053  // originally activated
1054  // the agreement for this party (and fronted the opening trans#.) Since
1055  // we need to verify his
1056  // signature, we have to load him up.
1057  //
1058  pAuthAgentsNym =
1059  theParty.LoadAuthorizingAgentNym(theSignerNym, &pAuthorizingAgent);
1060 
1061  if (nullptr != pAuthAgentsNym) // success
1062  {
1063  OT_ASSERT(nullptr !=
1064  pAuthorizingAgent); // This HAS to be set now. I
1065  // assume it henceforth.
1066  otLog3 << __FUNCTION__
1067  << ": I just had to load "
1068  "the authorizing agent's Nym for a party ("
1069  << theParty.GetPartyName()
1070  << "), "
1071  "so I guess it wasn't already available on the list of "
1072  "Nyms that were already loaded.\n";
1073 
1074  // Either I'm DEFINITELY cleaning it up myself, OR I'm adding it to
1075  // a list
1076  // where the CALLER can clean it up.
1077  //
1078  if (bNeedToCleanup)
1079  theAgentNymAngel.reset(pAuthAgentsNym); // CLEANUP!!
1080  else {
1081  const std::string str_agent_name =
1082  pAuthorizingAgent->GetName().Get();
1083 
1084  mapOfNyms& map_Nyms_Newly_Loaded = (*pmap_NEWLY_LOADED);
1085  map_Nyms_Newly_Loaded.insert(
1086  map_Nyms_Newly_Loaded.begin(),
1087  std::pair<std::string, OTPseudonym*>(
1088  str_agent_name,
1089  pAuthAgentsNym)); // (Caller must clean these up.)
1090  }
1091  }
1092  else {
1093  otErr << __FUNCTION__ << ": Error: Strange, unable to load "
1094  "authorizing agent's Nym (to verify his "
1095  "signature.)\n";
1096  return false;
1097  }
1098  }
1099 
1100  // Below this point, we KNOW that pAuthorizingAgent is a good pointer and
1101  // will be cleaned up properly/automatically.
1102  // I'm not using pAuthAgentsNym directly, but pAuthorizingAgent WILL use it
1103  // before this function is done.
1104 
1105  // (3) Verify the issued number, if he has one. If this instance is
1106  // OTScriptable-derived, but NOT OTCronItem-derived,
1107  // then that means there IS NO opening number (or closing number) since
1108  // we're not even on Cron. The parties just
1109  // happen to store their opening number for the cases where we ARE on
1110  // Cron, which will probably be most cases.
1111  // Therefore we CHECK TO SEE if the opening number is NONZERO -- and if
1112  // so, we VERIFY ISSUED on that #. That way,
1113  // for cases where this IS a cron item, it will still verify the number
1114  // (as it should) and in other cases, it will
1115  // just skip this step.
1116  //
1117 
1118  const int64_t lOpeningNo = theParty.GetOpeningTransNo();
1119 
1120  if (lOpeningNo > 0) // If one exists, then verify it.
1121  {
1122  if (false ==
1123  pAuthorizingAgent->VerifyIssuedNumber(lOpeningNo, strServerID)) {
1124  otErr << __FUNCTION__ << ": Opening trans number " << lOpeningNo
1125  << " doesn't "
1126  "verify for the nym listed as the authorizing agent for "
1127  "party " << theParty.GetPartyName() << ".\n";
1128  if (bHadToLoadItMyself && bNeedToCleanup)
1129  pAuthorizingAgent->ClearTemporaryPointers(); // We loaded the
1130  // Nym ourselves,
1131  // which goes out
1132  // of scope after
1133  // this function.
1134  return false;
1135  }
1136 
1137  // The caller wants the additional verification that the number hasn't
1138  // been USED
1139  // yet -- AND the caller wants you to BURN IT HERE.
1140  else if (bBurnTransNo) {
1141  if (false ==
1142  pAuthorizingAgent->VerifyTransactionNumber(lOpeningNo,
1143  strServerID)) {
1144  otErr << __FUNCTION__ << ": Opening trans number " << lOpeningNo
1145  << " doesn't "
1146  "verify as available for use, for the "
1147  "nym listed as the authorizing agent "
1148  "for party: " << theParty.GetPartyName() << ".\n";
1149  if (bHadToLoadItMyself && bNeedToCleanup)
1150  pAuthorizingAgent->ClearTemporaryPointers(); // We loaded
1151  // the Nym
1152  // ourselves,
1153  // which goes
1154  // out of scope
1155  // after this
1156  // function.
1157  return false;
1158  }
1159  else // SUCCESS -- It verified as available, so let's burn it
1160  // here. (So he can't use it twice. It remains issued and
1161  // open until the cron item is eventually closed out for
1162  // good.)
1163  {
1164  // This function also adds lOpeningNo to the agent's nym's list
1165  // of open cron items.
1166  // (OTPseudonym::GetSetOpenCronItems)
1167  //
1168  pAuthorizingAgent->RemoveTransactionNumber(
1169  lOpeningNo, strServerID, theSignerNym, true); // bSave=true
1170  }
1171  }
1172 
1173  } // if lOpeningNo>0
1174  else if (bBurnTransNo) // In this case, bBurnTransNo=true, then the caller
1175  // EXPECTED to burn a transaction
1176  { // num. But the number was 0! Therefore, FAILURE!
1177  otOut << __FUNCTION__ << ": FAILURE. On Party "
1178  << theParty.GetPartyName().c_str()
1179  << ", expected to burn a legitimate opening transaction "
1180  "number, but got this instead: " << lOpeningNo << "\n";
1181  if (bHadToLoadItMyself && bNeedToCleanup)
1182  pAuthorizingAgent->ClearTemporaryPointers(); // We loaded the Nym
1183  // ourselves, which
1184  // goes out of scope
1185  // after this function.
1186  return false;
1187  }
1188 
1189  // (4)
1190  // Here, we use the Authorizing Agent to verify the signature on his party's
1191  // version of the contract.
1192  // Notice: Even if the authorizing agent gets fired, we can still load his
1193  // Nym to verify the original signature on the
1194  // original contract! We should ALWAYS be able to verify our signatures!
1195  // Therefore, TODO: When a Nym is DELETED, it's necessary
1196  // to KEEP the public key on file. We may not have a Nymfile with any
1197  // request #s or trans# signed out, and there are may be no
1198  // accounts for him, but we still need that public key, for later
1199  // verification of the signature.
1200  // UNLESS... the public key ITSELF is stashed into the contract... Notice
1201  // that normal asset contracts already keep the keys inside,
1202  // so why shouldn't these? In fact I can pop the "key" value onto the
1203  // contract as part of the "Party-Signing" API call. Just grab the
1204  // public key from each one. Meanwhile the server can verify that it's
1205  // actually there, and refuse to process without it!! Nice.
1206  // This also shows why we need to store the NymID, even if it can be
1207  // overridden by a Role: because you want to be able to verify
1208  // the original signature, no matter WHO is authorized now. Otherwise your
1209  // entire contract falls apart.
1210 
1211  OTScriptable* pPartySignedCopy =
1213  std::unique_ptr<OTScriptable> theCopyAngel;
1214 
1215  if (nullptr == pPartySignedCopy) {
1216  otErr << __FUNCTION__ << ": Error loading party's signed copy of "
1217  "agreement. Has it been executed?\n";
1218  if (bHadToLoadItMyself && bNeedToCleanup)
1219  pAuthorizingAgent->ClearTemporaryPointers();
1220  return false;
1221  }
1222  else {
1223  theCopyAngel.reset(pPartySignedCopy);
1224  }
1225 
1226  const bool bSigVerified =
1227  pAuthorizingAgent->VerifySignature(*pPartySignedCopy);
1228  bool bContentsVerified = false;
1229 
1230  if (bSigVerified) {
1231  // Todo OPTIMIZE: Might move this call to a higher layer, so it gets
1232  // called MUCH less often but retains the same security.
1233  // There are several places currently in smart contracts like this.
1234  // Need to analyze security aspects before doing it.
1235  //
1236  bContentsVerified =
1237  Compare(*pPartySignedCopy); // This also compares the opening
1238  // / closing numbers, if they are
1239  // non-zero.
1240 
1241  if (!bContentsVerified)
1242  otOut << __FUNCTION__
1243  << ": Though the signature verifies, the contract "
1244  "signed by the party (" << theParty.GetPartyName()
1245  << ") doesn't match this contract. (Failed comparison.)\n";
1246  }
1247  else
1248  otOut << __FUNCTION__ << ": Signature failed to verify for party: "
1249  << theParty.GetPartyName() << " \n";
1250 
1251  if (bHadToLoadItMyself && bNeedToCleanup)
1252  pAuthorizingAgent->ClearTemporaryPointers(); // We loaded the Nym
1253  // ourselves, which goes
1254  // out of scope after this
1255  // function.
1256  // The party is done with it now, and we don't want it to keep pointing to
1257  // something that is now going out of scope.
1258 
1259  return bContentsVerified;
1260 }
1261 
1262 // Kind of replaces VerifySignature() in certain places. It still verifies
1263 // signatures inside, but
1264 // OTTrade and OTAgreement have a much simpler way of doing that than
1265 // OTScriptable/OTSmartContract.
1266 //
1267 // This function also loads its own versions of certain nyms, when necessary,
1268 // and cleans the pointers
1269 // when it's done.
1270 //
1272  OTPseudonym& theSignerNym,
1273  mapOfNyms* pmap_ALREADY_LOADED) const
1274 {
1275  // (COmmented out) existing trades / payment plans on OT basically just have
1276  // this one line:
1277  //
1278  // VerifySignature(theNym)
1279 
1280  // NEW VERSION:
1281  /*
1282  Proves the original party DOES approve of Nym:
1283 
1284  1) Lookup the party for this Nym, (loop to see if Nym is listed as an agent
1285  by any party.)
1286  2) If party found, lookup authorizing agent for party, loading him if
1287  necessary.
1288  3) Use authorizing agent to verify signature on original copy of this
1289  contract. Each party stores their
1290  own copy of the agreement, therefore use that copy to verify signature,
1291  instead of the current version.
1292 
1293  This proves that the original authorizing agent for the party that lists
1294  Nym as an agent HAS signed the smart contract.
1295  (As long as that same party OWNS the account, that should be fine.)
1296  Obviously the best proof is to verify the ORIGINAL version of the contract
1297  against the PARTY'S ORIGINAL SIGNED COPY,
1298  and also to verify them AGAINST EACH OTHER. The calling function should do
1299  this. Otherwise what if the "authorized signer"
1300  has been changed, and some new guy and signature are substituted? Well, I
1301  guess as long as he really is authorized... but
1302  you simply don't know what the original agreement really says unless you
1303  look at it. So load it and use it to call THIS METHOD.
1304  */
1305 
1306  // (1)
1307  // This step verifies that theNym is at least REGISTERED as a valid agent
1308  // for the party. (According to the party.)
1309  //
1310  OTParty* pParty = FindPartyBasedOnNymAsAgent(theNym);
1311 
1312  if (nullptr == pParty) {
1313  otOut << "OTScriptable::VerifyNymAsAgent: Unable to find party based "
1314  "on Nym as agent.\n";
1315  return false;
1316  }
1317  // Below this point, pParty is good.
1318 
1319  // This party hasn't signed the contract??
1320  //
1321  if (!pParty->GetMySignedCopy().Exists()) {
1322  otOut << "OTScriptable::VerifyNymAsAgent: Unable to find party's ("
1323  << pParty->GetPartyName()
1324  << ") signed copy of this contract. Has it been executed?\n";
1325  return false;
1326  }
1327 
1328  // By this point, we know that pParty has a signed copy of the agreement (or
1329  // of SOMETHING anyway) and we know that
1330  // we were able to find the party based on theNym as one of its agents. But
1331  // the signature still needs to be verified...
1332 
1333  // (2)
1334  // This step verifies that the party has been signed by its authorizing
1335  // agent. (Who may not be the Nym, yet might be.)
1336  //
1337  OTAgent* pAuthorizingAgent = nullptr;
1338  OTPseudonym* pAuthAgentsNym = nullptr;
1339  std::unique_ptr<OTPseudonym> theAgentNymAngel;
1340 
1341  // See if theNym is the authorizing agent.
1342  //
1343  if ((false == pParty->HasAuthorizingAgent(theNym, &pAuthorizingAgent)) &&
1344  (nullptr != pmap_ALREADY_LOADED)) {
1345  // No? Okay then, let's see if the authorizing agent is one of these
1346  // already loaded.
1347  // (So we don't load it twice.)
1348  //
1349  mapOfNyms& map_Nyms_Already_Loaded = (*pmap_ALREADY_LOADED);
1350  for (auto& it : map_Nyms_Already_Loaded) {
1351  OTPseudonym* pNym = it.second;
1352  OT_ASSERT(nullptr != pNym);
1353 
1354  if (pParty->HasAuthorizingAgent(*pNym, &pAuthorizingAgent)) {
1355  pAuthAgentsNym = pNym; // Just in case.
1356  break;
1357  }
1358  }
1359  // if pAuthorizingAgent != nullptr, that means the authorizing agent was
1360  // found among the map of nyms that were already loaded.
1361  }
1362 
1363  // Still not found?
1364  if (nullptr == pAuthorizingAgent) {
1365  // Of all of a party's Agents, the "authorizing agent" is the one who
1366  // originally activated
1367  // the agreement for this party (and fronted the opening trans#.) Since
1368  // we need to verify his
1369  // signature, we have to load him up.
1370  //
1371  pAuthAgentsNym =
1372  pParty->LoadAuthorizingAgentNym(theSignerNym, &pAuthorizingAgent);
1373 
1374  if (nullptr != pAuthAgentsNym) // success
1375  {
1376  OT_ASSERT(nullptr !=
1377  pAuthorizingAgent); // This HAS to be set now. I
1378  // assume it henceforth.
1379  otLog3 << "OTScriptable::VerifyNymAsAgent: I just had to load the "
1380  "authorizing agent's Nym for a party ("
1381  << pParty->GetPartyName()
1382  << "), so I guess it wasn't already available "
1383  "on the list of Nyms that were already loaded.\n";
1384  theAgentNymAngel.reset(pAuthAgentsNym); // CLEANUP!!
1385  }
1386  else {
1387  otErr << "OTScriptable::VerifyNymAsAgent: Error: Strange, unable "
1388  "to load authorizing "
1389  "agent's Nym for party " << pParty->GetPartyName()
1390  << " (to verify his signature.)\n";
1391  pParty->ClearTemporaryPointers();
1392  return false;
1393  }
1394  }
1395 
1396  // Below this point, we KNOW that pAuthorizingAgent is a good pointer and
1397  // will be cleaned up properly/automatically.
1398  // I'm not using pAuthAgentsNym directly, but pAuthorizingAgent WILL use it
1399  // before this function is done.
1400 
1401  // TODO: Verify the opening transaction # here, like I do in
1402  // VerifyPartyAuthorization() ?? Research first.
1403 
1404  // (3)
1405  // Here, we use the Authorizing Agent to verify the signature on his party's
1406  // version of the contract.
1407  // Notice: Even if the authorizing agent gets fired, we can still load his
1408  // Nym to verify the original signature on the
1409  // original contract! We should ALWAYS be able to verify our signatures!
1410  // Therefore, TODO: When a Nym is DELETED, it's necessary
1411  // to KEEP the public key on file. We may not have a Nymfile with any
1412  // request #s or trans# signed out, and there are may be no
1413  // accounts for him, but we still need that public key, for later
1414  // verification of the signature.
1415  // UNLESS... the public key ITSELF is stashed into the contract... Notice
1416  // that normal asset contracts already keep the keys inside,
1417  // so why shouldn't these? In fact I can pop the "key" value onto the
1418  // contract as part of the "Party-Signing" API call. Just grab the
1419  // public key from each one. Meanwhile the server can verify that it's
1420  // actually there, and refuse to process without it!! Nice.
1421  // This also shows why we need to store the NymID, even if it can be
1422  // overridden by a Role: because you want to be able to verify
1423  // the original signature, no matter WHO is authorized now. Otherwise your
1424  // entire contract falls apart.
1425 
1426  OTScriptable* pPartySignedCopy =
1428  std::unique_ptr<OTScriptable> theCopyAngel;
1429 
1430  if (nullptr == pPartySignedCopy) {
1431  otErr << "OTScriptable::VerifyNymAsAgent: Error loading party's ("
1432  << pParty->GetPartyName()
1433  << ") signed copy of agreement. Has it been executed?\n";
1434  pParty->ClearTemporaryPointers();
1435  return false;
1436  }
1437  else
1438  theCopyAngel.reset(pPartySignedCopy);
1439 
1440  const bool bSigVerified =
1441  pAuthorizingAgent->VerifySignature(*pPartySignedCopy);
1442  bool bContentsVerified = false;
1443 
1444  if (bSigVerified) {
1445  // Todo OPTIMIZE: Might move this call to a higher layer, so it gets
1446  // called MUCH less often but retains the same security.
1447  // There are several places currently in smart contracts like this.
1448  // Need to analyze security aspects before doing it.
1449  //
1450  bContentsVerified = Compare(*pPartySignedCopy);
1451 
1452  if (!bContentsVerified)
1453  otOut << "OTScriptable::VerifyNymAsAgent: Though the signature "
1454  "verifies, the contract "
1455  "signed by the party (" << pParty->GetPartyName()
1456  << ") doesn't match this contract. (Failed comparison.)\n";
1457  }
1458  else
1459  otOut << "OTScriptable::VerifyNymAsAgent: Signature failed to verify "
1460  "for party: " << pParty->GetPartyName() << " \n";
1461 
1462  // Todo: possibly call Compare(*pPartySignedCopy); to make sure
1463  // there's no funny business.
1464  // Well actually that HAS to happen anyway, it's just a question of whether
1465  // it goes here too, or only somewhere else.
1466 
1467  pParty->ClearTemporaryPointers(); // We loaded a Nym ourselves, which goes
1468  // out of scope after this function. The
1469  // party is done
1470  // with it now, and we don't want it to keep pointing to something that is
1471  // now going out of scope.
1472 
1473  return bContentsVerified;
1474 }
1475 
1476 // Call VerifyPartyAuthorization() first.
1477 // Also, this function, unlike VerifyPartyAuthorization(), is able to ASSUME
1478 // that ALL
1479 // of the Nyms AND accounts have ALREADY been loaded into memory, AND that *this
1480 // has
1481 // pointers to them. That is all prepared before this function is called. That
1482 // is why
1483 // you don't see me passing in maps to Nyms that are already loaded -- because
1484 // *this
1485 // already has them all loaded.
1486 //
1487 // This function verifies ownership AND agency of the account, and it
1488 // also handles closing transaction numbers when appropriate.
1489 //
1491  OTPartyAccount& thePartyAcct, // The party is assumed to have been verified
1492  // already via VerifyPartyAuthorization()
1493  OTPseudonym& theSignerNym, // For verifying signature on the authorizing
1494  // Nym.
1495  const OTString& strServerID, // For verifying issued num, need the serverID
1496  // the # goes with.
1497  const bool bBurnTransNo) // In OTServer::VerifySmartContract(),
1498  // it not only wants to verify the
1499  // closing # is properly issued, but it
1500  // additionally wants to see that it
1501  // hasn't been USED yet -- AND it wants
1502  // to burn it, so it can't be used
1503  // again! This bool allows you to tell
1504  // the function whether or not to do
1505  // that.
1506 {
1507  OTParty* pParty = thePartyAcct.GetParty();
1508 
1509  if (nullptr == pParty) {
1510  otErr << "OTScriptable::" << __FUNCTION__
1511  << ": Unable to find party for acct: " << thePartyAcct.GetName()
1512  << " \n";
1513  return false;
1514  }
1515 
1516  OTAgent* pAuthorizedAgent = thePartyAcct.GetAuthorizedAgent();
1517 
1518  if (nullptr == pAuthorizedAgent) {
1519  otOut << "OTScriptable::" << __FUNCTION__
1520  << ": Unable to find authorized agent ("
1521  << thePartyAcct.GetAgentName()
1522  << ") for acct: " << thePartyAcct.GetName() << " \n";
1523  return false;
1524  }
1525 
1526  // BELOW THIS POINT, pParty and pAuthorizedAgent are both good pointers.
1527  //
1528  // Next, we need to verify that pParty is the proper OWNER of thePartyAcct..
1529  //
1530  // AND that pAuthorizedAgent really IS authorized to manipulate the actual
1531  // account itself. (Either he is listed as its actual owner, or he is an
1532  // agent for an entity, authorized based on a specific role, and the account
1533  // is owned by that entity / controlled by that role.)
1534  //
1535 
1536  // VERIFY ACCOUNT's OWNERSHIP BY PARTY
1537  //
1538  if (!thePartyAcct.VerifyOwnership()) // This will use pParty internally.
1539  {
1540  otOut << "OTScriptable::" << __FUNCTION__
1541  << ": Unable to verify party's (" << pParty->GetPartyName()
1542  << ") ownership of acct: " << thePartyAcct.GetName() << " \n";
1543  return false;
1544  }
1545 
1546  // VERIFY ACCOUNT's AUTHORIZED AGENT (that he has rights to manipulate the
1547  // account itself)
1548  //
1549  if (!thePartyAcct.VerifyAgency()) // This will use pAuthorizedAgent
1550  // internally.
1551  {
1552  otOut << "OTScriptable::" << __FUNCTION__
1553  << ": Unable to verify agent's ("
1554  << pAuthorizedAgent->GetName().Get()
1555  << ") rights re: acct: " << thePartyAcct.GetName() << " \n";
1556  return false;
1557  }
1558 
1559  // Verify the closing number, if he has one. (If this instance is
1560  // OTScriptable-derived, but NOT OTCronItem-derived,
1561  // then that means there IS NO closing number, since we're not even on
1562  // Cron.) The PartyAccts just happen
1563  // to store their closing number for the cases where we ARE on Cron,
1564  // which will probably be most cases.
1565  // Therefore we CHECK TO SEE if the closing number is NONZERO -- and if
1566  // so, we VERIFY ISSUED on that #. That way,
1567  // for cases where this IS a cron item, it will still verify the number
1568  // (as it should) and in other cases, it will
1569  // just skip this step.
1570  //
1571  // Also: If bBurnTransNo is set to true, then it will force this issue,
1572  // since the code then DEMANDS a number
1573  // be available for use.
1574 
1575  const int64_t lClosingNo = thePartyAcct.GetClosingTransNo();
1576 
1577  if (lClosingNo > 0) // If one exists, then verify it.
1578  {
1579  if (false ==
1580  pAuthorizedAgent->VerifyIssuedNumber(lClosingNo, strServerID)) {
1581  otOut << "OTScriptable::" << __FUNCTION__
1582  << ": Closing trans number " << lClosingNo
1583  << " doesn't "
1584  "verify for the nym listed as the authorized agent for "
1585  "account " << thePartyAcct.GetName() << ".\n";
1586  return false;
1587  }
1588 
1589  // The caller wants the additional verification that the number hasn't
1590  // been USED
1591  // yet -- AND the caller wants you to BURN IT HERE.
1592  //
1593  else if (bBurnTransNo) {
1594  if (false ==
1595  pAuthorizedAgent->VerifyTransactionNumber(lClosingNo,
1596  strServerID)) {
1597  otOut << "OTScriptable::" << __FUNCTION__
1598  << ": Closing trans number " << lClosingNo
1599  << " doesn't "
1600  "verify as available for use, for the "
1601  "nym listed as the authorized agent for "
1602  "acct: " << thePartyAcct.GetName() << ".\n";
1603  return false;
1604  }
1605  else // SUCCESS -- It verified as available, so let's burn it
1606  // here. (So he can't use it twice. It remains
1607  { // issued and open until the cron item is eventually closed out
1608  // for good.)
1609  //
1610  // NOTE: This also adds lClosingNo to the agent's nym's
1611  // GetSetOpenCronItems.
1612  //
1613  pAuthorizedAgent->RemoveTransactionNumber(
1614  lClosingNo, strServerID, theSignerNym, true); // bSave=true
1615  }
1616  }
1617 
1618  } // if lClosingNo>0
1619  else if (bBurnTransNo) // In this case, bBurnTransNo=true, then the caller
1620  // EXPECTED to burn a transaction
1621  { // num. But the number was 0! Therefore, FAILURE!
1622  otOut << "OTScriptable::" << __FUNCTION__ << ": FAILURE. On Acct "
1623  << thePartyAcct.GetName()
1624  << ", expected to burn a legitimate closing transaction "
1625  "number, but got this instead: " << lClosingNo << "\n";
1626  return false;
1627  }
1628 
1629  return true;
1630 }
1631 
1632 // Wherever you call the below function, you need to call the above function
1633 // too, and make sure the same
1634 // Party is the one found in both cases.
1635 //
1636 // AGAIN: CALL VerifyNymAsAgent() BEFORE you call this function! Otherwise you
1637 // aren't proving nearly as much. ALWAYS call it first.
1638 //
1640  OTAccount& theAccount) const
1641 {
1642 
1643  // Lookup the party via the ACCOUNT.
1644  //
1645  OTPartyAccount* pPartyAcct = nullptr;
1646  OTParty* pParty = FindPartyBasedOnAccount(theAccount, &pPartyAcct);
1647 
1648  if (nullptr == pParty) {
1649  OT_ASSERT(nullptr != pPartyAcct);
1650  otOut << "OTScriptable::VerifyNymAsAgentForAccount: Unable to find "
1651  "party based on account.\n";
1652  return false;
1653  }
1654  // pPartyAcct is a good pointer below this point.
1655 
1656  // Verify ownership.
1657  //
1658  if (!pParty->VerifyOwnershipOfAccount(theAccount)) {
1659  otOut << "OTScriptable::VerifyNymAsAgentForAccount: pParty is not the "
1660  "owner of theAccount.\n";
1661  pParty->ClearTemporaryPointers(); // Just in case.
1662  return false;
1663  }
1664 
1665  const std::string str_acct_agent_name = pPartyAcct->GetAgentName().Get();
1666  OTAgent* pAgent = pParty->GetAgent(str_acct_agent_name);
1667 
1668  // Make sure they are from the SAME PARTY.
1669  //
1670  if (nullptr == pAgent) {
1671  otOut << "OTScriptable::VerifyNymAsAgentForAccount: Unable to find the "
1672  "right agent for this account.\n";
1673  pParty->ClearTemporaryPointers(); // Just in case.
1674  return false;
1675  }
1676  // Below this point, pPartyAcct is a good pointer, and so is pParty, as well
1677  // as pAgent
1678  // We also know that the agent's name is the same one that was listed on the
1679  // account as authorized.
1680  // (Because we used the account's agent_name to look up pAgent in the first
1681  // place.)
1682 
1683  // Make sure theNym is a valid signer for pAgent, whether representing
1684  // himself as in individual, or in a role for an entity.
1685  // This means that pAgent (looked up based on partyAcct's agent name) will
1686  // return true to IsValidSigner when passed theNym,
1687  // assuming theNym really is the agent that partyAcct was talking about.
1688  //
1689  if (!pAgent->IsValidSigner(theNym)) {
1690  otOut << "OTScriptable::VerifyNymAsAgentForAccount: theNym is not a "
1691  "valid signer for pAgent.\n";
1692  pParty->ClearTemporaryPointers(); // Just in case.
1693  return false;
1694  }
1695  if (!pAgent->VerifyAgencyOfAccount(theAccount)) {
1696  otOut << "OTScriptable::VerifyNymAsAgentForAccount: theNym is not a "
1697  "valid agent for theAccount.\n";
1698  pParty->ClearTemporaryPointers(); // Just in case.
1699  return false;
1700  }
1701 
1702  // Now we know:
1703  // (1) theNym is agent for pParty, (according to the party)
1704  // (2) theAccount is owned by pParty (according to the party)
1705  // (3) theNym is agent for theAccount (according to the party)
1706  // (4) theNym is valid signer for pAgent
1707  // (5) pParty is the actual OWNER of the account. (According to theAccount.)
1708 
1709  pParty->ClearTemporaryPointers(); // Just in case.
1710 
1711  return true;
1712 }
1713 
1714 // Normally I'd call this to prove OWNERSHIP and I'd ASSUME AGENCY based on
1715 // that:
1716 // pSourceAcct->VerifyOwner(*pSenderNym)
1717 
1718 // However, if I'm instead supposed to accept that pSenderNym, while NOT listed
1719 // as the "Owner" on the
1720 // account itself, is still somehow AUTHORIZED to change it, "because the actual
1721 // owner says that it's okay"...
1722 // Well in that case, it's not good enough unless I prove BOTH ownership AND
1723 // Agency. I should prove:
1724 // -- the actual owner for the account,
1725 // -- AND is shown to have signed the agreement with his authorizing agent,
1726 // -- AND is shown to have set theNym as his agent, and listed theNym as
1727 // authorized agent for that account.
1728 
1729 /*
1730  Proves the original party DOES approve of Nym managing that account (assuming
1731  that VerifyNymAsAgentForAnyParty was called, which
1732  saves us from having to look up the authorizing agent for the party and verify
1733  his signature on the entire contract. We assume the
1734  contract itself is sound, and we go on to verify its term.)
1735  Also needs to prove that the ACCOUNT believes itself to be owned by the
1736  original party and was signed by the server.
1737  (If we have proved that ACCOUNT believes itself to be owned by the party, AND
1738  that the PARTY believes it has authorized Nym to
1739  manage that account,
1740  plus the previous function already proves that Nym is an agent of the PARTY and
1741  that the original agreement
1742  is sound, as signed by the party's authorizing agent.)
1743 
1744  AGENCY
1745  1) Lookup the account from among all the parties. This way we find the party.
1746  bool FindPartyBasedOnAccount(theAccount);
1747  2) Lookup the party based on the Nym as agent, and compare it to make sure they
1748  are the SAME PARTY.
1749  3) Lookup the authorized agent for that account (from that party.) This is
1750  different than the authorizing agent in
1751  the function above, which is who signed to open the contract and fronted the
1752  opening trans#. But in THIS case, the authorized
1753  agent must be available for EACH asset account, and he is the one who
1754  supplied the CLOSING number. Each acct has an agent
1755  name, so lookup that agent from pParty.
1756  4) Make sure theNym IS that authorized agent. Only THEN do we know that theNym
1757  is authorized (as far as the party is concerned.)
1758  Notice also that we didn't verify theNym's signature on anything since he
1759  hasn't actually signed anything on the contract itself.
1760  Notice that the ONLY REASON THAT WE KNOW FOR SURE is because
1761  VerifyNymAsAgent() was called before this function! Because that is
1762  what loads the original signer and verifies his signature. Unless that was
1763  done, we honestly don't even know this much! So make
1764  sure you call that function before this one.
1765 
1766  Assuming we get this far, this means the Party / Smart Contract actually
1767  approves of theNym as an Agent, and of theAccount as an
1768  account, and it also approves that Nym is authorized to manipulate that
1769  account.
1770  But it doesn't prove who OWNS that account! Nor does it prove, even if the Nym
1771  DOES own it, whether theNym actually authorizes
1772  this action. Therefore we must also prove that the owner of the account
1773  (according to the ACCOUNT) is the same party who authorized
1774  the Nym to manage that account in the smart contract. (If the Nym IS the
1775  party, then he will show as the owner AND agent.)
1776 
1777  OWNERSHIP
1778  1) pParty->VerifyOwnership(theAccount)
1779  2) If Party owner is a Nym, then call verifyOwner on the account directly with
1780  that Nym (just like the old way.)
1781  3) BUT, if Party owner is an Entity, verify that the entity owns the account.
1782  4) ALSO: Outside of the smart contract, the same Nym should be able to
1783  manipulate that account in this same way, just
1784  by showing that the account is owned by an entity where that Nym has the
1785  RoleID in that entity that appears on the
1786  account. (Account should have entity AND role).
1787 
1788  AHH this is the difference between "this Nym may manipulate this account in
1789  general, due to his role" vs. "this Nym may
1790  manipulate this account DUE TO THE AGENCY OF THE ROLE ID stored in the
1791  Account."
1792  What's happening is, I'm proving BOTH. The smart contract, even if you HAVE
1793  the role, still restricts you from doing anything
1794  FROM INSIDE THE SMART CONTRACT (scripts) where that Nym isn't explicitly set up
1795  as the authorized agent for that account. The Nym
1796  may STILL *normally* be able to mess with that account, if the role is set up
1797  that way -- he just can't do it from inside the script,
1798  without the additional setup inside the script itself that THIS Nym is the one
1799  setup on THIS account.
1800 
1801  Really though, inside the script itself, the only time a Nym would be set up as
1802  the account manager is really if the script
1803  owner wanted to set the ROLE as the account manager. I don't REALLY want to
1804  set Frank in charge in the sales budget money.
1805  Rather, I want to set the SALES DIRECTOR ROLE as being in charge of the sales
1806  budget money, and Frank just happens to be in that
1807  role. IF I FIRE HIM TOMORROW, AND PUT ANOTHER NYM IN THAT ROLE, THE CONTRACT
1808  SHOULD STILL FUNCTION, right? Following that...
1809 
1810  The account itself will store the EntityID and RoleID.
1811 
1812  The partyaccount (on the party) only has the "agent name" who deals with that
1813  account. (No nym ID so far.)
1814 
1815  When I lookup the partyaccount, I lookup the authorized agent. At this point,
1816  the agent could still be a Role, not a Nym.
1817 
1818  Therefore when I verify the Nym against the agent, I do it the same way as I
1819  might verify a nym against an account. If the
1820  agent is a nym repping himself, I compare the NymIDs. Else if the agent is an
1821  individual in a role, then I take the Entity that
1822  owns that agent (the entity is hidden inside the party) and I compare the Nym's
1823  ID to the NymID recorded in the Entity as being
1824  responsible for that role based on the RoleID stored in the agent. CLearer:
1825  The agent has a RoleID and an Entity ID. The entity
1826  that owns it has a list of NymIDs, each mapped to a RoleID. For the account
1827  controlled by the agent, if the Nym trying to change
1828  that account is actually listed in entity EntityID as being assigned role
1829  RoleID, where EntityID and RoleID match those in the agent,
1830  then Nym IS authorized to play with the account. This is verifiable for
1831  entities, nyms, and accounts even OUTSIDE of a smart contract,
1832  and doesn't rely on the smart contract having the partyaccount/authorized_agent
1833  set up. Those are just ADDITIONAL restrictions.
1834  Thus, Inside a smart contract, OT should enforce those additional restrictions
1835  as a layer above the verification of role/owner, etc.
1836 
1837  OR: Should I make it instead: That you must EITHER have Role-permission, OR
1838  smartcontract authorization, and EITHER WAY it allows
1839  you to manipulate the account?
1840 
1841  */
1842 
1843 // Find the first (and hopefully the only) clause on this scriptable object,
1844 // with a given name. (Searches ALL Bylaws on *this.)
1845 //
1846 OTClause* OTScriptable::GetClause(std::string str_clause_name) const
1847 {
1848  if (!OTScriptable::ValidateName(str_clause_name)) // this logs, FYI.
1849  {
1850  otErr << __FUNCTION__ << ": Error: invalid name.\n";
1851  return nullptr;
1852  }
1853 
1854  for (auto& it : m_mapBylaws) {
1855  OTBylaw* pBylaw = it.second;
1856  OT_ASSERT(nullptr != pBylaw);
1857 
1858  OTClause* pClause = pBylaw->GetClause(str_clause_name);
1859 
1860  if (nullptr != pClause) // found it.
1861  return pClause;
1862  }
1863 
1864  return nullptr;
1865 }
1866 
1867 OTAgent* OTScriptable::GetAgent(std::string str_agent_name) const
1868 {
1869  if (!OTScriptable::ValidateName(str_agent_name)) // this logs, FYI.
1870  {
1871  otErr << __FUNCTION__ << ": Error: invalid name.\n";
1872  return nullptr;
1873  }
1874 
1875  for (auto& it : m_mapParties) {
1876  OTParty* pParty = it.second;
1877  OT_ASSERT(nullptr != pParty);
1878 
1879  OTAgent* pAgent = pParty->GetAgent(str_agent_name);
1880 
1881  if (nullptr != pAgent) // found it.
1882  return pAgent;
1883  }
1884 
1885  return nullptr;
1886 }
1887 
1888 OTBylaw* OTScriptable::GetBylaw(std::string str_bylaw_name) const
1889 {
1890  if (!OTScriptable::ValidateName(str_bylaw_name)) // this logs, FYI.
1891  {
1892  otErr << __FUNCTION__ << ": Error: invalid name.\n";
1893  return nullptr;
1894  }
1895 
1896  auto it = m_mapBylaws.find(str_bylaw_name);
1897 
1898  if (m_mapBylaws.end() == it) // Did NOT find it.
1899  {
1900  return nullptr;
1901  }
1902 
1903  OTBylaw* pBylaw = it->second;
1904  OT_ASSERT(nullptr != pBylaw);
1905 
1906  return pBylaw;
1907 }
1908 
1909 OTParty* OTScriptable::GetParty(std::string str_party_name) const
1910 {
1911  if (!OTScriptable::ValidateName(str_party_name)) // this logs, FYI.
1912  {
1913  otErr << __FUNCTION__ << ": Error: invalid name.\n";
1914  return nullptr;
1915  }
1916 
1917  auto it = m_mapParties.find(str_party_name);
1918 
1919  if (m_mapParties.end() == it) // Did NOT find it.
1920  {
1921  return nullptr;
1922  }
1923 
1924  OTParty* pParty = it->second;
1925  OT_ASSERT(nullptr != pParty);
1926 
1927  return pParty;
1928 }
1929 
1931 {
1932  if ((nIndex < 0) || (nIndex >= static_cast<int64_t>(m_mapParties.size()))) {
1933  otErr << __FUNCTION__ << ": Index out of bounds: " << nIndex << "\n";
1934  }
1935  else {
1936 
1937  int32_t nLoopIndex = -1; // will be 0 on first iteration.
1938 
1939  for (auto& it : m_mapParties) {
1940  OTParty* pParty = it.second;
1941  OT_ASSERT(nullptr != pParty);
1942 
1943  ++nLoopIndex; // 0 on first iteration.
1944 
1945  if (nLoopIndex == nIndex) return pParty;
1946  }
1947  }
1948  return nullptr;
1949 }
1950 
1952 {
1953  if ((nIndex < 0) || (nIndex >= static_cast<int64_t>(m_mapBylaws.size()))) {
1954  otErr << __FUNCTION__ << ": Index out of bounds: " << nIndex << "\n";
1955  }
1956  else {
1957 
1958  int32_t nLoopIndex = -1; // will be 0 on first iteration.
1959 
1960  for (auto& it : m_mapBylaws) {
1961  OTBylaw* pBylaw = it.second;
1962  OT_ASSERT(nullptr != pBylaw);
1963 
1964  ++nLoopIndex; // 0 on first iteration.
1965 
1966  if (nLoopIndex == nIndex) return pBylaw;
1967  }
1968  }
1969  return nullptr;
1970 }
1971 
1972 // Verify the contents of THIS contract against signed copies of it that are
1973 // stored in each Party.
1974 //
1976 {
1977  bool bReturnVal = !m_mapParties.empty();
1978 
1979  // MAKE SURE ALL SIGNED COPIES ARE OF THE SAME CONTRACT.
1980  // Loop through ALL the parties. For whichever ones are already signed,
1981  // load up the signed copy and make sure it compares to the main one.
1982  // This is in order to make sure that I am signing the same thing that
1983  // everyone else signed, before I actually sign it.
1984  //
1985  for (auto& it : m_mapParties) {
1986  const std::string current_party_name = it.first;
1987  OTParty* pParty = it.second;
1988  OT_ASSERT(nullptr != pParty);
1989 
1990  if (pParty->GetMySignedCopy().Exists()) {
1991  OTScriptable* pPartySignedCopy =
1993  std::unique_ptr<OTScriptable> theCopyAngel;
1994 
1995  if (nullptr == pPartySignedCopy) {
1996  otErr << __FUNCTION__ << ": Error loading party's ("
1997  << current_party_name
1998  << ") signed copy of agreement. Has it been executed?\n";
1999  return false;
2000  }
2001  else
2002  theCopyAngel.reset(pPartySignedCopy);
2003 
2004  if (!Compare(*pPartySignedCopy)) // <==== For all signed
2005  // copies, we compare them to
2006  // *this.
2007  {
2008  otErr << __FUNCTION__ << ": Party's (" << current_party_name
2009  << ") signed copy of agreement doesn't match *this.\n";
2010  return false;
2011  }
2012  }
2013  // else nothing. (We only verify against the ones that are signed.)
2014  }
2015 
2016  return bReturnVal;
2017 }
2018 
2019 // Done
2020 // Takes ownership. Client side.
2021 // ONLY works if the party is ALREADY there. Assumes the transaction #s, etc are
2022 // set up already.
2023 //
2024 // Used once all the actual parties have examined a specific smartcontract and
2025 // have
2026 // chosen to sign-on to it. This function looks up the theoretical party (such
2027 // as "trustee")
2028 // that they are trying to sign on to, compares the two, then replaces the
2029 // theoretical one
2030 // with the actual one. Then it signs the contract and saves a copy inside the
2031 // party.
2032 //
2034 {
2035  const std::string str_party_name = theParty.GetPartyName();
2036 
2037  if (!OTScriptable::ValidateName(str_party_name)) // this logs, FYI.
2038  {
2039  otErr << "OTScriptable::ConfirmParty: Error: invalid name.\n";
2040  return false;
2041  }
2042 
2043  // MAKE SURE ALL SIGNED COPIES ARE OF THE SAME CONTRACT.
2044  // Loop through ALL the parties. For whichever ones are already signed,
2045  // load up the signed copy and make sure it compares to the main one.
2046  // This is in order to make sure that I am signing the same thing that
2047  // everyone else signed, before I actually sign it.
2048  //
2050  return false; // This already logs on failure.
2051 
2052  // BY THIS POINT, we know that, of all the parties who have already signed,
2053  // their signed copies DO match this smart contract.
2054  //
2055 
2056  //
2057  // Next, find the theoretical Party on this scriptable that matches the
2058  // actual Party that
2059  // was passed in. (It should already be there.) If found, replace it with
2060  // the one passed in.
2061  // Then sign the contract, save the signed version in the new party, and
2062  // then sign again.
2063  //
2064  // If NOT found, then we failed. (For trying to confirm a non-existent
2065  // party.)
2066  //
2067  auto it_delete = m_mapParties.find(str_party_name);
2068 
2069  if (it_delete != m_mapParties.end()) // It was already there. (Good.)
2070  {
2071  OTParty* pParty = it_delete->second;
2072  OT_ASSERT(nullptr != pParty);
2073 
2074  if (!pParty->Compare(theParty)) // Make sure my party compares to the
2075  // one it's replacing...
2076  {
2077  otOut << "OTScriptable::ConfirmParty: Party (" << str_party_name
2078  << ") doesn't match the one it's confirming.\n";
2079  return false;
2080  }
2081  // else...
2082  m_mapParties.erase(it_delete); // Remove the theoretical party from the
2083  // map, so we can replace it with the
2084  // real one.
2085  delete pParty;
2086  pParty = nullptr; // Delete it, since I own it.
2087 
2088  // Careful: This ** DOES ** TAKE OWNERSHIP! theParty will get deleted
2089  // when
2090  // this OTScriptable instance is.
2091  //
2092  m_mapParties.insert(
2093  std::pair<std::string, OTParty*>(str_party_name, &theParty));
2094  theParty.SetOwnerAgreement(*this); // Now the actual party is in place,
2095  // instead of a placekeeper version
2096  // of it. There are actual Acct/Nym
2097  // IDs now, etc.
2098 
2099  // Sign it and save it,
2100  OTString strNewSignedCopy;
2102  bool bSuccess = theParty.SignContract(*this);
2103  if (bSuccess) {
2104  SaveContract();
2105  SaveContractRaw(strNewSignedCopy);
2106 
2107  // then save a copy of it inside theParty,
2108  //
2109  theParty.SetMySignedCopy(strNewSignedCopy);
2110 
2111  // then sign the overall thing again, so that signed copy (now
2112  // inside theParty) will be properly saved.
2113  // That way when other people verify my signature, it will be there
2114  // for them to verify.
2115  //
2117  theParty.SignContract(*this);
2118  SaveContract();
2119 
2120  return true;
2121  }
2122 
2123  return false;
2124  }
2125  else
2126  otOut << "OTScriptable::ConfirmParty: Failed attempt to confirm "
2127  "non-existent party: " << str_party_name << " \n ";
2128 
2129  return false;
2130 }
2131 
2132 // ONLY adds it if it's not already there.
2133 // Used during the design of the smartcontract. (Adding theoretical parties.)
2134 //
2136 {
2137  const std::string str_party_name = theParty.GetPartyName();
2138 
2139  if (!OTScriptable::ValidateName(str_party_name)) // this logs, FYI.
2140  {
2141  otErr << "OTScriptable::AddParty: Error: invalid name.\n";
2142  return false;
2143  }
2144 
2145  if (m_mapParties.find(str_party_name) == m_mapParties.end()) {
2146  // Careful: This ** DOES ** TAKE OWNERSHIP! theParty will get deleted
2147  // when this OTScriptable is.
2148  m_mapParties.insert(
2149  std::pair<std::string, OTParty*>(str_party_name, &theParty));
2150 
2151  theParty.SetOwnerAgreement(*this);
2152 
2153  return true;
2154  }
2155  else
2156  otOut << "OTScriptable::AddParty: Failed attempt: party already exists "
2157  "on contract.\n ";
2158 
2159  return false;
2160 }
2161 
2163 {
2164  const std::string str_name = theBylaw.GetName().Get();
2165 
2166  if (!OTScriptable::ValidateName(str_name)) // this logs, FYI.
2167  {
2168  otErr << "OTScriptable::AddBylaw: Error: invalid name.\n";
2169  return false;
2170  }
2171 
2172  if (m_mapBylaws.find(str_name) == m_mapBylaws.end()) {
2173  // Careful: This ** DOES ** TAKE OWNERSHIP! theBylaw will get deleted
2174  // when this OTScriptable is.
2175  m_mapBylaws.insert(
2176  std::pair<std::string, OTBylaw*>(str_name, &theBylaw));
2177 
2178  theBylaw.SetOwnerAgreement(*this);
2179 
2180  return true;
2181  }
2182  else
2183  otOut << "OTScriptable::AddBylaw: Failed attempt: bylaw already exists "
2184  "on contract.\n ";
2185 
2186  return false;
2187 }
2188 
2189 /*
2190  <party name=“shareholders”
2191  Owner_Type=“entity” // ONLY can be “nym” or “entity”.
2192  Owner_ID=“this” > // Nym ID or Entity ID. Not known at creation.
2193 
2194  <agent type=“group”// could be “nym”, or “role”, or “group”.
2195  Nym_id=“” // In case of “nym”, this is the Nym’s ID. If “role”, this is
2196  NymID of employee in role.
2197  Role_id=“” // In case of “role”, this is the Role’s ID.
2198  Entity_id=“this” // same as OwnerID if ever used. Should remove.
2199  Group_ID=“class_A” // “class A shareholders” are the voting group that
2200  controls this agent.
2201  />
2202 
2203  </party>
2204  */
2205 
2207 {
2208  const char* szFunc = "OTScriptable::Compare";
2209  //
2210  // UPDATE: ALL of the parties should be there, in terms of their
2211  // names and account names --- but the actual IDs can remain blank,
2212  // and the signed copies can be blank. (Those things are all verified
2213  // elsewhere. That's about verifying the signature and authorization,
2214  // versus verifying the content.)
2215  //
2216  if (GetPartyCount() != rhs.GetPartyCount()) {
2217  otOut << szFunc << ": The number of parties does not match.\n";
2218  return false;
2219  }
2220  if (GetBylawCount() != rhs.GetBylawCount()) {
2221  otOut << szFunc << ": The number of bylaws does not match.\n";
2222  return false;
2223  }
2224 
2225  for (const auto& it : m_mapBylaws) {
2226  const std::string str_bylaw_name = it.first;
2227  OTBylaw* pBylaw = it.second;
2228  OT_ASSERT(nullptr != pBylaw);
2229 
2230  OTBylaw* p2 = rhs.GetBylaw(str_bylaw_name);
2231 
2232  if (nullptr == p2) {
2233  otOut << szFunc << ": Unable to find bylaw " << str_bylaw_name
2234  << " on rhs.\n";
2235  return false;
2236  }
2237  else if (!pBylaw->Compare(*p2)) {
2238  otOut << szFunc << ": Bylaws don't match: " << str_bylaw_name
2239  << ".\n";
2240  return false;
2241  }
2242  }
2243 
2244  for (const auto& it : m_mapParties) {
2245  const std::string str_party_name = it.first;
2246  OTParty* pParty = it.second;
2247  OT_ASSERT(nullptr != pParty);
2248 
2249  OTParty* p2 = rhs.GetParty(str_party_name);
2250 
2251  if (nullptr == p2) {
2252  otOut << szFunc << ": Unable to find party " << str_party_name
2253  << " on rhs.\n";
2254  return false;
2255  }
2256  else if (!pParty->Compare(*p2)) {
2257  otOut << szFunc << ": Parties don't match: " << str_party_name
2258  << ".\n";
2259  return false;
2260  }
2261  }
2262 
2263  return true;
2264 }
2265 
2266 // Most contracts calculate their ID by hashing the Raw File (signatures and
2267 // all).
2268 // The scriptable only hashes the unsigned contents, and only with specific data
2269 // removed.
2270 // This way, the smart contract will produce a consistent ID even when asset
2271 // account IDs
2272 // or Nym IDs have been added to it (which would alter the hash of any normal
2273 // contract
2274 // such as an OTAssetContract.)
2275 //
2277 {
2278  // Produce a template version of the scriptable.
2279  OTStringXML xmlUnsigned;
2280  UpdateContentsToString(xmlUnsigned, true);
2281 
2282  newID.CalculateDigest(xmlUnsigned);
2283 }
2284 
2286  bool bCalculatingID) const
2287 {
2288  if ((!m_mapParties.empty()) || (!m_mapBylaws.empty())) {
2289  strAppend.Concatenate("<scriptableContract\n specifyAssetID=\"%s\"\n "
2290  "specifyParties=\"%s\"\n"
2291  " numParties=\"%d\"\n numBylaws=\"%d\" >\n\n",
2292  m_bSpecifyAssetID ? "true" : "false",
2293  m_bSpecifyParties ? "true" : "false",
2294  m_mapParties.size(), m_mapBylaws.size());
2295 
2296  for (auto& it : m_mapParties) {
2297  OTParty* pParty = it.second;
2298  OT_ASSERT(nullptr != pParty);
2299 
2300  // Serialization is slightly different depending on whether we are
2301  // saving
2302  // for real, or just generating a template version of the contract
2303  // in order
2304  // to generate its ID.
2305  //
2306  pParty->Serialize(strAppend, bCalculatingID, m_bSpecifyAssetID,
2308  }
2309 
2310  for (auto& it : m_mapBylaws) {
2311  OTBylaw* pBylaw = it.second;
2312  OT_ASSERT(nullptr != pBylaw);
2313 
2314  pBylaw->Serialize(strAppend, bCalculatingID);
2315  }
2316 
2317  strAppend.Concatenate("</scriptableContract>\n\n");
2318  }
2319 }
2320 
2321 void OTScriptable::UpdateContents() // Before transmission or serialization,
2322  // this is where the contract updates its
2323  // contents
2324 {
2325  // I release this because I'm about to repopulate it.
2327 
2329 }
2330 
2331 // return -1 if error, 0 if nothing, and 1 if the node was processed.
2333 {
2334  int32_t nReturnVal = 0; // Unless/until I want to add OTContract::Compare(),
2335  // then people would be able to surreptitiously
2336  // insert keys and
2337  // int32_t nReturnVal = ot_super::ProcessXMLNode(xml); // conditions, and
2338  // entities, that passed OTScriptable::Compare() with flying colors
2339  // even though they didn't really match. Therefore, here I explicitly
2340  // disallow loading those things.
2341 
2342  // Here we call the parent class first.
2343  // If the node is found there, or there is some error,
2344  // then we just return either way. But if it comes back
2345  // as '0', then nothing happened, and we'll continue executing.
2346  //
2347  // -- Note: you can choose not to call the parent, if
2348  // you don't want to use any of those xml tags.
2349 
2350  // if (nReturnVal == 1 || nReturnVal == (-1))
2351  // return nReturnVal;
2352 
2353  const OTString strNodeName(xml->getNodeName());
2354 
2355  // otErr << "OTScriptable::ProcessXMLNode: strNodeName: %s \n",
2356  // strNodeName.Get());
2357 
2358  if (strNodeName.Compare("scriptableContract")) {
2359  const char* szFunc = "OTScriptable::ProcessXMLNode";
2360  const OTString strSpecify1 = xml->getAttributeValue("specifyAssetID");
2361  const OTString strSpecify2 = xml->getAttributeValue("specifyParties");
2362 
2363  OTString strNumParties = xml->getAttributeValue("numParties");
2364  OTString strNumBylaws = xml->getAttributeValue("numBylaws");
2365 
2366  // These determine whether asset IDs and/or party owner IDs
2367  // are used on the template for any given smart contract.
2368  // (Some templates are specific to certain asset types, while
2369  // other smart contract types allow you to leave asset ID blank
2370  // until the confirmation phase.)
2371  //
2372  if (strSpecify1.Compare("true")) m_bSpecifyAssetID = true;
2373  if (strSpecify2.Compare("true")) m_bSpecifyParties = true;
2374 
2375  // Load up the Parties.
2376  //
2377  int32_t nPartyCount =
2378  strNumParties.Exists() ? atoi(strNumParties.Get()) : 0;
2379  if (nPartyCount > 0) {
2380  while (nPartyCount-- > 0) {
2381  // xml->read(); // <==================
2382  if (!SkipToElement(xml)) {
2383  otOut << szFunc << ": Failure: Unable to find expected "
2384  "element for party. \n";
2385  return (-1);
2386  }
2387 
2388  // otOut << "%s: Looping to load parties:
2389  // currently on: %s \n", szFunc, xml->getNodeName());
2390 
2391  if ((!strcmp("party", xml->getNodeName()))) {
2392  OTString strName = xml->getAttributeValue(
2393  "name"); // Party name (in script code)
2394  OTString strOwnerType = xml->getAttributeValue(
2395  "ownerType"); // "nym" or "entity"
2396  OTString strOwnerID = xml->getAttributeValue(
2397  "ownerID"); // Nym or Entity ID. todo security probably
2398  // make these separate variables.
2399 
2400  OTString strOpeningTransNo = xml->getAttributeValue(
2401  "openingTransNo"); // the closing #s are on the asset
2402  // accounts.
2403 
2404  OTString strAuthAgent = xml->getAttributeValue(
2405  "authorizingAgent"); // When an agent activates this
2406  // contract, it's HIS opening
2407  // trans# that's used.
2408 
2409  OTString strNumAgents = xml->getAttributeValue(
2410  "numAgents"); // number of agents on this party.
2411  OTString strNumAccounts = xml->getAttributeValue(
2412  "numAccounts"); // number of accounts for this party.
2413 
2414  OTString strIsCopyProvided =
2415  xml->getAttributeValue("signedCopyProvided");
2416 
2417  bool bIsCopyProvided = false; // default
2418 
2419  if (strIsCopyProvided.Compare("true"))
2420  bIsCopyProvided = true;
2421 
2422  int64_t lOpeningTransNo = 0;
2423 
2424  if (strOpeningTransNo.Exists())
2425  lOpeningTransNo = atol(strOpeningTransNo.Get());
2426  else
2427  otErr << szFunc
2428  << "s: Expected openingTransNo in party.\n";
2429 
2430  OTParty* pParty = new OTParty(
2431  strName.Exists() ? strName.Get() : "PARTY_ERROR_NAME",
2432  strOwnerType.Compare("nym") ? true : false,
2433  strOwnerID.Get(), strAuthAgent.Get());
2434  OT_ASSERT(nullptr != pParty);
2435 
2436  pParty->SetOpeningTransNo(
2437  lOpeningTransNo); // WARNING: NEED TO MAKE SURE pParty
2438  // IS CLEANED UP BELOW THIS POINT, IF
2439  // FAILURE!!
2440 
2441  // Load up the agents.
2442  //
2443  int32_t nAgentCount =
2444  strNumAgents.Exists() ? atoi(strNumAgents.Get()) : 0;
2445  if (nAgentCount > 0) {
2446  while (nAgentCount-- > 0) {
2447  // xml->read(); //
2448  // <==================
2449  if (!SkipToElement(xml)) {
2450  otOut << szFunc << ": Failure: Unable to find "
2451  "expected element for "
2452  "agent. \n";
2453  delete pParty;
2454  pParty = nullptr;
2455  return (-1);
2456  }
2457 
2458  if ((xml->getNodeType() == irr::io::EXN_ELEMENT) &&
2459  (!strcmp("agent", xml->getNodeName()))) {
2460  OTString strAgentName = xml->getAttributeValue(
2461  "name"); // Agent name (if needed in script
2462  // code)
2463  OTString strAgentRepSelf =
2464  xml->getAttributeValue(
2465  "doesAgentRepresentHimself"); // Agent
2466  // might
2467  // also BE the
2468  // party, and
2469  // not just
2470  // party's
2471  // employee.
2472  OTString strAgentIndividual =
2473  xml->getAttributeValue(
2474  "isAgentAnIndividual"); // Is the agent
2475  // a voting
2476  // group, or an
2477  // individual
2478  // nym? (whether
2479  // employee or
2480  // not)
2481  OTString strNymID = xml->getAttributeValue(
2482  "nymID"); // Nym ID if Nym in role for
2483  // entity, or if representing
2484  // himself.
2485  OTString strRoleID = xml->getAttributeValue(
2486  "roleID"); // Role ID if Nym in Role.
2487  OTString strGroupName = xml->getAttributeValue(
2488  "groupName"); // Group name if voting group.
2489  // (Relative to entity.)
2490 
2491  if (!strAgentName.Exists() ||
2492  !strAgentRepSelf.Exists() ||
2493  !strAgentIndividual.Exists()) {
2494  otErr << szFunc << ": Error loading agent: "
2495  "Either the name, or "
2496  "one of the bool "
2497  "variables was EMPTY.\n";
2498  delete pParty;
2499  pParty = nullptr;
2500  return (-1);
2501  }
2502 
2504  strAgentName.Get())) {
2505  otErr << szFunc
2506  << ": Failed loading agent due to "
2507  "Invalid name: " << strAgentName
2508  << "\n";
2509  delete pParty;
2510  pParty = nullptr;
2511  return (-1);
2512  }
2513 
2514  bool bRepsHimself = true; // default
2515 
2516  if (strAgentRepSelf.Compare("false"))
2517  bRepsHimself = false;
2518 
2519  bool bIsIndividual = true; // default
2520 
2521  if (strAgentIndividual.Compare("false"))
2522  bIsIndividual = false;
2523 
2524  // See if the same-named agent already exists on
2525  // ANY of the OTHER PARTIES
2526  // (There can only be one agent on an
2527  // OTScriptable with a given name.)
2528  //
2529  OTAgent* pExistingAgent =
2530  GetAgent(strAgentName.Get());
2531 
2532  if (nullptr != pExistingAgent) // Uh-oh, it's
2533  // already there!
2534  {
2535  otOut << szFunc
2536  << ": Error loading agent named "
2537  << strAgentName
2538  << ", since one was "
2539  "already there on party "
2540  << strName << ".\n";
2541  delete pParty;
2542  pParty = nullptr;
2543  return (-1);
2544  }
2545  // The AddAgent call below checks to see if it's
2546  // already there, but only for the
2547  // currently-loading party.
2548  // Whereas the above GetAgent() call checks this
2549  // OTScriptable for ALL the agents on the
2550  // already-loaded parties.
2551 
2552  OTAgent* pAgent = new OTAgent(
2553  bRepsHimself, bIsIndividual, strAgentName,
2554  strNymID, strRoleID, strGroupName);
2555  OT_ASSERT(nullptr != pAgent);
2556 
2557  if (!pParty->AddAgent(*pAgent)) {
2558  delete pAgent;
2559  pAgent = nullptr;
2560  delete pParty;
2561  pParty = nullptr;
2562  otErr
2563  << szFunc
2564  << ": Failed adding agent to party.\n";
2565  return (-1);
2566  }
2567 
2568  // xml->read(); //
2569  // <==================
2570 
2571  // MIGHT need to add "skip after element" here.
2572 
2573  // Update: Nope.
2574  }
2575  else {
2576  otErr << szFunc
2577  << ": Expected agent element in party.\n";
2578  delete pParty;
2579  pParty = nullptr;
2580  return (-1); // error condition
2581  }
2582  } // while
2583  }
2584 
2585  // LOAD PARTY ACCOUNTS.
2586  //
2587  int32_t nAcctCount = strNumAccounts.Exists()
2588  ? atoi(strNumAccounts.Get())
2589  : 0;
2590  if (nAcctCount > 0) {
2591  while (nAcctCount-- > 0) {
2592  if (!OTContract::SkipToElement(xml)) {
2593  otErr << szFunc << ": Error finding expected "
2594  "next element for party "
2595  "account.\n";
2596  delete pParty;
2597  pParty = nullptr;
2598  return (-1);
2599  }
2600 
2601  if ((xml->getNodeType() == irr::io::EXN_ELEMENT) &&
2602  (!strcmp("assetAccount", xml->getNodeName()))) {
2603  OTString strAcctName = xml->getAttributeValue(
2604  "name"); // Acct name (if needed in script
2605  // code)
2606  OTString strAcctID = xml->getAttributeValue(
2607  "acctID"); // Asset Acct ID
2608  OTString strAssetTypeID =
2609  xml->getAttributeValue(
2610  "assetTypeID"); // Asset Type ID
2611  OTString strAgentName = xml->getAttributeValue(
2612  "agentName"); // Name of agent who controls
2613  // this account.
2614  OTString strClosingTransNo =
2615  xml->getAttributeValue(
2616  "closingTransNo"); // the closing #s are
2617  // on the asset
2618  // accounts.
2619 
2620  int64_t lClosingTransNo = 0;
2621 
2622  if (strClosingTransNo.Exists())
2623  lClosingTransNo =
2624  atol(strClosingTransNo.Get());
2625  else {
2626  otErr << szFunc << ": Expected "
2627  "closingTransNo in "
2628  "partyaccount.\n";
2629  delete pParty;
2630  pParty = nullptr;
2631  return (-1);
2632  }
2633 
2634  // Missing Account ID is allowed, as well as
2635  // agent name, since those things may not be
2636  // decided yet.
2637  //
2638  if (!strAcctName.Exists() ||
2639  (m_bSpecifyAssetID &&
2640  !strAssetTypeID.Exists())) {
2641  otErr << szFunc << ": Expected missing "
2642  "AcctID or AssetTypeID "
2643  "or Name or AgentName "
2644  "in partyaccount.\n";
2645  delete pParty;
2646  pParty = nullptr;
2647  return (-1);
2648  }
2649 
2650  // See if the same-named partyacct already
2651  // exists on ANY of the OTHER PARTIES
2652  // (There can only be one partyacct on an
2653  // OTScriptable with a given name.)
2654  //
2655  OTPartyAccount* pAcct =
2656  GetPartyAccount(strAcctName.Get());
2657 
2658  if (nullptr !=
2659  pAcct) // Uh-oh, it's already there!
2660  {
2661  otOut << szFunc
2662  << ": Error loading partyacct named "
2663  << strAcctName
2664  << ", since one was "
2665  "already there on party "
2666  << strName << ".\n";
2667  delete pParty;
2668  pParty = nullptr;
2669  return (-1);
2670  }
2671  // The AddAccount call below checks to see if
2672  // it's already there, but only for the
2673  // currently-loading party.
2674  // Whereas the above call checks this
2675  // OTScriptable for all the accounts on the
2676  // already-loaded parties.
2677 
2678  if (false ==
2679  pParty->AddAccount(
2680  strAgentName, strAcctName, strAcctID,
2681  strAssetTypeID, lClosingTransNo)) {
2682  otErr << szFunc << ": Failed adding "
2683  "account to party.\n";
2684  delete pParty;
2685  pParty = nullptr;
2686  return (-1);
2687  }
2688 
2689  // MIGHT need to add "skip after field" call
2690  // here.
2691 
2692  // UPdate: Nope. Not here.
2693 
2694  }
2695  else {
2696  otErr << szFunc << ": Expected assetAccount "
2697  "element in party.\n";
2698  delete pParty;
2699  pParty = nullptr;
2700  return (-1); // error condition
2701  }
2702  } // while
2703  }
2704 
2705  if (bIsCopyProvided) {
2706  const char* pElementExpected = "mySignedCopy";
2707  OTString strTextExpected; // signed copy will go here.
2708 
2709  if (false ==
2711  xml, strTextExpected, pElementExpected)) {
2712  otErr << szFunc << ": Expected " << pElementExpected
2713  << " element with text field.\n";
2714  delete pParty;
2715  pParty = nullptr;
2716  return (-1); // error condition
2717  }
2718  // else ...
2719 
2720  pParty->SetMySignedCopy(strTextExpected);
2721  }
2722 
2723  if (AddParty(*pParty))
2724  otInfo << szFunc
2725  << ": Loaded Party: " << pParty->GetPartyName()
2726  << "\n";
2727  else {
2728  otErr << szFunc << ": Failed loading Party: "
2729  << pParty->GetPartyName() << "\n";
2730  delete pParty;
2731  pParty = nullptr;
2732  return (-1); // error condition
2733  }
2734  }
2735  else {
2736  otErr << szFunc << ": Expected party element.\n";
2737  return (-1); // error condition
2738  }
2739  } // while
2740  }
2741 
2742  // Load up the Bylaws.
2743  //
2744  int32_t nBylawCount =
2745  strNumBylaws.Exists() ? atoi(strNumBylaws.Get()) : 0;
2746  if (nBylawCount > 0) {
2747  while (nBylawCount-- > 0) {
2748  if (!SkipToElement(xml)) {
2749  otOut << szFunc << ": Failure: Unable to find expected "
2750  "element for bylaw. \n";
2751  return (-1);
2752  }
2753 
2754  if (!strcmp("bylaw", xml->getNodeName())) {
2755  OTString strName =
2756  xml->getAttributeValue("name"); // bylaw name
2757  OTString strLanguage = xml->getAttributeValue(
2758  "language"); // The script language used in this bylaw.
2759 
2760  OTString strNumVariable = xml->getAttributeValue(
2761  "numVariables"); // number of variables on this bylaw.
2762  OTString strNumClauses = xml->getAttributeValue(
2763  "numClauses"); // number of clauses on this bylaw.
2764  OTString strNumHooks = xml->getAttributeValue(
2765  "numHooks"); // hooks to server events.
2766  OTString strNumCallbacks = xml->getAttributeValue(
2767  "numCallbacks"); // Callbacks the server may initiate,
2768  // when it needs answers.
2769 
2770  OTBylaw* pBylaw =
2771  new OTBylaw(strName.Get(), strLanguage.Get());
2772 
2773  OT_ASSERT(nullptr != pBylaw);
2774 
2775  // LOAD VARIABLES AND CONSTANTS.
2776  //
2777  int32_t nCount = strNumVariable.Exists()
2778  ? atoi(strNumVariable.Get())
2779  : 0;
2780  if (nCount > 0) {
2781  while (nCount-- > 0) {
2782  if (!OTContract::SkipToElement(xml)) {
2783  otErr << szFunc << ": Error finding expected "
2784  "next element for "
2785  "variable.\n";
2786  delete pBylaw;
2787  pBylaw = nullptr;
2788  return (-1);
2789  }
2790 
2791  if ((xml->getNodeType() == irr::io::EXN_ELEMENT) &&
2792  (!strcmp("variable", xml->getNodeName()))) {
2793  OTString strVarName = xml->getAttributeValue(
2794  "name"); // Variable name (if needed in
2795  // script code)
2796  OTString strVarValue = xml->getAttributeValue(
2797  "value"); // Value stored in variable (If
2798  // this is "true" then a real
2799  // value is expected in a text
2800  // field below. Otherwise, it's
2801  // assumed to be a BLANK STRING.)
2802  OTString strVarType = xml->getAttributeValue(
2803  "type"); // string or int64_t
2804  OTString strVarAccess = xml->getAttributeValue(
2805  "access"); // constant, persistent, or
2806  // important.
2807 
2808  if (!strVarName.Exists() ||
2809  !strVarType.Exists() ||
2810  !strVarAccess.Exists()) {
2811  otErr << szFunc << ": Expected missing "
2812  "name, type, or access "
2813  "type in variable.\n";
2814  delete pBylaw;
2815  pBylaw = nullptr;
2816  return (-1);
2817  }
2818 
2819  // See if the same-named variable already exists
2820  // on ANY of the OTHER BYLAWS
2821  // (There can only be one variable on an
2822  // OTScriptable with a given name.)
2823  //
2824  OTVariable* pVar =
2825  GetVariable(strVarName.Get());
2826 
2827  if (nullptr !=
2828  pVar) // Uh-oh, it's already there!
2829  {
2830  otOut << szFunc
2831  << ": Error loading variable named "
2832  << strVarName
2833  << ", since one was "
2834  "already there on one of the "
2835  "bylaws.\n";
2836  delete pBylaw;
2837  pBylaw = nullptr;
2838  return (-1);
2839  }
2840  // The AddVariable call below checks to see if
2841  // it's already there, but only for the
2842  // currently-loading bylaw.
2843  // Whereas the above call checks this
2844  // OTScriptable for all the variables on the
2845  // already-loaded bylaws.
2846 
2847  // VARIABLE TYPE AND ACCESS TYPE
2848  //
2849  OTVariable::OTVariable_Type theVarType =
2851 
2852  if (strVarType.Compare("integer"))
2853  theVarType = OTVariable::Var_Integer;
2854  else if (strVarType.Compare("string"))
2855  theVarType = OTVariable::Var_String;
2856  else if (strVarType.Compare("bool"))
2857  theVarType = OTVariable::Var_Bool;
2858  else
2859  otErr << szFunc << ": Bad variable type: "
2860  << strVarType << ".\n";
2861 
2862  OTVariable::OTVariable_Access theVarAccess =
2864 
2865  if (strVarAccess.Compare("constant"))
2866  theVarAccess = OTVariable::Var_Constant;
2867  else if (strVarAccess.Compare("persistent"))
2868  theVarAccess = OTVariable::Var_Persistent;
2869  else if (strVarAccess.Compare("important"))
2870  theVarAccess = OTVariable::Var_Important;
2871  else
2872  otErr << szFunc
2873  << ": Bad variable access type: "
2874  << strVarAccess << ".\n";
2875 
2877  theVarAccess) ||
2879  theVarType)) {
2880  otErr << szFunc
2881  << ": Error loading variable to "
2882  "bylaw: bad type (" << strVarType
2883  << ") or access type ("
2884  << strVarAccess << ").\n";
2885  delete pBylaw;
2886  pBylaw = nullptr;
2887  return (-1);
2888  }
2889 
2890  bool bAddedVar = false;
2891  const std::string str_var_name =
2892  strVarName.Get();
2893 
2894  switch (theVarType) {
2896  if (strVarValue.Exists()) {
2897  const int32_t nVarValue =
2898  atoi(strVarValue.Get());
2899  bAddedVar = pBylaw->AddVariable(
2900  str_var_name, nVarValue,
2901  theVarAccess);
2902  }
2903  else {
2904  otErr << szFunc
2905  << ": No value found for integer "
2906  "variable: " << strVarName
2907  << "\n";
2908  delete pBylaw;
2909  pBylaw = nullptr;
2910  return (-1);
2911  }
2912  break;
2913 
2914  case OTVariable::Var_Bool:
2915  if (strVarValue.Exists()) {
2916  const bool bVarValue =
2917  strVarValue.Compare("true") ? true
2918  : false;
2919  bAddedVar = pBylaw->AddVariable(
2920  str_var_name, bVarValue,
2921  theVarAccess);
2922  }
2923  else {
2924  otErr << szFunc
2925  << ": No value found for bool "
2926  "variable: " << strVarName
2927  << "\n";
2928  delete pBylaw;
2929  pBylaw = nullptr;
2930  return (-1);
2931  }
2932  break;
2933 
2934  case OTVariable::Var_String: {
2935  // I realized I should probably allow empty
2936  // strings. :-P
2937  if (strVarValue.Exists() &&
2938  strVarValue.Compare("exists")) {
2939  strVarValue.Release(); // probably
2940  // unnecessary.
2941  if (false ==
2943  xml, strVarValue)) {
2944  otErr << szFunc
2945  << ": No value found for "
2946  "string variable: "
2947  << strVarName << "\n";
2948  delete pBylaw;
2949  pBylaw = nullptr;
2950  return (-1);
2951  }
2952  // (else success)
2953  }
2954  else
2955  strVarValue.Release(); // Necessary. If
2956  // it's going to
2957  // be a blank
2958  // string, then
2959  // let's make
2960  // sure.
2961 
2962  const std::string str_var_value =
2963  strVarValue.Get();
2964  bAddedVar = pBylaw->AddVariable(
2965  str_var_name, str_var_value,
2966  theVarAccess);
2967  } break;
2968  default:
2969  otErr << szFunc
2970  << ": Wrong variable type... "
2971  "somehow AFTER I should have "
2972  "already detected it...\n";
2973  delete pBylaw;
2974  pBylaw = nullptr;
2975  return (-1);
2976  }
2977 
2978  if (!bAddedVar) {
2979  otErr << szFunc << ": Failed adding "
2980  "variable to bylaw.\n";
2981  delete pBylaw;
2982  pBylaw = nullptr;
2983  return (-1);
2984  }
2985 
2986  }
2987  else {
2988  otErr << szFunc << ": Expected variable "
2989  "element in bylaw.\n";
2990  delete pBylaw;
2991  pBylaw = nullptr;
2992  return (-1); // error condition
2993  }
2994  } // while
2995  }
2996 
2997  // LOAD CLAUSES
2998  //
2999  nCount =
3000  strNumClauses.Exists() ? atoi(strNumClauses.Get()) : 0;
3001  if (nCount > 0) {
3002  while (nCount-- > 0) {
3003  const char* pElementExpected = "clause";
3004  OTString strTextExpected; // clause's script code
3005  // will go here.
3006 
3007  OTString::Map temp_MapAttributes;
3008  //
3009  // This map contains values we will also want, when
3010  // we read the clause...
3011  // (The OTContract::LoadEncodedTextField call below
3012  // will read all the values
3013  // as specified in this map.)
3014  //
3015  //
3016  temp_MapAttributes.insert(
3017  std::pair<std::string, std::string>("name",
3018  ""));
3020  xml, strTextExpected, pElementExpected,
3021  &temp_MapAttributes)) // </clause>
3022  {
3023  otErr << szFunc << ": Error: Expected "
3024  << pElementExpected
3025  << " element with text field.\n";
3026  delete pBylaw;
3027  pBylaw = nullptr;
3028  return (-1); // error condition
3029  }
3030 
3031  // Okay we now have the script code in
3032  // strTextExpected. Next, let's read the clause's
3033  // NAME
3034  // from the map. If it's there, and presumably some
3035  // kind of harsh validation for both, then
3036  // create a clause object and add to my list here.
3037 
3038  auto it = temp_MapAttributes.find("name");
3039 
3040  if ((it != temp_MapAttributes.end())) // We expected
3041  // this much.
3042  {
3043  std::string& str_name = it->second;
3044 
3045  if (str_name.size() > 0) // SUCCESS
3046  {
3047 
3048  // See if the same-named clause already
3049  // exists on ANY of the OTHER BYLAWS
3050  // (There can only be one clause on an
3051  // OTScriptable with a given name.)
3052  //
3053  OTClause* pClause =
3054  GetClause(str_name.c_str());
3055 
3056  if (nullptr !=
3057  pClause) // Uh-oh, it's already there!
3058  {
3059  otOut
3060  << szFunc
3061  << ": Error loading clause named "
3062  << str_name
3063  << ", since one was already "
3064  "there on one of the bylaws.\n";
3065  delete pBylaw;
3066  pBylaw = nullptr;
3067  return (-1);
3068  }
3069  else if (false ==
3070  pBylaw->AddClause(
3071  str_name.c_str(),
3072  strTextExpected.Get())) {
3073  otErr << szFunc << ": Failed adding "
3074  "clause to bylaw.\n";
3075  delete pBylaw;
3076  pBylaw = nullptr;
3077  return (-1); // error condition
3078  }
3079  }
3080  // else it's empty, which is expected if nothing
3081  // was there, since that's the default value
3082  // that we set above for "name" in
3083  // temp_MapAttributes.
3084  else {
3085  otErr << szFunc
3086  << ": Expected clause name.\n";
3087  delete pBylaw;
3088  pBylaw = nullptr;
3089  return (-1); // error condition
3090  }
3091  }
3092  else {
3093  otErr << szFunc << ": Strange error: couldn't "
3094  "find name AT ALL.\n";
3095  delete pBylaw;
3096  pBylaw = nullptr;
3097  return (-1); // error condition
3098  }
3099  } // while
3100  } // if strNumClauses.Exists() && nCount > 0
3101 
3102  // LOAD HOOKS.
3103  //
3104  nCount = strNumHooks.Exists() ? atoi(strNumHooks.Get()) : 0;
3105  if (nCount > 0) {
3106  while (nCount-- > 0) {
3107  // xml->read();
3108  if (!SkipToElement(xml)) {
3109  otOut << szFunc << ": Failure: Unable to find "
3110  "expected element.\n";
3111  delete pBylaw;
3112  pBylaw = nullptr;
3113  return (-1);
3114  }
3115 
3116  if ((xml->getNodeType() == irr::io::EXN_ELEMENT) &&
3117  (!strcmp("hook", xml->getNodeName()))) {
3118  OTString strHookName = xml->getAttributeValue(
3119  "name"); // Name of standard hook such as
3120  // hook_activate or cron_process,
3121  // etc
3122  OTString strClause = xml->getAttributeValue(
3123  "clause"); // Name of clause on this Bylaw
3124  // that should trigger when that
3125  // callback occurs.
3126 
3127  if (!strHookName.Exists() ||
3128  !strClause.Exists()) {
3129  otErr << szFunc << ": Expected missing "
3130  "name or clause while "
3131  "loading hook.\n";
3132  delete pBylaw;
3133  pBylaw = nullptr;
3134  return (-1);
3135  }
3136 
3137  if (false ==
3138  pBylaw->AddHook(strHookName.Get(),
3139  strClause.Get())) {
3140  otErr << szFunc
3141  << ": Failed adding hook to bylaw.\n";
3142  delete pBylaw;
3143  pBylaw = nullptr;
3144  return (-1);
3145  }
3146  }
3147  else {
3148  otErr << szFunc
3149  << ": Expected hook element in bylaw.\n";
3150  delete pBylaw;
3151  pBylaw = nullptr;
3152  return (-1); // error condition
3153  }
3154  } // while
3155  }
3156 
3157  // LOAD CALLBACKS.
3158  //
3159  nCount = strNumCallbacks.Exists()
3160  ? atoi(strNumCallbacks.Get())
3161  : 0;
3162  if (nCount > 0) {
3163  while (nCount-- > 0) {
3164  // xml->read();
3165  if (!SkipToElement(xml)) {
3166  otOut << szFunc << ": Failure: Unable to find "
3167  "expected element.\n";
3168  delete pBylaw;
3169  pBylaw = nullptr;
3170  return (-1);
3171  }
3172 
3173  if ((xml->getNodeType() == irr::io::EXN_ELEMENT) &&
3174  (!strcmp("callback", xml->getNodeName()))) {
3175  OTString strCallbackName =
3176  xml->getAttributeValue(
3177  "name"); // Name of standard callback
3178  // such as OnActivate,
3179  // OnDeactivate, etc
3180  OTString strClause = xml->getAttributeValue(
3181  "clause"); // Name of clause on this Bylaw
3182  // that should trigger when that
3183  // hook occurs.
3184 
3185  if (!strCallbackName.Exists() ||
3186  !strClause.Exists()) {
3187  otErr << szFunc
3188  << ": Expected, yet nevertheless "
3189  "missing, name or clause while "
3190  "loading "
3191  "callback for bylaw " << strName
3192  << ".\n";
3193  delete pBylaw;
3194  pBylaw = nullptr;
3195  return (-1);
3196  }
3197 
3198  // See if the same-named callback already exists
3199  // on ANY of the OTHER BYLAWS
3200  // (There can only be one clause to handle any
3201  // given callback.)
3202  //
3203  OTClause* pClause =
3204  GetCallback(strCallbackName.Get());
3205 
3206  if (nullptr !=
3207  pClause) // Uh-oh, it's already there!
3208  {
3209  otOut << szFunc
3210  << ": Error loading callback "
3211  << strCallbackName
3212  << ", since one was already there on "
3213  "one of the other bylaws.\n";
3214  delete pBylaw;
3215  pBylaw = nullptr;
3216  return (-1);
3217  }
3218  // The below call checks to see if it's already
3219  // there, but only for the currently-loading
3220  // bylaw.
3221  // Whereas the above call checks this
3222  // OTScriptable for all the already-loaded
3223  // bylaws.
3224 
3225  if (false ==
3226  pBylaw->AddCallback(strCallbackName.Get(),
3227  strClause.Get())) {
3228  otErr << szFunc
3229  << ": Failed adding callback ("
3230  << strCallbackName << ") to bylaw ("
3231  << strName << ").\n";
3232  delete pBylaw;
3233  pBylaw = nullptr;
3234  return (-1);
3235  }
3236  }
3237  else {
3238  otErr << szFunc << ": Expected callback "
3239  "element in bylaw.\n";
3240  delete pBylaw;
3241  pBylaw = nullptr;
3242  return (-1); // error condition
3243  }
3244  } // while
3245  }
3246 
3247  if (AddBylaw(*pBylaw)) {
3248  otInfo << szFunc
3249  << ": Loaded Bylaw: " << pBylaw->GetName()
3250  << "\n";
3251  }
3252  else {
3253  otErr << szFunc
3254  << ": Failed loading Bylaw: " << pBylaw->GetName()
3255  << "\n";
3256  delete pBylaw;
3257  pBylaw = nullptr;
3258  return (-1); // error condition
3259  }
3260  }
3261  else {
3262  otErr << szFunc << ": Expected bylaw element.\n";
3263  return (-1); // error condition
3264  }
3265 
3266  } // while
3267  }
3268 
3269  nReturnVal = 1;
3270  }
3271 
3272  return nReturnVal;
3273 }
3274 
3275 // Look up the first (and hopefully only) variable registered for a given name.
3276 // (Across all of my Bylaws)
3277 //
3278 OTVariable* OTScriptable::GetVariable(std::string str_VarName)
3279 {
3280  if (!OTScriptable::ValidateName(str_VarName)) // this logs, FYI.
3281  {
3282  otErr << "OTScriptable::GetVariable: Error: invalid name.\n";
3283  return nullptr;
3284  }
3285 
3286  for (auto& it : m_mapBylaws) {
3287  OTBylaw* pBylaw = it.second;
3288  OT_ASSERT(nullptr != pBylaw);
3289 
3290  OTVariable* pVar = pBylaw->GetVariable(str_VarName);
3291 
3292  if (nullptr != pVar) // found it.
3293  return pVar;
3294  }
3295 
3296  return nullptr;
3297 }
3298 
3299 // Look up the first (and hopefully only) clause registered for a given
3300 // callback.
3301 //
3302 OTClause* OTScriptable::GetCallback(std::string str_CallbackName)
3303 {
3304  if ((false == OTScriptable::ValidateName(str_CallbackName)) ||
3305  (str_CallbackName.compare(0, 9, "callback_") != 0)) // this logs, FYI.
3306  {
3307  otErr << "OTScriptable::GetCallback: Error: invalid name: "
3308  << str_CallbackName << "\n";
3309  return nullptr;
3310  }
3311 
3312  for (auto& it : m_mapBylaws) {
3313  OTBylaw* pBylaw = it.second;
3314  OT_ASSERT(nullptr != pBylaw);
3315 
3316  OTClause* pClause = pBylaw->GetCallback(str_CallbackName);
3317 
3318  if (nullptr != pClause) // found it.
3319  return pClause;
3320  }
3321 
3322  return nullptr;
3323 }
3324 
3325 // Look up all clauses matching a specific hook.
3326 //
3327 bool OTScriptable::GetHooks(std::string str_HookName, mapOfClauses& theResults)
3328 {
3329  if ((false == OTScriptable::ValidateName(str_HookName)) ||
3330  ((str_HookName.compare(0, 5, "cron_") != 0) &&
3331  (str_HookName.compare(0, 5, "hook_") != 0))) // this logs, FYI.
3332  {
3333  otErr << "OTScriptable::GetHooks: Error: invalid name.\n";
3334  return false;
3335  }
3336 
3337  bool bReturnVal = false;
3338 
3339  for (auto& it : m_mapBylaws) {
3340  OTBylaw* pBylaw = it.second;
3341  OT_ASSERT(nullptr != pBylaw);
3342 
3343  // Look up all clauses matching a specific hook.
3344  //
3345  if (pBylaw->GetHooks(str_HookName, theResults)) bReturnVal = true;
3346  }
3347 
3348  return bReturnVal;
3349 }
3350 
3352 {
3353  // Go through the existing list of parties and bylaws at this point, and
3354  // delete them all.
3355  // (After all, I own them.)
3356  //
3357  while (!m_mapParties.empty()) {
3358  OTParty* pParty = m_mapParties.begin()->second;
3359  OT_ASSERT(nullptr != pParty);
3360 
3361  m_mapParties.erase(m_mapParties.begin());
3362 
3363  delete pParty;
3364  pParty = nullptr;
3365  }
3366  while (!m_mapBylaws.empty()) {
3367  OTBylaw* pBylaw = m_mapBylaws.begin()->second;
3368  OT_ASSERT(nullptr != pBylaw);
3369 
3370  m_mapBylaws.erase(m_mapBylaws.begin());
3371 
3372  delete pBylaw;
3373  pBylaw = nullptr;
3374  }
3375 }
3376 
3378 {
3380 
3381  // If there were any dynamically allocated objects, clean them up here.
3382 
3383  ot_super::Release(); // since I've overridden the base class, I call it
3384  // now...
3385 }
3386 
3388  : ot_super()
3389  , m_bCalculatingID(false)
3390  , // This is not serialized.
3391  m_bSpecifyAssetID(false)
3392  , m_bSpecifyParties(false) // These are.
3393 {
3394 }
3395 
3397 {
3399 }
3400 
3401 bool OTScriptable::SaveContractWallet(std::ofstream&) const
3402 {
3403  return true;
3404 }
3405 
3406 } // namespace opentxs
OTParty * FindPartyBasedOnNymIDAsAgent(const OTIdentifier &theNymID, OTAgent **ppAgent=nullptr) const
bool HasAgentByNymID(const OTIdentifier &theNymID, OTAgent **ppAgent=nullptr) const
Definition: OTParty.cpp:792
EXPORT bool CanExecuteClause(std::string str_party_name, std::string str_clause_name)
std::map< std::string, std::string > Map
Definition: OTString.hpp:162
static bool ValidateName(std::string str_name)
bool SignContract(OTContract &theInput) const
Definition: OTParty.cpp:1423
EXPORT bool AddClause(OTClause &theClause)
Definition: OTBylaw.cpp:854
bool AddAgent(OTAgent &theAgent)
Definition: OTParty.cpp:307
bool is_ot_namechar_invalid(char c)
virtual EXPORT bool AddParty(OTParty &theParty)
EXPORT std::string GetPartyName(bool *pBoolSuccess=nullptr) const
Definition: OTParty.cpp:489
EXPORT bool CalculateDigest(const OTData &dataInput)
EXPORT void RegisterForExecution(OTScript &theScript)
Definition: OTVariable.cpp:424
EXPORT bool SendNoticeToAllParties(bool bSuccessMsg, OTPseudonym &theServerNym, const OTIdentifier &theServerID, const int64_t &lNewTransactionNumber, const OTString &strReference, OTString *pstrNote=nullptr, OTString *pstrAttachment=nullptr, OTPseudonym *pActualNym=nullptr) const
EXPORT bool VerifyThisAgainstAllPartiesSignedCopies()
void ClearTemporaryPointers()
Definition: OTAgent.hpp:231
EXPORT OTAgent * GetAgent(const std::string &str_agent_name) const
Definition: OTParty.cpp:609
bool VerifySignature(const OTContract &theContract) const
Definition: OTAgent.cpp:159
EXPORT OTParty * FindPartyBasedOnNymAsAuthAgent(OTPseudonym &theNym, OTAgent **ppAgent=nullptr) const
void SetOwnerAgreement(OTScriptable &theOwner)
Definition: OTParty.hpp:283
EXPORT void RegisterVariablesForExecution(OTScript &theScript)
Definition: OTBylaw.cpp:276
void ClearTemporaryPointers()
Definition: OTParty.cpp:468
EXPORT bool SaveContract()
static EXPORT OTScriptable * InstantiateScriptable(const OTString &strInput)
EXPORT bool AllPartiesHaveSupposedlyConfirmed()
EXPORT const OTString & GetName() const
virtual bool SaveContractWallet(std::ofstream &ofs) const
EXPORT OTBylaw * GetBylaw(std::string str_bylaw_name) const
bool SendNoticeToParty(bool bSuccessMsg, OTPseudonym &theServerNym, const OTIdentifier &theServerID, const int64_t &lNewTransactionNumber, const OTString &strReference, OTString *pstrNote=nullptr, OTString *pstrAttachment=nullptr, OTPseudonym *pActualNym=nullptr)
Definition: OTParty.cpp:1057
EXPORT OTClause * GetCallback(std::string str_CallbackName)
Definition: OTBylaw.cpp:468
int32_t GetCountAuthorizedAccts()
Definition: OTAgent.cpp:636
std::map< std::string, OTVariable * > mapOfVariables
Definition: OTBylaw.hpp:146
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
virtual EXPORT void RegisterOTNativeCallsWithScript(OTScript &theScript)
EXPORT int32_t GetCountTransNumsNeededForAgent(std::string str_agent_name) const
OTLOG_IMPORT OTLogStream otOut
bool VerifyTransactionNumber(const int64_t &lNumber, const OTString &strServerID)
Definition: OTAgent.cpp:911
std::map< std::string, OTPseudonym * > mapOfNyms
Definition: OTWallet.hpp:161
virtual EXPORT bool Compare(OTScriptable &rhs) const
bool VerifyOwnershipOfAccount(const OTAccount &theAccount) const
Definition: OTParty.cpp:934
EXPORT bool Compare(OTBylaw &rhs)
Definition: OTBylaw.cpp:288
OTLOG_IMPORT OTLogStream otLog3
bool CopyValueBool() const
Definition: OTVariable.hpp:250
EXPORT bool GetHooks(std::string str_HookName, mapOfClauses &theResults)
Definition: OTBylaw.cpp:686
EXPORT bool SaveContractRaw(OTString &strOutput) const
std::map< std::string, OTClause * > mapOfClauses
Definition: OTBylaw.hpp:145
EXPORT bool IsDirty() const
Definition: OTBylaw.cpp:204
static std::string GetTime()
bool AddAccount(OTPartyAccount &thePartyAcct)
Definition: OTParty.cpp:374
EXPORT const OTString & GetName() const
Definition: OTClause.hpp:155
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
int64_t time64_t
Definition: Common.hpp:209
EXPORT OTAgent * GetAuthorizedAgent()
bool VerifyPartyAcctAuthorization(OTPartyAccount &thePartyAcct, OTPseudonym &theSignerNym, const OTString &strServerID, bool bBurnTransNo=false)
#define SCRIPTABLE_CALLBACK_PARTY_MAY_EXECUTE
mapOfParties m_mapParties
EXPORT void SetAsClean()
Definition: OTBylaw.cpp:262
EXPORT bool DecodeIfArmored(bool escapedIsAllowed=true)
Definition: OTString.cpp:1212
EXPORT void ReleaseSignatures()
Definition: OTContract.cpp:989
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT OTClause * GetClause(std::string str_Name) const
Definition: OTBylaw.cpp:623
EXPORT OTClause * GetClause(std::string str_clause_name) const
EXPORT bool IsValidSigner(OTPseudonym &theNym)
Definition: OTAgent.cpp:553
EXPORT void Format(const char *fmt,...)
Definition: OTString.cpp:1319
int32_t GetBylawCount() const
bool HasAccount(OTAccount &theAccount, OTPartyAccount **ppPartyAccount=nullptr) const
Definition: OTParty.cpp:755
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
bool ExecuteCallback(OTClause &theCallbackClause, mapOfVariables &theParameters, OTVariable &varReturnVal)
int32_t GetPartyCount() const
EXPORT const OTString & GetName()
Definition: OTAgent.hpp:388
void SetMySignedCopy(const OTString &strMyCopy)
Definition: OTParty.hpp:287
bool VerifyPartyAuthorization(OTParty &theParty, OTPseudonym &theSignerNym, const OTString &strServerID, mapOfNyms *pmap_ALREADY_LOADED=nullptr, mapOfNyms *pmap_NEWLY_LOADED=nullptr, bool bBurnTransNo=false)
bool Compare(const OTParty &rhs) const
Definition: OTParty.cpp:1791
time64_t OTTimeGetCurrentTime()
Definition: Common.hpp:211
void UpdateContentsToString(OTString &strAppend, bool bCalculatingID) const
bool VerifyIssuedNumber(const int64_t &lNumber, const OTString &strServerID)
Definition: OTAgent.cpp:892
EXPORT bool AddVariable(OTVariable &theVariable)
Definition: OTBylaw.cpp:743
OTPseudonym * LoadAuthorizingAgentNym(OTPseudonym &theSignerNym, OTAgent **ppAgent=nullptr)
Definition: OTParty.cpp:899
EXPORT void SetOwnerAgreement(OTScriptable &theOwner)
Definition: OTBylaw.hpp:264
EXPORT const char * GetCode() const
Definition: OTClause.cpp:177
OTParty * FindPartyBasedOnAccountID(const OTIdentifier &theAcctID, OTPartyAccount **ppPartyAccount=nullptr) const
static EXPORT bool LoadEncodedTextField(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
bool sgets(char *buffer, uint32_t size)
Definition: OTString.cpp:1380
#define OT_ASSERT(x)
Definition: Assert.hpp:150
virtual EXPORT void SetDisplayLabel(const std::string *pstrLabel=nullptr)
void RetrieveNymPointers(mapOfNyms &map_Nyms_Already_Loaded)
OTParty * FindPartyBasedOnAccount(OTAccount &theAccount, OTPartyAccount **ppPartyAccount=nullptr) const
EXPORT bool IsDirtyImportant() const
Definition: OTBylaw.cpp:235
OTClause * GetCallback(std::string str_CallbackName)
OTVariable * GetVariable(std::string str_VarName)
bool HasAuthorizingAgentByNymID(const OTIdentifier &theNymID, OTAgent **ppAgent=nullptr) const
Definition: OTParty.cpp:845
OTLOG_IMPORT OTLogStream otInfo
EXPORT OTParty * GetParty(std::string str_party_name) const
const OTString & GetAgentName() const
bool HasAgent(OTPseudonym &theNym, OTAgent **ppAgent=nullptr) const
Definition: OTParty.cpp:776
EXPORT void Serialize(OTString &strAppend, bool bCalculatingID=false) const
Definition: OTBylaw.cpp:146
EXPORT OTPartyAccount * GetAccountByID(const OTIdentifier &theAcctID) const
Definition: OTParty.cpp:721
bool HasAccountByID(const OTIdentifier &theAcctID, OTPartyAccount **ppPartyAccount=nullptr) const
Definition: OTParty.cpp:736
virtual void UpdateContents()
OTParty * GetParty() const
EXPORT OTVariable * GetVariable(std::string str_Name)
Definition: OTBylaw.cpp:579
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
EXPORT bool AddCallback(std::string str_CallbackName, std::string str_ClauseName)
Definition: OTBylaw.cpp:512
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
EXPORT const char * Get() const
Definition: OTString.cpp:1045
virtual void Release()
static bool SkipToElement(irr::io::IrrXMLReader *&xml)
OTLOG_IMPORT OTLogStream otErr
EXPORT OTPartyAccount * GetAccount(const std::string &str_acct_name) const
Definition: OTParty.cpp:653
OTBylaw * GetBylaw() const
Definition: OTClause.hpp:160
void Serialize(OTString &strAppend, bool bCalculatingID=false, bool bSpecifyAssetID=false, bool bSpecifyParties=false) const
Definition: OTParty.cpp:1731
bool VerifyAgencyOfAccount(const OTAccount &theAccount) const
Definition: OTAgent.cpp:699
EXPORT const OTString & GetName() const
Definition: OTBylaw.hpp:177
EXPORT const char * GetLanguage() const
Definition: OTBylaw.cpp:916
virtual EXPORT void Release()
Definition: OTContract.cpp:277
virtual EXPORT bool VerifyNymAsAgent(OTPseudonym &theNym, OTPseudonym &theSignerNym, mapOfNyms *pmap_ALREADY_LOADED=nullptr) const
const OTString & GetMySignedCopy()
Definition: OTParty.hpp:291
virtual EXPORT bool VerifyNymAsAgentForAccount(OTPseudonym &theNym, OTAccount &theAccount) const
bool RemoveTransactionNumber(const int64_t &lNumber, const OTString &strServerID, OTPseudonym &SIGNER_NYM, bool bSave=true)
Definition: OTAgent.cpp:1006
bool IsDirtyImportant() const
EXPORT bool Contains(const char *compare) const
Definition: OTString.cpp:1137
int64_t GetOpeningTransNo() const
Definition: OTParty.hpp:295
int64_t GetClosingTransNo() const
EXPORT OTParty * FindPartyBasedOnNymAsAgent(OTPseudonym &theNym, OTAgent **ppAgent=nullptr) const
EXPORT bool AddHook(std::string str_HookName, std::string str_ClauseName)
Definition: OTBylaw.cpp:556
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
OTAgent * GetAgent(std::string str_agent_name) const
void SetOpeningTransNo(const int64_t &theNumber)
Definition: OTParty.hpp:299
EXPORT OTParty * GetPartyByIndex(int32_t nIndex) const
EXPORT bool LoadContractFromString(const OTString &theStr)
bool GetHooks(std::string str_HookName, mapOfClauses &theResults)
OTParty * FindPartyBasedOnNymIDAsAuthAgent(const OTIdentifier &theNymID, OTAgent **ppAgent=nullptr) const
OTPartyAccount * GetPartyAccountByID(const OTIdentifier &theAcctID) const
EXPORT OTBylaw * GetBylawByIndex(int32_t nIndex) const
OTPartyAccount * GetPartyAccount(std::string str_acct_name) const
virtual EXPORT bool ConfirmParty(OTParty &theParty)
bool IsAuthorizingAgentForParty()
Definition: OTAgent.cpp:623
virtual EXPORT void Release()
Definition: OTString.cpp:765
EXPORT std::shared_ptr< OTScript > OTScriptFactory(const std::string &script_type="")
Definition: OTScript.cpp:203
virtual EXPORT bool AddBylaw(OTBylaw &theBylaw)
bool HasAuthorizingAgent(OTPseudonym &theNym, OTAgent **ppAgent=nullptr) const
Definition: OTParty.cpp:814
void RetrieveNymPointers(mapOfNyms &map_Nyms_Already_Loaded)
Definition: OTParty.cpp:879
static bool LoadEncodedTextFieldByName(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput, const char *&szName, OTString::Map *pmapExtraVars=nullptr)