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

#include <OTTransaction.hpp>

Inheritance diagram for opentxs::OTTransaction:
Collaboration diagram for opentxs::OTTransaction:

Public Types

enum  transactionType {
  blank, message, notice, replyNotice,
  successNotice, pending, transferReceipt, chequeReceipt,
  voucherReceipt, marketReceipt, paymentReceipt, finalReceipt,
  basketReceipt, instrumentNotice, instrumentRejection, processNymbox,
  atProcessNymbox, processInbox, atProcessInbox, transfer,
  atTransfer, deposit, atDeposit, withdrawal,
  atWithdrawal, marketOffer, atMarketOffer, paymentPlan,
  atPaymentPlan, smartContract, atSmartContract, cancelCronItem,
  atCancelCronItem, exchangeBasket, atExchangeBasket, payDividend,
  atPayDividend, error_state
}
 

Public Member Functions

 OTTransaction (const OTLedger &theOwner)
 
EXPORT OTTransaction (const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID)
 
 OTTransaction (const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, int64_t lTransactionNum)
 
 OTTransaction (const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, const int64_t &lNumberOfOrigin, const int64_t &lTransactionNum, const int64_t &lInRefTo, const int64_t &lInRefDisplay, time64_t the_DATE_SIGNED, transactionType theType, const OTString &strHash, const int64_t &lAdjustment, const int64_t &lDisplayValue, const int64_t &lClosingNum, const int64_t &lRequestNum, bool bReplyTransSuccess, OTNumList *pNumList=nullptr)
 
virtual EXPORT ~OTTransaction ()
 
virtual void Release ()
 
virtual EXPORT int64_t GetNumberOfOrigin ()
 
virtual EXPORT void CalculateNumberOfOrigin ()
 
virtual bool VerifyAccount (const OTPseudonym &theNym)
 
virtual bool SaveContractWallet (std::ofstream &ofs) const
 
void InitTransaction ()
 
EXPORT bool IsCancelled ()
 
EXPORT void SetAsCancelled ()
 
void SetParent (const OTLedger &theParent)
 
EXPORT bool AddNumbersToTransaction (const OTNumList &theAddition)
 
bool IsAbbreviated () const
 
int64_t GetAbbrevAdjustment () const
 
void SetAbbrevAdjustment (int64_t lAmount)
 
int64_t GetAbbrevDisplayAmount () const
 
void SetAbbrevDisplayAmount (int64_t lAmount)
 
int64_t GetAbbrevInRefDisplay () const
 
void SetAbbrevInRefDisplay (int64_t lAmount)
 
const int64_t & GetRequestNum () const
 
void SetRequestNum (const int64_t &lNum)
 
bool GetReplyTransSuccess ()
 
void SetReplyTransSuccess (bool bVal)
 
EXPORT int64_t GetClosingNum () const
 
EXPORT void SetClosingNum (int64_t lClosingNum)
 
EXPORT int64_t GetReferenceNumForDisplay ()
 
EXPORT bool GetSenderUserIDForDisplay (OTIdentifier &theReturnID)
 
EXPORT bool GetRecipientUserIDForDisplay (OTIdentifier &theReturnID)
 
EXPORT bool GetSenderAcctIDForDisplay (OTIdentifier &theReturnID)
 
EXPORT bool GetRecipientAcctIDForDisplay (OTIdentifier &theReturnID)
 
EXPORT bool GetMemo (OTString &strMemo)
 
time64_t GetDateSigned () const
 
EXPORT bool GetSuccess ()
 
EXPORT int64_t GetReceiptAmount ()
 
transactionType GetType () const
 
void SetType (transactionType theType)
 
EXPORT bool SaveBoxReceipt (int64_t lLedgerType)
 
EXPORT bool SaveBoxReceipt (OTLedger &theLedger)
 
EXPORT bool DeleteBoxReceipt (OTLedger &theLedger)
 
bool VerifyBoxReceipt (OTTransaction &theFullVersion)
 
EXPORT bool VerifyBalanceReceipt (OTPseudonym &SERVER_NYM, OTPseudonym &THE_NYM)
 
EXPORT bool VerifyItems (OTPseudonym &theNym)
 
int32_t GetItemCount () const
 
int32_t GetItemCountInRefTo (int64_t lReference)
 
EXPORT OTItemGetItem (OTItem::itemType theType)
 
EXPORT OTItemGetItemInRefTo (int64_t lReference)
 
EXPORT void AddItem (OTItem &theItem)
 
listOfItemsGetItemList ()
 
void SaveAbbreviatedNymboxRecord (OTString &strOutput)
 
void SaveAbbreviatedOutboxRecord (OTString &strOutput)
 
void SaveAbbreviatedInboxRecord (OTString &strOutput)
 
void SaveAbbrevPaymentInboxRecord (OTString &strOutput)
 
void SaveAbbrevRecordBoxRecord (OTString &strOutput)
 
void SaveAbbrevExpiredBoxRecord (OTString &strOutput)
 
void ProduceInboxReportItem (OTItem &theBalanceItem)
 
void ProduceOutboxReportItem (OTItem &theBalanceItem)
 
const char * GetTypeString () const
 
bool HarvestOpeningNumber (OTPseudonym &theNym, bool bHarvestingForRetry, bool bReplyWasSuccess, bool bReplyWasFailure, bool bTransactionWasSuccess, bool bTransactionWasFailure)
 
bool HarvestClosingNumbers (OTPseudonym &theNym, bool bHarvestingForRetry, bool bReplyWasSuccess, bool bReplyWasFailure, bool bTransactionWasSuccess, bool bTransactionWasFailure)
 
- Public Member Functions inherited from opentxs::OTTransactionType
EXPORT void GetNumList (OTNumList &theOutput)
 
bool Contains (const OTString &strContains)
 
EXPORT bool Contains (const char *szContains)
 
bool IsSameAccount (const OTTransactionType &rhs) const
 
void SetLoadInsecure ()
 
const OTIdentifierGetUserID () const
 
void SetUserID (const OTIdentifier &theID)
 
const OTIdentifierGetRealAccountID () const
 
void SetRealAccountID (const OTIdentifier &theID)
 
const OTIdentifierGetPurportedAccountID () const
 
void SetPurportedAccountID (const OTIdentifier &theID)
 
const OTIdentifierGetRealServerID () const
 
void SetRealServerID (const OTIdentifier &theID)
 
const OTIdentifierGetPurportedServerID () const
 
void SetPurportedServerID (const OTIdentifier &theID)
 
virtual EXPORT bool VerifyContractID () const
 
 OTTransactionType (const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID)
 
 OTTransactionType (const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, int64_t lTransactionNum)
 
void InitTransactionType ()
 
virtual ~OTTransactionType ()
 
void Release_TransactionType ()
 
EXPORT int64_t GetTransactionNum () const
 
void SetTransactionNum (int64_t lTransactionNum)
 
EXPORT int64_t GetRawNumberOfOrigin () const
 
EXPORT void SetNumberOfOrigin (int64_t lTransactionNum)
 
EXPORT void SetNumberOfOrigin (OTTransactionType &setFrom)
 
EXPORT bool VerifyNumberOfOrigin (OTTransactionType &compareTo)
 
EXPORT int64_t GetReferenceToNum () const
 
EXPORT void SetReferenceToNum (int64_t lTransactionNum)
 
EXPORT void GetReferenceString (OTString &theStr) const
 
EXPORT void SetReferenceString (const OTString &theStr)
 
- 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 void CalculateContractID (OTIdentifier &newID) 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 EXPORT OTTransactionGenerateTransaction (const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, transactionType theType, int64_t lTransactionNum=0)
 
static EXPORT OTTransactionGenerateTransaction (const OTLedger &theOwner, transactionType theType, int64_t lTransactionNum=0)
 
static transactionType GetTypeFromString (const OTString &strType)
 
- Static Public Member Functions inherited from opentxs::OTTransactionType
static EXPORT OTTransactionTypeTransactionFactory (OTString strInput)
 
- 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 int32_t ProcessXMLNode (irr::io::IrrXMLReader *&xml)
 
virtual void UpdateContents ()
 
 OTTransaction ()
 
- Protected Member Functions inherited from opentxs::OTTransactionType
 OTTransactionType ()
 
- Protected Member Functions inherited from opentxs::OTContract
bool LoadContractXML ()
 

Protected Attributes

const OTLedgerm_pParent
 
bool m_bIsAbbreviated
 
int64_t m_lAbbrevAmount
 
int64_t m_lDisplayAmount
 
int64_t m_lInRefDisplay
 
OTIdentifier m_Hash
 
time64_t m_DATE_SIGNED
 
transactionType m_Type
 
listOfItems m_listItems
 
int64_t m_lClosingTransactionNo
 
OTASCIIArmor m_ascCancellationRequest
 
int64_t m_lRequestNumber
 
bool m_bReplyTransSuccess
 
bool m_bCancelled
 
- Protected Attributes inherited from opentxs::OTTransactionType
OTIdentifier m_AcctID
 
OTIdentifier m_ServerID
 
OTIdentifier m_AcctServerID
 
OTIdentifier m_AcctUserID
 
int64_t m_lTransactionNum
 
int64_t m_lInReferenceToTransaction
 
int64_t m_lNumberOfOrigin
 
OTASCIIArmor m_ascInReferenceTo
 
bool m_bLoadSecurely
 
OTNumList m_Numlist
 
- 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
 

Friends

OTTransactionTypeOTTransactionType::TransactionFactory (OTString strInput)
 

Detailed Description

Definition at line 440 of file OTTransaction.hpp.

Member Enumeration Documentation

Enumerator
blank 
message 
notice 
replyNotice 
successNotice 
pending 
transferReceipt 
chequeReceipt 
voucherReceipt 
marketReceipt 
paymentReceipt 
finalReceipt 
basketReceipt 
instrumentNotice 
instrumentRejection 
processNymbox 
atProcessNymbox 
processInbox 
atProcessInbox 
transfer 
atTransfer 
deposit 
atDeposit 
withdrawal 
atWithdrawal 
marketOffer 
atMarketOffer 
paymentPlan 
atPaymentPlan 
smartContract 
atSmartContract 
cancelCronItem 
atCancelCronItem 
exchangeBasket 
atExchangeBasket 
payDividend 
atPayDividend 
error_state 

Definition at line 450 of file OTTransaction.hpp.

450  {
451  // ***** INBOX / OUTBOX / NYMBOX
452 
453  // NYMBOX
454  blank, // freshly issued transaction number, not used yet
455  // (the server drops these into the nymbox.)
456  message, // A message from one user to another, also in the nymbox.
457  notice, // A notice from the server. Used in Nymbox.
458  replyNotice, // A copy of a server reply to a previous request you sent.
459  // (To make SURE you get the reply.)
460  successNotice, // A transaction # has successfully been signed out.
461 
462  // INBOX / OUTBOX (pending transfer)
463  pending, // Server puts this in your outbox (when sending) and
464  // recipient's inbox.
465 
466  // INBOX / receipts
467  transferReceipt, // the server drops this into your inbox, when someone
468  // accepts your transfer.
469  chequeReceipt, // the server drops this into your inbox, when someone
470  // deposits your cheque.
471  voucherReceipt, // the server drops this into your inbox, when someone
472  // deposits your voucher.
473  marketReceipt, // server periodically drops this into your inbox if an
474  // offer is live.
475  paymentReceipt, // the server drops this into people's inboxes, every
476  // time a payment processes. (from a payment plan or a
477  // smart contract)
478  finalReceipt, // the server drops this into your in/nym box(es), when a
479  // CronItem expires or is canceled.
480  basketReceipt, // the server drops this into your inboxes, when a basket
481  // exchange is processed.
482 
483  // PAYMENT INBOX / PAYMENT OUTBOX / RECORD BOX
484  instrumentNotice, // Receive these in paymentInbox (by way of Nymbox),
485  // and send in Outpayments (like Outmail).) (When
486  // done, they go to recordBox or expiredBox to await
487  // deletion.)
488  instrumentRejection, // When someone rejects your invoice from his
489  // paymentInbox, you get one of these in YOUR
490  // paymentInbox.
491 
492  // **** MESSAGES ****
493  processNymbox, // process nymbox transaction // comes from client
494  atProcessNymbox, // process nymbox reply // comes from
495  // server
496  processInbox, // process inbox transaction // comes from client
497  atProcessInbox, // process inbox reply // comes from server
498  transfer, // or "spend". This transaction is a request to transfer from
499  // one account to another
500  atTransfer, // reply from the server regarding a transfer request
501  deposit, // this transaction is a deposit (cash or cheque)
502  atDeposit, // reply from the server regarding a deposit request
503  withdrawal, // this transaction is a withdrawal (cash or voucher)
504  atWithdrawal, // reply from the server regarding a withdrawal request
505  marketOffer, // this transaction is a market offer
506  atMarketOffer, // reply from the server regarding a market offer
507  paymentPlan, // this transaction is a payment plan
508  atPaymentPlan, // reply from the server regarding a payment plan
509  smartContract, // this transaction is a smart contract
510  atSmartContract, // reply from the server regarding a smart contract
511  cancelCronItem, // this transaction is intended to cancel a market offer
512  // or payment plan.
513  atCancelCronItem, // reply from the server regarding said cancellation.
514  exchangeBasket, // this transaction is an exchange in/out of a basket
515  // currency.
516  atExchangeBasket, // reply from the server regarding said exchange.
517  payDividend, // this transaction is dividend payment (to all
518  // shareholders...)
519  atPayDividend, // reply from the server regarding said dividend payment.
521  }; // If you add any types to this list, update the list of strings at the

Constructor & Destructor Documentation

opentxs::OTTransaction::OTTransaction ( const OTLedger theOwner)

Definition at line 3244 of file OTTransaction.cpp.

3245  : OTTransactionType(theOwner.GetUserID(), theOwner.GetPurportedAccountID(),
3246  theOwner.GetPurportedServerID())
3247  , m_pParent(&theOwner)
3248  , m_bIsAbbreviated(false)
3249  , m_lAbbrevAmount(0)
3250  , m_lDisplayAmount(0)
3251  , m_lInRefDisplay(0)
3255  , m_lRequestNumber(0)
3256  , m_bReplyTransSuccess(false)
3257  , m_bCancelled(false)
3258 {
3259  InitTransaction();
3260 }
const OTLedger * m_pParent
transactionType m_Type
#define OT_TIME_ZERO
Definition: Common.hpp:180
opentxs::OTTransaction::OTTransaction ( const OTIdentifier theUserID,
const OTIdentifier theAccountID,
const OTIdentifier theServerID 
)

Definition at line 3272 of file OTTransaction.cpp.

3275  : OTTransactionType(theUserID, theAccountID, theServerID)
3276  , m_pParent(nullptr)
3277  , m_bIsAbbreviated(false)
3278  , m_lAbbrevAmount(0)
3279  , m_lDisplayAmount(0)
3280  , m_lInRefDisplay(0)
3284  , m_lRequestNumber(0)
3285  , m_bReplyTransSuccess(false)
3286  , m_bCancelled(false)
3287 {
3288  InitTransaction();
3289 
3290  // m_AcctID = theID; // these must be loaded or generated. NOT
3291  // set in constructor, for security reasons.
3292  // m_ServerID = theServerID; // There are only here in ghostly form
3293  // as a WARNING to you!
3294 }
const OTLedger * m_pParent
transactionType m_Type
#define OT_TIME_ZERO
Definition: Common.hpp:180
opentxs::OTTransaction::OTTransaction ( const OTIdentifier theUserID,
const OTIdentifier theAccountID,
const OTIdentifier theServerID,
int64_t  lTransactionNum 
)

Definition at line 3296 of file OTTransaction.cpp.

3300  : OTTransactionType(theUserID, theAccountID, theServerID, lTransactionNum)
3301  , m_pParent(nullptr)
3302  , m_bIsAbbreviated(false)
3303  , m_lAbbrevAmount(0)
3304  , m_lDisplayAmount(0)
3305  , m_lInRefDisplay(0)
3309  , m_lRequestNumber(0)
3310  , m_bReplyTransSuccess(false)
3311  , m_bCancelled(false)
3312 {
3313  InitTransaction();
3314 
3315  // m_lTransactionNum = lTransactionNum; // This is set in
3316  // OTTransactionType's constructor, as are m_ID and m_ServerID
3317  // m_AcctID = theID; // these must be loaded or
3318  // generated. NOT set in constructor, for security reasons.
3319  // m_ServerID = theServerID; // There are only here in
3320  // ghostly form as a WARNING to you!
3321 }
const OTLedger * m_pParent
transactionType m_Type
#define OT_TIME_ZERO
Definition: Common.hpp:180
opentxs::OTTransaction::OTTransaction ( const OTIdentifier theUserID,
const OTIdentifier theAccountID,
const OTIdentifier theServerID,
const int64_t &  lNumberOfOrigin,
const int64_t &  lTransactionNum,
const int64_t &  lInRefTo,
const int64_t &  lInRefDisplay,
time64_t  the_DATE_SIGNED,
transactionType  theType,
const OTString strHash,
const int64_t &  lAdjustment,
const int64_t &  lDisplayValue,
const int64_t &  lClosingNum,
const int64_t &  lRequestNum,
bool  bReplyTransSuccess,
OTNumList pNumList = nullptr 
)

Definition at line 3343 of file OTTransaction.cpp.

3352  : OTTransactionType(theUserID, theAccountID, theServerID, lTransactionNum)
3353  , m_pParent(nullptr)
3354  , m_bIsAbbreviated(true)
3355  , m_lAbbrevAmount(lAdjustment)
3356  , m_lDisplayAmount(lDisplayValue)
3357  , m_lInRefDisplay(lInRefDisplay)
3358  , m_Hash(strHash)
3359  , m_DATE_SIGNED(the_DATE_SIGNED)
3360  , m_Type(theType)
3361  , m_lClosingTransactionNo(lClosingNum)
3362  , m_lRequestNumber(lRequestNum)
3363  , m_bReplyTransSuccess(bReplyTransSuccess)
3364  , m_bCancelled(false)
3365 {
3366  InitTransaction();
3367 
3368  // This gets zeroed out in InitTransaction() above. But since we set it in
3369  // this
3370  // constructor, I'm setting it back again.
3371  // Then why call it? I don't know, convention? For the sake of future
3372  // subclasses?
3373  //
3374  m_bIsAbbreviated = true;
3375  m_DATE_SIGNED = the_DATE_SIGNED;
3376  m_Type = theType; // This one is same story as date signed. Setting it back.
3377  m_lClosingTransactionNo = lClosingNum;
3378  m_lAbbrevAmount = lAdjustment;
3379  m_lDisplayAmount = lDisplayValue;
3380  m_lInRefDisplay = lInRefDisplay;
3381 
3382  m_lRequestNumber = lRequestNum; // for replyNotice
3383  m_bReplyTransSuccess = bReplyTransSuccess; // for replyNotice
3384 
3385  m_Hash.SetString(strHash);
3386  m_lTransactionNum = lTransactionNum; // This is set in OTTransactionType's
3387  // constructor, as are m_ID and
3388  // m_ServerID
3389 
3390  SetReferenceToNum(lInRefTo);
3391  SetNumberOfOrigin(lNumberOfOrigin);
3392 
3393  // NOTE: For THIS CONSTRUCTOR ONLY, we DO set the purported AcctID and
3394  // purported ServerID.
3395  // (AFTER the constructor has executed, in OTLedger::ProcessXMLNode();
3396  //
3397  // WHY? Normally you set the "real" IDs at construction, and then set the
3398  // "purported" IDs
3399  // when loading from string. But this constructor (only this one) is
3400  // actually used when
3401  // loading abbreviated receipts as you load their inbox/outbox/nymbox.
3402  // Abbreviated receipts are not like real transactions, which have serverID,
3403  // AcctID, userID,
3404  // and signature attached, and the whole thing is base64-encoded and then
3405  // added to the ledger
3406  // as part of a list of contained objects. Rather, with abbreviated
3407  // receipts, there are a series
3408  // of XML records loaded up as PART OF the ledger itself. None of these
3409  // individual XML records
3410  // has its own signature, or its own record of the main IDs -- those are
3411  // assumed to be on the parent
3412  // ledger.
3413  // That's the whole point: abbreviated records don't store redundant info,
3414  // and don't each have their
3415  // own signature, because we want them to be as small as possible inside
3416  // their parent ledger.
3417  // Therefore I will pass in the parent ledger's "real" IDs at construction,
3418  // and immediately thereafter
3419  // set the parent ledger's "purported" IDs onto the abbreviated transaction.
3420  // That way, VerifyContractID()
3421  // will still work and do its job properly with these abbreviated records.
3422 
3423  // Note: I'm going to go ahead and set it in here for now. This is a special
3424  // constructor (abbreviated receipt constructor)
3425  // todo: come back to this during security sweep.
3426  //
3427  SetRealAccountID(theAccountID);
3428  SetPurportedAccountID(theAccountID);
3429 
3430  SetRealServerID(theServerID);
3431  SetPurportedServerID(theServerID);
3432 
3433  SetUserID(theUserID);
3434 
3435  if (nullptr != pNumList) m_Numlist = *pNumList;
3436 }
EXPORT void SetNumberOfOrigin(int64_t lTransactionNum)
const OTLedger * m_pParent
void SetRealAccountID(const OTIdentifier &theID)
void SetRealServerID(const OTIdentifier &theID)
EXPORT void SetString(const char *szString)
void SetUserID(const OTIdentifier &theID)
EXPORT void SetReferenceToNum(int64_t lTransactionNum)
void SetPurportedServerID(const OTIdentifier &theID)
transactionType m_Type
void SetPurportedAccountID(const OTIdentifier &theID)
opentxs::OTTransaction::~OTTransaction ( )
virtual

Definition at line 3492 of file OTTransaction.cpp.

3493 {
3494  while (!m_listItems.empty()) {
3495  OTItem* pItem = m_listItems.front();
3496  m_listItems.pop_front();
3497  delete pItem;
3498  }
3499 }
opentxs::OTTransaction::OTTransaction ( )
protected

Definition at line 3220 of file OTTransaction.cpp.

3221  : OTTransactionType()
3222  , m_pParent(nullptr)
3223  , m_bIsAbbreviated(false)
3224  , m_lAbbrevAmount(0)
3225  , m_lDisplayAmount(0)
3226  , m_lInRefDisplay(0)
3230  , m_lRequestNumber(0)
3231  , m_bReplyTransSuccess(false)
3232  , m_bCancelled(false)
3233 {
3234  InitTransaction();
3235 }
const OTLedger * m_pParent
transactionType m_Type
#define OT_TIME_ZERO
Definition: Common.hpp:180

Member Function Documentation

void opentxs::OTTransaction::AddItem ( OTItem theItem)

Definition at line 3515 of file OTTransaction.cpp.

3516 {
3517  m_listItems.push_back(&theItem);
3518 }
bool opentxs::OTTransaction::AddNumbersToTransaction ( const OTNumList theAddition)

Definition at line 4344 of file OTTransaction.cpp.

4345 {
4346  return m_Numlist.Add(theAddition);
4347 }
void opentxs::OTTransaction::CalculateNumberOfOrigin ( )
virtual

Reimplemented from opentxs::OTTransactionType.

Definition at line 5791 of file OTTransaction.cpp.

5792 {
5794 
5795  switch (GetType()) {
5796  case blank: // freshly issued transaction number, not used yet
5797  case message: // A message from one user to another, also in the nymbox.
5798  case notice: // A notice from the server. Used in Nymbox.
5799  case replyNotice: // A copy of a server reply to a previous request you
5800  // sent. (To make SURE you get the reply.)
5801  case successNotice: // A transaction # has successfully been signed out.
5802  case processNymbox: // process nymbox transaction // comes from client
5803  case atProcessNymbox: // process nymbox reply // comes from server
5804  SetNumberOfOrigin(0); // Not applicable.
5805  break;
5806 
5807  case pending: // Server puts this in your outbox (when sending) and
5808  // recipient's inbox.
5809  case marketReceipt: // server periodically drops this into your inbox if an
5810  // offer is live.
5811  case paymentReceipt: // the server drops this into people's inboxes, every
5812  // time a payment processes.
5813  case finalReceipt: // the server drops this into your in/nym box(es), when a
5814  // CronItem expires or is canceled.
5815  case basketReceipt: // the server drops this into your inboxes, when a
5816  // basket exchange is processed.
5817  SetNumberOfOrigin(GetReferenceToNum()); // pending is in
5818  // reference to the
5819  // original
5820  // transfer.
5821  break;
5822 
5823  case transferReceipt: // the server drops this into your inbox, when someone
5824  // accepts your transfer.
5825  case deposit: // this transaction is a deposit (cash or cheque)
5826  case atDeposit: // reply from the server regarding a deposit request
5827  case instrumentNotice: // Receive these in paymentInbox (by way of Nymbox),
5828  // and send in Outpayments.
5829  case instrumentRejection: // When someone rejects your invoice, you get one
5830  // of these in YOUR paymentInbox.
5831  otErr << __FUNCTION__ << ": In this case, you can't calculate the "
5832  "origin number, you must set it explicitly.\n";
5833  SetNumberOfOrigin(0); // Not applicable.
5834  // Comment this out later so people can't use it to crash the server:
5835  OT_FAIL_MSG("In this case, you can't calculate the origin number, you "
5836  "must set it explicitly.");
5837  break;
5838 
5839  case chequeReceipt: // the server drops this into your inbox, when someone
5840  // deposits your cheque.
5841  case voucherReceipt: // the server drops this into your inbox, when someone
5842  // deposits your voucher.
5843  {
5844  OTString strReference;
5845  GetReferenceString(strReference);
5846 
5847  // "In reference to" is the depositor's trans#, which I use here to
5848  // load
5849  // the depositor's
5850  // depositCheque item, which I use to get the cheque, which contains
5851  // the
5852  // number of origin
5853  // as its transaction number.
5854  //
5855  std::unique_ptr<OTItem> pOriginalItem(OTItem::CreateItemFromString(
5856  strReference, GetPurportedServerID(), GetReferenceToNum()));
5857  OT_ASSERT(nullptr != pOriginalItem);
5858 
5859  if (OTItem::depositCheque != pOriginalItem->GetType()) {
5860  otErr << __FUNCTION__ << ": ERROR: Wrong item type attached to "
5861  << ((chequeReceipt == GetType()) ? "chequeReceipt"
5862  : "voucherReceipt")
5863  << " "
5864  "(expected OTItem::depositCheque)\n";
5865  SetNumberOfOrigin(0);
5866  return;
5867  }
5868 
5869  SetNumberOfOrigin(pOriginalItem->GetNumberOfOrigin());
5870  }
5871  break;
5872 
5873  case processInbox: // process inbox transaction // comes from client
5874  case atProcessInbox: // process inbox reply // comes from server
5875 
5876  case transfer: // or "spend". This transaction is a request to transfer from
5877  // one account to another
5878  case atTransfer: // reply from the server regarding a transfer request
5879 
5880  case withdrawal: // this transaction is a withdrawal (cash or voucher)
5881  case atWithdrawal: // reply from the server regarding a withdrawal request
5882 
5883  case marketOffer: // this transaction is a market offer
5884  case atMarketOffer: // reply from the server regarding a market offer
5885 
5886  case paymentPlan: // this transaction is a payment plan
5887  case atPaymentPlan: // reply from the server regarding a payment plan
5888 
5889  case smartContract: // this transaction is a smart contract
5890  case atSmartContract: // reply from the server regarding a smart contract
5891 
5892  case cancelCronItem: // this transaction is intended to cancel a market
5893  // offer or payment plan.
5894  case atCancelCronItem: // reply from the server regarding said cancellation.
5895 
5896  case exchangeBasket: // this transaction is an exchange in/out of a basket
5897  // currency.
5898  case atExchangeBasket: // reply from the server regarding said exchange.
5899 
5900  case payDividend: // this transaction is dividend payment (to all
5901  // shareholders...)
5902  case atPayDividend: // reply from the server regarding said dividend
5903  // payment.
5904 
5905  default:
5907  break;
5908  } // switch
5909 }
EXPORT void GetReferenceString(OTString &theStr) const
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
Definition: OTItem.cpp:1473
EXPORT void SetNumberOfOrigin(int64_t lTransactionNum)
const OTIdentifier & GetPurportedServerID() const
#define OT_ASSERT(x)
Definition: Assert.hpp:150
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
EXPORT int64_t GetReferenceToNum() const
transactionType GetType() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
bool opentxs::OTTransaction::DeleteBoxReceipt ( OTLedger theLedger)

Definition at line 2935 of file OTTransaction.cpp.

2936 {
2937  OTString strFolder1name, strFolder2name, strFolder3name, strFilename;
2938 
2940  theLedger, *this, "OTTransaction::DeleteBoxReceipt", strFolder1name,
2941  strFolder2name, strFolder3name, strFilename))
2942  return false; // This already logs -- no need to log twice, here.
2943 
2944  // See if the box receipt exists before trying to save over it...
2945  //
2946  if (!OTDB::Exists(strFolder1name.Get(), strFolder2name.Get(),
2947  strFolder3name.Get(), strFilename.Get())) {
2948  otInfo
2949  << __FUNCTION__
2950  << ": Box receipt already doesn't exist, thus no need to delete: "
2951  "At location: " << strFolder1name << OTLog::PathSeparator()
2952  << strFolder2name << OTLog::PathSeparator() << strFolder3name
2953  << OTLog::PathSeparator() << strFilename << "\n";
2954  return false;
2955  }
2956 
2957  OTString strFinal;
2958  OTASCIIArmor ascTemp;
2959 
2960  if (m_strRawFile.Exists()) {
2961  ascTemp.SetString(m_strRawFile);
2962 
2963  if (false ==
2964  ascTemp.WriteArmoredString(strFinal, m_strContractType.Get())) {
2965  otErr << __FUNCTION__
2966  << ": Error deleting (writing over) box receipt (failed "
2967  "writing armored string):\n" << strFolder1name
2968  << OTLog::PathSeparator() << strFolder2name
2969  << OTLog::PathSeparator() << strFolder3name
2970  << OTLog::PathSeparator() << strFilename << "\n";
2971  return false;
2972  }
2973  }
2974 
2975  // NOTE: I do the armored string FIRST, THEN add the "marked for deletion"
2976  // part as I save it. (This way, it's still searchable with grep.)
2977 
2978  //
2979  // Try to save the deleted box receipt to local storage.
2980  //
2981  OTString strOutput;
2982 
2983  if (m_strRawFile.Exists())
2984  strOutput.Format("%s\n\n%s\n", strFinal.Get(),
2985  "MARKED_FOR_DELETION"); // todo hardcoded.
2986  else
2987  strOutput.Format("%s\n\n%s\n",
2988  "(Transaction was already empty -- strange.)",
2989  "MARKED_FOR_DELETION"); // todo hardcoded.
2990 
2991  bool bDeleted = OTDB::StorePlainString(
2992  strOutput.Get(), strFolder1name.Get(), strFolder2name.Get(),
2993  strFolder3name.Get(), strFilename.Get());
2994  if (!bDeleted)
2995  otErr << __FUNCTION__
2996  << ": Error deleting (writing over) file: " << strFolder1name
2997  << OTLog::PathSeparator() << strFolder2name
2998  << OTLog::PathSeparator() << strFolder3name
2999  << OTLog::PathSeparator() << strFilename << "\nContents:\n\n"
3000  << m_strRawFile << "\n\n";
3001 
3002  return bDeleted;
3003 }
EXPORT bool StorePlainString(std::string strContents, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:698
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
EXPORT bool Exists() const
Definition: OTString.cpp:1035
OTString m_strContractType
Definition: OTContract.hpp:178
OTLOG_IMPORT OTLogStream otInfo
bool SetupBoxReceiptFilename(int64_t lLedgerType, OTTransaction &theTransaction, const char *szCaller, OTString &strFolder1name, OTString &strFolder2name, OTString &strFolder3name, OTString &strFilename)
Definition: Helpers.cpp:591
EXPORT const char * Get() const
Definition: OTString.cpp:1045
OTLOG_IMPORT OTLogStream otErr
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
OTTransaction * opentxs::OTTransaction::GenerateTransaction ( const OTIdentifier theUserID,
const OTIdentifier theAccountID,
const OTIdentifier theServerID,
transactionType  theType,
int64_t  lTransactionNum = 0 
)
static

Definition at line 3465 of file OTTransaction.cpp.

3469 {
3470  OTTransaction* pTransaction = new OTTransaction(
3471  theUserID, theAccountID, theServerID, lTransactionNum);
3472  OT_ASSERT(nullptr != pTransaction);
3473 
3474  pTransaction->m_Type = theType;
3475 
3476  // Since we're actually generating this transaction, then we can go ahead
3477  // and set the purported account and server IDs (we have already set the
3478  // real ones in the constructor). Now both sets are fill with matching data.
3479  // No need to security check the IDs since we are creating this transaction
3480  // versus loading and inspecting it.
3481  pTransaction->SetPurportedAccountID(theAccountID);
3482  pTransaction->SetPurportedServerID(theServerID);
3483 
3484  return pTransaction;
3485 }
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTTransaction * opentxs::OTTransaction::GenerateTransaction ( const OTLedger theOwner,
transactionType  theType,
int64_t  lTransactionNum = 0 
)
static

Definition at line 3452 of file OTTransaction.cpp.

3455 {
3456  OTTransaction* pTransaction = GenerateTransaction(
3457  theOwner.GetUserID(), theOwner.GetPurportedAccountID(),
3458  theOwner.GetPurportedServerID(), theType, lTransactionNum);
3459  if (nullptr != pTransaction) pTransaction->SetParent(theOwner);
3460 
3461  return pTransaction;
3462 }
static EXPORT OTTransaction * GenerateTransaction(const OTIdentifier &theUserID, const OTIdentifier &theAccountID, const OTIdentifier &theServerID, transactionType theType, int64_t lTransactionNum=0)
void SetParent(const OTLedger &theParent)
int64_t opentxs::OTTransaction::GetAbbrevAdjustment ( ) const
inline

Definition at line 587 of file OTTransaction.hpp.

588  {
589  return m_lAbbrevAmount;
590  }
int64_t opentxs::OTTransaction::GetAbbrevDisplayAmount ( ) const
inline

Definition at line 597 of file OTTransaction.hpp.

598  {
599  return m_lDisplayAmount;
600  }
int64_t opentxs::OTTransaction::GetAbbrevInRefDisplay ( ) const
inline

Definition at line 607 of file OTTransaction.hpp.

608  {
609  return m_lInRefDisplay;
610  }
int64_t opentxs::OTTransaction::GetClosingNum ( ) const

Definition at line 154 of file OTTransaction.cpp.

155 {
157 }
time64_t opentxs::OTTransaction::GetDateSigned ( ) const
inline

Definition at line 658 of file OTTransaction.hpp.

659  {
660  return m_DATE_SIGNED;
661  }
OTItem * opentxs::OTTransaction::GetItem ( OTItem::itemType  theType)

Definition at line 3522 of file OTTransaction.cpp.

3523 {
3524  for (auto& it : m_listItems) {
3525  OTItem* pItem = it;
3526  OT_ASSERT(nullptr != pItem);
3527 
3528  if (pItem->GetType() == theType) return pItem;
3529  }
3530 
3531  return nullptr;
3532 }
#define OT_ASSERT(x)
Definition: Assert.hpp:150
int32_t opentxs::OTTransaction::GetItemCount ( ) const
inline

Definition at line 709 of file OTTransaction.hpp.

710  {
711  return static_cast<int32_t>(m_listItems.size());
712  }
int32_t opentxs::OTTransaction::GetItemCountInRefTo ( int64_t  lReference)

Definition at line 3559 of file OTTransaction.cpp.

3560 {
3561  int32_t nCount = 0;
3562 
3563  for (auto& it : m_listItems) {
3564  OTItem* pItem = it;
3565  OT_ASSERT(nullptr != pItem);
3566 
3567  if (pItem->GetReferenceToNum() == lReference) nCount++;
3568  }
3569 
3570  return nCount;
3571 }
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTItem * opentxs::OTTransaction::GetItemInRefTo ( int64_t  lReference)

Definition at line 3537 of file OTTransaction.cpp.

3538 {
3539  if (GetItemCountInRefTo(lReference) > 1) {
3540  OT_FAIL_MSG("CAN'T USE GetItemInRefTo! (There are multiple items in "
3541  "reference to the same number...) SWITCH to using "
3542  "NumberOfOrigin?");
3543  }
3544 
3545  for (auto& it : m_listItems) {
3546  OTItem* pItem = it;
3547  OT_ASSERT(nullptr != pItem);
3548 
3549  if (pItem->GetReferenceToNum() == lReference) return pItem;
3550  }
3551 
3552  return nullptr;
3553 }
int32_t GetItemCountInRefTo(int64_t lReference)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
listOfItems& opentxs::OTTransaction::GetItemList ( )
inline

Definition at line 731 of file OTTransaction.hpp.

732  {
733  return m_listItems;
734  }
bool opentxs::OTTransaction::GetMemo ( OTString strMemo)

Definition at line 6680 of file OTTransaction.cpp.

6681 {
6682  if (IsAbbreviated()) return false;
6683 
6684  bool bSuccess = false;
6685 
6686  OTItem* pOriginalItem = nullptr;
6687  std::unique_ptr<OTItem> theItemAngel;
6688 
6689  OTString strReference;
6690  GetReferenceString(strReference);
6691 
6692  switch (GetType()) {
6694  OTString strUpdatedCronItem;
6695  OTItem* pItem = GetItem(OTItem::paymentReceipt);
6696 
6697  if (nullptr != pItem)
6698  pItem->GetAttachment(strUpdatedCronItem);
6699  else
6700  otErr << "OTTransaction::" << __FUNCTION__
6701  << ": Failed trying to get paymentReceipt item from "
6702  "paymentReceipt transaction.\n";
6703 
6704  std::unique_ptr<OTCronItem> pCronItem(
6705  OTCronItem::NewCronItem(strUpdatedCronItem));
6706 
6707  OTSmartContract* pSmart =
6708  dynamic_cast<OTSmartContract*>(pCronItem.get());
6709  OTPaymentPlan* pPlan = dynamic_cast<OTPaymentPlan*>(pCronItem.get());
6710 
6711  if (nullptr != pSmart) // if it's a smart contract...
6712  {
6713  // NOTE: smart contracts currently do not have a "memo" field.
6714 
6715  return false;
6716  }
6717  else if (nullptr != pPlan) // else if it is a payment plan.
6718  {
6719  if (pPlan->GetConsideration().Exists())
6720  strMemo.Set(pPlan->GetConsideration());
6721 
6722  return true;
6723  }
6724  else // else if it's any other kind of cron item.
6725  {
6726  otErr
6727  << "OTTransaction::" << __FUNCTION__
6728  << ": Unable to load Cron Item. Should never happen. Receipt: "
6729  << GetTransactionNum() << " Origin: " << GetNumberOfOrigin()
6730  << "\n";
6731  return false;
6732  }
6733  } break; // this break never actually happens. Above always returns, if
6734  // triggered.
6735 
6740  pOriginalItem = OTItem::CreateItemFromString(
6741  strReference, GetPurportedServerID(), GetReferenceToNum());
6742 
6743  if (nullptr != pOriginalItem) theItemAngel.reset(pOriginalItem);
6744 
6745  break;
6746  }
6747  default:
6748  return false;
6749  }
6750 
6751  if (nullptr == pOriginalItem)
6752  return false; // Should never happen, since we always expect one based
6753  // on the transaction type.
6754 
6755  OTCheque theCheque; // allocated on the stack :-)
6756  OTString strAttachment;
6757 
6758  switch (GetType()) {
6760  if (pOriginalItem->GetType() != OTItem::acceptPending) {
6761  otErr << __FUNCTION__
6762  << ": Wrong item type attached to transferReceipt\n";
6763  return false;
6764  }
6765  else {
6766  pOriginalItem->GetNote(strMemo);
6767  bSuccess = strMemo.Exists();
6768  }
6769  } break;
6770 
6773  if (pOriginalItem->GetType() != OTItem::depositCheque) {
6774  otErr << __FUNCTION__ << ": Wrong item type attached to "
6776  ? "chequeReceipt"
6777  : "voucherReceipt") << " (expected depositCheque)\n";
6778  return false;
6779  }
6780  else {
6781  OTCheque theCheque;
6782  OTString strCheque;
6783  pOriginalItem->GetAttachment(strCheque);
6784 
6785  if (!((strCheque.GetLength() > 2) &&
6786  theCheque.LoadContractFromString(strCheque))) {
6787  otErr << __FUNCTION__
6788  << ": Error loading cheque or voucher from string:\n"
6789  << strCheque << "\n";
6790  return false;
6791  }
6792 
6793  // Success loading the cheque.
6794  strMemo = theCheque.GetMemo();
6795  bSuccess = strMemo.Exists();
6796  }
6797  } break;
6798 
6800 
6801  if (pOriginalItem->GetType() != OTItem::transfer) {
6802  otErr << __FUNCTION__
6803  << ": Wrong item type attached to pending transfer\n";
6804  }
6805  else {
6806  pOriginalItem->GetNote(strMemo);
6807  bSuccess = strMemo.Exists();
6808  }
6809  break;
6810 
6811  default:
6812  return false;
6813  }
6814 
6815  return bSuccess;
6816 }
EXPORT void GetReferenceString(OTString &theStr) const
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
Definition: OTItem.cpp:1473
virtual EXPORT int64_t GetNumberOfOrigin()
EXPORT OTItem * GetItem(OTItem::itemType theType)
const OTIdentifier & GetPurportedServerID() const
EXPORT int64_t GetReferenceToNum() const
transactionType GetType() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
static EXPORT OTCronItem * NewCronItem(const OTString &strCronItem)
Definition: OTCronItem.cpp:165
int64_t opentxs::OTTransaction::GetNumberOfOrigin ( )
virtual

Reimplemented from opentxs::OTTransactionType.

Definition at line 5758 of file OTTransaction.cpp.

5759 {
5760 
5761  if (0 == m_lNumberOfOrigin) {
5762  switch (GetType()) {
5763  case transferReceipt: // the server drops this into your inbox, when
5764  // someone accepts your transfer.
5765  case deposit: // this transaction is a deposit (cash or cheque)
5766  case atDeposit: // reply from the server regarding a deposit request
5767  case instrumentNotice: // Receive these in paymentInbox (by way of
5768  // Nymbox), and send in Outpayments.
5769  case instrumentRejection: // When someone rejects your invoice, you get
5770  // one of these in YOUR paymentInbox.
5771 
5772  otErr << __FUNCTION__ << ": In this case, you can't calculate the "
5773  "origin number, you must set it "
5774  "explicitly.\n";
5775  SetNumberOfOrigin(0); // Not applicable.
5776  // Comment this out later so people can't use it to crash the
5777  // server:
5778  OT_FAIL_MSG("In this case, you can't calculate the origin number, "
5779  "you must set it explicitly.");
5780  break;
5781  default:
5782  break;
5783  }
5784 
5786  }
5787 
5788  return m_lNumberOfOrigin;
5789 }
EXPORT void SetNumberOfOrigin(int64_t lTransactionNum)
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
transactionType GetType() const
OTLOG_IMPORT OTLogStream otErr
virtual EXPORT void CalculateNumberOfOrigin()
int64_t opentxs::OTTransaction::GetReceiptAmount ( )

Definition at line 5561 of file OTTransaction.cpp.

5562 {
5563  if (IsAbbreviated()) return GetAbbrevAdjustment();
5564 
5565  int64_t lAdjustment = 0;
5566 
5567  OTItem* pOriginalItem = nullptr;
5568  std::unique_ptr<OTItem> theItemAngel;
5569 
5570  switch (GetType()) { // These are the types that have an amount (somehow)
5571  case OTTransaction::marketReceipt: // amount is stored on ** marketReceipt
5572  // item **, on MY LIST of items.
5573  pOriginalItem = GetItem(OTItem::marketReceipt); // (The Reference string
5574  // contains an
5575  // OTCronItem with the
5576  // Original Trade.)
5577  break; // The "reference to" ID is
5578  case OTTransaction::paymentReceipt: // amount is stored on ** paymentReceipt
5579  // ** item, on MY LIST of items.
5580  pOriginalItem = GetItem(OTItem::paymentReceipt);
5581  break;
5582  case OTTransaction::basketReceipt: // amount is stored on ** basketReceipt
5583  // ** item, on MY LIST of items.
5584  pOriginalItem = GetItem(OTItem::basketReceipt);
5585  break;
5586  case OTTransaction::pending: // amount is stored on the ** transfer item **,
5587  // here as reference string.
5588  case OTTransaction::chequeReceipt: // amount is stored on *cheque* (attached
5589  // to ** depositCheque ITEM **, which is
5590  // here as reference string.)
5591  case OTTransaction::voucherReceipt: // amount is stored on *voucher*
5592  // (attached to ** depositCheque ITEM
5593  // **, which is here as reference string.)
5594  case OTTransaction::transferReceipt: // amount is stored on ** acceptPending
5595  // ITEM **, (here as reference string.)
5596  {
5597  OTString strReference;
5598  GetReferenceString(strReference);
5599 
5600  pOriginalItem = OTItem::CreateItemFromString(
5601  strReference, GetPurportedServerID(), GetReferenceToNum());
5602 
5603  if (nullptr != pOriginalItem) theItemAngel.reset(pOriginalItem);
5604 
5605  break;
5606  }
5607 
5608  default: // All other types have no amount -- return 0.
5609  return 0;
5610  }
5611 
5612  if (nullptr == pOriginalItem) {
5613  otErr << "OTTransaction::" << __FUNCTION__
5614  << ": Unable to find original item. Should never happen.\n";
5615  return 0; // Should never happen, since we always expect one based on
5616  // the transaction type.
5617  }
5618 
5619  OTString strAttachment;
5620  OTCheque theCheque; // allocated on the stack :-)
5621 
5622  switch (GetType()) { // These are the types that have an amount (somehow)
5623  case OTTransaction::chequeReceipt: // amount is stored on cheque (attached
5624  // to depositCheque item, attached.)
5625  case OTTransaction::voucherReceipt: // amount is stored on voucher (attached
5626  // to depositCheque item, attached.)
5627  {
5628  if (pOriginalItem->GetType() != OTItem::depositCheque) {
5629  otErr << __FUNCTION__ << ": Wrong item type attached to "
5631  ? "chequeReceipt"
5632  : "voucherReceipt")
5633  << ". (expected depositCheque)\n";
5634  return 0;
5635  }
5636 
5637  // Get the cheque from the Item and load it up into a Cheque object.
5638  pOriginalItem->GetAttachment(strAttachment);
5639  bool bLoadContractFromString =
5640  theCheque.LoadContractFromString(strAttachment);
5641 
5642  if (!bLoadContractFromString) {
5643  OTString strCheque(theCheque);
5644 
5645  otErr << "ERROR loading cheque from string in OTTransaction::"
5646  << __FUNCTION__ << ":\n" << strCheque << "\n";
5647  }
5648  else {
5649  lAdjustment =
5650  (theCheque.GetAmount() * (-1)); // a cheque reduces my
5651  // balance, unless
5652  // it's negative.
5653  } // So if I wrote a 100 clam cheque, that means -100 hit my
5654  // account
5655  // when I got the
5656  // chequeReceipt, and writing a -100c cheque means 100 went in when
5657  // I
5658  // got the chequeReceipt.
5659  }
5660  break;
5661 
5662  // NOTE: a voucherReceipt (above) doesn't actually change your balance,
5663  // and neither does a transferReceipt. (below) But they both have a
5664  // "receipt amount" for display purposes.
5665 
5666  case OTTransaction::transferReceipt: // amount is stored on acceptPending
5667  // item. (Server refuses acceptPendings
5668  // with wrong amount on them.)
5669 
5670  if (pOriginalItem->GetType() != OTItem::acceptPending) {
5671  otErr << "Wrong item type attached to transferReceipt\n";
5672  }
5673  else { // If I transfer 100 clams to someone, then my account is
5674  // smaller by 100 clams. -100 has hit my account.
5675  // So the pending will show as -100 in my outbox, not 100, because
5676  // that is the adjustment actually made to my account.
5677  // This positive/negative aspect of pending transactions is not
5678  // stored in the data itself, since it switches based
5679  // on whether the pending appears in the inbox or the outbox. It's
5680  // based on context. Whereas the transferReceipt
5681  // is IN REFERENCE TO that same transaction--it appears in my inbox
5682  // when the recipient accepts the pending transfer
5683  // I sent him.) Therefore the transferReceipt is "worth" -100 (just
5684  // as the pending in my outbox was "worth" -100), even
5685  // though its actual value is 0.
5686  // (Since the transferReceipt itself doesn't change my balance, but
5687  // merely is a notice that such has happened.) You could
5688  // say, for example in the SaveAbbreviatedToInbox() function, that
5689  // the transferReceipt has an "actual value" of 0 and a
5690  // "display value" of -100 clams, when it is in reference to an
5691  // original transfer of 100 clams.
5692  // This function is clearly returning the display value, since the
5693  // actual value (of 0) is useless, since balance
5694  // agreements already discount transferReceipts as having any impact
5695  // on the balance.
5696  //
5697  lAdjustment = (pOriginalItem->GetAmount() * (-1));
5698  }
5699  break;
5700  case OTTransaction::pending: // amount is stored on transfer item
5701 
5702  if (pOriginalItem->GetType() != OTItem::transfer) {
5703  otErr << "Wrong item type attached to pending transfer\n";
5704  }
5705  else {
5706  // Pending transfer adds to my account if this is inbox, and removes
5707  // if outbox.
5708  // I'll let the caller multiply by (-1) or not. His choice.
5709  // Note: Indeed, if you look in ProduceOutboxReportItem(), it is
5710  // multiplying by (-1).
5711  lAdjustment = pOriginalItem->GetAmount();
5712  }
5713  break;
5714  case OTTransaction::marketReceipt: // amount is stored on marketReceipt item
5715 
5716  if (pOriginalItem->GetType() != OTItem::marketReceipt) {
5717  otErr << "Wrong item type attached to marketReceipt\n";
5718  }
5719  else {
5720  lAdjustment = pOriginalItem->GetAmount(); // THIS WILL ALSO USE THE
5721  // POSITIVE / NEGATIVE
5722  // THING. (Already.)
5723  }
5724  break;
5725  case OTTransaction::paymentReceipt: // amount is stored on paymentReceipt
5726  // item
5727 
5728  if (pOriginalItem->GetType() != OTItem::paymentReceipt) {
5729  otErr << "Wrong item type attached to paymentReceipt\n";
5730  }
5731  else {
5732  lAdjustment = pOriginalItem->GetAmount(); // THIS WILL ALSO USE THE
5733  // POSITIVE / NEGATIVE
5734  // THING. (Already.)
5735  }
5736  break;
5737  case OTTransaction::basketReceipt: // amount is stored on basketReceipt item
5738 
5739  if (pOriginalItem->GetType() != OTItem::basketReceipt) {
5740  otErr << "Wrong item type attached to basketReceipt\n";
5741  }
5742  else {
5743  lAdjustment = pOriginalItem->GetAmount(); // THIS WILL ALSO USE THE
5744  // POSITIVE / NEGATIVE
5745  // THING. (Already.)
5746  }
5747 
5748  break;
5749  default: // All other types have no amount -- return 0.
5750  return 0;
5751  }
5752 
5753  return lAdjustment;
5754 }
EXPORT void GetReferenceString(OTString &theStr) const
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
Definition: OTItem.cpp:1473
int64_t GetAbbrevAdjustment() const
EXPORT OTItem * GetItem(OTItem::itemType theType)
const OTIdentifier & GetPurportedServerID() const
EXPORT int64_t GetReferenceToNum() const
transactionType GetType() const
OTLOG_IMPORT OTLogStream otErr
bool IsAbbreviated() const
bool opentxs::OTTransaction::GetRecipientAcctIDForDisplay ( OTIdentifier theReturnID)

Definition at line 6550 of file OTTransaction.cpp.

6551 {
6552  if (IsAbbreviated()) return false;
6553 
6554  bool bSuccess = false;
6555 
6556  OTItem* pOriginalItem = nullptr;
6557  std::unique_ptr<OTItem> theItemAngel;
6558 
6559  OTString strReference;
6560  GetReferenceString(strReference);
6561 
6562  switch (GetType()) {
6564  OTString strUpdatedCronItem;
6565  OTItem* pItem = GetItem(OTItem::paymentReceipt);
6566 
6567  if (nullptr != pItem)
6568  pItem->GetAttachment(strUpdatedCronItem);
6569  else
6570  otErr << "OTTransaction::" << __FUNCTION__
6571  << ": Failed trying to get paymentReceipt item from "
6572  "paymentReceipt transaction.\n";
6573 
6574  std::unique_ptr<OTCronItem> pCronItem(
6575  OTCronItem::NewCronItem(strUpdatedCronItem));
6576 
6577  OTSmartContract* pSmart =
6578  dynamic_cast<OTSmartContract*>(pCronItem.get());
6579  OTPaymentPlan* pPlan = dynamic_cast<OTPaymentPlan*>(pCronItem.get());
6580 
6581  if (nullptr != pSmart) // if it's a smart contract...
6582  {
6583  if (!pSmart->GetLastRecipientAcctID().Exists()) return false;
6584 
6585  theReturnID.SetString(pSmart->GetLastRecipientAcctID());
6586  return true;
6587  }
6588  else if (nullptr != pPlan) // else if it's a payment plan.
6589  {
6590  theReturnID = pPlan->GetRecipientAcctID();
6591  return true;
6592  }
6593  else // else if it is any other kind of cron item...
6594  {
6595  otErr
6596  << "OTTransaction::" << __FUNCTION__
6597  << ": Unable to load Cron Item. Should never happen. Receipt: "
6598  << GetTransactionNum() << " Origin: " << GetNumberOfOrigin()
6599  << "\n";
6600  return false;
6601  }
6602  } break; // this break never actually happens. Above always returns, if
6603  // triggered.
6604 
6609  pOriginalItem = OTItem::CreateItemFromString(
6610  strReference, GetPurportedServerID(), GetReferenceToNum());
6611 
6612  if (nullptr != pOriginalItem) theItemAngel.reset(pOriginalItem);
6613 
6614  break;
6615  }
6616  default: // All other types have no amount -- return 0.
6617  return false;
6618  }
6619 
6620  if (nullptr == pOriginalItem)
6621  return false; // Should never happen, since we always expect one based
6622  // on the transaction type.
6623 
6624  OTCheque theCheque; // allocated on the stack :-)
6625  OTString strAttachment;
6626 
6627  switch (GetType()) {
6629  if (pOriginalItem->GetType() != OTItem::acceptPending) {
6630  otErr << "Wrong item type attached to transferReceipt\n";
6631  return false;
6632  }
6633  else {
6634  theReturnID = pOriginalItem->GetPurportedAccountID();
6635  bSuccess = true;
6636  }
6637  } break;
6638 
6641  if (pOriginalItem->GetType() != OTItem::depositCheque) {
6642  otErr << __FUNCTION__ << ": Wrong item type attached to "
6644  ? "chequeReceipt"
6645  : "voucherReceipt") << " (expected depositCheque)\n";
6646  return false;
6647  }
6648  else {
6649  theReturnID = pOriginalItem->GetPurportedAccountID(); // Here's the
6650  // depositor's account
6651  // ID (even though the
6652  // cheque was made out
6653  // to a user, not an
6654  // account, it still
6655  // eventually had to be
6656  // DEPOSITED into an
6657  // account... right?)
6658  bSuccess = true;
6659  }
6660  } break;
6661 
6662  case OTTransaction::pending: // amount is stored on transfer item
6663 
6664  if (pOriginalItem->GetType() != OTItem::transfer) {
6665  otErr << "Wrong item type attached to pending transfer\n";
6666  }
6667  else {
6668  theReturnID = pOriginalItem->GetDestinationAcctID();
6669  bSuccess = true;
6670  }
6671  break;
6672 
6673  default: // All other types have no amount -- return 0.
6674  return false;
6675  }
6676 
6677  return bSuccess;
6678 }
EXPORT void GetReferenceString(OTString &theStr) const
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
Definition: OTItem.cpp:1473
virtual EXPORT int64_t GetNumberOfOrigin()
EXPORT OTItem * GetItem(OTItem::itemType theType)
const OTIdentifier & GetPurportedServerID() const
EXPORT int64_t GetReferenceToNum() const
transactionType GetType() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
static EXPORT OTCronItem * NewCronItem(const OTString &strCronItem)
Definition: OTCronItem.cpp:165
bool opentxs::OTTransaction::GetRecipientUserIDForDisplay ( OTIdentifier theReturnID)

Definition at line 6219 of file OTTransaction.cpp.

6220 {
6221  if (IsAbbreviated()) return false;
6222 
6223  bool bSuccess = false;
6224 
6225  OTItem* pOriginalItem = nullptr;
6226  std::unique_ptr<OTItem> theItemAngel;
6227 
6228  OTString strReference;
6229  GetReferenceString(strReference);
6230 
6231  switch (GetType()) {
6232  case OTTransaction::paymentReceipt: // Used for paymentPlans AND for smart
6233  // contracts...
6234  {
6235  OTString strUpdatedCronItem;
6236  OTItem* pItem = GetItem(OTItem::paymentReceipt);
6237 
6238  if (nullptr != pItem)
6239  pItem->GetAttachment(strUpdatedCronItem);
6240  else
6241  otErr << "OTTransaction::" << __FUNCTION__
6242  << ": Failed trying to get paymentReceipt item from "
6243  "paymentReceipt transaction.\n";
6244 
6245  std::unique_ptr<OTCronItem> pCronItem(
6246  OTCronItem::NewCronItem(strUpdatedCronItem));
6247 
6248  OTSmartContract* pSmart =
6249  dynamic_cast<OTSmartContract*>(pCronItem.get());
6250  OTPaymentPlan* pPlan =
6251  dynamic_cast<OTPaymentPlan*>(pCronItem.get());
6252 
6253  if (nullptr != pSmart) // if it's a smart contract...
6254  {
6255  if (!pSmart->GetLastRecipientUserID().Exists()) return false;
6256 
6257  theReturnID.SetString(pSmart->GetLastRecipientUserID());
6258  return true;
6259  }
6260  else if (nullptr !=
6261  pPlan) // else if it is any other kind of cron item...
6262  {
6263  theReturnID = pPlan->GetRecipientUserID();
6264  return true;
6265  }
6266  else {
6267  otErr << "OTTransaction::" << __FUNCTION__
6268  << ": Unable to load Cron Item. Should never happen. "
6269  "Receipt: " << GetTransactionNum()
6270  << " Origin: " << GetNumberOfOrigin() << "\n";
6271  return false;
6272  }
6273  }
6274  break; // this break never actually happens. Above always returns, if
6275  // triggered.
6276 
6278  /*
6279  Therefore, if I am looping through my Nymbox, iterating through
6280  transactions, and one of them
6281  is an *** instrumentNotice *** then I should expect
6282  GetReferenceString(strOutput) to:
6283 
6284  1. load up from string as an OTMessage of type "sendUserInstrument",
6285  -------------------------------------------------------------------
6286  2. and I should expect the PAYLOAD of that message to contain an
6287  encrypted OTEnvelope,
6288  3. which can be decrypted by Msg.m_strNymID2's private key,
6289  4. And the resulting plaintext can be loaded into memory as an
6290  OTPayment object,
6291  5. ...which contains an instrument of ambiguous type.
6292  -------------------------------------------------------------------
6293  FYI:
6294  OTPayment provides a consistent interface, and consolidation of
6295  handling, for
6296  the several financial instruments that appear on the PAYMENTS page, in
6297  the PaymentsInbox.
6298  For example:
6299  [ Cheques, Invoices, Vouchers ],
6300  Payment Plans, Smart Contracts, ...and Purses.
6301  -------------------------------------------------------------------
6302  (In this block we don't need to go any farther than step 1 above.)
6303  -------------------------------------------------------------------
6304  */
6305 
6306  OTMessage theSentMsg;
6307 
6308  if (strReference.Exists() &&
6309  theSentMsg.LoadContractFromString(strReference)) {
6310  // All we need is this message itself. We aren't going to decrypt
6311  // the payload, we're just going to grab the sender/receiver data
6312  // from the msg.
6313  //
6314  // We can't decrypt the payload (the OTPayment object) but we still
6315  // have sender / recipient.
6316  // todo security need to consider security implications of that and
6317  // maybe improve it a bit.
6318  // (But I do NOT want to get into the messaging business.)
6319 
6320  if (theSentMsg.m_strNymID2.Exists()) {
6321  theReturnID.SetString(theSentMsg.m_strNymID2);
6322  return true;
6323  }
6324  }
6325  return false;
6326  } break;
6327 
6331  pOriginalItem = OTItem::CreateItemFromString(
6332  strReference, GetPurportedServerID(), GetReferenceToNum());
6333 
6334  if (nullptr != pOriginalItem) theItemAngel.reset(pOriginalItem);
6335 
6336  break;
6337  }
6338  default: // All other types have no amount -- return false.
6339  return false;
6340  }
6341 
6342  if (nullptr == pOriginalItem)
6343  return false; // Should never happen, since we always expect one based
6344  // on the transaction type.
6345 
6346  OTCheque theCheque; // allocated on the stack :-)
6347  OTString strAttachment;
6348 
6349  switch (GetType()) {
6351  if (pOriginalItem->GetType() != OTItem::acceptPending) {
6352  otErr << "Wrong item type attached to transferReceipt\n";
6353  return false;
6354  }
6355  else {
6356  theReturnID = pOriginalItem->GetUserID(); // Even though a transfer
6357  // has no recipient user
6358  // (just a recipient acct)
6359  // I still get the User ID
6360  // when he accepts it!
6361  bSuccess = true;
6362  }
6363  } break;
6364 
6365  case OTTransaction::chequeReceipt: // amount is stored on cheque (attached
6366  // to depositCheque item, attached.)
6367  case OTTransaction::voucherReceipt: // amount is stored on voucher (attached
6368  // to depositCheque item, attached.)
6369  {
6370  if (pOriginalItem->GetType() != OTItem::depositCheque) {
6371  otErr << __FUNCTION__ << ": Wrong item type attached to "
6373  ? "chequeReceipt"
6374  : "voucherReceipt")
6375  << " (expected depositCheque)\n";
6376  return false;
6377  }
6378 
6379  // Get the cheque from the Item and load it up into a Cheque object.
6380  pOriginalItem->GetAttachment(strAttachment);
6381  bool bLoadContractFromString =
6382  theCheque.LoadContractFromString(strAttachment);
6383 
6384  if (!bLoadContractFromString) {
6385  OTString strCheque(theCheque);
6386 
6387  otErr << "ERROR loading cheque or voucher from string in "
6388  "OTTransaction::" << __FUNCTION__ << ":\n" << strCheque
6389  << "\n";
6390  }
6391  else if (theCheque.HasRecipient()) {
6392  theReturnID = theCheque.GetRecipientUserID();
6393  bSuccess = true;
6394  }
6395  else {
6396  theReturnID =
6397  pOriginalItem->GetUserID(); // Even though the cheque
6398  // has no recipient, I
6399  // still get the User ID
6400  // when he deposits it!
6401  bSuccess = true;
6402  }
6403  }
6404  break;
6405 
6406  default: // All other types have no recipient user ID -- return false.
6407  return false;
6408  }
6409 
6410  return bSuccess;
6411 }
EXPORT void GetReferenceString(OTString &theStr) const
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
Definition: OTItem.cpp:1473
virtual EXPORT int64_t GetNumberOfOrigin()
EXPORT OTItem * GetItem(OTItem::itemType theType)
const OTIdentifier & GetPurportedServerID() const
EXPORT int64_t GetReferenceToNum() const
transactionType GetType() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
static EXPORT OTCronItem * NewCronItem(const OTString &strCronItem)
Definition: OTCronItem.cpp:165
int64_t opentxs::OTTransaction::GetReferenceNumForDisplay ( )

for display purposes. The "reference #" we show the user is not the same one we used internally.

The "display reference #" that we want to display for the User might be different depending on the type.

For example, if pending, then it's in ref to the original transfer request (sender's transaction #) But if chequeReceipt, then it's in reference to the original cheque (also sender's transaction #) But if marketReceipt, then it's in reference to the original market offer (which is my own trans#) But if paymentReceipt, then it's in reference to the original "activate payment plan" request, which may or may not be mine.

Internally of course, a chequeReceipt is "in reference to" the depositor's deposit request. But the user doesn't care about that number – he wants to see the original cheque # from when he first wrote it. Thus we have this function for resolving the "display reference #" in cases like that.

Another example: with market trades, you want the "in reference to" to show the trans# of the original market offer request. Of course, if you load up the item within, you can get the "in reference to" showing a different trans# for EACH TRADE THAT HAS OCCURRED. We use that internally, we need to be able to reference each of those trades. But the user merely wants to see that his receipt is in reference to the original market offer, so he can line up his receipts with his offers. What else does he care?

Definition at line 5945 of file OTTransaction.cpp.

5946 {
5947  if (IsAbbreviated()) return GetAbbrevInRefDisplay();
5948 
5949  int64_t lReferenceNum = 0;
5950 
5951  switch (GetType()) {
5952  // "in ref to #" is stored on me: GetReferenceToNum()
5954  case OTTransaction::notice:
5963  lReferenceNum = GetReferenceToNum();
5964  break;
5965 
5966  // A transferReceipt ACTUALLY references the acceptPending (recipient's
5967  // trans#) that accepted it.
5968  // But I don't care about the recipient's transaction #s! This function is
5969  // for DISPLAY. I am the sender,
5970  // and I want to see a reference to my original transfer that I sent. This
5971  // receipt, as far as I care,
5972  // is for THAT TRANSFER.
5976  lReferenceNum = GetNumberOfOrigin();
5977  break;
5978 
5979  default: // All other types have no amount -- return 0.
5980  return 0;
5981  }
5982 
5983  return lReferenceNum;
5984 }
virtual EXPORT int64_t GetNumberOfOrigin()
EXPORT int64_t GetReferenceToNum() const
transactionType GetType() const
bool IsAbbreviated() const
int64_t GetAbbrevInRefDisplay() const
bool opentxs::OTTransaction::GetReplyTransSuccess ( )
inline

Definition at line 629 of file OTTransaction.hpp.

630  {
631  return m_bReplyTransSuccess;
632  }
const int64_t& opentxs::OTTransaction::GetRequestNum ( ) const
inline

Definition at line 619 of file OTTransaction.hpp.

620  {
621  return m_lRequestNumber;
622  }
bool opentxs::OTTransaction::GetSenderAcctIDForDisplay ( OTIdentifier theReturnID)

Definition at line 6413 of file OTTransaction.cpp.

6414 {
6415  if (IsAbbreviated()) return false;
6416 
6417  bool bSuccess = false;
6418 
6419  OTItem* pOriginalItem = nullptr;
6420  std::unique_ptr<OTItem> theItemAngel;
6421 
6422  OTString strReference;
6423  GetReferenceString(strReference);
6424 
6425  if (strReference.GetLength() < 2) return false;
6426 
6427  switch (GetType()) {
6429  OTString strUpdatedCronItem;
6430  OTItem* pItem = GetItem(OTItem::paymentReceipt);
6431 
6432  if (nullptr != pItem)
6433  pItem->GetAttachment(strUpdatedCronItem);
6434  else
6435  otErr << "OTTransaction::" << __FUNCTION__
6436  << ": Failed trying to get paymentReceipt item from "
6437  "paymentReceipt transaction.\n";
6438 
6439  std::unique_ptr<OTCronItem> pCronItem(
6440  OTCronItem::NewCronItem(strUpdatedCronItem));
6441 
6442  OTSmartContract* pSmart =
6443  dynamic_cast<OTSmartContract*>(pCronItem.get());
6444 
6445  if (nullptr != pSmart) // if it's a smart contract...
6446  {
6447  if (!pSmart->GetLastSenderAcctID().Exists()) return false;
6448 
6449  theReturnID.SetString(pSmart->GetLastSenderAcctID());
6450  return true;
6451  }
6452  else if (nullptr !=
6453  pCronItem) // else if it is any other kind of cron item...
6454  {
6455  theReturnID = pCronItem->GetSenderAcctID();
6456  return true;
6457  }
6458  else {
6459  otErr
6460  << "OTTransaction::" << __FUNCTION__
6461  << ": Unable to load Cron Item. Should never happen. Receipt: "
6462  << GetTransactionNum() << " Origin: " << GetNumberOfOrigin()
6463  << "\n";
6464  return false;
6465  }
6466  } break;
6467  case OTTransaction::pending: // amount is stored on the transfer item, on my
6468  // list of items.
6469  case OTTransaction::chequeReceipt: // amount is stored on cheque (attached
6470  // to depositCheque item, attached.)
6471  case OTTransaction::voucherReceipt: // amount is stored on voucher (attached
6472  // to depositCheque item, attached.)
6473  {
6474  pOriginalItem = OTItem::CreateItemFromString(
6475  strReference, GetPurportedServerID(), GetReferenceToNum());
6476 
6477  if (nullptr != pOriginalItem) theItemAngel.reset(pOriginalItem);
6478 
6479  break;
6480  }
6481  default: // All other types have no sender acct ID -- return false.
6482  return false;
6483  }
6484 
6485  if (nullptr == pOriginalItem) {
6486  otErr << "OTTransaction::" << __FUNCTION__
6487  << ": couldn't load original item, should never happen. \n";
6488  return false; // Should never happen, since we always expect one based
6489  // on the transaction type.
6490  }
6491 
6492  OTCheque theCheque; // allocated on the stack :-)
6493  OTString strAttachment;
6494 
6495  switch (GetType()) { // These are the types that have an amount (somehow)
6496  case OTTransaction::chequeReceipt: // amount is stored on cheque (attached
6497  // to depositCheque item, attached.)
6498  case OTTransaction::voucherReceipt: // amount is stored on voucher (attached
6499  // to depositCheque item, attached.)
6500  {
6501  if (pOriginalItem->GetType() != OTItem::depositCheque) {
6502  otErr << __FUNCTION__ << ": Wrong item type attached to "
6504  ? "chequeReceipt"
6505  : "voucherReceipt")
6506  << " (expected depositCheque)\n";
6507  return false;
6508  }
6509 
6510  // Get the cheque from the Item and load it up into a Cheque object.
6511  pOriginalItem->GetAttachment(strAttachment);
6512  bool bLoadContractFromString =
6513  theCheque.LoadContractFromString(strAttachment);
6514 
6515  if (!bLoadContractFromString) {
6516  OTString strCheque(theCheque);
6517 
6518  otErr << "ERROR loading cheque from string in OTTransaction::"
6519  << __FUNCTION__ << ":\n" << strCheque << "\n";
6520  }
6521  else {
6523  theReturnID = theCheque.GetSenderAcctID();
6524  else
6525  theReturnID = theCheque.GetRemitterAcctID();
6526 
6527  bSuccess = true;
6528  }
6529  }
6530  break;
6531 
6532  case OTTransaction::pending: // amount is stored on transfer item
6533 
6534  if (pOriginalItem->GetType() != OTItem::transfer) {
6535  otErr << "Wrong item type attached to pending transfer\n";
6536  }
6537  else {
6538  theReturnID = pOriginalItem->GetPurportedAccountID();
6539  bSuccess = true;
6540  }
6541  break;
6542 
6543  default: // All other types have no amount -- return 0.
6544  return false;
6545  }
6546 
6547  return bSuccess;
6548 }
EXPORT void GetReferenceString(OTString &theStr) const
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
Definition: OTItem.cpp:1473
virtual EXPORT int64_t GetNumberOfOrigin()
EXPORT OTItem * GetItem(OTItem::itemType theType)
const OTIdentifier & GetPurportedServerID() const
EXPORT int64_t GetReferenceToNum() const
transactionType GetType() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
static EXPORT OTCronItem * NewCronItem(const OTString &strCronItem)
Definition: OTCronItem.cpp:165
bool opentxs::OTTransaction::GetSenderUserIDForDisplay ( OTIdentifier theReturnID)

For display purposes. The "ref #" you actually display (versus the one you use internally) might change based on transaction type. (Like with a cheque receipt you actually have to load up the original cheque.)

Definition at line 6028 of file OTTransaction.cpp.

6029 {
6030  if (IsAbbreviated()) return false;
6031 
6032  bool bSuccess = false;
6033 
6034  OTItem* pOriginalItem = nullptr;
6035  std::unique_ptr<OTItem> theItemAngel;
6036 
6037  OTString strReference;
6038  GetReferenceString(strReference);
6039 
6040  if (strReference.GetLength() < 2) return false;
6041 
6042  switch (GetType()) {
6043  case OTTransaction::paymentReceipt: // for paymentPlans AND smartcontracts.
6044  // (If the smart contract does a
6045  // payment, it leaves a paymentReceipt...)
6046  {
6047  OTString strUpdatedCronItem;
6048  OTItem* pItem = GetItem(OTItem::paymentReceipt);
6049 
6050  if (nullptr != pItem)
6051  pItem->GetAttachment(strUpdatedCronItem);
6052  else
6053  otErr << "OTTransaction::" << __FUNCTION__
6054  << ": Failed trying to get paymentReceipt item from "
6055  "paymentReceipt transaction.\n";
6056 
6057  std::unique_ptr<OTCronItem> pCronItem(
6058  OTCronItem::NewCronItem(strUpdatedCronItem));
6059 
6060  OTSmartContract* pSmart =
6061  dynamic_cast<OTSmartContract*>(pCronItem.get());
6062 
6063  if (nullptr != pSmart) // if it's a smart contract...
6064  {
6065  if (!pSmart->GetLastSenderUserID().Exists()) return false;
6066 
6067  theReturnID.SetString(pSmart->GetLastSenderUserID());
6068  return true;
6069  }
6070  else if (nullptr != pCronItem) // else if it is any other kind of
6071  // cron item...
6072  {
6073  theReturnID = pCronItem->GetSenderUserID();
6074  return true;
6075  }
6076  else {
6077  otErr << "OTTransaction::" << __FUNCTION__
6078  << ": Unable to load Cron Item. Should never happen. "
6079  "Receipt: " << GetTransactionNum()
6080  << " Origin: " << GetNumberOfOrigin() << "\n";
6081  return false;
6082  }
6083  break;
6084  }
6085 
6087  /*
6088  Therefore, if I am looping through my Nymbox, iterating through
6089  transactions, and one of them
6090  is an *** instrumentNotice *** then I should expect
6091  GetReferenceString(strOutput) to:
6092 
6093  1. load up from string as an OTMessage of type "sendUserInstrument",
6094  -------------------------------------------------------------------
6095  2. and I should expect the PAYLOAD of that message to contain an
6096  encrypted OTEnvelope,
6097  3. which can be decrypted by Msg.m_strNymID2's private key,
6098  4. And the resulting plaintext can be loaded into memory as an
6099  OTPayment object,
6100  5. ...which contains an instrument of ambiguous type.
6101  -------------------------------------------------------------------
6102  FYI:
6103  OTPayment provides a consistent interface, and consolidation of
6104  handling, for
6105  the several financial instruments that appear on the PAYMENTS page, in
6106  the PaymentsInbox.
6107  For example:
6108  [ Cheques, Invoices, Vouchers ],
6109  Payment Plans, Smart Contracts, ...and Purses.
6110  -------------------------------------------------------------------
6111  (In this block we don't need to go any farther than step 1 above.)
6112  -------------------------------------------------------------------
6113  */
6114  // OTString strReference; // (Already done above.)
6115  // GetReferenceString(strReference); // (Already done above.)
6116 
6117  OTMessage theSentMsg;
6118 
6119  if (strReference.Exists() &&
6120  theSentMsg.LoadContractFromString(strReference)) {
6121  // All we need is this message itself. We aren't going to decrypt
6122  // the payload, we're just going to grab the sender/receiver data
6123  // from the msg.
6124  //
6125  // We can't decrypt the payload (the OTPayment object) but we still
6126  // have sender / recipient.
6127  // todo security need to consider security implications of that and
6128  // maybe improve it a bit.
6129  // (But I do NOT want to get into the messaging business.)
6130 
6131  if (theSentMsg.m_strNymID.Exists()) {
6132  theReturnID.SetString(theSentMsg.m_strNymID);
6133  return true;
6134  }
6135  }
6136  return false;
6137  }
6138 
6142  pOriginalItem = OTItem::CreateItemFromString(
6143  strReference, GetPurportedServerID(), GetReferenceToNum());
6144 
6145  if (nullptr != pOriginalItem) theItemAngel.reset(pOriginalItem);
6146 
6147  break;
6148  }
6149 
6150  default: // All other types are irrelevant here.
6151  return false;
6152  }
6153 
6154  if (nullptr == pOriginalItem) {
6155  otErr << "OTTransaction::GetSenderUserIDForDisplay: original item not "
6156  "found. Should never happen.\n";
6157  return false; // Should never happen, since we always expect one based
6158  // on the transaction type.
6159  }
6160 
6161  OTCheque theCheque; // allocated on the stack :-)
6162  OTString strAttachment;
6163 
6164  switch (GetType()) { // These are the types that have an amount (somehow)
6165  case OTTransaction::chequeReceipt: // amount is stored on cheque (attached
6166  // to depositCheque item, attached.)
6167  case OTTransaction::voucherReceipt: // amount is stored on voucher (attached
6168  // to depositCheque item, attached.)
6169  {
6170  if (pOriginalItem->GetType() != OTItem::depositCheque) {
6171  otErr << __FUNCTION__ << ": Wrong item type attached to "
6173  ? "chequeReceipt"
6174  : "voucherReceipt")
6175  << " (expected depositCheque)\n";
6176  return false;
6177  }
6178 
6179  // Get the cheque from the Item and load it up into a Cheque object.
6180  pOriginalItem->GetAttachment(strAttachment);
6181  bool bLoadContractFromString =
6182  theCheque.LoadContractFromString(strAttachment);
6183 
6184  if (!bLoadContractFromString) {
6185  OTString strCheque(theCheque);
6186 
6187  otErr << "ERROR loading cheque or voucher from string in "
6188  "OTTransaction::" << __FUNCTION__ << ":\n" << strCheque
6189  << "\n";
6190  }
6191  else {
6193  theReturnID = theCheque.GetSenderUserID();
6194  else
6195  theReturnID = theCheque.GetRemitterUserID();
6196 
6197  bSuccess = true;
6198  }
6199  }
6200  break;
6201 
6202  case OTTransaction::pending: // amount is stored on transfer item
6203 
6204  if (pOriginalItem->GetType() != OTItem::transfer) {
6205  otErr << "Wrong item type attached to pending transfer\n";
6206  }
6207  else {
6208  theReturnID = pOriginalItem->GetUserID();
6209  bSuccess = true;
6210  }
6211  break;
6212  default: // All other types have no sender user ID -- return false.
6213  return false;
6214  }
6215 
6216  return bSuccess;
6217 }
EXPORT void GetReferenceString(OTString &theStr) const
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
Definition: OTItem.cpp:1473
virtual EXPORT int64_t GetNumberOfOrigin()
EXPORT OTItem * GetItem(OTItem::itemType theType)
const OTIdentifier & GetPurportedServerID() const
EXPORT int64_t GetReferenceToNum() const
transactionType GetType() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
static EXPORT OTCronItem * NewCronItem(const OTString &strCronItem)
Definition: OTCronItem.cpp:165
bool opentxs::OTTransaction::GetSuccess ( )

Definition at line 3642 of file OTTransaction.cpp.

3643 {
3644  bool bFoundAnActionItem = false, bFoundABalanceAgreement = false;
3645 
3648  for (auto& it : m_listItems) {
3649  OTItem* pItem = it;
3650  OT_ASSERT(nullptr != pItem);
3651 
3652  switch (pItem->GetType()) {
3653 
3654  // BALANCE AGREEMENT / TRANSACTION STATEMENT
3655 
3656  // Even if one of these is a success, it is only the balance
3657  // agreement for
3658  // the transaction itself, which must also be a success. For
3659  // example, if there
3660  // is a transaction for a cash withdrawal, then it will contain 2
3661  // items: one item
3662  // is the withdrawal itself, and the other item is the balance
3663  // agreement for that
3664  // withdrawal. Therefore, even if the balanace agreement item is
3665  // successful, the
3666  // withdrawal item itself must ALSO be successful, for the
3667  // transaction AS A WHOLE
3668  // to be "successful."
3669  // However, if this balance agreement failed, then the rest of the
3670  // transaction has
3671  // definitely failed as well.
3672  // Therefore, here we either return false, or CONTINUE and let the
3673  // decision be made
3674  // from the other items in this transaction otherwise.
3675  //
3676  case OTItem::atBalanceStatement: // processInbox and
3677  // notarizeTransactions. server's
3678  // reply to a
3679  // balance statement. One of these items appears inside any
3680  // transaction reply.
3681  case OTItem::atTransactionStatement: // processNymbox and also for
3682  // starting/stopping any cron
3683  // items. (notarizeTransactions: payment plan, market offer,
3684  // smart contract, trigger clause, cancel cron item, etc.) The
3685  // server's reply to a transaction statement. Like a balance
3686  // statement, except no asset acct is involved.
3687  //
3688 
3689  if (OTItem::acknowledgement == pItem->GetStatus()) {
3690  bFoundABalanceAgreement = true;
3691  }
3692  else if (OTItem::rejection == pItem->GetStatus()) {
3693  return false;
3694  }
3695  // else continue...
3696  //
3697  continue;
3698 
3699  // PROCESS NYMBOX
3700 
3701  // These are only a success if ALL of them (all of the items
3702  // in this processNymbox transaction) are a success.
3703 
3704  // NOTE: these cases only matter if *this is an atProcessNymbox, and
3705  // in THAT case, it requires ALL items
3706  // to verify, not just the first one of a specific type.
3707  //
3708  //
3709  case OTItem::atAcceptTransaction: // processNymbox. server's reply
3710  // to the Nym's attempt to accept
3711  // (sign for) transaction
3712  // numbers that are sitting in his nymbox (since he requested more
3713  // numbers....)
3714  case OTItem::atAcceptMessage: // processNymbox. server's reply to
3715  // nym's accepting a message (from
3716  // another nym) that's in his nymbox.
3717  case OTItem::atAcceptNotice: // processNymbox. server's reply to
3718  // nym's accepting a notice
3719  // from the server, such as a successNotice (success signing
3720  // out new transaction numbers) or a replyNotice, or an
3721  // instrumentNotice.
3722  // For example, some server replies are dropped into your Nymbox, to
3723  // make sure you receive them. Then you accept them, to remove from
3724  // your Nymbox.
3725 
3726  // PROCESS NYMBOX *and* PROCESS INBOX
3727 
3728  // These are only a success if ALL of them (all of the items
3729  // in this processInbox or processNymbox transaction) are a success.
3730 
3731  case OTItem::atAcceptFinalReceipt: // Part of a processInbox or
3732  // processNymbox transaction
3733  // reply from the server.
3734  case OTItem::atDisputeFinalReceipt: // Would be in processNymbox AND
3735  // processInbox. Can these be
3736  // disputed? Think through the process. Todo.
3737 
3738  // PROCESS INBOX
3739 
3740  // These are only a success if ALL of them (all of the items
3741  // in this processInbox transaction) are a success.
3742 
3743  case OTItem::atAcceptPending: // processInbox. server's reply to
3744  // nym's request to accept an incoming
3745  // pending transfer that's sitting in
3746  // his asset acct's inbox.
3747  case OTItem::atRejectPending: // processInbox. Same thing, except
3748  // rejecting that pending transfer
3749  // instead of accepting it.
3750 
3751  case OTItem::atAcceptCronReceipt: // processInbox. Accepting a
3752  // payment receipt or market
3753  // receipt. (Smart contracts also drop payment receipts,
3754  // currently.)
3755  case OTItem::atDisputeCronReceipt: // processInbox. Dispute. (Todo.)
3756 
3757  case OTItem::atAcceptItemReceipt: // processInbox. Accepting a
3758  // transferReceipt, or
3759  // chequeReceipt, etc.
3760  case OTItem::atDisputeItemReceipt: // processInbox. Dispute. (Todo.)
3761 
3762  case OTItem::atAcceptBasketReceipt: // processInbox. Basket Receipt,
3763  // from a basket currency
3764  // exchange (in or out.)
3765  case OTItem::atDisputeBasketReceipt: // processInbox. dispute basket
3766  // receipt.
3767 
3768  // If we found at least one of these, and nothing fails by the
3769  // end of the loop,
3770  // then for processNymbox and processInbox, it's a success. (If
3771  // balance agreement also...)
3772 
3773  if (OTItem::acknowledgement == pItem->GetStatus()) {
3774  bFoundAnActionItem = true;
3775  }
3776  else if (OTItem::rejection == pItem->GetStatus()) {
3777  return false;
3778  }
3779  // else continue...
3780  //
3781  continue;
3782 
3783  default:
3784  otErr << "Wrong transaction type passed to "
3785  "OTTransaction::GetSuccess() "
3786  "for processNymbox or processInbox transaction.\n";
3787  return false;
3788  } // switch
3789  }
3790 
3791  return (bFoundABalanceAgreement && bFoundAnActionItem);
3792 
3793  } // if processNymbox or processInbox.
3794 
3795  // Okay, it's not a processNymbox or processInbox.
3796  //
3797  // Maybe it's one of these other transaction types...
3798 
3799  for (auto& it : m_listItems) {
3800  OTItem* pItem = it;
3801  OT_ASSERT(nullptr != pItem);
3802 
3803  switch (pItem->GetType()) {
3804  // case OTItem::atServerfee: // Fees currently
3805  // aren't coded. Todo.
3806  // case OTItem::atIssuerfee: // Same as above.
3807  // Todo.
3808 
3809  // BALANCE AGREEMENT / TRANSACTION STATEMENT
3810 
3811  // Even if one of these is a success, it is only the balance agreement
3812  // for
3813  // the transaction itself, which must also be a success. For example, if
3814  // there
3815  // is a transaction for a cash withdrawal, then it will contain 2 items:
3816  // one item
3817  // is the withdrawal itself, and the other item is the balance agreement
3818  // for that
3819  // withdrawal. Therefore, even if the balanace agreement item is
3820  // successful, the
3821  // withdrawal item itself must ALSO be successful, for the transaction
3822  // AS A WHOLE
3823  // to be "successful."
3824  // However, if this balance agreement failed, then the rest of the
3825  // transaction has
3826  // definitely failed as well.
3827  // Therefore, here we either return false, or CONTINUE and let the
3828  // decision be made
3829  // from the other items in this transaction otherwise.
3830  //
3831  case OTItem::atBalanceStatement: // processInbox and
3832  // notarizeTransactions. server's reply
3833  // to a
3834  // balance statement. One of these items appears inside any
3835  // transaction reply.
3836  case OTItem::atTransactionStatement: // processNymbox and also for
3837  // starting/stopping any cron
3838  // items.
3839  // (notarizeTransactions: payment plan, market offer, smart
3840  // contract, trigger clause, cancel cron item, etc.) The server's
3841  // reply to a transaction statement. Like a balance statement,
3842  // except no asset acct is involved.
3843 
3844  if (OTItem::acknowledgement == pItem->GetStatus()) {
3845  bFoundABalanceAgreement = true;
3846  }
3847  if (OTItem::rejection == pItem->GetStatus()) {
3848  return false;
3849  }
3850  // else continue...
3851  //
3852  continue;
3853 
3854  /*
3855  atProcessNymbox, // process nymbox reply // comes from
3856  server
3857  atProcessInbox, // process inbox reply // comes from
3858  server
3859 
3860  // Note: the above two transaction types are handled in the switch
3861  block above this one.
3862  // Whereas the below transaction types are handled right here in this
3863  switch block.
3864 
3865  atTransfer, // reply from the server regarding a transfer
3866  request
3867  atDeposit, // reply from the server regarding a deposit request
3868  atWithdrawal, // reply from the server regarding a withdrawal
3869  request
3870  atMarketOffer, // reply from the server regarding a market offer
3871  atPaymentPlan, // reply from the server regarding a payment plan
3872  atSmartContract, // reply from the server regarding a smart contract
3873  atCancelCronItem, // reply from the server regarding said
3874  cancellation.
3875  atExchangeBasket, // reply from the server regarding said exchange.
3876  */
3877 
3878  // NOTARIZE TRANSACTION
3879  // If any of these are a success, then the transaction as a whole is a
3880  // success also.
3881 
3882  case OTItem::atTransfer: // notarizeTransactions. server's reply to
3883  // nym's request to initiate a transfer
3884 
3885  case OTItem::atWithdrawal: // notarizeTransaction. server's reply to
3886  // withdrawal (cash) request.
3887  case OTItem::atDeposit: // notarizeTransaction. server's reply to
3888  // deposit (cash) request.
3889  case OTItem::atWithdrawVoucher: // notarizeTransaction. server's reply
3890  // to "withdraw voucher" request.
3891  case OTItem::atDepositCheque: // notarizeTransaction. server's reply to
3892  // "deposit cheque" request.
3893  case OTItem::atPayDividend: // notarizeTransaction. server's reply to
3894  // "pay dividend" request.
3895  case OTItem::atMarketOffer: // notarizeTransaction. server's reply to
3896  // request to place a market offer.
3897  case OTItem::atPaymentPlan: // notarizeTransaction. server's reply to
3898  // request to activate a payment plan.
3899  case OTItem::atSmartContract: // notarizeTransaction. server's reply to
3900  // request to activate a smart contract.
3901 
3902  case OTItem::atCancelCronItem: // notarizeTransaction. server's reply to
3903  // request to cancel a [ market offer |
3904  // payment plan | smart contract ]
3905  case OTItem::atExchangeBasket: // notarizeTransaction. server's reply to
3906  // request to exchange in or out of a
3907  // basket currency.
3908 
3909  // RECEIPTS
3910 
3911  // 1. ACTUAL RECEIPTS (item attached to similar transaction), and also
3912  // 2. INBOX REPORT ITEMS (sub-item to ANOTHER item, which is used on
3913  // Balance Agreements and Transaction Statements.)
3914  //
3915  // In case of (1), GetSuccess() is relevant.
3916  // But in case of (2) GetSuccess() is NOT relevant. FYI.
3917  //
3918  // Anyway, if a marketReceipt item is attached to a marketReceipt
3919  // transaction, then we
3920  // can return success or failure right away, since such status is set on
3921  // the item, not
3922  // the transaction, and since there are no other items that matter if
3923  // this IS a success.
3924 
3925  // case OTItem::chequeReceipt: // not needed in OTItem.
3926  // Meaning, actual OTTransaction cheque receipts do NOT need a
3927  // chequeReceipt Item attached....
3928  case OTItem::chequeReceipt: // ...but it's here anyway as a type, for
3929  // dual use reasons (balance agreement
3930  // sub-items. Like for an inbox report.)
3932  case OTItem::marketReceipt: // Used for actual market receipts, as well
3933  // as for balance agreement sub-items.
3934  case OTItem::paymentReceipt: // Used for actual payment receipts, as
3935  // well as for balance agreement sub-items.
3936  case OTItem::transferReceipt: // Used for actual transfer receipts, as
3937  // well as for balance
3938  // agreement sub-items. (Hmm does balance agreement need this?)
3939  case OTItem::finalReceipt: // Used for actual final receipt (I think) as
3940  // well as for balance agreement sub item (I
3941  // think.)
3942  case OTItem::basketReceipt: // Used for basket receipt (I think) as well
3943  // as for balance agreement sub-item (I
3944  // think.)
3945 
3946  if (OTItem::acknowledgement == pItem->GetStatus()) {
3947  bFoundAnActionItem = true;
3948  }
3949  else if (OTItem::rejection == pItem->GetStatus()) {
3950  return false;
3951  }
3952 
3953  break;
3954 
3955  default:
3956  otErr << "Wrong transaction type passed to "
3957  "OTTransaction::GetSuccess()\n";
3958  return false;
3959  }
3960  }
3961 
3962  return (bFoundABalanceAgreement && bFoundAnActionItem);
3963 }
#define OT_ASSERT(x)
Definition: Assert.hpp:150
transactionType GetType() const
OTLOG_IMPORT OTLogStream otErr
transactionType opentxs::OTTransaction::GetType ( ) const
inline

Definition at line 678 of file OTTransaction.hpp.

679  {
680  return m_Type;
681  }
transactionType m_Type
OTTransaction::transactionType opentxs::OTTransaction::GetTypeFromString ( const OTString strType)
static

Definition at line 3970 of file OTTransaction.cpp.

3972 {
3974 
3975  if (strType.Compare("blank"))
3976  theType = OTTransaction::blank;
3977 
3978  else if (strType.Compare("message"))
3979  theType = OTTransaction::message;
3980  else if (strType.Compare("notice"))
3981  theType = OTTransaction::notice;
3982  else if (strType.Compare("replyNotice"))
3983  theType = OTTransaction::replyNotice;
3984  else if (strType.Compare("successNotice"))
3985  theType = OTTransaction::successNotice;
3986 
3987  else if (strType.Compare("pending"))
3988  theType = OTTransaction::pending;
3989 
3990  else if (strType.Compare("transferReceipt"))
3992  else if (strType.Compare("voucherReceipt"))
3994  else if (strType.Compare("chequeReceipt"))
3995  theType = OTTransaction::chequeReceipt;
3996  else if (strType.Compare("marketReceipt"))
3997  theType = OTTransaction::marketReceipt;
3998  else if (strType.Compare("paymentReceipt"))
4000  else if (strType.Compare("finalReceipt"))
4001  theType = OTTransaction::finalReceipt;
4002  else if (strType.Compare("basketReceipt"))
4003  theType = OTTransaction::basketReceipt;
4004 
4005  else if (strType.Compare("instrumentNotice"))
4007  else if (strType.Compare("instrumentRejection"))
4009 
4010  else if (strType.Compare("processNymbox"))
4011  theType = OTTransaction::processNymbox;
4012  else if (strType.Compare("atProcessNymbox"))
4014  else if (strType.Compare("processInbox"))
4015  theType = OTTransaction::processInbox;
4016  else if (strType.Compare("atProcessInbox"))
4018  else if (strType.Compare("transfer"))
4019  theType = OTTransaction::transfer;
4020  else if (strType.Compare("atTransfer"))
4021  theType = OTTransaction::atTransfer;
4022  else if (strType.Compare("deposit"))
4023  theType = OTTransaction::deposit;
4024  else if (strType.Compare("atDeposit"))
4025  theType = OTTransaction::atDeposit;
4026  else if (strType.Compare("withdrawal"))
4027  theType = OTTransaction::withdrawal;
4028  else if (strType.Compare("atWithdrawal"))
4029  theType = OTTransaction::atWithdrawal;
4030  else if (strType.Compare("marketOffer"))
4031  theType = OTTransaction::marketOffer;
4032  else if (strType.Compare("atMarketOffer"))
4033  theType = OTTransaction::atMarketOffer;
4034  else if (strType.Compare("paymentPlan"))
4035  theType = OTTransaction::paymentPlan;
4036  else if (strType.Compare("atPaymentPlan"))
4037  theType = OTTransaction::atPaymentPlan;
4038  else if (strType.Compare("smartContract"))
4039  theType = OTTransaction::smartContract;
4040  else if (strType.Compare("atSmartContract"))
4042  else if (strType.Compare("cancelCronItem"))
4044  else if (strType.Compare("atCancelCronItem"))
4046  else if (strType.Compare("exchangeBasket"))
4048  else if (strType.Compare("atExchangeBasket"))
4050  else if (strType.Compare("payDividend"))
4051  theType = OTTransaction::payDividend;
4052  else if (strType.Compare("atPayDividend"))
4053  theType = OTTransaction::atPayDividend;
4054  else
4055  theType = OTTransaction::error_state;
4056 
4057  return theType;
4058 }
const char* opentxs::OTTransaction::GetTypeString ( ) const
inline

Definition at line 750 of file OTTransaction.hpp.

751  {
752  return GetTransactionTypeString(static_cast<int>(m_Type));
753  }
EXPORT const char * GetTransactionTypeString(int transactionNumber)
Definition: Helpers.cpp:212
transactionType m_Type
bool opentxs::OTTransaction::HarvestClosingNumbers ( OTPseudonym theNym,
bool  bHarvestingForRetry,
bool  bReplyWasSuccess,
bool  bReplyWasFailure,
bool  bTransactionWasSuccess,
bool  bTransactionWasFailure 
)

Definition at line 898 of file OTTransaction.cpp.

905 {
906  bool bSuccess = false;
907 
908  switch (m_Type) { // Note: the below remarks about "success or fail" are
909  // specific to TRANSACTION success, not message success.
910 
911  // case OTTransaction::processNymbox: // Why is this even here?
912  // processNymbox uses NO trans#s--that's the purpose of processNymbox.
913  case OTTransaction::processInbox: // Has no closing numbers.
914  case OTTransaction::deposit: // Has no closing numbers.
915  case OTTransaction::withdrawal: // Has no closing numbers.
916  case OTTransaction::cancelCronItem: // Has no closing numbers.
917  case OTTransaction::payDividend: // Has no closing numbers.
918  case OTTransaction::transfer: // Has no closing numbers.
919 
920  break;
921 
922  case OTTransaction::marketOffer: // Uses 3 transaction #s, the opening
923  // number and 2 closers.
924  // If message fails, all closing numbers are harvestable.
925  // If message succeeds but transaction fails, closers can also be
926  // harvested.
927  // If message succeeds and transaction succeeds, closers are marked as
928  // "used" (like opener.)
929  // In that last case, you can't claw them back since they are used.
930  {
931  OTItem* pItem = GetItem(OTItem::marketOffer);
932 
933  if (nullptr == pItem) {
934  otErr << "OTTransaction::HarvestClosingNumbers: Error: Unable "
935  "to find "
936  "marketOffer item in marketOffer transaction.\n";
937  }
938  else // pItem is good. Let's load up the OTCronIteam object...
939  {
940  OTCronItem theTrade;
941  OTString strTrade;
942  pItem->GetAttachment(strTrade);
943 
944  // First load the Trade up...
945  const bool bLoadContractFromString =
946  (strTrade.Exists() &&
947  theTrade.LoadContractFromString(strTrade));
948 
949  // If failed to load the trade...
950  if (!bLoadContractFromString) {
951  otErr << "OTTransaction::HarvestClosingNumbers: ERROR: "
952  "Failed loading trade from string:\n\n" << strTrade
953  << "\n\n";
954  }
955  else // theTrade is ready to go....
956  {
957 
958  // The message reply itself was a failure. This means the
959  // transaction itself never got a chance
960  // to run... which means ALL the closing numbers on that
961  // transaction are STILL GOOD.
962  //
963  if (bReplyWasFailure) // && !bHarvestingForRetry) // on
964  // re-try, we need the closing #s to
965  // stay put, so the re-try has a
966  // chance to work.
967  { // NOTE: We do NOT exclude harvesting of closing numbers,
968  // for a marketoffer, based on bHarvestingForRetry. Why
969  // not?
970  // Because with marketOffer, ALL transaction #s are
971  // re-set EACH re-try, not just the opening #. Therefore
972  // ALL must be clawed back.
973  theTrade.HarvestClosingNumbers(
974  theNym); // (Contrast this with payment plan,
975  // exchange basket, smart contract...)
976  bSuccess = true;
977 
978  // theTrade.GetAssetAcctClosingNum();
979  // // For reference.
980  // theTrade.GetCurrencyAcctClosingNum();
981  // // (The above harvest call grabs THESE numbers.)
982 
983  }
984  // Else if the server reply message was unambiguously a
985  // SUCCESS, that means the opening number is DEFINITELY NOT
986  // HARVESTABLE.
987  // Why? Because that means the transaction definitely
988  // ran--and the opener is marked as "used" on SUCCESS, or
989  // "burned" on
990  // FAILURE--either way, that's bad for harvesting (no
991  // point.)
992  //
993  // ===> But the CLOSING numbers are harvestable on
994  // transaction *failure.*
995  // (They are not harvestable on transaction *success*
996  // though.)
997  //
998  else if (bReplyWasSuccess) {
999  if (bTransactionWasSuccess) {
1000  // (They are not harvestable on transaction success
1001  // though.)
1002  // This means the "marketOffer" closing trans#s (one
1003  // for asset account, and one for currency account)
1004  // are both
1005  // MARKED AS "USED", and will someday be marked as
1006  // CLOSED.
1007  // EITHER WAY, you certainly can't claw those
1008  // numbers back now! (They are still outstanding,
1009  // though. They're not gone, yet...)
1010  //
1011  // theTrade.HarvestClosingNumbers(theNym);
1012  // bSuccess = true;
1013  }
1014  else if (bTransactionWasFailure) {
1015  // But the CLOSING numbers ARE harvestable on
1016  // transaction failure.
1017  // (Closing numbers for marketOffers are only marked
1018  // "used" if the
1019  // marketOffer transaction was a success.)
1020  //
1021  theTrade.HarvestClosingNumbers(theNym);
1022  bSuccess = true;
1023  }
1024  } // else if (bReplyWasSuccess)
1025 
1026  } // else (the trade loaded successfully)
1027  } // pItem was found.
1028  }
1029  break;
1030 
1031  // These aren't AS simple.
1032  case OTTransaction::paymentPlan: // Uses 4 transaction #s: the opener
1033  // (sender's #), which is burned on
1034  // transaction failure, but kept alive on success,
1035  // ===> the sender's closing #, which is only marked as "used" upon
1036  // success (harvestable up until that point.)
1037  // ===> and the recipient's opening/closing numbers, which are also both
1038  // only marked as "used" upon success, and are harvestable up until that
1039  // point.
1040 
1041  {
1042  OTItem* pItem = GetItem(OTItem::paymentPlan);
1043 
1044  if (nullptr == pItem) {
1045  otErr << "OTTransaction::HarvestClosingNumbers: Error: Unable "
1046  "to find "
1047  "paymentPlan item in paymentPlan transaction.\n";
1048  }
1049  else // pItem is good. Let's load up the OTPaymentPlan object...
1050  {
1051  OTString strPaymentPlan;
1052  OTPaymentPlan thePlan;
1053  pItem->GetAttachment(strPaymentPlan);
1054 
1055  // First load the payment plan up...
1056  const bool bLoadContractFromString =
1057  (strPaymentPlan.Exists() &&
1058  thePlan.LoadContractFromString(strPaymentPlan));
1059 
1060  // If failed to load the payment plan from string...
1061  if (!bLoadContractFromString) {
1062  otErr << "OTTransaction::HarvestClosingNumbers: ERROR: "
1063  "Failed loading payment plan from string:\n\n"
1064  << strPaymentPlan << "\n\n";
1065  }
1066  else // thePlan is ready to go....
1067  {
1068  // If the server reply message was unambiguously a FAIL,
1069  // that means the closing numbers are STILL GOOD.
1070  // (Because the transaction therefore never even had a
1071  // chance to run.)
1072  //
1073  if (bReplyWasFailure &&
1074  !bHarvestingForRetry) // on re-try, we need the closing
1075  // #s to stay put, so the re-try
1076  // has a chance to work.
1077  {
1078  thePlan.HarvestClosingNumbers(theNym);
1079  bSuccess = true;
1080  }
1081  // Else if the server reply message was unambiguously a
1082  // SUCCESS, that means the opening number is DEFINITELY
1083  // NOT HARVESTABLE. (For the sender, anyway.) Why not?
1084  // Because that means the transaction definitely ran--and
1085  // the opener is marked as "used" on success, and "burned"
1086  // on failure--either way, that's bad for harvesting (no
1087  // point.)
1088  // The recipient, by contrast, actually retains
1089  // harvestability on his opening number up until the very
1090  // point of
1091  // transaction success.
1092  //
1093  // ====> I know you are wondering:
1094  // ====> HOW ABOUT THE CLOSING NUMBERS? (When message is
1095  // success)
1096  // 1. Transaction success: Sender and Recipient CANNOT
1097  // harvest closing numbers, which are now marked as "used."
1098  // 2. Transaction failed: Sender and Recipient **CAN**
1099  // both harvest their closing numbers.
1100  //
1101  else if (bReplyWasSuccess) {
1102  if (bTransactionWasSuccess) {
1103  // This means the "paymentPlan" closing trans#s are
1104  // MARKED AS "USED", and will someday be marked as
1105  // CLOSED.
1106  // EITHER WAY, you certainly can't claw that number
1107  // back now! (It is still outstanding, though. It's
1108  // not gone, yet...)
1109  // thePlan.HarvestClosingNumbers(theNym);
1110  // bSuccess = true;
1111  }
1112  else if (bTransactionWasFailure &&
1113  !bHarvestingForRetry) // on re-try, we need
1114  // the closing #s to
1115  // stay put, so the
1116  // re-try has a chance
1117  // to work.
1118  {
1119  // Whereas if the payment plan was a failure, that
1120  // means the closing numbers are harvestable!
1121  thePlan.HarvestClosingNumbers(theNym);
1122  bSuccess = true;
1123  }
1124  }
1125 
1126  } // else (the payment plan loaded successfully)
1127  } // pItem was found.
1128  }
1129  break;
1130 
1131  case OTTransaction::smartContract: // Uses X transaction #s, with an opener
1132  // for each party and a closer for each
1133  // asset account.
1134  // If the message is rejected by the server, then ALL openers can be
1135  // harvested. But if the
1136  // message was successful (REGARDLESS of whether the transaction was
1137  // successful) then all of
1138  // the openers for all of the parties have been burned. The closers,
1139  // meanwhile, can be recovered
1140  // if the message is a failure, as well as in cases where message
1141  // succeeds but transaction failed.
1142  // But if transaction succeeded, then the closers CANNOT be recovered.
1143  // (Only removed, once you sign
1144  // off on the receipt.)
1145  {
1146 
1147  OTItem* pItem = GetItem(OTItem::smartContract);
1148 
1149  if (nullptr == pItem) {
1150  otErr << "OTTransaction::HarvestClosingNumbers: Error: Unable "
1151  "to find "
1152  "smartContract item in smartContract transaction.\n";
1153  }
1154  else // Load up the smart contract...
1155  {
1156  OTString strSmartContract;
1157  OTSmartContract theSmartContract(GetPurportedServerID());
1158  pItem->GetAttachment(strSmartContract);
1159 
1160  // If we failed to load the smart contract...
1161  if (!strSmartContract.Exists() ||
1162  (false ==
1163  theSmartContract.LoadContractFromString(
1164  strSmartContract))) {
1165  otErr << "OTTransaction::HarvestClosingNumbers: Error: "
1166  "Unable to load "
1167  "smartContract object from smartContract "
1168  "transaction item.\n";
1169  }
1170  else // theSmartContract is ready to go....
1171  {
1172 
1173  // The message reply itself was a failure. This means the
1174  // transaction itself never got a chance
1175  // to run... which means ALL the closing numbers on that
1176  // transaction are STILL GOOD.
1177  //
1178  if (bReplyWasFailure &&
1179  !bHarvestingForRetry) // on re-try, we need the closing
1180  // #s to stay put, so the re-try
1181  // has a chance to work.
1182  {
1183  theSmartContract.HarvestClosingNumbers(theNym);
1184  bSuccess = true;
1185  }
1186  // Else if the server reply message was unambiguously a
1187  // SUCCESS, that means the opening number is DEFINITELY NOT
1188  // HARVESTABLE.
1189  // Why? Because that means the transaction definitely
1190  // ran--and the opener is marked as "used" on SUCCESS, or
1191  // "burned" on
1192  // FAILURE--either way, that's bad for harvesting (no
1193  // point.)
1194  //
1195  // ===> HOW ABOUT THE CLOSING NUMBERS?
1196  // In cases where the message succeeds but the transaction
1197  // failed, the closing numbers are recoverable. (TODO send
1198  // notice to the parties when this happens...)
1199  // But if transaction succeeded, then the closers CANNOT be
1200  // recovered. They are now "used" on the server, so you
1201  // might as well keep them in that format on the client
1202  // side, since that's how the client has them already.
1203  else if (bReplyWasSuccess) {
1204  if (bTransactionWasSuccess) {
1205  // This means the "smartContract" opening trans# is
1206  // MARKED AS "USED", and will someday be marked as
1207  // CLOSED.
1208  // EITHER WAY, you certainly can't claw that number
1209  // back now! (It is still outstanding, though. It's
1210  // not gone, yet...)
1211  //
1212  // theSmartContract.HarvestClosingNumbers(theNym);
1213  // bSuccess = true;
1214  }
1215  else if (bTransactionWasFailure &&
1216  !bHarvestingForRetry) // on re-try, we need
1217  // the closing #s to
1218  // stay put, so the
1219  // re-try has a chance
1220  // to work.
1221  {
1222  // If the transaction was a failure, the opening
1223  // trans number was burned,
1224  // but the CLOSING numbers are still harvestable...
1225  //
1226  theSmartContract.HarvestClosingNumbers(theNym);
1227  bSuccess = true;
1228  }
1229  } // else if (bReplyWasSuccess)
1230 
1231  } // else (smart contract loaded successfully)
1232  } // pItem was found.
1233  }
1234  break;
1235 
1236  default:
1237  break;
1238  }
1239 
1240  return bSuccess;
1241 }
EXPORT OTItem * GetItem(OTItem::itemType theType)
const OTIdentifier & GetPurportedServerID() const
OTLOG_IMPORT OTLogStream otErr
transactionType m_Type
bool opentxs::OTTransaction::HarvestOpeningNumber ( OTPseudonym theNym,
bool  bHarvestingForRetry,
bool  bReplyWasSuccess,
bool  bReplyWasFailure,
bool  bTransactionWasSuccess,
bool  bTransactionWasFailure 
)

