aboutsummaryrefslogtreecommitdiff
path: root/market.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'market.cpp')
-rw-r--r--market.cpp264
1 files changed, 264 insertions, 0 deletions
diff --git a/market.cpp b/market.cpp
new file mode 100644
index 0000000000..22b5365fa4
--- /dev/null
+++ b/market.cpp
@@ -0,0 +1,264 @@
+// Copyright (c) 2009 Satoshi Nakamoto
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+
+#include "headers.h"
+
+
+
+
+
+
+
+
+
+
+//
+// Global state variables
+//
+
+//// later figure out how these are persisted
+map<uint256, CProduct> mapMyProducts;
+
+
+
+
+map<uint256, CProduct> mapProducts;
+CCriticalSection cs_mapProducts;
+
+bool AdvertInsert(const CProduct& product)
+{
+ uint256 hash = product.GetHash();
+ bool fNew = false;
+ bool fUpdated = false;
+
+ CRITICAL_BLOCK(cs_mapProducts)
+ {
+ // Insert or find existing product
+ pair<map<uint256, CProduct>::iterator, bool> item = mapProducts.insert(make_pair(hash, product));
+ CProduct* pproduct = &(*(item.first)).second;
+ fNew = item.second;
+
+ // Update if newer
+ if (product.nSequence > pproduct->nSequence)
+ {
+ *pproduct = product;
+ fUpdated = true;
+ }
+ }
+
+ //if (fNew)
+ // NotifyProductAdded(hash);
+ //else if (fUpdated)
+ // NotifyProductUpdated(hash);
+
+ return (fNew || fUpdated);
+}
+
+void AdvertErase(const CProduct& product)
+{
+ uint256 hash = product.GetHash();
+ CRITICAL_BLOCK(cs_mapProducts)
+ mapProducts.erase(hash);
+ //NotifyProductDeleted(hash);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+template<typename T>
+unsigned int Union(T& v1, T& v2)
+{
+ // v1 = v1 union v2
+ // v1 and v2 must be sorted
+ // returns the number of elements added to v1
+
+ ///// need to check that this is equivalent, then delete this comment
+ //vector<unsigned short> vUnion(v1.size() + v2.size());
+ //vUnion.erase(set_union(v1.begin(), v1.end(),
+ // v2.begin(), v2.end(),
+ // vUnion.begin()),
+ // vUnion.end());
+
+ T vUnion;
+ vUnion.reserve(v1.size() + v2.size());
+ set_union(v1.begin(), v1.end(),
+ v2.begin(), v2.end(),
+ back_inserter(vUnion));
+ unsigned int nAdded = vUnion.size() - v1.size();
+ if (nAdded > 0)
+ v1 = vUnion;
+ return nAdded;
+}
+
+void CUser::AddAtom(unsigned short nAtom, bool fOrigin)
+{
+ // Ignore duplicates
+ if (binary_search(vAtomsIn.begin(), vAtomsIn.end(), nAtom) ||
+ find(vAtomsNew.begin(), vAtomsNew.end(), nAtom) != vAtomsNew.end())
+ return;
+
+ //// instead of zero atom, should change to free atom that propagates,
+ //// limited to lower than a certain value like 5 so conflicts quickly
+ // The zero atom never propagates,
+ // new atoms always propagate through the user that created them
+ if (nAtom == 0 || fOrigin)
+ {
+ vector<unsigned short> vTmp(1, nAtom);
+ Union(vAtomsIn, vTmp);
+ if (fOrigin)
+ vAtomsOut.push_back(nAtom);
+ return;
+ }
+
+ vAtomsNew.push_back(nAtom);
+
+ if (vAtomsNew.size() >= nFlowthroughRate || vAtomsOut.empty())
+ {
+ // Select atom to flow through to vAtomsOut
+ vAtomsOut.push_back(vAtomsNew[GetRand(vAtomsNew.size())]);
+
+ // Merge vAtomsNew into vAtomsIn
+ sort(vAtomsNew.begin(), vAtomsNew.end());
+ Union(vAtomsIn, vAtomsNew);
+ vAtomsNew.clear();
+ }
+}
+
+bool AddAtomsAndPropagate(uint256 hashUserStart, const vector<unsigned short>& vAtoms, bool fOrigin)
+{
+ CReviewDB reviewdb;
+ map<uint256, vector<unsigned short> > pmapPropagate[2];
+ pmapPropagate[0][hashUserStart] = vAtoms;
+
+ for (int side = 0; !pmapPropagate[side].empty(); side = 1 - side)
+ {
+ map<uint256, vector<unsigned short> >& mapFrom = pmapPropagate[side];
+ map<uint256, vector<unsigned short> >& mapTo = pmapPropagate[1 - side];
+
+ for (map<uint256, vector<unsigned short> >::iterator mi = mapFrom.begin(); mi != mapFrom.end(); ++mi)
+ {
+ const uint256& hashUser = (*mi).first;
+ const vector<unsigned short>& vReceived = (*mi).second;
+
+ ///// this would be a lot easier on the database if it put the new atom at the beginning of the list,
+ ///// so the change would be right next to the vector size.
+
+ // Read user
+ CUser user;
+ reviewdb.ReadUser(hashUser, user);
+ unsigned int nIn = user.vAtomsIn.size();
+ unsigned int nNew = user.vAtomsNew.size();
+ unsigned int nOut = user.vAtomsOut.size();
+
+ // Add atoms received
+ foreach(unsigned short nAtom, vReceived)
+ user.AddAtom(nAtom, fOrigin);
+ fOrigin = false;
+
+ // Don't bother writing to disk if no changes
+ if (user.vAtomsIn.size() == nIn && user.vAtomsNew.size() == nNew)
+ continue;
+
+ // Propagate
+ if (user.vAtomsOut.size() > nOut)
+ foreach(const uint256& hash, user.vLinksOut)
+ mapTo[hash].insert(mapTo[hash].end(), user.vAtomsOut.begin() + nOut, user.vAtomsOut.end());
+
+ // Write back
+ if (!reviewdb.WriteUser(hashUser, user))
+ return false;
+ }
+ mapFrom.clear();
+ }
+ return true;
+}
+
+
+
+
+
+
+bool CReview::AcceptReview()
+{
+ // Timestamp
+ nTime = GetTime();
+
+ // Check signature
+ if (!CKey::Verify(vchPubKeyFrom, GetSigHash(), vchSig))
+ return false;
+
+ CReviewDB reviewdb;
+
+ // Add review text to recipient
+ vector<CReview> vReviews;
+ reviewdb.ReadReviews(hashTo, vReviews);
+ vReviews.push_back(*this);
+ if (!reviewdb.WriteReviews(hashTo, vReviews))
+ return false;
+
+ // Add link from sender
+ CUser user;
+ uint256 hashFrom = Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end());
+ reviewdb.ReadUser(hashFrom, user);
+ user.vLinksOut.push_back(hashTo);
+ if (!reviewdb.WriteUser(hashFrom, user))
+ return false;
+
+ reviewdb.Close();
+
+ // Propagate atoms to recipient
+ vector<unsigned short> vZeroAtom(1, 0);
+ if (!AddAtomsAndPropagate(hashTo, user.vAtomsOut.size() ? user.vAtomsOut : vZeroAtom, false))
+ return false;
+
+ return true;
+}
+
+
+
+
+
+bool CProduct::CheckSignature()
+{
+ return (CKey::Verify(vchPubKeyFrom, GetSigHash(), vchSig));
+}
+
+bool CProduct::CheckProduct()
+{
+ if (!CheckSignature())
+ return false;
+
+ // Make sure it's a summary product
+ if (!mapDetails.empty() || !vOrderForm.empty())
+ return false;
+
+ // Look up seller's atom count
+ CReviewDB reviewdb("r");
+ CUser user;
+ reviewdb.ReadUser(GetUserHash(), user);
+ nAtoms = user.GetAtomCount();
+ reviewdb.Close();
+
+ ////// delme, this is now done by AdvertInsert
+ //// Store to memory
+ //CRITICAL_BLOCK(cs_mapProducts)
+ // mapProducts[GetHash()] = *this;
+
+ return true;
+}