Permalink
Browse files

Smart Contracts!! Compiles, runs. See scripts dir.

Signed-off-by: FellowTraveler <F3llowTraveler@gmail.com>
  • Loading branch information...
1 parent 65e743c commit 5f8c4158f984f2537dd36d0f23fc33ee928c5063 @FellowTraveler committed Nov 30, 2011
Showing with 4,465 additions and 700 deletions.
  1. +1 −1 LICENSE-AND-CREDITS.txt
  2. 0 OTLib/Lucre/CHANGES
  3. 0 OTLib/Lucre/bank-new.cpp
  4. 0 OTLib/Lucre/bank-sign.cpp
  5. 0 OTLib/Lucre/bank-verify.cpp
  6. 0 OTLib/Lucre/bank.h
  7. 0 OTLib/Lucre/bankdemo.cpp
  8. 0 OTLib/Lucre/bankimp.cpp
  9. 0 OTLib/Lucre/banktest.cpp
  10. 0 OTLib/Lucre/banktest2.cpp
  11. 0 OTLib/Lucre/coin-request.cpp
  12. 0 OTLib/Lucre/coin-unblind.cpp
  13. +14 −3 OTLib/OTAccount.cpp
  14. +4 −1 OTLib/OTAgreement.cpp
  15. +216 −30 OTLib/OTBylaw.cpp
  16. +15 −8 OTLib/OTBylaw.h
  17. +180 −19 OTLib/OTContract.cpp
  18. +13 −2 OTLib/OTContract.h
  19. +27 −7 OTLib/OTCron.cpp
  20. +7 −2 OTLib/OTInstrument.cpp
  21. 0 OTLib/OTLib/stdafx.cpp
  22. 0 OTLib/OTLib/stdafx.h
  23. 0 OTLib/OTLib/targetver.h
  24. +250 −73 OTLib/OTScriptable.cpp
  25. +8 −0 OTLib/OTScriptable.h
  26. +44 −16 OTLib/OTSmartContract.cpp
  27. +4 −4 OTLib/OTWallet.cpp
  28. 0 OTLib/anyoption.cpp
  29. 0 OTLib/anyoption.h
  30. 0 OTLib/bigint/BigInteger.cc
  31. 0 OTLib/bigint/BigInteger.hh
  32. 0 OTLib/bigint/BigIntegerAlgorithms.cc
  33. 0 OTLib/bigint/BigIntegerAlgorithms.hh
  34. 0 OTLib/bigint/BigIntegerLibrary.hh
  35. 0 OTLib/bigint/BigUnsigned.cc
  36. 0 OTLib/bigint/BigUnsigned.hh
  37. 0 OTLib/bigint/BigUnsignedInABase.cc
  38. 0 OTLib/bigint/BigUnsignedInABase.hh
  39. 0 OTLib/bigint/ChangeLog
  40. 0 OTLib/bigint/Makefile
  41. 0 OTLib/bigint/NumberlikeArray.hh
  42. 0 OTLib/bigint/README
  43. 0 OTLib/bigint/run-testsuite
  44. 0 OTLib/bigint/testsuite.cc
  45. 0 OTLib/irrxml/CXMLReaderImpl.h
  46. 0 OTLib/irrxml/fast_atof.h
  47. 0 OTLib/irrxml/heapsort.h
  48. 0 OTLib/irrxml/irrArray.h
  49. 0 OTLib/irrxml/irrString.h
  50. 0 OTLib/irrxml/irrTypes.h
  51. 0 OTLib/irrxml/irrXML.cpp
  52. 0 OTLib/irrxml/irrXML.h
  53. 0 OTLib/simpleini/ConvertUTF.c
  54. 0 OTLib/simpleini/ConvertUTF.h
  55. 0 OTLib/simpleini/Makefile
  56. 0 OTLib/simpleini/SimpleIni.h
  57. 0 OTLib/simpleini/SimpleIni.sln
  58. 0 OTLib/simpleini/SimpleIni.vcproj
  59. 0 OTLib/simpleini/ini.syn
  60. 0 OTLib/simpleini/package.cmd
  61. 0 OTLib/simpleini/simpleini.doxy
  62. 0 OTLib/simpleini/simpleini.dsp
  63. 0 OTLib/simpleini/simpleini.dsw
  64. 0 OTLib/simpleini/snippets.cpp
  65. 0 OTLib/simpleini/test.cmd
  66. 0 OTLib/simpleini/test1-expected.ini
  67. 0 OTLib/simpleini/test1-input.ini
  68. 0 OTLib/simpleini/test1.cpp
  69. 0 OTLib/simpleini/testsi-EUCJP.ini
  70. 0 OTLib/simpleini/testsi-SJIS.ini
  71. 0 OTLib/simpleini/testsi-UTF8.ini
  72. 0 OTLib/simpleini/testsi.cpp
  73. +1 −1 docs/LICENSE-AND-CREDITS.txt
  74. +3 −1 docs/RELEASE-NOTES.txt
  75. +12 −11 docs/SSL-NOTES.txt
  76. +4 −4 docs/WIPE-USERS-ACCOUNTS.txt
  77. +1 −0 ot-sample-data-clean/CLIENT-COMMANDS.txt
  78. 0 ot-sample-data-clean/client_data/LICENSE-AND-CREDITS.txt
  79. BIN ot-sample-data-clean/client_data/signcontract.exe
  80. 0 ot-sample-data-clean/client_data/wallet.xml
  81. BIN ot-sample-data-clean/server_data/createmint.exe
  82. 0 ot-sample-data-clean/server_data/notaryServer.xml
  83. +1 −0 ot-sample-data/CLIENT-COMMANDS.txt
  84. +1 −1 ot-sample-data/client_data/LICENSE-AND-CREDITS.txt
  85. 0 ot-sample-data/client_data/wallet.xml
  86. 0 ot-sample-data/server_data/notaryServer.xml
  87. 0 sample-contracts/NOTES.txt
  88. +358 −0 scripts/create_smartcontract.ot
  89. 0 ssl/Makefile
  90. 0 ssl/NOTES.txt
  91. 0 ssl/client.cnf
  92. 0 ssl/root.cnf
  93. 0 ssl/server.cnf
  94. 0 ssl/serverCA.cnf
  95. 0 testwallet/JNI_API_Windows/JNI_API_Windows.cpp
  96. 0 testwallet/JNI_API_Windows/JNI_API_Windows.h
  97. 0 testwallet/JNI_API_Windows/applink.c
  98. 0 testwallet/JNI_API_Windows/dllmain.cpp
  99. 0 testwallet/JNI_API_Windows/stdafx.cpp
  100. 0 testwallet/JNI_API_Windows/stdafx.h
  101. 0 testwallet/JNI_API_Windows/targetver.h
  102. +5 −2 testwallet/Makefile
  103. +5 −2 testwallet/Makefile.API
  104. +91 −57 testwallet/OTAPI.cpp
  105. +1,575 −0 testwallet/OTAPI_Wrapper.cpp
  106. +866 −0 testwallet/OTAPI_Wrapper.h
  107. +14 −0 testwallet/OTAPI_csharp.cpp
  108. +9 −0 testwallet/OTAPI_funcdef.h
  109. +26 −0 testwallet/OTAPI_java.cpp
  110. +41 −0 testwallet/OTAPI_perl5.cpp
  111. +42 −0 testwallet/OTAPI_php.cpp
  112. +38 −0 testwallet/OTAPI_python.cpp
  113. +39 −0 testwallet/OTAPI_ruby.cpp
  114. +36 −0 testwallet/OTAPI_tcl.cpp
  115. +0 −31 testwallet/OTAPI_wrap.h
  116. 0 testwallet/SSL-Example/SFSocket.c
  117. 0 testwallet/SSL-Example/SFSocket.h
  118. 0 testwallet/SSL-Example/client.c
  119. 0 testwallet/SSL-Example/server.c
  120. +5 −0 testwallet/otapi.cs
  121. +4 −0 testwallet/otapi.java
  122. +4 −0 testwallet/otapi.php
  123. +1 −0 testwallet/otapi.pm
  124. +4 −0 testwallet/otapi.py
  125. +1 −0 testwallet/otapiJNI.java
  126. +3 −0 testwallet/otapiPINVOKE.cs
  127. +1 −0 testwallet/php_otapi.h
  128. +0 −13 testwallet/test.ot
  129. +0 −11 testwallet/test.php
  130. +165 −193 testwallet/testclient.cpp
  131. 0 testwallet/testwallet/applink.c
  132. 0 testwallet/testwallet/stdafx.cpp
  133. 0 testwallet/testwallet/stdafx.h
  134. 0 testwallet/testwallet/targetver.h
  135. 0 testwallet/testwallet/testwallet.cpp
  136. +308 −196 testwallet/xmlrpcxx_client.cpp
  137. +3 −1 transaction/OTServer.cpp
  138. 0 transaction/SSL-Example/SFSocket.c
  139. 0 transaction/SSL-Example/SFSocket.h
  140. 0 transaction/SSL-Example/client.c
  141. 0 transaction/SSL-Example/server.c
  142. +0 −5 transaction/ot_server.cfg
  143. 0 transaction/transaction/applink.c
  144. 0 transaction/transaction/stdafx.cpp
  145. 0 transaction/transaction/stdafx.h
  146. 0 transaction/transaction/targetver.h
  147. 0 transaction/transaction/transaction.cpp
  148. +15 −5 transaction/xmlrpcxx_server.cpp
  149. 0 util/NOTES.txt
  150. 0 util/otcreatemint/main.cpp
  151. 0 util/signcontract/main.cpp
