Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
opentxs::OTSmartContract Class Reference

#include <OTSmartContract.hpp>

Inheritance diagram for opentxs::OTSmartContract:
Collaboration diagram for opentxs::OTSmartContract:

Public Member Functions

virtual void SetDisplayLabel (const std::string *pstrLabel=nullptr)
 
const OTStringGetLastSenderUserID () const
 
const OTStringGetLastSenderAcctID () const
 
const OTStringGetLastRecipientUserID () const
 
const OTStringGetLastRecipientAcctID () const
 
int32_t GetCountStashes () const
 
int32_t GetCountStashAccts () const
 
virtual bool Compare (OTScriptable &rhs) const
 
virtual bool CanRemoveItemFromCron (OTPseudonym &theNym)
 
virtual void HarvestOpeningNumber (OTPseudonym &theNym)
 
virtual void HarvestClosingNumbers (OTPseudonym &theNym)
 
void CloseoutOpeningNumbers (OTPseudonym *pSignerNym=nullptr)
 
void HarvestClosingNumbers (OTPseudonym *pSignerNym=nullptr, std::set< OTParty * > *pFailedParties=nullptr)
 
virtual bool ProcessCron ()
 
virtual bool HasTransactionNum (const int64_t &lInput) const
 
virtual void GetAllTransactionNumbers (OTNumList &numlistOutput) const
 
virtual bool AddParty (OTParty &theParty)
 
virtual bool ConfirmParty (OTParty &theParty)
 
EXPORT bool SetServerIDIfEmpty (const OTIdentifier &theID)
 
EXPORT bool VerifySmartContract (OTPseudonym &theNym, OTAccount &theAcct, OTPseudonym &theServerNym, bool bBurnTransNo=false)
 
EXPORT void PrepareToActivate (const int64_t &lOpeningTransNo, const int64_t &lClosingTransNo, const OTIdentifier &theUserID, const OTIdentifier &theAcctID)
 
bool CanCancelContract (std::string str_party_name)
 
void SetRemainingTimer (std::string str_seconds_from_now)
 
std::string GetRemainingTimer () const
 
bool MoveAcctFundsStr (std::string from_acct_name, std::string to_acct_name, std::string str_Amount)
 
bool StashAcctFunds (std::string from_acct_name, std::string to_stash_name, std::string str_Amount)
 
bool UnstashAcctFunds (std::string to_acct_name, std::string from_stash_name, std::string str_Amount)
 
std::string GetAcctBalance (std::string from_acct_name)
 
std::string GetStashBalance (std::string stash_name, std::string asset_type_id)
 
std::string GetAssetTypeIDofAcct (std::string from_acct_name)
 
bool SendNoticeToParty (std::string party_name)
 
bool SendANoticeToAllParties ()
 
void DeactivateSmartContract ()
 
virtual void RegisterOTNativeCallsWithScript (OTScript &theScript)
 
OTStashGetStash (std::string str_stash_name)
 
EXPORT void ExecuteClauses (mapOfClauses &theClauses, OTString *pParam=nullptr)
 
EXPORT bool StashFunds (const mapOfNyms &map_NymsAlreadyLoaded, const int64_t &lAmount, const OTIdentifier &PARTY_ACCT_ID, const OTIdentifier &PARTY_USER_ID, OTStash &theStash)
 
EXPORT OTSmartContract ()
 
EXPORT OTSmartContract (const OTIdentifier &SERVER_ID)
 
virtual EXPORT ~OTSmartContract ()
 
void InitSmartContract ()
 
virtual void Release ()
 
void Release_SmartContract ()
 
void ReleaseStashes ()
 
virtual bool IsValidOpeningNumber (const int64_t &lOpeningNum) const
 
virtual int64_t GetOpeningNumber (const OTIdentifier &theNymID) const
 
virtual int64_t GetClosingNumber (const OTIdentifier &theAcctID) const
 
virtual int32_t ProcessXMLNode (irr::io::IrrXMLReader *&xml)
 
virtual void UpdateContents ()
 
virtual bool SaveContractWallet (std::ofstream &ofs) const
 
- Public Member Functions inherited from opentxs::OTCronItem
 OTCronItem ()
 
bool DropFinalReceiptToInbox (const OTIdentifier &USER_ID, const OTIdentifier &ACCOUNT_ID, const int64_t &lNewTransactionNumber, const int64_t &lClosingNumber, const OTString &strOrigCronItem, OTString *pstrNote=nullptr, OTString *pstrAttachment=nullptr, OTAccount *pActualAcct=nullptr)
 
bool DropFinalReceiptToNymbox (const OTIdentifier &USER_ID, const int64_t &lNewTransactionNumber, const OTString &strOrigCronItem, OTString *pstrNote=nullptr, OTString *pstrAttachment=nullptr, OTPseudonym *pActualNym=nullptr)
 
void HookActivationOnCron (OTPseudonym *pActivator, bool bForTheFirstTime=false)
 
void HookRemovalFromCron (OTPseudonym *pRemover, int64_t newTransactionNo)
 
bool IsFlaggedForRemoval () const
 
void FlagForRemoval ()
 
void SetCronPointer (OTCron &theCron)
 
void SetCreationDate (const time64_t &CREATION_DATE)
 
const time64_tGetCreationDate () const
 
EXPORT bool SetDateRange (time64_t VALID_FROM=OT_TIME_ZERO, time64_t VALID_TO=OT_TIME_ZERO)
 
void SetLastProcessDate (const time64_t &THE_DATE)
 
const time64_tGetLastProcessDate () const
 
void SetProcessInterval (const int64_t &THE_DATE)
 
const int64_t & GetProcessInterval () const
 
OTCronGetCron () const
 
void setServerNym (OTPseudonym *serverNym)
 
void setServerId (OTIdentifier *serverId)
 
EXPORT bool SaveCronReceipt ()
 
EXPORT bool SaveActiveCronReceipt (const OTIdentifier &theNymID)
 
virtual ~OTCronItem ()
 
void InitCronItem ()
 
void Release_CronItem ()
 
EXPORT bool GetCancelerID (OTIdentifier &theOutput) const
 
EXPORT bool IsCanceled () const
 
EXPORT bool CancelBeforeActivation (OTPseudonym &theCancelerNym)
 
EXPORT int64_t GetClosingTransactionNoAt (uint32_t nIndex) const
 
EXPORT int32_t GetCountClosingNumbers () const
 
EXPORT void AddClosingTransactionNo (const int64_t &lClosingTransactionNo)
 
EXPORT int64_t GetOpeningNum () const
 
EXPORT int64_t GetClosingNum () const
 
- Public Member Functions inherited from opentxs::OTTrackable
 OTTrackable ()
 
 OTTrackable (const OTIdentifier &SERVER_ID, const OTIdentifier &ASSET_ID)
 
 OTTrackable (const OTIdentifier &SERVER_ID, const OTIdentifier &ASSET_ID, const OTIdentifier &ACCT_ID, const OTIdentifier &USER_ID)
 
virtual ~OTTrackable ()
 
void InitTrackable ()
 
void Release_Trackable ()
 
int64_t GetTransactionNum () const
 
void SetTransactionNum (int64_t lTransactionNum)
 
const OTIdentifierGetSenderAcctID () const
 
const OTIdentifierGetSenderUserID () const
 
- Public Member Functions inherited from opentxs::OTInstrument
EXPORT OTInstrument ()
 
EXPORT OTInstrument (const OTIdentifier &SERVER_ID, const OTIdentifier &ASSET_ID)
 
virtual EXPORT ~OTInstrument ()
 
void Release_Instrument ()
 
EXPORT bool VerifyCurrentDate ()
 
EXPORT bool IsExpired ()
 
time64_t GetValidFrom () const
 
time64_t GetValidTo () const
 
const OTIdentifierGetAssetID () const
 
const OTIdentifierGetServerID () const
 
void InitInstrument ()
 
- Public Member Functions inherited from opentxs::OTScriptable
int32_t GetPartyCount () const
 
int32_t GetBylawCount () const
 
virtual EXPORT bool AddBylaw (OTBylaw &theBylaw)
 
EXPORT OTPartyGetParty (std::string str_party_name) const
 
EXPORT OTBylawGetBylaw (std::string str_bylaw_name) const
 
EXPORT OTClauseGetClause (std::string str_clause_name) const
 
EXPORT OTPartyGetPartyByIndex (int32_t nIndex) const
 
EXPORT OTBylawGetBylawByIndex (int32_t nIndex) const
 
EXPORT OTPartyFindPartyBasedOnNymAsAgent (OTPseudonym &theNym, OTAgent **ppAgent=nullptr) const
 
EXPORT OTPartyFindPartyBasedOnNymAsAuthAgent (OTPseudonym &theNym, OTAgent **ppAgent=nullptr) const
 
OTPartyFindPartyBasedOnAccount (OTAccount &theAccount, OTPartyAccount **ppPartyAccount=nullptr) const
 
OTPartyFindPartyBasedOnNymIDAsAgent (const OTIdentifier &theNymID, OTAgent **ppAgent=nullptr) const
 
OTPartyFindPartyBasedOnNymIDAsAuthAgent (const OTIdentifier &theNymID, OTAgent **ppAgent=nullptr) const
 
OTPartyFindPartyBasedOnAccountID (const OTIdentifier &theAcctID, OTPartyAccount **ppPartyAccount=nullptr) const
 
OTAgentGetAgent (std::string str_agent_name) const
 
OTPartyAccountGetPartyAccount (std::string str_acct_name) const
 
OTPartyAccountGetPartyAccountByID (const OTIdentifier &theAcctID) const
 
EXPORT int32_t GetCountTransNumsNeededForAgent (std::string str_agent_name) const
 
virtual EXPORT bool VerifyNymAsAgent (OTPseudonym &theNym, OTPseudonym &theSignerNym, mapOfNyms *pmap_ALREADY_LOADED=nullptr) const
 
virtual EXPORT bool VerifyNymAsAgentForAccount (OTPseudonym &theNym, OTAccount &theAccount) const
 
bool VerifyPartyAuthorization (OTParty &theParty, OTPseudonym &theSignerNym, const OTString &strServerID, mapOfNyms *pmap_ALREADY_LOADED=nullptr, mapOfNyms *pmap_NEWLY_LOADED=nullptr, bool bBurnTransNo=false)
 
bool VerifyPartyAcctAuthorization (OTPartyAccount &thePartyAcct, OTPseudonym &theSignerNym, const OTString &strServerID, bool bBurnTransNo=false)
 
EXPORT bool VerifyThisAgainstAllPartiesSignedCopies ()
 
EXPORT bool AllPartiesHaveSupposedlyConfirmed ()
 
void RetrieveNymPointers (mapOfNyms &map_Nyms_Already_Loaded)
 
void ClearTemporaryPointers ()
 
bool GetHooks (std::string str_HookName, mapOfClauses &theResults)
 
OTClauseGetCallback (std::string str_CallbackName)
 
OTVariableGetVariable (std::string str_VarName)
 
bool IsDirty () const
 
bool IsDirtyImportant () const
 
void SetAsClean ()
 
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 CanExecuteClause (std::string str_party_name, std::string str_clause_name)
 
bool ExecuteCallback (OTClause &theCallbackClause, mapOfVariables &theParameters, OTVariable &varReturnVal)
 
 OTScriptable ()
 
virtual ~OTScriptable ()
 
void UpdateContentsToString (OTString &strAppend, bool bCalculatingID) const
 
virtual EXPORT void CalculateContractID (OTIdentifier &newID) const
 
void Release_Scriptable ()
 
- Public Member Functions inherited from opentxs::OTContract
const char * GetHashType () const
 
void SetIdentifier (const OTIdentifier &theID)
 
EXPORT OTContract ()
 
EXPORT OTContract (const OTString &name, const OTString &foldername, const OTString &filename, const OTString &strID)
 
EXPORT OTContract (const OTString &strID)
 
EXPORT OTContract (const OTIdentifier &theID)
 
void Initialize ()
 
virtual EXPORT ~OTContract ()
 
EXPORT void Release_Contract ()
 
EXPORT void ReleaseSignatures ()
 
virtual EXPORT bool CreateContract (const OTString &strContract, const OTPseudonym &theSigner)
 
EXPORT bool InsertNym (const OTString &strKeyName, const OTString &strKeyValue)
 
EXPORT void GetName (OTString &strName) const
 
EXPORT void SetName (const OTString &strName)
 
virtual EXPORT bool VerifyContract ()
 
virtual EXPORT void GetIdentifier (OTIdentifier &theIdentifier) const
 
virtual EXPORT void GetIdentifier (OTString &theIdentifier) const
 
EXPORT void GetFilename (OTString &strFilename) const
 
EXPORT void GetFoldername (OTString &strFoldername) const
 
virtual EXPORT bool LoadContract ()
 
EXPORT bool LoadContract (const char *szFoldername, const char *szFilename)
 
EXPORT bool LoadContractFromString (const OTString &theStr)
 
bool LoadContractRawFile ()
 
EXPORT bool ParseRawFile ()
 
EXPORT bool SaveToContractFolder ()
 
EXPORT bool SaveContractRaw (OTString &strOutput) const
 
EXPORT bool RewriteContract (OTString &strOutput) const
 
EXPORT bool SaveContract ()
 
EXPORT bool SaveContract (const char *szFoldername, const char *szFilename)
 
virtual EXPORT void CreateContents ()
 
EXPORT void CreateInnerContents ()
 
virtual EXPORT bool SaveContents (std::ofstream &ofs) const
 
virtual EXPORT bool SaveContractWallet (OTString &strContents) const
 
virtual EXPORT bool DisplayStatistics (OTString &strContents) const
 
virtual EXPORT bool SaveContents (OTString &strContents) const
 
