1464 otErr <<
"OTTransaction::VerifyBalanceReceipt: Error: This is an "
1465 "abbreviated receipt. (Load the box receipt first.)\n";
1469 OTIdentifier USER_ID(THE_NYM), SERVER_USER_ID(SERVER_NYM);
1483 OTString strFilename;
1484 strFilename.Format(
"%s.success", strReceiptID.Get());
1487 const char* szFolder2name = strServerID.Get();
1488 const char* szFilename =
1491 if (!
OTDB::Exists(szFolder1name, szFolder2name, szFilename)) {
1492 otWarn <<
"Receipt file doesn't exist in "
1493 "OTTransaction::VerifyBalanceReceipt:\n " << szFilename
1498 std::string strFileContents(
1502 if (strFileContents.length() < 2) {
1503 otErr <<
"OTTransaction::VerifyBalanceReceipt: Error reading "
1504 "transaction statement:\n " << szFolder1name
1510 OTString strTransaction(strFileContents.c_str());
1513 std::unique_ptr<OTTransactionType> pContents(
1516 if (
nullptr == pContents) {
1517 otErr <<
"OTTransaction::VerifyBalanceReceipt: Unable to load "
1518 "transaction statement:\n " << szFolder1name
1523 else if (!pContents->VerifySignature(SERVER_NYM)) {
1524 otErr <<
"OTTransaction::VerifyBalanceReceipt: Unable to verify "
1525 "signature on transaction statement:\n " << szFolder1name
1535 if (
nullptr == pTrans) {
1536 otErr <<
"OTTransaction::VerifyBalanceReceipt: Was expecting an "
1537 "OTTransaction to be stored in the transaction statement "
1561 OTItem* pItemWithIssuedList =
1566 OTItem* pTransactionItem =
nullptr;
1574 OTItem* pResponseTransactionItem =
1577 if (
nullptr == pResponseTransactionItem) {
1579 otOut <<
"No atTransactionStatement item found on receipt "
1584 pResponseTransactionItem->GetStatus()) {
1586 otOut <<
"Error: atTransactionStatement found on receipt, but not "
1587 "a successful one.\n";
1590 else if (!pResponseTransactionItem->VerifySignature(SERVER_NYM)) {
1591 otOut <<
"Unable to verify signature on atTransactionStatement "
1592 "item in OTTransaction::VerifyBalanceReceipt.\n";
1599 OTString strBalanceItem;
1600 pResponseTransactionItem->GetReferenceString(strBalanceItem);
1602 if (!strBalanceItem.Exists()) {
1604 otOut <<
"No transactionStatement item found as 'in ref to' string "
1605 "on a receipt containing atTransactionStatement item.\n";
1611 pResponseTransactionItem->GetReferenceToNum());
1613 if (
nullptr == pTransactionItem) {
1614 otOut <<
"Unable to load transactionStatement item from string "
1615 "(from a receipt containing an atTransactionStatement "
1619 else if (pTransactionItem->GetType() !=
1621 otOut <<
"Wrong type on pTransactionItem (expected "
1622 "OTItem::transactionStatement)\n";
1625 else if (!pTransactionItem->VerifySignature(THE_NYM)) {
1626 otOut <<
"Unable to verify signature on transactionStatement item "
1627 "in OTTransaction::VerifyBalanceReceipt.\n";
1631 pItemWithIssuedList = pTransactionItem;
1638 if (!THE_ACCOUNT.LoadContract() || !THE_ACCOUNT.VerifyAccount(THE_NYM)) {
1640 otOut <<
"Failed loading or verifying account for THE_NYM in "
1641 "OTTransaction::VerifyBalanceReceipt.\n";
1644 else if (THE_ACCOUNT.GetPurportedServerID() !=
1650 otOut <<
"Account, inbox or outbox server ID fails to match receipt "
1654 else if (THE_ACCOUNT.GetPurportedAccountID() !=
1659 otOut <<
"Account ID fails to match receipt account ID.\n";
1665 std::unique_ptr<OTLedger> pInbox(THE_ACCOUNT.LoadInbox(
1667 std::unique_ptr<OTLedger> pOutbox(THE_ACCOUNT.LoadOutbox(
1670 if ((
nullptr == pInbox) || (
nullptr == pOutbox)) {
1672 otOut <<
"Inbox or outbox was nullptr after THE_ACCOUNT.Load in "
1673 "OTTransaction::VerifyBalanceReceipt.\n";
1681 if (
nullptr == pResponseBalanceItem) {
1683 otOut <<
"No atBalanceStatement item found on receipt (strange.)\n";
1688 otOut <<
"Error: atBalanceStatement found on receipt, but not a "
1689 "successful one.\n";
1692 else if (!pResponseBalanceItem->VerifySignature(SERVER_NYM)) {
1693 otOut <<
"Unable to verify signature on atBalanceStatement item in "
1694 "OTTransaction::VerifyBalanceReceipt.\n";
1700 OTItem* pBalanceItem =
nullptr;
1702 OTString strBalanceItem;
1703 pResponseBalanceItem->GetReferenceString(strBalanceItem);
1705 if (!strBalanceItem.Exists()) {
1707 otOut <<
"No balanceStatement item found as 'in ref to' string on a "
1708 "receipt containing atBalanceStatement item.\n";
1714 pResponseBalanceItem->GetReferenceToNum());
1716 if (
nullptr == pBalanceItem) {
1717 otOut <<
"Unable to load balanceStatement item from string (from a "
1718 "receipt containing an atBalanceStatement item.)\n";
1722 otOut <<
"Wrong type on pBalanceItem (expected "
1723 "OTItem::balanceStatement)\n";
1726 else if (!pBalanceItem->VerifySignature(THE_NYM)) {
1727 otOut <<
"Unable to verify signature on balanceStatement item in "
1728 "OTTransaction::VerifyBalanceReceipt.\n";
1734 OTPseudonym theMessageNym;
1735 OTString strMessageNym;
1739 if ((
nullptr != pTransactionItem) &&
1744 pItemWithIssuedList =
1748 pItemWithIssuedList =
1752 pItemWithIssuedList->GetAttachment(
1755 if (!strMessageNym.Exists() ||
1756 !theMessageNym.LoadFromString(strMessageNym)) {
1757 otOut <<
"Unable to load message nym in "
1758 "OTTransaction::VerifyBalanceReceipt.\n";
1827 if (!THE_NYM.VerifyTransactionStatementNumbersOnNym(
1833 otOut <<
"Unable to verify issued numbers on last signed receipt with "
1834 "numbers on THE_NYM in OTTransaction::VerifyBalanceReceipt.\n";
1841 int32_t nInboxItemCount = 0, nOutboxItemCount = 0;
1846 const char* szInbox =
"Inbox";
1847 const char* szOutbox =
"Outbox";
1848 const char* pszLedgerType =
nullptr;
1849 int64_t lReceiptBalanceChange =
1855 otWarn <<
"Number of inbox/outbox items on the balance statement: "
1856 << pBalanceItem->GetItemCount() <<
"\n";
1867 for (int32_t i = 0; i < pBalanceItem->GetItemCount(); i++) {
1870 int64_t lReceiptAmountMultiplier = 1;
1872 OTItem* pSubItem = pBalanceItem->GetItem(i);
1876 OTLedger* pLedger =
nullptr;
1878 switch (pSubItem->GetType()) {
1887 lReceiptBalanceChange += pSubItem->GetAmount();
1902 pLedger = pInbox.get();
1903 pszLedgerType = szInbox;
1911 OTString strItemType;
1912 pSubItem->GetTypeString(strItemType);
1914 <<
"OTTransaction::VerifyBalanceReceipt: Ignoring "
1917 "in balance statement while verifying it against inbox.\n";
1922 switch (pSubItem->GetType()) {
1925 if (pSubItem->GetAmount() < 0)
1927 lReceiptAmountMultiplier =
1935 pLedger = pOutbox.get();
1936 pszLedgerType = szOutbox;
1939 lReceiptAmountMultiplier =
1942 pLedger = pInbox.get();
1943 pszLedgerType = szInbox;
1961 lReceiptAmountMultiplier = 1;
1970 int64_t lTempTransactionNum = 0;
1971 int64_t lTempReferenceToNum = 0;
1972 int64_t lTempNumberOfOrigin = 0;
1981 if ((pOutbox.get() ==
1986 (pSubItem->GetTransactionNum() ==
1991 (pResponseBalanceItem->GetNewOutboxTransNum() >
1994 lTempTransactionNum = pResponseBalanceItem->GetNewOutboxTransNum();
1995 pTransaction = pLedger->GetTransaction(lTempTransactionNum);
1997 otLog3 <<
"OTTransaction::VerifyBalanceReceipt: (This iteration, "
1998 "I'm handling an item listed as '1' in the outbox.)\n";
2006 lTempTransactionNum = pSubItem->GetTransactionNum();
2007 pTransaction = pLedger->GetTransaction(lTempTransactionNum);
2010 if (
nullptr != pTransaction) {
2011 lTempReferenceToNum = pTransaction->GetReferenceToNum();
2012 lTempNumberOfOrigin = pTransaction->GetRawNumberOfOrigin();
2015 bool bSwitchedBoxes =
false;
2038 if ((
nullptr == pTransaction) && (pOutbox.get() == pLedger)) {
2039 otLog4 <<
"OTTransaction::" << __FUNCTION__
2040 <<
": Outbox pending found as inbox transferReceipt. "
2049 pInbox->GetTransferReceipt(pSubItem->GetNumberOfOrigin());
2051 if (
nullptr != pTransaction) {
2052 lTempTransactionNum = pTransaction->GetTransactionNum();
2053 lTempNumberOfOrigin = pTransaction->GetRawNumberOfOrigin();
2100 lTempReferenceToNum = pSubItem->GetReferenceToNum();
2102 lReceiptAmountMultiplier = 1;
2111 pLedger = pInbox.get();
2112 pszLedgerType = szInbox;
2140 if (
nullptr == pTransaction) {
2141 otOut <<
"OTTransaction::" << __FUNCTION__ <<
": Expected "
2142 << pszLedgerType <<
" transaction (" << lTempTransactionNum
2143 <<
") not found. (Amount " << pSubItem->GetAmount() <<
".)\n";
2149 if (pSubItem->GetReferenceToNum() != lTempReferenceToNum) {
2150 otOut <<
"OTTransaction::" << __FUNCTION__ <<
": " << pszLedgerType
2151 <<
" transaction (" << lTempTransactionNum
2152 <<
") mismatch Reference Num: "
2153 << pSubItem->GetReferenceToNum() <<
", expected "
2154 << lTempReferenceToNum <<
"\n";
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";
2167 int64_t lTransactionAmount = pTransaction->GetReceiptAmount();
2168 lTransactionAmount *= lReceiptAmountMultiplier;
2170 if (pSubItem->GetAmount() != lTransactionAmount) {
2171 otOut <<
"OTTransaction::" << __FUNCTION__ <<
": " << pszLedgerType
2172 <<
" transaction (" << lTempTransactionNum
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";
2184 (((bSwitchedBoxes ==
true) &&
2186 ((pLedger == pOutbox.get()) &&
2188 ((pLedger == pInbox.get()) &&
2191 otOut <<
"OTTransaction::" << __FUNCTION__ <<
": " << pszLedgerType
2192 <<
" transaction (" << lTempTransactionNum
2193 <<
") wrong type. (pending block)\n";
2199 otOut <<
"OTTransaction::" << __FUNCTION__ <<
": " << pszLedgerType
2200 <<
" transaction (" << lTempTransactionNum
2201 <<
") wrong type. (chequeReceipt block)\n";
2207 otOut <<
"OTTransaction::" << __FUNCTION__ <<
": " << pszLedgerType
2208 <<
" transaction (" << lTempTransactionNum
2209 <<
") wrong type. (voucherReceipt block)\n";
2215 otOut <<
"OTTransaction::" << __FUNCTION__ <<
": " << pszLedgerType
2216 <<
" transaction (" << lTempTransactionNum
2217 <<
") wrong type. (marketReceipt block)\n";
2223 otOut <<
"OTTransaction::" << __FUNCTION__ <<
": " << pszLedgerType
2224 <<
" transaction (" << lTempTransactionNum
2225 <<
") wrong type. (paymentReceipt block)\n";
2231 otOut <<
"OTTransaction::" << __FUNCTION__ <<
": " << pszLedgerType
2232 <<
" transaction (" << lTempTransactionNum
2233 <<
") wrong type. (transferReceipt block)\n";
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";
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";
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()
2278 "--- nInboxItemCount: " << nInboxItemCount
2279 <<
" --- nOutboxItemCount: " << nOutboxItemCount <<
"\n\n";
2290 int64_t lInboxBalanceChange = 0;
2293 int64_t lInboxSupposedDifference = 0;
2297 for (int32_t i = 0; i < pInbox->GetTransactionCount(); i++) {
2298 OTTransaction* pTransaction = pInbox->GetTransactionByIndex(i);
2302 switch (pTransaction->GetType()) {
2308 lInboxBalanceChange +=
2309 pTransaction->GetReceiptAmount();
2330 otLog4 <<
"OTTransaction::" << __FUNCTION__ <<
": Ignoring "
2331 << pTransaction->GetTypeString()
2332 <<
" item in inbox while verifying it against balance "
2346 OTItem* pSubItem = pBalanceItem->GetItemByTransactionNum(
2347 pTransaction->GetTransactionNum());
2356 if (
nullptr == pSubItem) {
2357 OTItem* pFinalReceiptItem =
nullptr;
2358 switch (pTransaction->GetType()) {
2387 pBalanceItem->GetFinalReceiptItemByReferenceNum(
2388 pTransaction->GetReferenceToNum());
2392 if (
nullptr != pFinalReceiptItem) {
2393 otOut <<
"OTTransaction::" << __FUNCTION__
2394 <<
": Malicious server? A new cronReceipt has "
2396 "even though its corresponding \nfinalReceipt was "
2397 "already present in the LAST SIGNED RECEIPT. "
2399 << pTransaction->GetReferenceToNum() <<
"\n";
2410 lInboxSupposedDifference +=
2411 pTransaction->GetReceiptAmount();
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";
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";
2470 if (pSubItem->GetAmount() != (pTransaction->GetReceiptAmount())) {
2471 otOut <<
"OTTransaction::" << __FUNCTION__
2472 <<
": Inbox transaction ("
2473 << pSubItem->GetTransactionNum()
2475 "amounts don't match: " << pSubItem->GetAmount()
2476 <<
", expected " << pTransaction->GetReceiptAmount()
2477 <<
". (pBalanceItem->GetAmount() == "
2478 << pBalanceItem->GetAmount() <<
".)\n";
2484 otOut <<
"OTTransaction::" << __FUNCTION__
2485 <<
": Inbox transaction ("
2486 << pSubItem->GetTransactionNum()
2487 <<
") wrong type. (pending block)\n";
2493 otOut <<
"OTTransaction::" << __FUNCTION__
2494 <<
": Inbox transaction ("
2495 << pSubItem->GetTransactionNum()
2497 "(chequeReceipt block)\n";
2503 otOut <<
"OTTransaction:" << __FUNCTION__
2504 <<
": Inbox transaction ("
2505 << pSubItem->GetTransactionNum()
2507 "(voucherReceipt block)\n";
2513 otOut <<
"OTTransaction::" << __FUNCTION__
2514 <<
": Inbox transaction ("
2515 << pSubItem->GetTransactionNum()
2517 "(marketReceipt block)\n";
2523 otOut <<
"OTTransaction::" << __FUNCTION__
2524 <<
": Inbox transaction ("
2525 << pSubItem->GetTransactionNum()
2527 "(paymentReceipt block)\n";
2533 otOut <<
"OTTransaction::" << __FUNCTION__
2534 <<
": Inbox transaction ("
2535 << pSubItem->GetTransactionNum()
2537 "(transferReceipt block)\n";
2543 (pSubItem->GetClosingNum() !=
2544 pTransaction->GetClosingNum()))) {
2545 otOut <<
"OTTransaction::" << __FUNCTION__
2546 <<
": Inbox transaction ("
2547 << pSubItem->GetTransactionNum()
2549 "or mismatched closing num. (basketReceipt block)\n";
2555 (pSubItem->GetClosingNum() !=
2556 pTransaction->GetClosingNum()))) {
2557 otOut <<
"OTTransaction::" << __FUNCTION__
2558 <<
": Inbox transaction ("
2559 << pSubItem->GetTransactionNum()
2561 "or mismatched closing num. (finalReceipt block)\n";
2573 int64_t lIssuedNum = 0;
2578 switch (pTransaction->GetType()) {
2586 lIssuedNum = pTransaction->GetNumberOfOrigin();
2608 pFinalReceiptTransaction =
2609 pInbox->GetFinalReceipt(pTransaction->GetReferenceToNum());
2611 if (
nullptr != pFinalReceiptTransaction)
2612 lIssuedNum = pFinalReceiptTransaction->GetClosingNum();
2614 lIssuedNum = pTransaction->GetReferenceToNum();
2646 lIssuedNum = pTransaction->GetClosingNum();
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";
2756 const int64_t lAbsoluteDifference =
2757 std::abs(lInboxBalanceChange - lReceiptBalanceChange);
2758 const int64_t lNegativeDifference = (lAbsoluteDifference * (-1));
2762 const bool bNewInboxWasBigger =
2763 ((lInboxBalanceChange > lReceiptBalanceChange) ?
true :
false);
2764 const bool bNewInboxWasSmaller =
2765 ((lInboxBalanceChange < lReceiptBalanceChange) ?
true :
false);
2767 int64_t lActualDifference;
2769 if (bNewInboxWasBigger)
2770 lActualDifference = lAbsoluteDifference;
2771 else if (bNewInboxWasSmaller)
2772 lActualDifference = lNegativeDifference;
2774 lActualDifference = 0;
2856 if (lActualDifference != lInboxSupposedDifference) {
2857 otErr <<
"OTTransaction::" << __FUNCTION__ <<
": lActualDifference ("
2858 << lActualDifference
2859 <<
") is not equal to lInboxSupposedDifference ("
2860 << lInboxSupposedDifference
2862 "FYI, Inbox balance on old receipt: " << lReceiptBalanceChange
2863 <<
" Inbox balance on current inbox: " << lInboxBalanceChange
2909 if (pBalanceItem->GetAmount() !=
2910 (THE_ACCOUNT.GetBalance() + (lActualDifference * (-1)))) {
2916 otErr <<
"OTTransaction::" << __FUNCTION__
2917 <<
": lActualDifference in receipts (" << lActualDifference
2919 "plus current acct balance (" << THE_ACCOUNT.GetBalance()
2920 <<
") is NOT equal to last signed balance ("
2921 << pBalanceItem->GetAmount() <<
")\n";
OTLOG_IMPORT OTLogStream otLog4
static EXPORT OTItem * CreateItemFromString(const OTString &strItem, const OTIdentifier &theServerID, int64_t lTransactionNumber)
static EXPORT OTTransactionType * TransactionFactory(OTString strInput)
static EXPORT const char * PathSeparator()
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="")
static EXPORT const OTString & Receipt()
time64_t GetDateSigned() const
OTLOG_IMPORT OTLogStream otWarn
EXPORT const char * Get() const
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="")
const OTIdentifier & GetRealServerID() const