View
2 LICENSE-AND-CREDITS.txt
@@ -1,4 +1,4 @@
-Open Transactions v0.73
+Open Transactions v0.74
(Scroll to the bottom to see the complete AGPLv3.)
/************************************************************
-----BEGIN PGP SIGNED MESSAGE-----
View
0 OTLib/Lucre/CHANGES 100755 → 100644
File mode changed.
View
0 OTLib/Lucre/bank-new.cpp 100755 → 100644
File mode changed.
View
0 OTLib/Lucre/bank-sign.cpp 100755 → 100644
File mode changed.
View
0 OTLib/Lucre/bank-verify.cpp 100755 → 100644
File mode changed.
View
0 OTLib/Lucre/bank.h 100755 → 100644
File mode changed.
View
0 OTLib/Lucre/bankdemo.cpp 100755 → 100644
File mode changed.
View
0 OTLib/Lucre/bankimp.cpp 100755 → 100644
File mode changed.
View
0 OTLib/Lucre/banktest.cpp 100755 → 100644
File mode changed.
View
0 OTLib/Lucre/banktest2.cpp 100755 → 100644
File mode changed.
View
0 OTLib/Lucre/coin-request.cpp 100755 → 100644
File mode changed.
View
0 OTLib/Lucre/coin-unblind.cpp 100755 → 100644
File mode changed.
View
17 OTLib/OTAccount.cpp
@@ -1144,12 +1144,18 @@ int OTAcctList::ReadFromXMLNode(irr::io::IrrXMLReader*& xml, const OTString & st
//
// Load up the account IDs.
//
- int nCount = 0;
- if (strAcctCount.Exists() && ( (nCount = atoi(strAcctCount.Get()) > 0 )))
+ int nCount = strAcctCount.Exists() ? atoi(strAcctCount.Get()) : 0;
+ if (nCount > 0)
{
while (nCount-- > 0)
{
- xml->read();
+// xml->read();
+ if (false == OTContract::SkipToElement(xml))
+ {
+ OTLog::Output(0, "OTAcctList::ReadFromXMLNode: Failure: Unable to find expected element.\n");
+ return (-1);
+ }
+ // --------------------------------------
if ((xml->getNodeType() == EXN_ELEMENT) && (!strcmp("accountEntry", xml->getNodeName())))
{
@@ -1176,6 +1182,11 @@ int OTAcctList::ReadFromXMLNode(irr::io::IrrXMLReader*& xml, const OTString & st
} // while
}
// --------------------------------
+
+ if (false == OTContract::SkipAfterLoadingField(xml)) // </accountList>
+ { OTLog::Output(0, "*** OTAcctList::ReadFromXMLNode: Bad data? Expected EXN_ELEMENT_END here, but "
+ "didn't get it. Returning false.\n"); return (-1); }
+
return 1;
}
View
5 OTLib/OTAgreement.cpp
@@ -483,7 +483,10 @@ bool OTAgreement::ProcessCron()
// START DATE --------------------------------
- // Okay, so it's not expired. But might not have reached START DATE yet...
+ // Okay, so it's NOT expired. But might not have reached START DATE yet...
+ // (If not expired, yet current date is not verified, that means it hasn't
+ // ENTERED the date range YET.)
+ //
if (!VerifyCurrentDate())
return true; // The Trade is not yet valid, so we return. BUT, we return
// true, so it will stay on Cron until it BECOMES valid.
View
246 OTLib/OTBylaw.cpp
@@ -445,7 +445,7 @@ void OTAgent::SetParty(OTParty & theOwnerParty) // This happens when the agent i
bool bGetOwnerNymID = false;
const std::string str_owner_nym_id = theOwnerParty.GetNymID(&bGetOwnerNymID);
- m_strNymID.Set(bGetOwnerNymID ? str_owner_nym_id.c_str() : "ERROR_GETTING_NYM_ID_FROM_OWNER_PARTY");
+ m_strNymID.Set(bGetOwnerNymID ? str_owner_nym_id.c_str() : "");
// Todo here, instead of copying the Owner's Nym ID like above, just make sure they match.
// Similarly, make sure that the RoleID or GroupName, whichever is relevant, is validated for the owner.
@@ -682,6 +682,62 @@ bool OTAgent::GetEntityID(OTIdentifier& theOutput) const
+
+// Returns true/false whether THIS agent is the authorizing agent for his party.
+//
+bool OTAgent::IsAuthorizingAgentForParty()
+{
+ if (NULL == m_pForParty)
+ return false;
+
+ if (m_strName.Compare(m_pForParty->GetAuthorizingAgentName().c_str()))
+ return true;
+
+ return false;
+}
+
+
+
+// Only counts accounts authorized for str_agent_name.
+//
+int OTParty::GetAccountCount(const std::string str_agent_name) const
+{
+ int nCount = 0;
+
+ FOR_EACH_CONST(mapOfPartyAccounts, m_mapPartyAccounts)
+ {
+ OTPartyAccount * pAcct = (*it).second;
+ OT_ASSERT_MSG(NULL != pAcct, "Unexpected NULL partyaccount pointer in party map.");
+ // -------------------------------------
+
+ const OTString & strAgentName = pAcct->GetAgentName();
+
+ if (strAgentName.Compare(str_agent_name.c_str()))
+ nCount++;
+ }
+
+ return nCount;
+}
+
+
+// Returns the number of accounts, owned by this agent's party, that this agent
+// is the authorized agent FOR.
+//
+int OTAgent::GetCountAuthorizedAccts()
+{
+ if (NULL == m_pForParty)
+ {
+ OTLog::Error("OTAgent::CountAuthorizedAccts: Error: m_pForParty was NULL.\n");
+ return 0; // Maybe should log here...
+ }
+
+ return m_pForParty->GetAccountCount(m_strName.Get());
+}
+
+
+
+
+
// ------------------------------------------
// For when the agent is a voting group:
// If !IsGroup() aka IsIndividual(), then this will return false.
@@ -698,8 +754,6 @@ bool OTAgent::GetGroupName(OTString & strGroupName)
return false;
}
-
-
//
//
// --------------------
@@ -940,12 +994,29 @@ OTParty::OTParty()
}
-OTParty::OTParty(const char * szName, bool bIsOwnerNym, const char * szOwnerID, const char * szAuthAgent)
+OTParty::OTParty(const char * szName, bool bIsOwnerNym, const char * szOwnerID, const char * szAuthAgent, const bool bCreateAgent/*=false*/)
: m_pstr_party_name(NULL), m_bPartyIsNym(bIsOwnerNym), m_str_owner_id(szOwnerID != NULL ? szOwnerID : ""),
m_str_authorizing_agent(szAuthAgent != NULL ? szAuthAgent : ""),
m_lOpeningTransNo(0), m_pOwnerAgreement(NULL)
{
m_pstr_party_name = new std::string(szName != NULL ? szName : "");
+
+ // ------------------------------------------
+ if (bCreateAgent)
+ {
+ const OTString strName(m_str_authorizing_agent.c_str()),
+ strNymID(""), strRoleID(""), strGroupName("");
+ OTAgent * pAgent = new OTAgent(true /*bNymRepresentsSelf*/, true /*bIsAnIndividual*/,
+ strName, strNymID, strRoleID, strGroupName);
+ OT_ASSERT(NULL != pAgent);
+
+ if (!AddAgent(*pAgent))
+ {
+ OTLog::Error("OTParty::OTParty: *** Failed *** while adding default agent in CONSTRUCTOR! 2\n");
+ delete pAgent; pAgent = NULL;
+ }
+ }
+ // ------------------------------------------
}
@@ -959,10 +1030,10 @@ OTParty::OTParty(const std::string str_PartyName,
const std::string * pstr_account_name/*=NULL*/,
const long lClosingTransNo/*=0*/
)
-: m_pstr_party_name(NULL), m_bPartyIsNym(true),
+: m_pstr_party_name(new std::string(str_PartyName)), m_bPartyIsNym(true),
m_lOpeningTransNo(0), m_pOwnerAgreement(NULL)
{
- m_pstr_party_name = new std::string(str_PartyName);
+// m_pstr_party_name = new std::string(str_PartyName);
OT_ASSERT(NULL != m_pstr_party_name);
// theNym is owner, therefore save his ID information, and create the agent
@@ -1164,21 +1235,21 @@ long OTParty::GetClosingTransNo(const std::string str_for_acct_name) const
//}
-OTParty::~OTParty()
+void OTParty::CleanupAgents()
{
- if (NULL != m_pstr_party_name)
- delete m_pstr_party_name;
-
- // Don't cleanup the nym or account here, since Party doesn't own them.
- // (He has pointers for reference uses only.)
-
+ // ------------------------
while (!m_mapAgents.empty())
{
OTAgent * pTemp = m_mapAgents.begin()->second;
OT_ASSERT(NULL != pTemp);
delete pTemp; pTemp = NULL;
m_mapAgents.erase(m_mapAgents.begin());
- }
+ }
+ // ------------------------
+}
+
+void OTParty::CleanupAccounts()
+{
// ------------------------
while (!m_mapPartyAccounts.empty())
{
@@ -1187,6 +1258,20 @@ OTParty::~OTParty()
delete pTemp; pTemp = NULL;
m_mapPartyAccounts.erase(m_mapPartyAccounts.begin());
}
+ // ------------------------
+}
+
+
+OTParty::~OTParty()
+{
+ if (NULL != m_pstr_party_name)
+ delete m_pstr_party_name;
+
+ // Don't cleanup the nym or account here, since Party doesn't own them.
+ // (He has pointers for reference uses only.)
+
+ CleanupAgents();
+ CleanupAccounts();
}
@@ -1422,6 +1507,28 @@ OTPartyAccount * OTParty::GetAccountByAgent(const std::string & str_agent_name)
}
+
+// Get PartyAccount pointer by Acct ID.
+//
+// Returns NULL on failure.
+OTPartyAccount * OTParty::GetAccountByID(const OTIdentifier & theAcctID)
+{
+ FOR_EACH(mapOfPartyAccounts, m_mapPartyAccounts)
+ {
+ OTPartyAccount * pAcct = (*it).second;
+ OT_ASSERT(NULL != pAcct);
+ // ----------------
+ const OTIdentifier theTempAcctID(pAcct->GetAcctID());
+
+ if (theTempAcctID == theAcctID)
+ return pAcct;
+ }
+
+ return NULL;
+}
+
+
+
// If account is present for Party, set account's pointer to theAccount and return true.
bool OTParty::HasAccount(OTAccount & theAccount, OTPartyAccount ** ppPartyAccount/*=NULL*/) const
{
@@ -1877,6 +1984,8 @@ bool OTParty::LoadAndVerifyAssetAccounts(OTPseudonym & theServerNym,
mapOfAccounts & map_Accts_Already_Loaded,
mapOfAccounts & map_NewlyLoaded)
{
+ std::set<std::string> theAcctIDSet; // Make sure all the acct IDs are unique.
+
FOR_EACH_IT(mapOfPartyAccounts, m_mapPartyAccounts, it_acct)
{
const std::string str_acct_name = (*it_acct).first;
@@ -1896,6 +2005,22 @@ bool OTParty::LoadAndVerifyAssetAccounts(OTPseudonym & theServerNym,
return false;
}
// ----------------------
+ // Disallow duplicate Acct IDs.
+ // (Only can use an acct once inside a smart contract.)
+ //
+ std::set<std::string>::iterator it_acct_id = theAcctIDSet.find(strAcctID.Get());
+
+ if (theAcctIDSet.end() == it_acct_id) // It's not already there (good).
+ {
+ theAcctIDSet.insert(strAcctID.Get()); // Save a copy so we can make sure there's no duplicate acct IDs. (Not allowed.)
+ }
+ else
+ {
+ OTLog::vOutput(0, "OTParty::LoadAndVerifyAssetAccounts: Failure: Found a duplicate Acct ID (%s), on acct: %s.\n",
+ strAcctID.Get(), str_acct_name.c_str());
+ return false;
+ }
+ // ----------------------
mapOfAccounts::iterator ii = map_Accts_Already_Loaded.find(strAcctID.Get()); // If it's there, it's mapped by Acct ID, so we can look it up.
if (map_Accts_Already_Loaded.end() != ii) // Found it.
@@ -2818,7 +2943,7 @@ const char * OTClause::GetCode() const
void OTVariable::Serialize(OTString & strAppend)
{
// ---------------------------------------
- std::string str_access;
+ std::string str_access("");
switch (m_Access) {
case OTVariable::Var_Constant: // This cannot be changed from inside the script.
@@ -2831,28 +2956,49 @@ void OTVariable::Serialize(OTString & strAppend)
str_access = "important";
break;
default:
- str_access = "ERROR_ACCESS_TYPE";
+ OTLog::Error("OTVariable::Serialize: ERROR: Bad variable type.\n");
break;
}
// ---------------------------------------
std::string str_type;
switch (m_Type) {
case OTVariable::Var_String:
+ {
str_type = "string";
- strAppend.Concatenate("<variable name=\"%s\"\n"
- " value=\"%s\"\n"
- " type=\"%s\"\n",
- " access=\"%s\" />\n\n",
- m_strName.Get(),
- m_str_Value.c_str(),
- str_type.c_str(), str_access.c_str());
+
+ if (m_str_Value.size() > 0)
+ {
+ OTString strVal(m_str_Value.c_str());
+ OTASCIIArmor ascVal(strVal);
+ strAppend.Concatenate("<variable name=\"%s\"\n"
+ " value=\"%s\"\n"
+ " type=\"%s\"\n"
+ " access=\"%s\" >\n%s</variable>\n\n",
+ m_strName.Get(),
+ "exists",
+ str_type.c_str(),
+ str_access.c_str(),
+ ascVal.Get());
+ }
+ else
+ {
+ strAppend.Concatenate("<variable name=\"%s\"\n"
+ " value=\"%s\"\n"
+ " type=\"%s\"\n"
+ " access=\"%s\" />\n\n",
+ m_strName.Get(),
+ "none", // value
+ str_type.c_str(),
+ str_access.c_str());
+ }
+ }
break;
case OTVariable::Var_Long:
str_type = "long";
strAppend.Concatenate("<variable name=\"%s\"\n"
" value=\"%ld\"\n"
- " type=\"%s\"\n",
+ " type=\"%s\"\n"
" access=\"%s\" />\n\n",
m_strName.Get(),
m_lValue,
@@ -2862,7 +3008,7 @@ void OTVariable::Serialize(OTString & strAppend)
str_type = "bool";
strAppend.Concatenate("<variable name=\"%s\"\n"
" value=\"%s\"\n"
- " type=\"%s\"\n",
+ " type=\"%s\"\n"
" access=\"%s\" />\n\n",
m_strName.Get(),
m_bValue ? "true" : "false",
@@ -3676,6 +3822,33 @@ bool OTParty::Compare(const OTParty & rhs) const
return true;
}
+// When confirming a party, a new version replaces the original. This is part of that process.
+// *this is the old one, and theParty is the new one.
+//
+bool OTParty::CopyAcctsToConfirmingParty(OTParty & theParty) const
+{
+ theParty.CleanupAccounts(); // (We're going to copy our own accounts into theParty.)
+
+ FOR_EACH_CONST(mapOfPartyAccounts, m_mapPartyAccounts)
+ {
+ const std::string str_acct_name = (*it).first;
+ OTPartyAccount * pAcct = (*it).second;
+ OT_ASSERT(NULL != pAcct);
+ // ----------------------------------
+
+ if (false == theParty.AddAccount(pAcct->GetAgentName(), pAcct->GetName(),
+ pAcct->GetAcctID(), pAcct->GetAssetTypeID(),
+ pAcct->GetClosingTransNo()))
+ {
+ OTLog::vOutput(0, "OTParty::CopyAcctsToConfirmingParty: Unable to add Account %s, when copying from *this party %s. \n",
+ str_acct_name.c_str(), GetPartyName().c_str());
+ return false;
+ }
+ }
+ // -----------------------------------
+
+ return true;
+}
OTClause * OTBylaw::GetCallback(const std::string str_CallbackName)
@@ -4076,8 +4249,11 @@ OTBylaw::OTBylaw(const char * szName, const char * szLanguage) : m_pOwnerAgreeme
// Let the calling function validate these, if he doesn't want to risk an ASSERT...
//
- OT_ASSERT (OTScriptable::ValidateName(str_bylaw_name) &&
- OTScriptable::ValidateName(str_language));
+ if (!OTScriptable::ValidateName(str_bylaw_name) ||
+ !OTScriptable::ValidateName(str_language))
+ {
+ OTLog::Error("Failed validation in to OTBylaw::OTBylaw \n");
+ }
}
@@ -4243,12 +4419,18 @@ int OTStash::ReadFromXMLNode(irr::io::IrrXMLReader*& xml, const OTString & strSt
//
// Load up the stash items.
//
- int nCount = 0;
- if (strItemCount.Exists() && ( (nCount = atoi(strItemCount.Get()) > 0 )))
+ int nCount = strItemCount.Exists() ? atoi(strItemCount.Get()) : 0;
+ if (nCount > 0)
{
while (nCount-- > 0)
{
- xml->read();
+// xml->read();
+ if (false == OTContract::SkipToElement(xml))
+ {
+ OTLog::Output(0, "OTStash::ReadFromXMLNode: Failure: Unable to find expected element.\n");
+ return (-1);
+ }
+ // --------------------------------------
if ((xml->getNodeType() == EXN_ELEMENT) && (!strcmp("stashItem", xml->getNodeName())))
{
@@ -4281,6 +4463,10 @@ int OTStash::ReadFromXMLNode(irr::io::IrrXMLReader*& xml, const OTString & strSt
} // while
}
// --------------------------------
+ if (false == OTContract::SkipAfterLoadingField(xml)) // </stash>
+ { OTLog::Output(0, "*** OTStash::ReadFromXMLNode: Bad data? Expected EXN_ELEMENT_END here, but "
+ "didn't get it. Returning -1.\n"); return (-1); }
+
return 1;
}
View
23 OTLib/OTBylaw.h
@@ -263,6 +263,9 @@ class OTAgent
bool IsValidSigner(OTPseudonym & theNym);
+ bool IsAuthorizingAgentForParty(); // true/false whether THIS agent is the authorizing agent for his party.
+ int GetCountAuthorizedAccts(); // The number of accounts, owned by this agent's party, that this agent is the authorized agent FOR.
+
// ---------------------------------
// Only one of these can be true:
// (I wrestle with making these 2 calls private, since technically it should be irrelevant to the external.)
@@ -563,7 +566,7 @@ class OTParty
// ----------------------
OTParty();
- OTParty(const char * szName, bool bIsOwnerNym, const char * szOwnerID, const char * szAuthAgent);
+ OTParty(const char * szName, bool bIsOwnerNym, const char * szOwnerID, const char * szAuthAgent, const bool bCreateAgent=false);
OTParty(const std::string str_PartyName,
OTPseudonym & theNym, // Nym is BOTH owner AND agent, when using this constructor.
const std::string str_agent_name,
@@ -573,6 +576,10 @@ class OTParty
virtual ~OTParty();
+ void CleanupAgents();
+ void CleanupAccounts();
+
+
bool Compare(const OTParty & rhs) const;
// OTParty(const OTParty & rhs);
@@ -714,12 +721,7 @@ class OTParty
void RetrieveNymPointers(mapOfNyms & map_Nyms_Already_Loaded);
// ----------------------------------------
-
-
-
-
-
-
+
bool AddAccount(OTPartyAccount& thePartyAcct);
bool AddAccount(const OTString& strAgentName, const OTString& strName,
const OTString & strAcctID, const OTString & strAssetTypeID, const long lClosingTransNo);
@@ -734,13 +736,16 @@ class OTParty
// const std::string * pstr_account_name=NULL,
// const long lClosingTransNo=0);
- int GetAccountCount() const { return m_mapPartyAccounts.size(); }
+ int GetAccountCount() const { return m_mapPartyAccounts.size(); } // returns total of all accounts owned by this party.
+ int GetAccountCount(const std::string str_agent_name) const; // Only counts accounts authorized for str_agent_name.
// Get PartyAcct by name.
//
OTPartyAccount * GetAccount(const std::string & str_acct_name) const;
// by agent name
OTPartyAccount * GetAccountByAgent(const std::string & str_agent_name);
+ // by asset acct id
+ OTPartyAccount * GetAccountByID(const OTIdentifier & theAcctID);
// If account is present for Party, set account's pointer to theAccount and return true.
//
@@ -752,6 +757,8 @@ class OTParty
const OTString & strServerID,
const bool bBurnTransNo=false);
+ bool CopyAcctsToConfirmingParty(OTParty & theParty) const; // When confirming a party, a new version replaces the original. This is part of that process.
+
// ------------------------------------------------------
bool LoadAndVerifyAgentNyms(OTPseudonym & theServerNym,
mapOfNyms & map_Nyms_Already_Loaded,
View
199 OTLib/OTContract.cpp
@@ -1972,7 +1972,102 @@ bool OTContract::LoadContractXML()
// -------------------------------------------------------------
+bool OTContract::SkipToElement(IrrXMLReader*& xml)
+{
+ OT_ASSERT_MSG(NULL != xml, "OTContract::SkipToElement -- assert: NULL != xml");
+
+ // ------------------
+ while(xml->read() && (xml->getNodeType() != EXN_ELEMENT))
+ {
+ if (xml->getNodeType() == EXN_NONE)
+ { OTLog::Output(0, "*** OTContract::SkipToElement: EXN_NONE (skipping)\n"); continue; } // SKIP
+ else if (xml->getNodeType() == EXN_COMMENT)
+ { OTLog::Output(0, "*** OTContract::SkipToElement: EXN_COMMENT (skipping)\n"); continue; } // SKIP
+ else if (xml->getNodeType() == EXN_ELEMENT_END)
+ { OTLog::Output(0, "*** OTContract::SkipToElement: EXN_ELEMENT_END (ERROR)\n"); return false; }
+ else if (xml->getNodeType() == EXN_CDATA)
+ { OTLog::Output(0, "*** OTContract::SkipToElement: EXN_CDATA (ERROR -- unexpected CData)\n"); return false; }
+ else if (xml->getNodeType() == EXN_TEXT)
+ { OTLog::Error("*** OTContract::SkipToElement: EXN_TEXT\n"); return false; }
+ else if (xml->getNodeType() == EXN_ELEMENT)
+ { OTLog::Output(0, "*** OTContract::SkipToElement: EXN_ELEMENT\n"); break; } // (Should never happen due to while() second condition.) Still returns true.
+ else
+ { OTLog::Error("*** OTContract::SkipToElement: SHOULD NEVER HAPPEN (Unknown element type!)\n"); return false; } // Failure / Error
+ }
+ // ------------------
+
+ return true;
+}
+
+bool OTContract::SkipToTextField(IrrXMLReader*& xml)
+{
+ OT_ASSERT_MSG(NULL != xml, "OTContract::SkipToTextField -- assert: NULL != xml");
+
+ // ------------------
+ while(xml->read() && (xml->getNodeType() != EXN_TEXT))
+ {
+ if (xml->getNodeType() == EXN_NONE)
+ { OTLog::Output(0, "*** OTContract::SkipToTextField: EXN_NONE (skipping)\n"); continue; } // SKIP
+ else if (xml->getNodeType() == EXN_COMMENT)
+ { OTLog::Output(0, "*** OTContract::SkipToTextField: EXN_COMMENT (skipping)\n"); continue; } // SKIP
+ else if (xml->getNodeType() == EXN_ELEMENT_END)
+ { OTLog::Output(0, "*** OTContract::SkipToTextField: EXN_ELEMENT_END (ERROR)\n"); return false; }
+ else if (xml->getNodeType() == EXN_CDATA)
+ { OTLog::Output(0, "*** OTContract::SkipToTextField: EXN_CDATA (ERROR -- unexpected CData)\n"); return false; }
+ else if (xml->getNodeType() == EXN_ELEMENT)
+ { OTLog::Output(0, "*** OTContract::SkipToTextField: EXN_ELEMENT\n"); return false; }
+ else if (xml->getNodeType() == EXN_TEXT)
+ { OTLog::Error("*** OTContract::SkipToTextField: EXN_TEXT\n"); break; } // (Should never happen due to while() second condition.) Still returns true.
+ else
+ { OTLog::Error("*** OTContract::SkipToTextField: SHOULD NEVER HAPPEN (Unknown element type!)\n"); return false; } // Failure / Error
+ }
+ // ------------------
+
+ return true;
+}
+
+// ---------------
+// AFTER you read an element or text field, there is some whitespace, and you
+// just want to bring your cursor back to wherever it should be for the next guy.
+// So you call this function..
+//
+bool OTContract::SkipAfterLoadingField(IrrXMLReader*& xml)
+{
+ OT_ASSERT_MSG(NULL != xml, "OTContract::SkipAfterLoadingField -- assert: NULL != xml");
+
+ if (EXN_ELEMENT_END != xml->getNodeType()) // If we're not ALREADY on the ending element, then go there.
+ {
+ // move to the next node which SHOULD be the expected element_end.
+ //
+ while(xml->read())
+ {
+ if (xml->getNodeType() == EXN_NONE)
+ { OTLog::Output(0, "*** OTContract::SkipAfterLoadingField: EXN_NONE (skipping)\n"); continue; } // SKIP
+ else if (xml->getNodeType() == EXN_COMMENT)
+ { OTLog::Output(0, "*** OTContract::SkipAfterLoadingField: EXN_COMMENT (skipping)\n"); continue; } // SKIP
+ else if (xml->getNodeType() == EXN_ELEMENT_END)
+ { OTLog::Output(5, "*** OTContract::SkipAfterLoadingField: EXN_ELEMENT_END (success)\n"); break; } // Success...
+ else if (xml->getNodeType() == EXN_CDATA)
+ { OTLog::Output(0, "*** OTContract::SkipAfterLoadingField: EXN_CDATA (Unexpected!)\n"); return false; } // Failure / Error
+ else if (xml->getNodeType() == EXN_ELEMENT)
+ { OTLog::Output(0, "*** OTContract::SkipAfterLoadingField: EXN_ELEMENT (Unexpected!)\n"); return false; } // Failure / Error
+ else if (xml->getNodeType() == EXN_TEXT)
+ { OTLog::Error("*** OTContract::SkipAfterLoadingField: EXN_TEXT (Unexpected!)\n"); return false; } // Failure / Error
+ else
+ { OTLog::Error("*** OTContract::SkipAfterLoadingField: SHOULD NEVER HAPPEN (Unknown element type!)\n"); return false; } // Failure / Error
+ }
+ }
+ // ------------------
+ // else ... (already on the ending element.)
+ //
+ // ------------------
+
+ return true;
+}
+
+
// Loads it up and also decodes it to a string.
+//
bool OTContract::LoadEncodedTextField(IrrXMLReader*& xml, OTString & strOutput)
{
OTASCIIArmor ascOutput;
@@ -1985,13 +2080,28 @@ bool OTContract::LoadEncodedTextField(IrrXMLReader*& xml, OTString & strOutput)
return false;
}
-// Loads it up and keeps it encoded in an ascii-armored object.
+// ---------------
+
bool OTContract::LoadEncodedTextField(IrrXMLReader*& xml, OTASCIIArmor & ascOutput)
{
- // go to the next node and read the text.
- xml->read();
+ OT_ASSERT_MSG(NULL != xml, "OTContract::LoadEncodedTextField -- assert: NULL != xml");
- if (EXN_TEXT == xml->getNodeType())
+ // ------------------
+ // If we're not ALREADY on a text field, maybe there is some whitespace, so let's skip ahead...
+ //
+ if (EXN_TEXT != xml->getNodeType())
+ {
+ // move to the next node which SHOULD be the expected text field.
+ //
+ if (false == SkipToTextField(xml))
+ {
+ OTLog::Output(0, "OTContract::LoadEncodedTextField: Failure: Unable to find expected text field.\n");
+ return false;
+ }
+ }
+ // ------------------
+ //
+ if (EXN_TEXT == xml->getNodeType()) // SHOULD always be true, in fact this could be an assert().
{
OTString strNodeData = xml->getNodeData();
@@ -2011,11 +2121,20 @@ bool OTContract::LoadEncodedTextField(IrrXMLReader*& xml, OTASCIIArmor & ascOutp
ascOutput.Set(strNodeData.Get());
}
- xml->read(); // THIS PUTS us on the CLOSING TAG.
-
+ // ----------------------------------------
+ // SkipAfterLoadingField() only skips ahead if it's not ALREADY
+ // sitting on an element_end node.
+ //
+ xml->read(); // THIS PUTS us on the CLOSING TAG. <========================
+ // The below call won't advance any further if it's ALREADY on the closing tag (e.g. from the above xml->read() call.)
+ if (false == SkipAfterLoadingField(xml))
+ { OTLog::Output(0, "*** OTContract::LoadEncodedTextField: Bad data? Expected EXN_ELEMENT_END here, but "
+ "didn't get it. Returning false.\n"); return false; }
return true;
}
}
+ else
+ OTLog::Output(0, "OTContract::LoadEncodedTextField: Failure: Unable to find expected text field. 2\n");
return false;
}
@@ -2045,46 +2164,72 @@ bool OTContract::LoadEncodedTextFieldByName(IrrXMLReader*& xml, OTASCIIArmor & a
{
OT_ASSERT(NULL != szName);
- // move to the next node which SHOULD be the expected name.
- xml->read();
-
const char * pElementExpected = szName;
- if (EXN_ELEMENT == xml->getNodeType())
+ // ------------------
+ // If we're not ALREADY on an element, maybe there is some whitespace, so let's skip ahead...
+ //
+ if ((EXN_ELEMENT != xml->getNodeType()) || // If we're not already on a node, OR if the node's
+ !(strcmp(pElementExpected, xml->getNodeName()) == 0) ) // name doesn't match the one expected.
+ {
+ // move to the next node which SHOULD be the expected name.
+ //
+ if (false == SkipToElement(xml))
+ {
+ OTLog::vOutput(0, "OTContract::LoadEncodedTextFieldByName: Failure: Unable to find expected element: %s. \n",
+ szName);
+ return false;
+ }
+ }
+ // ------------------
+ if (EXN_ELEMENT == xml->getNodeType()) // SHOULD always be true...
{
if (!strcmp(pElementExpected, xml->getNodeName()))
{
// ----------------------------------------
-
+
if (NULL != pmapExtraVars) // If the caller wants values for certain names expected to be on this node.
{
mapOfStrings & mapExtraVars = (*pmapExtraVars);
FOR_EACH(mapOfStrings, mapExtraVars)
- {
+ {
+
std::string first = ((*it).first);
// std::string second = ((*it).second);
-
+
OTString strTemp = xml->getAttributeValue(first.c_str());
-
+
if (strTemp.Exists())
{
- mapExtraVars.erase(first);
- mapExtraVars.insert(std::pair<std::string, std::string>(first, strTemp.Get()));
+ mapExtraVars[first] = strTemp.Get();
+
+// mapExtraVars.erase(first);
+// mapExtraVars.insert(std::pair<std::string, std::string>(first, strTemp.Get()));
}
}
} // Any attribute names passed in, now have their corresponding values set on mapExtraVars (for caller.)
// ----------------------------------------
- if (false == LoadEncodedTextField(xml, ascOutput))
+ if (false == LoadEncodedTextField(xml, ascOutput)) // <====================================================
{
OTLog::vError("OTContract::LoadEncodedTextFieldByName: Error loading %s field.\n",
pElementExpected);
return false; // error condition
}
else
{
+ // ----------------------------------------
+ // SkipAfterLoadingField() only skips ahead if it's not ALREADY
+ // sitting on an element_end node.
+ //
+ // Update: Above, LoadEncodedTextField() already does this (below).
+ //
+// if (false == SkipAfterLoadingField(xml))
+// { OTLog::Output(0, "*** OTContract::LoadEncodedTextFieldByName: Bad data? Expected EXN_ELEMENT_END here, but "
+// "didn't get it. Returning false.\n"); return false; }
+
return true; // <============ SUCCESS!!!!
}
}
@@ -2141,7 +2286,15 @@ int OTContract::ProcessXMLNode(IrrXMLReader*& xml)
{
strConditionName = xml->getAttributeValue("name");
- xml->read();
+// xml->read();
+ // ------------------
+ if (false == SkipToTextField(xml))
+ {
+ OTLog::vOutput(0, "OTContract::ProcessXMLNode: Failure: Unable to find expected text field for xml node named: %s\n",
+ xml->getNodeName());
+ return (-1); // error condition
+ }
+ // ------------------
if (EXN_TEXT == xml->getNodeType())
{
@@ -2165,7 +2318,15 @@ int OTContract::ProcessXMLNode(IrrXMLReader*& xml)
{
strKeyName = xml->getAttributeValue("name");
- xml->read();
+// xml->read();
+ // ------------------
+ if (false == SkipToTextField(xml))
+ {
+ OTLog::vOutput(0, "OTContract::ProcessXMLNode: Failure: Unable to find expected text field for xml node named: %s\n",
+ xml->getNodeName());
+ return (-1); // error condition
+ }
+ // ------------------
if (EXN_TEXT == xml->getNodeType())
{
View
15 OTLib/OTContract.h
@@ -200,33 +200,44 @@ class OTContract
// -------------------------------------------------------------------
//
-
bool LoadContractXML(); // The XML file is in m_xmlUnsigned. Load it from there into members here.
+ // -------------------------------------------------------------------
bool LoadEncodedTextField(irr::io::IrrXMLReader*& xml, OTString &strOutput);
bool LoadEncodedTextField(irr::io::IrrXMLReader*& xml, OTASCIIArmor &ascOutput);
bool LoadEncodedTextFieldByName(irr::io::IrrXMLReader*& xml, OTString &strOutput,
const char *& szName, mapOfStrings * pmapExtraVars = NULL);
bool LoadEncodedTextFieldByName(irr::io::IrrXMLReader*& xml, OTASCIIArmor &ascOutput,
const char *& szName, mapOfStrings * pmapExtraVars = NULL);
-
+ // -------------------------------------------------------------------
+
// return -1 if error, 0 if nothing, and 1 if the node was processed.
virtual int ProcessXMLNode(irr::io::IrrXMLReader*& xml);
+ // -------------------------------------------------------------------
virtual bool SignContract(const EVP_PKEY * pkey, OTSignature & theSignature,
const OTString & strHashType);
+ // -------------------------------------------------------------------
bool VerifySignature(const EVP_PKEY * pkey, const OTSignature & theSignature,
const OTString & strHashType) const;
+ // -------------------------------------------------------------------
// The default hash scheme involves combining 2 other hashes
// If a hash with one of the special names comes through, it will
// be processed here instead of the normal code. The above two functions
// will call these two when appropriate.
bool SignContractDefaultHash(const EVP_PKEY * pkey, OTSignature & theSignature);
bool VerifyContractDefaultHash(const EVP_PKEY * pkey, const OTSignature & theSignature) const;
+ // -------------------------------------------------------------------
public:
+ static bool SkipToElement(IrrXMLReader*& xml);
+ static bool SkipToTextField(IrrXMLReader*& xml);
+ static bool SkipAfterLoadingField(IrrXMLReader*& xml);
+
+ // -------------------------------------------------------------------
+
inline const char * GetHashType() const { return m_strSigHashType.Get(); }
inline void SetIdentifier(const OTIdentifier & theID) { m_ID = theID; }
View
34 OTLib/OTCron.cpp
@@ -534,8 +534,21 @@ int OTCron::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
OTLog::Error("Unable to create cron item from data in cron file.\n");
return (-1);
}
+ // -------------------------------------------
- if (AddCronItem(*pItem, NULL, false)) // bSaveReceipt=false. The receipt is only saved once: When item FIRST added to cron.
+ // Why not do this here (when loading from storage), as well as when first adding the item to cron,
+ // and thus save myself the trouble of verifying the signature EVERY ITERATION of ProcessCron().
+ //
+ if (false == pItem->VerifySignature(*m_pServerNym))
+ {
+ OTLog::vError("OTCron::ProcessXMLNode: ERROR SECURITY: Server signature failed to "
+ "verify on a cron item while loading: %ld\n", pItem->GetTransactionNum());
+ delete pItem;
+ pItem = NULL;
+ return (-1);
+ }
+ // -------------------------------------------
+ else if (AddCronItem(*pItem, NULL, false)) // bSaveReceipt=false. The receipt is only saved once: When item FIRST added to cron.
{ // But here, the item was ALREADY in cron, and is merely being loaded from disk. Thus,
// it would be wrong to try to create the "original record" as if it were brand new
// and still had the user's signature on it. (Once added to Cron, the signatures are
@@ -545,7 +558,8 @@ int OTCron::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
}
else
{
- OTLog::Error("Though loaded successfully, unable to add cron item (from cron file) to cron list.\n");
+ OTLog::Error("OTCron::ProcessXMLNode: Though loaded / verified successfully, unable to add cron item "
+ "(from cron file) to cron list.\n");
delete pItem;
pItem = NULL;
return (-1);
@@ -696,10 +710,16 @@ void OTCron::ProcessCronItems()
OTCronItem * pItem = (*it).second;
OT_ASSERT(NULL != pItem);
- bool bVerifySig = pItem->VerifySignature(*m_pServerNym);
+// bool bVerifySig = pItem->VerifySignature(*m_pServerNym);
bool bProcessCron = false;
- if (bVerifySig)
+ // We already verify and sign the cron item when FIRST ADDING it to Cron.
+ // We also verify the signature on the cron item whenever loading it up
+ // from storage.
+ // THEREFORE, FOR NOW, I'VE DECIDED THAT VERIFYING THE SIGNATURE AGAIN
+ // (HERE) IS OVERKILL, SO IT's COMMENTED OUT.
+ //
+// if (bVerifySig)
{
bProcessCron = pItem->ProcessCron();
@@ -709,16 +729,16 @@ void OTCron::ProcessCronItems()
if (false == bProcessCron)
pItem->HookRemovalFromCron(NULL); // We give the hook a chance to do its thing.
}
- else
- OTLog::Error("OTCron::ProcessCronItems: Signature failed to verify on cron item!\n");
+// else
+// OTLog::Error("OTCron::ProcessCronItems: Signature failed to verify on cron item!\n");
// -----------------------------------------------------
// Remove it from the list.
//
if (false == bProcessCron)
{
- OTLog::vOutput(0, "OTCron::ProcessCronItems: Removing expired or unverified cron item.\n");
+ OTLog::vOutput(0, "OTCron::ProcessCronItems: Removing expired cron item.\n");
m_mapCronItems.erase(it++);
delete pItem;
pItem = NULL;
View
9 OTLib/OTInstrument.cpp
@@ -151,7 +151,11 @@ bool OTInstrument::IsExpired()
{
const time_t CURRENT_TIME = time(NULL);
- if (CURRENT_TIME >= m_VALID_TO)
+ // If the current time is AFTER the valid-TO date,
+ // AND the valid_to is a nonzero number (0 means "doesn't expire")
+ // THEN return true (it's expired.)
+ //
+ if ((CURRENT_TIME >= m_VALID_TO) && (m_VALID_TO > 0))
return true;
else
return false;
@@ -163,7 +167,8 @@ bool OTInstrument::VerifyCurrentDate()
{
const time_t CURRENT_TIME = time(NULL);
- if ((CURRENT_TIME >= m_VALID_FROM) && (CURRENT_TIME <= m_VALID_TO))
+ if ((CURRENT_TIME >= m_VALID_FROM) &&
+ ((CURRENT_TIME <= m_VALID_TO) || (0 == m_VALID_TO)))
return true;
else
return false;
View
0 OTLib/OTLib/stdafx.cpp 100755 → 100644
File mode changed.
View
0 OTLib/OTLib/stdafx.h 100755 → 100644
File mode changed.
View
0 OTLib/OTLib/targetver.h 100755 → 100644
File mode changed.
View
323 OTLib/OTScriptable.cpp
@@ -271,7 +271,8 @@ void OTScriptable::RegisterOTNativeCallsWithScript(OTScript & theScript)
if (NULL != pScript)
{
- pScript->chai.add(fun(&OTScriptable::CanExecuteClause, (*this)), "party_may_execute_clause");
+ pScript->chai.add(fun(&OTScriptable::CanExecuteClause, this), "party_may_execute_clause");
+// pScript->chai.add(fun(&OTScriptable::CanExecuteClause, (*this)), "party_may_execute_clause");
}
// else if (NULL != (pScript = dynamic_cast<OTScriptSomeOtherScriptingLanguageSubClass_GOES_HERE *> (&theScript)) )
// { }
@@ -806,6 +807,38 @@ void OTScriptable::SetAsClean()
}
+// Note: this maybe would have been more appropriate on OTSmartContract, since that is
+// where the opening/closing numbers are actually USED. But still, they ARE stored HERE,
+// so I might as well put the function here also. That way later on, if some new subclass
+// uses those numbers, it will have access to count them as well.
+//
+// Returns 0 if this agent is not the authorizing agent for a party, and is also not the
+// authorized agent for any party's accounts.
+//
+int OTScriptable::GetCountTransNumsNeededForAgent(const std::string str_agent_name)
+{
+ int nReturnVal = 0;
+
+ OTAgent * pAgent = this->GetAgent(str_agent_name);
+ if (NULL == pAgent)
+ return nReturnVal; // (Looks like there is no agent with that name.)
+
+ // Below this point, pAgent is good, meaning str_agent_name really IS
+ // a legit agent for this party. But that doesn't necessarily mean the
+ // agent has to supply any opening or closing transaction #s for this
+ // smart contract. That's only true if he's the AUTHORIZING agent for
+ // the party (for the opening num) or the authorized agent for any of
+ // party's accounts (for the closing number). So let's add it up...
+ //
+ if (pAgent->IsAuthorizingAgentForParty()) // true/false whether THIS agent is the authorizing agent for his party.
+ nReturnVal++;
+
+ // Add the number of accounts, owned by this agent's party, that this agent is the authorized agent FOR.
+ //
+ nReturnVal += pAgent->GetCountAuthorizedAccts();
+
+ return nReturnVal;
+}
OTParty * OTScriptable::FindPartyBasedOnNymAsAgent(OTPseudonym & theNym, OTAgent ** ppAgent/*=NULL*/)
@@ -980,8 +1013,10 @@ bool OTScriptable::VerifyPartyAuthorization(OTParty & theParty, // The party
if (NULL != pAuthAgentsNym) // success
{
OT_ASSERT(NULL != pAuthorizingAgent); // This HAS to be set now. I assume it henceforth.
- OTLog::Output(0, "OTScriptable::VerifyPartyAuthorization: I just had to load the authorizing agent's Nym for a party, "
- "so I guess it wasn't already available on the list of Nyms that were already loaded.\n");
+ OTLog::vOutput(0, "OTScriptable::VerifyPartyAuthorization: I just had to load "
+ "the authorizing agent's Nym for a party (%s), "
+ "so I guess it wasn't already available on the list of "
+ "Nyms that were already loaded.\n", theParty.GetPartyName().c_str());
theAgentNymAngel.SetCleanupTarget(*pAuthAgentsNym); // CLEANUP!!
}
else
@@ -1009,7 +1044,6 @@ bool OTScriptable::VerifyPartyAuthorization(OTParty & theParty, // The party
if (lOpeningNo > 0) // If one exists, then verify it.
{
if (false == pAuthorizingAgent->VerifyIssuedNumber(lOpeningNo, strServerID))
-// if (false == pAuthAgentsNym->VerifyIssuedNum(strServerID, lOpeningNo))
{
OTLog::vError("OTScriptable::VerifyPartyAuthorization: Opening trans number %ld doesn't "
"verify for the nym listed as the authorizing agent for party %s.\n", lOpeningNo,
@@ -1024,7 +1058,6 @@ bool OTScriptable::VerifyPartyAuthorization(OTParty & theParty, // The party
else if (bBurnTransNo)
{
if (false == pAuthorizingAgent->VerifyTransactionNumber(lOpeningNo, strServerID))
-// if (false == pAuthAgentsNym->VerifyTransactionNum(strServerID, lOpeningNo))
{
OTLog::vError("OTScriptable::VerifyPartyAuthorization: Opening trans number %ld doesn't "
"verify as available for use, for the nym listed as the authorizing agent for party: %s.\n", lOpeningNo,
@@ -1160,7 +1193,8 @@ bool OTScriptable::VerifyNymAsAgent(OTPseudonym & theNym,
//
if (false == pParty->GetMySignedCopy().Exists())
{
- OTLog::Output(0, "OTScriptable::VerifyNymAsAgent: Unable to find party's signed copy of this contract. Has it been executed?\n");
+ OTLog::vOutput(0, "OTScriptable::VerifyNymAsAgent: Unable to find party's (%s) signed copy of "
+ "this contract. Has it been executed?\n", pParty->GetPartyName().c_str());
return false;
}
@@ -1210,14 +1244,15 @@ bool OTScriptable::VerifyNymAsAgent(OTPseudonym & theNym,
if (NULL != pAuthAgentsNym) // success
{
OT_ASSERT(NULL != pAuthorizingAgent); // This HAS to be set now. I assume it henceforth.
- OTLog::Output(0, "OTScriptable::VerifyNymAsAgent: I just had to load the authorizing agent's Nym for a party, "
- "so I guess it wasn't already available on the list of Nyms that were already loaded.\n");
+ OTLog::vOutput(0, "OTScriptable::VerifyNymAsAgent: I just had to load the authorizing agent's Nym for a party (%s), "
+ "so I guess it wasn't already available on the list of Nyms that were already loaded.\n",
+ pParty->GetPartyName().c_str());
theAgentNymAngel.SetCleanupTarget(*pAuthAgentsNym); // CLEANUP!!
}
else
{
- OTLog::Error("OTScriptable::VerifyNymAsAgent: Error: Strange, unable to load authorizing "
- "agent's Nym (to verify his signature.)\n");
+ OTLog::vError("OTScriptable::VerifyNymAsAgent: Error: Strange, unable to load authorizing "
+ "agent's Nym for party %s (to verify his signature.)\n", pParty->GetPartyName().c_str());
pParty->ClearTemporaryPointers();
return false;
}
@@ -1246,7 +1281,8 @@ bool OTScriptable::VerifyNymAsAgent(OTPseudonym & theNym,
if (NULL == pPartySignedCopy)
{
- OTLog::Error("OTScriptable::VerifyNymAsAgent: Error loading party's signed copy of agreement. Has it been executed?\n");
+ OTLog::vError("OTScriptable::VerifyNymAsAgent: Error loading party's (%s) signed copy of agreement. Has it been executed?\n",
+ pParty->GetPartyName().c_str());
pParty->ClearTemporaryPointers();
return false;
}
@@ -1676,17 +1712,20 @@ OTBylaw * OTScriptable::GetBylaw(const std::string str_bylaw_name)
}
// -----------------------------------------------------------
- mapOfBylaws::iterator it = m_mapBylaws.find(str_bylaw_name);
+ mapOfBylaws::iterator iii = m_mapBylaws.find(str_bylaw_name);
- if (m_mapBylaws.end() == it) // Did NOT find it.
+ if (m_mapBylaws.end() == iii) // Did NOT find it.
{
- OTLog::vOutput(0, "OTScriptable::GetBylaw: Strange: bylaw not found: %s\n",
- str_bylaw_name.c_str());
+ // People call this function sometimes just to SEE if one is there.
+ // So it's not an error if it's not there...
+ //
+// OTLog::vOutput(0, "OTScriptable::GetBylaw: Strange: bylaw not found: %s. Bylaw count is: %d \n",
+// str_bylaw_name.c_str(), m_mapBylaws.size());
return NULL;
}
// ----------------------------------------
- OTBylaw * pBylaw = (*it).second;
+ OTBylaw * pBylaw = (*iii).second;
OT_ASSERT(NULL != pBylaw);
return pBylaw;
@@ -1707,8 +1746,11 @@ OTParty * OTScriptable::GetParty(const std::string str_party_name)
if (m_mapParties.end() == it) // Did NOT find it.
{
- OTLog::vOutput(0, "OTScriptable::GetParty: Strange: party not found: %s\n",
- str_party_name.c_str());
+ // GetParty() is often called to SEE if a party is there.
+ // (So if the party ain't there, it's not necessarily an error.)
+ //
+// OTLog::vOutput(0, "OTScriptable::GetParty: Strange: party not found: %s\n",
+// str_party_name.c_str());
return NULL;
}
// ----------------------------------------
@@ -1900,7 +1942,7 @@ bool OTScriptable::AddParty(OTParty & theParty)
bool OTScriptable::AddBylaw(OTBylaw & theBylaw)
{
- const std::string str_name = theBylaw.GetName().Exists() ? theBylaw.GetName().Get() : "";
+ const std::string str_name = theBylaw.GetName().Get();
if (false == OTScriptable::ValidateName(str_name)) // this logs, FYI.
{
@@ -2023,25 +2065,28 @@ bool OTScriptable::Compare(OTScriptable & rhs)
void OTScriptable::UpdateContentsToString(OTString & strAppend)
{
- strAppend.Concatenate("<scriptableContract>\n\n");
-
- FOR_EACH(mapOfParties, m_mapParties)
+ if ((m_mapParties.size()>0) || (m_mapBylaws.size()>0))
{
- OTParty * pParty = (*it).second;
- OT_ASSERT(NULL != pParty);
+ strAppend.Concatenate("<scriptableContract>\n\n");
- pParty->Serialize(strAppend);
- }
-
- FOR_EACH(mapOfBylaws, m_mapBylaws)
- {
- OTBylaw * pBylaw = (*it).second;
- OT_ASSERT(NULL != pBylaw);
+ FOR_EACH(mapOfParties, m_mapParties)
+ {
+ OTParty * pParty = (*it).second;
+ OT_ASSERT(NULL != pParty);
+
+ pParty->Serialize(strAppend);
+ }
- pBylaw->Serialize(strAppend);
+ FOR_EACH(mapOfBylaws, m_mapBylaws)
+ {
+ OTBylaw * pBylaw = (*it).second;
+ OT_ASSERT(NULL != pBylaw);
+
+ pBylaw->Serialize(strAppend);
+ }
+
+ strAppend.Concatenate("</scriptableContract>\n\n");
}
-
- strAppend.Concatenate("</scriptableContract>\n\n");
}
@@ -2108,23 +2153,30 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
OTParty * pParty = new OTParty(strName.Exists() ? strName.Get() : "PARTY_ERROR_NAME",
strOwnerType.Compare("nym") ? true : false,
- strOwnerID.Exists() ? strOwnerID.Get() : "PARTY_ERROR_OWNER_ID",
- strAuthAgent.Exists() ? strAuthAgent.Get() : "");
+ strOwnerID.Get(),
+ strAuthAgent.Get());
OT_ASSERT(NULL != pParty);
- pParty->SetOpeningTransNo(lOpeningTransNo);
+ pParty->SetOpeningTransNo(lOpeningTransNo); // WARNING: NEED TO MAKE SURE pParty IS CLEANED UP BELOW THIS POINT, IF FAILURE!!
// -----------------------------------------------
//
// Load up the agents.
//
- int nCount = 0;
- if (strNumAgents.Exists() && ( (nCount = atoi(strNumAgents.Get()) > 0 )))
+ int nCount = strNumAgents.Exists() ? atoi(strNumAgents.Get()) : 0;
+ if (nCount > 0)
{
while (nCount-- > 0)
{
- xml->read();
-
+// xml->read(); // <==================
+ if (false == SkipToElement(xml))
+ {
+ OTLog::Output(0, "OTScriptable::ProcessXMLNode: Failure: Unable to find expected element for agent. \n");
+ delete pParty; pParty=NULL;
+ return (-1);
+ }
+ // -----------------------------------------------
+
if ((xml->getNodeType() == EXN_ELEMENT) && (!strcmp("agent", xml->getNodeName())))
{
OTString strAgentName = xml->getAttributeValue("name"); // Agent name (if needed in script code)
@@ -2191,6 +2243,12 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
OTLog::Error("OTScriptable::ProcessXMLNode: Failed adding agent to party.\n");
return (-1);
}
+
+// xml->read(); // <==================
+
+ // MIGHT need to add "skip after element" here.
+
+ // Update: Nope.
}
else
{
@@ -2204,12 +2262,19 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
//
// LOAD PARTY ACCOUNTS.
//
- nCount = 0;
- if (strNumAccounts.Exists() && ( (nCount = atoi(strNumAccounts.Get()) > 0 )))
+ nCount = strNumAccounts.Exists() ? atoi(strNumAccounts.Get()) : 0;
+ if (nCount > 0)
{
while (nCount-- > 0)
{
- xml->read();
+// xml->read(); // <==================
+ if (false == OTContract::SkipToElement(xml))
+ {
+ OTLog::Error("OTScriptable::ProcessXMLNode: Error finding expected next element for party account.\n");
+ delete pParty; pParty=NULL;
+ return (-1);
+ }
+ // -----------------------------------------------
if ((xml->getNodeType() == EXN_ELEMENT) && (!strcmp("assetAccount", xml->getNodeName())))
{
@@ -2264,6 +2329,14 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
delete pParty; pParty=NULL;
return (-1);
}
+
+// xml->read(); // <==================
+
+
+ // MIGHT need to add "skip after field" call here.
+
+ // UPdate: Nope. Not here.
+
}
else
{
@@ -2293,6 +2366,15 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
pParty->SetMySignedCopy(strTextExpected);
}
+
+ // --------------------------------
+ if (false == SkipAfterLoadingField(xml)) // </party>
+ {
+ OTLog::Output(0, "*** OTScriptable::ProcessXMLNode: Bad data? Expected EXN_ELEMENT_END here, but "
+ "didn't get it. Failure.\n");
+ delete pParty; pParty=NULL;
+ return (-1);
+ }
// --------------------------------
if (AddParty(*pParty))
@@ -2305,7 +2387,7 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
}
nReturnVal = 1;
- }
+ } // "party"
// ----------------------------------------------------------------------------------
@@ -2319,26 +2401,32 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
OTString strNumHooks = xml->getAttributeValue("numHooks"); // hooks to server events.
OTString strNumCallbacks = xml->getAttributeValue("numCallbacks"); // Callbacks the server may initiate, when it needs answers.
- OTBylaw * pBylaw = new OTBylaw(strName.Exists() ? strName.Get() : "",
- strLanguage.Exists() ? strLanguage.Get() : "" );
+ OTBylaw * pBylaw = new OTBylaw(strName.Get(), strLanguage.Get());
OT_ASSERT(NULL != pBylaw);
// ---------------------------------------------------------------------------
//
// LOAD VARIABLES AND CONSTANTS.
//
- int nCount = 0;
- if (strNumVariable.Exists() && ( (nCount = atoi(strNumVariable.Get()) > 0 )))
+ int nCount = strNumVariable.Exists() ? atoi(strNumVariable.Get()) : 0;
+ if (nCount > 0)
{
while (nCount-- > 0)
{
- xml->read();
+// xml->read(); // <==================
+ if (false == OTContract::SkipToElement(xml))
+ {
+ OTLog::Error("OTScriptable::ProcessXMLNode: Error finding expected next element for variable.\n");
+ delete pBylaw; pBylaw=NULL;
+ return (-1);
+ }
+ // -----------------------------------------------
if ((xml->getNodeType() == EXN_ELEMENT) && (!strcmp("variable", xml->getNodeName())))
{
OTString strVarName = xml->getAttributeValue("name"); // Variable name (if needed in script code)
- OTString strVarValue = xml->getAttributeValue("value"); // Value stored in variable
+ OTString strVarValue = xml->getAttributeValue("value"); // Value stored in variable (If this is "true" then a real value is expected in a text field below. Otherwise, it's assumed to be a BLANK STRING.)
OTString strVarType = xml->getAttributeValue("type"); // string or long
OTString strVarAccess = xml->getAttributeValue("access"); // constant, persistent, or important.
@@ -2378,6 +2466,9 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
theVarType = OTVariable::Var_String;
else if (strVarType.Compare("bool"))
theVarType = OTVariable::Var_Bool;
+ else
+ OTLog::vError("OTScriptable::ProcessXMLNode: Bad variable type: %s.\n", strVarType.Get());
+
// ---------
OTVariable::OTVariable_Access theVarAccess = OTVariable::Var_Error_Access;
@@ -2388,6 +2479,9 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
theVarAccess = OTVariable::Var_Persistent;
else if (strVarAccess.Compare("important"))
theVarAccess = OTVariable::Var_Important;
+ else
+ OTLog::vError("OTScriptable::ProcessXMLNode: Bad variable access type: %s.\n", strVarAccess.Get());
+
// ---------
if ((OTVariable::Var_Error_Access == theVarAccess) ||
@@ -2401,14 +2495,15 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
// ---------------------------------------
bool bAddedVar = false;
+ const std::string str_var_name = strVarName.Get();
switch (theVarType)
{
case OTVariable::Var_Long:
if (strVarValue.Exists())
{
const long lVarValue = atol(strVarValue.Get());
- bAddedVar = pBylaw->AddVariable(strVarName.Get(), lVarValue, theVarAccess);
+ bAddedVar = pBylaw->AddVariable(str_var_name, lVarValue, theVarAccess);
}
else
{
@@ -2423,7 +2518,6 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
if (strVarValue.Exists())
{
const bool bVarValue = strVarValue.Compare("true") ? true : false;
- const std::string str_var_name = strVarName.Get();
bAddedVar = pBylaw->AddVariable(str_var_name, bVarValue, theVarAccess);
}
else
@@ -2436,8 +2530,26 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
break;
// ---------------------------------
case OTVariable::Var_String:
- //if (strVarValue.Exists()) // I realized I should probably allow empty strings.
- bAddedVar = pBylaw->AddVariable(strVarName.Get(), strVarValue.Exists() ? strVarValue.Get() : "", theVarAccess);
+ {
+ // I realized I should probably allow empty strings. :-P
+ if (strVarValue.Exists() && strVarValue.Compare("exists"))
+ {
+ strVarValue.Release(); // probably unnecessary.
+ if (false == LoadEncodedTextField(xml, strVarValue))
+ {
+ OTLog::vError("OTScriptable::ProcessXMLNode: No value found for string variable: %s\n",
+ strVarName.Get());
+ delete pBylaw; pBylaw=NULL;
+ return (-1);
+ }
+ // (else success)
+ }
+ else
+ strVarValue.Release(); // Necessary. If it's going to be a blank string, then let's make sure.
+
+ const std::string str_var_value = strVarValue.Get();
+ bAddedVar = pBylaw->AddVariable(str_var_name, str_var_value, theVarAccess);
+ }
break;
default:
OTLog::Error("OTScriptable::ProcessXMLNode: Wrong variable type... "
@@ -2453,6 +2565,20 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
delete pBylaw; pBylaw=NULL;
return (-1);
}
+
+// xml->read(); // <==================
+
+ // MIGHT NEED TO HAVE "SKIP AFTER" HERE...
+ // Update: Nope.
+
+
+// if (false == SkipAfterLoadingField(xml))
+// {
+// OTLog::Output(0, "*** OTScriptable::ProcessXMLNode: Bad data? Expected EXN_ELEMENT_END here, but "
+// "didn't get it. Failure.\n");
+// delete pBylaw; pBylaw=NULL;
+// return (-1);
+// }
}
else
{
@@ -2466,11 +2592,22 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
// ---------------------------------------------------------------------------
// LOAD CLAUSES
//
- nCount = 0;
- if (strNumClauses.Exists() && ( (nCount = atoi(strNumClauses.Get()) > 0 )))
- {
+ nCount = strNumClauses.Exists() ? atoi(strNumClauses.Get()) : 0;
+ if (nCount > 0)
+ {
while (nCount-- > 0)
- {
+ {
+ // LoadEncodedTextFieldByName() (below) does this stuff already. Commented out.
+ //
+// xml->read(); // <==================
+// if (false == OTContract::SkipToElement(xml))
+// {
+// OTLog::Error("OTScriptable::ProcessXMLNode: Error finding expected next element for variable.\n");
+// delete pBylaw; pBylaw=NULL;
+// return (-1);
+// }
+ // -----------------------------------------------
+
const char * pElementExpected = "clause";
OTString strTextExpected; // clause's script code will go here.
@@ -2489,7 +2626,7 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
// temp_MapAttributes.insert(std::pair<std::string, std::string>("name", ""));
// temp_MapAttributes.insert(std::pair<std::string, std::string>("name", ""));
- if (false == LoadEncodedTextFieldByName(xml, strTextExpected, pElementExpected, &temp_MapAttributes))
+ if (false == LoadEncodedTextFieldByName(xml, strTextExpected, pElementExpected, &temp_MapAttributes)) // </clause>
{
OTLog::vError("Error in OTScriptable::ProcessXMLNode: "
"Expected %s element with text field.\n",
@@ -2506,12 +2643,22 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
mapOfStrings::iterator it = temp_MapAttributes.find("name");
if ((it != temp_MapAttributes.end())) // We expected this much.
- {
+ {
std::string & str_name = (*it).second;
if (str_name.size() > 0) // SUCCESS
{
// ---------------------------------------
+
+// if (false == SkipAfterLoadingField(xml)) // NOt sure yet about this block....
+// {
+// OTLog::Output(0, "*** OTScriptable::ProcessXMLNode: Bad data? Expected EXN_ELEMENT_END here, but "
+// "didn't get it. Failure.\n");
+// delete pBylaw; pBylaw=NULL;
+// return (-1);
+// }
+ // *****************************************************
+
// See if the same-named clause already exists on ANY of the OTHER BYLAWS
// (There can only be one clause on an OTScriptable with a given name.)
//
@@ -2526,7 +2673,7 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
}
// ---------------------------------------------------------
else if (false == pBylaw->AddClause(str_name.c_str(),
- strTextExpected.Exists() ? strTextExpected.Get() : ""))
+ strTextExpected.Get()))
{
OTLog::Error("OTScriptable::ProcessXMLNode: Failed adding clause to bylaw.\n");
delete pBylaw; pBylaw=NULL;
@@ -2549,19 +2696,26 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
return (-1); // error condition
}
} // while
- } // if strNumClauses.Exists() && nCount > 0
-
+ } // if strNumClauses.Exists() && nCount > 0
+
// ---------------------------------------------------------------------------
//
// LOAD HOOKS.
//
- nCount = 0;
- if (strNumHooks.Exists() && ( (nCount = atoi(strNumHooks.Get()) > 0 )))
+ nCount = strNumHooks.Exists() ? atoi(strNumHooks.Get()) : 0;
+ if (nCount > 0)
{
while (nCount-- > 0)
{
- xml->read();
+// xml->read();
+ if (false == SkipToElement(xml))
+ {
+ OTLog::Output(0, "OTScriptable::ProcessXMLNode: Failure: Unable to find expected element.\n");
+ delete pBylaw; pBylaw=NULL;
+ return (-1);
+ }
+ // --------------------------------------
if ((xml->getNodeType() == EXN_ELEMENT) && (!strcmp("hook", xml->getNodeName())))
{
@@ -2585,6 +2739,8 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
return (-1);
}
// ---------------------------------------
+
+// xml->read(); // <================== NO NEED FOR THIS HERE.
}
else
{
@@ -2600,11 +2756,19 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
// LOAD CALLBACKS.
//
nCount = 0;
- if (strNumCallbacks.Exists() && ( (nCount = atoi(strNumCallbacks.Get()) > 0 )))
+ nCount = strNumCallbacks.Exists() ? atoi(strNumCallbacks.Get()) : 0;
+ if (nCount > 0)
{
while (nCount-- > 0)
{
- xml->read();
+// xml->read();
+ if (false == SkipToElement(xml))
+ {
+ OTLog::Output(0, "OTScriptable::ProcessXMLNode: Failure: Unable to find expected element.\n");
+ delete pBylaw; pBylaw=NULL;
+ return (-1);
+ }
+ // --------------------------------------
if ((xml->getNodeType() == EXN_ELEMENT) && (!strcmp("callback", xml->getNodeName())))
{
@@ -2645,6 +2809,8 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
return (-1);
}
// ---------------------------------------
+
+// xml->read(); // <================== NO NEED FOR THIS HERE.
}
else
{
@@ -2655,21 +2821,32 @@ int OTScriptable::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
} // while
}
- // ---------------------------------------------------------------
+ // --------------------------------
+ if (false == SkipAfterLoadingField(xml)) // </bylaw>
+ {
+ OTLog::Output(0, "*** OTScriptable::ProcessXMLNode: Bad data? Expected EXN_ELEMENT_END here, but "
+ "didn't get it. Failure.\n");
+ delete pBylaw; pBylaw=NULL;
+ return (-1);
+ }
+ // --------------------------------
if (AddBylaw(*pBylaw))
+ {
OTLog::vOutput(2, "OTScriptable: Loaded Bylaw: %s\n",
- pBylaw->GetName().Exists() ? pBylaw->GetName().Get() : "");
+ pBylaw->GetName().Get());
+
+ }
else
{
OTLog::vError("OTScriptable: Failed loading Bylaw: %s\n",
- pBylaw->GetName().Exists() ? pBylaw->GetName().Get() : "");
+ pBylaw->GetName().Get());
delete pBylaw; pBylaw = NULL;
return (-1); // error condition
}
nReturnVal = 1;
- }
+ } // "bylaw"
return nReturnVal;
}
View
8 OTLib/OTScriptable.h
@@ -175,6 +175,14 @@ class OTScriptable : public OTContract
OTAgent * GetAgent(const std::string str_agent_name);
OTPartyAccount * GetPartyAccount(const std::string str_acct_name);
+ // -----------------------------------------------------------------
+ // This function returns the count of how many trans#s a Nym needs in order to confirm as
+ // a specific agent for a contract. (An opening number is needed for every party of which
+ // agent is the authorizing agent, plus a closing number for every acct of which agent is the
+ // authorized agent.)
+ //
+ int GetCountTransNumsNeededForAgent(const std::string str_agent_name);
+
// ----------------
// Verifies that Nym is actually an agent for this agreement.
// (Verifies that Nym has signed this agreement, if it's a trade or a payment plan, OR
View
60 OTLib/OTSmartContract.cpp
@@ -668,18 +668,18 @@ void OTSmartContract::RegisterOTNativeCallsWithScript(OTScript & theScript)
// (These functions can be called from INSIDE the scripted clauses.)
// // Parameters must match as described below. Return value will be as described below.
// // -------------------------------------------------------------
- pScript->chai.add(fun(&OTSmartContract::MoveAcctFunds, (*this)), "move_funds"); // bool MoveAcctFunds(const std::string from_acct_name, const std::string to_acct_name, const long lAmount); // calls OTCronItem::MoveFunds()
- pScript->chai.add(fun(&OTSmartContract::StashAcctFunds, (*this)), "stash_funds"); // bool StashAcctFunds(const std::string from_acct_name, const std::string to_stash_name, const long lAmount); // calls StashFunds()
- pScript->chai.add(fun(&OTSmartContract::UnstashAcctFunds, (*this)), "unstash_funds"); // bool UnstashAcctFunds(const std::string to_acct_name, const std::string from_stash_name, const long lAmount); // calls StashFunds( lAmount * (-1) )
+ pScript->chai.add(fun(&OTSmartContract::MoveAcctFunds, this), "move_funds"); // bool MoveAcctFunds(const std::string from_acct_name, const std::string to_acct_name, const long lAmount); // calls OTCronItem::MoveFunds()
+ pScript->chai.add(fun(&OTSmartContract::StashAcctFunds, this), "stash_funds"); // bool StashAcctFunds(const std::string from_acct_name, const std::string to_stash_name, const long lAmount); // calls StashFunds()
+ pScript->chai.add(fun(&OTSmartContract::UnstashAcctFunds, this), "unstash_funds"); // bool UnstashAcctFunds(const std::string to_acct_name, const std::string from_stash_name, const long lAmount); // calls StashFunds( lAmount * (-1) )
- pScript->chai.add(fun(&OTSmartContract::GetAcctBalance, (*this)), "get_acct_balance"); // long GetAcctBalance(const std::string acct_name);
- pScript->chai.add(fun(&OTSmartContract::GetAssetTypeIDofAcct, (*this)), "get_acct_asset_type_id"); // std::string OTSmartContract::GetAssetTypeIDofAcct(const std::string from_acct_name)
- pScript->chai.add(fun(&OTSmartContract::GetStashBalance, (*this)), "get_stash_balance"); // long GetStashBalance(const std::string stash_name, const std::string asset_type_id);
+ pScript->chai.add(fun(&OTSmartContract::GetAcctBalance, this), "get_acct_balance"); // long GetAcctBalance(const std::string acct_name);
+ pScript->chai.add(fun(&OTSmartContract::GetAssetTypeIDofAcct, this), "get_acct_asset_type_id"); // std::string OTSmartContract::GetAssetTypeIDofAcct(const std::string from_acct_name)
+ pScript->chai.add(fun(&OTSmartContract::GetStashBalance, this), "get_stash_balance"); // long GetStashBalance(const std::string stash_name, const std::string asset_type_id);
- pScript->chai.add(fun(&OTSmartContract::SendNoticeToParty, (*this)), "send_notice"); // bool SendNoticeToParty(const std::string party_name);
- pScript->chai.add(fun(&OTSmartContract::SendANoticeToAllParties, (*this)), "send_notice_to_parties"); // bool SendANoticeToAllParties();
+ pScript->chai.add(fun(&OTSmartContract::SendNoticeToParty, this), "send_notice"); // bool SendNoticeToParty(const std::string party_name);
+ pScript->chai.add(fun(&OTSmartContract::SendANoticeToAllParties, this), "send_notice_to_parties"); // bool SendANoticeToAllParties();
- pScript->chai.add(fun(&OTSmartContract::DeactivateSmartContract, (*this)), "deactivate_contract"); // void DeactivateSmartContract();
+ pScript->chai.add(fun(&OTSmartContract::DeactivateSmartContract, this), "deactivate_contract"); // void DeactivateSmartContract();
// ---------------------------------------------------------
// CALLBACKS
@@ -688,7 +688,7 @@ void OTSmartContract::RegisterOTNativeCallsWithScript(OTScript & theScript)
//FYI: pScript->chai.add(fun(&(OTScriptable::CanExecuteClause), (*this)), "party_may_execute_clause"); // From OTScriptable (FYI) param_party_name and param_clause_name will be available inside script. Script must return bool.
//FYI: #define SCRIPTABLE_CALLBACK_PARTY_MAY_EXECUTE "callback_party_may_execute_clause" <=== THE CALLBACK WITH THIS NAME must be connected to a script clause, and then the clause will trigger when the callback is needed.
- pScript->chai.add(fun(&OTSmartContract::CanCancelContract, (*this)), "party_may_cancel_contract"); // param_party_name will be available inside script. Script must return bool.
+ pScript->chai.add(fun(&OTSmartContract::CanCancelContract, this), "party_may_cancel_contract"); // param_party_name will be available inside script. Script must return bool.
//FYI: #define SMARTCONTRACT_CALLBACK_PARTY_MAY_CANCEL "callback_party_may_cancel_contract" <=== THE CALLBACK WITH THIS NAME must be connected to a script clause, and then the clause will trigger when the callback is needed.
// Callback USAGE: Your clause, in your smart contract, may have whatever name you want. (Within limits.)
@@ -3093,12 +3093,11 @@ bool OTSmartContract::ProcessCron()
return true; // The Payment Plan is not yet valid, so we return. BUT, we also
// return TRUE, so it will STAY on Cron until it BECOMES valid.
-
// -----------------------------------------------------------------------------
if (GetCron()->GetTransactionCount() < 1)
{
- OTLog::Output(0, "Failed to process smart contract: Out of transaction numbers!\n");
+ OTLog::Output(0, "Failed to process smart contract: Cron is out of transaction numbers!\n");
return true;
}
@@ -3853,11 +3852,31 @@ bool OTSmartContract::VerifySmartContract(OTPseudonym & theNym, OTAccount & theA
(Don't I do something like that already?)
*/
+ bool bToBurnOrNotToBurn = bBurnTransNo;
+ // ------------------------------------------------
+ // If we're burning a number, but THIS party has the same opening # as
+ // the smart contract itself, then don't bother verifying / burning this
+ // specific number (since it's been done already, higher-up.)
+ //
+ if (bBurnTransNo && (this->GetTransactionNum() == pParty->GetOpeningTransNo()))
+ {
+ // In cases where we're supposed to burn the transaction number, we do that
+ // for ALL parties EXCEPT the one who has the same Opening# as the SmartContract
+ // has for its GetTransactionNum(). Why? Because that one was already burned, when
+ // the activating party (pParty) activated the smart contract. At that time, the normal
+ // transaction system inside OTServer burned the # as part of its process before even
+ // calling NotarizeSmartContract(). Therefore, by this point, we ASSUME that party's
+ // opening num has already JUST been verified, and we skip it, (continuing to verify
+ // all the others.)
+
+ bToBurnOrNotToBurn = false;
+ }
+ // ------------------------------------------------------------------
bool bIsPartyAuthorized = this->VerifyPartyAuthorization(*pParty, // The party that supposedly is authorized for this supposedly executed agreement.
theServerNym, // For verifying signature on the authorizing Nym, when loading it
strServerID, // For verifying issued num, need the serverID the # goes with.
&map_Nyms_Already_Loaded,
- bBurnTransNo); // bBurnTransNo = true (default is false)
+ bToBurnOrNotToBurn); // bBurnTransNo = true (default is false)
// By this point, we've verified that pParty->GetOpeningTransNo() really is ISSUED to pParty.
// After all, you can Verify a Party's Authorization even after the smart contract has been activated.
@@ -4283,12 +4302,14 @@ void OTSmartContract::UpdateContents()
// -------------------------------------------------------------
const OTString SERVER_ID (GetServerID()),
- ACTIVATOR_USER_ID (GetSenderUserID());
+ ACTIVATOR_USER_ID (GetSenderUserID()),
+ ACTIVATOR_ACCT_ID (GetSenderAcctID());
// OTSmartContract
m_xmlUnsigned.Concatenate("<smartContract\n version=\"%s\"\n"
" serverID=\"%s\"\n"
" activatorUserID=\"%s\"\n"
+ " activatorAcctID=\"%s\"\n"
" lastSenderUserID=\"%s\"\n"
" lastSenderAcctID=\"%s\"\n"
" lastRecipientUserID=\"%s\"\n"
@@ -4301,6 +4322,7 @@ void OTSmartContract::UpdateContents()
m_strVersion.Get(),
SERVER_ID.Get(),
ACTIVATOR_USER_ID.Get(),
+ ACTIVATOR_ACCT_ID.Get(),
m_strLastSenderUser.Get(),
m_strLastSenderAcct.Get(),
m_strLastRecipientUser.Get(),
@@ -4422,6 +4444,7 @@ int OTSmartContract::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
const OTString strServerID(xml->getAttributeValue("serverID"));
const OTString strActivatorUserID(xml->getAttributeValue("activatorUserID"));
+ const OTString strActivatorAcctID(xml->getAttributeValue("activatorAcctID"));
if (strServerID.Exists())
{
@@ -4433,6 +4456,11 @@ int OTSmartContract::ProcessXMLNode(irr::io::IrrXMLReader*& xml)
const OTIdentifier ACTIVATOR_USER_ID(strActivatorUserID);
SetSenderUserID(ACTIVATOR_USER_ID);
}
+ if (strActivatorAcctID.Exists())
+ {
+ const OTIdentifier ACTIVATOR_ACCT_ID(strActivatorAcctID);
+ SetSenderAcctID