virtual EXPORT bool SignContract (const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
 
EXPORT bool SignContractAuthent (const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
 
EXPORT bool SignWithKey (const OTAsymmetricKey &theKey, const OTPasswordData *pPWData=nullptr)
 
EXPORT bool SignContract (const OTPseudonym &theNym, OTSignature &theSignature, const OTPasswordData *pPWData=nullptr)
 
EXPORT bool SignContractAuthent (const OTPseudonym &theNym, OTSignature &theSignature, const OTPasswordData *pPWData=nullptr)
 
EXPORT bool SignContract (const OTAsymmetricKey &theKey, OTSignature &theSignature, const OTString &strHashType, const OTPasswordData *pPWData=nullptr)
 
EXPORT bool SignContract (const char *szFoldername, const char *szFilename, OTSignature &theSignature, const OTPasswordData *pPWData=nullptr)
 
virtual EXPORT bool VerifyContractID () const
 
virtual EXPORT bool VerifySignature (const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
 
virtual EXPORT bool VerifySigAuthent (const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
 
EXPORT bool VerifyWithKey (const OTAsymmetricKey &theKey, const OTPasswordData *pPWData=nullptr) const
 
EXPORT bool VerifySignature (const OTPseudonym &theNym, const OTSignature &theSignature, const OTPasswordData *pPWData=nullptr) const
 
EXPORT bool VerifySigAuthent (const OTPseudonym &theNym, const OTSignature &theSignature, const OTPasswordData *pPWData=nullptr) const
 
EXPORT bool VerifySignature (const OTAsymmetricKey &theKey, const OTSignature &theSignature, const OTString &strHashType, const OTPasswordData *pPWData=nullptr) const
 
EXPORT bool VerifySignature (const char *szFoldername, const char *szFilename, const OTSignature &theSignature, const OTPasswordData *pPWData=nullptr) const
 
EXPORT const OTAsymmetricKeyGetContractPublicKey () const
 
EXPORT const OTPseudonymGetContractPublicNym () const
 

Static Public Member Functions

static void CleanupNyms (mapOfNyms &theMap)
 
static void CleanupAccts (mapOfAccounts &theMap)
 
- Static Public Member Functions inherited from opentxs::OTCronItem
static EXPORT OTCronItemNewCronItem (const OTString &strCronItem)
 
static EXPORT OTCronItemLoadCronReceipt (const int64_t &lTransactionNum)
 
static EXPORT OTCronItemLoadActiveCronReceipt (const int64_t &lTransactionNum, const OTIdentifier &serverID)
 
static EXPORT bool EraseActiveCronReceipt (const int64_t &lTransactionNum, const OTIdentifier &nymID, const OTIdentifier &serverID)
 
static EXPORT bool GetActiveCronTransNums (OTNumList &output, const OTIdentifier &nymID, const OTIdentifier &serverID)
 
- Static Public Member Functions inherited from opentxs::OTScriptable
static EXPORT OTScriptableInstantiateScriptable (const OTString &strInput)
 
static bool ValidateName (std::string str_name)
 
static std::string GetTime ()
 
- Static Public Member Functions inherited from opentxs::OTContract
static EXPORT bool DearmorAndTrim (const OTString &strInput, OTString &strOutput, OTString &strFirstLine)
 
static bool AddBookendsAroundContent (OTString &strOutput, const OTString &strContents, const OTString &strContractType, const OTString &strHashType, const listOfSignatures &listSignatures)
 
static EXPORT bool LoadEncodedTextField (irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
 
static EXPORT bool LoadEncodedTextField (irr::io::IrrXMLReader *&xml, OTString &strOutput)
 
static bool LoadEncodedTextFieldByName (irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput, const char *&szName, OTString::Map *pmapExtraVars=nullptr)
 
static bool LoadEncodedTextFieldByName (irr::io::IrrXMLReader *&xml, OTString &strOutput, const char *&szName, OTString::Map *pmapExtraVars=nullptr)
 
static bool SkipToElement (irr::io::IrrXMLReader *&xml)
 
static bool SkipToTextField (irr::io::IrrXMLReader *&xml)
 
static bool SkipAfterLoadingField (irr::io::IrrXMLReader *&xml)
 
static EXPORT bool SignFlatText (OTString &strFlatText, const OTString &strContractType, const OTPseudonym &theSigner, OTString &strOutput)
 

Protected Member Functions

virtual void onActivate ()
 
virtual void onFinalReceipt (OTCronItem &theOrigCronItem, const int64_t &lNewTransactionNumber, OTPseudonym &theOriginator, OTPseudonym *pRemover)
 
virtual void onRemovalFromCron ()
 
void ReleaseLastSenderRecipientIDs ()
 
void SetNextProcessDate (const time64_t &tNEXT_DATE)
 
const time64_tGetNextProcessDate () const
 
- Protected Member Functions inherited from opentxs::OTCronItem
 OTCronItem (const OTIdentifier &SERVER_ID, const OTIdentifier &ASSET_ID)
 
 OTCronItem (const OTIdentifier &SERVER_ID, const OTIdentifier &ASSET_ID, const OTIdentifier &ACCT_ID, const OTIdentifier &USER_ID)
 
void ClearClosingNumbers ()
 
- Protected Member Functions inherited from opentxs::OTTrackable
void SetSenderAcctID (const OTIdentifier &ACCT_ID)
 
void SetSenderUserID (const OTIdentifier &USER_ID)
 
- Protected Member Functions inherited from opentxs::OTInstrument
void SetValidFrom (time64_t TIME_FROM)
 
void SetValidTo (time64_t TIME_TO)
 
void SetAssetID (const OTIdentifier &ASSET_ID)
 
void SetServerID (const OTIdentifier &SERVER_ID)
 
- Protected Member Functions inherited from opentxs::OTContract
bool LoadContractXML ()
 

Additional Inherited Members

- Protected Attributes inherited from opentxs::OTCronItem
std::deque< int64_t > m_dequeClosingNumbers
 
OTIdentifierm_pCancelerNymID
 
bool m_bCanceled
 
bool m_bRemovalFlag
 
- Protected Attributes inherited from opentxs::OTTrackable
int64_t m_lTransactionNum
 
OTIdentifier m_SENDER_ACCT_ID
 
OTIdentifier m_SENDER_USER_ID
 
- Protected Attributes inherited from opentxs::OTInstrument
OTIdentifier m_AssetTypeID
 
OTIdentifier m_ServerID
 
time64_t m_VALID_FROM
 
time64_t m_VALID_TO
 
- Protected Attributes inherited from opentxs::OTScriptable
mapOfParties m_mapParties
 
mapOfBylaws m_mapBylaws
 
bool m_bCalculatingID
 
bool m_bSpecifyAssetID
 
bool m_bSpecifyParties
 
OTString m_strLabel
 
- Protected Attributes inherited from opentxs::OTContract
OTString m_strName
 
OTString m_strFoldername
 
OTString m_strFilename
 
OTIdentifier m_ID
 
OTStringXML m_xmlUnsigned
 
OTString m_strRawFile
 
OTString m_strSigHashType
 
OTString m_strContractType
 
mapOfNyms m_mapNyms
 
listOfSignatures m_listSignatures
 
OTString m_strVersion
 
OTString m_strEntityShortName
 
OTString m_strEntityLongName
 
OTString m_strEntityEmail
 
OTString::Map m_mapConditions
 

Detailed Description

Definition at line 150 of file OTSmartContract.hpp.

Constructor & Destructor Documentation

opentxs::OTSmartContract::OTSmartContract ( )

Definition at line 5335 of file OTSmartContract.cpp.

5336  : ot_super()
5337  , m_StashAccts(OTAccount::stash)
5338  , m_tNextProcessDate(OT_TIME_ZERO)
5339 {
5341 }
#define OT_TIME_ZERO
Definition: Common.hpp:180
opentxs::OTSmartContract::OTSmartContract ( const OTIdentifier SERVER_ID)

Definition at line 5343 of file OTSmartContract.cpp.

5344  : ot_super()
5345  , m_StashAccts(OTAccount::stash)
5346  , m_tNextProcessDate(OT_TIME_ZERO)
5347 {
5348  OTInstrument::SetServerID(SERVER_ID);
5350 }
void SetServerID(const OTIdentifier &SERVER_ID)
#define OT_TIME_ZERO
Definition: Common.hpp:180
opentxs::OTSmartContract::~OTSmartContract ( )
virtual

Definition at line 5352 of file OTSmartContract.cpp.

5353 {
5355 }

Member Function Documentation

bool opentxs::OTSmartContract::AddParty ( OTParty theParty)
virtual

Reimplemented from opentxs::OTScriptable.

Definition at line 5193 of file OTSmartContract.cpp.

5194 {
5195  if (!theParty.HasActiveAgent()) {
5196  otOut << "OTSmartContract::AddParty: Party doesn't have an active "
5197  "agent -- who will sign for this smart contract?\n";
5198  return false;
5199  }
5200 
5201  // MIGHT move this below (1).. OR this might turn out to be important going
5202  // first...
5203  //
5204  if (!OTScriptable::AddParty(theParty)) {
5205  otOut << "OTSmartContract::AddParty: Failed adding party.\n";
5206  return false;
5207  }
5208 
5209  return true;
5210 }
virtual EXPORT bool AddParty(OTParty &theParty)
OTLOG_IMPORT OTLogStream otOut
bool opentxs::OTSmartContract::CanCancelContract ( std::string  str_party_name)

Definition at line 3969 of file OTSmartContract.cpp.

3970 {
3971  OTCron* pCron = GetCron();
3972  OT_ASSERT(nullptr != pCron);
3973 
3974  OTPseudonym* pServerNym = pCron->GetServerNym();
3975  OT_ASSERT(nullptr != pServerNym);
3976 
3977  OTParty* pParty = GetParty(str_party_name);
3978 
3979  if (nullptr == pParty) {
3980  otOut
3981  << "OTSmartContract::CanCancelContract: Unable to find this party: "
3982  << str_party_name << "\n";
3983  return false;
3984  }
3985  // Below this point, pParty is good.
3986 
3987  // ...This WILL check to see if pParty has its Opening number verified as
3988  // issued.
3989  // (If the opening number is > 0 then VerifyPartyAuthorization() is smart
3990  // enough to verify it.)
3991  //
3992  // To KNOW that a party has the right to even ASK the script to cancel a
3993  // contract, MEANS that
3994  // (1) The party is listed as a party on the contract. (2) The party's copy
3995  // of that contract
3996  // is signed by the authorizing agent for that party. and (3) The opening
3997  // transaction number for
3998  // that party is verified as issued for authorizing agent. (2 and 3 are both
3999  // performed at the same
4000  // time, in VerifyPartyAuthorization(), since the agent may need to be
4001  // loaded in order to verify
4002  // them.) 1 is already done by this point, as it's performed above.
4003  //
4004  // Done: notice this code appears in CanCancelContract() (this function) as
4005  // well as
4006  // OTScriptable::CanExecuteClause.
4007  // Therefore I can see that THIS VERIFICATION CODE WILL GET CALLED EVERY
4008  // SINGLE TIME THE SCRIPT
4009  // CALLS ANY CLAUSE OR OT NATIVE FUNCTION. Since technically this only
4010  // needs to be verified before the
4011  // first call, and not for EVERY call during any of a script's runs, I
4012  // should probably move this verification
4013  // higher, such as each time the OTCronItem triggers, plus each time a party
4014  // triggers a clause directly
4015  // through the API (server message). As long as those are covered, I will be
4016  // able to remove it from here
4017  // which should be a significant improvement for performance.
4018  // It will be at the bottom of those same functions that
4019  // "ClearTemporaryPointers()" should finally be called.
4020  //
4021  // Also todo: Need to implement MOVE CONSTRUCTORS and MOVE COPY
4022  // CONSTRUCTORS all over the place,
4023  // once I'm sure C++0x build environments are available for all of the
4024  // various OT platforms. That should
4025  // be another great performance boost!
4026  //
4027  // FINAL DECISION: Redundant. See comment in
4028  // OTSmartContract::StashAcctFunds()
4029  //
4030 
4031  // IF NO CALLBACK IS PROVIDED, The default answer to this function is:
4032  // YES, this party MAY cancel this contract! (Assuming he's a real
4033  // party,
4034  // which we have verified by this point.)
4035  //
4036  // But... first we check to see if this OTScriptable has a clause named:
4037  // "callback_party_may_cancel_contract"
4038  // ...and if so, we ask the CALLBACK to make the decision instead. This way,
4039  // people can define
4040  // in their own scripts any rules they want about which parties may cancel
4041  // the contract.
4042 
4043  //
4044  const std::string str_CallbackName(SMARTCONTRACT_CALLBACK_PARTY_MAY_CANCEL);
4045 
4046  OTClause* pCallbackClause =
4047  GetCallback(str_CallbackName); // See if there is a script clause
4048  // registered for this callback.
4049 
4050  if (nullptr != pCallbackClause) // Found it! There's a clause registered for
4051  // this callback. Let's call it...
4052  {
4053  otOut << "OTSmartContract::CanCancelContract: Found script for: "
4054  << SMARTCONTRACT_CALLBACK_PARTY_MAY_CANCEL << ". Asking...\n";
4055 
4056  // The function we're IN defaults to TRUE, if there's no script
4057  // available.
4058  // However, if the script IS available, then our default return value
4059  // starts as FALSE.
4060  // (The script itself will then have to set it to true, if that's what
4061  // it wants.)
4062  //
4063  OTVariable theReturnVal("return_val", false);
4064 
4065  OTVariable param1(
4066  "param_party_name", str_party_name,
4067  OTVariable::Var_Constant); // script can reference param_party_name
4068 
4069  mapOfVariables theParameters;
4070  theParameters.insert(
4071  std::pair<std::string, OTVariable*>("param_party_name", &param1));
4072 
4073  if (false ==
4075  *pCallbackClause, theParameters,
4076  theReturnVal)) // <============================================
4077  {
4078  otErr << "OTSmartContract::CanCancelContract: Error while running "
4079  "callback script "
4080  << SMARTCONTRACT_CALLBACK_PARTY_MAY_CANCEL << ", clause "
4081  << pCallbackClause->GetName() << " \n";
4082  return false;
4083  }
4084  else {
4085  otOut << "OTSmartContract::CanCancelContract: Success executing "
4086  "callback script "
4087  << SMARTCONTRACT_CALLBACK_PARTY_MAY_CANCEL
4088  << ", clause: " << pCallbackClause->GetName() << ".\n\n";
4089 
4090  return theReturnVal.CopyValueBool();
4091  }
4092 
4093  }
4094  else {
4095  otOut
4096  << "OTSmartContract::CanCancelContract: Unable to find script for: "
4097  << SMARTCONTRACT_CALLBACK_PARTY_MAY_CANCEL
4098  << ". Therefore, default return value is: TRUE.\n";
4099  }
4100 
4101  return true;
4102 }
std::map< std::string, OTVariable * > mapOfVariables
Definition: OTBylaw.hpp:146
OTLOG_IMPORT OTLogStream otOut
bool ExecuteCallback(OTClause &theCallbackClause, mapOfVariables &theParameters, OTVariable &varReturnVal)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTClause * GetCallback(std::string str_CallbackName)
EXPORT OTParty * GetParty(std::string str_party_name) const
OTLOG_IMPORT OTLogStream otErr
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
#define SMARTCONTRACT_CALLBACK_PARTY_MAY_CANCEL
bool opentxs::OTSmartContract::CanRemoveItemFromCron ( OTPseudonym theNym)
virtual

See if theNym has rights to remove this item from Cron.

Reimplemented from opentxs::OTCronItem.

Definition at line 4106 of file OTSmartContract.cpp.

4107 {
4108  // You don't just go willy-nilly and remove a cron item from a market unless
4109  // you check first
4110  // and make sure the Nym who requested it actually has said number (or a
4111  // related closing number)
4112  // signed out to him on his last receipt...
4113  //
4114  // Note: overrode parent method and NOT calling it.
4115  // We do it our own way here, and call a script if it's available.
4116 
4117  // IT'S ASSUMED that the opening and closing numbers WILL be verified in
4118  // order to
4119  // insure they are CURRENTLY ISSUED.
4120  //
4121  // theNym.VerifyIssuedNum(strServerID, GetOpeningNum();
4122  // theNym.VerifyIssuedNum(strServerID, GetClosingNum();
4123  //
4124  // The default version OTCronItem does this for theNym, and the PaymentPlan
4125  // version
4126  // has to be a little smarter: it has to figure out whether theNym is the
4127  // Sender or Recipient,
4128  // so that it knows where to verify the numbers from, before allowing theNym
4129  // to do the removal.
4130  //
4131  //
4132  // ===> THIS version (OTSmartContract) will look up pParty using theNym via:
4133  // OTParty * OTScriptable::FindPartyBasedOnNymAsAgent(const OTPseudonym&
4134  // theNym, OTAgent ** ppAgent=nullptr);
4135  //
4136  // ...Then it WILL check to see if pParty has its Opening number verified as
4137  // issued.
4138  // ...It COULD ALSO loop the partyaccounts and see if pAgent is authorized
4139  // agent for any of them.
4140  // (If so, pAcct->VerifyClosingNumber() or pAgent->VerifyClosingNumber()
4141  // as well.)
4142  //
4143  //
4144  OTAgent* pAgent = nullptr;
4145  OTParty* pParty = FindPartyBasedOnNymAsAgent(
4146  theNym, &pAgent); // This sets a pointer to theNym inside pAgent, so
4147  // pParty can use it later.
4148 
4149  if (nullptr == pParty) {
4150  otOut << "OTSmartContract::CanRemoveItemFromCron: Warning: theNym is "
4151  "not an agent "
4152  "for any party to this contract, yet tried to remove it.\n";
4153  return false;
4154  }
4155  OT_ASSERT(nullptr != pAgent); // With one comes the other.
4156 
4157  // Below this point, pAgent is not only good, but it contains a secret
4158  // hidden pointer now to theNym.
4159  // That way, when the SCRIPT asks the party to verify issued number, without
4160  // even having a reference to theNym,
4161  // the party will internally still be able to handle it. This always works
4162  // in cases where it's needed because
4163  // we used theNym to look up pParty, and the lookup function is what sets
4164  // that pointer. That's why I clean
4165  // the pointer again after I'm done. (AT THE BOTTOM OF THIS FUNCTION.)
4166  //
4167 
4168  // NOTE: You can see OTCronItem looks up the relevant numbers by trying to
4169  // figure out if theNym
4170  // is sender or receiver, and then calling these methods:
4171  // if (GetCountClosingNumbers() < 1)
4172  // if (GetRecipientCountClosingNumbers() < 2)
4173  // Etc.
4174  //
4175  // But OTSmartContract doesn't use those functions, except where it has to
4176  // in order to
4177  // work within the existing OTCronItem system. (That is, the ORIGINATOR who
4178  // actually activates
4179  // a smart contract must still provide at least an opening number, which is
4180  // stored in the old
4181  // system and used by it.)
4182  // Instead, OTSmartContract keeps its own records (via its parent class
4183  // OTScriptable) of all the
4184  // parties to the contract, and all of their opening transaction #s, as well
4185  // as the accounts that
4186  // are party to the contract, and the closing transaction #s for each of
4187  // those.
4188  //
4189  // ===> Therefore, when it comes to verifying whether the Nym has CERTAIN
4190  // RIGHTS regarding the
4191  // contract, OTSmartContract doesn't actually use the old system for that,
4192  // but instead queries its
4193  // own, superior system.
4194  //
4195  // In order to prevent infinite recursion I think I will be adding THAT code
4196  // into:
4197  // OTSmartContract::CanCancelContract(party_name)
4198 
4199  bool bReturnValue = false;
4200  bool bPartyHasName = false;
4201  const std::string str_party_name = pParty->GetPartyName(&bPartyHasName);
4202 
4203  if (bPartyHasName &&
4204  CanCancelContract(str_party_name)) // Here is where it calls the
4205  // script, inside this call.
4206  {
4207  otOut << "OTSmartContract::CanRemoveItemFromCron: Looks like theNym "
4208  "represents a party (" << str_party_name
4209  << ") and "
4210  "IS allowed by this contract to cancel it whenever he "
4211  "chooses.\n";
4212  bReturnValue = true;
4213  }
4214 
4215  pParty->ClearTemporaryPointers(); // FindPartyBasedOnNymAsAgent() set the
4216  // party's agent's nym pointer to theNym.
4217  // This clears it.
4218 
4219  return bReturnValue;
4220 }
bool CanCancelContract(std::string str_party_name)
OTLOG_IMPORT OTLogStream otOut
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT OTParty * FindPartyBasedOnNymAsAgent(OTPseudonym &theNym, OTAgent **ppAgent=nullptr) const
void opentxs::OTSmartContract::CleanupAccts ( mapOfAccounts theMap)
static

Definition at line 5164 of file OTSmartContract.cpp.

5165 {
5166 
5167  while (!theMap.empty()) {
5168  OTAccount* pAcct = theMap.begin()->second;
5169  OT_ASSERT(nullptr != pAcct);
5170 
5171  delete pAcct;
5172  pAcct = nullptr;
5173 
5174  theMap.erase(theMap.begin());
5175  }
5176 }
#define OT_ASSERT(x)
Definition: Assert.hpp:150
void opentxs::OTSmartContract::CleanupNyms ( mapOfNyms theMap)
static

Definition at line 5149 of file OTSmartContract.cpp.

5150 {
5151 
5152  while (!theMap.empty()) {
5153  OTPseudonym* pNym = theMap.begin()->second;
5154  OT_ASSERT(nullptr != pNym);
5155 
5156  delete pNym;
5157  pNym = nullptr;
5158 
5159  theMap.erase(theMap.begin());
5160  }
5161 }
#define OT_ASSERT(x)
Definition: Assert.hpp:150
void opentxs::OTSmartContract::CloseoutOpeningNumbers ( OTPseudonym pSignerNym = nullptr)

Definition at line 4976 of file OTSmartContract.cpp.

4977 {
4978  const OTString strServerID(GetServerID());
4979 
4980  for (auto& it : m_mapParties) {
4981  OTParty* pParty = it.second;
4982  OT_ASSERT_MSG(nullptr != pParty,
4983  "OTSmartContract::CloseoutOpeningNumbers:"
4984  " Unexpected nullptr pointer in party map.");
4985 
4986  // Closeout the opening transaction numbers:
4987  //
4988  if (GetTransactionNum() !=
4989  pParty->GetOpeningTransNo()) // We skip the activating Nym. (His is
4990  // already closed-out in
4991  // NotarizeTransaction.)
4992  pParty->CloseoutOpeningNumber(strServerID, true, // bSave=true
4993  pSignerNym);
4994  }
4995 }
int64_t GetTransactionNum() const
mapOfParties m_mapParties
const OTIdentifier & GetServerID() const
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
bool opentxs::OTSmartContract::Compare ( OTScriptable rhs) const
virtual

Reimplemented from opentxs::OTScriptable.

Definition at line 5417 of file OTSmartContract.cpp.

5418 {
5419  if (!OTScriptable::Compare(rhs)) return false;
5420 
5421  if (GetCountStashes() > 0) {
5422  otErr << "OTSmartContract::Compare: Error: How is this function EVER "
5423  "being called when there are stashes present? Only the server "
5424  "can create stashes.\n";
5425  return false;
5426  }
5427 
5428  if (GetCountStashAccts() > 0) {
5429  otErr << "OTSmartContract::Compare: Error: How is this function EVER "
5430  "being called when there are "
5431  "stash accounts present? Only the server can create stash "
5432  "accounts.\n";
5433  return false;
5434  }
5435 
5436  // Compare OTSmartContract specific info here.
5437  const OTSmartContract* pSmartContract =
5438  dynamic_cast<const OTSmartContract*>(&rhs);
5439 
5440  if (nullptr != pSmartContract) {
5441  if (pSmartContract->GetCountStashes() > 0) {
5442  otErr << "OTSmartContract::Compare: Error: How is this function "
5443  "EVER being called when there are stashes present on rhs? "
5444  "Only the server can create stashes.\n";
5445  return false;
5446  }
5447 
5448  if (pSmartContract->GetCountStashAccts() > 0) {
5449  otErr << "OTSmartContract::Compare: Error: How is this function "
5450  "EVER being called when there are stash accounts present "
5451  "on rhs? Only the server can create stash accounts.\n";
5452  return false;
5453  }
5454 
5455  if ((GetServerID() == pSmartContract->GetServerID()) &&
5456  (GetValidFrom() == pSmartContract->GetValidFrom()) &&
5457  (GetValidTo() == pSmartContract->GetValidTo()))
5458  return true;
5459  }
5460 
5461  return false;
5462 }
int32_t GetCountStashAccts() const
time64_t GetValidTo() const
virtual EXPORT bool Compare(OTScriptable &rhs) const
const OTIdentifier & GetServerID() const
time64_t GetValidFrom() const
int32_t GetCountStashes() const
OTLOG_IMPORT OTLogStream otErr
bool opentxs::OTSmartContract::ConfirmParty ( OTParty theParty)
virtual

Reimplemented from opentxs::OTScriptable.

Definition at line 5230 of file OTSmartContract.cpp.

5231 {
5232  if (!theParty.HasActiveAgent()) {
5233  otOut << "OTSmartContract::ConfirmParty: Party doesn't have an active "
5234  "agent -- who will sign for this smart contract?\n";
5235  return false;
5236  }
5237 
5238  // Let's RESERVE however many transaction numbers we need to confirm this
5239  // smartcontract...
5240  //
5241  const OTString strServerID(GetServerID());
5242 
5243  // ReserveTransNumsForConfirm() sets aside the Opening # for the party,
5244  // as well as the Closing #s for all the asset accounts for that party.
5245  //
5246  // This MUST be done before calling OTScriptable::ConfirmParty, because
5247  // *this will get SIGNED in there, and so must have its final data in
5248  // place already. If the confirmation fails, we will harvest the numbers
5249  // back again.
5250  //
5251  if (!theParty.ReserveTransNumsForConfirm(strServerID)) {
5252  otOut << "OTSmartContract::ConfirmParty: Failure trying to reserve "
5253  "transaction numbers for "
5254  "the smart contract. (Nym needs more numbers than he has.)\n";
5255  return false;
5256  }
5257  // Note: BELOW THIS POINT, the transaction numbers have been set aside, and
5258  // must be retrieved,
5259  // below this point, in the event of any failure, using this call:
5260  // theParty.HarvestAllTransactionNumbers(strServerID);
5261 
5262  // Since EVERY party keeps his own signed copy, then we reset the creation
5263  // date
5264  // before EACH signature. That way, we have the date of signing for EVERY
5265  // signer.
5266  // (The final date will be set upon activation.)
5267  //
5268  const time64_t& CURRENT_TIME = OTTimeGetCurrentTime(),
5269  OLD_TIME = GetCreationDate();
5270 
5271  // Set the Creation Date.
5272  SetCreationDate(CURRENT_TIME);
5273 
5274  // THIS IS where the SIGNED COPY is SAVED, so all final changes must occur
5275  // ABOVE this point.
5276  //
5277  if (!OTScriptable::ConfirmParty(theParty)) {
5278  otOut << "OTSmartContract::ConfirmParty: Failed confirming party.\n";
5279  SetCreationDate(OLD_TIME); // Might as well set this back.
5280  theParty.HarvestAllTransactionNumbers(strServerID); // If it failed,
5281  // grab BACK the
5282  // numbers that we
5283  // reserved above.
5284  return false;
5285  }
5286 
5287  // SUCCESS!!
5288  //
5289  return true;
5290 
5291  // Are we good? The contract is compared against the other parties' signed
5292  // contracts; my own party and
5293  // transaction #s are added, and a signed copy of everything is saved in my
5294  // party. Then the entire contract
5295  // is re-signed (saving its updated contents) and then sent on to the next
5296  // party, who is free to release that
5297  // signature since I already have a signed copy in my party.
5298  //
5299  // Assuming all parties have signed AND provided valid transaction #s, then
5300  // the server is free to get started
5301  // immediately upon activation, and furthermore to cancel whenever it wants
5302  // (and probably just according to
5303  // the terms.) There should be a standard call for seeing if a person can
5304  // cancel the agreement, and if it's
5305  // not overridden in the contract, then it defaults to return true. (Note:
5306  // that is done now.)
5307  //
5308  // Technically ANY party's authorizing agent could become the originator by
5309  // activating the contract, but
5310  // only if all parties have validly signed. (Server needs to verify.)
5311 }
OTLOG_IMPORT OTLogStream otOut
int64_t time64_t
Definition: Common.hpp:209
void SetCreationDate(const time64_t &CREATION_DATE)
Definition: OTCronItem.hpp:264
const OTIdentifier & GetServerID() const
time64_t OTTimeGetCurrentTime()
Definition: Common.hpp:211
virtual EXPORT bool ConfirmParty(OTParty &theParty)
const time64_t & GetCreationDate() const
Definition: OTCronItem.hpp:268
void opentxs::OTSmartContract::DeactivateSmartContract ( )

Definition at line 970 of file OTSmartContract.cpp.

971 {
972  // WARNING: If a party has the right to execute a clause that calls
973  // DeactivateSmartContract(),
974  // then that party can deactivate the smartcontract by calling that clause,
975  // regardless of what
976  // "CanPartyCancelClause()" says he can do.
977  // (And by default, any legitimate party can trigger any clause, at any
978  // time, unless your script
979  // override says differently.)
980 
981  otOut << "OTSmartContract::DeactivateSmartContract: deactivate_contract() "
982  "was called from within the script. "
983  "Flagging smartcontract for removal from Cron ("
984  << GetTransactionNum() << ").\n";
985 
986  FlagForRemoval(); // Remove it from future Cron processing, please.
987 }
int64_t GetTransactionNum() const
OTLOG_IMPORT OTLogStream otOut
void opentxs::OTSmartContract::ExecuteClauses ( mapOfClauses theClauses,
OTString pParam = nullptr 
)

Definition at line 3761 of file OTSmartContract.cpp.

3769 {
3770  // Loop through the clauses passed in, and execute them all.
3771  for (auto& it_clauses : theClauses) {
3772  const std::string str_clause_name = it_clauses.first;
3773  OTClause* pClause = it_clauses.second;
3774  OT_ASSERT((nullptr != pClause) && (str_clause_name.size() > 0));
3775  OTBylaw* pBylaw = pClause->GetBylaw();
3776  OT_ASSERT(nullptr != pBylaw);
3777 
3778  // By this point, we have the clause we are executing as pClause,
3779  // and we have the Bylaw it belongs to, as pBylaw.
3780 
3781  const std::string str_code =
3782  pClause->GetCode(); // source code for the script.
3783  const std::string str_language =
3784  pBylaw->GetLanguage(); // language it's in. (Default is "chai")
3785 
3786  std::shared_ptr<OTScript> pScript =
3787  OTScriptFactory(str_language, str_code);
3788 
3789  std::unique_ptr<OTVariable> theVarAngel;
3790 
3791  //
3792  // SET UP THE NATIVE CALLS, REGISTER THE PARTIES, REGISTER THE
3793  // VARIABLES, AND EXECUTE THE SCRIPT.
3794  //
3795  if (pScript) {
3796  // Register the special server-side native OT calls we make
3797  // available to all scripts.
3798  //
3800 
3801  // Register all the parties with the script.
3802  //
3803  for (auto& it : m_mapParties) {
3804  const std::string str_party_name = it.first;
3805  OTParty* pParty = it.second;
3806  OT_ASSERT((nullptr != pParty) && (str_party_name.size() > 0));
3807 
3808  pScript->AddParty(str_party_name, *pParty); // This also
3809  // registers all of
3810  // Party's accounts
3811  // with pScript.
3812  }
3813 
3814  // Also need to loop through the Variables on pBylaw and register
3815  // those as well.
3816  //
3817  pBylaw->RegisterVariablesForExecution(
3818  *pScript); // This also sets all the variables as CLEAN so we
3819  // can check for dirtiness after execution.
3820 
3821  // A parameter might also be passed in, so we add that to the script
3822  // as well.
3823  // (Like if a client is sending a triggerClause message to a server,
3824  // and passing
3825  // a string parameter to that clause as input.)
3826  //
3827  const std::string str_Name("param_string");
3828  std::string str_Value("");
3829 
3830  // See if param_string variable is already found on the bylaw...
3831  //
3832  if (nullptr !=
3833  pBylaw->GetVariable(str_Name)) // disallow duplicate names.
3834  {
3835  otErr << "OTSmartContract::ExecuteClauses: While preparing to "
3836  "run smartcontract trans# " << GetTransactionNum()
3837  << ", clause: " << str_clause_name
3838  << ". Error: Parameter variable named " << str_Name
3839  << " already exists. (Skipping the parameter actually "
3840  "passed in.)\n";
3841  }
3842  else // The param_string variable isn't already there. (So we add
3843  // it as blank, if a value wasn't passed in.)
3844  {
3845  if (nullptr != pParam) // if a param was passed in...
3846  str_Value = pParam->Get();
3847  // else (it's already "")
3848 
3849  OTVariable* pVar = new OTVariable(str_Name, str_Value,
3851  OT_ASSERT(nullptr != pVar);
3852  theVarAngel.reset(pVar);
3853 
3854  pVar->RegisterForExecution(*pScript); // This causes pVar to
3855  // keep a pointer to the
3856  // script so it can remove
3857  // itself from the script
3858  // upon destruction.
3859  // pScript->AddVariable(str_Name, *pVar);
3860  }
3861 
3862  // TEMP FOR TESTING (HARDCODED CLAUSE NAME HERE...)
3863  // OTVariable theReturnVal("return_val", false); //
3864  // initial value is: false.
3865 
3866  SetDisplayLabel(&str_clause_name);
3867 
3868  pScript->SetDisplayFilename(m_strLabel.Get());
3869 
3870  if (!pScript->ExecuteScript()) // If I passed theReturnVal
3871  // in here, then it'd be
3872  // assumed a bool is expected
3873  // to be returned inside it.
3874  // if (false ==
3875  // pScript->ExecuteScript((str_clause_name.compare("process_clause")
3876  // == 0) ? &theReturnVal : nullptr))
3877  {
3878  otErr << "OTSmartContract::ExecuteClauses: Error while running "
3879  "smartcontract trans# " << GetTransactionNum()
3880  << ", clause: " << str_clause_name << " \n\n";
3881  }
3882  else
3883  otOut << "OTSmartContract::ExecuteClauses: Success executing "
3884  "smartcontract trans# " << GetTransactionNum()
3885  << ", clause: " << str_clause_name << " \n\n";
3886 
3887  // For now, I've decided to allow ALL clauses to trigger
3888  // on the hook. The flag only matters after
3889  // they are done, and not between scripts. Otherwise
3890  // problems could arise, such as order of execution.
3891  // Remember, there is nothing stopping people from using
3892  // their own variables and ending all behavior
3893  // after that flag is set. Todo security: revisit this
3894  // just in case.
3895  //
3896  }
3897  else {
3898  otErr << "OTSmartContract::ExecuteClauses: Error instantiating "
3899  "script!\n";
3900  }
3901  }
3902 
3903  // "Important" variables.
3904  // (If any of them have changed, then I need to notice the parties.)
3905  //
3906  // TODO: Fix IsDirtyImportant() so that it checks for changed STASHES
3907  // as well. (Or have another function to do it, which is also called here.)
3908  //
3909  // I'd like to get to where I can just call IsDirty() here, and then SAVE
3910  // CRON HERE,
3911  // so I'm not having to save it after EACH change, which is currently
3912  // occuring in the
3913  // StashAcctFunds / MoveAcctFunds functions. Todo.
3914  //
3915  if (IsDirtyImportant()) // This tells us if any "Important" variables
3916  // have changed since executing the scripts.
3917  {
3918  OTCron* pCron = GetCron();
3919  OT_ASSERT(nullptr != pCron);
3920 
3921  OTPseudonym* pServerNym = pCron->GetServerNym();
3922  OT_ASSERT(nullptr != pServerNym);
3923 
3924  const int64_t lNewTransactionNumber = pCron->GetNextTransactionNumber();
3925 
3926  // OT_ASSERT(lNewTransactionNumber > 0); // this can be my
3927  // reminder.
3928  if (0 == lNewTransactionNumber) {
3929  otErr << "OTSmartContract::ExecuteClauses: ** ERROR: Notice not "
3930  "sent to parties, since no "
3931  "transaction numbers were available!\n";
3932  }
3933  else {
3935  SignContract(*pServerNym);
3936  SaveContract();
3937 
3938  const OTString strReference(*this);
3939  bool bDroppedNotice = SendNoticeToAllParties(
3940  true, // bSuccessMsg=true
3941  *pServerNym, GetServerID(), lNewTransactionNumber,
3942  strReference); // pstrNote and pstrAttachment aren't used in
3943  // this case.
3944 
3945  otOut << __FUNCTION__
3946  << ": FYI, 'Important' variables were changed during the "
3947  "execution of this script.\n"
3948  << (bDroppedNotice ? "Success" : "Failure")
3949  << " dropping notifications into all parties' nymboxes.\n";
3950  }
3951  }
3952 }
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
virtual void RegisterOTNativeCallsWithScript(OTScript &theScript)
int64_t GetTransactionNum() const
EXPORT bool SaveContract()
OTLOG_IMPORT OTLogStream otOut
virtual void SetDisplayLabel(const std::string *pstrLabel=nullptr)
mapOfParties m_mapParties
EXPORT void ReleaseSignatures()
Definition: OTContract.cpp:989
const OTIdentifier & GetServerID() const
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT const char * Get() const
Definition: OTString.cpp:1045
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
Definition: OTContract.cpp:484
OTLOG_IMPORT OTLogStream otErr
bool IsDirtyImportant() const
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
EXPORT std::shared_ptr< OTScript > OTScriptFactory(const std::string &script_type="")
Definition: OTScript.cpp:203
std::string opentxs::OTSmartContract::GetAcctBalance ( std::string  from_acct_name)

Definition at line 1182 of file OTSmartContract.cpp.

1183 {
1184  OTCron* pCron = GetCron();
1185  OT_ASSERT(nullptr != pCron);
1186 
1187  OTPseudonym* pServerNym = pCron->GetServerNym();
1188  OT_ASSERT(nullptr != pServerNym);
1189 
1190  // Below this point, these are all good:
1191  //
1192  // pServerNym, pCron.
1193  //
1194 
1195  if (from_acct_name.size() <= 0) {
1196  otErr << "OTSmartContract::GetAcctBalance: error: from_acct_name is "
1197  "non-existent.\n";
1198  return 0;
1199  }
1200 
1201  // Below this point, these are all good:
1202  //
1203  // from_acct_name,
1204  // pServerNym, pCron.
1205 
1206  OTPartyAccount* pFromAcct = GetPartyAccount(from_acct_name);
1207 
1208  if (nullptr == pFromAcct) {
1209  otOut << "OTSmartContract::GetAcctBalances: error: from_acct ("
1210  << from_acct_name << ") not found on any party.\n";
1211  return 0;
1212  }
1213 
1214  // Below this point, these are all good:
1215  //
1216  // pFromAcct, from_acct_name,
1217  // pServerNym, pCron.
1218 
1219  OTAgent* pFromAgent =
1220  pFromAcct->GetAuthorizedAgent(); // This searches the account's party
1221  // for the account's authorized agent.
1222  // (That way it's impossible to get an agent for any other party.)
1223 
1224  if (nullptr == pFromAgent) {
1225  otOut << "OTSmartContract::GetAcctBalance: error: authorized agent ("
1226  << pFromAcct->GetAgentName() << ") not found for from_acct ("
1227  << from_acct_name << ") on acct's party.\n";
1228  return 0;
1229  }
1230 
1231  if (!pFromAgent->IsAnIndividual()) {
1232  otOut << "OTSmartContract::GetAcctBalance: error: authorized agent ("
1233  << pFromAcct->GetAgentName() << ") for from_acct ("
1234  << from_acct_name << ") is not an active agent.\n";
1235  return 0;
1236  }
1237  //
1238  // Below this point, these are all good:
1239  //
1240  // pFromAcct, from_acct_name, pFromAgent,
1241  // pServerNym, pCron.
1242 
1243  OTParty* pFromParty = pFromAgent->GetParty();
1244 
1245  if (nullptr == pFromParty) {
1246  otErr
1247  << "OTSmartContract::GetAcctBalance: error: Party pointer nullptr "
1248  "on authorized agent (" << pFromAcct->GetAgentName()
1249  << ") for from_acct (" << from_acct_name << ").\n";
1250  return 0;
1251  }
1252  //
1253  // Below this point, these are all good:
1254  //
1255  // pFromAcct, from_acct_name, pFromAgent, pFromParty,
1256  // pServerNym, pCron.
1257 
1258  // Done: I can see that THIS VERIFICATION CODE WILL GET CALLED EVERY SINGLE
1259  // TIME THE SCRIPT
1260  // CALLS MOVE FUNDS. Maybe that's good, but since technically this only
1261  // needs to be verified before the
1262  // first call, and not for EVERY call during any of a script's runs, I
1263  // should probably move this verification
1264  // higher, such as each time the OTCronItem triggers, plus each time a party
1265  // triggers a clause directly
1266  // through the API (server message). As long as those are covered, I will be
1267  // able to remove it from here
1268  // which should be a significant improvement for performance.
1269  // It will be at the bottom of those same functions that
1270  // "ClearTemporaryPointers()" should finally be called.
1271  //
1272  //
1273  // FINAL DECISION: Redundant, already verified upon activation on cron.
1274  // See longer comment in OTSmartContract::StashAcctFunds()
1275  //
1276  // const OTString strServerID(GetServerID());
1277  //
1278  // mapOfNyms map_Nyms_Already_Loaded;
1279  // RetrieveNymPointers(map_Nyms_Already_Loaded);
1280  //
1281  //
1282  // if (!VerifyPartyAuthorization(*pFromParty, *pServerNym,
1283  // strServerID, &map_Nyms_Already_Loaded))
1284  // {
1285  // otErr << "OTSmartContract::GetAcctBalance: error: 'From' Party
1286  // (%s) not authorized for this contract.\n",
1287  // pFromParty->GetPartyName().c_str());
1288  // return 0;
1289  // }
1290 
1291  // A party might have many agents who are only voting groups, and cannot
1292  // actually sign for things
1293  // the way that nyms can. But at least ONE of those agents IS a Nym --
1294  // because there must have been
1295  // an authorizing agent who initially signed to accept the agreement, and
1296  // who fronted the opening
1297  // transaction number that activated it.
1298  //
1299  // Similarly, the authorized agent for any given party's account (each
1300  // account has its own authorized
1301  // agent) MUST be an active agent (an active agent is one with a
1302  // Nym--whether that Nym is representing
1303  // himself as the party, or whether representing some entity as an employee
1304  // in a role). Why MUST the
1305  // authorized agent be an active agent? Because when funds are moved, that
1306  // Nym must be loaded since
1307  // the account must show that Nym as a legal owner/agent. The MoveFunds will
1308  // cause a paymentReceipt to
1309  // drop into the Inbox for the relevant asset accounts, and that
1310  // paymentReceipt can ONLY be accepted
1311  // by that same Nym, who must use a transaction # that he signed for
1312  // previously and received through
1313  // his nymbox. There is actually no justification at all to take funds from
1314  // that account, since the
1315  // new balance has not yet been signed, UNLESS THE PAYMENTRECEIPT CONTAINS A
1316  // VALID, SIGNED AUTHORIZATION
1317  // FROM THE ACCOUNT HOLDER. *That* is why the authorizing agent must either
1318  // be the Party's Owner himself
1319  // (representing himself as an agent, which most will do) in which case he
1320  // will appear as the valid
1321  // owner of the account, OR he MUST be a Nym working in a Valid Role for an
1322  // Entity, where said Entity is
1323  // the valid owner on the account in question. Either OT, it will be
1324  // possible in OT for him to sign for
1325  // the paymentReceipts when they come in, and impossible for him to escape
1326  // liability for them.
1327  // (That's the idea anyway.)
1328  //
1329  // Since we know that the Authorized Agent for an account must be an ACTIVE
1330  // agent (one way or the other)
1331  // then we can error out here if he's not. We can then pass in his Nym ID.
1332  //
1333 
1334  OTIdentifier theFromAgentID;
1335  const bool bFromAgentID = pFromAgent->GetSignerID(theFromAgentID);
1336 
1337  if (!bFromAgentID) {
1338  otErr << "OTSmartContract::GetAcctBalance: Failed to find FromAgent's "
1339  "Signer ID: " << pFromAgent->GetName() << " \n";
1340  return 0;
1341  }
1342 
1343  if (!pFromAcct->GetAcctID().Exists()) {
1344  otErr << "OTSmartContract::GetAcctBalance: Error: FromAcct has empty "
1345  "AcctID: " << from_acct_name << " \n";
1346  return 0;
1347  }
1348 
1349  const OTIdentifier theFromAcctID(pFromAcct->GetAcctID());
1350  //
1351  // BELOW THIS POINT, theFromAcctID and theFromAgentID available.
1352 
1353  const OTIdentifier SERVER_ID(pCron->GetServerID());
1354  const OTIdentifier SERVER_USER_ID(*pServerNym);
1355 
1356  const std::string str_party_id = pFromParty->GetPartyID();
1357  const OTString strPartyID(str_party_id);
1358  const OTIdentifier PARTY_USER_ID(strPartyID);
1359 
1360  const OTIdentifier PARTY_ACCT_ID(pFromAcct->GetAcctID());
1361 
1362  // Load up the party's account so we can get the balance.
1363  //
1364  OTAccount* pPartyAssetAcct =
1365  OTAccount::LoadExistingAccount(PARTY_ACCT_ID, SERVER_ID);
1366 
1367  if (nullptr == pPartyAssetAcct) {
1368  otOut << "OTSmartContract::GetAcctBalance: ERROR verifying existence "
1369  "of source account.\n";
1370  FlagForRemoval(); // Remove it from future Cron processing, please.
1371  return 0;
1372  }
1373  else if (!pPartyAssetAcct->VerifySignature(*pServerNym)) {
1374  otOut << "OTSmartContract::GetAcctBalance: ERROR failed to verify the "
1375  "server's signature on the party's account.\n";
1376  FlagForRemoval(); // Remove it from future Cron processing, please.
1377  return 0;
1378  }
1379  else if (!pPartyAssetAcct->VerifyOwnerByID(PARTY_USER_ID)) {
1380  otOut << "OTSmartContract::GetAcctBalance: ERROR failed to verify "
1381  "party user ownership of party account.\n";
1382  FlagForRemoval(); // Remove it from future Cron processing, please.
1383  return 0;
1384  }
1385  // Past this point we know pPartyAssetAcct is good and will clean itself up.
1386  std::unique_ptr<OTAccount> theSourceAcctSmrtPtr(pPartyAssetAcct);
1387 
1388  OTString strBalance;
1389  strBalance.Format("%lld", pPartyAssetAcct->GetBalance());
1390 
1391  return strBalance.Get();
1392 }
OTLOG_IMPORT OTLogStream otOut
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTLOG_IMPORT OTLogStream otErr
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
OTPartyAccount * GetPartyAccount(std::string str_acct_name) const
static EXPORT OTAccount * LoadExistingAccount(const OTIdentifier &accountId, const OTIdentifier &serverId)
Definition: OTAccount.cpp:480
void opentxs::OTSmartContract::GetAllTransactionNumbers ( OTNumList numlistOutput) const
virtual

Reimplemented from opentxs::OTTrackable.

Definition at line 1052 of file OTSmartContract.cpp.

1053 {
1054  for (const auto& it : m_mapParties) {
1055  const OTParty* pParty = it.second;
1056  OT_ASSERT(nullptr != pParty);
1057 
1058  pParty->GetAllTransactionNumbers(numlistOutput);
1059  }
1060 }
mapOfParties m_mapParties
#define OT_ASSERT(x)
Definition: Assert.hpp:150
std::string opentxs::OTSmartContract::GetAssetTypeIDofAcct ( std::string  from_acct_name)

Definition at line 1394 of file OTSmartContract.cpp.

1395 {
1396  OTCron* pCron = GetCron();
1397  OT_ASSERT(nullptr != pCron);
1398 
1399  OTPseudonym* pServerNym = pCron->GetServerNym();
1400  OT_ASSERT(nullptr != pServerNym);
1401 
1402  // Below this point, these are all good:
1403  //
1404  // pServerNym, pCron.
1405  //
1406 
1407  std::string str_return_value;
1408 
1409  if (from_acct_name.size() <= 0) {
1410  otErr << "OTSmartContract::GetAssetTypeIDofAcct: error: from_acct_name "
1411  "is non-existent.\n";
1412  return str_return_value;
1413  }
1414 
1415  // Below this point, these are all good:
1416  //
1417  // from_acct_name,
1418  // pServerNym, pCron.
1419 
1420  OTPartyAccount* pFromAcct = GetPartyAccount(from_acct_name);
1421 
1422  if (nullptr == pFromAcct) {
1423  otOut << "OTSmartContract::GetAssetTypeIDofAcct: error: from_acct ("
1424  << from_acct_name << ") not found on any party.\n";
1425  return str_return_value;
1426  }
1427 
1428  // Below this point, these are all good:
1429  //
1430  // pFromAcct, from_acct_name,
1431  // pServerNym, pCron.
1432 
1433  OTAgent* pFromAgent =
1434  pFromAcct->GetAuthorizedAgent(); // This searches the account's party
1435  // for the account's authorized agent.
1436  // (That way it's impossible to get an agent for any other party.)
1437 
1438  if (nullptr == pFromAgent) {
1439  otOut << "OTSmartContract::GetAssetTypeIDofAcct: error: authorized "
1440  "agent (" << pFromAcct->GetAgentName()
1441  << ") not found for from_acct (" << from_acct_name
1442  << ") on acct's party.\n";
1443  return str_return_value;
1444  }
1445 
1446  if (!pFromAgent->IsAnIndividual()) {
1447  otOut << "OTSmartContract::GetAssetTypeIDofAcct: error: authorized "
1448  "agent (" << pFromAcct->GetAgentName() << ") for from_acct ("
1449  << from_acct_name << ") is not an active agent.\n";
1450  return str_return_value;
1451  }
1452  //
1453  // Below this point, these are all good:
1454  //
1455  // pFromAcct, from_acct_name, pFromAgent,
1456  // pServerNym, pCron.
1457 
1458  OTParty* pFromParty = pFromAgent->GetParty();
1459 
1460  if (nullptr == pFromParty) {
1461  otErr << "OTSmartContract::GetAssetTypeIDofAcct: error: Party pointer "
1462  "nullptr on authorized agent (" << pFromAcct->GetAgentName()
1463  << ") for from_acct (" << from_acct_name << ").\n";
1464  return str_return_value;
1465  }
1466  //
1467  // Below this point, these are all good:
1468  //
1469  // pFromAcct, from_acct_name, pFromAgent, pFromParty,
1470  // pServerNym, pCron.
1471 
1472  // Done: I can see that THIS VERIFICATION CODE WILL GET CALLED EVERY SINGLE
1473  // TIME THE SCRIPT
1474  // CALLS MOVE FUNDS. Maybe that's good, but since technically this only
1475  // needs to be verified before the
1476  // first call, and not for EVERY call during any of a script's runs, I
1477  // should probably move this verification
1478  // higher, such as each time the OTCronItem triggers, plus each time a party
1479  // triggers a clause directly
1480  // through the API (server message). As long as those are covered, I will be
1481  // able to remove it from here
1482  // which should be a significant improvement for performance.
1483  // It will be at the bottom of those same functions that
1484  // "ClearTemporaryPointers()" should finally be called.
1485  //
1486  //
1487  // FINAL DECISION: Redunant, already done upon activation onto cron.
1488  // Furthermore, expects no stashes to exist,
1489  // since they can only be created after activation. (Interfered with script
1490  // operations by complaining whenever
1491  // there was a stash.) See longer comment in StashAcctFunds().
1492  //
1493  // const OTString strServerID(GetServerID());
1494  //
1495  // mapOfNyms map_Nyms_Already_Loaded;
1496  // RetrieveNymPointers(map_Nyms_Already_Loaded);
1497  //
1498  //
1499  // if (!VerifyPartyAuthorization(*pFromParty, *pServerNym,
1500  // strServerID, &map_Nyms_Already_Loaded))
1501  // {
1502  // otErr << "OTSmartContract::GetAssetTypeIDofAcct: error: 'From'
1503  // Party (%s) not authorized for this contract.\n",
1504  // pFromParty->GetPartyName().c_str());
1505  // return str_return_value;
1506  // }
1507 
1508  // A party might have many agents who are only voting groups, and cannot
1509  // actually sign for things
1510  // the way that nyms can. But at least ONE of those agents IS a Nym --
1511  // because there must have been
1512  // an authorizing agent who initially signed to accept the agreement, and
1513  // who fronted the opening
1514  // transaction number that activated it.
1515  //
1516  // Similarly, the authorized agent for any given party's account (each
1517  // account has its own authorized
1518  // agent) MUST be an active agent (an active agent is one with a
1519  // Nym--whether that Nym is representing
1520  // himself as the party, or whether representing some entity as an employee
1521  // in a role). Why MUST the
1522  // authorized agent be an active agent? Because when funds are moved, that
1523  // Nym must be loaded since
1524  // the account must show that Nym as a legal owner/agent. The MoveFunds will
1525  // cause a paymentReceipt to
1526  // drop into the Inbox for the relevant asset accounts, and that
1527  // paymentReceipt can ONLY be accepted
1528  // by that same Nym, who must use a transaction # that he signed for
1529  // previously and received through
1530  // his nymbox. There is actually no justification at all to take funds from
1531  // that account, since the
1532  // new balance has not yet been signed, UNLESS THE PAYMENTRECEIPT CONTAINS A
1533  // VALID, SIGNED AUTHORIZATION
1534  // FROM THE ACCOUNT HOLDER. *That* is why the authorizing agent must either
1535  // be the Party's Owner himself
1536  // (representing himself as an agent, which most will do) in which case he
1537  // will appear as the valid
1538  // owner of the account, OR he MUST be a Nym working in a Valid Role for an
1539  // Entity, where said Entity is
1540  // the valid owner on the account in question. Either OT, it will be
1541  // possible in OT for him to sign for
1542  // the paymentReceipts when they come in, and impossible for him to escape
1543  // liability for them.
1544  // (That's the idea anyway.)
1545  //
1546  // Since we know that the Authorized Agent for an account must be an ACTIVE
1547  // agent (one way or the other)
1548  // then we can error out here if he's not. We can then pass in his Nym ID.
1549  //
1550 
1551  OTIdentifier theFromAgentID;
1552  const bool bFromAgentID = pFromAgent->GetSignerID(theFromAgentID);
1553 
1554  if (!bFromAgentID) {
1555  otErr << "OTSmartContract::GetAssetTypeIDofAcct: Failed to find "
1556  "FromAgent's Signer ID: " << pFromAgent->GetName() << " \n";
1557  return str_return_value;
1558  }
1559 
1560  if (!pFromAcct->GetAcctID().Exists()) {
1561  otErr << "OTSmartContract::GetAssetTypeIDofAcct: Error: FromAcct has "
1562  "empty AcctID: " << from_acct_name << " \n";
1563  return str_return_value;
1564  }
1565 
1566  const OTIdentifier theFromAcctID(pFromAcct->GetAcctID());
1567  //
1568  // BELOW THIS POINT, theFromAcctID and theFromAgentID available.
1569 
1570  const OTIdentifier SERVER_ID(pCron->GetServerID());
1571  const OTIdentifier SERVER_USER_ID(*pServerNym);
1572 
1573  const std::string str_party_id = pFromParty->GetPartyID();
1574  const OTString strPartyID(str_party_id);
1575  const OTIdentifier PARTY_USER_ID(strPartyID);
1576 
1577  const OTIdentifier PARTY_ACCT_ID(pFromAcct->GetAcctID());
1578 
1579  // Load up the party's account and get the asset type.
1580  //
1581  OTAccount* pPartyAssetAcct =
1582  OTAccount::LoadExistingAccount(PARTY_ACCT_ID, SERVER_ID);
1583 
1584  if (nullptr == pPartyAssetAcct) {
1585  otOut << "OTSmartContract::GetAssetTypeIDofAcct: ERROR verifying "
1586  "existence of source account.\n";
1587  FlagForRemoval(); // Remove it from future Cron processing, please.
1588  return str_return_value;
1589  }
1590  else if (!pPartyAssetAcct->VerifySignature(*pServerNym)) {
1591  otOut << "OTSmartContract::GetAssetTypeIDofAcct: ERROR failed to "
1592  "verify the server's signature on the party's account.\n";
1593  FlagForRemoval(); // Remove it from future Cron processing, please.
1594  return str_return_value;
1595  }
1596  else if (!pPartyAssetAcct->VerifyOwnerByID(PARTY_USER_ID)) {
1597  otOut << "OTSmartContract::GetAssetTypeIDofAcct: ERROR failed to "
1598  "verify party user ownership of party account.\n";
1599  FlagForRemoval(); // Remove it from future Cron processing, please.
1600  return str_return_value;
1601  }
1602  // Past this point we know pPartyAssetAcct is good and will clean itself up.
1603  std::unique_ptr<OTAccount> theSourceAcctSmrtPtr(pPartyAssetAcct);
1604 
1605  const OTString strAssetTypeID(pPartyAssetAcct->GetAssetTypeID());
1606  str_return_value = strAssetTypeID.Get();
1607 
1608  return str_return_value;
1609 }
OTLOG_IMPORT OTLogStream otOut
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTLOG_IMPORT OTLogStream otErr
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
OTPartyAccount * GetPartyAccount(std::string str_acct_name) const
static EXPORT OTAccount * LoadExistingAccount(const OTIdentifier &accountId, const OTIdentifier &serverId)
Definition: OTAccount.cpp:480
int64_t opentxs::OTSmartContract::GetClosingNumber ( const OTIdentifier theAcctID) const
virtual

Reimplemented from opentxs::OTCronItem.

Definition at line 1077 of file OTSmartContract.cpp.

1078 {
1079  OTPartyAccount* pPartyAcct =
1080  GetPartyAccountByID(theAcctID); // from OTScriptable.
1081 
1082  if (nullptr != pPartyAcct) {
1083  return pPartyAcct->GetClosingTransNo();
1084  }
1085 
1086  return 0;
1087 }
OTPartyAccount * GetPartyAccountByID(const OTIdentifier &theAcctID) const
int32_t opentxs::OTSmartContract::GetCountStashAccts ( ) const

Definition at line 5407 of file OTSmartContract.cpp.

5408 {
5409  return m_StashAccts.GetCountAccountIDs();
5410 }
EXPORT int32_t GetCountAccountIDs() const
int32_t opentxs::OTSmartContract::GetCountStashes ( ) const

Definition at line 5402 of file OTSmartContract.cpp.

5403 {
5404  return static_cast<int32_t>(m_mapStashes.size());
5405 }
const OTString& opentxs::OTSmartContract::GetLastRecipientAcctID ( ) const
inline

Definition at line 261 of file OTSmartContract.hpp.

262  {
263  return m_strLastRecipientAcct;
264  }
const OTString& opentxs::OTSmartContract::GetLastRecipientUserID ( ) const
inline

Definition at line 257 of file OTSmartContract.hpp.

258  {
259  return m_strLastRecipientUser;
260  }
const OTString& opentxs::OTSmartContract::GetLastSenderAcctID ( ) const
inline

Definition at line 253 of file OTSmartContract.hpp.

254  {
255  return m_strLastSenderAcct;
256  }
const OTString& opentxs::OTSmartContract::GetLastSenderUserID ( ) const
inline

Definition at line 249 of file OTSmartContract.hpp.

250  {
251  return m_strLastSenderUser;
252  }
const time64_t& opentxs::OTSmartContract::GetNextProcessDate ( ) const
inlineprotected

Definition at line 232 of file OTSmartContract.hpp.

233  {
234  return m_tNextProcessDate;
235  }
int64_t opentxs::OTSmartContract::GetOpeningNumber ( const OTIdentifier theNymID) const
virtual

Reimplemented from opentxs::OTCronItem.

Definition at line 1062 of file OTSmartContract.cpp.

1063 {
1064  OTAgent* pAgent = nullptr;
1065  OTParty* pParty = FindPartyBasedOnNymIDAsAgent(theNymID, &pAgent);
1066 
1067  if (nullptr != pParty) {
1068  OT_ASSERT_MSG(nullptr != pAgent,
1069  "OT_ASSERT: nullptr != pAgent in "
1070  "OTSmartContract::GetOpeningNumber.\n");
1071  return pParty->GetOpeningTransNo();
1072  }
1073 
1074  return 0;
1075 }
OTParty * FindPartyBasedOnNymIDAsAgent(const OTIdentifier &theNymID, OTAgent **ppAgent=nullptr) const
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
std::string opentxs::OTSmartContract::GetRemainingTimer ( ) const

Definition at line 1124 of file OTSmartContract.cpp.

1127 {
1128  const time64_t& tNextDate = GetNextProcessDate();
1129  const time64_t tCurrent = OTTimeGetCurrentTime();
1130 
1131  OTString strReturnVal("0"); // the default return value is "0".
1132 
1133  if (tNextDate > OT_TIME_ZERO) {
1134  const int64_t tSecondsLeft = OTTimeGetTimeInterval(tNextDate, tCurrent);
1135  strReturnVal.Format("%" PRId64 "", tSecondsLeft);
1136  }
1137 
1138  return strReturnVal.Get();
1139 }
int64_t OTTimeGetTimeInterval(time64_t lhs, time64_t rhs)
Definition: Common.hpp:234
int64_t time64_t
Definition: Common.hpp:209
const time64_t & GetNextProcessDate() const
time64_t OTTimeGetCurrentTime()
Definition: Common.hpp:211
#define OT_TIME_ZERO
Definition: Common.hpp:180
OTStash * opentxs::OTSmartContract::GetStash ( std::string  str_stash_name)

Definition at line 5315 of file OTSmartContract.cpp.

5316 {
5317  auto it = m_mapStashes.find(str_stash_name);
5318 
5319  if (m_mapStashes.end() == it) // It's not there. Create it.
5320  {
5321  OTStash* pStash = new OTStash(str_stash_name);
5322  OT_ASSERT(nullptr != pStash);
5323 
5324  m_mapStashes.insert(
5325  std::pair<std::string, OTStash*>(str_stash_name, pStash));
5326  return pStash;
5327  }
5328 
5329  OTStash* pStash = it->second;
5330  OT_ASSERT(nullptr != pStash);
5331 
5332  return pStash;
5333 }
#define OT_ASSERT(x)
Definition: Assert.hpp:150
std::string opentxs::OTSmartContract::GetStashBalance ( std::string  stash_name,
std::string  asset_type_id 
)

Definition at line 1611 of file OTSmartContract.cpp.

1613 {
1614  OTCron* pCron = GetCron();
1615  OT_ASSERT(nullptr != pCron);
1616 
1617  OTPseudonym* pServerNym = pCron->GetServerNym();
1618  OT_ASSERT(nullptr != pServerNym);
1619 
1620  // Below this point, these are all good:
1621  //
1622  // pServerNym, pCron.
1623  //
1624 
1625  if (from_stash_name.size() <= 0) {
1626  otErr << "OTSmartContract::GetStashBalance: error: from_stash_name is "
1627  "non-existent.\n";
1628  return 0;
1629  }
1630  if (asset_type_id.size() <= 0) {
1631  otErr << "OTSmartContract::GetStashBalance: error: asset_type_id is "
1632  "non-existent.\n";
1633  return 0;
1634  }
1635 
1636  // Below this point, these are all good:
1637  //
1638  // from_stash_name,
1639  // asset_type_id
1640  // pServerNym, pCron.
1641  //
1642 
1643  OTStash* pStash = GetStash(from_stash_name); // This ALWAYS succeeds.
1644  // (It will OT_ASSERT()
1645  // if failure.)
1646 
1647  //
1648  // Below this point, these are all good:
1649  //
1650  // pStash, from_stash_name,
1651  // asset_type_id
1652  // pServerNym, pCron.
1653  //
1654  OTString strBalance;
1655  strBalance.Format("%lld", pStash->GetAmount(asset_type_id));
1656  return strBalance.Get();
1657 }
OTStash * GetStash(std::string str_stash_name)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTLOG_IMPORT OTLogStream otErr
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
void opentxs::OTSmartContract::HarvestClosingNumbers ( OTPseudonym theNym)
virtual

Reimplemented from opentxs::OTCronItem.

Definition at line 5069 of file OTSmartContract.cpp.

5070 {
5071  // We do NOT call the parent version.
5072  // OTCronItem::HarvestClosingNumbers(theNym);
5073 
5074  // For payment plan, the parent (OTCronItem) grabs the sender's #s, and then
5075  // the subclass's
5076  // override (OTAgreement::HarvestClosingNumbers) grabs the recipient's #s.
5077  // But with SMART
5078  // CONTRACTS, there are only "the parties" and they ALL burned an opening #,
5079  // plus they can
5080  // ALL harvest their closing #s if activation failed. In fact, done: might
5081  // as well send them
5082  // all a notification if it fails, so they can all AUTOMATICALLY remove said
5083  // numbers from
5084  // their future balance agreements.
5085  //
5086 
5087  const OTString strServerID(GetServerID());
5088  const int32_t nTransNumCount = theNym.GetTransactionNumCount(
5089  GetServerID()); // save this to see if it changed, later.
5090 
5091  for (auto& it : m_mapParties) {
5092  OTParty* pParty = it.second;
5093  OT_ASSERT_MSG(nullptr != pParty,
5094  "Unexpected nullptr pointer in party map.");
5095 
5096  pParty->HarvestClosingNumbers(theNym, strServerID);
5097  }
5098 
5099  // It changed, so let's save it.
5100  if (nTransNumCount != theNym.GetTransactionNumCount(GetServerID()))
5101  theNym.SaveSignedNymfile(theNym);
5102 }
mapOfParties m_mapParties
const OTIdentifier & GetServerID() const
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
void opentxs::OTSmartContract::HarvestClosingNumbers ( OTPseudonym pSignerNym = nullptr,
std::set< OTParty * > *  pFailedParties = nullptr 
)

Definition at line 5008 of file OTSmartContract.cpp.

5010 {
5011  const OTString strServerID(GetServerID());
5012 
5013  for (auto& it : m_mapParties) {
5014  const std::string str_party_name = it.first;
5015  OTParty* pParty = it.second;
5016  OT_ASSERT_MSG(nullptr != pParty,
5017  "OTSmartContract::HarvestClosingNumbers: "
5018  "Unexpected nullptr pointer in party map.");
5019 
5020  // If certain parties failed verification, then
5021  // OTSmartContract::VerifySmartContract() is smart enough
5022  // not to bother verifying the accounts of those parties. Thus, the
5023  // closing numbers for those accounts
5024  // could NOT have been marked as "used" (since they were skipped). So we
5025  // passed that same set of failed
5026  // parties into this function here, so that we can skip them here as
5027  // well, when harvesting the closing
5028  // numbers back again.
5029  //
5030  if (nullptr != pFailedParties) // There are failed parties.
5031  {
5032 
5033  // Skip failed parties...
5034  //
5035  auto it_failed = pFailedParties->find(pParty);
5036 
5037  if (pFailedParties->end() != it_failed) // this means pParty was
5038  // found on the FAILED list.
5039  // (So we can skip it here.)
5040  {
5041  otOut << __FUNCTION__ << ": FYI, at least one party ("
5042  << str_party_name
5043  << ") has failed verification, so right now I'm skipping "
5044  "harvesting of his "
5045  "closing transaction numbers. (Since he failed, we "
5046  "never verified his accounts, so we never grabbed "
5047  "those closing "
5048  "numbers in the first place, so there's no need to "
5049  "grab them back now.)\n";
5050  continue;
5051  }
5052  }
5053 
5054  // For all non-failed parties, now we harvest the closing transaction
5055  // numbers:
5056  //
5057  pParty->HarvestClosingNumbers(
5058  strServerID, // <============== (THE HARVEST.)
5059  true, // bSave=true
5060  pSignerNym);
5061  }
5062 }
OTLOG_IMPORT OTLogStream otOut
mapOfParties m_mapParties
const OTIdentifier & GetServerID() const
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
void opentxs::OTSmartContract::HarvestOpeningNumber ( OTPseudonym theNym)
virtual

Reimplemented from opentxs::OTCronItem.

Definition at line 5113 of file OTSmartContract.cpp.

5114 {
5115  // We do NOT call the parent version.
5116  // OTCronItem::HarvestOpeningNumber(theNym);
5117 
5118  // For payment plan, the parent (OTCronItem) grabs the sender's #s, and then
5119  // the subclass's
5120  // override (OTAgreement::HarvestClosingNumbers) grabs the recipient's #s.
5121  // But with SMART
5122  // CONTRACTS, there are only "the parties" and they ALL burned an opening #,
5123  // plus they can
5124  // ALL harvest their closing #s if activation failed. In fact, todo: might
5125  // as well send them
5126  // all a notification if it fails, so they can all AUTOMATICALLY remove said
5127  // numbers from
5128  // their future balance agreements.
5129  //
5130 
5131  const OTString strServerID(GetServerID());
5132  const int32_t nTransNumCount = theNym.GetTransactionNumCount(
5133  GetServerID()); // save this to see if it changed, later.
5134 
5135  for (auto& it : m_mapParties) {
5136  OTParty* pParty = it.second;
5137  OT_ASSERT_MSG(nullptr != pParty,
5138  "Unexpected nullptr pointer in party map.");
5139 
5140  pParty->HarvestOpeningNumber(theNym, strServerID);
5141  }
5142 
5143  // It changed, so let's save it.
5144  if (nTransNumCount != theNym.GetTransactionNumCount(GetServerID()))
5145  theNym.SaveSignedNymfile(theNym);
5146 }
mapOfParties m_mapParties
const OTIdentifier & GetServerID() const
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
bool opentxs::OTSmartContract::HasTransactionNum ( const int64_t &  lInput) const
virtual

Reimplemented from opentxs::OTTrackable.

Definition at line 1040 of file OTSmartContract.cpp.

1041 {
1042  for (const auto& it : m_mapParties) {
1043  const OTParty* pParty = it.second;
1044  OT_ASSERT(nullptr != pParty);
1045 
1046  if (pParty->HasTransactionNum(lInput)) return true;
1047  }
1048 
1049  return false;
1050 }
mapOfParties m_mapParties
#define OT_ASSERT(x)
Definition: Assert.hpp:150
void opentxs::OTSmartContract::InitSmartContract ( )

Definition at line 5357 of file OTSmartContract.cpp.

5358 {
5359  m_strContractType = "SMARTCONTRACT";
5360 
5362  SMART_CONTRACT_PROCESS_INTERVAL); // Smart contracts current default is
5363  // 30 seconds. Actual default will
5364  // probably be configurable in config
5365  // file, and most contracts will also
5366  // probably override this.
5367 }
#define SMART_CONTRACT_PROCESS_INTERVAL
OTString m_strContractType
Definition: OTContract.hpp:178
void SetProcessInterval(const int64_t &THE_DATE)
Definition: OTCronItem.hpp:284
bool opentxs::OTSmartContract::IsValidOpeningNumber ( const int64_t &  lOpeningNum) const
virtual

Reimplemented from opentxs::OTCronItem.

Definition at line 1024 of file OTSmartContract.cpp.

1025 {
1026  for (const auto& it : m_mapParties) {
1027  OTParty* pParty = it.second;
1028  OT_ASSERT(nullptr != pParty);
1029 
1030  if (pParty->GetOpeningTransNo() == lOpeningNum) return true;
1031  }
1032 
1033  return false;
1034 }
mapOfParties m_mapParties
#define OT_ASSERT(x)
Definition: Assert.hpp:150
bool opentxs::OTSmartContract::MoveAcctFundsStr ( std::string  from_acct_name,
std::string  to_acct_name,
std::string  str_Amount 
)

Definition at line 3119 of file OTSmartContract.cpp.

3122 {
3123  OTCron* pCron = GetCron();
3124  OT_ASSERT(nullptr != pCron);
3125 
3126  OTPseudonym* pServerNym = pCron->GetServerNym();
3127  OT_ASSERT(nullptr != pServerNym);
3128 
3129  // Below this point, these are all good:
3130  //
3131  // pServerNym, pCron.
3132 
3133  if (str_Amount.size() < 1) {
3134  otOut << "OTSmartContract::MoveAcctFunds: Error: empty amount.\n";
3135  return false;
3136  }
3137 
3138  const int64_t lAmount = atol(str_Amount.c_str());
3139 
3140  if (lAmount <= 0) {
3141  otOut << "OTSmartContract::MoveAcctFunds: Error: lAmount cannot be 0 "
3142  "or <0. (Value passed in was " << lAmount << ".)\n";
3143  return false;
3144  }
3145 
3146  if (from_acct_name.size() <= 0) {
3147  otErr << "OTSmartContract::MoveAcctFunds: error: from_acct_name is "
3148  "non-existent.\n";
3149  return false;
3150  }
3151  if (to_acct_name.size() <= 0) {
3152  otErr << "OTSmartContract::MoveAcctFunds: error: to_acct_name is "
3153  "non-existent.\n";
3154  return false;
3155  }
3156 
3157  // Below this point, these are all good:
3158  //
3159  // from_acct_name,
3160  // to_acct_name,
3161  // pServerNym, pCron.
3162 
3163  OTPartyAccount* pFromAcct = GetPartyAccount(from_acct_name);
3164  OTPartyAccount* pToAcct = GetPartyAccount(to_acct_name);
3165 
3166  if (nullptr == pFromAcct) {
3167  otOut << "OTSmartContract::MoveAcctFunds: error: from_acct ("
3168  << from_acct_name << ") not found on any party.\n";
3169  otOut << "FULL CONTRACT: \n" << m_xmlUnsigned << " \n\n";
3170  return false;
3171  }
3172  if (nullptr == pToAcct) {
3173  otOut << "OTSmartContract::MoveAcctFunds: error: to_acct ("
3174  << to_acct_name << ") not found on any party.\n";
3175  otOut << "FULL CONTRACT: \n" << m_xmlUnsigned << " \n\n";
3176 
3177  return false;
3178  }
3179 
3180  // Below this point, these are all good:
3181  //
3182  // pFromAcct, from_acct_name,
3183  // pToAcct, to_acct_name,
3184  // pServerNym, pCron.
3185 
3186  OTAgent* pFromAgent =
3187  pFromAcct->GetAuthorizedAgent(); // This searches the account's party
3188  // for the account's authorized agent.
3189  OTAgent* pToAgent =
3190  pToAcct->GetAuthorizedAgent(); // (That way it's impossible to get an
3191  // agent for any other party.)
3192 
3193  if (nullptr == pFromAgent) {
3194  otOut << "OTSmartContract::MoveAcctFunds: error: authorized agent ("
3195  << pFromAcct->GetAgentName() << ") not found for from_acct ("
3196  << from_acct_name << ") on acct's party.\n";
3197  return false;
3198  }
3199  if (nullptr == pToAgent) {
3200  otOut << "OTSmartContract::MoveAcctFunds: error: authorized agent ("
3201  << pToAcct->GetAgentName() << ") not found for to_acct ("
3202  << to_acct_name << ") on acct's party.\n";
3203  return false;
3204  }
3205 
3206  if (!pFromAgent->IsAnIndividual()) {
3207  otOut << "OTSmartContract::MoveAcctFunds: error: authorized agent ("
3208  << pFromAcct->GetAgentName() << ") for from_acct ("
3209  << from_acct_name << ") is not an active agent.\n";
3210  return false;
3211  }
3212  if (!pToAgent->IsAnIndividual()) {
3213  otOut << "OTSmartContract::MoveAcctFunds: error: authorized agent ("
3214  << pToAcct->GetAgentName() << ") for to_acct (" << to_acct_name
3215  << ") is not an active agent.\n";
3216  return false;
3217  }
3218  //
3219  // Below this point, these are all good:
3220  //
3221  // pFromAcct, from_acct_name, pFromAgent,
3222  // pToAcct, to_acct_name, pToAgent,
3223  // pServerNym, pCron.
3224 
3225  OTParty* pFromParty = pFromAgent->GetParty();
3226  OTParty* pToParty = pToAgent->GetParty();
3227 
3228  if (nullptr == pFromParty) {
3229  otErr << "OTSmartContract::MoveAcctFunds: error: Party pointer nullptr "
3230  "on "
3231  "authorized agent (" << pFromAcct->GetAgentName()
3232  << ") for from_acct (" << from_acct_name << ").\n";
3233  return false;
3234  }
3235  if (nullptr == pToParty) {
3236  otErr << "OTSmartContract::MoveAcctFunds: error: Party pointer nullptr "
3237  "on "
3238  "authorized agent (" << pToAcct->GetAgentName()
3239  << ") for to_acct (" << to_acct_name << ").\n";
3240  return false;
3241  }
3242  //
3243  // Below this point, these are all good:
3244  //
3245  // pFromAcct, from_acct_name, pFromAgent, pFromParty,
3246  // pToAcct, to_acct_name, pToAgent, pToParty,
3247  // pServerNym, pCron.
3248 
3249  // Done: I can see that THIS VERIFICATION CODE WILL GET CALLED EVERY SINGLE
3250  // TIME THE SCRIPT
3251  // CALLS MOVE FUNDS. Maybe that's good, but since technically this only
3252  // needs to be verified before the
3253  // first call, and not for EVERY call during any of a script's runs, I
3254  // should probably move this verification
3255  // higher, such as each time the OTCronItem triggers, plus each time a party
3256  // triggers a clause directly
3257  // through the API (server message). As long as those are covered, I will be
3258  // able to remove it from here
3259  // which should be a significant improvement for performance.
3260  // It will be at the bottom of those same functions that
3261  // "ClearTemporaryPointers()" should finally be called.
3262  //
3263  // FINAL DECISION: Redundant. See comment in
3264  // OTSmartContract::StashAcctFunds()
3265  //
3266  // A party might have many agents who are only voting groups, and cannot
3267  // actually sign for things
3268  // the way that nyms can. But at least ONE of those agents IS a Nym --
3269  // because there must have been
3270  // an authorizing agent who initially signed to accept the agreement, and
3271  // who fronted the opening
3272  // transaction number that activated it.
3273  //
3274  // Similarly, the authorized agent for any given party's account (each
3275  // account has its own authorized
3276  // agent) MUST be an active agent (an active agent is one with a
3277  // Nym--whether that Nym is representing
3278  // himself as the party, or whether representing some entity as an employee
3279  // in a role). Why MUST the
3280  // authorized agent be an active agent? Because when funds are moved, that
3281  // Nym must be loaded since
3282  // the account must show that Nym as a legal owner/agent. The MoveFunds will
3283  // cause a paymentReceipt to
3284  // drop into the Inbox for the relevant asset accounts, and that
3285  // paymentReceipt can ONLY be accepted
3286  // by that same Nym, who must use a transaction # that he signed for
3287  // previously and received through
3288  // his nymbox. There is actually no justification at all to take funds from
3289  // that account, since the
3290  // new balance has not yet been signed, UNLESS THE PAYMENTRECEIPT CONTAINS A
3291  // VALID, SIGNED AUTHORIZATION
3292  // FROM THE ACCOUNT HOLDER. *That* is why the authorizing agent must either
3293  // be the Party's Owner himself
3294  // (representing himself as an agent, which most will do) in which case he
3295  // will appear as the valid
3296  // owner of the account, OR he MUST be a Nym working in a Valid Role for an
3297  // Entity, where said Entity is
3298  // the valid owner on the account in question. Either OT, it will be
3299  // possible in OT for him to sign for
3300  // the paymentReceipts when they come in, and impossible for him to escape
3301  // liability for them.
3302  // (That's the idea anyway.)
3303  //
3304  // Since we know that the Authorized Agent for an account must be an ACTIVE
3305  // agent (one way or the other)
3306  // then we can error out here if he's not. We can then pass in his Nym ID
3307  //
3308 
3309  OTIdentifier theFromAgentID, theToAgentID;
3310  const bool bFromAgentID = pFromAgent->GetSignerID(theFromAgentID);
3311  const bool bToAgentID = pToAgent->GetSignerID(theToAgentID);
3312 
3313  if (!bFromAgentID) {
3314  otErr << "OTSmartContract::MoveAcctFunds: Failed to find FromAgent's "
3315  "Signer ID: " << pFromAgent->GetName() << " \n";
3316  return false;
3317  }
3318  if (!bToAgentID) {
3319  otErr << "OTSmartContract::MoveAcctFunds: Failed to find ToAgent's "
3320  "Signer ID: " << pToAgent->GetName() << " \n";
3321  return false;
3322  }
3323 
3324  if (!pFromAcct->GetAcctID().Exists()) {
3325  otErr << "OTSmartContract::MoveAcctFunds: Error: FromAcct has empty "
3326  "AcctID: " << from_acct_name << " \n";
3327  return false;
3328  }
3329  if (!pToAcct->GetAcctID().Exists()) {
3330  otErr << "OTSmartContract::MoveAcctFunds: Error: ToAcct has empty "
3331  "AcctID: " << to_acct_name << " \n";
3332  return false;
3333  }
3334 
3335  const OTIdentifier theFromAcctID(pFromAcct->GetAcctID()),
3336  theToAcctID(pToAcct->GetAcctID());
3337  //
3338  // BELOW THIS POINT, theFromAcctID, theFromAgentID, theToAcctID, and
3339  // theToAgentID are all available.
3340 
3341  // WE SET THESE HERE SO THE RECEIPT SHOWS, SUCCESS OR FAIL,
3342  // WHO THE INTENDED SENDER / RECIPIENT ARE FOR THAT RECEIPT.
3343  //
3345 
3346  theFromAgentID.GetString(m_strLastSenderUser); // This is the last User ID
3347  // of a party who SENT money.
3348  theFromAcctID.GetString(m_strLastSenderAcct); // This is the last Acct ID of
3349  // a party who SENT money.
3350  theToAgentID.GetString(m_strLastRecipientUser); // This is the last User ID
3351  // of a party who RECEIVED
3352  // money.
3353  theToAcctID.GetString(m_strLastRecipientAcct); // This is the last Acct ID
3354  // of a party who RECEIVED
3355  // money.
3356 
3357  mapOfNyms map_Nyms_Already_Loaded;
3358  RetrieveNymPointers(map_Nyms_Already_Loaded);
3359 
3360  bool bMoved = MoveFunds(map_Nyms_Already_Loaded, lAmount, theFromAcctID,
3361  theFromAgentID, theToAcctID, theToAgentID);
3362  if (!bMoved) {
3363  otOut << "OTSmartContract::MoveAcctFunds: Failed in call to MoveFunds. "
3364  "from_acct: " << from_acct_name
3365  << " to_acct: " << to_acct_name << "\n";
3366  return false;
3367  }
3368 
3369  return true;
3370 }
OTLOG_IMPORT OTLogStream otOut
std::map< std::string, OTPseudonym * > mapOfNyms
Definition: OTWallet.hpp:161
#define OT_ASSERT(x)
Definition: Assert.hpp:150
void RetrieveNymPointers(mapOfNyms &map_Nyms_Already_Loaded)
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
OTLOG_IMPORT OTLogStream otErr
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
OTPartyAccount * GetPartyAccount(std::string str_acct_name) const
void opentxs::OTSmartContract::onActivate ( )
protectedvirtual

Reimplemented from opentxs::OTCronItem.

Definition at line 1156 of file OTSmartContract.cpp.

1157 {
1158  OT_ASSERT(nullptr != GetCron());
1159 
1160  if (GetCron()->GetTransactionCount() < 1) {
1161  otOut << __FUNCTION__ << ": Failed to process smart contract "
1162  << GetTransactionNum() << ": Out of transaction numbers for "
1163  "receipts! Flagging for removal.\n";
1164  FlagForRemoval();
1165  return;
1166  }
1167 
1168  // Execute the scripts (clauses) that have registered for this hook.
1169 
1170  const std::string str_HookName(SMARTCONTRACT_HOOK_ON_ACTIVATE);
1171  mapOfClauses theMatchingClauses;
1172 
1173  if (GetHooks(str_HookName, theMatchingClauses)) {
1174  otOut << "Cron: Processing smart contract clauses for hook: "
1175  << SMARTCONTRACT_HOOK_ON_ACTIVATE << " \n";
1176 
1178  theMatchingClauses); // <============================================
1179  }
1180 }
#define SMARTCONTRACT_HOOK_ON_ACTIVATE
int64_t GetTransactionNum() const
OTLOG_IMPORT OTLogStream otOut
std::map< std::string, OTClause * > mapOfClauses
Definition: OTBylaw.hpp:145
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT void ExecuteClauses(mapOfClauses &theClauses, OTString *pParam=nullptr)
bool GetHooks(std::string str_HookName, mapOfClauses &theResults)
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
void opentxs::OTSmartContract::onFinalReceipt ( OTCronItem theOrigCronItem,
const int64_t &  lNewTransactionNumber,
OTPseudonym theOriginator,
OTPseudonym pRemover 
)
protectedvirtual

Reimplemented from opentxs::OTCronItem.

Definition at line 3377 of file OTSmartContract.cpp.

3384 {
3385  OTCron* pCron = GetCron();
3386  OT_ASSERT(nullptr != pCron);
3387 
3388  OTPseudonym* pServerNym = pCron->GetServerNym();
3389  OT_ASSERT(nullptr != pServerNym);
3390 
3391  const OTString strServerID(GetServerID());
3392 
3393  // The finalReceipt Item's ATTACHMENT contains the UPDATED Cron Item.
3394  // (With the SERVER's signature on it!)
3395  //
3396  OTString strUpdatedCronItem(*this);
3397  OTString* pstrAttachment = &strUpdatedCronItem;
3398 
3399  const OTString strOrigCronItem(theOrigCronItem);
3400 
3401  // IF server is originator and/or remover then swap it in for it/them so I
3402  // don't load it twice.
3403  // (already handled before this function is called.)
3404 
3405  // THIS FUNCTION:
3406  //
3407  //
3408  // LOOP through all parties.
3409  // For each party:
3410  // If party is server or originator or ActingNym, etc then set pointer
3411  // appropriately for that party.
3412  // Find opening and closing numbers for that party.
3413  // Drop finalReceipt to Inboxes for each asset account, using closing
3414  // numbers.
3415  // Drop finalReceipt to Nymbox for that party, using opening number.
3416  //
3417  // A similar process should happen whenever ANY contract action occurs. (Not
3418  // just finalReceipt)
3419  // We loop through all the parties and give them a receipt in the relevant
3420  // accounts.
3421  // And perhaps all notices should be numbered (similar to request number) so
3422  // that
3423  // people can prove which notices they have received.
3424  // Receipts are given based on?
3425  // The asset accounts that are CHANGED should definitely get an
3426  // agreementReceipt for the
3427  // balance change. + All Nymboxes should receive a notice at that time.
3428  // They should receive
3429  // additional notice for any change in any variable as well. Maybe let
3430  // parties register for
3431  // various notices.
3432  // What about if a clause processes, but no asset accounts are changed, (no
3433  // inbox notice)
3434  // and no other variables are changed (no nymbox notices at all...) In that
3435  // case,
3436  // no other receipts are dropped, right? There will be some standard by
3437  // which DIRTY flags
3438  // are set onto the various parties and asset accounts, and then notices
3439  // will be sent based
3440  // upon those.
3441  //
3442  // For those, instead of:
3443  // "theOriginator" (GetSenderUserID()) and "pRemover" and pRecipient,
3444  //
3445  // We would have:
3446  // "theOriginator" (GetSenderUserID()) and "pActingNym" and pParty /
3447  // pPartyNym (for Party[0..n])
3448  //
3449  // Just like here:
3450  //
3451 
3452  for (auto& it : m_mapParties) {
3453  OTParty* pParty = it.second;
3454  OT_ASSERT_MSG(nullptr != pParty,
3455  "Unexpected nullptr pointer in party map.");
3456 
3457  // The Nym who is actively requesting to remove a cron item will be
3458  // passed in as pActingNym.
3459  // However, sometimes there is no Nym... perhaps it just expired and
3460  // pActingNym is nullptr.
3461  // The originating Nym (if different than pActingNym) is loaded up.
3462  // Otherwise theOriginator
3463  // just points to *pActingNym also.
3464  //
3465  OTPseudonym* pPartyNym = nullptr;
3466  std::unique_ptr<OTPseudonym> thePartyNymAngel;
3467 
3468  // See if the serverNym is an agent on this party.
3469  //
3470  if (pParty->HasAuthorizingAgent(*pServerNym)) // This should set the
3471  // temp nym ptr inside the
3472  // agent also, so I don't
3473  // have to search twice.
3474  {
3475  pPartyNym = pServerNym; // Just in case the party's agent's Nym is
3476  // also the server Nym.
3477  }
3478  //
3479  // If pActingNym is NOT nullptr, and HE is an agent on this party...
3480  // then set the pointer accordingly.
3481  //
3482  else if ((nullptr != pActingNym) &&
3483  pParty->HasAuthorizingAgent(*pActingNym)) // There is only one
3484  // authorizing agent
3485  // per party.
3486  {
3487  pPartyNym = pActingNym; // <======== now both pointers are set (to
3488  // same Nym). DONE!
3489  }
3490 
3491  // Still not found?
3492  if (nullptr == pPartyNym) {
3493  // Of all of a party's Agents, the "authorizing agent" is the one
3494  // who originally activated
3495  // the agreement for this party (and fronted the opening trans#.) If
3496  // we're ending the agreement,
3497  // Then we need to free that number from him. (Even if he was since
3498  // fired from the role!)
3499  //
3500  // Perhaps need to figure out if the Role itself stores the opening
3501  // number, and if so, treat
3502  // the Nym's signature as the role's, even though the Nym himself
3503  // doesn't actually store the #.
3504  // Anyway, I'll deal with that when I get to entities and roles.
3505  // Todo.
3506  //
3507  pPartyNym = pParty->LoadAuthorizingAgentNym(*pServerNym);
3508  thePartyNymAngel.reset(pPartyNym);
3509  }
3510 
3511  // Every party SHOULD have an authorizing agent (otherwise how did that
3512  // party sign on in the first
3513  // place??) So this should never fail. That's why there's an error
3514  // message below if it's still nullptr.
3515  //
3516 
3517  if ((nullptr != pPartyNym) && (pParty->GetOpeningTransNo() > 0) &&
3518  // Todo: once entities and roles are added, Parties should have
3519  // their OWN "verify" function
3520  // (Instead of me having to directly find the Nym and verify it
3521  // myself.)
3522  //
3523  pPartyNym->VerifyIssuedNum(
3524  strServerID,
3525  pParty->GetOpeningTransNo()) // <=====================
3526  ) {
3527  // The Nym (server side) stores a list of all opening and closing
3528  // cron #s.
3529  // So when the number is released from the Nym, we also take it off
3530  // that list.
3531  //
3532  std::set<int64_t>& theIDSet = pPartyNym->GetSetOpenCronItems();
3533  theIDSet.erase(pParty->GetOpeningTransNo());
3534 
3535  // the RemoveIssued call means the original transaction# (to find
3536  // this cron item on cron) is now CLOSED.
3537  // But the Transaction itself is still OPEN. How? Because the
3538  // CLOSING number is still signed out.
3539  // The closing number is also USED, since the smart contract was
3540  // initially activated, but it remains
3541  // ISSUED, until the final receipt itself is accepted during a
3542  // process inbox.
3543  //
3544  pPartyNym->RemoveIssuedNum(*pServerNym, strServerID,
3545  pParty->GetOpeningTransNo(),
3546  false); // bSave=false
3547  pPartyNym->SaveSignedNymfile(*pServerNym);
3548  }
3549  else {
3550  otErr
3551  << "OTSmartContract::" << __FUNCTION__
3552  << ": Failed verifying "
3553  "pPartyNym != nullptr && pParty->GetOpeningTransNo() > 0 && "
3554  " "
3555  "pPartyNym->VerifyIssuedNum(pParty->GetOpeningTransNo())\n";
3556  }
3557 
3558  // NOTIFY ALL AGENTS for this party, with a copy of the finalReceipt in
3559  // their Nymbox.
3560  //
3561  // TOdo: if the above block fails, should I still go dropping these
3562  // receipts?
3563  //
3564  if ((false ==
3565  pParty->DropFinalReceiptToNymboxes(
3566  lNewTransactionNumber, // new, owned by the server.
3567  // For notices.
3568  strOrigCronItem, nullptr, pstrAttachment, pPartyNym))) {
3569  otErr << "OTSmartContract::" << __FUNCTION__
3570  << ": Failure dropping final receipt into nymbox for even a "
3571  "single agent.\n";
3572  }
3573 
3574  // So the same Nym doesn't get loaded twice on accident. (We pass in
3575  // pointers to nyms that
3576  // are already loaded, so the called function can use them instead of
3577  // loading, if it came
3578  // to that.)
3579  //
3580  // typedef std::map <std::string, OTPseudonym *> mapOfNyms;
3581 
3582  mapOfNyms nym_map;
3583 
3584  // pServerNym
3585  {
3586  const OTIdentifier theServerNymID(*pServerNym);
3587  const OTString strServerNymID(theServerNymID);
3588 
3589  if (nym_map.end() == nym_map.find(strServerNymID.Get()))
3590  nym_map.insert(std::pair<std::string, OTPseudonym*>(
3591  strServerNymID.Get(), pServerNym));
3592  }
3593 
3594  // theOriginator
3595  {
3596  const OTIdentifier theOriginatorNymID(theOriginator);
3597  const OTString strOriginatorNymID(theOriginatorNymID);
3598 
3599  if (nym_map.end() == nym_map.find(strOriginatorNymID.Get()))
3600  nym_map.insert(std::pair<std::string, OTPseudonym*>(
3601  strOriginatorNymID.Get(), &theOriginator));
3602  }
3603 
3604  if (nullptr != pActingNym) {
3605  const OTIdentifier theActingNymID(*pActingNym);
3606  const OTString strActingNymID(theActingNymID);
3607 
3608  if (nym_map.end() == nym_map.find(strActingNymID.Get()))
3609  nym_map.insert(std::pair<std::string, OTPseudonym*>(
3610  strActingNymID.Get(), pActingNym));
3611  }
3612 
3613  if (nullptr != pPartyNym) {
3614  const OTIdentifier thePartyNymID(*pPartyNym);
3615  const OTString strPartyNymID(thePartyNymID);
3616 
3617  if (nym_map.end() == nym_map.find(strPartyNymID.Get()))
3618  nym_map.insert(std::pair<std::string, OTPseudonym*>(
3619  strPartyNymID.Get(), pPartyNym));
3620  }
3621 
3622  // NOTIFY the agent for EACH ACCOUNT listed by this party,
3623  // with a copy of the finalReceipt in the Inbox for each asset acct.
3624  //
3625  // Also for each, if he has a Nym (HE SHOULD), and if
3626  // (CLOSING_NUMBER_HERE > 0), then call:
3627  //
3628  // pNym->VerifyIssuedNum(strServerID, lClosingNumber)
3629  // (This happens in OTAgent::DropFinalReceipt, FYI.)
3630  //
3631 
3632  if (false ==
3633  pParty->DropFinalReceiptToInboxes(
3634  &nym_map, // contains any Nyms who might already be
3635  // loaded, mapped by ID.
3636  strServerID, *pServerNym, lNewTransactionNumber,
3637  strOrigCronItem, nullptr, pstrAttachment)) {
3638  otErr << "OTSmartContract::onFinalReceipt: Failure dropping final "
3639  "receipt into all inboxes. (Missed at least one.)\n";
3640  }
3641 
3642  pParty->ClearTemporaryPointers();
3643  }
3644 }
std::map< std::string, OTPseudonym * > mapOfNyms
Definition: OTWallet.hpp:161
mapOfParties m_mapParties
const OTIdentifier & GetServerID() const
#define OT_ASSERT(x)
Definition: Assert.hpp:150
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
OTLOG_IMPORT OTLogStream otErr
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
void opentxs::OTSmartContract::onRemovalFromCron ( )
protectedvirtual

Reimplemented from opentxs::OTCronItem.

Definition at line 1141 of file OTSmartContract.cpp.

1142 {
1143  // Not much needed here. Done, I guess.
1144 
1145  otErr << "FYI: OTSmartContract::onRemovalFromCron was just called. \n";
1146 
1147  // Trigger a script maybe.
1148  // OR maybe it's too late for scripts.
1149  // I give myself an onRemoval() here in C++, but perhaps I cut
1150  // off the SCRIPTS after onFinalReceipt(). I think that's best.
1151 }
OTLOG_IMPORT OTLogStream otErr
void opentxs::OTSmartContract::PrepareToActivate ( const int64_t &  lOpeningTransNo,
const int64_t &  lClosingTransNo,
const OTIdentifier theUserID,
const OTIdentifier theAcctID 
)

Definition at line 5589 of file OTSmartContract.cpp.

5593 {
5594  SetTransactionNum(lOpeningTransNo);
5595 
5596  ClearClosingNumbers(); // Just in case. Should be unnecessary, but you never
5597  // know how people might screw around.
5598  AddClosingTransactionNo(lClosingTransNo);
5599 
5600  SetSenderUserID(theUserID); // This is the activator of the contract. (NOT
5601  // the actual "sender" of any single payment, in
5602  // the case of smart contracts anyway.)
5603  SetSenderAcctID(theAcctID); // This is an account provided by the activator
5604  // so a closing number and final receipt are
5605  // guaranteed for this smart contract.
5606 
5607  ReleaseLastSenderRecipientIDs(); // These should be blank starting out
5608  // anyway.
5609 
5610  // You shouldn't have any of these anyway; the server only creates
5611  // them after a smart contract is activated.
5612  //
5613  ReleaseStashes();
5614 }
void SetTransactionNum(int64_t lTransactionNum)
void SetSenderAcctID(const OTIdentifier &ACCT_ID)
void SetSenderUserID(const OTIdentifier &USER_ID)
EXPORT void AddClosingTransactionNo(const int64_t &lClosingTransactionNo)
Definition: OTCronItem.cpp:693
bool opentxs::OTSmartContract::ProcessCron ( )
virtual

Reimplemented from opentxs::OTCronItem.

Definition at line 3649 of file OTSmartContract.cpp.

3650 {
3651  OT_ASSERT(nullptr != GetCron());
3652 
3653  // Right now Cron is called 10 times per second.
3654  // I'm going to slow down all trades so they are once every
3655  // GetProcessInterval()
3656  // Todo: Create separate lists in Cron. 10*/sec list, 1/second list, 1 min
3657  // list, 1 hour, 1 day, 1 month.
3658  // That way I'm not looping through ALL cron items 10*/second, but only the
3659  // ones who are paying for those
3660  // kinds of resources. (Different lists will cost different server fees.)
3661  //
3662  if (GetLastProcessDate() > OT_TIME_ZERO) {
3663  // Default ProcessInternal is 1 second, but Trades will use 10 seconds,
3664  // and Payment
3665  // Plans will use an hour or day. Smart contracts are currently 30
3666  // seconds. (For testing.)
3667  //
3670  return true;
3671  }
3672  // Keep a record of the last time this was processed.
3673  // (NOT saved to storage, only used while the software is running.)
3674  // (Thus no need to release signatures, sign contract, save contract, etc.)
3676 
3677  // END DATE --------------------------------
3678  // First call the parent's version (which this overrides) so it has
3679  // a chance to check its stuff.
3680  // Currently it calls IsExpired().
3681  //
3682  if (!ot_super::ProcessCron()) {
3683  otLog3 << "Cron job has expired.\n";
3684  return false; // It's expired or flagged for removal--remove it from
3685  // Cron.
3686  }
3687 
3688  // START DATE --------------------------------
3689  // Okay, so it's not expired. But might not have reached START DATE yet...
3690  if (!VerifyCurrentDate())
3691  return true; // The Payment Plan is not yet valid, so we return. BUT, we
3692  // also
3693  // return TRUE, so it will STAY on Cron until it BECOMES valid.
3694 
3695  // Make sure there are transaction numbers available in Cron.
3696  // (Can't do anything without those....)
3697  //
3698  if (GetCron()->GetTransactionCount() < 1) {
3699  otOut << "Failed to process smart contract: Cron is out of transaction "
3700  "numbers!\n";
3701  return true;
3702  }
3703 
3704  // Make sure, if the script set a timer, that we don't process Cron until
3705  // that timer
3706  // is reached. (If the timer's not set, then we go ahead and process every
3707  // time.)
3708  //
3709  const time64_t& tNextProcessDate = GetNextProcessDate();
3710 
3711  if (tNextProcessDate > OT_TIME_ZERO) // IF there is a timer set (as to when
3712  // the next "onProcess" should
3713  // occur)...
3714  {
3715  if (OTTimeGetCurrentTime() <=
3716  tNextProcessDate) // AND if the current time has NOT YET reached
3717  // that date (the date in the timer)...
3718  {
3719  // ...Then RETURN (since the timer hasn't popped yet)
3720  // But return TRUE, so that this cron item stays active for now.
3721  //
3722  return true;
3723  }
3724  else // else it HAS now reached the official timer date...
3725  {
3726  SetNextProcessDate(OT_TIME_ZERO); // Therefore timer has triggered,
3727  // so we will continue processing.
3728  } // We also reset timer to 0 again since it has now "binged".
3729  } // Continuing on....
3730 
3731  // Execute the scripts (clauses) that have registered for this hook.
3732 
3733  const std::string str_HookName(SMARTCONTRACT_HOOK_ON_PROCESS);
3734  mapOfClauses theMatchingClauses;
3735 
3736  if (GetHooks(str_HookName, theMatchingClauses)) {
3737  otOut << "Cron: Processing smart contract clauses for hook: "
3738  << SMARTCONTRACT_HOOK_ON_PROCESS << " \n";
3739 
3741  theMatchingClauses); // <============================================
3742  }
3743 
3744  if (IsFlaggedForRemoval()) {
3745  otLog3 << "OTSmartContract::ProcessCron: Removing smart contract from "
3746  "cron processing...\n";
3747  return false; // false means "remove this cron item from cron"
3748  }
3749 
3750  return true;
3751 }
int64_t OTTimeGetTimeInterval(time64_t lhs, time64_t rhs)
Definition: Common.hpp:234
bool IsFlaggedForRemoval() const
Definition: OTCronItem.hpp:238
#define SMARTCONTRACT_HOOK_ON_PROCESS
OTLOG_IMPORT OTLogStream otOut
OTLOG_IMPORT OTLogStream otLog3
std::map< std::string, OTClause * > mapOfClauses
Definition: OTBylaw.hpp:145
int64_t time64_t
Definition: Common.hpp:209
EXPORT bool VerifyCurrentDate()
const time64_t & GetNextProcessDate() const
void SetNextProcessDate(const time64_t &tNEXT_DATE)
time64_t OTTimeGetCurrentTime()
Definition: Common.hpp:211
virtual bool ProcessCron()
Definition: OTCronItem.cpp:769
#define OT_ASSERT(x)
Definition: Assert.hpp:150
const int64_t & GetProcessInterval() const
Definition: OTCronItem.hpp:288
EXPORT void ExecuteClauses(mapOfClauses &theClauses, OTString *pParam=nullptr)
const time64_t & GetLastProcessDate() const
Definition: OTCronItem.hpp:279
bool GetHooks(std::string str_HookName, mapOfClauses &theResults)
#define OT_TIME_ZERO
Definition: Common.hpp:180
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
void SetLastProcessDate(const time64_t &THE_DATE)
Definition: OTCronItem.hpp:275
int32_t opentxs::OTSmartContract::ProcessXMLNode ( irr::io::IrrXMLReader *&  xml)
virtual

Reimplemented from opentxs::OTCronItem.

Definition at line 5617 of file OTSmartContract.cpp.

5618 {
5619  const OTString strNodeName(xml->getNodeName());
5620 
5621  int32_t nReturnVal = 0;
5622 
5623  // Here we call the parent class first.
5624  // If the node is found there, or there is some error,
5625  // then we just return either way. But if it comes back
5626  // as '0', then nothing happened, and we'll continue executing.
5627  //
5628  // OTSmartContract::ProcessXMLNode calls OTCronItem::ProcessXMLNode,
5629  // which calls OTScriptable... Meaning:
5630  //
5631  // NO NEED to explicitly load OTScriptable stuff here!
5632  //
5633  nReturnVal = ot_super::ProcessXMLNode(xml);
5634 
5635  if (0 != (nReturnVal)) {
5636  return nReturnVal;
5637  }
5638 
5639  if (strNodeName.Compare("smartContract")) {
5640  m_strVersion = xml->getAttributeValue("version");
5641 
5642  const OTString strServerID(xml->getAttributeValue("serverID"));
5643  const OTString strActivatorUserID(
5644  xml->getAttributeValue("activatorUserID"));
5645  const OTString strActivatorAcctID(
5646  xml->getAttributeValue("activatorAcctID"));
5647  const OTString strCanceled(xml->getAttributeValue("canceled"));
5648  const OTString strCancelerUserID(
5649  xml->getAttributeValue("cancelerUserID"));
5650 
5651  if (strServerID.Exists()) {
5652  const OTIdentifier SERVER_ID(strServerID);
5653  SetServerID(SERVER_ID);
5654  }
5655  if (strActivatorUserID.Exists()) {
5656  const OTIdentifier ACTIVATOR_USER_ID(strActivatorUserID);
5657  SetSenderUserID(ACTIVATOR_USER_ID);
5658  }
5659  if (strActivatorAcctID.Exists()) {
5660  const OTIdentifier ACTIVATOR_ACCT_ID(strActivatorAcctID);
5661  SetSenderAcctID(ACTIVATOR_ACCT_ID);
5662  }
5663 
5664  if (strCanceled.Exists() && strCanceled.Compare("true")) {
5665  m_bCanceled = true;
5666 
5667  if (strCancelerUserID.Exists())
5668  m_pCancelerNymID->SetString(strCancelerUserID);
5669  // else log
5670  }
5671  else {
5672  m_bCanceled = false;
5674  }
5675 
5676  const OTString strTransNum = xml->getAttributeValue("transactionNum");
5677 
5678  SetTransactionNum(strTransNum.Exists() ? atol(strTransNum.Get()) : 0);
5679 
5680  const OTString str_valid_from = xml->getAttributeValue("validFrom");
5681  const OTString str_valid_to = xml->getAttributeValue("validTo");
5682  const OTString str_creation = xml->getAttributeValue("creationDate");
5683  const OTString str_next_process =
5684  xml->getAttributeValue("nextProcessDate");
5685 
5686  int64_t tValidFrom = str_valid_from.ToLong();
5687  int64_t tValidTo = str_valid_to.ToLong();
5688  int64_t tCreation = str_creation.ToLong();
5689  int64_t tNextProcess = str_next_process.ToLong();
5690 
5695 
5696  // These are stored for RECEIPTS, so if there is an inbox receipt with
5697  // an amount,
5698  // we will know who was sending and receiving. If sender or receiver is
5699  // blank, that
5700  // means the source/destination was a STASH instead of an account. FYI.
5701  //
5702  m_strLastSenderUser = xml->getAttributeValue(
5703  "lastSenderUserID"); // Last User ID of a party who SENT money.
5704  m_strLastSenderAcct = xml->getAttributeValue(
5705  "lastSenderAcctID"); // Last Acct ID of a party who SENT money.
5706  m_strLastRecipientUser =
5707  xml->getAttributeValue("lastRecipientUserID"); // Last User ID of a
5708  // party who RECEIVED
5709  // money.
5710  m_strLastRecipientAcct =
5711  xml->getAttributeValue("lastRecipientAcctID"); // Last Acct ID of a
5712  // party who RECEIVED
5713  // money.
5714 
5715  otWarn << "\n\n Smartcontract. Transaction Number: "
5716  << m_lTransactionNum << "\n";
5717 
5718  otInfo << " Creation Date: " << tCreation
5719  << " Valid From: " << tValidFrom << "\n Valid To: " << tValidTo
5720  << "\n"
5721  " ServerID: " << strServerID
5722  << "\n"
5723  " activatorUserID: " << strActivatorUserID << "\n ";
5724 
5725  nReturnVal = 1;
5726  }
5727  else if (strNodeName.Compare("accountList")) // the stash reserve account
5728  // IDs.
5729  {
5730  const OTString strAcctType = xml->getAttributeValue("type");
5731  const OTString strAcctCount = xml->getAttributeValue("count");
5732 
5733  if ((-1) ==
5734  m_StashAccts.ReadFromXMLNode(xml, strAcctType, strAcctCount)) {
5735  otErr << "OTSmartContract::ProcessXMLNode: Error loading stash "
5736  "accountList.\n";
5737  nReturnVal = (-1);
5738  }
5739  else
5740  nReturnVal = 1;
5741  }
5742  else if (strNodeName.Compare("stash")) // the actual stashes.
5743  {
5744  const OTString strStashName = xml->getAttributeValue("name");
5745  const OTString strItemCount = xml->getAttributeValue("count");
5746 
5747  const std::string str_stash_name = strStashName.Get();
5748  OTStash* pStash = new OTStash(str_stash_name);
5749  OT_ASSERT(nullptr != pStash);
5750 
5751  if ((-1) == pStash->ReadFromXMLNode(xml, strStashName, strItemCount)) {
5752  otErr << "OTSmartContract::ProcessXMLNode: Error loading stash: "
5753  << strStashName << "\n";
5754  delete pStash;
5755  nReturnVal = (-1);
5756  }
5757  else {
5758  // Success
5759  //
5760  m_mapStashes.insert(
5761  std::pair<std::string, OTStash*>(strStashName.Get(), pStash));
5762 
5763  nReturnVal = 1;
5764  }
5765  }
5766 
5767  return nReturnVal;
5768 }
void SetValidFrom(time64_t TIME_FROM)
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
void SetValidTo(time64_t TIME_TO)
time64_t OTTimeGetTimeFromSeconds(int64_t seconds)
Definition: Common.hpp:215
EXPORT int32_t ReadFromXMLNode(irr::io::IrrXMLReader *&xml, const OTString &acctType, const OTString &acctCount)
void SetCreationDate(const time64_t &CREATION_DATE)
Definition: OTCronItem.hpp:264
EXPORT void SetString(const char *szString)
void SetNextProcessDate(const time64_t &tNEXT_DATE)
void SetTransactionNum(int64_t lTransactionNum)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTLOG_IMPORT OTLogStream otInfo
void SetSenderAcctID(const OTIdentifier &ACCT_ID)
OTLOG_IMPORT OTLogStream otWarn
void SetServerID(const OTIdentifier &SERVER_ID)
OTLOG_IMPORT OTLogStream otErr
OTIdentifier * m_pCancelerNymID
Definition: OTCronItem.hpp:177
void SetSenderUserID(const OTIdentifier &USER_ID)
virtual EXPORT void Release()
Definition: OTData.cpp:257
void opentxs::OTSmartContract::RegisterOTNativeCallsWithScript ( OTScript theScript)
virtual

Reimplemented from opentxs::OTScriptable.

Definition at line 859 of file OTSmartContract.cpp.

860 {
861  // CALL THE PARENT
863 
864 #ifdef OT_USE_SCRIPT_CHAI
865  using namespace chaiscript;
866 
867  OTScriptChai* pScript = dynamic_cast<OTScriptChai*>(&theScript);
868 
869  if (nullptr != pScript) {
870  OT_ASSERT(nullptr != pScript->chai)
871 
872  // OT NATIVE FUNCTIONS
873  // (These functions can be called from INSIDE the scripted clauses.)
874  // //
875  // Parameters must match as described below. Return value will be as
876  // described below.
877  //
878  // pScript->chai->add(base_class<OTScriptable,
879  // OTSmartContract>());
880 
881  pScript->chai->add(
883  "move_funds");
884 
885  pScript->chai->add(fun(&OTSmartContract::StashAcctFunds, this),
886  "stash_funds");
887  pScript->chai->add(fun(&OTSmartContract::UnstashAcctFunds, this),
888  "unstash_funds");
889  pScript->chai->add(fun(&OTSmartContract::GetAcctBalance, this),
890  "get_acct_balance");
891  pScript->chai->add(fun(&OTSmartContract::GetAssetTypeIDofAcct, this),
892  "get_acct_asset_type_id");
893  pScript->chai->add(fun(&OTSmartContract::GetStashBalance, this),
894  "get_stash_balance");
895  pScript->chai->add(fun(&OTSmartContract::SendNoticeToParty, this),
896  "send_notice");
897  pScript->chai->add(fun(&OTSmartContract::SendANoticeToAllParties, this),
898  "send_notice_to_parties");
899  pScript->chai->add(fun(&OTSmartContract::SetRemainingTimer, this),
900  "set_seconds_until_timer");
901  pScript->chai->add(fun(&OTSmartContract::GetRemainingTimer, this),
902  "get_remaining_timer");
903 
904  pScript->chai->add(fun(&OTSmartContract::DeactivateSmartContract, this),
905  "deactivate_contract");
906 
907  // CALLBACKS
908  // (Called by OT at key moments) todo security: What if these are
909  // recursive? Need to lock down, put the smack down, on these smart
910  // contracts.
911  //
912  // FYI: pScript->chai->add(fun(&(OTScriptable::CanExecuteClause),
913  // (*this)), "party_may_execute_clause"); // From OTScriptable (FYI)
914  // param_party_name and param_clause_name will be available inside
915  // script. Script must return bool.
916  // FYI: #define SCRIPTABLE_CALLBACK_PARTY_MAY_EXECUTE
917  // "callback_party_may_execute_clause" <=== THE CALLBACK WITH THIS
918  // NAME must be connected to a script clause, and then the clause will
919  // trigger when the callback is needed.
920 
921  pScript->chai->add(fun(&OTSmartContract::CanCancelContract, this),
922  "party_may_cancel_contract"); // param_party_name
923  // will be available
924  // inside script.
925  // Script must return
926  // bool.
927  // FYI: #define SMARTCONTRACT_CALLBACK_PARTY_MAY_CANCEL
928  // "callback_party_may_cancel_contract" <=== THE CALLBACK WITH THIS
929  // NAME must be connected to a script clause, and then the clause will
930  // trigger when the callback is needed.
931 
932  // Callback USAGE: Your clause, in your smart contract, may have
933  // whatever name you want. (Within limits.)
934  // There must be a callback entry in the smart
935  // contract, linking your clause the the appropriate callback.
936  // The CALLBACK ENTRY uses the names
937  // "callback_party_may_execute_clause" and
938  // "callback_party_may_cancel_contract".
939  // If you want to call these from INSIDE YOUR SCRIPT,
940  // then use the names "party_may_execute_clause" and
941  // "party_may_cancel_contract".
942 
943  // HOOKS:
944  //
945  // Hooks are not native calls needing to be registered with the script.
946  // (Like the above functions are.)
947  // Rather, hooks are SCRIPT CLAUSES, that you have a CHOICE to provide
948  // inside your SMART CONTRACT.
949  // *IF* you have provided those clauses, then OT *WILL* call them, at
950  // the appropriate times. (When
951  // specific events occur.) Specifically, Hook entries must be in your
952  // smartcontract, linking the below
953  // standard hooks to your clauses.
954  //
955  // FYI: #define SMARTCONTRACT_HOOK_ON_PROCESS "cron_process"
956  // // Called regularly in OTSmartContract::ProcessCron() based on
957  // SMART_CONTRACT_PROCESS_INTERVAL.
958  // FYI: #define SMARTCONTRACT_HOOK_ON_ACTIVATE "cron_activate"
959  // // Done. This is called when the contract is first activated.
960  }
961  else
962 #endif // OT_USE_SCRIPT_CHAI
963  {
964  otErr << "OTSmartContract::RegisterOTNativeCallsWithScript: Failed "
965  "dynamic casting OTScript to OTScriptChai \n";
966  }
967 
968 } // void function
std::string GetRemainingTimer() const
std::string GetAssetTypeIDofAcct(std::string from_acct_name)
bool(OTSmartContract::* OT_SM_RetBool_ThrStr)(std::string from_acct_name, std::string to_acct_name, std::string str_Amount)
virtual EXPORT void RegisterOTNativeCallsWithScript(OTScript &theScript)
bool CanCancelContract(std::string str_party_name)
std::string GetStashBalance(std::string stash_name, std::string asset_type_id)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTLOG_IMPORT OTLogStream otErr
void SetRemainingTimer(std::string str_seconds_from_now)
bool SendNoticeToParty(std::string party_name)
std::string GetAcctBalance(std::string from_acct_name)
bool UnstashAcctFunds(std::string to_acct_name, std::string from_stash_name, std::string str_Amount)
bool StashAcctFunds(std::string from_acct_name, std::string to_stash_name, std::string str_Amount)
bool MoveAcctFundsStr(std::string from_acct_name, std::string to_acct_name, std::string str_Amount)
void opentxs::OTSmartContract::Release ( void  )
virtual

Reimplemented from opentxs::OTCronItem.

Definition at line 5391 of file OTSmartContract.cpp.

5392 {
5394 
5395  ot_super::Release(); // since I've overridden the base class, I call it
5396  // now...
5397 
5398  // Then I call this to re-initialize everything
5400 }
virtual void Release()
void opentxs::OTSmartContract::Release_SmartContract ( )

Definition at line 5385 of file OTSmartContract.cpp.

5386 {
5387 
5388  ReleaseStashes();
5389 }
void opentxs::OTSmartContract::ReleaseLastSenderRecipientIDs ( )
protected

Definition at line 5571 of file OTSmartContract.cpp.

5572 {
5573  m_strLastSenderUser.Release(); // This is the last User ID of a party who
5574  // SENT money.
5575  m_strLastSenderAcct.Release(); // This is the last Acct ID of a party who
5576  // SENT money.
5577  m_strLastRecipientUser.Release(); // This is the last User ID of a party who
5578  // RECEIVED money.
5579  m_strLastRecipientAcct.Release(); // This is the last Acct ID of a party who
5580  // RECEIVED money.
5581 }
virtual EXPORT void Release()
Definition: OTString.cpp:765
void opentxs::OTSmartContract::ReleaseStashes ( )

Definition at line 5369 of file OTSmartContract.cpp.

5370 {
5371 
5372  while (!m_mapStashes.empty()) {
5373  OTStash* pStash = m_mapStashes.begin()->second;
5374  OT_ASSERT(nullptr != pStash);
5375 
5376  delete pStash;
5377  pStash = nullptr;
5378 
5379  m_mapStashes.erase(m_mapStashes.begin());
5380  }
5381 
5382  m_StashAccts.Release();
5383 }
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT void Release()
bool opentxs::OTSmartContract::SaveContractWallet ( std::ofstream &  ofs) const
virtual

Reimplemented from opentxs::OTInstrument.

Definition at line 5770 of file OTSmartContract.cpp.

5771 {
5772  return true;
5773 }
bool opentxs::OTSmartContract::SendANoticeToAllParties ( )

Definition at line 1659 of file OTSmartContract.cpp.

1660 {
1661  OTCron* pCron = GetCron();
1662  OT_ASSERT(nullptr != pCron);
1663 
1664  OTPseudonym* pServerNym = pCron->GetServerNym();
1665  OT_ASSERT(nullptr != pServerNym);
1666 
1667  // Below this point, these are all good:
1668  //
1669  // pServerNym, pCron.
1670  //
1671 
1672  const int64_t lNewTransactionNumber = pCron->GetNextTransactionNumber();
1673  bool bDroppedNotice = false;
1674 
1675  // OT_ASSERT(lNewTransactionNumber > 0); // this can be my reminder.
1676  if (0 == lNewTransactionNumber) {
1677  otErr << __FUNCTION__ << ": ** ERROR: Notice not sent to parties, "
1678  "since no transaction numbers were "
1679  "available!\n";
1680  }
1681  else {
1683  SignContract(*pServerNym);
1684  SaveContract();
1685 
1686  const OTString strReference(*this);
1687  bDroppedNotice = SendNoticeToAllParties(
1688  true, // bSuccessMsg=true
1689  *pServerNym, GetServerID(), lNewTransactionNumber,
1690  // GetTransactionNum(), // each party has its own opening number.
1691  strReference); // pstrNote and pstrAttachment aren't used in this
1692  // case.
1693 
1694  otOut << __FUNCTION__
1695  << ": Dropping notifications into all parties' nymboxes: "
1696  << (bDroppedNotice ? "Success" : "Failure") << "\n";
1697  }
1698 
1699  return bDroppedNotice;
1700 }
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 SaveContract()
OTLOG_IMPORT OTLogStream otOut
EXPORT void ReleaseSignatures()
Definition: OTContract.cpp:989
const OTIdentifier & GetServerID() const
#define OT_ASSERT(x)
Definition: Assert.hpp:150
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
Definition: OTContract.cpp:484
OTLOG_IMPORT OTLogStream otErr
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
bool opentxs::OTSmartContract::SendNoticeToParty ( std::string  party_name)

Definition at line 1702 of file OTSmartContract.cpp.

1703 {
1704  OTCron* pCron = GetCron();
1705  OT_ASSERT(nullptr != pCron);
1706 
1707  OTPseudonym* pServerNym = pCron->GetServerNym();
1708  OT_ASSERT(nullptr != pServerNym);
1709 
1710  // Below this point, these are all good:
1711  //
1712  // pServerNym, pCron.
1713 
1714  OTParty* pParty = GetParty(party_name);
1715 
1716  if (nullptr == pParty) {
1717  otOut << __FUNCTION__ << ": Unable to find this party: " << party_name
1718  << "\n";
1719  return false;
1720  }
1721  // Below this point, pParty is good.
1722 
1723  // ...This WILL check to see if pParty has its Opening number verified as
1724  // issued.
1725  // (If the opening number is > 0 then VerifyPartyAuthorization() is smart
1726  // enough to verify it.)
1727  //
1728  // To KNOW that a party has the right to even ASK the script to cancel a
1729  // contract, MEANS that
1730  // (1) The party is listed as a party on the contract. (2) The party's copy
1731  // of that contract
1732  // is signed by the authorizing agent for that party. and (3) The opening
1733  // transaction number for
1734  // that party is verified as issued for authorizing agent. (2 and 3 are both
1735  // performed at the same
1736  // time, in VerifyPartyAuthorization(), since the agent may need to be
1737  // loaded in order to verify
1738  // them.) 1 is already done by this point, as it's performed above.
1739  //
1740  // Done: notice this code appears in CanCancelContract() (this function) as
1741  // well as
1742  // OTScriptable::CanExecuteClause.
1743  // Therefore I can see that THIS VERIFICATION CODE WILL GET CALLED EVERY
1744  // SINGLE TIME THE SCRIPT
1745  // CALLS ANY CLAUSE OR OT NATIVE FUNCTION. Since technically this only
1746  // needs to be verified before the
1747  // first call, and not for EVERY call during any of a script's runs, I
1748  // should probably move this verification
1749  // higher, such as each time the OTCronItem triggers, plus each time a party
1750  // triggers a clause directly
1751  // through the API (server message). As long as those are covered, I will be
1752  // able to remove it from here
1753  // which should be a significant improvement for performance.
1754  // It will be at the bottom of those same functions that
1755  // "ClearTemporaryPointers()" should finally be called.
1756  //
1757  // Also todo: Need to implement MOVE CONSTRUCTORS and MOVE COPY
1758  // CONSTRUCTORS all over the place,
1759  // once I'm sure C++0x build environments are available for all of the
1760  // various OT platforms. That should
1761  // be another great performance boost!
1762  //
1763  // FINAL DECISION: See longer comment in
1764  // OTSmartContract::StashAcctFunds(). This is redundant and was
1765  // removed. It expects itself to be executed only upon the initial
1766  // activation of a smart contract, and
1767  // not again after. (For example, it disallows stashes, which cannot exist
1768  // prior to activation.)
1769  //
1770  bool bDroppedNotice = false;
1771  const int64_t lNewTransactionNumber = pCron->GetNextTransactionNumber();
1772 
1773  // OT_ASSERT(lNewTransactionNumber > 0); // this can be my reminder.
1774  if (0 == lNewTransactionNumber) {
1775  otErr << __FUNCTION__ << ": ** ERROR: Notice not sent to party, since "
1776  "no transaction numbers were available!\n";
1777  }
1778  else {
1780  SignContract(*pServerNym);
1781  SaveContract();
1782 
1783  const OTString strReference(*this);
1784 
1785  bDroppedNotice = pParty->SendNoticeToParty(
1786  true, // bSuccessMsg=true. True in general means "success" and false
1787  // means "failure."
1788  *pServerNym, GetServerID(), lNewTransactionNumber,
1789  // GetTransactionNum(), // each party has its own opening trans #
1790  // and supplies it internally.
1791  strReference);
1792 
1793  otOut << __FUNCTION__ << ": "
1794  << (bDroppedNotice ? "Success" : "Failure")
1795  << " dropping notification into party's nymbox: "
1796  << pParty->GetPartyName() << "\n";
1797  }
1798 
1799  return bDroppedNotice;
1800 }
EXPORT bool SaveContract()
OTLOG_IMPORT OTLogStream otOut
EXPORT void ReleaseSignatures()
Definition: OTContract.cpp:989
const OTIdentifier & GetServerID() const
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT OTParty * GetParty(std::string str_party_name) const
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
Definition: OTContract.cpp:484
OTLOG_IMPORT OTLogStream otErr
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
void opentxs::OTSmartContract::SetDisplayLabel ( const std::string *  pstrLabel = nullptr)
virtual

Reimplemented from opentxs::OTScriptable.

Definition at line 3754 of file OTSmartContract.cpp.

3755 {
3756  m_strLabel.Format("smartcontract trans# %lld, clause: %s",
3758  (nullptr != pstrLabel) ? pstrLabel->c_str() : "");
3759 }
int64_t GetTransactionNum() const
EXPORT void Format(const char *fmt,...)
Definition: OTString.cpp:1319
void opentxs::OTSmartContract::SetNextProcessDate ( const time64_t tNEXT_DATE)
inlineprotected

Definition at line 228 of file OTSmartContract.hpp.

229  {
230  m_tNextProcessDate = tNEXT_DATE;
231  }
void opentxs::OTSmartContract::SetRemainingTimer ( std::string  str_seconds_from_now)

Definition at line 1102 of file OTSmartContract.cpp.

1105 {
1106  if (str_seconds_from_now.size() <= 0) // string length...
1107  {
1108  otOut << "OTSmartContract::" << __FUNCTION__
1109  << ": blank input (str_seconds_from_now).\n";
1110  }
1111  else {
1112  const int64_t tPlus = OTString::StringToLong(str_seconds_from_now);
1113 
1114  if (tPlus > 0)
1117  else
1118  SetNextProcessDate(OT_TIME_ZERO); // This way, you can deactivate
1119  // the timer, by setting the next
1120  // process date to 0.
1121  }
1122 }
static EXPORT int64_t StringToLong(const std::string &number)
Definition: OTString.cpp:677
time64_t OTTimeAddTimeInterval(time64_t lhs, int64_t rhs)
Definition: Common.hpp:238
OTLOG_IMPORT OTLogStream otOut
void SetNextProcessDate(const time64_t &tNEXT_DATE)
time64_t OTTimeGetCurrentTime()
Definition: Common.hpp:211
#define OT_TIME_ZERO
Definition: Common.hpp:180
bool opentxs::OTSmartContract::SetServerIDIfEmpty ( const OTIdentifier theID)

Definition at line 1015 of file OTSmartContract.cpp.

1016 {
1017  if (GetServerID().IsEmpty()) {
1018  SetServerID(theID);
1019  return true;
1020  }
1021  return false;
1022 }
const OTIdentifier & GetServerID() const
void SetServerID(const OTIdentifier &SERVER_ID)
bool opentxs::OTSmartContract::StashAcctFunds ( std::string  from_acct_name,
std::string  to_stash_name,
std::string  str_Amount 
)

Definition at line 1819 of file OTSmartContract.cpp.

1822 {
1823  OTCron* pCron = GetCron();
1824  OT_ASSERT(nullptr != pCron);
1825 
1826  OTPseudonym* pServerNym = pCron->GetServerNym();
1827  OT_ASSERT(nullptr != pServerNym);
1828 
1829  // Below this point, these are all good:
1830  //
1831  // pServerNym, pCron.
1832 
1833  if (str_Amount.size() < 1) {
1834  otOut << "OTSmartContract::StashAcctFunds: Error: empty amount.\n";
1835  return false;
1836  }
1837 
1838  const int64_t lAmount = atol(str_Amount.c_str());
1839 
1840  if (lAmount <= 0) {
1841  otOut << "OTSmartContract::StashAcctFunds: Error: lAmount cannot be 0 "
1842  "or <0. (Value passed in was " << lAmount << ".)\n";
1843  return false;
1844  }
1845 
1846  if (from_acct_name.size() <= 0) {
1847  otErr << "OTSmartContract::StashAcctFunds: error: from_acct_name is "
1848  "non-existent.\n";
1849  return false;
1850  }
1851  if (to_stash_name.size() <= 0) {
1852  otErr << "OTSmartContract::StashAcctFunds: error: to_stash_name is "
1853  "non-existent.\n";
1854  return false;
1855  }
1856 
1857  // Below this point, these are all good:
1858  //
1859  // from_acct_name,
1860  // to_stash_name,
1861  // pServerNym, pCron.
1862  //
1863 
1864  OTPartyAccount* pFromAcct = GetPartyAccount(from_acct_name);
1865  OTStash* pStash = GetStash(to_stash_name); // This ALWAYS succeeds.
1866  // (It will OT_ASSERT() if
1867  // failure.)
1868 
1869  if (nullptr == pFromAcct) {
1870  otOut << "OTSmartContract::StashAcctFunds: error: from_acct ("
1871  << from_acct_name << ") not found on any party.\n";
1872  return false;
1873  }
1874 
1875  // Below this point, these are all good:
1876  //
1877  // pFromAcct, from_acct_name,
1878  // pStash, to_stash_name,
1879  // pServerNym, pCron.
1880  //
1881 
1882  OTAgent* pFromAgent =
1883  pFromAcct->GetAuthorizedAgent(); // This searches the account's party
1884  // for the account's authorized agent.
1885  // (That way it's impossible to get an agent for any other party.)
1886 
1887  if (nullptr == pFromAgent) {
1888  otOut << "OTSmartContract::StashAcctFunds: error: authorized agent ("
1889  << pFromAcct->GetAgentName() << ") not found for from_acct ("
1890  << from_acct_name << ") on acct's party.\n";
1891  return false;
1892  }
1893 
1894  if (!pFromAgent->IsAnIndividual()) {
1895  otOut << "OTSmartContract::StashAcctFunds: error: authorized agent ("
1896  << pFromAcct->GetAgentName() << ") for from_acct ("
1897  << from_acct_name << ") is not an active agent.\n";
1898  return false;
1899  }
1900  //
1901  // Below this point, these are all good:
1902  //
1903  // pFromAcct, from_acct_name, pFromAgent,
1904  // pStash, to_stash_name,
1905  // pServerNym, pCron.
1906 
1907  OTParty* pFromParty = pFromAgent->GetParty();
1908 
1909  if (nullptr == pFromParty) {
1910  otErr
1911  << "OTSmartContract::StashAcctFunds: error: Party pointer nullptr "
1912  "on authorized agent (" << pFromAcct->GetAgentName()
1913  << ") for from_acct (" << from_acct_name << ").\n";
1914  return false;
1915  }
1916  //
1917  // Below this point, these are all good:
1918  //
1919  // pFromAcct, from_acct_name, pFromAgent, pFromParty,
1920  // pStash, to_stash_name,
1921  // pServerNym, pCron.
1922 
1923  // DONE: Problem: I can see that THIS VERIFICATION CODE WILL GET CALLED
1924  // EVERY SINGLE TIME THE SCRIPT
1925  // CALLS MOVE FUNDS. Maybe that's good, but since technically this only
1926  // needs to be verified before the
1927  // first call, and not for EVERY call during any of a script's runs, I
1928  // should probably move this verification
1929  // higher, such as each time the OTCronItem triggers, plus each time a party
1930  // triggers a clause directly
1931  // through the API (server message). As long as those are covered, I will be
1932  // able to remove it from here
1933  // which should be a significant improvement for performance.
1934  // It will be at the bottom of those same functions that
1935  // "ClearTemporaryPointers()" should finally be called.
1936  //
1937  //
1938  // const OTString strServerID(GetServerID());
1939 
1940  // mapOfNyms map_Nyms_Already_Loaded;
1941  // RetrieveNymPointers(map_Nyms_Already_Loaded);
1942 
1943  // FINAL DECISION: Since this verification is already done for the smart
1944  // contract to have been activated onto
1945  // cron in the first place, it is redundant to have it here.
1946  // Furthermore, what if a single clause calls stash_funds 30 times in a
1947  // loop? Does that mean we need to verify
1948  // all the parties and accounts 30 times, every single time we call that
1949  // clause? CLearly such is redundant, and
1950  // would be targeted in any optimization effort.
1951  // Furthermore, since actually running the software, it's become apparent
1952  // that it is no longer even appropriate
1953  // to Verify anymore, since stashes can exist after a smartcontract has been
1954  // activated, while this function
1955  // specifically verifies that no stashes exist, since it presumes that it is
1956  // only called during the initial
1957  // activation of the cron item, when no stashes SHOULD exist (since they are
1958  // only created after activation, by
1959  // the server itself, at the behest of the scripts.)
1960 
1961  // A party might have many agents who are only voting groups, and cannot
1962  // actually sign for things
1963  // the way that nyms can. But at least ONE of those agents IS a Nym --
1964  // because there must have been
1965  // an authorizing agent who initially signed to accept the agreement, and
1966  // who fronted the opening
1967  // transaction number that activated it.
1968  //
1969  // Similarly, the authorized agent for any given party's account (each
1970  // account has its own authorized
1971  // agent) MUST be an active agent (an active agent is one with a
1972  // Nym--whether that Nym is representing
1973  // himself as the party, or whether representing some entity as an employee
1974  // in a role). Why MUST the
1975  // authorized agent be an active agent? Because when funds are moved, that
1976  // Nym must be loaded since
1977  // the account must show that Nym as a legal owner/agent. The MoveFunds will
1978  // cause a paymentReceipt to
1979  // drop into the Inbox for the relevant asset accounts, and that
1980  // paymentReceipt can ONLY be accepted
1981  // by that same Nym, who must use a transaction # that he signed for
1982  // previously and received through
1983  // his nymbox. There is actually no justification at all to take funds from
1984  // that account, since the
1985  // new balance has not yet been signed, UNLESS THE PAYMENTRECEIPT CONTAINS A
1986  // VALID, SIGNED AUTHORIZATION
1987  // FROM THE ACCOUNT HOLDER. *That* is why the authorizing agent must either
1988  // be the Party's Owner himself
1989  // (representing himself as an agent, which most will do) in which case he
1990  // will appear as the valid
1991  // owner of the account, OR he MUST be a Nym working in a Valid Role for an
1992  // Entity, where said Entity is
1993  // the valid owner on the account in question. Either OT, it will be
1994  // possible in OT for him to sign for
1995  // the paymentReceipts when they come in, and impossible for him to escape
1996  // liability for them.
1997  // (That's the idea anyway.)
1998  //
1999  // Since we know that the Authorized Agent for an account must be an ACTIVE
2000  // agent (one way or the other)
2001  // then we can error out here if he's not. We can then pass in his Nym ID.
2002  //
2003 
2004  OTIdentifier theFromAgentID;
2005  const bool bFromAgentID = pFromAgent->GetSignerID(theFromAgentID);
2006 
2007  if (!bFromAgentID) {
2008  otErr << "OTSmartContract::StashAcctFunds: Failed to find FromAgent's "
2009  "Signer ID: " << pFromAgent->GetName() << " \n";
2010  return false;
2011  }
2012 
2013  if (!pFromAcct->GetAcctID().Exists()) {
2014  otErr << "OTSmartContract::StashAcctFunds: Error: FromAcct has empty "
2015  "AcctID: " << from_acct_name << " \n";
2016  return false;
2017  }
2018 
2019  const OTIdentifier theFromAcctID(pFromAcct->GetAcctID());
2020  //
2021  // BELOW THIS POINT, theFromAcctID and theFromAgentID available.
2022 
2023  // WE SET THESE HERE SO THE RECEIPT SHOWS, SUCCESS OR FAIL,
2024  // WHO THE INTENDED SENDER / RECIPIENT ARE FOR THAT RECEIPT.
2025  //
2027 
2028  theFromAgentID.GetString(m_strLastSenderUser); // This is the last User ID
2029  // of a party who SENT money.
2030  theFromAcctID.GetString(m_strLastSenderAcct); // This is the last Acct ID of
2031  // a party who SENT money.
2032  // theToAgentID.GetString(m_strLastRecipientUser); // This is the last
2033  // User ID of a party who RECEIVED money.
2034  // theToAcctID.GetString(m_strLastRecipientAcct); // This is the last
2035  // Acct ID of a party who RECEIVED money.
2036  // Above: the ToAgent and ToAcct are commented out,
2037  // since the funds are going into a stash.
2038 
2039  mapOfNyms map_Nyms_Already_Loaded;
2040  RetrieveNymPointers(map_Nyms_Already_Loaded);
2041 
2042  bool bMoved = StashFunds(map_Nyms_Already_Loaded, lAmount, theFromAcctID,
2043  theFromAgentID, *pStash);
2044  if (!bMoved) {
2045  otOut << "OTSmartContract::StashAcctFunds: Failed in final call. "
2046  "Values: from_acct: " << from_acct_name
2047  << ", to_stash: " << to_stash_name << ", lAmount: " << lAmount
2048  << ". \n";
2049  return false;
2050  }
2051 
2052  return true;
2053 }
EXPORT bool StashFunds(const mapOfNyms &map_NymsAlreadyLoaded, const int64_t &lAmount, const OTIdentifier &PARTY_ACCT_ID, const OTIdentifier &PARTY_USER_ID, OTStash &theStash)
OTStash * GetStash(std::string str_stash_name)
OTLOG_IMPORT OTLogStream otOut
std::map< std::string, OTPseudonym * > mapOfNyms
Definition: OTWallet.hpp:161
#define OT_ASSERT(x)
Definition: Assert.hpp:150
void RetrieveNymPointers(mapOfNyms &map_Nyms_Already_Loaded)
OTLOG_IMPORT OTLogStream otErr
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
OTPartyAccount * GetPartyAccount(std::string str_acct_name) const
bool opentxs::OTSmartContract::StashFunds ( const mapOfNyms map_NymsAlreadyLoaded,
const int64_t &  lAmount,
const OTIdentifier PARTY_ACCT_ID,
const OTIdentifier PARTY_USER_ID,
OTStash theStash 
)

Definition at line 2291 of file OTSmartContract.cpp.

2299 {
2300  OTCron* pCron = GetCron();
2301  OT_ASSERT(nullptr != pCron);
2302 
2303  OTPseudonym* pServerNym = pCron->GetServerNym();
2304  OT_ASSERT(nullptr != pServerNym);
2305 
2306  if (0 == lAmount) {
2307  otOut << "OTSmartContract::StashFunds: a zero amount is not allowed.\n";
2308  return false;
2309  }
2310 
2311  const OTIdentifier SERVER_ID(pCron->GetServerID());
2312  const OTIdentifier SERVER_USER_ID(*pServerNym);
2313 
2314  // Load up the party's account and get the asset type, so we know which
2315  // stash to get off the stash.
2316  //
2317  OTAccount* pPartyAssetAcct =
2318  OTAccount::LoadExistingAccount(PARTY_ACCT_ID, SERVER_ID);
2319 
2320  if (nullptr == pPartyAssetAcct) {
2321  otOut << "OTSmartContract::StashFunds: ERROR verifying existence of "
2322  "source account.\n";
2323  FlagForRemoval(); // Remove it from future Cron processing, please.
2324  return false;
2325  }
2326  else if (!pPartyAssetAcct->VerifySignature(*pServerNym)) {
2327  otOut << "OTSmartContract::StashFunds: ERROR failed to verify the "
2328  "server's signature on the party's account.\n";
2329  FlagForRemoval(); // Remove it from future Cron processing, please.
2330  return false;
2331  }
2332  else if (!pPartyAssetAcct->VerifyOwnerByID(PARTY_USER_ID)) {
2333  otOut << "OTSmartContract::StashFunds: ERROR failed to verify party "
2334  "user ownership of party account.\n";
2335  FlagForRemoval(); // Remove it from future Cron processing, please.
2336  return false;
2337  }
2338  // Past this point we know pPartyAssetAcct is good and will clean itself up.
2339  std::unique_ptr<OTAccount> theSourceAcctSmrtPtr(pPartyAssetAcct);
2340 
2341  //
2342  // There could be many stashes, each with a name. (One was passed in
2343  // here...)
2344  // And inside each one is a stash for each asset type. So let's get the one
2345  // for the asset type matching the party's account.
2346  //
2347  const OTString strAssetTypeID(pPartyAssetAcct->GetAssetTypeID());
2348  const std::string str_asset_type_id = strAssetTypeID.Get();
2349 
2350  OTStashItem* pStashItem = theStash.GetStash(str_asset_type_id);
2351  OT_ASSERT(nullptr !=
2352  pStashItem); // should never happen. Creates if non-existent.
2353 
2354  // Below this point, pStashItem is good, and has the right asset_type_id.
2355 
2356  //
2357  const bool bUnstashing =
2358  (lAmount < 0); // If the amount is negative, then we're UNSTASHING.
2359  const int64_t lAbsoluteAmount =
2360  bUnstashing
2361  ? (lAmount * (-1))
2362  : lAmount; // NEGATIVE AMOUNT SHOULD BEHAVE AS "UNSTASH FUNDS" !!
2363 
2364  // Normally if you stash 10 clams, then your account is -10 clams, and your
2365  // stash is +10 clams.
2366  // Therefore if you unstash 5 gg, then your gg acct is +5 grams and your
2367  // stash is -5 grams.
2368  //
2369  // Thus if lAmount is > 0, as normal, that amount should be DEBITED from the
2370  // Party Acct, and CREDITED to the Stash Acct.
2371  // Whereas if lAmount were < 0, then that amount should be DEBITED from the
2372  // Stash Acct, and CREDITED to the Party Acct.
2373 
2374  // Below this point, lAbsoluteAmount is always a positive number.
2375  // Whereas if lAmount < 0, that means we are doing an UNSTASH in this
2376  // function.
2377  //
2378 
2379  // Whether the funds are coming from the party's acct, or from the stash,
2380  // WHEREVER they
2381  // are coming from, is that source LARGE enough to accommodate the amount
2382  // we're trying to move?
2383  //
2384 
2385  const int64_t lPartyAssetBalance = pPartyAssetAcct->GetBalance();
2386  const int64_t lStashItemAmount = pStashItem->GetAmount();
2387 
2388  const int64_t lSourceAmount =
2389  bUnstashing ? lStashItemAmount : lPartyAssetBalance;
2390 
2391  // If the source, minus amount, is less than 0, then it CANNOT accommodate
2392  // the action.
2393  //
2394  if ((lSourceAmount - lAbsoluteAmount) < 0) {
2395  otOut << "OTSmartContract::StashFunds: Not enough funds available in "
2396  "the source to accommodate this action.\n";
2397  return false;
2398  }
2399 
2400  bool bWasAcctCreated = false; // GetOrCreateAccount() will verifyContractID
2401  // and verifySignature on the account
2402  // internally.
2403  std::shared_ptr<OTAccount> pStashAccount = m_StashAccts.GetOrCreateAccount(
2404  *pServerNym, SERVER_USER_ID, pPartyAssetAcct->GetAssetTypeID(),
2405  SERVER_ID, bWasAcctCreated, GetTransactionNum());
2406 
2407  if (!pStashAccount) {
2408  OT_FAIL_MSG("ASSERT in OTSmartContract::StashFunds: returned nullptr "
2409  "pointer (should never happen.)\n");
2410  }
2411 
2412  if (bWasAcctCreated) {
2413  OTString strAcctID;
2414  pStashAccount->GetIdentifier(strAcctID);
2415 
2416  otOut << "OTSmartContract::StashFunds: Successfully created stash "
2417  "account ID: " << strAcctID
2418  << "\n (Stash acct has Asset Type ID: " << strAssetTypeID
2419  << ") \n";
2420 
2421  // Todo: Some kind of save here?
2422  // It's kind of unnecessary, since I've already verified that there's
2423  // enough funds at the source
2424  // to successfully do the transfer, AND I will already save at the end
2425  // of this call, since funds are
2426  // being moved.
2427  }
2428 
2429  if (!pStashAccount) {
2430  OT_FAIL_MSG("ASSERT in OTSmartContract::StashFunds: returned nullptr "
2431  "pointer (should never happen.)\n");
2432  }
2433 
2434  // This code is similar to above, but it checks the stash ACCT itself
2435  // instead of the stash entry.
2436  //
2437  // Whether the funds are coming from the party's acct, or from the stash
2438  // acct, WHEREVER they
2439  // are coming from, is that source LARGE enough to accommodate the amount
2440  // we're trying to move?
2441  //
2442  const int64_t lSourceAmount2 = bUnstashing ? pStashAccount->GetBalance()
2443  : pPartyAssetAcct->GetBalance();
2444 
2445  // If the source, minus amount, is less than 0, then it CANNOT accommodate
2446  // the action.
2447  //
2448  if ((lSourceAmount2 - lAbsoluteAmount) < 0) {
2449  otOut << "OTSmartContract::StashFunds: Not enough funds available in "
2450  "the stash acct to accommodate this action.\n";
2451  return false; // THIS SHOULD NEVER HAPPEN, SINCE WE ALREADY VERIFIED THE
2452  // AMOUNT BEFORE LOADING THE ACCOUNT. FYI.
2453  }
2454 
2455  // Make sure they're not the same Account IDs ...
2456  // Otherwise we would have to take care not to load them twice, like with
2457  // the Nyms below.
2458  // (Instead I just disallow it entirely. After all, even if I DID allow the
2459  // account to transfer
2460  // to itself, there would be no difference in balance than disallowing it.)
2461  //
2462  const OTIdentifier STASH_ACCT_ID(pStashAccount->GetRealAccountID());
2463 
2464  if (PARTY_ACCT_ID == STASH_ACCT_ID) {
2465  otErr << "OTSmartContract::StashFunds: ERROR: both account IDs were "
2466  "identical.\n";
2467  FlagForRemoval(); // Remove from Cron
2468  return false; // TODO: should have a "Validate Scripts" function that
2469  // weeds this crap out before we even get here. (There are
2470  // other examples...)
2471  }
2472 
2473  // SHOULD NEVER HAPPEN
2474  if (pPartyAssetAcct->GetAssetTypeID() != pStashAccount->GetAssetTypeID()) {
2475  otErr << "OTSmartContract::StashFunds: Aborted stash: Asset type ID "
2476  "doesn't match. THIS SHOULD NEVER HAPPEN.\n";
2477  FlagForRemoval(); // Remove from Cron
2478  return false;
2479  }
2480 
2481  if (!pStashAccount->VerifyOwnerByID(SERVER_USER_ID)) {
2482  otErr << "OTSmartContract::StashFunds: Error: Somehow the stash "
2483  "account isn't server-nym owned.\n";
2484  FlagForRemoval(); // Remove from Cron
2485  return false;
2486  }
2487  const OTIdentifier STASH_USER_ID(pStashAccount->GetUserID());
2488 
2489  bool bSuccess = false; // The return value.
2490 
2491  OTString strPartyUserID(PARTY_USER_ID), strStashUserID(STASH_USER_ID),
2492  strPartyAcctID(PARTY_ACCT_ID), strStashAcctID(STASH_ACCT_ID),
2493  strServerNymID(SERVER_USER_ID);
2494 
2495  // Need to load up the ORIGINAL VERSION OF THIS SMART CONTRACT
2496  // Will need to verify the party's signature, as well as attach a copy of it
2497  // to the receipt.
2498 
2499  // OTCronItem::LoadCronReceipt loads the original version with the user's
2500  // signature.
2501  // (Updated versions, as processing occurs, are signed by the server.)
2502  std::unique_ptr<OTCronItem> pOrigCronItem(
2504 
2505  OT_ASSERT(nullptr != pOrigCronItem); // How am I processing it now if the
2506  // receipt wasn't saved in the first
2507  // place??
2508  // TODO: Decide global policy for handling situations where the hard drive
2509  // stops working, etc.
2510 
2511  // strOrigPlan is a String copy (a PGP-signed XML file, in string form) of
2512  // the original smart contract activation request...
2513  OTString strOrigPlan(*pOrigCronItem); // <====== Farther down in the code, I
2514  // attach this string to the receipts.
2515 
2516  // -------------- Make sure have both nyms loaded and checked out.
2517  // --------------------------------------------------
2518  // WARNING: The party's Nym could be also the Server Nym. But the Stash Nym
2519  // is ALWAYS the server.
2520  // In all of those different cases, I don't want to load the same file twice
2521  // and overwrite it with itself, losing
2522  // half of all my changes. I have to check all three IDs carefully and set
2523  // the pointers accordingly, and then operate
2524  // using the pointers from there.
2525 
2526  OTPseudonym thePartyNym;
2527 
2528  // Find out if party Nym is actually also the server nym.
2529  const bool bPartyNymIsServerNym =
2530  ((PARTY_USER_ID == SERVER_USER_ID) ? true : false);
2531 
2532  OTPseudonym* pPartyNym = nullptr;
2533  // OTPseudonym * pStashNym = pServerNym;
2534 
2535  const std::string str_party_id = strPartyUserID.Get();
2536  auto it_party = map_NymsAlreadyLoaded.find(str_party_id);
2537 
2538  if (map_NymsAlreadyLoaded.end() !=
2539  it_party) // found the party in list of Nyms that are already loaded.
2540  {
2541  pPartyNym = it_party->second;
2542  OT_ASSERT((nullptr != pPartyNym) &&
2543  (pPartyNym->CompareID(PARTY_USER_ID)));
2544  }
2545 
2546  // Figure out if party Nym is also Server Nym.
2547  if (bPartyNymIsServerNym) {
2548  // If the First Nym is the server, then just point to that.
2549  pPartyNym = pServerNym;
2550  }
2551  else if (nullptr == pPartyNym) // Else load the First Nym from storage, if
2552  // still not found.
2553  {
2554  thePartyNym.SetIdentifier(PARTY_USER_ID); // thePartyNym is pPartyNym
2555 
2556  if (!thePartyNym.LoadPublicKey()) {
2557  otErr << "OTSmartContract::StashFunds: Failure loading party Nym "
2558  "public key: " << strPartyUserID << "\n";
2559  FlagForRemoval(); // Remove it from future Cron processing, please.
2560  return false;
2561  }
2562 
2563  if (thePartyNym.VerifyPseudonym() &&
2564  thePartyNym.LoadSignedNymfile(*pServerNym)) // ServerNym here is not
2565  // thePartyNym's
2566  // identity, but merely
2567  // the signer on this
2568  // file.
2569  {
2570  otWarn << "OTSmartContract::StashFunds: Loading party Nym, since "
2571  "he apparently wasn't already loaded.\n"
2572  "(On a cron item processing, this is normal. But if you "
2573  "triggered a clause directly, then your Nym SHOULD be "
2574  "already loaded...)\n";
2575  pPartyNym = &thePartyNym; // <=====
2576  }
2577  else {
2578  otErr << "OTSmartContract::StashFunds: Failure loading or "
2579  "verifying party Nym public key: " << strPartyUserID
2580  << "\n";
2581  FlagForRemoval(); // Remove it from future Cron processing, please.
2582  return false;
2583  }
2584  }
2585  // Below this point, both Nyms are loaded and good-to-go.
2586 
2587  mapOfNyms map_ALREADY_LOADED; // I know I passed in one of these, but now I
2588  // have processed the Nym pointers (above) and
2589  // have better data here now.
2590  map_ALREADY_LOADED.insert(std::pair<std::string, OTPseudonym*>(
2591  strServerNymID.Get(),
2592  pServerNym)); // Add Server Nym to list of Nyms already loaded.
2593 
2594  auto it_temp = map_ALREADY_LOADED.find(strPartyUserID.Get());
2595  if (map_ALREADY_LOADED.end() == it_temp)
2596  map_ALREADY_LOADED.insert(std::pair<std::string, OTPseudonym*>(
2597  strPartyUserID.Get(),
2598  pPartyNym)); // Add party Nym to list of Nyms already loaded.
2599 
2600  // In this function, pStashNym and pServerNym are always the same.
2601 
2602  if (!pOrigCronItem->VerifyNymAsAgent(
2603  *pPartyNym, *pServerNym,
2604  // In case it needs to load the AUTHORIZING agent, and that agent
2605  // is already loaded, it will have access here.
2606  &map_ALREADY_LOADED)) {
2607  otErr << "OTSmartContract::StashFunds: Failed authorization for party "
2608  "Nym: " << strPartyUserID << "\n";
2609  FlagForRemoval(); // Remove it from Cron.
2610  return false;
2611  }
2612 
2613  // AT THIS POINT, I have: pServerNym, pPartyNym, and pStashNym,
2614  // PLUS: pStashAccount and pPartyAssetAcct
2615 
2616  // VerifySignature, VerifyContractID, and VerifyOwner have all been called
2617  // already
2618  // by this point. This is new:
2619  // (They might fall away in favor of this, once I start building.)
2620  //
2621  if (!VerifyNymAsAgentForAccount(*pPartyNym, *pPartyAssetAcct)) {
2622  otOut << "OTSmartContract::StashFunds: ERROR verifying ownership on "
2623  "source account.\n";
2624  FlagForRemoval(); // Remove it from future Cron processing, please.
2625  return false;
2626  }
2627  else {
2628  // Okay then, everything checks out. Let's add a receipt to the party's
2629  // inbox.
2630  // (No need for the stash's inbox -- the server owns it.)
2631 
2632  // Load the inbox in case it already exists
2633  OTLedger thePartyInbox(PARTY_USER_ID, PARTY_ACCT_ID, SERVER_ID);
2634 
2635  // ALL inboxes -- no outboxes. All will receive notification of
2636  // something ALREADY DONE.
2637  bool bSuccessLoadingPartyInbox = thePartyInbox.LoadInbox();
2638 
2639  // ...or generate them otherwise...
2640 
2641  if (true == bSuccessLoadingPartyInbox)
2642  bSuccessLoadingPartyInbox =
2643  thePartyInbox.VerifyAccount(*pServerNym);
2644  else
2645  otErr << "OTSmartContract::StashFunds: Failed trying to load "
2646  "party's inbox.\n";
2647  // OT_FAIL_MSG("ASSERT: TRYING TO GENERATE INBOX IN STASH
2648  // FUNDS!!!\n");
2649  // bSuccessLoadingPartyInbox =
2650  // thePartyInbox.GenerateLedger(PARTY_ACCT_ID, SERVER_ID,
2651  // OTLedger::inbox, true); // bGenerateFile=true
2652 
2653  if (!bSuccessLoadingPartyInbox) {
2654  otErr << "OTSmartContract::StashFunds: ERROR loading or generating "
2655  "inbox ledger.\n";
2656  }
2657  else {
2658  // Generate new transaction numbers for these new transactions
2659  int64_t lNewTransactionNumber = pCron->GetNextTransactionNumber();
2660 
2661  // OT_ASSERT(lNewTransactionNumber > 0); // this can be
2662  // my reminder.
2663  if (0 == lNewTransactionNumber) {
2664  otOut << "OTSmartContract::StashFunds: Aborted move: There are "
2665  "no more transaction numbers available in Cron.\n";
2666  // (Here I do NOT flag for removal.)
2667  return false;
2668  }
2669 
2670  OTTransaction* pTransParty = OTTransaction::GenerateTransaction(
2671  thePartyInbox, OTTransaction::paymentReceipt,
2672  lNewTransactionNumber);
2673  // (No need to OT_ASSERT on the above new transaction since it
2674  // occurs in GenerateTransaction().)
2675 
2676  // The party's inbox will get a receipt with a new transaction ID on
2677  // it, owned by the server.
2678  // It will have a "In reference to" field containing the original
2679  // signed smart contract.
2680  // (with all party's signatures from their authorizing agents.)
2681 
2682  // set up the transaction item (each transaction may have multiple
2683  // items... but not in this case.)
2684  //
2685  OTItem* pItemParty = OTItem::CreateItemFromTransaction(
2686  *pTransParty, OTItem::paymentReceipt);
2687  OT_ASSERT(nullptr !=
2688  pItemParty); // may be unnecessary, I'll have to
2689  // check CreateItemFromTransaction.
2690  // I'll leave for now.
2691 
2692  pItemParty->SetStatus(OTItem::rejection); // the default.
2693 
2694  // const int64_t lPartyTransRefNo =
2695  // GetTransactionNum();
2696  const int64_t lPartyTransRefNo = GetOpeningNumber(PARTY_USER_ID);
2697 
2698  // Here I make sure that each receipt (each inbox notice) references
2699  // the original
2700  // transaction number that was used to set the cron item into
2701  // place...
2702  // This number is used to track all cron items. (All Cron items
2703  // require a transaction
2704  // number from the user in order to add them to Cron in the first
2705  // place.)
2706  //
2707  // The number is also used to uniquely identify all other
2708  // transactions, as you
2709  // might guess from its name.
2710  //
2711  // UPDATE: Notice I'm now looking up a different number based on the
2712  // UserID.
2713  // This is to support smart contracts, which have many parties,
2714  // agents, and accounts.
2715  //
2716  // pItemParty->SetReferenceToNum(lPartyTransRefNo);
2717  pTransParty->SetReferenceToNum(lPartyTransRefNo);
2718 
2719  // The TRANSACTION (a receipt in my inbox) will be sent with "In
2720  // Reference To" information
2721  // containing the ORIGINAL SIGNED SMARTCONTRACT. (With all parties'
2722  // original signatures on it.)
2723  //
2724  // Whereas the TRANSACTION ITEM will include an "attachment"
2725  // containing the UPDATED
2726  // SMART CONTRACT (this time with the SERVER's signature on it.)
2727  //
2728  // Here's the original one going onto the transaction:
2729  //
2730  pTransParty->SetReferenceString(strOrigPlan);
2731 
2732  //
2733  // MOVE THE DIGITAL ASSETS FROM ONE ACCOUNT TO ANOTHER...
2734  //
2735  // Calculate the amount and debit/ credit the accounts
2736  // Make sure each Account can afford it, and roll back in case of
2737  // failure.
2738 
2739  // Normally if you stash 10 clams, then your account is -10 clams,
2740  // and your stash is +10 clams.
2741  // Therefore if you unstash 5 gg, then your gg acct is +5 grams and
2742  // your stash is -5 grams.
2743  //
2744  // Thus if lAmount is > 0, as normal, that amount should be DEBITED
2745  // from the Party Acct, and CREDITED to the Stash Acct.
2746  // Whereas if lAmount were < 0, then that amount should be DEBITED
2747  // from the Stash Acct, and CREDITED to the Party Acct.
2748 
2749  bool bMoveParty = false;
2750  bool bMoveStash = false;
2751 
2752  if (bUnstashing) // Debit Stash, Credit Party
2753  {
2754  if (pStashAccount->GetBalance() >= lAbsoluteAmount) {
2755  // Debit the stash account.
2756  bMoveStash = pStashAccount->Debit(
2757  lAbsoluteAmount); // <====== DEBIT FUNDS
2758 
2759  // IF success, credit the party.
2760  if (bMoveStash) {
2761  bMoveParty = pPartyAssetAcct->Credit(
2762  lAbsoluteAmount); // <=== CREDIT FUNDS
2763 
2764  // Okay, we already took it from the stash account.
2765  // But if we FAIL to credit the party, then we need to
2766  // PUT IT BACK in the stash acct.
2767  // (EVEN THOUGH we'll just "NOT SAVE" after any failure,
2768  // so it's really superfluous.)
2769  //
2770  if (!bMoveParty) {
2771  bool bErr = pStashAccount->Credit(
2772  lAbsoluteAmount); // put the money back
2773 
2774  otErr << "OTSmartContract::StashFunds: While "
2775  "succeeded debiting the stash account, "
2776  "FAILED in: "
2777  "pPartyAssetAcct->Credit(lAbsoluteAmount);"
2778  " \n"
2779  "Also, tried to credit stash account back "
2780  "again. Result: "
2781  << (bErr ? "success" : "failure") << ".\n";
2782  }
2783  else { // SUCCESS!
2784  //
2785  bool bStashSuccess = pStashItem->DebitStash(
2786  lAbsoluteAmount); // we already verified above
2787  // that this stash item has
2788  // enough funds to
2789  // successfully debit.
2790 
2791  if (bStashSuccess)
2792  bSuccess = true;
2793  else
2794  otErr << "OTSmartContract::StashFunds: ERROR: "
2795  "Debited stash account and credited "
2796  "party account, but "
2797  "then unable to debit the stash "
2798  "record inside the smart contract "
2799  "itself.\n";
2800  }
2801  }
2802  else {
2803  otErr << "OTSmartContract::StashFunds: FAILED in: "
2804  "pStashAccount->Debit(lAbsoluteAmount);\n";
2805  }
2806  }
2807  }
2808  else // Debit party, Credit Stash
2809  {
2810  if (pPartyAssetAcct->GetBalance() >= lAbsoluteAmount) {
2811  // Debit the party account.
2812  bMoveParty = pPartyAssetAcct->Debit(
2813  lAbsoluteAmount); // <====== DEBIT FUNDS
2814 
2815  // IF success, credit the Stash.
2816  if (bMoveParty) {
2817  bMoveStash = pStashAccount->Credit(
2818  lAbsoluteAmount); // <=== CREDIT FUNDS
2819 
2820  // Okay, we already took it from the party account.
2821  // But if we FAIL to credit the Stash, then we need to
2822  // PUT IT BACK in the party acct.
2823  // (EVEN THOUGH we'll just "NOT SAVE" after any failure,
2824  // so it's really superfluous.)
2825  //
2826  if (!bMoveStash) {
2827  bool bErr = pPartyAssetAcct->Credit(
2828  lAbsoluteAmount); // put the money back
2829 
2830  otErr << "OTSmartContract::StashFunds: While "
2831  "succeeded debiting the asset account, "
2832  "FAILED in: "
2833  "pStashAccount->Credit(lAbsoluteAmount); "
2834  "\n"
2835  "Also, tried to credit asset account back "
2836  "again. Result: "
2837  << (bErr ? "success" : "failure") << ".\n";
2838  }
2839  else { // SUCCESS!
2840  //
2841  bool bStashSuccess = pStashItem->CreditStash(
2842  lAbsoluteAmount); // we already verified above
2843  // that this stash item has
2844  // enough funds to
2845  // successfully debit.
2846 
2847  if (bStashSuccess)
2848  bSuccess = true;
2849  else
2850  otErr << "OTSmartContract::StashFunds: ERROR: "
2851  "Debited party account and credited "
2852  "stash account, but "
2853  "then unable to credit the stash "
2854  "record inside the smart contract "
2855  "itself.\n";
2856  }
2857  }
2858  else {
2859  otErr << "OTSmartContract::StashFunds: FAILED in: "
2860  "pPartyAssetAcct->Debit(lAbsoluteAmount);\n";
2861  }
2862  }
2863  }
2864 
2865  // If ANY of these failed, then roll them all back and break.
2866  // (In fact we could just be checking bSuccess here, I wager.
2867  // Might as well be thorough.)
2868  //
2869  if (!bMoveParty || !bMoveStash) {
2870  // No need to roll back pStashItem here, since it is never
2871  // changed in the
2872  // first place unless BOTH of the above bools were successful.
2873 
2874  otErr << "OTSmartContract::StashFunds: Very strange! Funds "
2875  "were available but "
2876  "debit " << ((bUnstashing) ? "stash" : "party")
2877  << " or credit " << ((bUnstashing) ? "party" : "stash")
2878  << " failed while performing move.\n";
2879  // We won't save the files anyway, if this failed.
2880  bSuccess = false;
2881  }
2882 
2883  // DO NOT SAVE ACCOUNTS if bSuccess is false.
2884  // We only save these accounts if bSuccess == true.
2885  // (But we do save the inboxes either way, since payment failures
2886  // always merit an inbox notice.)
2887  //
2888  if (true == bSuccess) // The payment succeeded.
2889  {
2890  // The party needs to get a receipt in his inbox.
2891  //
2892  pItemParty->SetStatus(
2893  OTItem::acknowledgement); // pPartyAssetAcct
2894 
2895  const int64_t lReceiptAmount = (lAmount * (-1));
2896 
2897  // pItemParty->SetAmount(lAmount); // lAmount
2898  // is already negative or positive by the time it's passed into
2899  // this function.
2900  pItemParty->SetAmount(lReceiptAmount); // However, if we are
2901  // stashing 100, that
2902  // means my account is
2903  // -100. Therefore
2904  // multiply by (-1)
2905  // EITHER WAY.
2906  // pItemParty->SetAmount(lAbsoluteAmount*(-1));
2907  // // "paymentReceipt" is otherwise ambigious about whether you
2908  // are paying or being paid.
2909  // This is also like market receipts, which use negative and
2910  // positive amounts.
2911 
2912  otOut << "OTSmartContract::StashFunds: Move performed.\n";
2913 
2914  // (I do NOT save m_pCron here, since that already occurs after
2915  // this function is called.)
2916  }
2917  else // bSuccess = false. The payment failed.
2918  {
2919  pItemParty->SetStatus(OTItem::rejection); // pPartyAssetAcct
2920  // // These are
2921  // already initialized
2922  // to false.
2923  pItemParty->SetAmount(
2924  0); // No money changed hands. Just being explicit.
2925 
2926  otOut << "OTSmartContract::StashFunds: Move failed.\n";
2927  }
2928 
2929  // Everytime a payment processes, a receipt is put in the user's
2930  // inbox, containing a
2931  // CURRENT copy of the cron item (which took just money from the
2932  // user's acct, or not,
2933  // and either way thus updated its status -- so its internal state
2934  // has changed.)
2935  //
2936  // It will also contain a copy of the user's ORIGINAL signed cron
2937  // item, where the data
2938  // has NOT changed, (so the user's original signature is still
2939  // good.) Although in the case of
2940  // smart contracts, each party stores their own signed copy anyway,
2941  // so it doesn't matter as
2942  // much.
2943  //
2944  // In order for it to export the RIGHT VERSION of the CURRENT smart
2945  // contract, which has just
2946  // changed (above), then I need to re-sign it and save it first.
2947  // (The original version I'll
2948  // load from a separate file using
2949  // OTSmartContract::LoadCronReceipt(lTransactionNum).
2950  //
2951  // I should be able to call a method on the original cronitem, where
2952  // I ask it to verify a certain
2953  // nym as being acceptable to that cron item as an agent, based on
2954  // the signature of the original
2955  // authorizing agent for that party. UPDATE: I believe the function
2956  // described in this paragraph
2957  // is now done.
2958  //
2959 
2961  SignContract(*pServerNym);
2962  SaveContract();
2963 
2964  //
2965  // EVERYTHING BELOW is just about notifying the party, by dropping
2966  // the receipt in his
2967  // inbox. The rest is done. The two accounts and the inbox will all
2968  // be saved at the same time.
2969  //
2970  // The Smart Contract is entirely updated and saved by this point,
2971  // and Cron will
2972  // also be saved in the calling function once we return (no matter
2973  // what.)
2974  //
2975 
2976  // Basically I load up the INBOX, which is actually a LEDGER, and
2977  // then I create
2978  // a new transaction, with a new transaction item, for that ledger.
2979  // (That's where the receipt information goes.)
2980  //
2981 
2982  // The TRANSACTION will be sent with "In Reference To" information
2983  // containing the
2984  // ORIGINAL SIGNED SMART CONTRACT. (With both of the users' original
2985  // signatures on it.)
2986  //
2987  // Whereas the TRANSACTION ITEM will include an "attachment"
2988  // containing the UPDATED
2989  // SMART CONTRACT (this time with the SERVER's signature on it.)
2990 
2991  // (Lucky I just signed and saved the updated smart contract
2992  // (above), or it would still have
2993  // have the old data in it.)
2994 
2995  // I also already loaded the original smart contact. Remember this
2996  // from above,
2997  // near the top of the function:
2998  // OTSmartContract * pOrigCronItem = nullptr;
2999  // OTString strOrigPlan(*pOrigCronItem); // <====== Farther down
3000  // in the code, I attach this string to the receipts.
3001  // ... then lower down...
3002  // pTransParty->SetReferenceString(strOrigPlan);
3003  //
3004  // So the original plan is already loaded and copied to the
3005  // Transaction as the "In Reference To"
3006  // Field. Now let's add the UPDATED plan as an ATTACHMENT on the
3007  // Transaction ITEM:
3008  //
3009 
3010  //
3011 
3012  OTString strUpdatedCronItem(*this);
3013 
3014  // Set the updated cron item as the attachment on the transaction
3015  // item.
3016  // (With the SERVER's signature on it!)
3017  // (As a receipt for the party, so they can see their smartcontract
3018  // updating.)
3019  //
3020  pItemParty->SetAttachment(strUpdatedCronItem);
3021 
3022  // Success OR failure, either way I want a receipt in the inbox.
3023  // ===> But if FAILURE, I do NOT want to save the Accounts, JUST the
3024  // inbox!!
3025  //
3026  // (So the inbox happens either way, but the accounts are saved only
3027  // on success.)
3028 
3029  // sign the item
3030  pItemParty->SignContract(*pServerNym);
3031  pItemParty->SaveContract();
3032 
3033  // the Transaction "owns" the item now and will handle cleaning it
3034  // up.
3035  pTransParty->AddItem(*pItemParty);
3036  pTransParty->SignContract(*pServerNym);
3037  pTransParty->SaveContract();
3038 
3039  // Here, the transaction we just created is actually added to the
3040  // inbox ledger.
3041  // This happens either way, success or fail.
3042 
3043  thePartyInbox.AddTransaction(*pTransParty);
3044 
3045  // Release any signatures that were there before (They won't
3046  // verify anymore anyway, since the content has changed.)
3047  //
3048  thePartyInbox.ReleaseSignatures();
3049  thePartyInbox.SignContract(*pServerNym);
3050  thePartyInbox.SaveContract();
3051 
3052  pPartyAssetAcct->SaveInbox(thePartyInbox);
3053 
3054  // This corresponds to the AddTransaction() call just above.
3055  // These are stored in a separate file now.
3056  //
3057  pTransParty->SaveBoxReceipt(thePartyInbox);
3058 
3059  // If success, save the accounts with new balance. (Save inboxes
3060  // with receipts either way,
3061  // and the receipts will contain a rejection or acknowledgment
3062  // stamped by the Server Nym.)
3063  //
3064  if (true == bSuccess) {
3065  // SAVE THE ACCOUNTS.
3066 
3067  // Release any signatures that were there before (They won't
3068  // verify anymore anyway, since the content has changed.)
3069  //
3070  pPartyAssetAcct->ReleaseSignatures();
3071  pStashAccount->ReleaseSignatures();
3072 
3073  // Sign both of them.
3074  pPartyAssetAcct->SignContract(*pServerNym);
3075  pStashAccount->SignContract(*pServerNym);
3076 
3077  // Save both of them internally
3078  pPartyAssetAcct->SaveContract();
3079  pStashAccount->SaveContract();
3080 
3081  // TODO: Better rollback capabilities in case of failures here:
3082 
3083  // Save both accounts to storage.
3084  pPartyAssetAcct->SaveAccount();
3085  pStashAccount->SaveAccount();
3086  // NO NEED TO LOG HERE, since success / failure is already
3087  // logged above.
3088  }
3089  } // the inbox was successfully loaded or generated.
3090  } // By the time we enter this block, accounts and nyms are already loaded.
3091  // As we begin, inboxes are instantiated.
3092 
3093  // Either way, Cron should save, since it just updated.
3094  // The above function call WILL change this smart contract
3095  // and re-sign it and save it, no matter what. So I just
3096  // call this here to keep it simple:
3097 
3098  pCron->SaveCron(); // TODO No need to call this here if I can make sure it's
3099  // being called higher up somewhere
3100  // (Imagine a script that has 10 account moves in it -- maybe don't need to
3101  // save cron until
3102  // after all 10 are done. Or maybe DO need to do in between. Todo research
3103  // this. Optimization.)
3104  return bSuccess;
3105 }
static EXPORT OTTransaction * GenerateTransaction(const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, transactionType theType, int64_t lTransactionNum=0)
int64_t GetTransactionNum() const
EXPORT bool SaveContract()
static EXPORT OTCronItem * LoadCronReceipt(const int64_t &lTransactionNum)
Definition: OTCronItem.cpp:227
OTLOG_IMPORT OTLogStream otOut
std::map< std::string, OTPseudonym * > mapOfNyms
Definition: OTWallet.hpp:161
EXPORT std::shared_ptr< OTAccount > GetOrCreateAccount(OTPseudonym &serverNym, const OTIdentifier &ACCOUNT_OWNER_ID, const OTIdentifier &ASSET_TYPE_ID, const OTIdentifier &SERVER_ID, bool &wasAcctCreated, int64_t stashTransNum=0)
static EXPORT OTItem * CreateItemFromTransaction(const OTTransaction &theOwner, OTItem::itemType theType, const OTIdentifier *pDestinationAcctID=nullptr)
Definition: OTItem.cpp:1451
EXPORT void ReleaseSignatures()
Definition: OTContract.cpp:989
#define OT_ASSERT(x)
Definition: Assert.hpp:150
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
OTLOG_IMPORT OTLogStream otWarn
virtual EXPORT bool SignContract(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr)
Definition: OTContract.cpp:484
OTLOG_IMPORT OTLogStream otErr
virtual int64_t GetOpeningNumber(const OTIdentifier &theNymID) const
virtual EXPORT bool VerifyNymAsAgentForAccount(OTPseudonym &theNym, OTAccount &theAccount) const
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
static EXPORT OTAccount * LoadExistingAccount(const OTIdentifier &accountId, const OTIdentifier &serverId)
Definition: OTAccount.cpp:480
bool opentxs::OTSmartContract::UnstashAcctFunds ( std::string  to_acct_name,
std::string  from_stash_name,
std::string  str_Amount 
)

Definition at line 2072 of file OTSmartContract.cpp.

2075 {
2076  OTCron* pCron = GetCron();
2077  OT_ASSERT(nullptr != pCron);
2078 
2079  OTPseudonym* pServerNym = pCron->GetServerNym();
2080  OT_ASSERT(nullptr != pServerNym);
2081 
2082  // Below this point, these are all good:
2083  //
2084  // pServerNym, pCron.
2085  //
2086 
2087  if (str_Amount.size() < 1) {
2088  otOut << "OTSmartContract::UnstashAcctFunds: Error: empty amount.\n";
2089  return false;
2090  }
2091 
2092  const int64_t lAmount = atol(str_Amount.c_str());
2093 
2094  if (lAmount <= 0) {
2095  otOut << "OTSmartContract::UnstashAcctFunds: Error: lAmount cannot be "
2096  "0 or <0. (Value passed in was " << lAmount << ".)\n";
2097  return false;
2098  }
2099 
2100  if (to_acct_name.size() <= 0) {
2101  otErr << "OTSmartContract::UnstashAcctFunds: error: to_acct_name is "
2102  "non-existent.\n";
2103  return false;
2104  }
2105  if (from_stash_name.size() <= 0) {
2106  otErr << "OTSmartContract::UnstashAcctFunds: error: from_stash_name is "
2107  "non-existent.\n";
2108  return false;
2109  }
2110 
2111  // Below this point, these are all good:
2112  //
2113  // to_acct_name,
2114  // from_stash_name,
2115  // pServerNym, pCron.
2116 
2117  OTPartyAccount* pToAcct = GetPartyAccount(to_acct_name);
2118  OTStash* pStash = GetStash(from_stash_name); // This ALWAYS succeeds.
2119  // (It will OT_ASSERT()
2120  // if failure.)
2121 
2122  if (nullptr == pToAcct) {
2123  otOut << "OTSmartContract::UnstashAcctFunds: error: to_acct ("
2124  << to_acct_name << ") not found on any party.\n";
2125  return false;
2126  }
2127 
2128  // Below this point, these are all good:
2129  //
2130  // pToAcct, to_acct_name,
2131  // pStash, from_stash_name,
2132  // pServerNym, pCron.
2133 
2134  OTAgent* pToAgent =
2135  pToAcct->GetAuthorizedAgent(); // This searches the account's party for
2136  // the account's authorized agent.
2137  // (That way it's impossible to get an agent for any other party.)
2138 
2139  if (nullptr == pToAgent) {
2140  otOut << "OTSmartContract::UnstashAcctFunds: error: authorized agent ("
2141  << pToAcct->GetAgentName().Get() << ") not found for to_acct ("
2142  << to_acct_name << ") on acct's party.\n";
2143  return false;
2144  }
2145 
2146  if (!pToAgent->IsAnIndividual()) {
2147  otOut << "OTSmartContract::UnstashAcctFunds: error: authorized agent ("
2148  << pToAcct->GetAgentName().Get() << ") for to_acct ("
2149  << to_acct_name << ") is not an active agent.\n";
2150  return false;
2151  }
2152  //
2153  // Below this point, these are all good:
2154  //
2155  // pToAcct, to_acct_name, pToAgent,
2156  // pStash, from_stash_name,
2157  // pServerNym, pCron.
2158 
2159  OTParty* pToParty = pToAgent->GetParty();
2160 
2161  if (nullptr == pToParty) {
2162  otErr << "OTSmartContract::UnstashAcctFunds: error: Party pointer "
2163  "nullptr "
2164  "on authorized agent (" << pToAcct->GetAgentName()
2165  << ") for to_acct (" << to_acct_name << ").\n";
2166  return false;
2167  }
2168  //
2169  // Below this point, these are all good:
2170  //
2171  // pToAcct, to_acct_name, pToAgent, pToParty,
2172  // pStash, from_stash_name,
2173  // pServerNym, pCron.
2174 
2175  // Done: I can see that THIS VERIFICATION CODE WILL GET CALLED EVERY SINGLE
2176  // TIME THE SCRIPT
2177  // CALLS MOVE FUNDS. Maybe that's good, but since technically this only
2178  // needs to be verified before the
2179  // first call, and not for EVERY call during any of a script's runs, I
2180  // should probably move this verification
2181  // higher, such as each time the OTCronItem triggers, plus each time a party
2182  // triggers a clause directly
2183  // through the API (server message). As long as those are covered, I will be
2184  // able to remove it from here
2185  // which should be a significant improvement for performance.
2186  // It will be at the bottom of those same functions that
2187  // "ClearTemporaryPointers()" should finally be called.
2188  //
2189  // FINAL DECISION: Redundant, removed. See comments in StashAcctFunds().
2190  //
2191  // A party might have many agents who are only voting groups, and cannot
2192  // actually sign for things
2193  // the way that nyms can. But at least ONE of those agents IS a Nym --
2194  // because there must have been
2195  // an authorizing agent who initially signed to accept the agreement, and
2196  // who fronted the opening
2197  // transaction number that activated it.
2198  //
2199  // Similarly, the authorized agent for any given party's account (each
2200  // account has its own authorized
2201  // agent) MUST be an active agent (an active agent is one with a
2202  // Nym--whether that Nym is representing
2203  // himself as the party, or whether representing some entity as an employee
2204  // in a role). Why MUST the
2205  // authorized agent be an active agent? Because when funds are moved, that
2206  // Nym must be loaded since
2207  // the account must show that Nym as a legal owner/agent. The MoveFunds will
2208  // cause a paymentReceipt to
2209  // drop into the Inbox for the relevant asset accounts, and that
2210  // paymentReceipt can ONLY be accepted
2211  // by that same Nym, who must use a transaction # that he signed for
2212  // previously and received through
2213  // his nymbox. There is actually no justification at all to take funds from
2214  // that account, since the
2215  // new balance has not yet been signed, UNLESS THE PAYMENTRECEIPT CONTAINS A
2216  // VALID, SIGNED AUTHORIZATION
2217  // FROM THE ACCOUNT HOLDER. *That* is why the authorizing agent must either
2218  // be the Party's Owner himself
2219  // (representing himself as an agent, which most will do) in which case he
2220  // will appear as the valid
2221  // owner of the account, OR he MUST be a Nym working in a Valid Role for an
2222  // Entity, where said Entity is
2223  // the valid owner on the account in question. Either OT, it will be
2224  // possible in OT for him to sign for
2225  // the paymentReceipts when they come in, and impossible for him to escape
2226  // liability for them.
2227  // (That's the idea anyway.)
2228  //
2229  // Since we know that the Authorized Agent for an account must be an ACTIVE
2230  // agent (one way or the other)
2231  // then we can error out here if he's not. We can then pass in his Nym ID.
2232  //
2233 
2234  OTIdentifier theToAgentID;
2235  const bool bToAgentID = pToAgent->GetSignerID(theToAgentID);
2236 
2237  if (!bToAgentID) {
2238  otErr << "OTSmartContract::UnstashAcctFunds: Failed to find 'To' "
2239  "Agent's Signer ID: " << pToAgent->GetName() << " \n";
2240  return false;
2241  }
2242 
2243  if (!pToAcct->GetAcctID().Exists()) {
2244  otErr << "OTSmartContract::UnstashAcctFunds: Error: ToAcct has empty "
2245  "AcctID: " << to_acct_name << " \n";
2246  return false;
2247  }
2248 
2249  const OTIdentifier theToAcctID(pToAcct->GetAcctID());
2250  //
2251  // BELOW THIS POINT, theToAcctID and theToAgentID available.
2252 
2253  // WE SET THESE HERE SO THE RECEIPT SHOWS, SUCCESS OR FAIL,
2254  // WHO THE INTENDED SENDER / RECIPIENT ARE FOR THAT RECEIPT.
2255  //
2257 
2258  theToAgentID.GetString(m_strLastRecipientUser); // This is the last User ID
2259  // of a party who RECEIVED
2260  // money.
2261  theToAcctID.GetString(m_strLastRecipientAcct); // This is the last Acct ID
2262  // of a party who RECEIVED
2263  // money.
2264  // Above: the FromAgent and FromAcct are commented out,
2265  // since the funds are coming from a stash.
2266 
2267  const int64_t lNegativeAmount = (lAmount * (-1));
2268 
2269  mapOfNyms map_Nyms_Already_Loaded;
2270  RetrieveNymPointers(map_Nyms_Already_Loaded);
2271 
2272  bool bMoved = StashFunds(map_Nyms_Already_Loaded, lNegativeAmount,
2273  theToAcctID, theToAgentID, *pStash);
2274  if (!bMoved) {
2275  otOut << "OTSmartContract::UnstashAcctFunds: Failed in final call. "
2276  "Values: to_acct: " << to_acct_name
2277  << ", from_stash: " << from_stash_name << ", lAmount: " << lAmount
2278  << ". \n";
2279  return false;
2280  }
2281 
2282  return true;
2283 }
EXPORT bool StashFunds(const mapOfNyms &map_NymsAlreadyLoaded, const int64_t &lAmount, const OTIdentifier &PARTY_ACCT_ID, const OTIdentifier &PARTY_USER_ID, OTStash &theStash)
OTStash * GetStash(std::string str_stash_name)
OTLOG_IMPORT OTLogStream otOut
std::map< std::string, OTPseudonym * > mapOfNyms
Definition: OTWallet.hpp:161
#define OT_ASSERT(x)
Definition: Assert.hpp:150
void RetrieveNymPointers(mapOfNyms &map_Nyms_Already_Loaded)
OTLOG_IMPORT OTLogStream otErr
OTCron * GetCron() const
Definition: OTCronItem.hpp:293
OTPartyAccount * GetPartyAccount(std::string str_acct_name) const
void opentxs::OTSmartContract::UpdateContents ( )
virtual

Reimplemented from opentxs::OTTrackable.

Definition at line 5464 of file OTSmartContract.cpp.

5465 {
5466  // I release this because I'm about to repopulate it.
5468 
5469  const OTString SERVER_ID(GetServerID()),
5470  ACTIVATOR_USER_ID(GetSenderUserID()),
5471  ACTIVATOR_ACCT_ID(GetSenderAcctID());
5472 
5473  OT_ASSERT(nullptr != m_pCancelerNymID);
5474 
5475  OTString strCanceler;
5476 
5477  if (m_bCanceled) m_pCancelerNymID->GetString(strCanceler);
5478 
5479  int64_t tCreation = OTTimeGetSecondsFromTime(
5481  int64_t tValidFrom = OTTimeGetSecondsFromTime(
5483  int64_t tValidTo = OTTimeGetSecondsFromTime(
5485  int64_t tNextProcess = OTTimeGetSecondsFromTime(
5487 
5488  // OTSmartContract
5490  "<smartContract\n version=\"%s\"\n"
5491  " serverID=\"%s\"\n"
5492  " activatorUserID=\"%s\"\n"
5493  " activatorAcctID=\"%s\"\n"
5494  " lastSenderUserID=\"%s\"\n"
5495  " lastSenderAcctID=\"%s\"\n"
5496  " lastRecipientUserID=\"%s\"\n"
5497  " lastRecipientAcctID=\"%s\"\n"
5498  " canceled=\"%s\"\n"
5499  " cancelerUserID=\"%s\"\n"
5500  " transactionNum=\"%lld\"\n"
5501  " creationDate=\"%" PRId64 "\"\n"
5502  " validFrom=\"%" PRId64 "\"\n"
5503  " validTo=\"%" PRId64 "\"\n"
5504  " nextProcessDate=\"%" PRId64 "\""
5505  " >\n\n",
5506  m_strVersion.Get(), m_bCalculatingID ? "" : SERVER_ID.Get(),
5507  m_bCalculatingID ? "" : ACTIVATOR_USER_ID.Get(),
5508  m_bCalculatingID ? "" : ACTIVATOR_ACCT_ID.Get(),
5509  m_bCalculatingID ? "" : m_strLastSenderUser.Get(),
5510  m_bCalculatingID ? "" : m_strLastSenderAcct.Get(),
5511  m_bCalculatingID ? "" : m_strLastRecipientUser.Get(),
5512  m_bCalculatingID ? "" : m_strLastRecipientAcct.Get(),
5513  m_bCanceled ? "true" : "false", m_bCanceled ? strCanceler.Get() : "",
5514  m_bCalculatingID ? 0 : m_lTransactionNum, tCreation, tValidFrom,
5515  tValidTo, tNextProcess);
5516 
5517  // OTCronItem
5518  if (!m_bCalculatingID) {
5519  for (int32_t i = 0; i < GetCountClosingNumbers(); i++) {
5520  int64_t lClosingNumber = GetClosingTransactionNoAt(i);
5521  OT_ASSERT(lClosingNumber > 0);
5522 
5524  "<closingTransactionNumber value=\"%lld\"/>\n\n",
5525  lClosingNumber);
5526 
5527  // For OTSmartContract, this should only contain a single number,
5528  // from the activator Nym.
5529  // I preserved the loop anyway. Call me crazy. But I'm still
5530  // displaying an error if there's
5531  // more than one.
5532  if (i > 0)
5533  otErr << "OTSmartContract::" << __FUNCTION__
5534  << ": ERROR: There's only ever "
5535  "supposed to be a single closing number here (for "
5536  "smart contracts.)\n";
5537  }
5538  }
5539 
5540  // *** OT SCRIPTABLE ***
5541  //
5543  m_bCalculatingID); // FYI: this is: void
5544 
5545  if (!m_bCalculatingID) {
5546 
5547  // Save m_StashAccts.
5548  //
5549  // (This is an object that contains a map of OTAccountIDs, by
5550  // asset_type_id)
5551  //
5552  m_StashAccts.Serialize(m_xmlUnsigned);
5553 
5554  // This is a map of OTStash's, by stash_name.
5555  // EACH ONE contains a map of OTStashItems, by asset_type_id
5556 
5557  // These stashes are what the scripts interact with. They have names.
5558  // Whereas the stash accts (above) are the actual accountIDs
5559  for (auto& it : m_mapStashes) {
5560  // where the actual funds are stored for each asset type.
5561  OTStash* pStash = it.second;
5562  OT_ASSERT(nullptr != pStash);
5563  pStash->Serialize(m_xmlUnsigned);
5564  }
5565  }
5566 
5567  m_xmlUnsigned.Concatenate("</smartContract>\n\n");
5568 }
const OTIdentifier & GetSenderUserID() const
time64_t GetValidTo() const
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
EXPORT int64_t GetClosingTransactionNoAt(uint32_t nIndex) const
Definition: OTCronItem.cpp:681
const time64_t & GetNextProcessDate() const
const OTIdentifier & GetServerID() const
time64_t GetValidFrom() const
EXPORT int32_t GetCountClosingNumbers() const
Definition: OTCronItem.cpp:676
void UpdateContentsToString(OTString &strAppend, bool bCalculatingID) const
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
EXPORT const char * Get() const
Definition: OTString.cpp:1045
OTLOG_IMPORT OTLogStream otErr
EXPORT void Serialize(OTString &append) const
OTIdentifier * m_pCancelerNymID
Definition: OTCronItem.hpp:177
EXPORT void GetString(OTString &theStr) const
const OTIdentifier & GetSenderAcctID() const
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
#define OT_TIME_ZERO
Definition: Common.hpp:180
virtual EXPORT void Release()
Definition: OTString.cpp:765
const time64_t & GetCreationDate() const
Definition: OTCronItem.hpp:268
bool opentxs::OTSmartContract::VerifySmartContract ( OTPseudonym theNym,
OTAccount theAcct,
OTPseudonym theServerNym,
bool  bBurnTransNo = false 
)

Definition at line 4391 of file OTSmartContract.cpp.

4395 {
4396  OTAgent* pAuthAgent = nullptr;
4397  OTParty* pAuthParty = FindPartyBasedOnNymAsAuthAgent(theNym, &pAuthAgent);
4398 
4399  if (nullptr == pAuthParty) {
4400  OTString strNymID;
4401  theNym.GetIdentifier(strNymID);
4402  otOut << __FUNCTION__
4403  << ": Unable to find a party in this smart contract, based "
4404  "on theNym (" << strNymID << ") as authorizing agent.\n";
4405  return false;
4406  }
4407  OT_ASSERT(nullptr !=
4408  pAuthAgent); // If it found the party, then it DEFINITELY
4409  // should have set the agent pointer.
4410  // BELOW THIS POINT, pAuthAgent and pAuthParty and both good pointers.
4411  // Furthermore, we know that theNym
4412  // really is the authorizing agent for one of the parties to the contract.
4413 
4414  const OTString strServerID(
4415  GetServerID()); // the serverID has already been verified by this time,
4416  // in OTServer::NotarizeSmartContract()
4417 
4418  mapOfNyms map_Nyms_Already_Loaded; // The list of Nyms that were already
4419  // instantiated before this function was
4420  // called.
4421  RetrieveNymPointers(map_Nyms_Already_Loaded); // now theNym is on this
4422  // map. (His party
4423  // already has a pointer
4424  // to him since he is
4425  // the activator.)
4426 
4427  mapOfNyms map_Nyms_Loaded_In_This_Function; // The total list of Nyms that
4428  // were instantiated inside this
4429  // function (and must be
4430  // deleted.)
4431 
4432  mapOfAccounts map_Accts_Already_Loaded; // The list of Accounts that were
4433  // already instantiated before this
4434  // function was called.
4435  const OTString strAcctID(theAcct.GetRealAccountID());
4436  map_Accts_Already_Loaded.insert(std::pair<std::string, OTAccount*>(
4437  strAcctID.Get(), &theAcct)); // now theAcct is on this map.
4438 
4439  mapOfAccounts map_Accts_Loaded_In_This_Function; // The total list of Accts
4440  // that were instantiated
4441  // inside this function
4442  // (and must be deleted.)
4443 
4444  bool bAreAnyInvalidParties = false;
4445  std::set<OTParty*> theFailedParties; // A set of pointers to parties who
4446  // failed verification.
4447 
4448  // LOOP THROUGH ALL PARTIES AND VERIFY THEM.
4449  for (auto& it_party : m_mapParties) {
4450  const std::string str_party_name = it_party.first;
4451  OTParty* pParty = it_party.second;
4452  OT_ASSERT_MSG(nullptr != pParty,
4453  "OTSmartContract::VerifySmartContract: "
4454  "Unexpected nullptr pointer in party "
4455  "map.\n");
4456 
4457  /*
4458  -- Load up the authorizing agent's Nym, if not already loaded. (Why? To
4459  verifySignature. Also, just to have
4460  it loaded so I don't have to load it twice in case it's needed for
4461  verifying one/some of the accts.) So really:
4462  -- Verify each party, that the authorizing agent and signature are all
4463  good. (I think I have this already...)
4464  -- Definitely during this, need to make sure that the contents of the
4465  signed version match the contents of the main version, for each signer.
4466  -- Verify that the authorizing agent actually has the opening
4467  transaction # for the party issued to him. (Do I have this?....)
4468 
4469  -- REMOVE the Opening transaction # for each agent.
4470  (leaving it as issued, but no longer as "available to be used on
4471  another transaction".)
4472 
4473  THE ABOVE is all accomplished via VerifyPartyAuthorization()..
4474 
4475  Next:
4476 
4477  -- Loop through all the asset accounts
4478  -- For each, get a pointer to the authorized agent and verify the
4479  CLOSING number for that asset acct. (I have something like this?...)
4480 
4481  -- Since we're looping through all the agents, and looping through all
4482  the asset accounts, and checking the agent for each asset account,
4483  then we might as well make sure that each agent is a legit agent for
4484  the party, and that each account has a legit agent lording over it.
4485  (Don't I do something like that already?)
4486  */
4487 
4488  bool bToBurnOrNotToBurn = bBurnTransNo;
4489 
4490  // If we're burning a number, but THIS party has the same opening # as
4491  // the smart contract itself, then don't bother verifying / burning this
4492  // specific number (since it's been done already, higher-up.)
4493  //
4494  if (bBurnTransNo && // If this party's opening number is the SMART
4495  // CONTRACT's opening number, then this party
4496  (GetTransactionNum() ==
4497  pParty->GetOpeningTransNo())) // MUST be the ACTIVATOR. (No need to
4498  // mark his trans# as IN USE since
4499  // already done earlier.)
4500  {
4501  // In cases where we're supposed to burn the transaction number, we
4502  // do that
4503  // for ALL parties EXCEPT the one who has the same Opening# as the
4504  // SmartContract
4505  // has for its GetTransactionNum(). Why? Because that one was
4506  // already burned, when
4507  // the activating party (pParty) activated the smart contract. At
4508  // that time, the normal
4509  // transaction system inside OTServer burned the # as part of its
4510  // process before even
4511  // calling NotarizeSmartContract(). Therefore, by this point, we
4512  // ASSUME that party's
4513  // opening num has already JUST been verified, and we skip it,
4514  // (continuing to verify
4515  // all the others.)
4516 
4517  bToBurnOrNotToBurn = false;
4518  }
4519 
4520  mapOfNyms map_Nyms_NewlyLoaded, map_Nyms_Already_Loaded_AS_OF_NOW;
4521 
4522  map_Nyms_Already_Loaded_AS_OF_NOW.insert(
4523  map_Nyms_Already_Loaded.begin(), map_Nyms_Already_Loaded.end());
4524  map_Nyms_Already_Loaded_AS_OF_NOW.insert(
4525  map_Nyms_Loaded_In_This_Function.begin(),
4526  map_Nyms_Loaded_In_This_Function.end());
4527 
4528  const bool bIsPartyAuthorized = VerifyPartyAuthorization(
4529  *pParty, // The party that supposedly is authorized for this
4530  // supposedly executed agreement.
4531  theServerNym, // For verifying signature on the authorizing Nym,
4532  // when loading it
4533  strServerID, // For verifying issued num, need the serverID the #
4534  // goes with.
4535  &map_Nyms_Already_Loaded_AS_OF_NOW, &map_Nyms_NewlyLoaded,
4536  bToBurnOrNotToBurn); // bBurnTransNo = true (default is false)
4537 
4538  map_Nyms_Loaded_In_This_Function.insert(map_Nyms_NewlyLoaded.begin(),
4539  map_Nyms_NewlyLoaded.end());
4540 
4541  // By this point, we've verified that pParty->GetOpeningTransNo() really
4542  // is ISSUED to pParty.
4543  // After all, you can Verify a Party's Authorization even after the
4544  // smart contract has been activated.
4545  // But in THIS function we also want to verify TRANSACTION num (not just
4546  // VerifyIssuedNum()) because
4547  // this is where that number is actually being BURNED for each one.
4548  // Since VerifyPartyAuthorization() ALREADY has the Nym loaded up for
4549  // verification, I'm going
4550  // to pass in a boolean arg to verify the Transaction Num as well, and
4551  // burn it. (for this very purpose.)
4552  //
4553  // Due to this, We don't want to stop this loop just because one of the
4554  // parties failed. We want to go ahead
4555  // and burn ALL the opening numbers for the remainder of the parties, so
4556  // that they have a consistent rule (the
4557  // opening number is considered burned and gone after a failed
4558  // activation attempt, though the closing numbers
4559  // are salvageable.) Otherwise they would never know, upon receiving a
4560  // server failure reply, whether their
4561  // opening number was to still be considered valid -- or not.
4562  //
4563  if (!bIsPartyAuthorized) {
4564  otOut << __FUNCTION__ << ": Party " << str_party_name
4565  << " does NOT verify as authorized! \n";
4566  bAreAnyInvalidParties = true; // We let them all go through, but we
4567  // still take notice that at least one
4568  // failed.
4569 
4570  theFailedParties.insert(pParty); // (So we can skip them in the loop
4571  // below. Meaning THEIR closing #s
4572  // also don't get marked as "used",
4573  // which is another reason for
4574  // clients to just harvest the
4575  // number in that case and consider
4576  // it as clean, since the server
4577  // is.)
4578  // return false; // see above comment. We still allow all
4579  // parties to burn their opening #s, to keep things consistent for
4580  // the client GUI code.
4581  }
4582  }
4583 
4584  // NEXT: THE ACCOUNTS
4585  //
4586  // We loop through the parties again, now knowing they are all authorized.
4587  // For each party, we call pParty->LoadAndVerifyAgentNyms(). This way, they
4588  // will
4589  // all be loaded up already for when we verify the accounts. Similarly we
4590  // call
4591  // pParty->LoadAndVerifyAssetAccounts(), so that all the accounts are loaded
4592  // up
4593  // as well. (We at least need to check their signatures...) At that point,
4594  // all
4595  // of the agent nyms AND accounts have been loaded! (And verified internally
4596  // against
4597  // themselves, such as their signature, etc.)
4598  //
4599  // From there, I need to verify the Party's Ownership over the account, as
4600  // well as
4601  // verify that the authorized agent listed for each account actually has
4602  // signer rights
4603  // over that account, and verify the closing transaction #s for each account
4604  // against its
4605  // authorized agent.
4606  //
4607  bool bAreAnyInvalidAccounts = false;
4608 
4609  /*
4610  NOTE on syncronicity...
4611 
4612  Above, we burned all the opening numbers for ALL the various nyms, even if
4613  there was some failure halfway through
4614  the verification process. This in order to make it easy to tell whether,
4615  for you, that number is still good or not.
4616 
4617  Similarly, what about the closing numbers (below) ? They are not instantly
4618  BURNED just for the ATTEMPT (as the
4619  opening numbers were) but they are still marked below as "USED BUT STILL
4620  ISSUED."
4621 
4622  if (bAreAnyInvalidParties) just above insures that the below code will not
4623  run if there are any invalid parties.
4624  That means that if "the message succeeded but transaction failed" due to
4625  invalid parties, then the closing numbers
4626  will never be seen by the server and thus never marked as "USED BUT STILL
4627  ISSUED." Instead, they would still be
4628  considered "ISSUED AND AVAILABLE."
4629 
4630  Based on that:
4631  If some FAILURE occurs below, as above, it still completes the loop in
4632  order to have consistent results for the
4633  closing transaction numbers, for all parties. So we know that success or
4634  fail, if the below code runs, the closing
4635  number is DEFINITELY marked as "USED BUT STILL ISSUED" for ALL parties,
4636  whereas if the below code does not run, the
4637  closing number for all parties is definitely still marked as "ISSUED AND
4638  AVAILABLE" (as far as this message is
4639  concerned.)
4640 
4641  Thus, there is still an inconsistency. When a client is later trying to
4642  interpret which transaction numbers to "claw
4643  back", he will have to harvest back the closing numbers SOMETIMES, based on
4644  WHY the transaction failed verification,
4645  and thus he cannot rely on a "transaction failed" state to give him a
4646  reliable answer to that question.
4647 
4648  However, we must keep in mind that these CLOSING numbers have NOT been
4649  burned -- they ARE still on the client's local
4650  list for his nym as "USED BUT STILL ISSUED." If the client harvests them
4651  back each time consistently, what will happen?
4652  The client will look at each closing number, see if it's on his local
4653  "issued" list (which it is) and then will re-add
4654  it to his "available" list as well. So is it really available on the server
4655  side? The answer is: sometimes.
4656 
4657  SOLUTION?
4658  1. Above, cache a list of all the parties who failed verification.
4659  2. Allow the code below to run, even if some parties have failed.
4660  3. Change the code below to skip failed parties while verifying accounts.
4661  (Using afore-mentioned list to make this possible.)
4662  4. Move the "if failed parties, return false" block BELOW this loop, in
4663  conjunction with the invalid accounts block.
4664 
4665  This will guarantee that closing numbers are consistently marked as "USED
4666  BUT STILL ISSUED" on the server side, no matter
4667  HOW the transaction has failed. (At least it will then be consistent.)
4668 
4669  However, if the transaction HAS failed, then all those closing numbers, if
4670  the clients are to claw them back, must be
4671  marked as available once again on the server side, as well! And if the
4672  clients are NOT to claw them back for future use,
4673  then how will they ever close them out? The server already won't allow the
4674  numbers to be used again, since they were
4675  marked as "used but still issued". But the transaction is ALREADY closed
4676  (it failed.)
4677 
4678  SOLUTIONS?
4679  -- Server could burn the closing numbers for failed transactions, vs
4680  marking them as "used but issued" when the transaction
4681  is successful. That way any client getting notice of the failure would
4682  DEFINITELY know that those numbers were burned, and
4683  could sync himself accordingly. (We definitely need to notice all
4684  parties as well, in this case, since they will need
4685  to discard the burned numbers after that point, in order to avoid going
4686  out-of-sync.)
4687 
4688  -- Server could also, in the event of transaction failure, mark the closing
4689  numbers as "available again, like new!"
4690  This way clients could clearly determine whether to burn their numbers
4691  or mark them as available again, purely based
4692  on the transaction's failure state. (State meaning the message itself is
4693  successful, and transaction could be success or fail.)
4694  Clients will not go out of sync in this case, if they fail to adjust to
4695  match the server. Well, they would be out of
4696  sync, but not the kind that prevents you from doing new transactions.
4697  (Rather, it's the kind where you have certain numbers
4698  signed out forever and you can never get rid of them.) Therefore, a
4699  notice is ALSO needed for this case.
4700 
4701  -- I know notices are already being sent upon activation, but I need to
4702  research that more closely now and determine the
4703  exact circumstances of these notices. Clearly a notice is REQUIRED, no
4704  matter which above option I choose!
4705 
4706  Thought: If notice is REQUIRED either way, perhaps the clients can just
4707  assume X unless a notice is received? For example,
4708  a client could just ASSUME the closing number is "used but still issued"
4709  unless notice is received to the contrary. This IS
4710  how the state would be if the transaction were successful, yet if it had
4711  failed, or hadn't been activated yet, the client
4712  also wouldn't experience any syncing issues by making this assumption.
4713 
4714  Clearly the server HAS to, in the event of transaction failure, mark the
4715  closing numbers either as "available again, like new!"
4716  or it has to mark them as BURNED, but either way, it's an additional piece
4717  the server has to do (up until now it has only
4718  marked them as "used but still issued.") What I can see is the server HAS
4719  to do something about those numbers, and it HAS
4720  to notify all the parties whether that transaction succeeded or failed, and
4721  then those parties HAVE to fix their client-side
4722  transaction count BASED on whether that transaciton succeeded or failed.
4723 
4724  Therefore:
4725 
4726  1. Implement the above 4-step solution.
4727  2. Do something about all the closing numbers, if activation fails.
4728  (Keep the nyms loaded until that is done, so as not to have to load them
4729  twice.)
4730  3. Make sure the parties are consistently noticed either way.
4731  4. Make sure the parties are syncing their numbers properly based on these
4732  notices.
4733 
4734 
4735  WOW, eh? But I believe that smart contracts are the most complicated case,
4736  so this has got to be the worst of it, now handled :-)
4737 
4738  Another note: If we assume the server burns the closing numbers, then the
4739  clients will suddenly be out-of-sync and unable
4740  to process transactions until they receive and process the notice of this
4741  failure. But if we instead assume that the server
4742  "makes new" those closing numbers, then the clients will remain in sync
4743  regardless of notice, and they only need to harvest
4744  the numbers upon notice, just so they can use them again, and they will not
4745  experience any "out of sync failures" along the
4746  way. Thus, it is preferable for the server to "make those numbers new
4747  again!" in the event of activation failure, AND to notice
4748  the parties of this so that they can do likewise.
4749  One way to notice them is to drop the "message succeeded but transaction
4750  failed" server reply into ALL of their Nymboxes,
4751  and not just the activator's. But not sure if that's safe... hm.
4752 
4753  */
4754 
4755  for (auto& it_party : m_mapParties) {
4756  const std::string str_party_name = it_party.first;
4757  OTParty* pParty = it_party.second;
4758  OT_ASSERT_MSG(nullptr != pParty,
4759  "Unexpected nullptr pointer in party map.");
4760 
4761  // SKIP FAILED PARTIES...
4762  //
4763  auto it_failed = theFailedParties.find(pParty);
4764 
4765  if (theFailedParties.end() != it_failed) // this means pParty was found
4766  // on the FAILED list. (So we
4767  // can skip it here.)
4768  {
4769  otOut << __FUNCTION__ << ": FYI, at least one party ("
4770  << str_party_name
4771  << ") has failed, and right now I'm skipping verification of "
4772  "his asset accounts.\n";
4773  continue;
4774  }
4775 
4776  mapOfNyms map_Nyms_NewlyLoaded, map_Nyms_Already_Loaded_AS_OF_NOW;
4777 
4778  map_Nyms_Already_Loaded_AS_OF_NOW.insert(
4779  map_Nyms_Already_Loaded.begin(), map_Nyms_Already_Loaded.end());
4780  map_Nyms_Already_Loaded_AS_OF_NOW.insert(
4781  map_Nyms_Loaded_In_This_Function.begin(),
4782  map_Nyms_Loaded_In_This_Function.end());
4783 
4784  // After calling this, map_Nyms_NewlyLoaded will contain pointers to
4785  // Nyms that MUST BE CLEANED UP.
4786  // LoadAndVerifyAgentNyms will not bother loading any Nyms which appear
4787  // on map_Nyms_Already_Loaded.
4788  //
4789  const bool bAgentsLoaded = pParty->LoadAndVerifyAgentNyms(
4790  theServerNym, map_Nyms_Already_Loaded_AS_OF_NOW, // Nyms it won't
4791  // bother loading
4792  // 'cause they are
4793  // loaded already.
4794  map_Nyms_NewlyLoaded); // Nyms it had to load itself, and thus that
4795  // YOU must clean up afterwards.
4796  map_Nyms_Loaded_In_This_Function.insert(map_Nyms_NewlyLoaded.begin(),
4797  map_Nyms_NewlyLoaded.end());
4798  if (!bAgentsLoaded) {
4799  otOut << __FUNCTION__
4800  << ": Failed trying to Load and Verify Agent Nyms for party: "
4801  << str_party_name << "\n";
4802  bAreAnyInvalidAccounts = true; // We let them all go through, so
4803  // there is consistent output, but we
4804  // still take notice that at least
4805  // one failed.
4806  }
4807 
4808  mapOfAccounts map_Accts_NewlyLoaded, map_Accts_Already_Loaded_AS_OF_NOW;
4809 
4810  map_Accts_Already_Loaded_AS_OF_NOW.insert(
4811  map_Accts_Already_Loaded.begin(), map_Accts_Already_Loaded.end());
4812  map_Accts_Already_Loaded_AS_OF_NOW.insert(
4813  map_Accts_Loaded_In_This_Function.begin(),
4814  map_Accts_Loaded_In_This_Function.end());
4815 
4816  // After calling this, map_Accts_NewlyLoaded will contain pointers to
4817  // Accts that MUST BE CLEANED UP.
4818  // LoadAndVerifyAssetAccounts will not bother loading any Accts which
4819  // appear on map_Accts_Already_Loaded.
4820  //
4821  const bool bAcctsLoaded = pParty->LoadAndVerifyAssetAccounts(
4822  theServerNym, strServerID,
4823  map_Accts_Already_Loaded_AS_OF_NOW, // Accts it won't bother loading
4824  // 'cause they are loaded
4825  // already.
4826  map_Accts_NewlyLoaded); // Accts it had to load itself, and thus
4827  // that YOU must clean up afterwards.
4828 
4829  map_Accts_Loaded_In_This_Function.insert(map_Accts_NewlyLoaded.begin(),
4830  map_Accts_NewlyLoaded.end());
4831  if (!bAcctsLoaded) {
4832  otOut
4833  << __FUNCTION__
4834  << ": Failed trying to Load and Verify Asset Accts for party: "
4835  << str_party_name << "\n";
4836  bAreAnyInvalidAccounts = true; // We let them all go through, so
4837  // there is consistent output, but we
4838  // still take notice that at least
4839  // one failed.
4840  }
4841 
4842  // BY THIS POINT, FOR THIS PARTY, we have successfully loaded and
4843  // verified ALL of the Nyms,
4844  // for ALL of the party's agents, and ALL of the asset accounts, for
4845  // this party. We know the
4846  // Party has pointers internally to all of those objects as well.
4847  // Therefore if we erase any of those objects, we must also clear the
4848  // pointers!
4849  //
4850  const bool bAreAcctsVerified = pParty->VerifyAccountsWithTheirAgents(
4851  theServerNym, strServerID,
4852  bBurnTransNo); // bBurnTransNo=false by default.
4853  if (!bAreAcctsVerified) {
4854  otOut << __FUNCTION__
4855  << ": Failed trying to Verify Asset Accts with their Agents, "
4856  "for party: " << str_party_name << "\n";
4857  bAreAnyInvalidAccounts = true; // We let them all go through, so
4858  // there is consistent output, but we
4859  // still take notice that at least
4860  // one failed.
4861  }
4862 
4863  // Now we don't delete these until AFTER the loop, until after we know
4864  // if it was a success.
4865  // If it failed, then we can fix their closing transaction numbers from
4866  // "used but still issued" back to
4867  // "issued and available for use." (If it was a success, then we don't
4868  // do anything, since the numbers are
4869  // already marked appropriately. And we still clean up all the nyms /
4870  // accounts--just AFTER this loop.)
4871  //
4872  // pParty->ClearTemporaryPointers(); // Don't want any bad
4873  // pointers floating around after cleanup. (Pointers must be cleared in
4874  // same scope as whatever they point to...)
4875  // OTSmartContract::CleanupNyms (map_Nyms_NewlyLoaded); // HAVE to
4876  // do this, or we'll leak. Even if something returned
4877  // OTSmartContract::CleanupAccts(map_Accts_NewlyLoaded); // false,
4878  // some objects may have been loaded before it failed.
4879  }
4880 
4881  const bool bSuccess = (!bAreAnyInvalidParties &&
4882  !bAreAnyInvalidAccounts); // <=== THE RETURN VALUE
4883 
4884  if (bAreAnyInvalidParties)
4885  otOut << __FUNCTION__ << ": Failure: There are invalid party(s) on "
4886  "this smart contract.\n";
4887 
4888  if (bAreAnyInvalidAccounts)
4889  otOut << __FUNCTION__ << ": Failure: there are invalid account(s) or "
4890  "authorized agent(s) on this smart "
4891  "contract.\n";
4892 
4893  // IF we marked the numbers as IN USE (bBurnTransNo) but then FAILURE
4894  // occurred,
4895  // then we need to CLOSE the opening numbers (RemoveIssuedNum) meaning they
4896  // are done
4897  // and over, and can never be used again, and we also need to HARVEST the
4898  // CLOSING
4899  // numbers, meaning they are available again for use in the future.
4900  // (If failure occurred in a case where we did NOT burn the numbers, then we
4901  // wouldn't
4902  // be worried about putting them back, now would we?)
4903  //
4904  //
4905  if (!bSuccess && // If this function was not a success, overall, and
4906  bBurnTransNo) // if we DID burn (mark as 'in use') the numbers during
4907  // this function...
4908  {
4909  // CloseoutOpeningNumbers...
4910  // This closes the opening numbers for all parties except the activator
4911  // Nym.
4912  // Why not him? Because his is already closed out in
4913  // NotarizeTransaction, if
4914  // the transaction has failed.
4915  //
4916  // Also, where that happens, his set of open cron items is also updated
4917  // to
4918  // remove the number from that list. (As the below function also does
4919  // for the rest
4920  // of the nyms involved.)
4921  //
4922  CloseoutOpeningNumbers(&theServerNym);
4923 
4924  // Then harvest those closing numbers back again (for ALL Nyms.)
4925  // (Not the opening numbers, which are already burned for good by this
4926  // point.)
4927  //
4929  &theServerNym, // theServerNym is the signer, here on the server
4930  // side.
4931  &theFailedParties); // Since we skipped marking the closing numbers
4932  // for these failed parties, then we skip adding
4933  // those same numbers back again, too.
4934  }
4935 
4936  // Now that all potentially-needed harvesting is done, we can clean up.
4937  //
4938  ClearTemporaryPointers(); // Don't want any bad pointers floating
4939  // around after cleanup.
4940 
4942  map_Nyms_Loaded_In_This_Function); // HAVE to do this, or we'll leak.
4943  // Even if something returned
4945  map_Accts_Loaded_In_This_Function); // false, some objects may have been
4946  // loaded before it failed.
4947 
4948  // DONE: if the above loop fails halfway through, then we should really PUT
4949  // BACK the closing
4950  // transaction #s that we removed. After all, we have a list of them.
4951  // Otherwise the only way
4952  // to know which parties have their numbers still, and which ones don't,
4953  // would be to stick a notice
4954  // in their nymbox, like we do for finalReceipt. Perhaps such a notice
4955  // should ALWAYS go into the
4956  // Nymbox in these cases... *shrug*
4957 
4958  return bSuccess;
4959 }
EXPORT OTParty * FindPartyBasedOnNymAsAuthAgent(OTPseudonym &theNym, OTAgent **ppAgent=nullptr) const
int64_t GetTransactionNum() const
OTLOG_IMPORT OTLogStream otOut
std::map< std::string, OTPseudonym * > mapOfNyms
Definition: OTWallet.hpp:161
void CloseoutOpeningNumbers(OTPseudonym *pSignerNym=nullptr)
mapOfParties m_mapParties
const OTIdentifier & GetServerID() const
bool VerifyPartyAuthorization(OTParty &theParty, OTPseudonym &theSignerNym, const OTString &strServerID, mapOfNyms *pmap_ALREADY_LOADED=nullptr, mapOfNyms *pmap_NEWLY_LOADED=nullptr, bool bBurnTransNo=false)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
void RetrieveNymPointers(mapOfNyms &map_Nyms_Already_Loaded)
static void CleanupAccts(mapOfAccounts &theMap)
static void CleanupNyms(mapOfNyms &theMap)
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
std::map< std::string, OTAccount * > mapOfAccounts
Definition: OTWallet.hpp:157
virtual void HarvestClosingNumbers(OTPseudonym &theNym)

The documentation for this class was generated from the following files: