/****************************************************************************** * Copyright © 2014-2016 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * * holder information and the developer policies on copyright and licensing. * * * * Unless otherwise agreed in a custom licensing agreement, no part of the * * SuperNET software, including this file may be copied, modified, propagated * * or distributed except according to the terms contained in the LICENSE file * * * * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ #include "peggy.h" #include "exchanges777.h" int32_t Peggy_inds[539] = {289, 404, 50, 490, 59, 208, 87, 508, 366, 288, 13, 38, 159, 440, 120, 480, 361, 104, 534, 195, 300, 362, 489, 108, 143, 220, 131, 244, 133, 473, 315, 439, 210, 456, 219, 352, 153, 444, 397, 491, 286, 479, 519, 384, 126, 369, 155, 427, 373, 360, 135, 297, 256, 506, 322, 425, 501, 251, 75, 18, 420, 537, 443, 438, 407, 145, 173, 78, 340, 240, 422, 160, 329, 32, 127, 128, 415, 495, 372, 522, 60, 238, 129, 364, 471, 140, 171, 215, 378, 292, 432, 526, 252, 389, 459, 350, 233, 408, 433, 51, 423, 19, 62, 115, 211, 22, 247, 197, 530, 7, 492, 5, 53, 318, 313, 283, 169, 464, 224, 282, 514, 385, 228, 175, 494, 237, 446, 105, 150, 338, 346, 510, 6, 348, 89, 63, 536, 442, 414, 209, 216, 227, 380, 72, 319, 259, 305, 334, 236, 103, 400, 176, 267, 355, 429, 134, 257, 527, 111, 287, 386, 15, 392, 535, 405, 23, 447, 399, 291, 112, 74, 36, 435, 434, 330, 520, 335, 201, 478, 17, 162, 483, 33, 130, 436, 395, 93, 298, 498, 511, 66, 487, 218, 65, 309, 419, 48, 214, 377, 409, 462, 139, 349, 4, 513, 497, 394, 170, 307, 241, 185, 454, 29, 367, 465, 194, 398, 301, 229, 212, 477, 303, 39, 524, 451, 116, 532, 30, 344, 85, 186, 202, 517, 531, 515, 230, 331, 466, 147, 426, 234, 304, 64, 100, 416, 336, 199, 383, 200, 166, 258, 95, 188, 246, 136, 90, 68, 45, 312, 354, 184, 314, 518, 326, 401, 269, 217, 512, 81, 88, 272, 14, 413, 328, 393, 198, 226, 381, 161, 474, 353, 337, 294, 295, 302, 505, 137, 207, 249, 46, 98, 27, 458, 482, 262, 253, 71, 25, 0, 40, 525, 122, 341, 107, 80, 165, 243, 168, 250, 375, 151, 503, 124, 52, 343, 371, 206, 178, 528, 232, 424, 163, 273, 191, 149, 493, 177, 144, 193, 388, 1, 412, 265, 457, 255, 475, 223, 41, 430, 76, 102, 132, 96, 97, 316, 472, 213, 263, 3, 317, 324, 274, 396, 486, 254, 205, 285, 101, 21, 279, 58, 467, 271, 92, 538, 516, 235, 332, 117, 500, 529, 113, 445, 390, 358, 79, 34, 488, 245, 83, 509, 203, 476, 496, 347, 280, 12, 84, 485, 323, 452, 10, 146, 391, 293, 86, 94, 523, 299, 91, 164, 363, 402, 110, 321, 181, 138, 192, 469, 351, 276, 308, 277, 428, 182, 260, 55, 152, 157, 382, 121, 507, 225, 61, 431, 31, 106, 327, 154, 16, 49, 499, 73, 70, 449, 460, 187, 24, 248, 311, 275, 158, 387, 125, 67, 284, 35, 463, 190, 179, 266, 376, 221, 42, 26, 290, 357, 268, 43, 167, 99, 374, 242, 156, 239, 403, 339, 183, 320, 180, 306, 379, 441, 20, 481, 141, 77, 484, 69, 410, 502, 172, 417, 118, 461, 261, 47, 333, 450, 296, 453, 368, 359, 437, 421, 264, 504, 281, 270, 114, 278, 56, 406, 448, 411, 521, 418, 470, 123, 455, 148, 356, 468, 109, 204, 533, 365, 8, 345, 174, 370, 28, 57, 11, 2, 231, 310, 196, 119, 82, 325, 44, 342, 37, 189, 142, 222, 9, 54, }; char *peggy_mapname(char *basebuf,char *relbuf,int32_t i) // sorry it is messy thing { char *base,*rel,buf[16]; base = rel = 0; strcpy(buf,peggy_bases[i]); base = buf, rel = "BTCD"; if ( strlen(buf) > 3 && strcmp(buf+strlen(buf)-3,"USD") == 0 ) { if ( strcmp(buf,"BTCUSD") == 0 ) base = "BTC"; buf[strlen(buf)-3] = 0; } else if ( strcmp(buf,"COPPER") == 0 || strcmp(buf,"NGAS") == 0 || strcmp(buf,"UKOIL") == 0 || strcmp(buf,"USOIL") == 0 || strcmp(buf,"US30") == 0 || strcmp(buf,"SPX500") == 0 || strcmp(buf,"NAS100") == 0 ) rel = "USD"; else if ( strcmp(buf,"BUND") == 0 ) rel = "yield"; else if ( strcmp(buf,"EUSTX50") == 0 ) rel = "EUR"; else if ( strcmp(buf,"JPN225") == 0 ) rel = "JPY"; else if ( strcmp(buf,"UK100") == 0 ) rel = "GBP"; else if ( strcmp(buf,"GER30") == 0 ) rel = "EUR"; else if ( strcmp(buf,"SUI30") == 0 ) rel = "CHF"; else if ( strcmp(buf,"AUS200") == 0 ) rel = "AUD"; else if ( strcmp(buf,"HKG33") == 0 ) rel = "HKD"; else if ( strlen(buf) > 3 && strcmp(buf+strlen(buf)-3,"BTC") == 0 ) base = buf, buf[strlen(buf)-3] = 0; if ( i == sizeof(peggy_bases)/sizeof(*peggy_bases)-1 && strcmp(peggy_bases[i],"BTCUSD") == 0 ) base = "BTC", rel = "USD"; else if ( i == sizeof(peggy_bases)/sizeof(*peggy_bases)-2 && strcmp(peggy_bases[i],"BTCCNY") == 0 ) base = "BTC", rel = "CNY"; else if ( i == sizeof(peggy_bases)/sizeof(*peggy_bases)-3 && strcmp(peggy_bases[i],"BTCRUB") == 0 ) base = "BTC", rel = "RUB"; else if ( i == sizeof(peggy_bases)/sizeof(*peggy_bases)-4 && strcmp(peggy_bases[i],"XAUUSD") == 0 ) base = "XAU", rel = "USD"; else if ( i == 0 ) base = "BTCD", rel = "maincurrency peggy, realtime"; basebuf[0] = relbuf[0] = 0; if ( rel != 0 ) strcpy(relbuf,rel);//, printf("rel.(%s) ",rel); if ( base != 0 ) strcpy(basebuf,base);//, printf("base.(%s) ",base); return(basebuf); } uint64_t peggy_basebits(char *name) { int32_t i; char basebuf[64],relbuf[64]; for (i=0; i<64; i++) { if ( strcmp(name,peggy_bases[i]) == 0 ) { peggy_mapname(basebuf,relbuf,i); return(stringbits(basebuf)); } } return(0); } uint64_t peggy_relbits(char *name) { int32_t i; char basebuf[64],relbuf[64]; for (i=0; i<64; i++) { if ( strcmp(name,peggy_bases[i]) == 0 ) { peggy_mapname(basebuf,relbuf,i); return(stringbits(relbuf)); } } return(0); } static uint64_t peggy_assetbits(char *name) { return((is_decimalstr(name) != 0) ? calc_nxt64bits(name) : stringbits(name)); } int32_t find_uint64(int32_t *emptyslotp,uint64_t *nums,long max,uint64_t val) { int32_t i; *emptyslotp = -1; for (i=0; i 2 ) printf("found in slot[%d] %llx\n",i,(long long)val); return(i); } } if ( Debuglevel > 2 ) printf("emptyslot[%d] for %llx\n",i,(long long)val); return(-1); } int32_t add_uint64(uint64_t *nums,long max,uint64_t val) { int32_t i,emptyslot; if ( (i= find_uint64(&emptyslot,nums,max,val)) >= 0 ) return(i); else if ( emptyslot >= 0 ) { nums[emptyslot] = val; return(emptyslot); } else return(-1); } // init time void peggy_descriptions(struct peggy_info *PEGS,struct peggy_description *P,char *name,char *base,char *rel) { int32_t emptyslot; strcpy(P->name,name), strcpy(P->base,base); if ( rel != 0 ) strcpy(P->rel,rel); P->assetbits = peggy_assetbits(name), P->basebits = stringbits(base), P->relbits = stringbits(P->rel); P->baseid = add_uint64(PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->basebits); P->relid = add_uint64(PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->relbits); if ( find_uint64(&emptyslot,PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->basebits) != P->baseid ) printf("(%s) (%s) (%s) error cant find baseid.%d for %llx\n",name,base,P->rel,P->baseid,(long long)P->basebits); if ( P->relbits != 0 && find_uint64(&emptyslot,PEGS->basebits,sizeof(PEGS->basebits)/sizeof(*PEGS->basebits),P->relbits) != P->relid ) printf("(%s) (%s) (%s) error cant find relid.%d for %llx\n",name,base,P->rel,P->relid,(long long)P->relbits); } /*int32_t peggy_timeframes(struct peggy_limits *limits,int64_t *scales,uint32_t *timeframes,int32_t numtimeframes,uint64_t maxsupply,uint64_t maxnetbalance) { int32_t i; memset(limits,0,sizeof(*limits)); limits->maxsupply = maxsupply, limits->maxnetbalance = maxnetbalance; if ( limits->maxsupply < 0 || limits->maxnetbalance < 0 ) { printf("peggy_check_limits: maxnetbalance %lld > %d\n",(long long)limits->maxnetbalance,(int32_t)PRICE_RESOLUTION); return(-1); } limits->numtimeframes = (numtimeframes <= MAX_TIMEFRAMES) ? numtimeframes : MAX_TIMEFRAMES; for (i=0; inumtimeframes; i++) { limits->scales[i] = scales[i]; if ( (limits->timeframes[i]= PEGGY_DAYTICKS * timeframes[i]) > MAX_TIMEFRAME || (i > 0 && limits->timeframes[i] <= limits->timeframes[i-1]) ) { printf("createpeg: illegal timeframe.%d: %d %d vs %d\n",i,timeframes[i],limits->timeframes[i],MAX_TIMEFRAME); getchar(); return(-1); } } limits->timeframes[0] = 0; return(0); }*/ int32_t peggy_lockparms(struct peggy_lock *dest,int32_t peg,struct peggy_lock *lockparms) { if ( lockparms->minlockdays > lockparms->maxlockdays ) { printf("peggy_check_lockparms: minlockdays %d > %d maxlockdays\n",lockparms->minlockdays,lockparms->maxlockdays); return(-1); } if ( lockparms->mixrange == 0 ) lockparms->mixrange = PEGGY_MIXRANGE; if ( lockparms->extralockdays < PEGGY_MINEXTRADAYS * 2 ) lockparms->extralockdays = PEGGY_MINEXTRADAYS * 2; *dest = *lockparms, dest->peg = peg; return(0); } int32_t peggy_setvars(struct peggy_info *PEGS,struct peggy *PEG,int16_t baseid,int16_t relid,int32_t peg,uint64_t maxsupply,uint64_t maxnetbalance,struct peggy_lock *lockparms,uint32_t unitincr,int32_t dailyrate,struct price_resolution *initialprices,int32_t numprices,int32_t hasprice) { int32_t i; PEG->name.id = peg, PEG->name.hasprice = hasprice; //if ( peggy_timeframes(&PEG->limits,limits->scales,limits->timeframes,limits->numtimeframes,limits->maxsupply,limits->maxnetbalance) < 0 ) // return(-1); if ( peggy_lockparms(&PEG->lockparms,peg,lockparms) < 0 ) return(-1); PEG->unitincr = unitincr; PEG->maxdailyrate = dailyrate; PEG->maxsupply = maxsupply, PEG->maxnetbalance = maxnetbalance; if ( initialprices != 0 ) { if ( numprices > 0 ) { //if ( initialprices[0].Pval >= PRICE_RESOLUTION_MAXPVAL ) // initialprices[0].Pval = PRICE_RESOLUTION_MAXPVAL; PEG->genesisprice = PEG->dayprice = PEG->price = initialprices[0]; for (i=0; imaincurrency, mainunitsize = PEGS->mainunitsize; if ( lockparms == 0 ) lockparms = &PEGS->default_lockparms; //if ( limits == 0 ) // limits = &PEGS->default_limits; if ( (PEGS->numpegs == 0 && stringbits(base) != PEGS->mainbits) || maxmargin > PEGGY_MARGINMAX ) { printf("peggy_create: numpegs.%d mismatched maincurrency.(%s) || illegal maxmargin.%d vs %d\n",PEGS->numpegs,maincurrency,maxmargin,PEGGY_MARGINMAX); return(0); } if ( firsttimestamp + (numprices-1)*PEGGY_DAYTICKS > time(NULL) ) { printf("peggy_createpair latest price must be in the past: 1st.%u + numprices.%d -> %u vs %u\n",firsttimestamp,numprices,firsttimestamp + (numprices-1)*PEGGY_DAYTICKS,(uint32_t)time(NULL)); return(0); } if ( quorum == 0 ) quorum = PEGS->quorum; if ( decisionthreshold == 0 ) decisionthreshold = PEGS->decisionthreshold; assetbits = peggy_assetbits(name); if ( PEGS->numpegs > 0 ) { for (i=0; inumpegs; i++) if ( PEGS->contracts[i]->name.assetbits == assetbits ) { printf("peggy_create: cant create duplicate peggy.(%s) base.(%s) rel.(%s)\n",name,base,rel); return(0); } } if ( hasprice != 0 ) PEG = &PEGS->pricedpegs[PEGS->numpricedpegs].PEG; else PEG = &PEGS->pairedpegs[PEGS->numpairedpegs]; memset(PEG,0,sizeof(*PEG)); peggy_descriptions(PEGS,&PEG->name,name,base,rel); PEG->pool.quorum = (quorum != 0) ? quorum : PEGS->quorum, PEG->pool.decisionthreshold = (decisionthreshold != 0) ? decisionthreshold : PEGS->decisionthreshold; PEG->pool.mainunitsize = PEGS->mainunitsize, PEG->pool.mainbits = PEGS->mainbits; PEG->genesistime = firsttimestamp, PEG->name.id = PEGS->numpegs; PEG->spread = spread, PEG->lockparms.margin = maxmargin, PEG->mindenomination = mindenomination; if ( hasprice == 0 ) PEG->baseprices = PEGS->pricedpegs[PEG->name.baseid].prices, PEG->relprices = PEGS->pricedpegs[PEG->name.relid].prices; else PEG->baseprices = PEGS->pricedpegs[PEG->name.id].prices, PEG->relprices = 0; if ( peggy_setvars(PEGS,PEG,PEG->name.baseid,PEG->name.relid,PEGS->numpegs,maxsupply,maxnetbalance,lockparms,unitincr,maxdailyrate,initialprices,numprices,hasprice) < 0 ) { printf("peggy_create: error init peggy.(%s) base.(%s) rel.(%s)\n",name,base,rel); return(0); } //printf("PEG.%p num.%d priced.%d paired.%d\n",PEG,PEGS->numpegs,PEGS->numpricedpegs,PEGS->numpairedpegs); if ( hasprice != 0 ) PEGS->numpricedpegs++; else PEGS->numpairedpegs++; PEGS->contracts[PEGS->numpegs++] = PEG; PEG->peggymils = peggymils; PEG->name.enabled = 1; return(PEG); } struct peggy_info *peggy_init(int32_t maxdays,char *maincurrency,uint64_t maincurrencyunitsize,uint64_t quorum,uint64_t decisionthreshold,struct price_resolution spread,uint32_t dailyrate,int32_t interesttenths,int32_t posboost,int32_t negpenalty,int32_t feediv,int32_t feemult,uint32_t firsttimestamp,uint32_t BTCD_price0) { //struct peggy_limits limits = { { PERCENTAGE(10), PERCENTAGE(25), PERCENTAGE(33), PERCENTAGE(50) }, SATOSHIDEN * 10000, SATOSHIDEN * 1000, { 0, 30, 90, 180 }, 4 }; struct peggy_lock default_lockparms = { 7, 365, 7, 0, 180, 0, -1 }; struct price_resolution mindenom,price; struct peggy_info *PEGS = calloc(1,sizeof(*PEGS)); //if ( default_limits != 0 ) // limits = *default_limits; spread.Pval = PERCENTAGE(1); //OS_ensure_directory(path); strcpy(PEGS->maincurrency,maincurrency); PEGS->mainbits = stringbits(maincurrency), PEGS->mainunitsize = maincurrencyunitsize, PEGS->quorum = quorum, PEGS->decisionthreshold = decisionthreshold; PEGS->default_lockparms = default_lockparms, PEGS->default_lockparms.maxlockdays = maxdays; //PEGS->default_limits = limits, PEGS->default_spread = spread, PEGS->default_dailyrate = dailyrate; PEGS->interesttenths = interesttenths, PEGS->posboost = posboost, PEGS->negpenalty = negpenalty, PEGS->feediv = feediv, PEGS->feemult = feemult; mindenom.Pval = PRICE_RESOLUTION; PEGS->genesistime = firsttimestamp; price.Pval = PEGS->BTCD_price0 = BTCD_price0; printf("set genesistime.%u BTCD0.%u\n",firsttimestamp,BTCD_price0); peggy_createpair(PEGS,0,0,"BTCD","BTCD",0,SATOSHIDEN*1000000,SATOSHIDEN*100000,0,SATOSHIDEN,PEGGY_RATE_777,firsttimestamp,&price,1,spread,0,mindenom,0,1,peggy_mils(0)); //PEGS->accts = accts777_init(path,0); return(PEGS); } //////////// end of consensus safe long hdecode_varint(uint64_t *valp,uint8_t *ptr,long offset,long mappedsize) { uint16_t s; uint32_t i; int32_t c; if ( ptr == 0 ) return(-1); *valp = 0; if ( offset < 0 || offset >= mappedsize ) return(-1); c = ptr[offset++]; switch ( c ) { case 0xfd: if ( offset+sizeof(s) > mappedsize ) return(-1); memcpy(&s,&ptr[offset],sizeof(s)), *valp = s, offset += sizeof(s); break; case 0xfe: if ( offset+sizeof(i) > mappedsize ) return(-1); memcpy(&i,&ptr[offset],sizeof(i)), *valp = i, offset += sizeof(i); break; case 0xff: if ( offset+sizeof(*valp) > mappedsize ) return(-1); memcpy(valp,&ptr[offset],sizeof(*valp)), offset += sizeof(*valp); break; default: *valp = c; break; } return(offset); } void peggy_priceinits(struct peggy_info *PEGS,uint32_t firsttimestamp,uint32_t *allprices) { char name[64],base[64],rel[64]; struct peggy *PEG; struct price_resolution mindenom,spread,price; uint64_t maxsupply=0,maxnetbalance=0; int32_t i,c,baseid,relid,peggymils=0,n=0,maxmargin=0; uint32_t pval = 0; mindenom.Pval = PRICE_RESOLUTION; spread.Pval = PERCENTAGE(1); for (i=1; icontracts[baseid]->peggymils * 10000) / PEGS->contracts[relid]->peggymils; if ( strcmp(PEGS->contracts[baseid]->name.base,base) == 0 && strcmp(PEGS->contracts[relid]->name.base,rel) == 0 ) price.Pval = (PRICE_RESOLUTION * allprices[baseid]) / allprices[relid]; else printf("mismatched %p base.(%s) baseid.%d (%s) or %p rel.(%s) relid.%d (%s)\n",PEGS->contracts[baseid],PEGS->contracts[baseid]->name.base,baseid,base,PEGS->contracts[relid],PEGS->contracts[relid]->name.base,relid,rel); pval = (uint32_t)price.Pval; } else printf("peggy_genesis RAN out of space\n"); if ( (PEG= peggy_createpair(PEGS,0,0,name,base,rel,maxsupply,maxnetbalance,0,SATOSHIDEN*10,PEGGY_RATE_777,firsttimestamp,&price,1,spread,maxmargin,mindenom,i,iname.name,PEG->name.base,PEG->name.rel,Pval(&price),Pval(&x),pval,maxmargin,dstr(maxsupply),dstr(maxnetbalance),Pval(&spread),Pval(&mindenom),PEG->peggymils); n++; } } } struct peggy_info *peggy_genesis(int32_t lookbacks[OPRETURNS_CONTEXTS],struct peggy_info *PEGS,char *path,uint32_t firsttimestamp,char *opreturnstr) { //struct peggy_limits limits = { { PERCENTAGE(10), PERCENTAGE(25), PERCENTAGE(33), PERCENTAGE(50) }, SATOSHIDEN * 10000, SATOSHIDEN * 1000, { 0, 30, 90, 180 }, 4 }; uint8_t opret[1024]; struct peggy_tx Ptx; struct price_resolution spread; uint64_t len; long offset; int32_t i,signedcount,datalen,n=0,numprices,err=-1; numprices = 1; datalen = (int32_t)strlen(opreturnstr) / 2; decode_hex(opret,datalen,opreturnstr); printf("peggy_genesis(%s)\n",opreturnstr); if ( opret[0] == OP_RETURN_OPCODE ) { offset = hdecode_varint(&len,opret,1,sizeof(opret)); if ( opret[offset] == 'P' && opret[offset+1] == 'A' && opret[offset+2] == 'X' ) { printf("deser\n"); if ( (n= serdes777_deserialize(&signedcount,&Ptx,firsttimestamp,opret+offset+3,(int32_t)len-3)) > 0 ) { err = 0; for (i=0; iaccts = accts777_init(path,0); PEGS->genesis = opreturnstr, opreturnstr = 0; } } else printf("i.%d vs %d\n",i,Ptx.details.price.num); } else printf("deser got n.%d\n",n); } else printf("illegal opret.(%c%c%c)\n",opret[offset],opret[offset+1],opret[offset+2]); } else printf("opret[0] %d\n",opret[0]); if ( err < 0 || PEGS == 0 ) return(0); peggy_priceinits(PEGS,firsttimestamp,Ptx.details.price.feed); printf("genesis prices t%u vs %u\n",Ptx.timestamp,firsttimestamp); return(PEGS); } char *peggybase(uint32_t blocknum,uint32_t blocktimestamp) { int32_t nonz; struct peggy_info *PEGS = opreturns_context("peggy",0); if ( PEGS != 0 ) return(peggy_emitprices(&nonz,PEGS,blocktimestamp,PEGS->genesis != 0 ? 0 : PEGGY_MAXLOCKDAYS)); return(0); } char *peggypayments(uint32_t blocknum,uint32_t blocktimestamp) { int32_t peggy_payments(queue_t *PaymentsQ,struct opreturn_payment *payments,int32_t max,uint32_t currentblocknum,uint32_t blocknum,uint32_t blocktimestamp); struct opreturn_payment payments[8192]; cJSON *json; int32_t i,n; struct peggy_info *PEGS = opreturns_context("peggy",0); memset(payments,0,sizeof(payments)); if ( PEGS != 0 && PEGS->accts != 0 && (n= peggy_payments(&PEGS->accts->PaymentsQ,payments,sizeof(payments)/sizeof(*payments),blocknum,blocknum,blocktimestamp)) > 0 ) { json = cJSON_CreateObject(); for (i=0; igenesis != 0 ? 0 : PEGGY_MAXLOCKDAYS); if ( opreturnstr != 0 ) { printf("OPRETURN.(%s)\n",opreturnstr); //if ( Debuglevel > 2 ) printf("update.%d opreturns.(%s) t%u\n",PEGS->numopreturns,opreturnstr,timestamp); sprintf(fname,"opreturns/%d",PEGS->numopreturns); if ( (fp= fopen(fname,"wb")) != 0 ) { fwrite(opreturnstr,1,strlen(opreturnstr)+1,fp); fclose(fp); } if ( nonz == 64 && PEGS->genesis == 0 ) peggy_genesis(lookbacks,PEGS,PEGS->path,timestamp,opreturnstr); else { num = 1; peggylen = (int32_t)strlen(opreturnstr) / 2; decode_hex(opret,peggylen,opreturnstr); opreturns_process(1,PEGS->numopreturns,PEGS->numopreturns,timestamp,0,0,opret,peggylen); free(opreturnstr); PEGS->numopreturns++; } } } } uint64_t map_apr(uint64_t *spreadp,int32_t maxdays,double apr) { int64_t bestdiff,diff; int32_t i; uint64_t rate,bestsatoshis,satoshis,bestrate = 0,target; target = PRICE_RESOLUTION * (1. + apr/100.); bestrate = ((PRICE_RESOLUTION * log(apr)/10) / (365-1)); satoshis = peggy_compound(0,PRICE_RESOLUTION,bestrate,365); bestdiff = (satoshis - target); if ( bestdiff < 0 ) bestdiff = -bestdiff; //err = ((double)bestdiff / target); //n = (int32_t)(err * 4. * bestrate); //if ( n < 1000 ) // n = 1000; //printf("err %f %d: new bestdiff %llu, bestrate %llu, satoshis %.8f target %.8f\n",err,n,(long long)bestdiff,(long long)bestrate,(double)satoshis/PRICE_RESOLUTION,(double)target/PRICE_RESOLUTION); //for (i=0,rate=bestrate-n; rate<=bestrate+2*n; rate++,i++) for (i=0,rate=1; rate %llu, rate %llu -> %llu, satoshis %.8f target %.8f\n",i,n,(long long)bestdiff,(long long)diff,(long long)bestrate,(long long)rate,(double)satoshis/PRICE_RESOLUTION,(double)target/PRICE_RESOLUTION); bestdiff = diff, bestrate = rate, bestsatoshis = satoshis; if ( diff == 0 ) break; } } //printf("\nnew bestdiff %llu rate %llu, satoshis %.8f target %.8f\n",(long long)bestdiff,(long long)bestrate,(double)bestsatoshis/PRICE_RESOLUTION,(double)target/PRICE_RESOLUTION); *spreadp = PERCENTAGE((apr * maxdays)/365); return(bestrate); } uint64_t peggy_dailyrates() { //struct peggy_limits limits = { { PERCENTAGE(10), PERCENTAGE(25), PERCENTAGE(33), PERCENTAGE(50) }, SATOSHIDEN * 10000, SATOSHIDEN * 1000, { 0, 30, 90, 180 }, 4 }; uint64_t satoshis,maxspread; int64_t err,errsum; int32_t i,milliperc; dailyrates[0] = (int32_t)map_apr(&maxspread,PEGGY_MAXLOCKDAYS,(double)7770/1000); satoshis = peggy_compound(0,SATOSHIDEN,dailyrates[0],365); printf("%.2f%% %d %llu -> %llu %.2f%%\n",(double)7770/1000,dailyrates[0],(long long)SATOSHIDEN,(long long)satoshis,100. * ((double)(satoshis-SATOSHIDEN)/SATOSHIDEN)); for (errsum=i=0; i<=100; i++) { satoshis = peggy_compound(0,SATOSHIDEN,dailyrates[i],365); //printf("%.1f%%: %d %llu -> %llu %.3f%%\n",(double)i*.1,dailyrates[i],(long long)PRICE_RESOLUTION,(long long)satoshis,100. * (double)satoshis/PRICE_RESOLUTION - 100.); printf("%.2f%% ",100. * (double)satoshis/SATOSHIDEN - 100.); err = (satoshis - SATOSHIDEN) - (i == 0 ? 7770000 : i*100000); errsum += err < 0 ? -err : err; //printf("i.%d err %lld sum %lld\n",i,(long long)err,(long long)errsum); } errsum /= 101; printf("dailyrate check errsum %lld %f%% ave err\n",(long long)errsum,100*dstr(errsum)); if ( errsum > 10000 ) { //int32_t dailyrates[101]; for (milliperc=100; milliperc<=10000; milliperc+=100) { dailyrates[milliperc/100] = (int32_t)map_apr(&maxspread,PEGGY_MAXLOCKDAYS,(double)milliperc/1000); satoshis = peggy_compound(0,SATOSHIDEN,dailyrates[milliperc/100],365); printf("%.2f%% %d %llu -> %llu %.3f%%\n",(double)milliperc/1000,dailyrates[milliperc/100],(long long)SATOSHIDEN,(long long)satoshis,100. * ((double)(satoshis-SATOSHIDEN)/SATOSHIDEN)); } for (i=0; i<=100; i++) printf("%d, ",dailyrates[i]); printf("dailyrates in 0.1%% incr\n"); printf("root.%lld resolution.%lld squared.%llu maxPval.%llu maxunits.%d\n",(long long)PRICE_RESOLUTION_ROOT,(long long)PRICE_RESOLUTION,(long long)PRICE_RESOLUTION2,(long long)PRICE_RESOLUTION_MAXPVAL,PRICE_RESOLUTION_MAXUNITS); } return(errsum); } void *peggy_replay(char *path,struct txinds777_info *opreturns,void *_PEGS,uint32_t blocknum,char *opreturnstr,uint8_t *data,int32_t datalen) { int32_t lookbacks[OPRETURNS_CONTEXTS]; long allocsize; uint64_t len; int32_t n,signedcount,valid=0; long offset; struct price_resolution tmp; char fname[512]; uint8_t opret[8192]; struct peggy_tx Ptx; struct peggy_info *PEGS = _PEGS; if ( blocknum == 0 ) opreturnstr = PEGGY_GENESIS; //printf("replay genesis.%p opreturnstr.%p data.%p\n",PEGGY_GENESIS,opreturnstr,data); if ( data == 0 ) { data = opret; if ( opreturnstr == 0 ) { sprintf(fname,"%s/%d",path,blocknum); if ( (opreturnstr= OS_filestr(&allocsize,fname)) != 0 ) { //printf("loaded.(%s) %s\n",fname,opreturnstr); if ( is_hexstr(opreturnstr,(int32_t)strlen(opreturnstr)) != 0 ) valid = 1; } //else printf("couldnt find.(%s)\n",fname); } else valid = 1; if ( valid != 0 ) { datalen = (int32_t)strlen(opreturnstr) / 2; decode_hex(opret,datalen,opreturnstr); } else return(0); } if ( data != 0 && data[0] == OP_RETURN_OPCODE ) { offset = hdecode_varint(&len,data,1,sizeof(opret)); if ( data[offset] == 'P' && data[offset+1] == 'A' && data[offset+2] == 'X' ) { if ( (n= serdes777_deserialize(&signedcount,&Ptx,0,&data[offset+3],(int32_t)(len - 3))) < 0 ) printf("peggy_process.%d peggy_deserialize error datalen.%d t%d\n",blocknum,datalen,Ptx.timestamp); else { int32_t j,nonz = 0; for (j=0; j PEGS->genesistime ) { Ptx.flags |= PEGGY_FLAGS_PEGGYBASE; if ( peggy_process(PEGS,1,&Ptx.funding.src.coinaddr,Ptx.funding.amount,&data[offset+3],(int32_t)len-3,blocknum,Ptx.timestamp,blocknum) < 0 ) { printf("error processing blocknum.%u Ptx.blocknum %u\n",blocknum,blocknum); } } if ( PEGS != 0 ) PEGS->numopreturns++; } } else printf("illegal.(%c%c%c)\n",data[offset],data[offset+1],data[offset+2]); } else printf("missing OP_RETURN_OPCODE [%02x]\n",data[0]); return(PEGS); } uint32_t peggy_currentblock(void *_PEGS) { struct peggy_info *PEGS; if ( (PEGS= _PEGS) != 0 ) return(PEGS->numopreturns); return(0); } void peggy_geninds() { int32_t inds[PEGGY_NUMCOEFFS],tmp,i,n = PEGGY_NUMCOEFFS; for (i=0; i 0 ) { i = ((rand() >> 8) % n); //printf("(n.%d [%d] i.%d [%d]) ",n,inds[n],i,inds[i]); n--; tmp = inds[n]; inds[n] = inds[i]; inds[i] = tmp; } for (i=0; inumopreturns,(OS_milliseconds() - startmilli)/PEGS->numopreturns);// getchar(); return(PEGS); } int32_t peggy_init_contexts(struct txinds777_info *opreturns,uint32_t RTblocknum,uint32_t RTblocktimestamp,char *path,void *globals[OPRETURNS_CONTEXTS],int32_t lookbacks[OPRETURNS_CONTEXTS],int32_t maxcontexts) { /* double startmilli; char buf[512]; struct price_resolution spread; struct peggy_info *PEGS=0,*PEGS2=0; if ( maxcontexts != 2 ) { printf("peggy needs 2 contexts\n"); exit(-1); } calc_smooth_code(127,7); if ( sizeof(Peggy_inds)/sizeof(*Peggy_inds) != PEGGY_NUMCOEFFS ) { peggy_geninds(); printf("need to update Peggy_inds with above\n"); exit(-1); } peggy_dailyrates(); spread.Pval = PERCENTAGE(1); //if ( (PEGS= peggy_lchain(opreturns,"opreturns")) == 0 ) PEGS = peggy_init(path,PEGGY_MAXLOCKDAYS,"BTCD",SATOSHIDEN/100,100,10,spread,PEGGY_RATE_777,40,10,2,5,2,0,0); globals[0] = PEGS; sprintf(buf,"%s_PERM",path); globals[1] = PEGS2 = peggy_init(buf,PEGGY_MAXLOCKDAYS,"BTCD",SATOSHIDEN/100,1,1,spread,PEGGY_RATE_777,40,10,2,5,2,PEGS->genesistime,PEGS->BTCD_price0); startmilli = OS_milliseconds(); peggy_clone(buf,PEGS2,PEGS); printf("cloned %d in %.3f millis per opreturn\n",PEGS->numopreturns,(OS_milliseconds() - startmilli)/PEGS->numopreturns); sleep(3);*/ return(2); } void peggy_indsinit() { if ( sizeof(Peggy_inds)/sizeof(*Peggy_inds) != PEGGY_NUMCOEFFS ) { peggy_geninds(); printf("need to update Peggy_inds with above\n"); iguana_exit(0,0); } peggy_dailyrates(); }