Definition at line 302 of file OTTransaction.cpp.

310 {
311  bool bSuccess = false;
312 
313  switch (m_Type) {
314  // Note: the below remarks about "success or fail" are specific to
315  // TRANSACTION success, not message success.
316  // case OTTransaction::processNymbox: // NOTE: why was this here? You
317  // don't need trans#s to process a Nymbox--that's the whole point of a
318  // Nymbox.
319  case OTTransaction::processInbox: // Uses 1 transaction #, the opening
320  // number, and burns it whether
321  // transaction is success-or-fail.
322  case OTTransaction::withdrawal: // Uses 1 transaction #, the opening number,
323  // and burns it whether transaction is
324  // success-or-fail.
325  case OTTransaction::deposit: // Uses 1 transaction #, the opening number,
326  // and burns it whether transaction is
327  // success-or-fail.
328  case OTTransaction::cancelCronItem: // Uses 1 transaction #, the opening
329  // number, and burns it whether
330  // transaction is success-or-fail.
331  case OTTransaction::payDividend: // Uses 1 transaction #, the opening
332  // number, and burns it whether transaction
333  // is success-or-fail.
334 
335  // If the server reply message was unambiguously a FAIL, that means the
336  // opening number is STILL GOOD.
337  // (Because the transaction therefore never even had a chance to run.)
338  //
339  // Note: what if, instead, I don't know whether the transaction itself
340  // failed, because I don't have a reply message?
341  // In that case, I cannot claw back the numbers because I don't know for
342  // sure. But my future transactions WILL fail if
343  // my nymbox hash goes out of sync, so if that transaction DID process,
344  // then I'll find out right away, and I'll be forced
345  // to download the nymbox and box receipts in order to get back into
346  // sync again. And if the transaction did NOT process,
347  // then I'll know it when I don't find it among the receipts. In which
348  // case I can pull the original message from the
349  // outbuffer, using the request number from when it was sent, and then
350  // harvest it from there.
351  //
352  if (bReplyWasFailure) // NOTE: If I'm harvesting for a re-try,
353  {
354  bSuccess = theNym.ClawbackTransactionNumber(
356  GetTransactionNum()); // bSave=false, pSignerNym=nullptr
357  }
358  // Else if the server reply message was unambiguously a SUCCESS, that
359  // means the opening number is DEFINITELY BURNED.
360  // (Why? Because that means the transaction definitely ran--and the
361  // opener is burned success-or-fail, if the transaction runs.)
362  //
363  else if (bReplyWasSuccess) {
364  // The opener is DEFINITELY BAD, so therefore, we're definitely not
365  // going to claw it back!
366  //
367  // bSuccess =
368  // theNym.ClawbackTransactionNumber(GetPurportedServerID(),
369  // GetTransactionNum());
370  // //bSave=false, pSignerNym=nullptr
371  }
372  break;
373 
374  case OTTransaction::transfer: // Uses 1 transaction #, the opening number,
375  // and burns it if failure. But if success,
376  // merely marks it as "used."
377 
378  // If the server reply message was unambiguously a FAIL, that means the
379  // opening number is STILL GOOD.
380  // (Because the transaction therefore never even had a chance to run.)
381  //
382  if (bReplyWasFailure) {
383  bSuccess = theNym.ClawbackTransactionNumber(
385  GetTransactionNum()); // bSave=false, pSignerNym=nullptr
386  }
387  // Else if the server reply message was unambiguously a SUCCESS, that
388  // means the opening number is DEFINITELY NOT HARVESTABLE.
389  // Why? Because that means the transaction definitely ran--and the
390  // opener is marked as "used" on success, and "burned" on
391  // failure--either way, that's bad for harvesting (no point.)
392  //
393  else if (bReplyWasSuccess) {
394  if (bTransactionWasSuccess) {
395  // This means the "transfer" transaction# is STILL MARKED AS
396  // "USED", and will someday be marked as CLOSED.
397  // EITHER WAY, you certainly can't claw that number back now!
398  // (It is still outstanding, though. It's not gone, yet...)
399  // bSuccess =
400  // theNym.ClawbackTransactionNumber(GetPurportedServerID(),
401  // GetTransactionNum());
402  // //bSave=false, pSignerNym=nullptr
403  }
404  else if (bTransactionWasFailure) {
405  // Whereas if the transaction was a failure, that means the
406  // transaction number was DEFINITELY burned.
407  // (No point clawing it back now--it's gone already.)
408  // bSuccess =
409  // theNym.ClawbackTransactionNumber(GetPurportedServerID(),
410  // GetTransactionNum());
411  // //bSave=false, pSignerNym=nullptr
412  }
413  }
414  break;
415 
416  case OTTransaction::marketOffer: // Uses 3 transaction #s, the opening
417  // number and 2 closers. If failure, opener
418  // is burned.
419  // But if success, merely marks it as "used." Closers are also marked
420  // "used" if success,
421  // but if message succeeds while transaction fails, then closers can be
422  // harvested.
423  // If the server reply message was unambiguously a FAIL, that means the
424  // opening number is STILL GOOD.
425  // (Because the transaction therefore never even had a chance to run.)
426  //
427  if (bReplyWasFailure) {
428  bSuccess = theNym.ClawbackTransactionNumber(
430  GetTransactionNum()); // bSave=false, pSignerNym=nullptr
431  }
432  // Else if the server reply message was unambiguously a SUCCESS, that
433  // means the opening number is DEFINITELY NOT HARVESTABLE.
434  // Why? Because that means the transaction definitely ran--and the
435  // opener is marked as "used" on success, and "burned" on
436  // failure--either way, that's bad for harvesting (no point.)
437  //
438  else if (bReplyWasSuccess) {
439  if (bTransactionWasSuccess) {
440  // This means the "marketOffer" transaction# is STILL MARKED AS
441  // "USED", and will someday be marked as CLOSED.
442  // EITHER WAY, you certainly can't claw that number back now!
443  // (It is still outstanding, though. It's not gone, yet...)
444  // bSuccess =
445  // theNym.ClawbackTransactionNumber(GetPurportedServerID(),
446  // GetTransactionNum());
447  // //bSave=false, pSignerNym=nullptr
448  }
449  else if (bTransactionWasFailure) {
450  // Whereas if the transaction was a failure, that means the
451  // transaction number was DEFINITELY burned.
452  // (No point clawing it back now--it's gone already.)
453  // bSuccess =
454  // theNym.ClawbackTransactionNumber(GetPurportedServerID(),
455  // GetTransactionNum());
456  // //bSave=false, pSignerNym=nullptr
457  }
458  }
459 
460  break;
461 
462  case OTTransaction::exchangeBasket: // Uses X transaction #s: the opener,
463  // which is burned success-or-fail, and
464  // Y closers (one for
465  // each account.) Closers are marked "used" if success transaction, but
466  // if message succeeds while
467  // transaction fails, then closers can be harvested.
468  // If the server reply message was unambiguously a FAIL, that means the
469  // opening number is STILL GOOD.
470  // (Because the transaction therefore never even had a chance to run.)
471  //
472  if (bReplyWasFailure) {
473  bSuccess = theNym.ClawbackTransactionNumber(
475  GetTransactionNum()); // bSave=false, pSignerNym=nullptr
476  }
477  // Else if the server reply message was unambiguously a SUCCESS, that
478  // means the opening number is DEFINITELY BURNED.
479  // (Why? Because that means the transaction definitely ran--and the
480  // opener is burned "success-or-fail", if this transaction runs.)
481  //
482  else if (bReplyWasSuccess) {
483  // The opener is DEFINITELY BURNED, so therefore, we're definitely
484  // not going to claw it back!
485  //
486  // bSuccess =
487  // theNym.ClawbackTransactionNumber(GetPurportedServerID(),
488  // GetTransactionNum());
489  // //bSave=false, pSignerNym=nullptr
490  }
491  break;
492 
493  // These aren't AS simple.
494  case OTTransaction::paymentPlan: // Uses 4 transaction #s: the opener
495  // (sender's #), which burned on failure
496  // but kept alive on success,
497  // the sender's closer, which is only marked as "used" upon success, and
498  // the recipient's opening and
499  // closing numbers, which are both only marked as "used" upon success.
500  {
501  // The PAYER's (sender) opening number is burned just from TRYING a
502  // transaction. It's only left
503  // open if the transaction succeeds (but in that case, it's still
504  // marked as "used.") But the
505  // PAYEE's (recipient) opening number isn't marked as "used" UNLESS
506  // the transaction succeeds.
507  //
508  // Basically a failed transaction means the sender's opening number
509  // is burned and gone, but the
510  // recipient's must be clawed back!! Whereas if the message fails
511  // (before transaction even has a
512  // chance to run) then BOTH sender and recipient can claw back their
513  // numbers. The only way to tell
514  // the difference is to look at the message itself (the info isn't
515  // stored here in the transaction.)
516  //
517  // 1.
518  // Therefore we must assume that the CALLER OF THIS FUNCTION knows.
519  // If the message failed, he knows
520  // this, and he SPECIFICALLY called HarvestOpeningNumber() ANYWAY,
521  // to get the opening number back
522  // (when normally he would only recoup the closed numbers--therefore
523  // he MUST know that the message
524  // failed and that the number is thus still good!)
525  //
526  // 2.
527  // WHEREAS if the message SUCCEEDED (followed by transaction FAIL),
528  // then the payer/sender already
529  // used his opening number, whereas the recipient DID NOT! Again,
530  // the caller MUST KNOW THIS ALREADY.
531  // The caller wouldn't call "HarvestOpeningNumber" for a burned
532  // number (of the sender.) Therefore
533  // he must be calling it to recoup the (still issued) opening number
534  // of the RECIPIENT.
535  //
536  // Problems:
537  // 1. What if caller is stupid, and message hasn't actually failed?
538  // What if caller is mistakenly
539  // trying to recoup numbers that are actually burned already?
540  // Well, the opening number is already
541  // marked as "used but still issued" so when I try to claw it
542  // back, that will work (because it
543  // only adds a number BACK after it can confirm that the number
544  // WAS issued to me in the first place,
545  // and in this case, that verification will succeed.)
546  // THEREFORE: need to explicitly pass the message's
547  // success/failure status into the current
548  // function. IF the msg was a failure, the transaction never had
549  // a chance to run and thus the
550  // opening number is still good, and we can claw it back. But if
551  // the message was a SUCCESS, then
552  // the transaction definitely TRIED to run, which means the
553  // opening number is now burned. (IF
554  // the transaction itself failed, that is. Otherwise if it
555  // succeeded, then it's possible, in the
556  // cases of transfer and marketOffer, that the opening number is
557  // STILL "used but issued", until
558  // you finally close out your transferReceipt or the finalReceipt
559  // for your market offer.)
560  //
561  // 2. What if caller is stupid, and he called HarvestOpeningNumber
562  // for the sender, even though the
563  // number was already burned in the original attempt? (Which we
564  // know it was, since the message
565  // itself succeeded.) The sender, of course, has that number on
566  // his "issued" list, so his clawback
567  // will succeed, putting him out of sync.
568  //
569  // 3. What if the recipient is passed into this function? His
570  // "opening number" is not the primary
571  // one, but rather, there are three "closing numbers" on a
572  // payment plan. One for the sender, to
573  // match his normal opening number, and 2 more for the recipient
574  // (an opening and closing number).
575  // Therefore in the case of the recipient, need to grab HIS
576  // opening number, not the sender's.
577  // (Therefore need to know whether Nym is sender or recipient.)
578  // Is that actually true? Or won't
579  // the harvest process be smart enough to figure that out
580  // already? And will it know that the
581  // recipient still needs to harvest HIS opening number, even if
582  // the transaction was attempted,
583  // since the recipient's number wasn't marked as "used" unless
584  // the transaction itself succeeded.
585  // NOTE: CronItem/Agreement/PaymentPlan is definitely smart
586  // enough already to know if the Nym is
587  // the sender or recipient. It will only grab the appropriate
588  // number for the right Nym. But here
589  // in THIS function we still have to be smart enough not to call
590  // it for the SENDER if the transaction
591  // was attempted (because it must be burned already), but TO call
592  // it for the sender if the transaction
593  // was not even attempted (meaning it wasn't burned yet.)
594  // Similarly, this function has to be smart
595  // enough TO call it for the recipient if transaction was
596  // attempted but didn't succeed, since the
597  // recipient's opening number is still good in that case.
598  //
599 
600  const OTIdentifier theNymID(theNym);
601 
602  // Assumption: if theNymID matches GetUserID(), then theNym
603  // must be the SENDER / PAYER!
604  // Else, he must be RECIPIENT / PAYEE, instead!
605  // This assumption is not for proving, since the harvest functions
606  // will verify the Nym's identity
607  // anyway. Instead, this assumption is merely for deciding which
608  // logic to use about which harvest
609  // functions to call.
610  //
611  if (theNymID == GetUserID()) // theNym is SENDER / PAYER
612  {
613  // If the server reply message was unambiguously a FAIL, that
614  // means the opening number is STILL GOOD.
615  // (Because the transaction therefore never even had a chance to
616  // run.)
617  //
618  if (bReplyWasFailure && !bHarvestingForRetry) {
619  bSuccess = theNym.ClawbackTransactionNumber(
621  GetTransactionNum()); // bSave=false, pSignerNym=nullptr
622  }
623  // Else if the server reply message was unambiguously a SUCCESS,
624  // that means the opening number is DEFINITELY
625  // NOT HARVESTABLE. (For the sender, anyway.) Why not? Because
626  // that means the transaction definitely ran--and
627  // the opener is marked as "used" on success, and "burned" on
628  // failure--either way, that's bad for harvesting (no point.)
629  //
630  else if (bReplyWasSuccess) {
631  if (bTransactionWasSuccess) {
632  // This means the "paymentPlan" transaction# is MARKED
633  // AS "USED", and will someday be marked as CLOSED.
634  // EITHER WAY, you certainly can't claw that number back
635  // now! (It is still outstanding, though. It's not gone,
636  // yet...)
637  // bSuccess =
638  // theNym.ClawbackTransactionNumber(GetPurportedServerID(),
639  // GetTransactionNum());
640  // //bSave=false, pSignerNym=nullptr
641  }
642  else if (bTransactionWasFailure) {
643  // Whereas if the transaction was a failure, that means
644  // the transaction number was DEFINITELY burned.
645  // (No point clawing it back now--it's gone already.)
646  // bSuccess =
647  // theNym.ClawbackTransactionNumber(GetPurportedServerID(),
648  // GetTransactionNum());
649  // //bSave=false, pSignerNym=nullptr
650  }
651  }
652  }
653 
654  // theNym is RECIPIENT / PAYEE
655  //
656  // This case is slightly different because above, a successful
657  // message with a failed transaction will burn the
658  // opening number, whereas here, if the message is successful but
659  // the transaction is failed, the recipient's
660  // opening transaction number is STILL GOOD and can be harvested!
661  // TODO: Make sure payment plans drop a NOTICE
662  // to the recipient, so he can harvest his numbers when this happens
663  // (similar to todos I have for smart contracts.)
664  //
665  // The other big difference with the recipient is that he has a
666  // different opening and closing number than the sender
667  // does, so I need to see if I can get those from the transaction,
668  // or if I have to load up the attached cron item
669  // to get that data.
670  //
671  else // theNym is RECIPIENT / PAYEE
672  {
673  // What is this class doing here?
674  // Answer: it's the C++ equivalent of local functions.
675  //
676  class _getRecipientOpeningNum
677  {
678  public:
679  int64_t Run(OTTransaction& theTransaction)
680  {
681  OTItem* pItem =
682  theTransaction.GetItem(OTItem::paymentPlan);
683  if (nullptr != pItem) {
684  // Also load up the Payment Plan from inside the
685  // transaction item.
686  //
687  OTString strPaymentPlan;
688  OTPaymentPlan thePlan;
689  pItem->GetAttachment(strPaymentPlan);
690 
691  if (strPaymentPlan.Exists() &&
692  thePlan.LoadContractFromString(strPaymentPlan))
693  return thePlan.GetRecipientOpeningNum();
694  else
695  otErr << "OTTransaction::HarvestOpeningNumber: "
696  "Error: Unable to load "
697  "paymentPlan object from paymentPlan "
698  "transaction item.\n";
699  }
700  else
701  otErr << "OTTransaction::HarvestOpeningNumber: "
702  "Error: Unable to find "
703  "paymentPlan item in paymentPlan "
704  "transaction.\n";
705  return 0;
706  }
707  }; // class _getRecipientOpeningNum
708 
709  // If the server reply message was unambiguously a FAIL, that
710  // means the opening number is STILL GOOD.
711  // (Because the transaction therefore never even had a chance to
712  // run.)
713  //
714  if (bReplyWasFailure && !bHarvestingForRetry) {
715  _getRecipientOpeningNum getRecipientOpeningNum;
716  const int64_t lRecipientOpeningNum =
717  getRecipientOpeningNum.Run(*this);
718 
719  if (lRecipientOpeningNum > 0)
720  bSuccess = theNym.ClawbackTransactionNumber(
722  lRecipientOpeningNum); // bSave=false,
723  // pSignerNym=nullptr
724  }
725  // Else if the server reply message was unambiguously a SUCCESS,
726  // then the next question is whether the
727  // TRANSACTION INSIDE IT was also a success, or if there's a
728  // "success message / failed transaction" situation
729  // going on here. For the recipient, that's important: in the
730  // first case, his opener is definitely marked as "used
731  // but still outstanding" and CANNOT be harvested. But in the
732  // second case, unlike with the sender, his opener IS
733  // harvestable!
734  // This is because of a peculiarity with payment plans: the
735  // recipient's opening number is not marked as used until
736  // the transaction itself is a success!
737  //
738  else if (bReplyWasSuccess) {
739  if (bTransactionWasSuccess) // The opener is DEFINITELY
740  // marked as "used but still
741  // outstanding" and CANNOT be
742  // harvested.
743  {
744  // This means the "paymentPlan" transaction# is MARKED
745  // AS "USED", and will someday be marked as CLOSED.
746  // EITHER WAY, you certainly can't claw that number back
747  // now! (It is still outstanding, though. It's not gone,
748  // yet...)
749  // bSuccess =
750  // theNym.ClawbackTransactionNumber(GetPurportedServerID(),
751  // RECIPIENTS--OPENING--NUMBER--GOES--HERE);
752  // //bSave=false, pSignerNym=nullptr
753  }
754  else if (bTransactionWasFailure && !bHarvestingForRetry) {
755  // In this case, unlike with the sender, the recipient's
756  // opener IS still harvestable! This is because
757  // of a peculiarity with payment plans: the recipient's
758  // opening number is not marked as used until the
759  // transaction itself is a success! Therefore, if the
760  // transaction was a failure, that means the recipient's
761  // opening number is DEFINITELY STILL GOOD.
762  //
763  _getRecipientOpeningNum getRecipientOpeningNum;
764  const int64_t lRecipientOpeningNum =
765  getRecipientOpeningNum.Run(*this);
766 
767  if (lRecipientOpeningNum > 0)
768  bSuccess = theNym.ClawbackTransactionNumber(
770  lRecipientOpeningNum); // bSave=false,
771  // pSignerNym=nullptr
772  }
773  }
774  }
775  }
776  break;
777 
778  // TODO: Make sure that when a user receives a success notice that a smart
779  // contract has been started up,
780  // that he marks his opener as "burned" instead of as "used." It's gone!
781  // Also: if the user receives a message failure notice (not done yet) then
782  // he can mark his opening #
783  // as "new" again! But if he instead receives a "message success but
784  // transaction failure", (todo: notice)
785  // then he must burn his opening #, as that is what the server has already
786  // done.
787  //
788  // In the case where message and transaction were BOTH success, then the
789  // user's existing setup is already
790  // correct. (The openers AND closers are already marked as "used but still
791  // issued" on the client side, and
792  // the server-side sees things that way already as well.)
793  //
794 
795  case OTTransaction::smartContract: // Uses X transaction #s, with an opener
796  // for each party and a closer for each
797  // asset account.
798  // If the message is rejected by the server, then ALL openers can be
799  // harvested. But if the
800  // message was successful (REGARDLESS of whether the transaction was
801  // successful) then all of
802  // the openers for all of the parties have been burned. The closers,
803  // meanwhile, can be recovered
804  // if the message is a failure, as well as in cases where message
805  // succeeds but transaction failed.
806  // But if transaction succeeded, then the closers CANNOT be recovered.
807  // (Only removed, once you sign
808  // off on the receipt.)
809  {
810 
811  OTItem* pItem = GetItem(OTItem::smartContract);
812 
813  if (nullptr == pItem) {
814  otErr << "OTTransaction::HarvestOpeningNumber: Error: Unable "
815  "to find "
816  "smartContract item in smartContract transaction.\n";
817  }
818  else // Load up the smart contract...
819  {
820  OTString strSmartContract;
821  OTSmartContract theSmartContract(GetPurportedServerID());
822  pItem->GetAttachment(strSmartContract);
823 
824  // If we failed to load the smart contract...
825  if (!strSmartContract.Exists() ||
826  (false ==
827  theSmartContract.LoadContractFromString(
828  strSmartContract))) {
829  otErr << "OTTransaction::HarvestOpeningNumber: Error: "
830  "Unable to load "
831  "smartContract object from smartContract "
832  "transaction item.\n";
833  }
834  else // theSmartContract is ready to go....
835  {
836 
837  // The message reply itself was a failure. This means the
838  // transaction itself never got a chance
839  // to run... which means ALL the opening numbers on that
840  // transaction are STILL GOOD.
841  //
842  if (bReplyWasFailure && !bHarvestingForRetry) {
843  // If I WAS harvesting for a re-try, I'd want to leave
844  // the opening number
845  // on this smart contract
846  theSmartContract.HarvestOpeningNumber(theNym);
847  bSuccess = true;
848  }
849  // Else if the server reply message was unambiguously a
850  // SUCCESS, that means the opening number is DEFINITELY NOT
851  // HARVESTABLE.
852  // Why? Because that means the transaction definitely
853  // ran--and the opener is marked as "used" on SUCCESS, or
854  // "burned" on
855  // FAILURE--either way, that's bad for harvesting (no
856  // point.)
857  //
858  else if (bReplyWasSuccess) {
859  if (bTransactionWasSuccess) {
860  // This means the "smartContract" opening trans# is
861  // MARKED AS "USED", and will someday be marked as
862  // CLOSED.
863  // EITHER WAY, you certainly can't claw that number
864  // back now! (It is still outstanding, though. It's
865  // not gone, yet...)
866  //
867  // theSmartContract.HarvestOpeningNumber(theNym);
868  // bSuccess = true;
869  }
870  else if (bTransactionWasFailure) {
871  // Whereas if the transaction was a failure, that
872  // means the opening trans number was DEFINITELY
873  // burned.
874  // (No point clawing it back now--it's gone
875  // already.)
876  //
877  // theSmartContract.HarvestOpeningNumber(theNym);
878  // bSuccess = true;
879  }
880  } // else if (bReplyWasSuccess)
881 
882  } // else (smart contract loaded successfully)
883  } // pItem was found.
884  }
885  break;
886 
887  default:
888  break;
889  }
890 
891  return bSuccess;
892 }
EXPORT OTItem * GetItem(OTItem::itemType theType)
const OTIdentifier & GetPurportedServerID() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
transactionType m_Type
const OTIdentifier & GetUserID() const
void opentxs::OTTransaction::InitTransaction ( )

Definition at line 3326 of file OTTransaction.cpp.

3327 {
3328  m_strContractType = "TRANSACTION"; // CONTRACT, MESSAGE, TRANSACTION,
3329  // LEDGER, TRANSACTION ITEM
3330  m_DATE_SIGNED = OT_TIME_ZERO; // Make sure to set this to the current time
3331  // whenever contract is signed.
3334  m_lRequestNumber = 0;
3335  m_bReplyTransSuccess = false;
3336 }
OTString m_strContractType
Definition: OTContract.hpp:178
transactionType m_Type
#define OT_TIME_ZERO
Definition: Common.hpp:180
bool opentxs::OTTransaction::IsAbbreviated ( ) const
inline

Definition at line 582 of file OTTransaction.hpp.

583  {
584  return m_bIsAbbreviated;
585  }
EXPORT bool opentxs::OTTransaction::IsCancelled ( )
inline

Definition at line 565 of file OTTransaction.hpp.

566  {
567  return m_bCancelled;
568  }
int32_t opentxs::OTTransaction::ProcessXMLNode ( irr::io::IrrXMLReader *&  xml)
protectedvirtual

Reimplemented from opentxs::OTContract.

Definition at line 4061 of file OTTransaction.cpp.

4062 {
4063  const OTString strNodeName = xml->getNodeName();
4064 
4065  OTNumList* pNumList = nullptr;
4066  if (strNodeName.Compare("nymboxRecord")) {
4067  pNumList = &m_Numlist;
4068  }
4069 
4070  if (strNodeName.Compare("nymboxRecord") ||
4071  strNodeName.Compare("inboxRecord") ||
4072  strNodeName.Compare("outboxRecord") ||
4073  strNodeName.Compare("paymentInboxRecord") ||
4074  strNodeName.Compare("recordBoxRecord") ||
4075  strNodeName.Compare("expiredBoxRecord")) {
4076  int64_t lNumberOfOrigin = 0;
4077  int64_t lTransactionNum = 0;
4078  int64_t lInRefTo = 0;
4079  int64_t lInRefDisplay = 0;
4080 
4081  time64_t the_DATE_SIGNED = OT_TIME_ZERO;
4082  int theType = OTTransaction::error_state; // default
4083  OTString strHash;
4084 
4085  int64_t lAdjustment = 0;
4086  int64_t lDisplayValue = 0;
4087  int64_t lClosingNum = 0;
4088  int64_t lRequestNumber = 0;
4089  bool bReplyTransSuccess = false;
4090 
4091  int32_t nAbbrevRetVal = LoadAbbreviatedRecord(
4092  xml, lNumberOfOrigin, lTransactionNum, lInRefTo, lInRefDisplay,
4093  the_DATE_SIGNED, theType, strHash, lAdjustment, lDisplayValue,
4094  lClosingNum, lRequestNumber, bReplyTransSuccess, pNumList);
4095 
4096  if ((-1) == nAbbrevRetVal)
4097  return (-1); // The function already logs appropriately.
4098 
4099  m_bIsAbbreviated = true;
4100 
4101  SetNumberOfOrigin(lNumberOfOrigin);
4102  SetTransactionNum(lTransactionNum);
4103  SetReferenceToNum(lInRefTo);
4104  SetClosingNum(lClosingNum);
4105  SetRequestNum(lRequestNumber);
4106 
4107  SetReplyTransSuccess(bReplyTransSuccess);
4108 
4109  m_lInRefDisplay = lInRefDisplay;
4110  m_lAbbrevAmount = lAdjustment;
4111  m_lDisplayAmount = lDisplayValue;
4112  m_DATE_SIGNED = the_DATE_SIGNED;
4113  m_Type = static_cast<OTTransaction::transactionType>(theType);
4114 
4115  if (strHash.Exists())
4116  m_Hash.SetString(strHash);
4117  else
4118  otErr << "OTTransaction::ProcessXMLNode: Missing receiptHash on "
4119  "abbreviated record.\n";
4120 
4121  return 1;
4122  }
4123 
4124  // THIS PART is probably what you're looking for.
4125  else if (strNodeName.Compare("transaction")) // Todo: notice how this "else
4126  // if" uses OTString::Compare,
4127  // where most other
4128  // ProcessXMLNode functions in
4129  // OT use !strcmp()? (That's
4130  // right: Buffer overflow. Need
4131  // to fix elsewhere as it is
4132  // fixed here.)
4133  {
4134 
4135  const OTString strType = xml->getAttributeValue("type");
4136 
4137  if (strType.Exists())
4139  else {
4140  otOut << "OTTransaction::ProcessXMLNode: Failure: unknown "
4141  "transaction type: " << strType << " \n";
4142  return (-1);
4143  }
4144 
4145  OTString strCancelled = xml->getAttributeValue("cancelled");
4146  if (strCancelled.Exists() && strCancelled.Compare("true"))
4147  m_bCancelled = true;
4148  else
4149  m_bCancelled = false;
4150 
4151  OTString strDateSigned = xml->getAttributeValue("dateSigned");
4152  const int64_t lDateSigned =
4153  strDateSigned.Exists() ? atol(strDateSigned.Get()) : 0;
4154  m_DATE_SIGNED = OTTimeGetTimeFromSeconds(lDateSigned); // Todo casting ?
4155 
4156  const OTString strAcctID = xml->getAttributeValue("accountID");
4157  const OTString strServerID = xml->getAttributeValue("serverID");
4158  const OTString strUserID = xml->getAttributeValue("userID");
4159 
4160  if (!strAcctID.Exists() || !strServerID.Exists() ||
4161  !strUserID.Exists()) {
4162  otOut
4163  << "OTTransaction::ProcessXMLNode: Failure: missing strAcctID ("
4164  << strAcctID << ") or strServerID (" << strServerID
4165  << ") or strUserID (" << strUserID << "). \n";
4166  return (-1);
4167  }
4168 
4169  const OTString strOrigin = xml->getAttributeValue("numberOfOrigin");
4170  const OTString strTransNum = xml->getAttributeValue("transactionNum");
4171  const OTString strInRefTo = xml->getAttributeValue("inReferenceTo");
4172 
4173  if (!strTransNum.Exists() || !strInRefTo.Exists()) {
4174  otOut << "OTTransaction::ProcessXMLNode: Failure: missing "
4175  "strTransNum (" << strTransNum << ") or strInRefTo ("
4176  << strInRefTo << "). \n";
4177  return (-1);
4178  }
4179 
4180  // a replyNotice (a copy of the server's reply to one of my messages)
4181  // is often dropped into my Nymbox, to make sure I see it. Usually these
4182  // have a REQUEST NUMBER on them, so I can quickly tell WHICH MESSAGE
4183  // it is in reply to.
4184  //
4186  const OTString strRequestNum =
4187  xml->getAttributeValue("requestNumber");
4188 
4189  if (strRequestNum.Exists())
4190  m_lRequestNumber = atol(strRequestNum.Get());
4191 
4192  const OTString strTransSuccess =
4193  xml->getAttributeValue("transSuccess");
4194 
4195  m_bReplyTransSuccess = strTransSuccess.Compare("true");
4196  }
4197 
4198  if ((OTTransaction::blank == m_Type) ||
4200  const OTString strTotalList =
4201  xml->getAttributeValue("totalListOfNumbers");
4202  m_Numlist.Release();
4203 
4204  if (strTotalList.Exists())
4205  m_Numlist.Add(strTotalList); // (Comma-separated list of numbers
4206  // now becomes std::set<int64_t>.)
4207  }
4208 
4209  OTIdentifier ACCOUNT_ID(strAcctID), SERVER_ID(strServerID),
4210  USER_ID(strUserID);
4211 
4213  ACCOUNT_ID); // GetPurportedAccountID() const { return m_AcctID; }
4214  SetPurportedServerID(SERVER_ID); // GetPurportedServerID() const {
4215  // return m_AcctServerID; }
4216  SetUserID(USER_ID);
4217 
4218  // m_bLoadSecurely defaults to true.
4219  // Normally the RealAccountID and RealServerID are set from above,
4220  // before
4221  // loading. That way, I can compare them to whatever is actually loaded.
4222  // (So people don't swap files on us!!)
4223  // But if the coder SPECIALLY sets m_bLoadSecurely to FALSE, that means
4224  // he
4225  // honestly doesn't know those IDs, and he is loading the file, and he
4226  // wants it
4227  // to load up properly AS IF THE IDs IN THE FILE WERE CORRECT. He only
4228  // does this
4229  // because it's the only way to get the file loaded without knowing
4230  // those IDs in
4231  // advance, and because he takes care, when doing this, to check them
4232  // after the fact
4233  // and see if they are, indeed, the ones he was expecting.
4234  //
4235  // This mechanism was ONLY FINALLY ADDED to get the class factory
4236  // working properly.
4237  // And even in this case, it is still INTERNALLY CONSISTENT. (The
4238  // sub-items will still
4239  // be expected to be correct with their parent items.)
4240  //
4241  if (!m_bLoadSecurely) {
4242  SetRealAccountID(ACCOUNT_ID);
4243  SetRealServerID(SERVER_ID);
4244  }
4245 
4246  if (strOrigin.Exists()) SetNumberOfOrigin(atol(strOrigin.Get()));
4247 
4248  SetTransactionNum(atol(strTransNum.Get()));
4249  SetReferenceToNum(atol(strInRefTo.Get()));
4250 
4251  otLog4 << "Loaded transaction " << GetTransactionNum()
4252  << ", in reference to: " << GetReferenceToNum()
4253  << " type: " << strType << "\n";
4254 
4255  return 1;
4256  }
4257  else if (!strcmp("closingTransactionNumber", xml->getNodeName())) {
4258  OTString strClosingNumber = xml->getAttributeValue("value");
4259 
4260  if (strClosingNumber.Exists() &&
4263  m_lClosingTransactionNo = atol(strClosingNumber.Get());
4264  }
4265  else {
4266  otErr << "Error in OTTransaction::ProcessXMLNode: "
4267  "closingTransactionNumber field without value, or in "
4268  "wrong transaction type.\n";
4269  return (-1); // error condition
4270  }
4271 
4272  return 1;
4273  }
4274  else if (!strcmp("cancelRequest", xml->getNodeName())) {
4275  if (false ==
4277  otErr << "Error in OTTransaction::ProcessXMLNode: cancelRequest "
4278  "field without value.\n";
4279  return (-1); // error condition
4280  }
4281 
4282  return 1;
4283  }
4284  else if (!strcmp("inReferenceTo", xml->getNodeName())) {
4285  if (false ==
4287  otErr << "Error in OTTransaction::ProcessXMLNode: inReferenceTo "
4288  "field without value.\n";
4289  return (-1); // error condition
4290  }
4291 
4292  return 1;
4293  }
4294  else if (!strcmp("item", xml->getNodeName())) {
4295  OTString strData;
4296 
4297  if (!OTContract::LoadEncodedTextField(xml, strData) ||
4298  !strData.Exists()) {
4299  otErr << "Error in OTTransaction::ProcessXMLNode: transaction item "
4300  "field without value.\n";
4301  return (-1); // error condition
4302  }
4303  else {
4304  OTItem* pItem = new OTItem(GetUserID(), *this);
4305  OT_ASSERT(nullptr != pItem);
4306 
4307  if (!m_bLoadSecurely) pItem->SetLoadInsecure();
4308 
4309  // If we're able to successfully base64-decode the string and load
4310  // it up as
4311  // a transaction, then add it to the ledger's list of transactions
4312  if (!pItem->LoadContractFromString(strData)) {
4313  otErr << "ERROR: OTTransaction failed loading item from "
4314  "string: \n\n"
4315  << (strData.Exists() ? strData.Get() : "") << "\n\n";
4316  delete pItem;
4317  pItem = nullptr;
4318  return (-1);
4319  }
4320  else if (!pItem->VerifyContractID()) {
4321  otErr << "ERROR: Failed verifying transaction Item in "
4322  "OTTransaction::ProcessXMLNode: \n\n" << strData
4323  << "\n\n";
4324  delete pItem;
4325  pItem = nullptr;
4326  return (-1);
4327  }
4328  else {
4329  m_listItems.push_back(pItem);
4330  // otLog5 << "Loaded transaction Item and adding
4331  // to m_listItems in OTTransaction\n");
4332  }
4333  }
4334 
4335  return 1;
4336  }
4337 
4338  return 0;
4339 }
OTLOG_IMPORT OTLogStream otLog4
int32_t LoadAbbreviatedRecord(irr::io::IrrXMLReader *&xml, int64_t &lNumberOfOrigin, int64_t &lTransactionNum, int64_t &lInRefTo, int64_t &lInRefDisplay, time64_t &the_DATE_SIGNED, int &theType, OTString &strHash, int64_t &lAdjustment, int64_t &lDisplayValue, int64_t &lClosingNum, int64_t &lRequestNum, bool &bReplyTransSuccess, OTNumList *pNumList=nullptr)
Definition: Helpers.cpp:218
EXPORT void SetNumberOfOrigin(int64_t lTransactionNum)
void SetTransactionNum(int64_t lTransactionNum)
EXPORT void Release()
Definition: OTNumList.cpp:465
OTLOG_IMPORT OTLogStream otOut
void SetRealAccountID(const OTIdentifier &theID)
time64_t OTTimeGetTimeFromSeconds(int64_t seconds)
Definition: Common.hpp:215
int64_t time64_t
Definition: Common.hpp:209
void SetRealServerID(const OTIdentifier &theID)
EXPORT void SetString(const char *szString)
EXPORT void SetClosingNum(int64_t lClosingNum)
OTASCIIArmor m_ascCancellationRequest
static EXPORT bool LoadEncodedTextField(irr::io::IrrXMLReader *&xml, OTASCIIArmor &ascOutput)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
static transactionType GetTypeFromString(const OTString &strType)
void SetReplyTransSuccess(bool bVal)
EXPORT int64_t GetReferenceToNum() const
void SetUserID(const OTIdentifier &theID)
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
EXPORT void SetReferenceToNum(int64_t lTransactionNum)
void SetRequestNum(const int64_t &lNum)
void SetPurportedServerID(const OTIdentifier &theID)
transactionType m_Type
const OTIdentifier & GetUserID() const
#define OT_TIME_ZERO
Definition: Common.hpp:180
void SetPurportedAccountID(const OTIdentifier &theID)
void opentxs::OTTransaction::ProduceInboxReportItem ( OTItem theBalanceItem)

