Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Basket.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * Basket.cpp
4  *
5  */
6 
7 /************************************************************
8  -----BEGIN PGP SIGNED MESSAGE-----
9  Hash: SHA1
10 
11  * OPEN TRANSACTIONS
12  *
13  * Financial Cryptography and Digital Cash
14  * Library, Protocol, API, Server, CLI, GUI
15  *
16  * -- Anonymous Numbered Accounts.
17  * -- Untraceable Digital Cash.
18  * -- Triple-Signed Receipts.
19  * -- Cheques, Vouchers, Transfers, Inboxes.
20  * -- Basket Currencies, Markets, Payment Plans.
21  * -- Signed, XML, Ricardian-style Contracts.
22  * -- Scripted smart contracts.
23  *
24  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
25  *
26  * EMAIL:
28  *
29  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
30  *
31  * KEY FINGERPRINT (PGP Key in license file):
32  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
33  *
34  * OFFICIAL PROJECT WIKI(s):
35  * https://github.com/FellowTraveler/Moneychanger
36  * https://github.com/FellowTraveler/Open-Transactions/wiki
37  *
38  * WEBSITE:
39  * http://www.OpenTransactions.org/
40  *
41  * Components and licensing:
42  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
43  * -- otlib.........A class library.......LICENSE:...LAGPLv3
44  * -- otapi.........A client API..........LICENSE:...LAGPLv3
45  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
46  * -- otserver......Server Application....LICENSE:....AGPLv3
47  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
48  *
49  * All of the above OT components were designed and written by
50  * Fellow Traveler, with the exception of Moneychanger, which
51  * was contracted out to Vicky C ([email protected]).
52  * The open-source community has since actively contributed.
53  *
54  * -----------------------------------------------------
55  *
56  * LICENSE:
57  * This program is free software: you can redistribute it
58  * and/or modify it under the terms of the GNU Affero
59  * General Public License as published by the Free Software
60  * Foundation, either version 3 of the License, or (at your
61  * option) any later version.
62  *
63  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
64  * section 7: (This paragraph applies only to the LAGPLv3
65  * components listed above.) If you modify this Program, or
66  * any covered work, by linking or combining it with other
67  * code, such other code is not for that reason alone subject
68  * to any of the requirements of the GNU Affero GPL version 3.
69  * (==> This means if you are only using the OT API, then you
70  * don't have to open-source your code--only your changes to
71  * Open-Transactions itself must be open source. Similar to
72  * LGPLv3, except it applies to software-as-a-service, not
73  * just to distributing binaries.)
74  *
75  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
76  * used by Open Transactions: This program is released under
77  * the AGPL with the additional exemption that compiling,
78  * linking, and/or using OpenSSL is allowed. The same is true
79  * for any other open source libraries included in this
80  * project: complete waiver from the AGPL is hereby granted to
81  * compile, link, and/or use them with Open-Transactions,
82  * according to their own terms, as long as the rest of the
83  * Open-Transactions terms remain respected, with regard to
84  * the Open-Transactions code itself.
85  *
86  * Lucre License:
87  * This code is also "dual-license", meaning that Ben Lau-
88  * rie's license must also be included and respected, since
89  * the code for Lucre is also included with Open Transactions.
90  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
91  * The Laurie requirements are light, but if there is any
92  * problem with his license, simply remove the Lucre code.
93  * Although there are no other blind token algorithms in Open
94  * Transactions (yet. credlib is coming), the other functions
95  * will continue to operate.
96  * See Lucre on Github: https://github.com/benlaurie/lucre
97  * -----------------------------------------------------
98  * You should have received a copy of the GNU Affero General
99  * Public License along with this program. If not, see:
100  * http://www.gnu.org/licenses/
101  *
102  * If you would like to use this software outside of the free
103  * software license, please contact FellowTraveler.
104  * (Unfortunately many will run anonymously and untraceably,
105  * so who could really stop them?)
106  *
107  * DISCLAIMER:
108  * This program is distributed in the hope that it will be
109  * useful, but WITHOUT ANY WARRANTY; without even the implied
110  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
111  * PURPOSE. See the GNU Affero General Public License for
112  * more details.
113 
114  -----BEGIN PGP SIGNATURE-----
115  Version: GnuPG v1.4.9 (Darwin)
116 
117  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
118  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
119  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
120  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
121  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
122  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
123  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
124  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
125  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
126  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
127  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
128  kamH0Y/n11lCvo1oQxM+
129  =uSzz
130  -----END PGP SIGNATURE-----
131  **************************************************************/
132 
133 #include "opentxs/core/stdafx.hpp"
134 
135 #include "Basket.hpp"
136 
138 #include "opentxs/core/OTLog.hpp"
139 
140 #include <irrxml/irrXML.hpp>
141 
142 // This is a good implementation. Dots all the i's, so to speak.
143 // client-side.
144 // The basket ONLY stores closing numbers, so this means "harvest 'em all."
145 //
146 // NOTE: The basket might be harvested in different ways, depending on context:
147 //
148 // 1. If the command-line client (OR ANY OTHER CLIENT) has a failure BEFORE
149 // sending the message,
150 // (e.g. while constructing the basket exchange request), then it should call
151 // OTAPI.Msg_HarvestTransactionNumbers
152 // and pass in the exchange basket string. That function will check to see if
153 // the input is an
154 // exchange basket, and if so, it will load it up (AS A BASKET) into Basket
155 // and call the below
156 // function to harvest the numbers.
157 //
158 // 2. If the high-level API actually SENDS the message, but the message FAILED
159 // before getting a chance
160 // to process the exchangeBasket transaction, then the high-level API will
161 // pass the failed message
162 // to OTAPI.Msg_HarvestTransactionNumbers, which will load it up (AS A
163 // MESSAGE) and that will then
164 // call pMsg->HarvestTransactionNumbers, which then loads up the transaction
165 // itself in order to call
166 // pTransaction->HarvestClosingNumbers. That function, if the transaction is
167 // indeed an exchangeBasket,
168 // will then call the below function Basket::HarvestClosingNumbers.
169 //
170 // 3. If the high-level API sends the message, and it SUCCEEDS, but the
171 // exchangeBasket transaction inside
172 // it has FAILED, then OTClient will harvest the transaction numbers when it
173 // receives the server reply
174 // containing the failed transaction, by calling the below function,
175 // Basket::HarvestClosingNumbers.
176 //
177 // 4. If the basket exchange request is constructed successfully, and then the
178 // message processes at the server
179 // successfully, and the transaction inside that message also processed
180 // successfully, then no harvesting will
181 // be performed at all (obviously.)
182 //
183 
184 namespace opentxs
185 {
186 
188  const OTIdentifier& theServerID, bool bSave)
189 {
190  const OTString strServerID(theServerID);
191  bool bNeedToSave = false;
192 
193  // The SUB-CURRENCIES first...
194  //
195  const uint32_t nCount = static_cast<uint32_t>(Count());
196 
197  for (uint32_t i = 0; i < nCount; i++) {
198  BasketItem* pRequestItem = At(i);
199  OT_ASSERT(nullptr != pRequestItem);
200 
201  const int64_t lClosingTransNo = pRequestItem->lClosingTransactionNo;
202 
203  // This function will only "add it back" if it was really there in the
204  // first place.
205  // (Verifies it is on issued list first, before adding to available
206  // list.)
207  //
208  const bool bClawedBack = theNym.ClawbackTransactionNumber(
209  theServerID, lClosingTransNo, false); // bSave=false
210 
211  if (bClawedBack) bNeedToSave = true;
212  }
213  // Then the BASKET currency itself...
214  //
215  const int64_t lClosingTransNo = GetClosingNum();
216 
217  // This function will only "add it back" if it was really there in the first
218  // place.
219  // (Verifies it is on issued list first, before adding to available list.)
220  //
221  const bool bClawedBack =
222  theNym.ClawbackTransactionNumber(theServerID, lClosingTransNo, false);
223 
224  if (bClawedBack) bNeedToSave = true;
225 
226  // Until I put this down here, there were subtle cases where the Nym
227  // wouldn't get saved.
228  // Therefore another vote for my "dirty instances" theory.
229  //
230  if (bSave && bNeedToSave) {
231  OTPseudonym* pSignerNym = &theNym; // probably unnecessary.
232  theNym.SaveSignedNymfile(*pSignerNym);
233  }
234 }
235 
236 // For generating a user request to EXCHANGE in/out of a basket.
237 // Assumes that SetTransferMultiple has already been called.
238 void Basket::AddRequestSubContract(const OTIdentifier& SUB_CONTRACT_ID,
239  const OTIdentifier& SUB_ACCOUNT_ID,
240  const int64_t& lClosingTransactionNo)
241 {
242  BasketItem* pItem = new BasketItem;
243 
244  OT_ASSERT_MSG(nullptr != pItem,
245  "Error allocating memory in Basket::AddRequestSubContract\n");
246 
247  // Minimum transfer amount is not set on a request. The server already knows
248  // its value.
249  // Also there is no multiple on the item, only on the basket as a whole.
250  // ALL items are multiplied by the same multiple. Even the basket amount
251  // itself is also.
252  m_dequeItems.push_back(pItem);
253 
254  pItem->SUB_CONTRACT_ID = SUB_CONTRACT_ID;
255  pItem->SUB_ACCOUNT_ID = SUB_ACCOUNT_ID;
256 
257  // When the basketReceipts are accepted in all the asset accounts,
258  // each one will have a transaction number, lClosingTransactionNo,
259  // which the user will finally clear from his record by accepting
260  // from his inbox.
261  pItem->lClosingTransactionNo = lClosingTransactionNo;
262 }
263 
264 // For generating a real basket
265 void Basket::AddSubContract(const OTIdentifier& SUB_CONTRACT_ID,
266  int64_t lMinimumTransferAmount)
267 {
268  BasketItem* pItem = new BasketItem;
269 
270  OT_ASSERT_MSG(nullptr != pItem,
271  "Error allocating memory in Basket::AddSubContract\n");
272 
273  pItem->SUB_CONTRACT_ID = SUB_CONTRACT_ID;
274  pItem->lMinimumTransferAmount = lMinimumTransferAmount;
275 
276  m_dequeItems.push_back(pItem);
277 }
278 
279 // The closing transaction number is the one that gets closed when the
280 // basketReceipt
281 // is accepted for the exchange that occured, specific to the basket item at
282 // nIndex.
283 // (Each asset account gets its own basketReceipt when an exchange happens.)
284 //
285 int64_t Basket::GetClosingTransactionNoAt(uint32_t nIndex)
286 {
287  OT_ASSERT_MSG((nIndex < m_dequeItems.size()),
288  "Basket::GetClosingTransactionNoAt: index out of bounds.");
289 
290  BasketItem* pItem = m_dequeItems.at(nIndex);
291 
292  OT_ASSERT_MSG(nullptr != pItem, "Basket::GetClosingTransactionNoAt: basket "
293  "item was nullptr at that index.");
294 
295  return pItem->lClosingTransactionNo;
296 }
297 
298 BasketItem* Basket::At(uint32_t nIndex)
299 {
300  if (nIndex < m_dequeItems.size()) return m_dequeItems.at(nIndex);
301 
302  return nullptr;
303 }
304 
305 int32_t Basket::Count() const
306 {
307  return static_cast<int32_t>(m_dequeItems.size());
308 }
309 
310 // return -1 if error, 0 if nothing, and 1 if the node was processed.
312 {
313  const OTString strNodeName(xml->getNodeName());
314 
315  if (strNodeName.Compare("currencyBasket")) {
316  OTString strSubCount, strMinTrans;
317  strSubCount = xml->getAttributeValue("contractCount");
318  strMinTrans = xml->getAttributeValue("minimumTransfer");
319 
320  m_nSubCount = atoi(strSubCount.Get());
321  m_lMinimumTransfer = atol(strMinTrans.Get());
322 
323  otWarn << "Loading currency basket...\n";
324 
325  return 1;
326  }
327  else if (strNodeName.Compare("requestExchange")) {
328  OTString strTransferMultiple, strRequestAccountID, strDirection,
329  strTemp;
330 
331  strTransferMultiple = xml->getAttributeValue("transferMultiple");
332  strRequestAccountID = xml->getAttributeValue("transferAccountID");
333  strDirection = xml->getAttributeValue("direction");
334  strTemp = xml->getAttributeValue("closingTransactionNo");
335 
336  if (strTransferMultiple.Exists())
337  m_nTransferMultiple = atoi(strTransferMultiple.Get());
338  if (strRequestAccountID.Exists())
339  m_RequestAccountID.SetString(strRequestAccountID);
340  if (strDirection.Exists()) m_bExchangingIn = strDirection.Compare("in");
341  if (strTemp.Exists()) SetClosingNum(atol(strTemp.Get()));
342 
343  otInfo << "Basket Transfer multiple is " << m_nTransferMultiple
344  << ". Direction is " << strDirection << ". Closing number is "
345  << m_lClosingTransactionNo << ". Target account is:\n"
346  << strRequestAccountID << "\n";
347 
348  return 1;
349  }
350  else if (strNodeName.Compare("basketItem")) {
351  BasketItem* pItem = new BasketItem;
352 
353  OT_ASSERT_MSG(nullptr != pItem,
354  "Error allocating memory in Basket::ProcessXMLNode\n");
355 
356  OTString strTemp;
357 
358  strTemp = xml->getAttributeValue("minimumTransfer");
359  if (strTemp.Exists())
360  pItem->lMinimumTransferAmount = atol(strTemp.Get());
361 
362  strTemp = xml->getAttributeValue("closingTransactionNo");
363  if (strTemp.Exists())
364  pItem->lClosingTransactionNo = atol(strTemp.Get());
365 
366  OTString strSubAccountID(xml->getAttributeValue("accountID")),
367  strContractID(xml->getAttributeValue("assetID"));
368  pItem->SUB_ACCOUNT_ID.SetString(strSubAccountID);
369  pItem->SUB_CONTRACT_ID.SetString(strContractID);
370 
371  m_dequeItems.push_back(pItem);
372 
373  otInfo << "Loaded basket item.\n";
374 
375  return 1;
376  }
377 
378  return 0;
379 }
380 
381 // Before transmission or serialization, this is where the basket updates its
382 // contents
384 {
385  GenerateContents(m_xmlUnsigned, m_bHideAccountID);
386 }
387 
388 void Basket::GenerateContents(OTStringXML& xmlUnsigned,
389  bool bHideAccountID) const
390 {
391  // I release this because I'm about to repopulate it.
392  xmlUnsigned.Release();
393 
394  xmlUnsigned.Concatenate("<currencyBasket contractCount=\"%d\"\n"
395  " minimumTransfer=\"%lld\" >\n\n",
397 
398  // Only uesd in Request Basket (requesting an exchange in/out.)
399  // (Versus a basket object used for ISSUING a basket currency, this is
400  // EXCHANGING instead.)
401  //
402  if (IsExchanging()) {
403  OTString strRequestAcctID(m_RequestAccountID);
404  xmlUnsigned.Concatenate("<requestExchange "
405  "transferMultiple=\"%d\"\n "
406  "transferAccountID=\"%s\"\n "
407  "closingTransactionNo=\"%lld\"\n "
408  "direction=\"%s\" />\n\n",
409  m_nTransferMultiple, strRequestAcctID.Get(),
411  m_bExchangingIn ? "in" : "out");
412  }
413 
414  for (int32_t i = 0; i < Count(); i++) {
415  BasketItem* pItem = m_dequeItems[i];
416 
417  OT_ASSERT_MSG(nullptr != pItem,
418  "Error allocating memory in Basket::UpdateContents\n");
419 
420  OTString strAcctID(pItem->SUB_ACCOUNT_ID),
421  strContractID(pItem->SUB_CONTRACT_ID);
422 
423  if (IsExchanging())
424  xmlUnsigned.Concatenate(
425  "<basketItem minimumTransfer=\"%lld\"\n"
426  " closingTransactionNo=\"%lld\"\n"
427  " accountID=\"%s\"\n"
428  " assetID=\"%s\" />\n\n",
429  pItem->lMinimumTransferAmount, pItem->lClosingTransactionNo,
430  bHideAccountID ? "" : strAcctID.Get(), strContractID.Get());
431  else
432  xmlUnsigned.Concatenate("<basketItem minimumTransfer=\"%lld\"\n"
433  " accountID=\"%s\"\n"
434  " assetID=\"%s\" />\n\n",
435  pItem->lMinimumTransferAmount,
436  bHideAccountID ? "" : strAcctID.Get(),
437  strContractID.Get());
438  }
439 
440  xmlUnsigned.Concatenate("</currencyBasket>\n");
441 }
442 
443 // Most contracts calculate their ID by hashing the Raw File (signatures and
444 // all).
445 // The Basket only hashes the unsigned contents, and only with the account IDs
446 // removed.
447 // This way, the basket will produce a consistent ID across multiple different
448 // servers.
450 {
451  // Produce a version of the file without account IDs (which are different
452  // from server to server.)
453  // do this on a copy since we don't want to modify this basket
454  OTStringXML xmlUnsigned;
455  GenerateContents(xmlUnsigned, true);
456 
457  newID.CalculateDigest(xmlUnsigned);
458 }
459 
460 Basket::Basket(int32_t nCount, int64_t lMinimumTransferAmount)
461  : OTContract()
462  , m_nSubCount(nCount)
463  , m_lMinimumTransfer(lMinimumTransferAmount)
464  , m_nTransferMultiple(0)
465  , m_bHideAccountID(false)
466  , m_bExchangingIn(false)
467  , m_lClosingTransactionNo(0)
468 {
469 }
470 
472  : OTContract()
473  , m_nSubCount(0)
474  , m_lMinimumTransfer(0)
475  , m_nTransferMultiple(0)
476  , m_bHideAccountID(false)
477  , m_bExchangingIn(false)
478  , m_lClosingTransactionNo(0)
479 {
480 }
481 
483 {
484  Release_Basket();
485 }
486 
488 {
490 
491  while (!m_dequeItems.empty()) {
492  BasketItem* pItem = m_dequeItems.front();
493  m_dequeItems.pop_front();
494  delete pItem;
495  }
496 
497  m_nSubCount = 0;
498  m_lMinimumTransfer = 0;
500  m_bHideAccountID = false;
501  m_bExchangingIn = false;
503 }
504 
506 {
507  Release_Basket();
508 
510 }
511 
512 bool Basket::SaveContractWallet(std::ofstream&) const
513 {
514  return true;
515 }
516 
517 } // namespace opentxs
int64_t m_lClosingTransactionNo
Definition: Basket.hpp:206
EXPORT void AddRequestSubContract(const OTIdentifier &SUB_CONTRACT_ID, const OTIdentifier &SUB_ACCOUNT_ID, const int64_t &lClosingTransactionNo)
Definition: Basket.cpp:238
EXPORT bool CalculateDigest(const OTData &dataInput)
EXPORT bool ClawbackTransactionNumber(const OTIdentifier &theServerID, const int64_t &lTransClawback, bool bSave=false, OTPseudonym *pSIGNER_NYM=nullptr)
bool m_bHideAccountID
Definition: Basket.hpp:200
int64_t lClosingTransactionNo
Definition: BasketItem.hpp:163
bool IsExchanging() const
Definition: Basket.hpp:235
EXPORT void Concatenate(const char *arg,...)
Definition: OTString.cpp:1334
virtual void Release()
Definition: Basket.cpp:505
bool m_bExchangingIn
Definition: Basket.hpp:204
int64_t GetClosingNum() const
Definition: Basket.hpp:254
EXPORT bool Exists() const
Definition: OTString.cpp:1035
EXPORT void SetString(const char *szString)
int64_t m_lMinimumTransfer
Definition: Basket.hpp:194
virtual void UpdateContents()
Definition: Basket.cpp:383
int32_t m_nSubCount
Definition: Basket.hpp:193
EXPORT bool Compare(const char *compare) const
Definition: OTString.cpp:1102
virtual EXPORT void CalculateContractID(OTIdentifier &newID) const
Definition: Basket.cpp:449
virtual int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
Definition: Basket.cpp:311
#define OT_ASSERT(x)
Definition: Assert.hpp:150
virtual bool SaveContractWallet(std::ofstream &ofs) const
Definition: Basket.cpp:512
dequeOfBasketItems m_dequeItems
Definition: Basket.hpp:199
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
virtual EXPORT ~Basket()
Definition: Basket.cpp:482
EXPORT BasketItem * At(uint32_t nIndex)
Definition: Basket.cpp:298
OTLOG_IMPORT OTLogStream otInfo
OTStringXML m_xmlUnsigned
Definition: OTContract.hpp:174
OTLOG_IMPORT OTLogStream otWarn
int32_t m_nTransferMultiple
Definition: Basket.hpp:195
EXPORT void HarvestClosingNumbers(OTPseudonym &theNym, const OTIdentifier &theServerID, bool bSave=true)
Definition: Basket.cpp:187
EXPORT const char * Get() const
Definition: OTString.cpp:1045
OTIdentifier SUB_ACCOUNT_ID
Definition: BasketItem.hpp:151
virtual EXPORT void Release()
Definition: OTContract.cpp:277
OTIdentifier SUB_CONTRACT_ID
Definition: BasketItem.hpp:150
EXPORT Basket()
Definition: Basket.cpp:471
void SetClosingNum(const int64_t &lClosingNum)
Definition: Basket.hpp:258
virtual EXPORT void Release()
Definition: OTData.cpp:257
int64_t GetClosingTransactionNoAt(uint32_t nIndex)
Definition: Basket.cpp:285
void Release_Basket()
Definition: Basket.cpp:487
virtual EXPORT void Release()
Definition: OTString.cpp:765
EXPORT void AddSubContract(const OTIdentifier &SUB_CONTRACT_ID, int64_t lMinimumTransferAmount)
Definition: Basket.cpp:265
OTIdentifier m_RequestAccountID
Definition: Basket.hpp:197
EXPORT bool SaveSignedNymfile(OTPseudonym &SIGNER_NYM)
EXPORT int32_t Count() const
Definition: Basket.cpp:305
int64_t lMinimumTransferAmount
Definition: BasketItem.hpp:153