Master Core  v0.0.9 - 2abfd2849db8ba7a83957c64eb976b406713c123
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
mastercore_sp.h
Go to the documentation of this file.
1 #ifndef _MASTERCOIN_SP
2 #define _MASTERCOIN_SP 1
3 
4 #include "mastercore.h"
5 
6 class CMPSPInfo
7 {
8 public:
9  struct Entry {
10  // common SP data
11  string issuer;
12  unsigned short prop_type;
13  unsigned int prev_prop_id;
14  string category;
15  string subcategory;
16  string name;
17  string url;
18  string data;
19  uint64_t num_tokens;
20 
21  // Crowdsale generated SP
22  unsigned int property_desired;
23  uint64_t deadline;
24  unsigned char early_bird;
25  unsigned char percentage;
26 
27  //We need this. Closedearly states if the SP was a crowdsale and closed due to MAXTOKENS or CLOSE command
29  bool max_tokens;
30  uint64_t missedTokens;
31  uint64_t timeclosed;
33 
34  // other information
38  bool fixed;
39  bool manual;
40 
41  // for crowdsale properties, schema is 'txid:amtSent:deadlineUnix:userIssuedTokens:IssuerIssuedTokens;'
42  // for manual properties, schema is 'txid:grantAmount:revokeAmount;'
43  std::map<std::string, std::vector<uint64_t> > historicalData;
44 
46  : issuer()
47  , prop_type(0)
48  , prev_prop_id(0)
49  , category()
50  , subcategory()
51  , name()
52  , url()
53  , data()
54  , num_tokens(0)
55  , property_desired(0)
56  , deadline(0)
57  , early_bird(0)
58  , percentage(0)
59  , close_early(0)
60  , max_tokens(0)
61  , missedTokens(0)
62  , timeclosed(0)
63  , txid_close()
64  , txid()
65  , creation_block()
66  , update_block()
67  , fixed(false)
68  , manual(false)
69  , historicalData()
70  {
71  }
72 
73  Object toJSON() const
74  {
75  Object spInfo;
76  spInfo.push_back(Pair("issuer", issuer));
77  spInfo.push_back(Pair("prop_type", prop_type));
78  spInfo.push_back(Pair("prev_prop_id", (uint64_t)prev_prop_id));
79  spInfo.push_back(Pair("category", category));
80  spInfo.push_back(Pair("subcategory", subcategory));
81  spInfo.push_back(Pair("name", name));
82  spInfo.push_back(Pair("url", url));
83  spInfo.push_back(Pair("data", data));
84  spInfo.push_back(Pair("fixed", fixed));
85  spInfo.push_back(Pair("manual", manual));
86 
87  spInfo.push_back(Pair("num_tokens", (boost::format("%d") % num_tokens).str()));
88  if (false == fixed && false == manual) {
89  spInfo.push_back(Pair("property_desired", (uint64_t)property_desired));
90  spInfo.push_back(Pair("deadline", (boost::format("%d") % deadline).str()));
91  spInfo.push_back(Pair("early_bird", (int)early_bird));
92  spInfo.push_back(Pair("percentage", (int)percentage));
93 
94  spInfo.push_back(Pair("close_early", (int)close_early));
95  spInfo.push_back(Pair("max_tokens", (int)max_tokens));
96  spInfo.push_back(Pair("missedTokens", (int) missedTokens));
97  spInfo.push_back(Pair("timeclosed", (boost::format("%d") % timeclosed).str()));
98  spInfo.push_back(Pair("txid_close", (boost::format("%s") % txid_close.ToString()).str()));
99  }
100 
101  //Initialize values
102  std::map<std::string, std::vector<uint64_t> >::const_iterator it;
103 
104  std::string values_long = "";
105  std::string values = "";
106 
107  //file_log("\ncrowdsale started to save, size of db %ld", database.size());
108 
109  //Iterate through fundraiser data, serializing it with txid:val:val:val:val;
110  bool crowdsale = !fixed && !manual;
111  for(it = historicalData.begin(); it != historicalData.end(); it++) {
112  values += it->first.c_str();
113  if (crowdsale) {
114  values += ":" + boost::lexical_cast<std::string>(it->second.at(0));
115  values += ":" + boost::lexical_cast<std::string>(it->second.at(1));
116  values += ":" + boost::lexical_cast<std::string>(it->second.at(2));
117  values += ":" + boost::lexical_cast<std::string>(it->second.at(3));
118  } else if (manual) {
119  values += ":" + boost::lexical_cast<std::string>(it->second.at(0));
120  values += ":" + boost::lexical_cast<std::string>(it->second.at(1));
121  }
122  values += ";";
123  values_long += values;
124  }
125  //file_log("\ncrowdsale saved %s", values_long.c_str());
126 
127  spInfo.push_back(Pair("historicalData", values_long));
128  spInfo.push_back(Pair("txid", (boost::format("%s") % txid.ToString()).str()));
129  spInfo.push_back(Pair("creation_block", (boost::format("%s") % creation_block.ToString()).str()));
130  spInfo.push_back(Pair("update_block", (boost::format("%s") % update_block.ToString()).str()));
131  return spInfo;
132  }
133 
134  void fromJSON(Object const &json)
135  {
136  unsigned int idx = 0;
137  issuer = json[idx++].value_.get_str();
138  prop_type = (unsigned short)json[idx++].value_.get_int();
139  prev_prop_id = (unsigned int)json[idx++].value_.get_uint64();
140  category = json[idx++].value_.get_str();
141  subcategory = json[idx++].value_.get_str();
142  name = json[idx++].value_.get_str();
143  url = json[idx++].value_.get_str();
144  data = json[idx++].value_.get_str();
145  fixed = json[idx++].value_.get_bool();
146  manual = json[idx++].value_.get_bool();
147 
148  num_tokens = boost::lexical_cast<uint64_t>(json[idx++].value_.get_str());
149  if (false == fixed && false == manual) {
150  property_desired = (unsigned int)json[idx++].value_.get_uint64();
151  deadline = boost::lexical_cast<uint64_t>(json[idx++].value_.get_str());
152  early_bird = (unsigned char)json[idx++].value_.get_int();
153  percentage = (unsigned char)json[idx++].value_.get_int();
154 
155  close_early = (unsigned char)json[idx++].value_.get_int();
156  max_tokens = (unsigned char)json[idx++].value_.get_int();
157  missedTokens = (unsigned char)json[idx++].value_.get_int();
158  timeclosed = boost::lexical_cast<uint64_t>(json[idx++].value_.get_str());
159  txid_close = uint256(json[idx++].value_.get_str());
160  }
161 
162  //reconstruct database
163  std::string longstr = json[idx++].value_.get_str();
164 
165  //file_log("\nDESERIALIZE GO ----> %s" ,longstr.c_str() );
166 
167  std::vector<std::string> strngs_vec;
168 
169  //split serialized form up
170  boost::split(strngs_vec, longstr, boost::is_any_of(";"));
171 
172  //file_log("\nDATABASE PRE-DESERIALIZE SUCCESS, %ld, %s" ,strngs_vec.size(), strngs_vec[0].c_str());
173 
174  //Go through and deserialize the database
175  bool crowdsale = !fixed && !manual;
176  for(std::vector<std::string>::size_type i = 0; i != strngs_vec.size(); i++) {
177  if (strngs_vec[i].empty()) {
178  continue;
179  }
180 
181  std::vector<std::string> str_split_vec;
182  boost::split(str_split_vec, strngs_vec[i], boost::is_any_of(":"));
183 
184  std::vector<uint64_t> txDataVec;
185 
186  if ( crowdsale && str_split_vec.size() == 5) {
187  //file_log("\n Deserialized values: %s, %s %s %s %s", str_split_vec.at(0).c_str(), str_split_vec.at(1).c_str(), str_split_vec.at(2).c_str(), str_split_vec.at(3).c_str(), str_split_vec.at(4).c_str());
188  txDataVec.push_back(boost::lexical_cast<uint64_t>( str_split_vec.at(1) ));
189  txDataVec.push_back(boost::lexical_cast<uint64_t>( str_split_vec.at(2) ));
190  txDataVec.push_back(boost::lexical_cast<uint64_t>( str_split_vec.at(3) ));
191  txDataVec.push_back(boost::lexical_cast<uint64_t>( str_split_vec.at(4) ));
192  } else if (manual && str_split_vec.size() == 3) {
193  txDataVec.push_back(boost::lexical_cast<uint64_t>( str_split_vec.at(1) ));
194  txDataVec.push_back(boost::lexical_cast<uint64_t>( str_split_vec.at(2) ));
195  }
196 
197  historicalData.insert(std::make_pair( str_split_vec.at(0), txDataVec ) ) ;
198  }
199  //file_log("\nDATABASE DESERIALIZE SUCCESS %lu", database.size());
200  txid = uint256(json[idx++].value_.get_str());
201  creation_block = uint256(json[idx++].value_.get_str());
202  update_block = uint256(json[idx++].value_.get_str());
203  }
204 
205  bool isDivisible() const
206  {
207  switch (prop_type)
208  {
212  return true;
213  }
214  return false;
215  }
216 
217  void print() const
218  {
219  printf("%s:%s(Fixed=%s,Divisible=%s):%lu:%s/%s, %s %s\n",
220  issuer.c_str(),
221  name.c_str(),
222  fixed ? "Yes":"No",
223  isDivisible() ? "Yes":"No",
224  num_tokens,
225  category.c_str(), subcategory.c_str(), url.c_str(), data.c_str());
226  }
227 
228  };
229 
230 private:
231  leveldb::DB *pDb;
232  boost::filesystem::path const path;
233 
234  // implied version of msc and tmsc so they don't hit the leveldb
237 
238  unsigned int next_spid;
239  unsigned int next_test_spid;
240 
241  void openDB() {
242  leveldb::Options options;
243  options.paranoid_checks = true;
244  options.create_if_missing = true;
245 
246  leveldb::Status s = leveldb::DB::Open(options, path.string(), &pDb);
247 
248  if (false == s.ok()) {
249  printf("Failed to create or read LevelDB for Smart Property at %s", path.c_str());
250  }
251  }
252 
253  void closeDB() {
254  delete pDb;
255  pDb = NULL;
256  }
257 
258 public:
259 
260  CMPSPInfo(const boost::filesystem::path &_path)
261  : path(_path)
262  {
263  openDB();
264 
265  // special cases for constant SPs MSC and TMSC
266  implied_msc.issuer = ExodusAddress();
268  implied_msc.num_tokens = 700000;
269  implied_msc.category = "N/A";
270  implied_msc.subcategory = "N/A";
271  implied_msc.name = "MasterCoin";
272  implied_msc.url = "www.mastercoin.org";
273  implied_msc.data = "***data***";
274  implied_tmsc.issuer = ExodusAddress();
275  implied_tmsc.prop_type = MSC_PROPERTY_TYPE_DIVISIBLE;
276  implied_tmsc.num_tokens = 700000;
277  implied_tmsc.category = "N/A";
278  implied_tmsc.subcategory = "N/A";
279  implied_tmsc.name = "Test MasterCoin";
280  implied_tmsc.url = "www.mastercoin.org";
281  implied_tmsc.data = "***data***";
282 
283  init();
284  }
285 
287  {
288  closeDB();
289  }
290 
291  void init(unsigned int nextSPID = 0x3UL, unsigned int nextTestSPID = TEST_ECO_PROPERTY_1)
292  {
293  next_spid = nextSPID;
294  next_test_spid = nextTestSPID;
295  }
296 
297  void clear() {
298  closeDB();
299  leveldb::DestroyDB(path.string(), leveldb::Options());
300  openDB();
301  init();
302  }
303 
304  unsigned int peekNextSPID(unsigned char ecosystem)
305  {
306  unsigned int nextId = 0;
307 
308  switch(ecosystem) {
309  case OMNI_PROPERTY_MSC: // mastercoin ecosystem, MSC: 1, TMSC: 2, First available SP = 3
310  nextId = next_spid;
311  break;
312  case OMNI_PROPERTY_TMSC: // Test MSC ecosystem, same as above with high bit set
313  nextId = next_test_spid;
314  break;
315  default: // non standard ecosystem, ID's start at 0
316  nextId = 0;
317  }
318 
319  return nextId;
320  }
321 
322  unsigned int updateSP(unsigned int propertyID, Entry const &info);
323  unsigned int putSP(unsigned char ecosystem, Entry const &info);
324  bool getSP(unsigned int spid, Entry &info);
325  bool hasSP(unsigned int spid);
326 
327  unsigned int findSPByTX(uint256 const &txid);
328 
329  int popBlock(uint256 const &block_hash);
330 
331  static string const watermarkKey;
332  void setWatermark(uint256 const &watermark)
333  {
334  leveldb::WriteOptions writeOptions;
335  writeOptions.sync = true;
336 
337  leveldb::WriteBatch commitBatch;
338  commitBatch.Delete(watermarkKey);
339  commitBatch.Put(watermarkKey, watermark.ToString());
340  pDb->Write(writeOptions, &commitBatch);
341  }
342 
343  int getWatermark(uint256 &watermark)
344  {
345  leveldb::ReadOptions readOpts;
346  readOpts.fill_cache = false;
347  string watermarkVal;
348  if (pDb->Get(readOpts, watermarkKey, &watermarkVal).ok()) {
349  watermark.SetHex(watermarkVal);
350  return 0;
351  } else {
352  return -1;
353  }
354  }
355 
356  void printAll()
357  {
358  // print off the hard coded MSC and TMSC entries
359  for (unsigned int idx = OMNI_PROPERTY_MSC; idx <= OMNI_PROPERTY_TMSC; idx++ ) {
360  Entry info;
361  printf("%10d => ", idx);
362  if (getSP(idx, info)) {
363  info.print();
364  } else {
365  printf("<Internal Error on implicit SP>\n");
366  }
367  }
368 
369  leveldb::ReadOptions readOpts;
370  readOpts.fill_cache = false;
371  leveldb::Iterator *iter = pDb->NewIterator(readOpts);
372  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
373  if (iter->key().starts_with("sp-")) {
374  std::vector<std::string> vstr;
375  std::string key = iter->key().ToString();
376  boost::split(vstr, key, boost::is_any_of("-"), token_compress_on);
377 
378  printf("%10s => ", vstr[1].c_str());
379 
380  // parse the encoded json, failing if it doesnt parse or is an object
381  Value spInfoVal;
382  if (read_string(iter->value().ToString(), spInfoVal) && spInfoVal.type() == obj_type ) {
383  Entry info;
384  info.fromJSON(spInfoVal.get_obj());
385  info.print();
386  } else {
387  printf("<Malformed JSON in DB>\n");
388  }
389  }
390  }
391 
392  // clean up the iterator
393  delete iter;
394  }
395 };
396 
397 // live crowdsales are these objects in a map
398 class CMPCrowd
399 {
400 private:
401  unsigned int propertyId;
402 
403  uint64_t nValue;
404 
405  unsigned int property_desired;
406  uint64_t deadline;
407  unsigned char early_bird;
408  unsigned char percentage;
409 
410  uint64_t u_created;
411  uint64_t i_created;
412 
413  uint256 txid; // NOTE: not persisted as it doesnt seem used
414 
415  std::map<std::string, std::vector<uint64_t> > txFundraiserData; // schema is 'txid:amtSent:deadlineUnix:userIssuedTokens:IssuerIssuedTokens;'
416 public:
417  CMPCrowd():propertyId(0),nValue(0),property_desired(0),deadline(0),early_bird(0),percentage(0),u_created(0),i_created(0)
418  {
419  }
420 
421  CMPCrowd(unsigned int pid, uint64_t nv, unsigned int cd, uint64_t dl, unsigned char eb, unsigned char per, uint64_t uct, uint64_t ict):
422  propertyId(pid),nValue(nv),property_desired(cd),deadline(dl),early_bird(eb),percentage(per),u_created(uct),i_created(ict)
423  {
424  }
425 
426  unsigned int getPropertyId() const { return propertyId; }
427 
428  uint64_t getDeadline() const { return deadline; }
429  uint64_t getCurrDes() const { return property_desired; }
430 
431  void incTokensUserCreated(uint64_t amount) { u_created += amount; }
432  void incTokensIssuerCreated(uint64_t amount) { i_created += amount; }
433 
434  uint64_t getUserCreated() const { return u_created; }
435  uint64_t getIssuerCreated() const { return i_created; }
436 
437  void insertDatabase(std::string txhash, std::vector<uint64_t> txdata ) { txFundraiserData.insert(std::make_pair<std::string, std::vector<uint64_t>& >(txhash,txdata)); }
438  std::map<std::string, std::vector<uint64_t> > getDatabase() const { return txFundraiserData; }
439 
440  void print(const string & address, FILE *fp = stdout) const
441  {
442  fprintf(fp, "%34s : id=%u=%X; prop=%u, value= %lu, deadline: %s (%lX)\n", address.c_str(), propertyId, propertyId,
443  property_desired, nValue, DateTimeStrFormat("%Y-%m-%d %H:%M:%S", deadline).c_str(), deadline);
444  }
445 
446  void saveCrowdSale(ofstream &file, SHA256_CTX *shaCtx, string const &addr) const
447  {
448  // compose the outputline
449  // addr,propertyId,nValue,property_desired,deadline,early_bird,percentage,created,mined
450  string lineOut = (boost::format("%s,%d,%d,%d,%d,%d,%d,%d,%d")
451  % addr
452  % propertyId
453  % nValue
454  % property_desired
455  % deadline
456  % (int)early_bird
457  % (int)percentage
458  % u_created
459  % i_created ).str();
460 
461  // append N pairs of address=nValue;blockTime for the database
462  std::map<std::string, std::vector<uint64_t> >::const_iterator iter;
463  for (iter = txFundraiserData.begin(); iter != txFundraiserData.end(); ++iter) {
464  lineOut.append((boost::format(",%s=") % (*iter).first).str());
465  std::vector<uint64_t> const &vals = (*iter).second;
466 
467  std::vector<uint64_t>::const_iterator valIter;
468  for (valIter = vals.begin(); valIter != vals.end(); ++valIter) {
469  if (valIter != vals.begin()) {
470  lineOut.append(";");
471  }
472 
473  lineOut.append((boost::format("%d") % (*valIter)).str());
474  }
475  }
476 
477  // add the line to the hash
478  SHA256_Update(shaCtx, lineOut.c_str(), lineOut.length());
479 
480  // write the line
481  file << lineOut << endl;
482  }
483 }; // end of CMPCrowd class
484 
485 namespace mastercore
486 {
487 extern CMPSPInfo *_my_sps;
488 
489 typedef std::map<string, CMPCrowd> CrowdMap;
490 
491 extern CrowdMap my_crowds;
492 
493 char *c_strPropertyType(int i);
494 
495 CMPCrowd *getCrowd(const string & address);
496 
497 int calculateFractional(unsigned short int propType, unsigned char bonusPerc, uint64_t fundraiserSecs,
498  uint64_t numProps, unsigned char issuerPerc, const std::map<std::string, std::vector<uint64_t> > txFundraiserData,
499  const uint64_t amountPremined );
500 
501 void eraseMaxedCrowdsale(const string &address, uint64_t blockTime, int block);
502 
503 unsigned int eraseExpiredCrowdsale(CBlockIndex const * pBlockIndex);
504 
505 void dumpCrowdsaleInfo(const string &address, CMPCrowd &crowd, bool bExpired = false);
506 }
507 
508 #endif // _MASTERCOIN_SP
509 
int popBlock(uint256 const &block_hash)
leveldb::DB * pDb
void SetHex(const char *psz)
Definition: uint256.h:305
Entry()
Definition: mastercore_sp.h:45
bool close_early
Definition: mastercore_sp.h:28
uint64_t deadline
bool fixed
Definition: mastercore_sp.h:38
#define MSC_PROPERTY_TYPE_DIVISIBLE_REPLACING
Definition: mastercore.h:81
uint256 update_block
Definition: mastercore_sp.h:37
CMPSPInfo * _my_sps
Definition: mastercore.cpp:362
uint256 txid
Definition: mastercore_sp.h:35
std::map< std::string, std::vector< uint64_t > > txFundraiserData
boost::filesystem::path const path
Entry implied_tmsc
Entry implied_msc
#define MSC_PROPERTY_TYPE_DIVISIBLE_APPENDING
Definition: mastercore.h:83
string data
Definition: mastercore_sp.h:18
void init(unsigned int nextSPID=0x3UL, unsigned int nextTestSPID=TEST_ECO_PROPERTY_1)
uint64_t u_created
uint64_t getCurrDes() const
string issuer
Definition: mastercore_sp.h:11
uint256 txid
uint64_t getUserCreated() const
CMPCrowd(unsigned int pid, uint64_t nv, unsigned int cd, uint64_t dl, unsigned char eb, unsigned char per, uint64_t uct, uint64_t ict)
void saveCrowdSale(ofstream &file, SHA256_CTX *shaCtx, string const &addr) const
#define TEST_ECO_PROPERTY_1
Definition: mastercore.h:22
unsigned int next_spid
unsigned char early_bird
Definition: mastercore_sp.h:24
bool hasSP(unsigned int spid)
uint64_t num_tokens
Definition: mastercore_sp.h:19
std::map< std::string, std::vector< uint64_t > > getDatabase() const
void print(const string &address, FILE *fp=stdout) const
std::string DateTimeStrFormat(const char *pszFormat, int64_t nTime)
Definition: util.cpp:1429
std::map< string, CMPCrowd > CrowdMap
unsigned short prop_type
Definition: mastercore_sp.h:12
#define OMNI_PROPERTY_MSC
Definition: mastercore.h:130
uint256 txid_close
Definition: mastercore_sp.h:32
unsigned int property_desired
Definition: mastercore_sp.h:22
std::map< std::string, std::vector< uint64_t > > historicalData
Definition: mastercore_sp.h:43
uint64_t timeclosed
Definition: mastercore_sp.h:31
uint64_t nValue
Definition: mastercore_sp.h:9
int calculateFractional(unsigned short int propType, unsigned char bonusPerc, uint64_t fundraiserSecs, uint64_t numProps, unsigned char issuerPerc, const std::map< std::string, std::vector< uint64_t > > txFundraiserData, const uint64_t amountPremined)
#define OMNI_PROPERTY_TMSC
Definition: mastercore.h:131
uint64_t getIssuerCreated() const
void dumpCrowdsaleInfo(const string &address, CMPCrowd &crowd, bool bExpired=false)
string category
Definition: mastercore_sp.h:14
uint64_t i_created
unsigned int property_desired
unsigned int next_test_spid
unsigned char percentage
bool max_tokens
Definition: mastercore_sp.h:29
void printAll()
void fromJSON(Object const &json)
uint64_t missedTokens
Definition: mastercore_sp.h:30
bool getSP(unsigned int spid, Entry &info)
bool isDivisible() const
string name
Definition: mastercore_sp.h:16
#define MSC_PROPERTY_TYPE_DIVISIBLE
Definition: mastercore.h:79
unsigned int prev_prop_id
Definition: mastercore_sp.h:13
void eraseMaxedCrowdsale(const string &address, uint64_t blockTime, int block)
unsigned char early_bird
CrowdMap my_crowds
Definition: mastercore.cpp:363
string subcategory
Definition: mastercore_sp.h:15
void insertDatabase(std::string txhash, std::vector< uint64_t > txdata)
256-bit unsigned integer
Definition: uint256.h:531
void setWatermark(uint256 const &watermark)
void closeDB()
unsigned char percentage
Definition: mastercore_sp.h:25
unsigned int putSP(unsigned char ecosystem, Entry const &info)
char * c_strPropertyType(int i)
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: main.h:688
std::string ToString() const
Definition: uint256.h:340
const std::string ExodusAddress()
unsigned int findSPByTX(uint256 const &txid)
unsigned int propertyId
int getWatermark(uint256 &watermark)
string url
Definition: mastercore_sp.h:17
unsigned int peekNextSPID(unsigned char ecosystem)
uint256 creation_block
Definition: mastercore_sp.h:36
void clear()
void incTokensUserCreated(uint64_t amount)
static string const watermarkKey
CMPCrowd * getCrowd(const string &address)
CMPSPInfo(const boost::filesystem::path &_path)
void incTokensIssuerCreated(uint64_t amount)
void openDB()
void print() const
unsigned int eraseExpiredCrowdsale(CBlockIndex const *pBlockIndex)
uint64_t deadline
Definition: mastercore_sp.h:23
uint64_t getDeadline() const
unsigned int updateSP(unsigned int propertyID, Entry const &info)
unsigned int getPropertyId() const
void format(FormatIterator &fmtIter)
Definition: tinyformat.h:869
Object toJSON() const
Definition: mastercore_sp.h:73
bool manual
Definition: mastercore_sp.h:39