Definition at line 5364 of file OTTransaction.cpp.

5365 {
5366  OTItem::itemType theItemType = OTItem::error_state;
5367 
5368  otLog3 << "Producing statement report item for inbox item type: "
5369  << GetTypeString() << ".\n"; // temp remove.
5370 
5371  switch (m_Type) { // These are the types that have an amount (somehow)
5372  case OTTransaction::pending: // the amount is stored on the transfer item in
5373  // my list.
5374  theItemType = OTItem::transfer;
5375  break;
5376  case OTTransaction::chequeReceipt: // the amount is stored on cheque
5377  // (attached to depositCheque item,
5378  // attached.)
5379  theItemType = OTItem::chequeReceipt;
5380  break;
5381  case OTTransaction::voucherReceipt: // the amount is stored on voucher
5382  // (attached to depositCheque item,
5383  // attached.)
5384  theItemType = OTItem::voucherReceipt;
5385  break;
5386  case OTTransaction::marketReceipt: // the amount is stored on marketReceipt
5387  // item
5388  theItemType = OTItem::marketReceipt;
5389  break;
5390  case OTTransaction::paymentReceipt: // amount is stored on paymentReceipt
5391  // item
5392  theItemType = OTItem::paymentReceipt;
5393  break;
5394  case OTTransaction::transferReceipt: // amount is 0 according to
5395  // GetReceiptAmount()
5396  theItemType = OTItem::transferReceipt;
5397  break;
5398  case OTTransaction::basketReceipt: // amount is stored on basketReceipt
5399  // item.
5400  theItemType = OTItem::basketReceipt;
5401  break;
5402  case OTTransaction::finalReceipt: // amount is 0 according to
5403  // GetReceiptAmount()
5404  theItemType = OTItem::finalReceipt;
5405  break;
5406  default: // All other types are irrelevant for inbox reports
5407  {
5408  otLog3 << "OTTransaction::ProduceInboxReportItem: Ignoring "
5409  << GetTypeString()
5410  << " transaction "
5411  "in inbox while making balance statement.\n";
5412  }
5413  return;
5414  } // why not transfer receipt? Because the amount was already removed from
5415  // your account when you transferred it,
5416  // and you already signed a balance agreement at that time. Thus, nothing in
5417  // your inbox is necessary to prove
5418  // the change in balance -- you already signed off on it. UPDATE: that's
5419  // okay since the below GetReceiptAmount()
5420  // will return 0 for a transfer receipt anyway.
5421 
5422  // In the case of a cron receipt which is in the inbox, but is being
5423  // accepted
5424  // by a notarizeProcessInbox, (if theOwner is a processInbox transaction)
5425  // then
5426  // we don't want to report that item. Why not? Because if the processInbox
5427  // is a
5428  // success, the item would be presumed removed. (That's what the process
5429  // aims to do,
5430  // after all: accept and remove the market receipt.) Therefore, I don't want
5431  // to add
5432  // it to the report, since the server will then think it's supposed to be
5433  // there, when
5434  // in fact it's supposed to be gone. I'm supposed to be showing a picture of
5435  // what would
5436  // be left in the event of a success. And if I successfully processed the
5437  // receipt out of my
5438  // inbox, then I would expect not to see it there anymore, so since that is
5439  // what I would
5440  // expect in that case, that is the picture I need to construct now.
5441  //
5442  // Thus, here we loop through theOwner (IF he's a process inbox transaction)
5443  // and we see
5444  // if he's actually trying to process a receipt off the inbox FOR ME (THIS
5445  // transaction.) If he is, then
5446  // we don't need to add this transaction to the report.
5447  //
5448 
5449  // the item will represent THIS TRANSACTION, and will be added to
5450  // theBalanceItem.
5451 
5452  OTItem* pReportItem = OTItem::CreateItemFromTransaction(*this, theItemType);
5453 
5454  if (nullptr !=
5455  pReportItem) // above line will assert if mem allocation fails.
5456  {
5457  int64_t lAmount = GetReceiptAmount();
5458  pReportItem->SetAmount(lAmount);
5459 
5460  pReportItem->SetTransactionNum(
5461  GetTransactionNum()); // Just making sure these both get set.
5462  pReportItem->SetReferenceToNum(
5463  GetReferenceToNum()); // Especially this one.
5464  pReportItem->SetNumberOfOrigin(GetNumberOfOrigin());
5465 
5466  // The "closing transaction number" is only used on finalReceipts and
5467  // basketReceipts.
5468  // FYI, Any cron receipts need to see if there is a corresponding final
5469  // receipt before checking
5470  // their transaction number for validity (since it changes that
5471  // number)... and also, if the final
5472  // receipt itself is present, then ALL of the cron receipts that it
5473  // corresponds to must be closed!
5474  //
5477  pReportItem->SetClosingNum(GetClosingNum());
5478 
5479  theBalanceItem.AddItem(
5480  *pReportItem); // Now theBalanceItem will handle cleaning it up.
5481 
5482  // No need to sign/save pReportItem, since it is just used for in-memory
5483  // storage, and is
5484  // otherwise saved as part of its owner's data, as part of its owner.
5485  // (As long as theBalanceItem
5486  // is signed and saved, which the caller does, then we're fine.)
5487  }
5488 }
virtual EXPORT int64_t GetNumberOfOrigin()
OTLOG_IMPORT OTLogStream otLog3
static EXPORT OTItem * CreateItemFromTransaction(const OTTransaction &theOwner, OTItem::itemType theType, const OTIdentifier *pDestinationAcctID=nullptr)
Definition: OTItem.cpp:1451
const char * GetTypeString() const
EXPORT int64_t GetClosingNum() const
EXPORT int64_t GetReferenceToNum() const
EXPORT int64_t GetReceiptAmount()
EXPORT int64_t GetTransactionNum() const
transactionType m_Type
void opentxs::OTTransaction::ProduceOutboxReportItem ( OTItem theBalanceItem)

Definition at line 5501 of file OTTransaction.cpp.

5502 {
5503  OTItem::itemType theItemType = OTItem::error_state;
5504 
5505  switch (m_Type) {
5507  theItemType = OTItem::transfer;
5508  break;
5509  default: // All other types are irrelevant for outbox reports.
5510  otErr
5511  << "ProduceOutboxReportItem: Error, wrong item type. Returning.\n";
5512  return;
5513  }
5514 
5515  // the item will represent THIS TRANSACTION, and will be added to
5516  // theBalanceItem.
5517 
5518  OTItem* pReportItem = OTItem::CreateItemFromTransaction(*this, theItemType);
5519 
5520  if (nullptr !=
5521  pReportItem) // above line will assert if mem allocation fails.
5522  {
5523  // I get away with "carte blanche" multiplying it by -1 here, because
5524  // I've
5525  // already verified that this is ONLY an OTTransaction::transfer before
5526  // even
5527  // getting this far. There is no other transaction type that I even have
5528  // to
5529  // worry about.
5530  const int64_t lAmount =
5531  GetReceiptAmount() * (-1); // in outbox, a transfer is leaving my
5532  // account. Balance gets smaller.
5533  pReportItem->SetAmount(lAmount);
5534 
5535  pReportItem->SetTransactionNum(
5536  GetTransactionNum()); // Just making sure these both get set.
5537  pReportItem->SetReferenceToNum(
5538  GetReferenceToNum()); // Especially this one.
5539  pReportItem->SetNumberOfOrigin(GetNumberOfOrigin());
5540 
5541  theBalanceItem.AddItem(
5542  *pReportItem); // Now theBalanceItem will handle cleaning it up.
5543 
5544  // No need to sign/save pReportItem, since it is just used for in-memory
5545  // storage, and is
5546  // otherwise saved as part of its owner's data, as part of its owner.
5547  // (As long as theBalanceItem
5548  // is signed and saved, which the caller does, then we're fine.)
5549  }
5550 }
virtual EXPORT int64_t GetNumberOfOrigin()
static EXPORT OTItem * CreateItemFromTransaction(const OTTransaction &theOwner, OTItem::itemType theType, const OTIdentifier *pDestinationAcctID=nullptr)
Definition: OTItem.cpp:1451
EXPORT int64_t GetReferenceToNum() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetReceiptAmount()
EXPORT int64_t GetTransactionNum() const
transactionType m_Type
void opentxs::OTTransaction::Release ( void  )
virtual

Reimplemented from opentxs::OTTransactionType.

Definition at line 3501 of file OTTransaction.cpp.

3502 {
3503  while (!m_listItems.empty()) {
3504  OTItem* pItem = m_listItems.front();
3505  m_listItems.pop_front();
3506  delete pItem;
3507  }
3508 
3510 }
void opentxs::OTTransaction::SaveAbbrevExpiredBoxRecord ( OTString strOutput)

Definition at line 4640 of file OTTransaction.cpp.

4641 {
4642  int64_t lDisplayValue = 0;
4643 
4644  switch (m_Type) {
4645  // PAYMENT INBOX / PAYMENT OUTBOX
4647  if (IsAbbreviated()) // not the actual value of 0.
4648  lDisplayValue = GetAbbrevDisplayAmount();
4649  else
4650  lDisplayValue = GetReceiptAmount();
4651  break;
4653  if (IsAbbreviated()) // not the actual value of 0.
4654  lDisplayValue = GetAbbrevDisplayAmount();
4655  else
4656  lDisplayValue = 0;
4657  break;
4658  case OTTransaction::notice: // A notice from the server. Used in Nymbox.
4659  // Probably contains an updated smart contract.
4660  if (IsAbbreviated()) // not the actual value of 0.
4661  lDisplayValue = GetAbbrevDisplayAmount();
4662  else
4663  lDisplayValue = 0;
4664  break;
4665  default: // All other types are irrelevant for inbox reports
4666  {
4667  otErr
4668  << "OTTransaction::" << __FUNCTION__ << ": Unexpected "
4669  << GetTypeString()
4670  << " transaction "
4671  "in expired box while making abbreviated expired-box record.\n";
4672 
4673  OT_FAIL_MSG("ASSERT: OTTransaction::SaveAbbrevExpiredBoxRecord: "
4674  "Unexpected transaction type.");
4675  }
4676  return;
4677  }
4678 
4679  // By this point, we know only the right types of receipts are being saved,
4680  // and
4681  // the adjustment and display value are both set correctly.
4682 
4683  // TYPE
4684  OTString strType;
4685  const char* pTypeStr = GetTypeString();
4686  strType.Set((nullptr != pTypeStr) ? pTypeStr : "error_state");
4687 
4688  // DATE SIGNED
4689  const int64_t lDateSigned = OTTimeGetSecondsFromTime(m_DATE_SIGNED);
4690 
4691  // HASH OF THE COMPLETE "BOX RECEIPT"
4692  // Save abbreviated is only used for receipts in boxes such as inbox,
4693  // outbox, and nymbox.
4694  // (Thus the moniker "Box Receipt", as contrasted with cron receipts or
4695  // normal transaction receipts with balance agreements.)
4696  //
4697  OTString strHash;
4698 
4699  // If this is already an abbreviated record, then save the existing hash.
4700  if (IsAbbreviated()) m_Hash.GetString(strHash);
4701  // Otherwise if it's a full record, then calculate the hash and save it.
4702  else {
4703  OTIdentifier idReceiptHash; // a hash of the actual transaction is
4704  // stored with its
4705  CalculateContractID(idReceiptHash); // abbreviated short-form
4706  // record (in the expired box,
4707  // for example.)
4708  idReceiptHash.GetString(strHash);
4709  }
4710 
4711  strOutput.Concatenate("<expiredBoxRecord type=\"%s\"\n"
4712  " dateSigned=\"%lld\"\n"
4713  " receiptHash=\"%s\"\n"
4714  " displayValue=\"%lld\"\n"
4715  " transactionNum=\"%lld\"\n"
4716  " inRefDisplay=\"%lld\"\n"
4717  " inReferenceTo=\"%lld\" />\n\n",
4718  strType.Get(), lDateSigned, strHash.Get(),
4719  lDisplayValue, GetTransactionNum(),
4721 }
const char * GetTypeString() const
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
EXPORT int64_t GetReferenceToNum() const
EXPORT int64_t GetReferenceNumForDisplay()
int64_t GetAbbrevDisplayAmount() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetReceiptAmount()
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
EXPORT void GetString(OTString &theStr) const
transactionType m_Type
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
Definition: OTContract.cpp:367
void opentxs::OTTransaction::SaveAbbreviatedInboxRecord ( OTString strOutput)

Definition at line 5184 of file OTTransaction.cpp.

5185 {
5186  // This is the actual amount that your account is changed BY this receipt.
5187  // Versus the useful amount the user will want to see (lDisplayValue.) For
5188  // example, if you perform
5189  // a transfer of 500 clams, then the money leaves your account at that time,
5190  // and you receive a transaction receipt
5191  // to that effect. LATER ON, when the recipient ACCEPTS the transfer, a
5192  // "transferReceipt" will pop into your inbox,
5193  // which you must accept in order to close out the transaction number. But
5194  // this transferReceipt "adjusts" your account
5195  // by ZERO, since the amount has ALREADY left your account before the
5196  // transferReceipt arrived. In that example, the
5197  // lAdjustment would be 0, while the lDisplayValue would be 500. The first
5198  // value is the actual impact on your balance
5199  // from that specific receipt, whereas the second value is the one that the
5200  // user probably wants to see.
5201 
5202  // NOTE: A similar logic envelops the GetReferenceNumForDisplay() field,
5203  // which, instead of returning the ACTUAL
5204  // ref# that OT needs to use, it will return the one that the user probably
5205  // wants to see.
5206  //
5207  int64_t lAdjustment = 0, lDisplayValue = 0;
5208 
5209  switch (m_Type) {
5210  // -- In inbox, pending hasn't been accepted yet. In outbox, it's already
5211  // gone. Either
5212  // way, it will have a 0 adjustment amount, even though perhaps 500 clams
5213  // display amount. Here I use the 500
5214  // for display, but in SaveAbbrevToOutbox, I multiply it by -1 so it appears
5215  // as -500 (leaving my account.)
5216  // -- In my inbox, the transferReceipt is notice of money that is already
5217  // gone. It thus has adjustment value of 0.
5218  // But the DISPLAY amount is the amount I originally sent. (Already
5219  // multiplied by -1 by GetReceiptAmount())
5220  //
5221  case OTTransaction::pending: // (The pending amount is stored on the
5222  // transfer item in my list of transaction
5223  // items.)
5224  case OTTransaction::transferReceipt: // The transferReceipt and
5225  // voucherReceipt amounts are the
5226  // display value (according to
5227  case OTTransaction::voucherReceipt: // GetReceiptAmount()), and not the
5228  // actual value of 0.
5229  if (IsAbbreviated()) {
5230  lAdjustment = GetAbbrevAdjustment();
5231  lDisplayValue = GetAbbrevDisplayAmount();
5232  }
5233  else {
5234  lAdjustment = 0;
5235  lDisplayValue = GetReceiptAmount();
5236  }
5237  break;
5238  // If chequeReceipt for 100 clams hit my inbox, then my balance is -100 from
5239  // where it was. (Same
5240  // value should be displayed.) Luckily, GetReceiptAmount() already
5241  // multiplies by (-1) for chequeReceipt.
5242  // For these (marketReceipt, paymentReceipt, basketReceipt), the actual
5243  // adjustment is positive OR negative
5244  // already, and the display value should match.
5245  case OTTransaction::chequeReceipt: // the amount is stored on cheque
5246  // (attached to depositCheque item,
5247  // attached.)
5248  case OTTransaction::marketReceipt: // amount is stored on marketReceipt
5249  // item. |
5250  case OTTransaction::paymentReceipt: // amount is stored on paymentReceipt
5251  // item. | and the display value should
5252  // match.
5253  case OTTransaction::basketReceipt: // amount is stored on basketReceipt
5254  // item. |
5255  if (IsAbbreviated()) // not the actual value of 0.
5256  {
5257  lAdjustment = GetAbbrevAdjustment();
5258  lDisplayValue = GetAbbrevDisplayAmount();
5259  }
5260  else {
5261  lAdjustment = GetReceiptAmount();
5262  lDisplayValue = lAdjustment;
5263  }
5264  break;
5265  case OTTransaction::finalReceipt: // amount is 0 according to
5266  // GetReceiptAmount()
5267  if (IsAbbreviated()) // not the actual value of 0.
5268  {
5269  lAdjustment = GetAbbrevAdjustment();
5270  lDisplayValue = GetAbbrevDisplayAmount();
5271  }
5272  else {
5273  lAdjustment = 0;
5274  lDisplayValue = 0;
5275  }
5276  break;
5277  default: // All other types are irrelevant for inbox reports
5278  {
5279  otErr << "OTTransaction::" << __FUNCTION__ << ": Unexpected "
5280  << GetTypeString()
5281  << " transaction "
5282  "in inbox while making abbreviated inbox record.\n";
5283 
5284  OT_FAIL_MSG("ASSERT: OTTransaction::SaveAbbreviatedInboxRecord: "
5285  "unexpected transaction type.");
5286  }
5287  return;
5288  } // why not transfer receipt? Because the amount was already removed from
5289  // your account when you transferred it,
5290 
5291  // By this point, we know only the right types of receipts are being saved,
5292  // and
5293  // the adjustment and display value are both set correctly.
5294 
5295  // TYPE
5296  OTString strType;
5297  const char* pTypeStr = GetTypeString();
5298  strType.Set((nullptr != pTypeStr) ? pTypeStr : "error_state");
5299 
5300  // DATE SIGNED
5301  const int64_t lDateSigned = OTTimeGetSecondsFromTime(m_DATE_SIGNED);
5302 
5303  // HASH OF THE COMPLETE "BOX RECEIPT"
5304  // Save abbreviated is only used for receipts in boxes such as inbox,
5305  // outbox, and nymbox.
5306  // (Thus the moniker "Box Receipt", as contrasted with cron receipts or
5307  // normal transaction receipts with balance agreements.)
5308  //
5309  OTString strHash;
5310 
5311  // If this is already an abbreviated record, then save the existing hash.
5312  if (IsAbbreviated()) m_Hash.GetString(strHash);
5313  // Otherwise if it's a full record, then calculate the hash and save it.
5314  else {
5315  OTIdentifier idReceiptHash; // a hash of the actual transaction is
5316  // stored with its
5317  CalculateContractID(idReceiptHash); // abbreviated short-form
5318  // record (in the inbox, for
5319  // example.)
5320  idReceiptHash.GetString(strHash);
5321  }
5322 
5325 
5326  strOutput.Concatenate(
5327  "<inboxRecord type=\"%s\"\n"
5328  " dateSigned=\"%lld\"\n"
5329  " receiptHash=\"%s\"\n"
5330  " adjustment=\"%lld\"\n"
5331  " displayValue=\"%lld\"\n"
5332  " numberOfOrigin=\"%lld\"\n"
5333  " transactionNum=\"%lld\"\n"
5334  " closingNum=\"%lld\"\n"
5335  " inRefDisplay=\"%lld\"\n"
5336  " inReferenceTo=\"%lld\" />\n\n",
5337  strType.Get(), lDateSigned, strHash.Get(), lAdjustment,
5338  lDisplayValue, GetRawNumberOfOrigin(), GetTransactionNum(),
5340  else
5341  strOutput.Concatenate("<inboxRecord type=\"%s\"\n"
5342  " dateSigned=\"%lld\"\n"
5343  " receiptHash=\"%s\"\n"
5344  " adjustment=\"%lld\"\n"
5345  " displayValue=\"%lld\"\n"
5346  " numberOfOrigin=\"%lld\"\n"
5347  " transactionNum=\"%lld\"\n"
5348  " inRefDisplay=\"%lld\"\n"
5349  " inReferenceTo=\"%lld\" />\n\n",
5350  strType.Get(), lDateSigned, strHash.Get(),
5351  lAdjustment, lDisplayValue,
5354 }
int64_t GetAbbrevAdjustment() const
const char * GetTypeString() const
EXPORT int64_t GetClosingNum() const
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
EXPORT int64_t GetReferenceToNum() const
EXPORT int64_t GetReferenceNumForDisplay()
int64_t GetAbbrevDisplayAmount() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetReceiptAmount()
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
EXPORT void GetString(OTString &theStr) const
transactionType m_Type
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
Definition: OTContract.cpp:367
EXPORT int64_t GetRawNumberOfOrigin() const
void opentxs::OTTransaction::SaveAbbreviatedNymboxRecord ( OTString strOutput)

Definition at line 4960 of file OTTransaction.cpp.

4961 {
4962  int64_t lDisplayValue = 0;
4963 
4964  OTString strDisplayValue; // IF this transaction is passing through on its
4965  // way to the paymentInbox, it will have a
4966  // displayValue.
4967  OTString strListOfBlanks; // IF this transaction is "blank" or
4968  // "successNotice" this will serialize the list of
4969  // transaction numbers for it. (They now support
4970  // multiple numbers.)
4971  OTString strRequestNum; // ONLY replyNotice transactions carry a request
4972  // Num.
4973 
4974  switch (m_Type) {
4975  case OTTransaction::blank: // freshly issued transaction number, not
4976  // accepted by the user (yet).
4977  case OTTransaction::successNotice: // A transaction # has successfully been
4978  // signed out.
4979  {
4980  if (m_Numlist.Count() >
4981  0) // This is always 0, except for blanks and successNotices.
4982  {
4983  OTString strNumbers;
4984  if (true == m_Numlist.Output(strNumbers))
4985  strListOfBlanks.Format(" totalListOfNumbers=\"%s\"\n",
4986  strNumbers.Get());
4987  else // (False just means it was empty.)
4988  strListOfBlanks.Set("");
4989  }
4990  }
4991  /* ! CONTINUES FALLING THROUGH HERE!!... */
4992 
4993  case OTTransaction::replyNotice: // A copy of a server reply to a previous
4994  // request you sent. (To make SURE you get
4995  // the reply.)
4996  strRequestNum.Format(" requestNumber=\"%lld\"\n transSuccess=\"%s\"\n",
4998  m_bReplyTransSuccess ? "true" : "false");
4999  break;
5000 
5001  case OTTransaction::message: // A message from one user to another, also in
5002  // the nymbox.
5003  case OTTransaction::notice: // A notice from the server. Used in Nymbox.
5004  // Probably contains an updated smart contract.
5005  case OTTransaction::finalReceipt: // Any finalReceipt in an inbox will also
5006  // drop a copy into the Nymbox.
5007  break;
5008 
5009  // paymentInbox items are transported through the Nymbox.
5010  // Therefore, this switch statement from SaveAbbrevPaymentInbox
5011  // is also found here, to handle those receipts as they pass through.
5012  case OTTransaction::instrumentNotice: // A financial instrument sent from/to
5013  // another nym.
5014  if (IsAbbreviated())
5015  lDisplayValue = GetAbbrevDisplayAmount();
5016  else
5017  lDisplayValue = GetReceiptAmount();
5018  strDisplayValue.Format(" displayValue=\"%lld\"\n", lDisplayValue);
5019  break; // (These last two are just passing through, on their way to the
5020  // paymentInbox.)
5021  case OTTransaction::instrumentRejection: // A rejection notice from the
5022  // intended recipient of an
5023  // instrumentNotice.
5024  lDisplayValue = 0;
5025  break;
5026 
5027  default: // All other types are irrelevant for nymbox reports.
5028  otErr << __FUNCTION__ << ": Unexpected " << GetTypeString()
5029  << " transaction in nymbox while making abbreviated nymbox "
5030  "record.\n";
5031  OT_FAIL_MSG("ASSERT: OTTransaction::SaveAbbreviatedNymboxRecord: "
5032  "Unexpected transaction in this Nymbox.");
5033 
5034  return;
5035  }
5036 
5037  // By this point, we know only the right types of receipts are being saved,
5038  // and
5039  // the adjustment and display value are both set correctly.
5040 
5041  // TYPE
5042  OTString strType;
5043  const char* pTypeStr = GetTypeString();
5044  strType.Set((nullptr != pTypeStr) ? pTypeStr : "error_state");
5045 
5046  // DATE SIGNED
5047  const int64_t lDateSigned = OTTimeGetSecondsFromTime(m_DATE_SIGNED);
5048 
5049  // HASH OF THE COMPLETE "BOX RECEIPT"
5050  // Save abbreviated is only used for receipts in boxes such as inbox,
5051  // outbox, and nymbox.
5052  // (Thus the moniker "Box Receipt", as contrasted with cron receipts or
5053  // normal transaction receipts with balance agreements.)
5054  //
5055  OTString strHash;
5056 
5057  // If this is already an abbreviated record, then save the existing hash.
5058  if (IsAbbreviated()) m_Hash.GetString(strHash);
5059  // Otherwise if it's a full record, then calculate the hash and save it.
5060  else {
5061  OTIdentifier idReceiptHash; // a hash of the actual transaction is
5062  // stored with its
5063  CalculateContractID(idReceiptHash); // abbreviated short-form
5064  // record (in the inbox, for
5065  // example.)
5066  idReceiptHash.GetString(strHash);
5067  }
5068 
5070  (OTTransaction::basketReceipt == m_Type)) // I actually don't think you
5071  // can put a basket receipt
5072  // notice in a nymbox, the way
5073  // you can with a final
5074  // receipt notice. Probably
5075  // can remove this line.
5076 
5077  strOutput.Concatenate("<nymboxRecord type=\"%s\"\n"
5078  " dateSigned=\"%lld\"\n"
5079  " receiptHash=\"%s\"\n"
5080  " transactionNum=\"%lld\"\n"
5081  " closingNum=\"%lld\"\n"
5082  " inRefDisplay=\"%lld\"\n"
5083  " inReferenceTo=\"%lld\" />\n\n",
5084  strType.Get(), lDateSigned, strHash.Get(),
5087 
5088  else
5089  strOutput.Concatenate(
5090  "<nymboxRecord type=\"%s\"\n"
5091  " dateSigned=\"%lld\"\n%s"
5092  " receiptHash=\"%s\"\n%s" // SOMETIMES this is added here by the
5093  // final %s: " displayValue=\"%lld\"\n"
5094  " transactionNum=\"%lld\"\n%s" // SOMETIMES this is added here by
5095  // the final %s: "
5096  // totalListOfNumbers=\"%s\"\n"
5097  " inRefDisplay=\"%lld\"\n"
5098  " inReferenceTo=\"%lld\" />\n\n",
5099  strType.Get(), lDateSigned, strRequestNum.Get(), strHash.Get(),
5100  strDisplayValue.Get(), GetTransactionNum(), strListOfBlanks.Get(),
5102 }
const char * GetTypeString() const
EXPORT bool Output(std::set< int64_t > &theOutput) const
Definition: OTNumList.cpp:430
EXPORT int64_t GetClosingNum() const
EXPORT int32_t Count() const
Definition: OTNumList.cpp:460
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
EXPORT int64_t GetReferenceToNum() const
EXPORT int64_t GetReferenceNumForDisplay()
int64_t GetAbbrevDisplayAmount() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetReceiptAmount()
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
EXPORT void GetString(OTString &theStr) const
transactionType m_Type
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
Definition: OTContract.cpp:367
void opentxs::OTTransaction::SaveAbbreviatedOutboxRecord ( OTString strOutput)

Definition at line 5104 of file OTTransaction.cpp.

5105 {
5106  int64_t lAdjustment = 0, lDisplayValue = 0;
5107 
5108  switch (m_Type) {
5110  if (IsAbbreviated()) {
5111  lAdjustment = GetAbbrevAdjustment();
5112  lDisplayValue = GetAbbrevDisplayAmount();
5113  }
5114  else {
5115  lAdjustment =
5116  0; // In the inbox, a pending hasn't been accepted yet.
5117  lDisplayValue = // In the outbox, it's already gone.
5118  (GetReceiptAmount() * (-1)); // Either way, it will have a 0
5119  // adjustment amount, even though
5120  // perhaps 500 clams display
5121  // amount.
5122  }
5123  break; // In this case, since it's the outbox, then it's a MINUS (-500)
5124  // Display amount (since I'm sending, not receiving it.)
5125  default: // All other types are irrelevant for outbox reports.
5126  otErr << "OTTransaction::SaveAbbreviatedOutboxRecord: Unexpected "
5127  << GetTypeString()
5128  << " transaction "
5129  "in outbox while making abbreviated outbox record.\n";
5130 
5131  OT_FAIL_MSG("ASSERT: OTTransaction::SaveAbbreviatedOutboxRecord: "
5132  "unexpected transaction type.");
5133 
5134  return;
5135  }
5136 
5137  // By this point, we know only the right types of receipts are being saved,
5138  // and
5139  // the adjustment and display value are both set correctly.
5140 
5141  // TYPE
5142  OTString strType;
5143  const char* pTypeStr = GetTypeString();
5144  strType.Set((nullptr != pTypeStr) ? pTypeStr : "error_state");
5145 
5146  // DATE SIGNED
5147  const int64_t lDateSigned = OTTimeGetSecondsFromTime(m_DATE_SIGNED);
5148 
5149  // HASH OF THE COMPLETE "BOX RECEIPT"
5150  // Save abbreviated is only used for receipts in boxes such as inbox,
5151  // outbox, and nymbox.
5152  // (Thus the moniker "Box Receipt", as contrasted with cron receipts or
5153  // normal transaction receipts with balance agreements.)
5154  //
5155  OTString strHash;
5156 
5157  // If this is already an abbreviated record, then save the existing hash.
5158  if (IsAbbreviated()) m_Hash.GetString(strHash);
5159  // Otherwise if it's a full record, then calculate the hash and save it.
5160  else {
5161  OTIdentifier idReceiptHash; // a hash of the actual transaction is
5162  // stored with its
5163  CalculateContractID(idReceiptHash); // abbreviated short-form
5164  // record (in the inbox, for
5165  // example.)
5166  idReceiptHash.GetString(strHash);
5167  }
5168 
5169  strOutput.Concatenate("<outboxRecord type=\"%s\"\n"
5170  " dateSigned=\"%lld\"\n"
5171  " receiptHash=\"%s\"\n"
5172  " adjustment=\"%lld\"\n"
5173  " displayValue=\"%lld\"\n"
5174  " numberOfOrigin=\"%lld\"\n"
5175  " transactionNum=\"%lld\"\n"
5176  " inRefDisplay=\"%lld\"\n"
5177  " inReferenceTo=\"%lld\" />\n\n",
5178  strType.Get(), lDateSigned, strHash.Get(),
5179  lAdjustment, lDisplayValue, GetRawNumberOfOrigin(),
5181  GetReferenceToNum());
5182 }
int64_t GetAbbrevAdjustment() const
const char * GetTypeString() const
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
EXPORT int64_t GetReferenceToNum() const
EXPORT int64_t GetReferenceNumForDisplay()
int64_t GetAbbrevDisplayAmount() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetReceiptAmount()
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
EXPORT void GetString(OTString &theStr) const
transactionType m_Type
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
Definition: OTContract.cpp:367
EXPORT int64_t GetRawNumberOfOrigin() const
void opentxs::OTTransaction::SaveAbbrevPaymentInboxRecord ( OTString strOutput)

Definition at line 4569 of file OTTransaction.cpp.

4570 {
4571  int64_t lDisplayValue = 0;
4572 
4573  switch (m_Type) {
4575  if (IsAbbreviated())
4576  lDisplayValue = GetAbbrevDisplayAmount();
4577  else
4578  lDisplayValue = GetReceiptAmount();
4579  break;
4581  if (IsAbbreviated()) // not the actual value of 0.
4582  lDisplayValue = GetAbbrevDisplayAmount();
4583  break;
4584  default: // All other types are irrelevant for payment inbox reports
4585  otErr << "OTTransaction::" << __FUNCTION__ << ": Unexpected "
4586  << GetTypeString() << " transaction "
4587  "in payment inbox while making abbreviated "
4588  "payment inbox record.\n";
4589 
4590  OT_FAIL_MSG("ASSERT: OTTransaction::SaveAbbrevPaymentInboxRecord: "
4591  "Unexpected transaction type.");
4592 
4593  return;
4594  }
4595 
4596  // By this point, we know only the right types of receipts are being saved,
4597  // and
4598  // the adjustment and display value are both set correctly.
4599 
4600  // TYPE
4601  OTString strType;
4602  const char* pTypeStr = GetTypeString();
4603  strType.Set((nullptr != pTypeStr) ? pTypeStr : "error_state");
4604 
4605  // DATE SIGNED
4606  const int64_t lDateSigned = OTTimeGetSecondsFromTime(m_DATE_SIGNED);
4607 
4608  // HASH OF THE COMPLETE "BOX RECEIPT"
4609  // Save abbreviated is only used for receipts in boxes such as inbox,
4610  // outbox, and nymbox.
4611  // (Thus the moniker "Box Receipt", as contrasted with cron receipts or
4612  // normal transaction receipts with balance agreements.)
4613  //
4614  OTString strHash;
4615 
4616  // If this is already an abbreviated record, then save the existing hash.
4617  if (IsAbbreviated()) m_Hash.GetString(strHash);
4618  // Otherwise if it's a full record, then calculate the hash and save it.
4619  else {
4620  OTIdentifier idReceiptHash; // a hash of the actual transaction is
4621  // stored with its
4622  CalculateContractID(idReceiptHash); // abbreviated short-form
4623  // record (in the payment
4624  // inbox, for example.)
4625  idReceiptHash.GetString(strHash);
4626  }
4627 
4628  strOutput.Concatenate("<paymentInboxRecord type=\"%s\"\n"
4629  " dateSigned=\"%lld\"\n"
4630  " receiptHash=\"%s\"\n"
4631  " displayValue=\"%lld\"\n"
4632  " transactionNum=\"%lld\"\n"
4633  " inRefDisplay=\"%lld\"\n"
4634  " inReferenceTo=\"%lld\" />\n\n",
4635  strType.Get(), lDateSigned, strHash.Get(),
4636  lDisplayValue, GetTransactionNum(),
4638 }
const char * GetTypeString() const
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
EXPORT int64_t GetReferenceToNum() const
EXPORT int64_t GetReferenceNumForDisplay()
int64_t GetAbbrevDisplayAmount() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetReceiptAmount()
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
EXPORT void GetString(OTString &theStr) const
transactionType m_Type
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
Definition: OTContract.cpp:367
void opentxs::OTTransaction::SaveAbbrevRecordBoxRecord ( OTString strOutput)

Definition at line 4764 of file OTTransaction.cpp.

4765 {
4766  // Have some kind of check in here, whether the AcctID and UserID match.
4767  // Some recordBoxes DO, and some DON'T (the different kinds store different
4768  // kinds of receipts. See above comment.)
4769 
4770  int64_t lAdjustment = 0, lDisplayValue = 0;
4771 
4772  switch (m_Type) {
4773  // ASSET ACCOUNT INBOX
4774  // -- In inbox, pending hasn't been accepted yet. In outbox, it's already
4775  // gone. Either
4776  // way, it will have a 0 adjustment amount, even though perhaps 500 clams
4777  // display amount. Here I use the 500
4778  // for display, but in SaveAbbrevToOutbox, I multiply it by -1 so it appears
4779  // as -500 (leaving my account.)
4780  // -- In my inbox, the transferReceipt is notice of money that is already
4781  // gone. It thus has adjustment value of 0.
4782  // But the DISPLAY amount is the amount I originally sent. (Already
4783  // multiplied by -1 by GetReceiptAmount())
4784  //
4785  case OTTransaction::pending: // (The pending amount is stored on the
4786  // transfer item in my list of transaction
4787  // items.)
4788  case OTTransaction::transferReceipt: // The transferReceipt and
4789  // voucherReceipt amounts are the
4790  // display value (according to
4791  case OTTransaction::voucherReceipt: // GetReceiptAmount()), and not the
4792  // actual value of 0.
4793  if (IsAbbreviated()) {
4794  lAdjustment = GetAbbrevAdjustment();
4795  lDisplayValue = GetAbbrevDisplayAmount();
4796  }
4797  else {
4798  lAdjustment = 0;
4799  lDisplayValue = GetReceiptAmount();
4800  }
4801  break;
4802  // If chequeReceipt for 100 clams hit my inbox, then my balance is -100 from
4803  // where it was. (Same
4804  // value should be displayed.) Luckily, GetReceiptAmount() already
4805  // multiplies by (-1) for chequeReceipt.
4806  // For these (marketReceipt, paymentReceipt, basketReceipt), the actual
4807  // adjustment is positive OR negative
4808  // already, and the display value should match.
4809  case OTTransaction::chequeReceipt: // the amount is stored on cheque
4810  // (attached to depositCheque item,
4811  // attached.)
4812  case OTTransaction::marketReceipt: // amount is stored on marketReceipt
4813  // item. |
4814  case OTTransaction::paymentReceipt: // amount is stored on paymentReceipt
4815  // item. | and the display value should
4816  // match.
4817  case OTTransaction::basketReceipt: // amount is stored on basketReceipt
4818  // item. |
4819  if (IsAbbreviated()) // not the actual value of 0.
4820  {
4821  lAdjustment = GetAbbrevAdjustment();
4822  lDisplayValue = GetAbbrevDisplayAmount();
4823  }
4824  else {
4825  lAdjustment = GetReceiptAmount();
4826  lDisplayValue = lAdjustment;
4827  }
4828  break;
4829  case OTTransaction::finalReceipt: // amount is 0 according to
4830  // GetReceiptAmount()
4831  if (IsAbbreviated()) // not the actual value of 0.
4832  {
4833  lAdjustment = GetAbbrevAdjustment();
4834  lDisplayValue = GetAbbrevDisplayAmount();
4835  }
4836  else {
4837  lAdjustment = 0;
4838  lDisplayValue = 0;
4839  }
4840  break;
4841  // NYMBOX
4842  case OTTransaction::notice: // A notice from the server. Used in Nymbox.
4843  // Probably contains an updated smart contract.
4844  if (IsAbbreviated()) // not the actual value of 0.
4845  {
4846  lAdjustment = GetAbbrevAdjustment();
4847  lDisplayValue = GetAbbrevDisplayAmount();
4848  }
4849  else {
4850  lAdjustment = 0;
4851  lDisplayValue = 0;
4852  }
4853  break;
4854  // PAYMENT INBOX / PAYMENT OUTBOX
4856  if (IsAbbreviated()) // not the actual value of 0.
4857  {
4858  lAdjustment = GetAbbrevAdjustment();
4859  lDisplayValue = GetAbbrevDisplayAmount();
4860  }
4861  else {
4862  lAdjustment = 0;
4863  lDisplayValue = GetReceiptAmount();
4864  }
4865  break;
4867  if (IsAbbreviated()) // not the actual value of 0.
4868  {
4869  lAdjustment = GetAbbrevAdjustment();
4870  lDisplayValue = GetAbbrevDisplayAmount();
4871  }
4872  else {
4873  lAdjustment = 0;
4874  lDisplayValue = 0;
4875  }
4876  break;
4877  default: // All other types are irrelevant for inbox reports
4878  {
4879  otErr << "OTTransaction::SaveAbbrevRecordBoxRecord: Unexpected "
4880  << GetTypeString()
4881  << " transaction "
4882  "in record box while making abbreviated record-box record.\n";
4883  }
4884  return;
4885  } // why not transfer receipt? Because the amount was already removed from
4886  // your account when you transferred it,
4887 
4888  // By this point, we know only the right types of receipts are being saved,
4889  // and
4890  // the adjustment and display value are both set correctly.
4891 
4892  // TYPE
4893  OTString strType;
4894  const char* pTypeStr = GetTypeString();
4895  strType.Set((nullptr != pTypeStr) ? pTypeStr : "error_state");
4896 
4897  // DATE SIGNED
4898  const int64_t lDateSigned = OTTimeGetSecondsFromTime(m_DATE_SIGNED);
4899 
4900  // HASH OF THE COMPLETE "BOX RECEIPT"
4901  // Save abbreviated is only used for receipts in boxes such as inbox,
4902  // outbox, and nymbox.
4903  // (Thus the moniker "Box Receipt", as contrasted with cron receipts or
4904  // normal transaction receipts with balance agreements.)
4905  //
4906  OTString strHash;
4907 
4908  // If this is already an abbreviated record, then save the existing hash.
4909  if (IsAbbreviated()) m_Hash.GetString(strHash);
4910  // Otherwise if it's a full record, then calculate the hash and save it.
4911  else {
4912  OTIdentifier idReceiptHash; // a hash of the actual transaction is
4913  // stored with its
4914  CalculateContractID(idReceiptHash); // abbreviated short-form
4915  // record (in the record box,
4916  // for example.)
4917  idReceiptHash.GetString(strHash);
4918  }
4919 
4922 
4923  strOutput.Concatenate(
4924  "<recordBoxRecord type=\"%s\"\n"
4925  " dateSigned=\"%lld\"\n"
4926  " receiptHash=\"%s\"\n"
4927  " adjustment=\"%lld\"\n"
4928  " displayValue=\"%lld\"\n"
4929  " numberOfOrigin=\"%lld\"\n"
4930  " transactionNum=\"%lld\"\n"
4931  " closingNum=\"%lld\"\n"
4932  " inRefDisplay=\"%lld\"\n"
4933  " inReferenceTo=\"%lld\" />\n\n",
4934  strType.Get(), lDateSigned, strHash.Get(), lAdjustment,
4935  lDisplayValue, GetRawNumberOfOrigin(), GetTransactionNum(),
4937  else
4938  strOutput.Concatenate("<recordBoxRecord type=\"%s\"\n"
4939  " dateSigned=\"%lld\"\n"
4940  " receiptHash=\"%s\"\n"
4941  " adjustment=\"%lld\"\n"
4942  " displayValue=\"%lld\"\n"
4943  " numberOfOrigin=\"%lld\"\n"
4944  " transactionNum=\"%lld\"\n"
4945  " inRefDisplay=\"%lld\"\n"
4946  " inReferenceTo=\"%lld\" />\n\n",
4947  strType.Get(), lDateSigned, strHash.Get(),
4948  lAdjustment, lDisplayValue,
4951 }
int64_t GetAbbrevAdjustment() const
const char * GetTypeString() const
EXPORT int64_t GetClosingNum() const
EXPORT int64_t GetReferenceToNum() const
EXPORT int64_t GetReferenceNumForDisplay()
int64_t GetAbbrevDisplayAmount() const
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetReceiptAmount()
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
EXPORT void GetString(OTString &theStr) const
transactionType m_Type
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
Definition: OTContract.cpp:367
EXPORT int64_t GetRawNumberOfOrigin() const
bool opentxs::OTTransaction::SaveBoxReceipt ( int64_t  lLedgerType)

Definition at line 3005 of file OTTransaction.cpp.

3006 {
3007 
3008  if (IsAbbreviated()) {
3009  otOut << __FUNCTION__ << ": Unable to save box receipt "
3010  << GetTransactionNum()
3011  << ": "
3012  "This transaction is the abbreviated version (box receipt is "
3013  "supposed to "
3014  "consist of the full version, so we can't save THIS as the "
3015  "box receipt.)\n";
3016  return false;
3017  }
3018 
3019  OTString strFolder1name, strFolder2name, strFolder3name, strFilename;
3020 
3022  lLedgerType, *this, "OTTransaction::SaveBoxReceipt", strFolder1name,
3023  strFolder2name, strFolder3name, strFilename))
3024  return false; // This already logs -- no need to log twice, here.
3025 
3026  // See if the box receipt exists before trying to save over it...
3027  //
3028  if (OTDB::Exists(strFolder1name.Get(), strFolder2name.Get(),
3029  strFolder3name.Get(), strFilename.Get())) {
3030  otOut << __FUNCTION__
3031  << ": Warning -- Box receipt already exists! (Overwriting)"
3032  "At location: " << strFolder1name << OTLog::PathSeparator()
3033  << strFolder2name << OTLog::PathSeparator() << strFolder3name
3034  << OTLog::PathSeparator() << strFilename << "\n";
3035  // return false;
3036  }
3037 
3038  // Try to save the box receipt to local storage.
3039  //
3040  OTString strFinal;
3041  OTASCIIArmor ascTemp(m_strRawFile);
3042 
3043  if (false ==
3044  ascTemp.WriteArmoredString(strFinal, m_strContractType.Get())) {
3045  otErr << __FUNCTION__
3046  << ": Error saving box receipt (failed writing armored string):\n"
3047  << strFolder1name << OTLog::PathSeparator() << strFolder2name
3048  << OTLog::PathSeparator() << strFolder3name
3049  << OTLog::PathSeparator() << strFilename << "\n";
3050  return false;
3051  }
3052 
3053  bool bSaved = OTDB::StorePlainString(
3054  strFinal.Get(), strFolder1name.Get(), strFolder2name.Get(),
3055  strFolder3name.Get(), strFilename.Get());
3056 
3057  if (!bSaved)
3058  otErr << __FUNCTION__ << ": Error writing file: " << strFolder1name
3059  << OTLog::PathSeparator() << strFolder2name
3060  << OTLog::PathSeparator() << strFolder3name
3061  << OTLog::PathSeparator() << strFilename << "\nContents:\n\n"
3062  << m_strRawFile << "\n\n";
3063 
3064  return bSaved;
3065 }
EXPORT bool StorePlainString(std::string strContents, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:698
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
OTLOG_IMPORT OTLogStream otOut
OTString m_strContractType
Definition: OTContract.hpp:178
bool SetupBoxReceiptFilename(int64_t lLedgerType, OTTransaction &theTransaction, const char *szCaller, OTString &strFolder1name, OTString &strFolder2name, OTString &strFolder3name, OTString &strFilename)
Definition: Helpers.cpp:591
EXPORT const char * Get() const
Definition: OTString.cpp:1045
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
bool opentxs::OTTransaction::SaveBoxReceipt ( OTLedger theLedger)

Definition at line 3070 of file OTTransaction.cpp.

3071 {
3072  int64_t lLedgerType = 0;
3073 
3074  switch (theLedger.GetType()) {
3075  case OTLedger::nymbox:
3076  lLedgerType = 0;
3077  break;
3078  case OTLedger::inbox:
3079  lLedgerType = 1;
3080  break;
3081  case OTLedger::outbox:
3082  lLedgerType = 2;
3083  break;
3084  // case OTLedger::message: lLedgerType = 3; break;
3086  lLedgerType = 4;
3087  break;
3088  case OTLedger::recordBox:
3089  lLedgerType = 5;
3090  break;
3091  case OTLedger::expiredBox:
3092  lLedgerType = 6;
3093  break;
3094  default:
3095  otErr << "OTTransaction::SaveBoxReceipt: Error: unknown box type. "
3096  "(This should never happen.)\n";
3097  return false;
3098  }
3099  return SaveBoxReceipt(lLedgerType);
3100 }
EXPORT bool SaveBoxReceipt(int64_t lLedgerType)
OTLOG_IMPORT OTLogStream otErr
bool opentxs::OTTransaction::SaveContractWallet ( std::ofstream &  ofs) const
virtual

Reimplemented from opentxs::OTTransactionType.

Definition at line 3487 of file OTTransaction.cpp.

3488 {
3489  return true;
3490 }
void opentxs::OTTransaction::SetAbbrevAdjustment ( int64_t  lAmount)
inline

Definition at line 592 of file OTTransaction.hpp.

593  {
594  m_lAbbrevAmount = lAmount;
595  }
void opentxs::OTTransaction::SetAbbrevDisplayAmount ( int64_t  lAmount)
inline

Definition at line 602 of file OTTransaction.hpp.

603  {
604  m_lDisplayAmount = lAmount;
605  }
void opentxs::OTTransaction::SetAbbrevInRefDisplay ( int64_t  lAmount)
inline

Definition at line 612 of file OTTransaction.hpp.

613  {
614  m_lInRefDisplay = lAmount;
615  }
EXPORT void opentxs::OTTransaction::SetAsCancelled ( )
inline

Definition at line 570 of file OTTransaction.hpp.

571  {
572  m_bCancelled = true;
573  }
void opentxs::OTTransaction::SetClosingNum ( int64_t  lClosingNum)

Definition at line 159 of file OTTransaction.cpp.

160 {
161  m_lClosingTransactionNo = lClosingNum;
162 }
void opentxs::OTTransaction::SetParent ( const OTLedger theParent)
inline

Definition at line 575 of file OTTransaction.hpp.

576  {
577  m_pParent = &theParent;
578  }
const OTLedger * m_pParent
void opentxs::OTTransaction::SetReplyTransSuccess ( bool  bVal)
inline

Definition at line 634 of file OTTransaction.hpp.

635  {
636  m_bReplyTransSuccess = bVal;
637  }
void opentxs::OTTransaction::SetRequestNum ( const int64_t &  lNum)
inline

Definition at line 624 of file OTTransaction.hpp.

625  {
626  m_lRequestNumber = lNum;
627  }
void opentxs::OTTransaction::SetType ( transactionType  theType)
inline

Definition at line 683 of file OTTransaction.hpp.

684  {
685  m_Type = theType;
686  }
transactionType m_Type
void opentxs::OTTransaction::UpdateContents ( )
protectedvirtual

Reimplemented from opentxs::OTContract.

Definition at line 4355 of file OTTransaction.cpp.

4356 {
4357  OTString strCancelled;
4358 
4359  if (m_bCancelled) {
4360  strCancelled.Format(" cancelled=\"%s\"\n", "true");
4361  }
4362 
4363  OTString strListOfBlanks; // IF this transaction is "blank" or
4364  // "successNotice" this will serialize the list of
4365  // transaction numbers for it. (They now support
4366  // multiple numbers.)
4367  OTString strRequestNum; // Used by replyNotice only.
4368 
4369  switch (m_Type) {
4371  strRequestNum.Format(" requestNumber=\"%lld\"\n transSuccess=\"%s\"\n",
4373  m_bReplyTransSuccess ? "true" : "false");
4374  break;
4375 
4376  case OTTransaction::blank: // freshly issued transaction number, not
4377  // accepted by the user (yet).
4378  case OTTransaction::successNotice: // A transaction # has successfully been
4379  // signed out.
4380  {
4381  if (m_Numlist.Count() >
4382  0) // This is always 0, except for blanks and successNotices.
4383  {
4384  OTString strNumbers;
4385  if (true == m_Numlist.Output(strNumbers))
4386  strListOfBlanks.Format(" totalListOfNumbers=\"%s\"\n",
4387  strNumbers.Get());
4388  else // (False just means m_Numlist was empty.)
4389  strListOfBlanks.Set("");
4390  }
4391  }
4392  default:
4393  break;
4394  }
4395 
4396  const char* pTypeStr = GetTypeString(); // TYPE
4397  const OTString strType((nullptr != pTypeStr) ? pTypeStr : "error_state"),
4398  strAcctID(GetPurportedAccountID()), strServerID(GetPurportedServerID()),
4399  strUserID(GetUserID());
4400 
4401  m_DATE_SIGNED = OTTimeGetCurrentTime(); // We store the timestamp of when
4402  // this transaction was signed.
4403  const int64_t lDateSigned = OTTimeGetSecondsFromTime(m_DATE_SIGNED);
4404 
4405  // I release this because I'm about to repopulate it.
4407 
4408  m_xmlUnsigned.Concatenate("<transaction type=\"%s\"\n%s"
4409  " dateSigned=\"%lld\"\n"
4410  " accountID=\"%s\"\n"
4411  " userID=\"%s\"\n"
4412  " serverID=\"%s\"\n%s"
4413  " numberOfOrigin=\"%lld\"\n"
4414  " transactionNum=\"%lld\"\n%s"
4415  " inReferenceTo=\"%lld\" >\n\n",
4416  strType.Get(), strCancelled.Get(), lDateSigned,
4417  strAcctID.Get(), strUserID.Get(),
4418  strServerID.Get(), strRequestNum.Get(),
4420  strListOfBlanks.Get(), GetReferenceToNum());
4421 
4422  if (IsAbbreviated()) {
4423  if (nullptr != m_pParent) {
4424 
4425  switch (m_pParent->GetType()) {
4426  case OTLedger::nymbox:
4428  break;
4429  case OTLedger::inbox:
4431  break;
4432  case OTLedger::outbox:
4434  break;
4437  break;
4438  case OTLedger::recordBox:
4440  break;
4441  case OTLedger::expiredBox:
4443  break;
4444  /* --- BREAK --- */
4445  case OTLedger::message:
4446  otErr << "OTTransaction::" << __FUNCTION__
4447  << ": Unexpected message ledger type in 'abbreviated' "
4448  "block. (Error.) \n";
4449  break;
4450  default:
4451  otErr << "OTTransaction::" << __FUNCTION__
4452  << ": Unexpected ledger type in 'abbreviated' block. "
4453  "(Error.) \n";
4454  break;
4455  } /*switch*/
4456  }
4457  else
4458  otErr << "OTTransaction::" << __FUNCTION__
4459  << ": Error: Unable to save abbreviated receipt here, since "
4460  "m_pParent is nullptr.\n";
4461 
4462  }
4463  else // not abbreviated (full details.)
4464  {
4468  "<closingTransactionNumber value=\"%lld\"/>\n\n",
4470  }
4471 
4472  // a transaction contains a list of items, but it is also in reference
4473  // to some item, from someone else
4474  // We include a full copy of that item here.
4476  m_xmlUnsigned.Concatenate("<inReferenceTo>\n%s</inReferenceTo>\n\n",
4478 
4480  m_xmlUnsigned.Concatenate("<cancelRequest>\n%s</cancelRequest>\n\n",
4482 
4483  // loop through the items that make up this transaction and print them
4484  // out here, base64-encoded, of course.
4485  for (auto& it : m_listItems) {
4486  OTItem* pItem = it;
4487  OT_ASSERT(nullptr != pItem);
4488 
4489  OTString strItem;
4490  pItem->SaveContractRaw(strItem);
4491 
4492  OTASCIIArmor ascItem;
4493  ascItem.SetString(strItem, true); // linebreaks = true
4494 
4495  m_xmlUnsigned.Concatenate("<item>\n%s</item>\n\n", ascItem.Get());
4496  }
4497  } // not abbreviated (full details.)
4498 
4499  m_xmlUnsigned.Concatenate("</transaction>\n");
4500 }
void SaveAbbrevExpiredBoxRecord(OTString &strOutput)
void SaveAbbrevRecordBoxRecord(OTString &strOutput)
void SaveAbbreviatedInboxRecord(OTString &strOutput)
const OTLedger * m_pParent
void SaveAbbreviatedNymboxRecord(OTString &strOutput)
void SaveAbbrevPaymentInboxRecord(OTString &strOutput)
EXPORT uint32_t GetLength() const
Definition: OTString.cpp:1040
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
const char * GetTypeString() const
const OTIdentifier & GetPurportedServerID() const
time64_t OTTimeGetCurrentTime()
Definition: Common.hpp:211
OTASCIIArmor m_ascCancellationRequest
EXPORT bool Output(std::set< int64_t > &theOutput) const
Definition: OTNumList.cpp:430
#define OT_ASSERT(x)
Definition: Assert.hpp:150
ledgerType GetType() const
Definition: OTLedger.hpp:212
EXPORT int32_t Count() const
Definition: OTNumList.cpp:460
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
EXPORT int64_t GetReferenceToNum() const
EXPORT const char * Get() const
Definition: OTString.cpp:1045
void SaveAbbreviatedOutboxRecord(OTString &strOutput)
OTLOG_IMPORT OTLogStream otErr
const OTIdentifier & GetPurportedAccountID() const
EXPORT int64_t GetTransactionNum() const
bool IsAbbreviated() const
transactionType m_Type
const OTIdentifier & GetUserID() const
int64_t OTTimeGetSecondsFromTime(time64_t time)
Definition: Common.hpp:230
virtual EXPORT void Release()
Definition: OTString.cpp:765
EXPORT int64_t GetRawNumberOfOrigin() const
bool opentxs::OTTransaction::VerifyAccount ( const OTPseudonym theNym)
virtual

Reimplemented from opentxs::OTTransactionType.

Definition at line 173 of file OTTransaction.cpp.

174 {
175  OTLedger* pParent = const_cast<OTLedger*>(m_pParent);
176 
177  // Make sure that the supposed AcctID matches the one read from the file.
178  //
179  if (!VerifyContractID()) {
180  otErr << __FUNCTION__ << ": Error verifying account ID.\n";
181  return false;
182  }
183  // todo security audit:
184  else if (IsAbbreviated() && (pParent != nullptr) &&
185  !pParent->VerifySignature(theNym)) {
186  otErr << __FUNCTION__ << ": Error verifying signature on parent ledger "
187  "for abbreviated transaction receipt.\n";
188  return false;
189  }
190  else if (!IsAbbreviated() && (false == VerifySignature(theNym))) {
191  otErr << __FUNCTION__ << ": Error verifying signature.\n";
192  return false;
193  }
194 
195  otLog4 << "\nWe now know that...\n"
196  "1) The expected Account ID matches the ID that was found on the "
197  "object.\n"
198  "2) The SIGNATURE VERIFIED on the object.\n\n";
199  return true;
200 }
OTLOG_IMPORT OTLogStream otLog4
const OTLedger * m_pParent
OTLOG_IMPORT OTLogStream otErr
bool IsAbbreviated() const
virtual EXPORT bool VerifySignature(const OTPseudonym &theNym, const OTPasswordData *pPWData=nullptr) const
Definition: OTContract.cpp:818
virtual EXPORT bool VerifyContractID() const
bool opentxs::OTTransaction::VerifyBalanceReceipt ( OTPseudonym SERVER_NYM,
OTPseudonym THE_NYM 
)

Definition at line 1277 of file OTTransaction.cpp.

1288 { // These are now loaded within this function, so no need to pass them in.
1289  // Load the other receipt (see above) if necessary.
1290 
1291  // Compare the inbox I just downloaded with what my last signed receipt SAYS
1292  // it should say.
1293  // Let's say the inbox has transaction 9 in it -- well, my last signed
1294  // receipt better show
1295  // that 9 was in my inbox then, too. But what if 9 was on a cheque, and it
1296  // only recently hit?
1297  // Well it won't be in my old inbox, but it WILL still be signed for as an
1298  // open transaction.
1299 
1300  // Since this involves verifying the outbox, inbox, AND account, this
1301  // function should only
1302  // be called after all three have been downloaded, not after each one.
1303  // Basically the outbox should RARELY change, the inbox is EXPECTED to
1304  // change, and the account
1305  // is EXPECTED to change, BUT ONLY in cases where the inbox justifies it!
1306  //
1307  // -- Verify the transaction numbers on the nym match those exactly on the
1308  // newest transaction or balance receipt. (this)
1309  // -- Make sure outbox is the same.
1310  // -- Loop through all items in the inbox, AND in the inbox according to the
1311  // receipt, and total the
1312  // values of both. I might have 9 and 10 issued in the last receipt, with
1313  // #9 in the inbox,
1314  // showing 50 clams and a balance of 93. But now I downloaded an inbox
1315  // showing #9 AND #10,
1316  // with values of 50 and 4, and a balance of 89.
1317  // The new inbox is still valid, and the new account balance is still
1318  // valid, because the
1319  // new number that appeared was issued to me and signed out, and because
1320  // the last receipt's
1321  // balance of 93 with 50 clams worth of receipts, matches up to the new
1322  // account/inbox
1323  // balance of 89 with 54 clams worth of receipts.
1324  // The two totals still match! That's what we're checking for.
1325  //
1326  // Not JUST that actually, but that, if #10 is NOT found in the old one,
1327  // THEN the amount (4)
1328  // must be the DIFFERENCE between the balances (counting all new
1329  // transactions like #10.)
1330  // Meaning, the difference between the two balances MUST be made up EXACTLY
1331  // by the transactions
1332  // that are found now, that were not previously found, minus the total of
1333  // the transactions
1334  // from before that are no longer there, but are also no longer on my issued
1335  // list and thus don't matter.
1336  //
1337  // Wow ! OTItem::VerifyBalanceStatement will have useful code but it doesn't
1338  // encapsulate all this
1339  // new functionality, since this version must assume differences are there,
1340  // and STILL verify things
1341  // by comparing details about those differences, whereas that version only
1342  // serves to make sure
1343  // everything still matches.
1344 
1345  // -- Verify nym transactions match. (issued.)
1346  // -- Verify outbox matches.
1347  // -- Loop through all items on receipt. If outbox item, should match
1348  // exactly.
1349  // -- But for inbox items, total up: the amount of the total of the items
1350  // from the receipt,
1351  // for all those that would actually change the balance (chequeReceipt,
1352  // marketReceipt, paymentReceipt, basketReceipt.)
1353  // These should ALL be found in the current version of the inbox. (They
1354  // can only be removed by balance agreement,
1355  // which would update THIS RECEIPT to remove them...)
1356  // -- That was the receipt. Now loop through the above inbox items and do
1357  // the reverse: for each item in the NEW inbox,
1358  // add up the total of those that would change the balance, for receipts
1359  // found on the new but not the old, and account for that exactly as a
1360  // difference in balance.
1361  /*
1362 
1363  Example.
1364 
1365  -- Oldest signed receipt shows a balance of 115 clams.
1366  But then, cheque #78 hits my inbox and though I haven't yet accepted the
1367  receipt, I still need to do a transaction, like a 5 clam withdrawal, or
1368  whatever,
1369  and somehow I end up doing a balance agreement. That results in the
1370  below signed receipt:
1371 
1372  --- Old receipt shows inbox/account/nym as:
1373  Currently signed out: 8, 9, 10, and 15
1374  Balance of 100 clams (Last signed balance before this was for 115 clams
1375  above)
1376  Inbox items:
1377  #78 cheque receipt (#8) for 15 clams. (The missing money is already
1378  reflected in the above balance. BUT!! #8 must still be signed out for this
1379  to verify. Here I must sign to acknowledge the receipt is in my inbox, but
1380  I still have option to accept or dispute the receipt. Until then, server
1381  keeps it around since it has my signature on it and proves the current
1382  balance.)
1383  #82 incoming transfer for 50 clams (A new balance agreement occurs during
1384  acceptance of this. And the number doesn't belong to me. So, irrelevant
1385  here.)
1386  #10 transfer receipt for some old transfer (does NOT change balance, which
1387  already happened in the past, BUT!! #10 must still be signed out for this
1388  to verify.)
1389 
1390  My nym ISSUED list should not change unless I have a new transaction
1391  agreement, therefore I expect the list to match every time.
1392  My outbox should also match. Thus, only my account balance and inbox might
1393  change. (On the server side, which I'll see when I dl
1394  new versions of them and compare against my last receipt i.e. this
1395  function.)
1396  How? NOT via transfer receipt, since I would sign a new balance agreement
1397  whenever that would actually impact my balance.
1398  But it could happen with a *** chequeReceipt, a paymentReceipt,
1399  marketReceipt, or basketReceipt. ***
1400  Those mean, my balance has changed.
1401  In those cases, my account balance WOULD be different, but there had better
1402  be matching receipts in the inbox!
1403 
1404  --- New inbox/account/nym shows:
1405  Currently signed out: 8, 9, 10, and 15
1406  Balance of 89 clams
1407  Inbox items:
1408  #78 cheque receipt (#8) for 15 clams.
1409  #82 incoming transfer for 50 clams (A new balance agreement occurs during
1410  acceptance. So this type has no affect on balance here.)
1411  #10 transfer receipt for some old transfer (does NOT change balance, which
1412  already happened in the past)
1413  #96 cheque receipt for 7 clams (cheque #9)
1414  #97 marketReceipt for 4 clams (marketOffer #15)
1415  #99 incoming transfer for 2000 clams (Accepting it will require a new
1416  balance agreement.)
1417 
1418  ---------------------------------
1419 
1420  How do I interpret all this data?
1421  -- Transaction numbers signed out had better match. (If #s issued had
1422  changed, I would have signed for it already.)
1423 
1424  Next loop through the inbox from the old receipt:
1425  -- #78, cheque receipt, had better be there in the new inbox, since
1426  removing it requires a balance agreement, meaning it would already be off
1427  the receipt that I'm verifying... Since it's here in inbox, should
1428  therefore also be in the last receipt.
1429  -- #82, incoming transfer from old receipt, had better be also on the new
1430  inbox, since I could only accept or reject it with a balance agreement,
1431  which I'm comparing the inbox to now.
1432  -- #10 had also better be there in the new inbox for the same reason: if I
1433  had accepted this transfer receipt, then my last balance receipt would
1434  reflect that.
1435  -- THEREFORE: ALL items from old receipt must be found inside new inbox!
1436 
1437  Next, loop through the new version of the inbox:
1438  -- #78, though found in the new inbox, wouldn't necessarily be expected to
1439  be found in the last receipt, since someone may have cashed my cheque since
1440  the receipt was made.
1441  -- #82, though found in the new inbox, wouldn't necessarily be expected to
1442  be found in the last receipt, since someone may have sent me the transfer
1443  since receipt was made.
1444  -- #10 in new inbox, same thing: Someone may have recently accepted my
1445  transfer, and thus #10 only would have popped in since the last agreement.
1446  (It was there before, but I couldn't EXPECT that in every case.)
1447  -- #96 and #97 represent balance CHANGES totalling -11 clams. They must
1448  correspond to a change in balance.
1449  -- #96 is a cheque receipt.. it has changed the balance and I must account
1450  for that. But #78 is ALSO a cheque receipt, so why am I not accounting for
1451  ITs total (instead just assuming it's accounted for already in the prior
1452  balance, like 78?) Because it's NEW and wasn't on the old receipt like 78
1453  is!
1454  -- Due to the reasoning explained on the above line, ANY chequeReceipt,
1455  paymentReceipt, marketReceipt, or basketReceipt
1456  found on the new version of the inbox but NOT on the old one from the
1457  receipt, must be accounted for against the balance.
1458  -- #99 is an incoming transfer, but it will not change the balance until
1459  that transfer is accepted with a new balance agreement sometime in the
1460  future.
1461  */
1462 
1463  if (IsAbbreviated()) {
1464  otErr << "OTTransaction::VerifyBalanceReceipt: Error: This is an "
1465  "abbreviated receipt. (Load the box receipt first.)\n";
1466  return false;
1467  }
1468 
1469  OTIdentifier USER_ID(THE_NYM), SERVER_USER_ID(SERVER_NYM);
1470 
1471  const OTString strServerID(GetRealServerID()), strReceiptID(USER_ID);
1472 
1473  // if (USER_ID != GetUserID())
1474  // {
1475  // otErr << "*** OTIdentifier USER_ID(OTPseudonym THE_NYM) doesn't
1476  // match OTTransactionType::GetUserID() in
1477  // OTTransaction::VerifyBalanceReceipt\n";
1478  // return false;
1479  // }
1480 
1481  // Load the last TRANSACTION STATEMENT as well...
1482 
1483  OTString strFilename;
1484  strFilename.Format("%s.success", strReceiptID.Get());
1485 
1486  const char* szFolder1name = OTFolders::Receipt().Get(); // receipts
1487  const char* szFolder2name = strServerID.Get(); // receipts/SERVER_ID
1488  const char* szFilename =
1489  strFilename.Get(); // receipts/SERVER_ID/USER_ID.success
1490 
1491  if (!OTDB::Exists(szFolder1name, szFolder2name, szFilename)) {
1492  otWarn << "Receipt file doesn't exist in "
1493  "OTTransaction::VerifyBalanceReceipt:\n " << szFilename
1494  << "\n";
1495  return false;
1496  }
1497 
1498  std::string strFileContents(
1499  OTDB::QueryPlainString(szFolder1name, szFolder2name,
1500  szFilename)); // <=== LOADING FROM DATA STORE.
1501 
1502  if (strFileContents.length() < 2) {
1503  otErr << "OTTransaction::VerifyBalanceReceipt: Error reading "
1504  "transaction statement:\n " << szFolder1name
1505  << OTLog::PathSeparator() << szFolder2name
1506  << OTLog::PathSeparator() << szFilename << "\n";
1507  return false;
1508  }
1509 
1510  OTString strTransaction(strFileContents.c_str());
1511 
1512  // OTTransaction tranOut(SERVER_USER_ID, USER_ID, GetRealServerID());
1513  std::unique_ptr<OTTransactionType> pContents(
1514  OTTransactionType::TransactionFactory(strTransaction));
1515 
1516  if (nullptr == pContents) {
1517  otErr << "OTTransaction::VerifyBalanceReceipt: Unable to load "
1518  "transaction statement:\n " << szFolder1name
1519  << OTLog::PathSeparator() << szFolder2name
1520  << OTLog::PathSeparator() << szFilename << "\n";
1521  return false;
1522  }
1523  else if (!pContents->VerifySignature(SERVER_NYM)) {
1524  otErr << "OTTransaction::VerifyBalanceReceipt: Unable to verify "
1525  "signature on transaction statement:\n " << szFolder1name
1526  << OTLog::PathSeparator() << szFolder2name
1527  << OTLog::PathSeparator() << szFilename << "\n";
1528  return false;
1529  }
1530 
1531  // At this point, pContents is successfully loaded and verified, containing
1532  // the last transaction receipt.
1533  OTTransaction* pTrans = dynamic_cast<OTTransaction*>(pContents.get());
1534 
1535  if (nullptr == pTrans) {
1536  otErr << "OTTransaction::VerifyBalanceReceipt: Was expecting an "
1537  "OTTransaction to be stored in the transaction statement "
1538  "at:\n " << szFolder1name << OTLog::PathSeparator()
1539  << szFolder2name << OTLog::PathSeparator() << szFilename << "\n";
1540  return false;
1541  }
1542 
1543  OTTransaction& tranOut = *pTrans;
1544 
1545  // I ONLY need this transaction statement if it's newer than the balance
1546  // statement.
1547  // Otherwise, I don't use it at all. But if it's newer, then I use it
1548  // instead of the current
1549  // balance statement (only for verifying the list of issued numbers, not for
1550  // anything else.)
1551 
1552  // And in the case where that happens, I ONLY expect to see new numbers
1553  // added, NOT removed.
1554  // But again, ONLY if the transaction statement is MORE RECENT. Otherwise it
1555  // may have extra
1556  // numbers alright: ones that were already removed and I don't want to
1557  // re-sign responsibility for!
1558 
1559  // CHECK IF IT'S NEWER AND SET A POINTER BASED ON THIS.
1560 
1561  OTItem* pItemWithIssuedList =
1562  nullptr; // the item from that transaction that
1563  // actually has the issued list we'll be
1564  // using.
1565 
1566  OTItem* pTransactionItem = nullptr;
1567 
1568  if (tranOut.GetDateSigned() > GetDateSigned()) // it's newer.
1569  {
1570  // GET THE "AT TRANSACTION STATEMENT" ITEM
1571  //
1572  // only if it's new than balance receipt does this get set, to:
1573  // tranOut.GetItem(OTItem::atTransactionStatement);
1574  OTItem* pResponseTransactionItem =
1575  tranOut.GetItem(OTItem::atTransactionStatement);
1576 
1577  if (nullptr == pResponseTransactionItem) {
1578  // error, return.
1579  otOut << "No atTransactionStatement item found on receipt "
1580  "(strange.)\n";
1581  return false;
1582  }
1583  else if (OTItem::acknowledgement !=
1584  pResponseTransactionItem->GetStatus()) {
1585  // error, return.
1586  otOut << "Error: atTransactionStatement found on receipt, but not "
1587  "a successful one.\n";
1588  return false;
1589  }
1590  else if (!pResponseTransactionItem->VerifySignature(SERVER_NYM)) {
1591  otOut << "Unable to verify signature on atTransactionStatement "
1592  "item in OTTransaction::VerifyBalanceReceipt.\n";
1593  return false;
1594  }
1595 
1596  // LOAD "TRANSACTION STATEMENT" (ITEM) from within the above item we
1597  // got.
1598 
1599  OTString strBalanceItem;
1600  pResponseTransactionItem->GetReferenceString(strBalanceItem);
1601 
1602  if (!strBalanceItem.Exists()) {
1603  // error, return.
1604  otOut << "No transactionStatement item found as 'in ref to' string "
1605  "on a receipt containing atTransactionStatement item.\n";
1606  return false;
1607  }
1608 
1609  pTransactionItem = OTItem::CreateItemFromString(
1610  strBalanceItem, GetRealServerID(),
1611  pResponseTransactionItem->GetReferenceToNum());
1612 
1613  if (nullptr == pTransactionItem) {
1614  otOut << "Unable to load transactionStatement item from string "
1615  "(from a receipt containing an atTransactionStatement "
1616  "item.)\n";
1617  return false;
1618  }
1619  else if (pTransactionItem->GetType() !=
1621  otOut << "Wrong type on pTransactionItem (expected "
1622  "OTItem::transactionStatement)\n";
1623  return false;
1624  }
1625  else if (!pTransactionItem->VerifySignature(THE_NYM)) {
1626  otOut << "Unable to verify signature on transactionStatement item "
1627  "in OTTransaction::VerifyBalanceReceipt.\n";
1628  return false;
1629  }
1630 
1631  pItemWithIssuedList = pTransactionItem;
1632  }
1633 
1634  // LOAD THE ACCOUNT
1635 
1636  OTAccount THE_ACCOUNT(USER_ID, GetRealAccountID(), GetRealServerID());
1637 
1638  if (!THE_ACCOUNT.LoadContract() || !THE_ACCOUNT.VerifyAccount(THE_NYM)) {
1639  // error, return.
1640  otOut << "Failed loading or verifying account for THE_NYM in "
1641  "OTTransaction::VerifyBalanceReceipt.\n";
1642  return false;
1643  }
1644  else if (THE_ACCOUNT.GetPurportedServerID() !=
1645  GetPurportedServerID()) // the account, inbox, and outbox all
1646  // have the same Server ID. But does it
1647  // match *this receipt?
1648  {
1649  // error, return.
1650  otOut << "Account, inbox or outbox server ID fails to match receipt "
1651  "server ID.\n";
1652  return false;
1653  }
1654  else if (THE_ACCOUNT.GetPurportedAccountID() !=
1655  GetPurportedAccountID()) // Same as above except for account ID
1656  // instead of server ID.
1657  {
1658  // error, return.
1659  otOut << "Account ID fails to match receipt account ID.\n";
1660  return false;
1661  }
1662 
1663  // LOAD INBOX AND OUTBOX
1664 
1665  std::unique_ptr<OTLedger> pInbox(THE_ACCOUNT.LoadInbox(
1666  THE_NYM)); // OTAccount::Load also calls VerifyAccount() already
1667  std::unique_ptr<OTLedger> pOutbox(THE_ACCOUNT.LoadOutbox(
1668  THE_NYM)); // OTAccount::Load also calls VerifyAccount() already
1669 
1670  if ((nullptr == pInbox) || (nullptr == pOutbox)) {
1671  // error, return.
1672  otOut << "Inbox or outbox was nullptr after THE_ACCOUNT.Load in "
1673  "OTTransaction::VerifyBalanceReceipt.\n";
1674  return false;
1675  }
1676 
1677  // LOAD "AT BALANCE STATEMENT" (ITEM)
1678 
1679  OTItem* pResponseBalanceItem = GetItem(OTItem::atBalanceStatement);
1680 
1681  if (nullptr == pResponseBalanceItem) {
1682  // error, return.
1683  otOut << "No atBalanceStatement item found on receipt (strange.)\n";
1684  return false;
1685  }
1686  else if (OTItem::acknowledgement != pResponseBalanceItem->GetStatus()) {
1687  // error, return.
1688  otOut << "Error: atBalanceStatement found on receipt, but not a "
1689  "successful one.\n";
1690  return false;
1691  }
1692  else if (!pResponseBalanceItem->VerifySignature(SERVER_NYM)) {
1693  otOut << "Unable to verify signature on atBalanceStatement item in "
1694  "OTTransaction::VerifyBalanceReceipt.\n";
1695  return false;
1696  }
1697 
1698  // LOAD "BALANCE STATEMENT" (ITEM)
1699 
1700  OTItem* pBalanceItem = nullptr;
1701 
1702  OTString strBalanceItem;
1703  pResponseBalanceItem->GetReferenceString(strBalanceItem);
1704 
1705  if (!strBalanceItem.Exists()) {
1706  // error, return.
1707  otOut << "No balanceStatement item found as 'in ref to' string on a "
1708  "receipt containing atBalanceStatement item.\n";
1709  return false;
1710  }
1711 
1712  pBalanceItem =
1714  pResponseBalanceItem->GetReferenceToNum());
1715 
1716  if (nullptr == pBalanceItem) {
1717  otOut << "Unable to load balanceStatement item from string (from a "
1718  "receipt containing an atBalanceStatement item.)\n";
1719  return false;
1720  }
1721  else if (pBalanceItem->GetType() != OTItem::balanceStatement) {
1722  otOut << "Wrong type on pBalanceItem (expected "
1723  "OTItem::balanceStatement)\n";
1724  return false;
1725  }
1726  else if (!pBalanceItem->VerifySignature(THE_NYM)) {
1727  otOut << "Unable to verify signature on balanceStatement item in "
1728  "OTTransaction::VerifyBalanceReceipt.\n";
1729  return false;
1730  }
1731 
1732  // LOAD MESSAGE NYM (THE LIST OF ISSUED NUMBERS ACCORDING TO THE RECEIPT.)
1733 
1734  OTPseudonym theMessageNym;
1735  OTString strMessageNym; // Okay now we have the transaction numbers in this
1736  // MessageNym string.
1737 
1738  //
1739  if ((nullptr != pTransactionItem) &&
1740  (tranOut.GetDateSigned() > GetDateSigned())) // transaction
1741  // statement is newer
1742  // than (this)
1743  // balance statement.
1744  pItemWithIssuedList =
1745  pTransactionItem; // already set above, but I'm re-stating here for
1746  // clarity, since the else is now possible...
1747  else
1748  pItemWithIssuedList =
1749  pBalanceItem; // Hereafter we can use pItemWithIssuedList to verify
1750  // issued transaction numbers (and NOTHING ELSE.)
1751 
1752  pItemWithIssuedList->GetAttachment(
1753  strMessageNym); // Like right here, for example.
1754 
1755  if (!strMessageNym.Exists() ||
1756  !theMessageNym.LoadFromString(strMessageNym)) {
1757  otOut << "Unable to load message nym in "
1758  "OTTransaction::VerifyBalanceReceipt.\n";
1759  return false;
1760  }
1761 
1762  // Finally everything is loaded and verified!
1763  // I have the Nym and Server Nym
1764  // I have the account, inbox, and outbox
1765  // I have the original balance statement, AND the server's reply to it (a
1766  // successful one)
1767  //
1768  // Repeating a note from above:
1769  // -- Verify nym transactions match. (The issued / signed-for ones.)
1770  // -- Verify outbox matches.
1771  // -- Loop through all items on receipt. If outbox item, should match
1772  // exactly.
1773  // -- But for inbox items, total up: the amount of the total of the items
1774  // from the receipt,
1775  // for all those that would actually change the balance (chequeReceipt,
1776  // marketReceipt, paymentReceipt.)
1777  // These should ALL be found in the current version of the inbox. (They
1778  // can only be removed by balance agreement which would update THIS RECEIPT
1779  // to remove them...)
1780  // -- That was the receipt. Now loop through the latest inbox items and do
1781  // the reverse: for each item in the NEW inbox,
1782  // add up the total of those that would change the balance, for receipts
1783  // found on the new but not the old, and account for that exactly as a
1784  // difference in balance.
1785  // Also make sure each receipt in the inbox (new or old) is an issued
1786  // transaction number, signed out to THE_NYM.
1787 
1788  // VERIFY THE LIST OF ISSUED (SIGNED FOR) TRANSACTION NUMBERS ON THE NYM
1789  // AGAINST THE RECEIPT.
1790  // The Nym should match whatever is on the newest receipt (determined just
1791  // above.)
1792  //
1793  // NOTE: I used to VerifyIssuedNumbersOnNym -- but that won't work. Why?
1794  // Because let's say I signed a balance agreement with #s 9, 10, and 11.
1795  // That's my last receipt. Now let's say, using a DIFFERENT ASSET ACCOUNT, I
1796  // do a withdrawal, burning #9. Now my balance agreement says 10, 11 for
1797  // that other account, which correctly matches the server. Now when the
1798  // FIRST ACCOUNT verifies his (formerly valid) receipt, 9 is missing from
1799  // his nym,
1800  // which doesn't match the receipt! Of course that's because there's a
1801  // newer balance receipt -- BUT ON A DIFFERENT ASSET ACCOUNT.
1802  //
1803  // VerifyTransactionStatement (vs VerifyBalanceStatement, where we are now)
1804  // gets around this whole problem with
1805  // VerifyTransactionStatementNumbersOnNym,
1806  // which only verifies that every issued number found on THE_NYM
1807  // (client-side) is definitely also found in the receipt (theMessageNym). It
1808  // does NOT do the reverse.
1809  // In other words, it does NOT make sure that every Trans# on theMessageNym
1810  // (last receipt) is also found on THE_NYM (current client-side nym.)
1811  // Numbers may
1812  // have been cleared since that receipt was signed, due to a balance
1813  // agreement FROM A DIFFERENT ASSET ACCOUNT. This is okay since numbers have
1814  // not been ADDED
1815  // to your list of responsibility (which is the danger.) In order to ADD a
1816  // number to your list, a transaction statement would have to be signed,
1817  // since new
1818  // transaction numbers can only be received through the Nymbox. Since this
1819  // function (VerifyBalanceReceipt) uses the transactionStatement for
1820  // verifying issued
1821  // numbers in cases where it is newer than the balanceStatement, then if a
1822  // new number was added, it will be on the receipt already.
1823  //
1824  // if (!THE_NYM.VerifyIssuedNumbersOnNym(theMessageNym)) // Explained
1825  // above. Balance Statements from other accts might be newer, and have
1826  // burned #s already. Thus I
1827  if (!THE_NYM.VerifyTransactionStatementNumbersOnNym(
1828  theMessageNym)) // Can't expect a # on the receipt to still be
1829  // available, though I MUST verify that every
1830  // number on current Nym IS on the receipt (just
1831  // not the other way around.)
1832  {
1833  otOut << "Unable to verify issued numbers on last signed receipt with "
1834  "numbers on THE_NYM in OTTransaction::VerifyBalanceReceipt.\n";
1835  return false;
1836  }
1837 
1838  // LOOP THROUGH THE BALANCE STATEMENT ITEMS (INBOX AND OUTBOX) TO GATHER
1839  // SOME DATA...
1840 
1841  int32_t nInboxItemCount = 0, nOutboxItemCount = 0;
1842 
1843  // otErr << "BEFORE LOOP nInboxItemCount: %d nOutboxItemCount: %d\n",
1844  // nInboxItemCount, nOutboxItemCount);
1845 
1846  const char* szInbox = "Inbox";
1847  const char* szOutbox = "Outbox";
1848  const char* pszLedgerType = nullptr;
1849  int64_t lReceiptBalanceChange =
1850  0; // For measuring the amount of the total of items in the inbox that
1851  // have changed the balance (like cheque receipts)
1852 
1853  // Notice here, I'm back to using pBalanceItem instead of
1854  // pItemWithIssuedList, since this is the inbox/outbox section...
1855  otWarn << "Number of inbox/outbox items on the balance statement: "
1856  << pBalanceItem->GetItemCount() << "\n";
1857 
1858  // TODO: Note: If the balance item shows a FINAL RECEIPT present, then ALL
1859  // the co-related cron receipts in
1860  // the ACTUAL INBOX must ALSO be present on the balance item, just as the
1861  // final receipt is present. IT cannot
1862  // be there unless THEY are also there! (The WHOLE PURPOSE of the final
1863  // receipt is to MAKE SURE that all its
1864  // related paymentReceipts/marketReceipts have been CLOSED OUT.)
1865  //
1866 
1867  for (int32_t i = 0; i < pBalanceItem->GetItemCount(); i++) {
1868  // for outbox calculations. (It's the only case where GetReceiptAmount()
1869  // is wrong and needs -1 multiplication.)
1870  int64_t lReceiptAmountMultiplier = 1;
1871 
1872  OTItem* pSubItem = pBalanceItem->GetItem(i);
1873 
1874  OT_ASSERT(nullptr != pSubItem);
1875 
1876  OTLedger* pLedger = nullptr;
1877 
1878  switch (pSubItem->GetType()) {
1879 
1880  // These types of receipts can actually change your balance.
1881  //
1882  case OTItem::chequeReceipt:
1883  case OTItem::marketReceipt:
1885  case OTItem::basketReceipt:
1886 
1887  lReceiptBalanceChange += pSubItem->GetAmount();
1888 
1889  // otErr << "RECEIPT: lReceiptBalanceChange: %lld
1890  // pSubItem->GetAmount() %lld\n",
1891  // lReceiptBalanceChange, pSubItem->GetAmount());
1892 
1893  // DROPS THROUGH HERE...
1894  case OTItem::transferReceipt: // These types of receipts do NOT change
1895  // your balance.
1897  case OTItem::finalReceipt:
1898 
1899  nInboxItemCount++;
1900  // otErr << "RECEIPT: nInboxItemCount: %d
1901  // nOutboxItemCount: %d\n", nInboxItemCount, nOutboxItemCount);
1902  pLedger = pInbox.get();
1903  pszLedgerType = szInbox;
1904 
1905  // DROPS THROUGH HERE...
1906  case OTItem::transfer:
1907 
1908  break; // we'll handle this in the next switch.
1909 
1910  default: {
1911  OTString strItemType;
1912  pSubItem->GetTypeString(strItemType);
1913  otLog3
1914  << "OTTransaction::VerifyBalanceReceipt: Ignoring "
1915  << strItemType
1916  << " item "
1917  "in balance statement while verifying it against inbox.\n";
1918  }
1919  continue;
1920  }
1921 
1922  switch (pSubItem->GetType()) {
1923  case OTItem::transfer:
1924 
1925  if (pSubItem->GetAmount() < 0) // it's an outbox item
1926  {
1927  lReceiptAmountMultiplier =
1928  -1; // transfers out always reduce your balance.
1929  nOutboxItemCount++;
1930 
1931  // otErr << "GetAmount() negative, OUTBOX
1932  // ITEM: nInboxItemCount: %d nOutboxItemCount: %d\n",
1933  // nInboxItemCount, nOutboxItemCount);
1934 
1935  pLedger = pOutbox.get();
1936  pszLedgerType = szOutbox;
1937  }
1938  else {
1939  lReceiptAmountMultiplier =
1940  1; // transfers in always increase your balance.
1941  nInboxItemCount++;
1942  pLedger = pInbox.get();
1943  pszLedgerType = szInbox;
1944 
1945  // otErr << "GetAmount() POSITIVE, INBOX
1946  // ITEM: nInboxItemCount: %d nOutboxItemCount: %d\n",
1947  // nInboxItemCount, nOutboxItemCount);
1948  }
1949  break;
1950 
1951  case OTItem::finalReceipt: // will have a 0 receipt amount.
1952  case OTItem::transferReceipt: // will have a 0 receipt amount.
1953  case OTItem::voucherReceipt: // will have a 0 receipt amount.
1954  case OTItem::chequeReceipt:
1955  case OTItem::marketReceipt: // will already be negative or positive
1956  // based on whichever is appropriate.
1957  case OTItem::paymentReceipt: // will already be negative or positive
1958  // based on whichever is appropriate.
1959  case OTItem::basketReceipt: // will already be negative or positive
1960  // based on whichever is appropriate.
1961  lReceiptAmountMultiplier = 1;
1962  break;
1963  default:
1964  continue; // This will never happen, due to the first continue above
1965  // in the first switch.
1966  }
1967 
1968  OTTransaction* pTransaction = nullptr;
1969 
1970  int64_t lTempTransactionNum = 0; // Used for the below block.
1971  int64_t lTempReferenceToNum = 0; // Used for the below block.
1972  int64_t lTempNumberOfOrigin = 0; // Used for the below block.
1973 
1974  // What's going on here? In the original balance statement, ONLY IN
1975  // CASES OF OUTOING TRANSFER,
1976  // the user has put transaction # "1" in his outbox, in anticipation
1977  // that
1978  // the server, upon success, will actually put a real pending transfer
1979  // into his outbox, and
1980  // issue a number for it (like "34").
1981  if ((pOutbox.get() ==
1982  pLedger) && // Thus it's understood that whenever the
1983  // balanceStatement
1984  // has a "1" in the outbox, I should find a corresponding "34" (or
1985  // whatever # the
1986  (pSubItem->GetTransactionNum() ==
1987  1) && // server chose) as the GetNewOutboxTransNum member on the
1988  // atBalanceStatement.
1989  // Now here, when verifying the receipt, this allows me to verify
1990  // the
1991  (pResponseBalanceItem->GetNewOutboxTransNum() >
1992  0)) // outbox request '1' against the actual '34' that resulted.
1993  {
1994  lTempTransactionNum = pResponseBalanceItem->GetNewOutboxTransNum();
1995  pTransaction = pLedger->GetTransaction(lTempTransactionNum);
1996 
1997  otLog3 << "OTTransaction::VerifyBalanceReceipt: (This iteration, "
1998  "I'm handling an item listed as '1' in the outbox.)\n";
1999  }
2000  else { // THE ABOVE IS THE *UNUSUAL* CASE, WHEREAS THIS IS THE NORMAL
2001  // CASE:
2002  //
2003  // Make sure that the transaction number of each sub-item is found
2004  // on the appropriate ledger (inbox or outbox).
2005 
2006  lTempTransactionNum = pSubItem->GetTransactionNum();
2007  pTransaction = pLedger->GetTransaction(lTempTransactionNum);
2008  }
2009 
2010  if (nullptr != pTransaction) {
2011  lTempReferenceToNum = pTransaction->GetReferenceToNum();
2012  lTempNumberOfOrigin = pTransaction->GetRawNumberOfOrigin();
2013  }
2014 
2015  bool bSwitchedBoxes = false; // In the event that an outbox pending
2016  // transforms into an inbox
2017  // transferReceipt, I set this true.
2018 
2019  // Let's say I sign a balance receipt showing a 100 clam pending
2020  // transfer, sitting in my outbox.
2021  // That means someday when I VERIFY that receipt, the 100 clam pending
2022  // better still be in that
2023  // outbox, or verification will fail. BUT WAIT -- if the receipient
2024  // accepts the transfer, then it
2025  // will disappear out of my outbox, and show up in my inbox as a
2026  // transferReceipt. So when I go to
2027  // verify my balance receipt, I have to expect that any outbox item
2028  // might be missing, but if that is
2029  // the case, there had better be a matching transferReceipt in the
2030  // inbox. (That wouldn't disappear
2031  // unless I processed my inbox, and signed a new balance agreement to
2032  // get rid of it, so I know it
2033  // has to be there in the inbox if the pending wasn't in the outbox. (If
2034  // the receipt is any good.)
2035  //
2036  // Therefore the code has to specifically allow for this case, for
2037  // outbox items...
2038  if ((nullptr == pTransaction) && (pOutbox.get() == pLedger)) {
2039  otLog4 << "OTTransaction::" << __FUNCTION__
2040  << ": Outbox pending found as inbox transferReceipt. "
2041  "(Normal.)\n";
2042 
2043  // We didn't find the transaction that was expected to be in the
2044  // outbox. (A pending.)
2045  // Therefore maybe it is now a transfer receipt in the Inbox. We
2046  // allow for this case.
2047 
2048  pTransaction =
2049  pInbox->GetTransferReceipt(pSubItem->GetNumberOfOrigin());
2050 
2051  if (nullptr != pTransaction) {
2052  lTempTransactionNum = pTransaction->GetTransactionNum();
2053  lTempNumberOfOrigin = pTransaction->GetRawNumberOfOrigin();
2054 
2055  // re: the code below: lTempReferenceToNum =
2056  // pSubItem->GetReferenceToNum();
2057  //
2058  // If it had been in the outbox, the pending receipt would be
2059  // "in reference to" my original
2060  // transfer.
2061  // But if it's since been processed into a transferReceipt in my
2062  // inbox, that transferReceipt
2063  // is now "in reference to" the recipient's acceptPending, and
2064  // thus is NOT in reference to
2065  // my original transfer.
2066  // Thus, when the ref num is compared (a little farther below)
2067  // to pSubItem->RefNum, it's
2068  // GUARANTEED to fail. That is why we are using
2069  // pSubItem->GetReferenceToNum here instead of
2070  // pTransaction->GetReferenceToNum.
2071  //
2072  // Now you might ask, "Then why, below, are we comparing
2073  // lTempReferenceToNum (containing
2074  // pSubItem->GetReferenceToNum) to pSubItem->GetReferenceToNum
2075  // ?? Aren't we just comparing
2076  // it to itself?"
2077  //
2078  // The answer is yes, in this specific case, we are. But
2079  // remember, in most cases, lTempReferenceToNum
2080  // contains pTransaction->GetReferenceToNum, and so in most
2081  // cases we are NOT comparing it
2082  // to itself. ONLY in this specific case where the receipt has
2083  // changed from an outbox-based
2084  // pending to an inbox-based transferReceipt. And so here,
2085  // lTempReferenceToNum is set to pSubItem's
2086  // version, so that it will not fail the below comparison, which
2087  // would otherwise succeed properly
2088  // in all other cases.
2089  //
2090  // Next you might ask, "But if we are comparing it to itself in
2091  // this specific case, sure it will
2092  // pass the comparison, but then what happens to the security,
2093  // in this specific case?"
2094  //
2095  // The answer is, the very next comparison after that is for the
2096  // NumberOfOrigin, which is unique
2097  // and which still must match. (Therefore we are still
2098  // protected.)
2099  //
2100  lTempReferenceToNum = pSubItem->GetReferenceToNum();
2101 
2102  lReceiptAmountMultiplier = 1;
2103 
2104  nInboxItemCount++;
2105  nOutboxItemCount--;
2106 
2107  // otErr << "PENDING->TransferReceipt.
2108  // nInboxItemCount: %d nOutboxItemCount: %d\n",
2109  // nInboxItemCount, nOutboxItemCount);
2110 
2111  pLedger = pInbox.get();
2112  pszLedgerType = szInbox;
2113 
2114  bSwitchedBoxes =
2115  true; // We need to know this in one place below.
2116  }
2117 
2118  /*
2119  Pending:
2120  Outbox: 1901, referencing 1884
2121  Inbox: 1901, referencing 1884
2122 
2123 
2124  transfer receipt:
2125  Trans 1902, referencing 1884 (That's just the display, however.
2126  Really 1902 refs 781, which refs 1884.)
2127 
2128 
2129  The pending in the outbox REFERENCES the right number.
2130 
2131  The transfer receipt includes (ref string) an acceptPending that
2132  references the right number.
2133 
2134  So for pending in outbox, when failure, get ReferenceNum(), and use
2135  that to find item in Inbox using GetTransferReceipt().
2136  */
2137  }
2138 
2139  // STILL not found??
2140  if (nullptr == pTransaction) {
2141  otOut << "OTTransaction::" << __FUNCTION__ << ": Expected "
2142  << pszLedgerType << " transaction (" << lTempTransactionNum
2143  << ") not found. (Amount " << pSubItem->GetAmount() << ".)\n";
2144  return false;
2145  }
2146 
2147  // subItem is from the balance statement, and pTransaction is from the
2148  // inbox/outbox
2149  if (pSubItem->GetReferenceToNum() != lTempReferenceToNum) {
2150  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2151  << " transaction (" << lTempTransactionNum
2152  << ") mismatch Reference Num: "
2153  << pSubItem->GetReferenceToNum() << ", expected "
2154  << lTempReferenceToNum << "\n";
2155  return false;
2156  }
2157 
2158  if (pSubItem->GetRawNumberOfOrigin() != lTempNumberOfOrigin) {
2159  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2160  << " transaction (" << lTempTransactionNum
2161  << ") mismatch Number of Origin: "
2162  << pSubItem->GetRawNumberOfOrigin() << ", expected "
2163  << lTempNumberOfOrigin << "\n";
2164  return false;
2165  }
2166 
2167  int64_t lTransactionAmount = pTransaction->GetReceiptAmount();
2168  lTransactionAmount *= lReceiptAmountMultiplier;
2169 
2170  if (pSubItem->GetAmount() != lTransactionAmount) {
2171  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2172  << " transaction (" << lTempTransactionNum
2173  << ") "
2174  "amounts don't match: Report says "
2175  << pSubItem->GetAmount() << ", but expected "
2176  << lTransactionAmount
2177  << ". Trans recpt amt: " << pTransaction->GetReceiptAmount()
2178  << ", (pBalanceItem->GetAmount() == "
2179  << pBalanceItem->GetAmount() << ".)\n";
2180  return false;
2181  }
2182 
2183  if ((pSubItem->GetType() == OTItem::transfer) &&
2184  (((bSwitchedBoxes == true) &&
2185  (pTransaction->GetType() != OTTransaction::transferReceipt)) ||
2186  ((pLedger == pOutbox.get()) &&
2187  (pTransaction->GetType() != OTTransaction::pending)) ||
2188  ((pLedger == pInbox.get()) &&
2189  (pTransaction->GetType() != OTTransaction::pending) &&
2190  (pTransaction->GetType() != OTTransaction::transferReceipt)))) {
2191  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2192  << " transaction (" << lTempTransactionNum
2193  << ") wrong type. (pending block)\n";
2194  return false;
2195  }
2196 
2197  if ((pSubItem->GetType() == OTItem::chequeReceipt) &&
2198  (pTransaction->GetType() != OTTransaction::chequeReceipt)) {
2199  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2200  << " transaction (" << lTempTransactionNum
2201  << ") wrong type. (chequeReceipt block)\n";
2202  return false;
2203  }
2204 
2205  if ((pSubItem->GetType() == OTItem::voucherReceipt) &&
2206  (pTransaction->GetType() != OTTransaction::voucherReceipt)) {
2207  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2208  << " transaction (" << lTempTransactionNum
2209  << ") wrong type. (voucherReceipt block)\n";
2210  return false;
2211  }
2212 
2213  if ((pSubItem->GetType() == OTItem::marketReceipt) &&
2214  (pTransaction->GetType() != OTTransaction::marketReceipt)) {
2215  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2216  << " transaction (" << lTempTransactionNum
2217  << ") wrong type. (marketReceipt block)\n";
2218  return false;
2219  }
2220 
2221  if ((pSubItem->GetType() == OTItem::paymentReceipt) &&
2222  (pTransaction->GetType() != OTTransaction::paymentReceipt)) {
2223  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2224  << " transaction (" << lTempTransactionNum
2225  << ") wrong type. (paymentReceipt block)\n";
2226  return false;
2227  }
2228 
2229  if ((pSubItem->GetType() == OTItem::transferReceipt) &&
2230  (pTransaction->GetType() != OTTransaction::transferReceipt)) {
2231  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2232  << " transaction (" << lTempTransactionNum
2233  << ") wrong type. (transferReceipt block)\n";
2234  return false;
2235  }
2236 
2237  if ((pSubItem->GetType() == OTItem::basketReceipt) &&
2238  ((pTransaction->GetType() != OTTransaction::basketReceipt) ||
2239  (pSubItem->GetClosingNum() != pTransaction->GetClosingNum()))) {
2240  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2241  << " transaction (" << lTempTransactionNum
2242  << ") wrong type or closing num ("
2243  << pSubItem->GetClosingNum() << "). "
2244  "(basketReceipt block)\n";
2245  return false;
2246  }
2247 
2248  if ((pSubItem->GetType() == OTItem::finalReceipt) &&
2249  ((pTransaction->GetType() != OTTransaction::finalReceipt) ||
2250  (pSubItem->GetClosingNum() != pTransaction->GetClosingNum()))) {
2251  otOut << "OTTransaction::" << __FUNCTION__ << ": " << pszLedgerType
2252  << " transaction (" << lTempTransactionNum
2253  << ") wrong type or closing num ("
2254  << pSubItem->GetClosingNum() << "). "
2255  "(finalReceipt block)\n";
2256  return false;
2257  }
2258  }
2259 
2260  // By this point, I have an accurate count of the inbox items, and outbox
2261  // items, represented
2262  // by *this receipt.
2263  // I also know that I found each item from the receipt on the new inbox or
2264  // outbox (as I should have)
2265  // But do I have to verify that the items are all signed for. I'll do that
2266  // below since this list
2267  // is a subset of that one (supposedly.)
2268 
2269  // otErr << "BEFORE COUNT MATCH. nInboxItemCount: %d nOutboxItemCount:
2270  // %d\n", nInboxItemCount, nOutboxItemCount);
2271 
2272  if (nOutboxItemCount != pOutbox->GetTransactionCount()) {
2273  otOut << "OTTransaction::" << __FUNCTION__
2274  << ": Outbox mismatch in expected transaction count.\n"
2275  " --- THE_INBOX count: " << pInbox->GetTransactionCount()
2276  << " --- THE_OUTBOX count: " << pOutbox->GetTransactionCount()
2277  << "\n"
2278  "--- nInboxItemCount: " << nInboxItemCount
2279  << " --- nOutboxItemCount: " << nOutboxItemCount << "\n\n";
2280 
2281  return false;
2282  }
2283 
2284  // (Notice I don't check inbox item count here, since that actually CAN
2285  // change.)
2286 
2287  // LOOP THROUGH LATEST INBOX AND GATHER DATA / VALIDATE AGAINST LAST
2288  // RECEIPT.
2289 
2290  int64_t lInboxBalanceChange = 0; // Change in the account balance we'd
2291  // expect, based on TOTAL receipts in the
2292  // inbox.
2293  int64_t lInboxSupposedDifference = 0; // Change in the account balance we'd
2294  // expect, based on the NEW receipts
2295  // in the inbox.
2296 
2297  for (int32_t i = 0; i < pInbox->GetTransactionCount(); i++) {
2298  OTTransaction* pTransaction = pInbox->GetTransactionByIndex(i);
2299 
2300  OT_ASSERT(nullptr != pTransaction);
2301 
2302  switch (pTransaction->GetType()) {
2307 
2308  lInboxBalanceChange +=
2309  pTransaction->GetReceiptAmount(); // Here I total ALL relevant
2310  // receipts.
2311 
2312  // otErr << "ON INBOX: lInboxBalanceChange: %lld
2313  // pTransaction->GetReceiptAmount(): %lld\n", // temp remove debugging
2314  // todo
2315  // lInboxBalanceChange,
2316  // pTransaction->GetReceiptAmount());
2317 
2318  case OTTransaction::finalReceipt: // finalReceipt has no amount.
2319  case OTTransaction::pending: // pending has an amount, but it already
2320  // came out of the account and thus isn't
2321  // figured here.
2322  case OTTransaction::transferReceipt: // transferReceipt has an amount,
2323  // but it already came out of
2324  // account and thus isn't figured in here.
2325  case OTTransaction::voucherReceipt: // voucherReceipt has an amount, but
2326  // it already came out of account
2327  // and thus isn't figured in here.
2328  break;
2329  default: {
2330  otLog4 << "OTTransaction::" << __FUNCTION__ << ": Ignoring "
2331  << pTransaction->GetTypeString()
2332  << " item in inbox while verifying it against balance "
2333  "receipt.\n";
2334  }
2335  continue;
2336  }
2337 
2338  // This "for" loop is in the process of iterating the LATEST INBOX...
2339  // ...For each receipt in that inbox, we try and look up a record of the
2340  // exact same receipt in
2341  // the INBOX REPORT (present in the balance agreement from the LAST
2342  // SIGNED TRANSACTION RECEIPT.)
2343  //
2344  // It may or may not be found...
2345 
2346  OTItem* pSubItem = pBalanceItem->GetItemByTransactionNum(
2347  pTransaction->GetTransactionNum());
2348 
2349  // The above loop already verified that all items in the receipt's inbox
2350  // were found in the new inbox.
2351  //
2352  // But THIS item, though found in the new inbox, WAS NOT FOUND in the
2353  // OLD inbox (on the receipt.)
2354  // That means it needs to be accounted for against the account balance!
2355  //
2356  if (nullptr == pSubItem) {
2357  OTItem* pFinalReceiptItem = nullptr;
2358  switch (pTransaction->GetType()) {
2361  //
2362  // New thought: if this transaction is from cron (paymentReceipt
2363  // or marketReceipt), AND THIS BEING A NEW ITEM
2364  // that IS in the latest inbox (but was NOT there before, in the
2365  // receipt), THEN the finalReceipt for THIS
2366  // transaction had BETTER NOT BE in the old inbox from my last
2367  // receipt!!
2368  //
2369  // Logic: Because the whole point of the finalReceipt is to
2370  // prevent any NEW marketReceipts from popping in,
2371  // once it is present! It's like a "red flag" or a "filing date"
2372  // -- once it is triggered, IT IS THE FINAL RECEIPT.
2373  // No other receipts can appear that reference the same
2374  // transaction number!
2375  //
2376  // THEREFORE: If the FINAL RECEIPT is ALREADY in my last signed
2377  // receipt, then WHY IN HELL are NEW marketReceipts or
2378  // paymentReceipts going into the latest inbox ??
2379  //
2380  // That is why I verify here that, IF THIS IS A CRON
2381  // TRANSACTION (payment, market), then the finalReceipt
2382  // should NOT be present in the inbox report from the last
2383  // receipt!
2384  //
2385 
2386  pFinalReceiptItem =
2387  pBalanceItem->GetFinalReceiptItemByReferenceNum(
2388  pTransaction->GetReferenceToNum());
2389 
2390  // If it was FOUND... (bad)
2391  //
2392  if (nullptr != pFinalReceiptItem) {
2393  otOut << "OTTransaction::" << __FUNCTION__
2394  << ": Malicious server? A new cronReceipt has "
2395  "appeared, "
2396  "even though its corresponding \nfinalReceipt was "
2397  "already present in the LAST SIGNED RECEIPT. "
2398  "In reference to: "
2399  << pTransaction->GetReferenceToNum() << "\n";
2400  return false;
2401  }
2402  // else drop-through, since marketReceipts and paymentReceipts DO
2403  // affect the balance...
2404 
2405  case OTTransaction::chequeReceipt: // Every one of these, we have to
2406  // add up the total and reconcile
2407  // against the latest balance.
2409 
2410  lInboxSupposedDifference +=
2411  pTransaction->GetReceiptAmount(); // Here I only total the
2412  // NEW receipts (not found
2413  // in old receipt inbox
2414  // but found in current
2415  // inbox.)
2416 
2417  // otErr << "NOT ON RECEIPT:
2418  // lInboxSupposedDifference: %lld pTransaction->GetReceiptAmount():
2419  // %lld\n", // temp remove debugging todo
2420  // lInboxSupposedDifference,
2421  // pTransaction->GetReceiptAmount());
2422 
2423  case OTTransaction::finalReceipt: // This has no value. 0 amount.
2424  case OTTransaction::pending: // pending has value, why aren't we
2425  // adding it? Because it hasn't changed
2426  // the balance yet.
2427  case OTTransaction::transferReceipt: // transferReceipt has an
2428  // amount, but it already came
2429  // out of
2430  // the account and thus isn't figured in here.
2431  case OTTransaction::voucherReceipt: // voucherReceipt has an amount,
2432  // but it already came out of
2433  // the account and thus isn't figured in here.
2434  break;
2435 
2436  default:
2437  break; // this should never happen due to above switch.
2438  }
2439  }
2440  else // If the transaction from the inbox WAS found as an item on the
2441  // old receipt, let's verify the two against each other...
2442  {
2443  // subItem is from the balance statement, and pTransaction is from
2444  // the inbox
2445  if (pSubItem->GetReferenceToNum() !=
2446  pTransaction->GetReferenceToNum()) {
2447  otOut << "OTTransaction::" << __FUNCTION__
2448  << ": Inbox transaction ("
2449  << pSubItem->GetTransactionNum()
2450  << ") mismatch Reference Num: "
2451  << pSubItem->GetReferenceToNum() << ", expected "
2452  << pTransaction->GetReferenceToNum() << "\n";
2453  return false;
2454  }
2455 
2456  if (pSubItem->GetNumberOfOrigin() !=
2457  pTransaction->GetNumberOfOrigin()) {
2458  otOut << "OTTransaction::" << __FUNCTION__
2459  << ": Inbox transaction ("
2460  << pSubItem->GetTransactionNum()
2461  << ") mismatch Reference Num: "
2462  << pSubItem->GetNumberOfOrigin() << ", expected "
2463  << pTransaction->GetNumberOfOrigin() << "\n";
2464  return false;
2465  }
2466 
2467  // We're looping through the inbox here, so no multiplier is needed
2468  // for the amount
2469  // (that was only for outbox items.)
2470  if (pSubItem->GetAmount() != (pTransaction->GetReceiptAmount())) {
2471  otOut << "OTTransaction::" << __FUNCTION__
2472  << ": Inbox transaction ("
2473  << pSubItem->GetTransactionNum()
2474  << ") "
2475  "amounts don't match: " << pSubItem->GetAmount()
2476  << ", expected " << pTransaction->GetReceiptAmount()
2477  << ". (pBalanceItem->GetAmount() == "
2478  << pBalanceItem->GetAmount() << ".)\n";
2479  return false;
2480  }
2481 
2482  if ((pSubItem->GetType() == OTItem::transfer) &&
2483  (pTransaction->GetType() != OTTransaction::pending)) {
2484  otOut << "OTTransaction::" << __FUNCTION__
2485  << ": Inbox transaction ("
2486  << pSubItem->GetTransactionNum()
2487  << ") wrong type. (pending block)\n";
2488  return false;
2489  }
2490 
2491  if ((pSubItem->GetType() == OTItem::chequeReceipt) &&
2492  (pTransaction->GetType() != OTTransaction::chequeReceipt)) {
2493  otOut << "OTTransaction::" << __FUNCTION__
2494  << ": Inbox transaction ("
2495  << pSubItem->GetTransactionNum()
2496  << ") wrong type. "
2497  "(chequeReceipt block)\n";
2498  return false;
2499  }
2500 
2501  if ((pSubItem->GetType() == OTItem::voucherReceipt) &&
2502  (pTransaction->GetType() != OTTransaction::voucherReceipt)) {
2503  otOut << "OTTransaction:" << __FUNCTION__
2504  << ": Inbox transaction ("
2505  << pSubItem->GetTransactionNum()
2506  << ") wrong type. "
2507  "(voucherReceipt block)\n";
2508  return false;
2509  }
2510 
2511  if ((pSubItem->GetType() == OTItem::marketReceipt) &&
2512  (pTransaction->GetType() != OTTransaction::marketReceipt)) {
2513  otOut << "OTTransaction::" << __FUNCTION__
2514  << ": Inbox transaction ("
2515  << pSubItem->GetTransactionNum()
2516  << ") wrong type. "
2517  "(marketReceipt block)\n";
2518  return false;
2519  }
2520 
2521  if ((pSubItem->GetType() == OTItem::paymentReceipt) &&
2522  (pTransaction->GetType() != OTTransaction::paymentReceipt)) {
2523  otOut << "OTTransaction::" << __FUNCTION__
2524  << ": Inbox transaction ("
2525  << pSubItem->GetTransactionNum()
2526  << ") wrong type. "
2527  "(paymentReceipt block)\n";
2528  return false;
2529  }
2530 
2531  if ((pSubItem->GetType() == OTItem::transferReceipt) &&
2532  (pTransaction->GetType() != OTTransaction::transferReceipt)) {
2533  otOut << "OTTransaction::" << __FUNCTION__
2534  << ": Inbox transaction ("
2535  << pSubItem->GetTransactionNum()
2536  << ") wrong type. "
2537  "(transferReceipt block)\n";
2538  return false;
2539  }
2540 
2541  if ((pSubItem->GetType() == OTItem::basketReceipt) &&
2542  ((pTransaction->GetType() != OTTransaction::basketReceipt) ||
2543  (pSubItem->GetClosingNum() !=
2544  pTransaction->GetClosingNum()))) {
2545  otOut << "OTTransaction::" << __FUNCTION__
2546  << ": Inbox transaction ("
2547  << pSubItem->GetTransactionNum()
2548  << ") wrong type, "
2549  "or mismatched closing num. (basketReceipt block)\n";
2550  return false;
2551  }
2552 
2553  if ((pSubItem->GetType() == OTItem::finalReceipt) &&
2554  ((pTransaction->GetType() != OTTransaction::finalReceipt) ||
2555  (pSubItem->GetClosingNum() !=
2556  pTransaction->GetClosingNum()))) {
2557  otOut << "OTTransaction::" << __FUNCTION__
2558  << ": Inbox transaction ("
2559  << pSubItem->GetTransactionNum()
2560  << ") wrong type, "
2561  "or mismatched closing num. (finalReceipt block)\n";
2562  return false;
2563  }
2564 
2565  } // else pSubItem WAS found on the old receipt
2566 
2567  // Next I need to find out the transaction number that I ORIGINALLY
2568  // used, that's somehow associated with the receipt
2569  // I found in my inbox, by looking up the number from within the
2570  // receipt...
2571  //
2572  OTString strRespTo;
2573  int64_t lIssuedNum = 0; // The number that must STILL be signed out to
2574  // me, in order for this receipt not be warrant
2575  // disputing.
2576  OTTransaction* pFinalReceiptTransaction = nullptr;
2577 
2578  switch (pTransaction->GetType()) {
2579 
2580  case OTTransaction::transferReceipt: // a transfer receipt is in
2581  // reference to some guy's
2582  // acceptPending
2585 
2586  lIssuedNum = pTransaction->GetNumberOfOrigin();
2587  break;
2588 
2589  // ANY cron-related receipts should go here...
2590  //
2592  case OTTransaction::paymentReceipt: // a payment receipt #92 is IN
2593  // REFERENCE TO my payment plan #13,
2594  // which I am still signed out for... UNTIL the final receipt
2595  // appears.
2596  // Once a final receipt appears that is "in reference to" the same
2597  // number as a marketReceipt (or paymentReceipt)
2598  // then the paymentReceipt #92 is now IN REFERENCE TO my payment
2599  // plan #13, WHICH IS CLOSED FOR NEW PAYMENTS, BUT
2600  // THE PAYMENT RECEIPT ITSELF IS STILL VALID UNTIL THE "closing
2601  // transaction num" ON THAT FINAL RECEIPT IS CLOSED.
2602  //
2603  // Therefore I first need to see if the final receipt is PRESENT in
2604  // the inbox, so I can then determine
2605  // which number should be expected to be found on my ISSUED list of
2606  // transaction numbers.
2607  //
2608  pFinalReceiptTransaction =
2609  pInbox->GetFinalReceipt(pTransaction->GetReferenceToNum());
2610 
2611  if (nullptr != pFinalReceiptTransaction) // FINAL RECEIPT WAS FOUND
2612  lIssuedNum = pFinalReceiptTransaction->GetClosingNum();
2613  else // NOT found...
2614  lIssuedNum = pTransaction->GetReferenceToNum();
2615 
2616  // If marketReceipt #15 is IN REFERENCE TO original market offer
2617  // #10,
2618  // then the "ISSUED NUM" that is still open on my "signed out" list
2619  // is #10.
2620  //
2621  // UNLESS!! Unless a final receipt is present in reference to this
2622  // same number, in which
2623  // case the CLOSING TRANSACTION NUMBER stored on that final receipt
2624  // will become my ISSUED NUM
2625  // for the purposes of this code. (Because the original number IS
2626  // closed, but the marketReceipt is
2627  // also still valid until the FINAL RECEIPT is closed.)
2628  //
2629  break;
2630 
2631  // basketReceipt always expects the issued num to be its "closing num".
2632  // The "reference to" is instead
2633  // expected to contain the basketExchange ID (Trans# of the original
2634  // request to exchange, which is already closed.)
2635  //
2636  // Final Receipt expects that its "in reference to" is already closed
2637  // (that's why the final receipt even exists...)
2638  // Its own GetClosingNum() now contains the only valid possible
2639  // transaction number for this receipt (and for any related
2640  // to it in this same inbox, which share the same "in reference to"
2641  // number...
2642 
2645 
2646  lIssuedNum = pTransaction->GetClosingNum();
2647  break;
2648 
2649  default:
2650  continue; // Below this point (inside the loop) is ONLY for receipts
2651  // that somehow represent a transaction number that's
2652  // still issued / signed out to me.
2653  }
2654 
2655  // Whether pSubItem is nullptr or not, pTransaction DEFINITELY exists
2656  // either way, in the newest inbox.
2657  // Therefore, let's verify whether I'm even responsible for that
2658  // transaction number... (Just because I signed
2659  // the instrument at some point in the past does NOT mean that I'm still
2660  // responsible for the transaction number
2661  // that's listed on the instrument. Maybe I already used it up a long
2662  // time ago...)
2663  //
2664  if (!theMessageNym.VerifyIssuedNum(strServerID, lIssuedNum)) {
2665  otErr << "OTTransaction::" << __FUNCTION__
2666  << ": Error verifying if transaction num in inbox ("
2667  << pTransaction->GetTransactionNum()
2668  << ") was actually signed out (" << lIssuedNum << ")\n";
2669  return false;
2670  }
2671 
2672  // NOTE: the above check to VerifyIssuedNum... in the case of
2673  // basketReceipts and finalReceipts, lIssuedNum is the CLOSING num
2674  // (this is already done.)
2675  // With marketReceipts and paymentReceipts, they check for the existence
2676  // of a FINAL receipt, and if it's there, they use its CLOSING
2677  // NUM. Otherwise they use the "in reference to" num. With final
2678  // receipts it uses its CLOSING NUM, since the original is
2679  // presumed closed.
2680 
2681  } // for
2682 
2683  // BY THIS POINT, I have lReceiptBalanceChange with the total change in the
2684  // receipt, and
2685  // lInboxBalanceChange with the total change in the new inbox. The
2686  // difference between the two
2687  // is the difference I should expect also in the account balances! That
2688  // amount should also
2689  // be equal to lInboxSupposedDifference, which is the total of JUST the
2690  // inbox receipts that
2691  // I DIDN'T find in the old receipt (they were ONLY in the new inbox.)
2692  //
2693  // I have looped through all inbox items, and I know they were either found
2694  // in the receipt's inbox record
2695  // (and verified), or their amounts were added to lInboxSupposedDifference
2696  // as appropriate.
2697  //
2698  // I also verified, for each inbox item, IF IT TAKES MONEY, THEN IT MUST
2699  // HAVE A TRANSACTION NUMBER
2700  // SIGNED OUT TO ME... Otherwise I could dispute it. The last code above
2701  // verifies this.
2702  //
2703  // All that's left is to make sure the balance is right...
2704  //
2705 
2706  // VERIFY ACCOUNT BALANCE (RECONCILING WITH NEW INBOX RECEIPTS)
2707 
2708  // lReceiptBalanceChange -- The balance of all the inbox items on the
2709  // receipt (at least, the items that change the balance.)
2710  // lInboxBalanceChange -- The balance of all the inbox items in the
2711  // inbox (at least, the items that change the balance.)
2712  // lInboxSupposedDifference -- The balance of all the inbox items in the
2713  // inbox that were NOT found in the receipt (that change balance.)
2714  // lAbsoluteDifference -- The absolute difference between the inbox
2715  // balance and the receipt balance. (Always positive.)
2716  // lAbsoluteDifference -- The balance of all the inbox items
2717  // (including new items) minus the old ones that were on the receipt.
2718 
2719  // (Helping me to visualize lInboxBalanceChange and lReceiptBalanceChange)
2720  // ACTUAL SIMPLE ADD/SUBTRACT ADD/ABS
2721  // -5 -100 difference == 95 (-5 + -100 == -105) 105
2722  // 5 100 difference == 95 ( 5 + 100 == 105) 105
2723  // -5 100 difference == 105 (-5 + 100 == 95) 95
2724  // 5 -100 difference == 105 ( 5 + -100 == -95) 95
2725 
2726  // -100 -5 difference == 95 (-100 + -5 == -105) 105
2727  // 100 -5 difference == 105 ( 100 + -5 == 95) 95
2728  // -100 5 difference == 105 (-100 + 5 == -95) 95
2729  // 100 5 difference == 95 ( 100 + 5 == 105) 105
2730 
2731  // Above == wrong, Below == right.
2732 
2733  // ***SUBTRACT/ABS***
2734  // -5 -100 difference == 95 (-5 - -100 == 95) 95 *
2735  // 5 100 difference == 95 ( 5 - 100 == -95) 95 *
2736  // -5 100 difference == 105 (-5 - 100 == -105) 105 *
2737  // 5 -100 difference == 105 ( 5 - -100 == 105) 105 *
2738 
2739  // -100 -5 difference == 95 (-100 - -5 == -95) 95 *
2740  // 100 -5 difference == 105 ( 100 - -5 == 105) 105 *
2741  // -100 5 difference == 105 (-100 - 5 == -105) 105 *
2742  // 100 5 difference == 95 ( 100 - 5 == 95) 95 *
2743 
2744  // Based on the above table, the solution is to subtract one value from the
2745  // other,
2746  // and then take the absolute of that to get the actual difference. Then use
2747  // an
2748  // 'if' statement to see which was larger, and based on that, calculate
2749  // whether the
2750  // balance is what would be expected.
2751  //
2752  // -1099 // -99 (example of 1000 absolute difference)
2753 
2754  // How much money came out? (Or went in, if the chequeReceipt was for
2755  // an invoice...) 901 -99 (example of 1000 absolute difference)
2756  const int64_t lAbsoluteDifference =
2757  std::abs(lInboxBalanceChange - lReceiptBalanceChange);
2758  const int64_t lNegativeDifference = (lAbsoluteDifference * (-1));
2759 
2760  // The new (current) inbox has a larger overall value than the balance in
2761  // the old (receipt) inbox. (As shown by subitem.)
2762  const bool bNewInboxWasBigger =
2763  ((lInboxBalanceChange > lReceiptBalanceChange) ? true : false);
2764  const bool bNewInboxWasSmaller =
2765  ((lInboxBalanceChange < lReceiptBalanceChange) ? true : false);
2766 
2767  int64_t lActualDifference;
2768 
2769  if (bNewInboxWasBigger)
2770  lActualDifference = lAbsoluteDifference;
2771  else if (bNewInboxWasSmaller)
2772  lActualDifference = lNegativeDifference;
2773  else
2774  lActualDifference = 0;
2775 
2776  /*
2777  Example for logic:
2778 
2779  Old Inbox on Receipt:
2780  10
2781  15
2782  40
2783  lReceiptBalanceChange: 65
2784  Old Balance (in addition to these inbox items): 1000 (total 1065)
2785 
2786  New Inbox scenario A:
2787  10
2788  15
2789  40
2790  20 (lInboxSupposedDifference==(20)) 20
2791  lInboxBalanceChange: 85
2792 
2793  New Inbox scenario B:
2794  10
2795  15
2796  40
2797  -20 (lInboxSupposedDifference==(-20)) -20
2798  lInboxBalanceChange: 45
2799 
2800 
2801  Inbox A: lAbsoluteDifference=abs(85-65)==abs( 20)==20
2802  Inbox B: lAbsoluteDifference=abs(45-65)==abs(-20)==20
2803 
2804  Inbox A: lNegativeDifference == -20
2805  Inbox B: lNegativeDifference == -20
2806 
2807  Inbox A: bNewInboxWasBigger == TRUE,
2808  bNewInboxWasSmaller == FALSE
2809 
2810  Inbox B: bNewInboxWasBigger == FALSE,
2811  bNewInboxWasSmaller == TRUE
2812 
2813 
2814 
2815  if (
2816  (bNewInboxWasBigger && (lAbsoluteDifference !=
2817  lInboxSupposedDifference)) || // lInboxSupposedDifference should be
2818  positive here.
2819  (bNewInboxWasSmaller && (lNegativeDifference !=
2820  lInboxSupposedDifference)) // lInboxSupposedDifference should be
2821  negative here.
2822  )
2823 
2824  Inbox A:
2825  if (
2826  (TRUE && (20 != 20)) || // lInboxSupposedDifference should be
2827  positive here. ***
2828  (FALSE && (-20 != 20)) // lInboxSupposedDifference should be
2829  negative here.
2830  )
2831 
2832  Inbox B:
2833  if (
2834  (FALSE && (20 != -20)) || // lInboxSupposedDifference should be
2835  positive here.
2836  (TRUE && (-20 != -20)) // lInboxSupposedDifference should be
2837  negative here. ***
2838  )
2839 
2840  ---------------
2841  if (
2842  (lActualDifference != lInboxSupposedDifference)
2843  )
2844 
2845  Inbox A (bigger): (lActualDifference is lAbsoluteDifference)
2846  if ( 20 != 20)
2847 
2848  Inbox B (smaller): (lActualDifference is lNegativeDifference)
2849  if (-20 != -20)
2850 
2851  */
2852 
2853  // If the actual difference between the two totals is not equal to the
2854  // supposed difference from adding up just the new receipts,
2855  // (Which is probably impossible anyway) then return false.
2856  if (lActualDifference != lInboxSupposedDifference) {
2857  otErr << "OTTransaction::" << __FUNCTION__ << ": lActualDifference ("
2858  << lActualDifference
2859  << ") is not equal to lInboxSupposedDifference ("
2860  << lInboxSupposedDifference
2861  << ")\n"
2862  "FYI, Inbox balance on old receipt: " << lReceiptBalanceChange
2863  << " Inbox balance on current inbox: " << lInboxBalanceChange
2864  << "\n";
2865  return false;
2866  }
2867 
2868  // if, according to the two inboxes, they are different (in terms of how
2869  // they would impact balance),
2870  // then therefore, they must have impacted my balance. THEREFORE, my old
2871  // balance MUST be equivalent to
2872  // the current (apparently new) balance, PLUS OR MINUS THE DIFFERENCE,
2873  // ACCORDING TO THE DIFFERENCE BETWEEN THE INBOXES.
2874  // If the actual difference (according to inbox receipts) + actual account
2875  // balance (according to newest copy of account)
2876  // is not equal to the last signed balance agreement, then return false.
2877  //
2878  /*
2879  if (
2880  (bNewInboxWasBigger && (pBalanceItem->GetAmount() !=
2881  (THE_ACCOUNT.GetBalance() + lNegativeDifference))) ||
2882  (bNewInboxWasSmaller && (pBalanceItem->GetAmount() !=
2883  (THE_ACCOUNT.GetBalance() + lAbsoluteDifference)))
2884  )
2885 
2886  Inbox A (bigger):
2887  if (
2888  (TRUE && (1000 != (1020 + -20))) ||
2889  (FALSE && (1000 != (1020 + 20)))
2890  )
2891  ---
2892  Inbox B (smaller):
2893  if (
2894  (FALSE && (1000 != (980 + -20))) ||
2895  (TRUE && (1000 != (980 + 20)))
2896  )
2897  ---------------------------------------------------------------------
2898 
2899  if (pBalanceItem->GetAmount() != (THE_ACCOUNT.GetBalance() +
2900  (lActualDifference*(-1))))
2901 
2902  Inbox A (bigger):
2903  if (1000 != (1020 + -20))
2904 
2905  Inbox B (smaller):
2906  if (1000 != (980 + 20))
2907  */
2908 
2909  if (pBalanceItem->GetAmount() !=
2910  (THE_ACCOUNT.GetBalance() + (lActualDifference * (-1)))) {
2911  // Let's say ActualDifference == 10-3 (prev balance minus current
2912  // balance) == 7.
2913  // If that's the case, then 7 + THE_ACCT.Balance should equal 10 again
2914  // from the last balance statement!
2915 
2916  otErr << "OTTransaction::" << __FUNCTION__
2917  << ": lActualDifference in receipts (" << lActualDifference
2918  << ") "
2919  "plus current acct balance (" << THE_ACCOUNT.GetBalance()
2920  << ") is NOT equal to last signed balance ("
2921  << pBalanceItem->GetAmount() << ")\n";
2922  return false;
2923  }
2924 
2925  // At this point: all good!
2926  //
2927 
2928  return true;
2929 }
OTLOG_IMPORT OTLogStream otLog4
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
Definition: OTItem.cpp:1473
static EXPORT OTTransactionType * TransactionFactory(OTString strInput)
static EXPORT const char * PathSeparator()
Definition: OTLog.cpp:408
OTLOG_IMPORT OTLogStream otOut
OTLOG_IMPORT OTLogStream otLog3
const OTIdentifier & GetRealAccountID() const
EXPORT OTItem * GetItem(OTItem::itemType theType)
const OTIdentifier & GetPurportedServerID() const
EXPORT std::string QueryPlainString(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:728
#define OT_ASSERT(x)
Definition: Assert.hpp:150
static EXPORT const OTString & Receipt()
Definition: OTFolders.cpp:355
time64_t GetDateSigned() const
OTLOG_IMPORT OTLogStream otWarn
EXPORT const char * Get() const
Definition: OTString.cpp:1045
OTLOG_IMPORT OTLogStream otErr
const OTIdentifier & GetPurportedAccountID() const
bool IsAbbreviated() const
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
Definition: OTStorage.cpp:584
const OTIdentifier & GetRealServerID() const
bool opentxs::OTTransaction::VerifyBoxReceipt ( OTTransaction theFullVersion)

Definition at line 3102 of file OTTransaction.cpp.

3103 {
3104  if (!m_bIsAbbreviated || theFullVersion.IsAbbreviated()) {
3105  otErr << "OTTransaction::" << __FUNCTION__
3106  << ": Failure: This transaction "
3107  "isn't abbreviated (val: "
3108  << (m_bIsAbbreviated ? "IS" : "IS NOT")
3109  << "), or the purported full version erroneously is (val: "
3110  << (theFullVersion.IsAbbreviated() ? "IS" : "IS NOT")
3111  << "). "
3112  "Either way, you can't use it in this way, for trans num: "
3113  << GetTransactionNum() << "\n";
3114  return false;
3115  }
3116 
3117  // VERIFY THE HASH
3118  //
3119  OTIdentifier idFullVersion; // Generate a message digest of that string.
3120  theFullVersion.CalculateContractID(idFullVersion);
3121 
3122  // Abbreviated version (*this) stores a hash of the original full version.
3123  // Sooo... let's hash the purported "full version" that was passed in, and
3124  // compare it to the stored one.
3125  //
3126  if (m_Hash != idFullVersion) {
3127  otErr << "OTTransaction::" << __FUNCTION__
3128  << ": Failure: The purported 'full version' of the transaction, "
3129  "passed in for verification fails to match the stored hash "
3130  "value for trans num: " << GetTransactionNum() << "\n";
3131  return false;
3132  }
3133 
3134  // BY THIS POINT, we already know it's a definite match.
3135  // But we check a few more things, just to be safe.
3136  // Such as the TRANSACTION NUMBER...
3137  if (GetTransactionNum() != theFullVersion.GetTransactionNum()) {
3138  otErr << "OTTransaction::" << __FUNCTION__
3139  << ": Failure: The purported 'full version' of the transaction "
3140  "passed in (number " << theFullVersion.GetTransactionNum()
3141  << ") fails to match the actual transaction number: "
3142  << GetTransactionNum() << "\n";
3143  return false;
3144  }
3145 
3146  // THE "IN REFERENCE TO" NUMBER (DISPLAY VERSION)
3147  if (GetAbbrevInRefDisplay() != theFullVersion.GetReferenceNumForDisplay()) {
3148  otErr << "OTTransaction::" << __FUNCTION__
3149  << ": Failure: The purported 'full version' of the transaction "
3150  "passed, GetReferenceNumForDisplay() ("
3151  << theFullVersion.GetReferenceNumForDisplay()
3152  << ") fails to match the GetAbbrevInRefDisplay ("
3153  << GetAbbrevInRefDisplay() << ") on this.\n";
3154  return false;
3155  }
3156 
3157  return true;
3158 }
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
int64_t GetAbbrevInRefDisplay() const
bool opentxs::OTTransaction::VerifyItems ( OTPseudonym theNym)

Definition at line 3166 of file OTTransaction.cpp.

3167 {
3168  const OTIdentifier NYM_ID(theNym);
3169 
3170  if (NYM_ID != GetUserID()) {
3171  otErr << "Wrong owner passed to OTTransaction::VerifyItems\n";
3172  return false;
3173  }
3174 
3175  // I'm not checking signature on transaction itself since that is already
3176  // checked before this function is called. But I AM calling Verify Owner,
3177  // so that when Verify Owner is called in the loop below, it proves the
3178  // items
3179  // and the transaction both have the same owner: Nym.
3180 
3181  // if pointer not null, and it's a withdrawal, and it's an acknowledgement
3182  // (not a rejection or error)
3183  //
3184  for (auto& it : GetItemList()) {
3185  // loop through the ALL items that make up this transaction and check
3186  // to see if a response to deposit.
3187  OTItem* pItem = it;
3188  OT_ASSERT(nullptr != pItem);
3189 
3190  if (GetTransactionNum() != pItem->GetTransactionNum()) return false;
3191 
3192  if (NYM_ID != pItem->GetUserID()) return false;
3193 
3194  if (!pItem->VerifySignature(theNym)) // NO need to call
3195  // VerifyAccount since
3196  // VerifyContractID is
3197  // ALREADY called and now
3198  // here's
3199  // VerifySignature().
3200  return false;
3201  }
3202 
3203  return true;
3204 }
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTLOG_IMPORT OTLogStream otErr
EXPORT int64_t GetTransactionNum() const
const OTIdentifier & GetUserID() const
listOfItems & GetItemList()

Friends And Related Function Documentation

Member Data Documentation

OTASCIIArmor opentxs::OTTransaction::m_ascCancellationRequest
protected

Definition at line 880 of file OTTransaction.hpp.

bool opentxs::OTTransaction::m_bCancelled
protected

Definition at line 920 of file OTTransaction.hpp.

bool opentxs::OTTransaction::m_bIsAbbreviated
protected

Definition at line 818 of file OTTransaction.hpp.

bool opentxs::OTTransaction::m_bReplyTransSuccess
protected

Definition at line 892 of file OTTransaction.hpp.

time64_t opentxs::OTTransaction::m_DATE_SIGNED
protected

Definition at line 873 of file OTTransaction.hpp.

OTIdentifier opentxs::OTTransaction::m_Hash
protected

Definition at line 870 of file OTTransaction.hpp.

int64_t opentxs::OTTransaction::m_lAbbrevAmount
protected

Definition at line 828 of file OTTransaction.hpp.

int64_t opentxs::OTTransaction::m_lClosingTransactionNo
protected

Definition at line 879 of file OTTransaction.hpp.

int64_t opentxs::OTTransaction::m_lDisplayAmount
protected

Definition at line 847 of file OTTransaction.hpp.

int64_t opentxs::OTTransaction::m_lInRefDisplay
protected

Definition at line 853 of file OTTransaction.hpp.

listOfItems opentxs::OTTransaction::m_listItems
protected

Definition at line 877 of file OTTransaction.hpp.

int64_t opentxs::OTTransaction::m_lRequestNumber
protected

Definition at line 891 of file OTTransaction.hpp.

const OTLedger* opentxs::OTTransaction::m_pParent
protected

Definition at line 807 of file OTTransaction.hpp.

transactionType opentxs::OTTransaction::m_Type
protected

Definition at line 875 of file OTTransaction.hpp.


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