]>
Commit | Line | Data |
---|---|---|
d019c447 | 1 | /****************************************************************************** |
2 | * Copyright © 2014-2016 The SuperNET Developers. * | |
3 | * * | |
4 | * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * | |
5 | * the top-level directory of this distribution for the individual copyright * | |
6 | * holder information and the developer policies on copyright and licensing. * | |
7 | * * | |
8 | * Unless otherwise agreed in a custom licensing agreement, no part of the * | |
9 | * SuperNET software, including this file may be copied, modified, propagated * | |
10 | * or distributed except according to the terms contained in the LICENSE file * | |
11 | * * | |
12 | * Removal or modification of this copyright notice is prohibited. * | |
13 | * * | |
14 | ******************************************************************************/ | |
1e81ccb7 | 15 | |
16 | int32_t NUM_PRICES; uint32_t *PVALS; | |
17 | ||
41a4a4db | 18 | #define USD 0 |
19 | ||
1e81ccb7 | 20 | #define MAX_CURRENCIES 32 |
21 | char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies | |
22 | "CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", | |
23 | "KMD" }; | |
24 | ||
a4ebaad7 | 25 | uint64_t M1SUPPLY[] = { 3317900000000, 6991604000000, 667780000000000, 1616854000000, 331000000000, 861909000000, 584629000000, 46530000000, // major currencies |
05dfe053 | 26 | 45434000000000, 16827000000000, 3473357229000, 306435000000, 27139000000000, 2150641000000, 347724099000, 1469583000000, 749543000000, 1826110000000, 2400434000000, 1123925000000, 3125276000000, 13975000000000, 317657000000, 759706000000000, 354902000000, 2797061000000, 162189000000, 163745000000, 1712000000000, 39093000000, 1135490000000000, 80317000000, |
a4ebaad7 | 27 | 100000000 }; |
28 | ||
29 | #define MIND 1000 | |
30 | uint32_t MINDENOMS[] = { MIND, MIND, 100*MIND, MIND, MIND, MIND, MIND, MIND, // major currencies | |
31 | 10*MIND, 100*MIND, 10*MIND, MIND, 100*MIND, 10*MIND, MIND, 10*MIND, MIND, 10*MIND, 10*MIND, 10*MIND, 10*MIND, 100*MIND, MIND, 1000*MIND, MIND, 10*MIND, MIND, MIND, 10*MIND, MIND, 10000*MIND, 10*MIND, // end of currencies | |
32 | 10*MIND, | |
1e81ccb7 | 33 | }; |
34 | ||
ab6984e9 | 35 | uint64_t komodo_paxvol(uint64_t volume,uint64_t price) |
36 | { | |
37 | if ( volume < 10000000000 ) | |
38 | return((volume * price) / 1000000000); | |
39 | else if ( volume < (uint64_t)10 * 10000000000 ) | |
40 | return((volume * (price / 10)) / 100000000); | |
41 | else if ( volume < (uint64_t)100 * 10000000000 ) | |
42 | return(((volume / 10) * (price / 10)) / 10000000); | |
43 | else if ( volume < (uint64_t)1000 * 10000000000 ) | |
44 | return(((volume / 10) * (price / 100)) / 1000000); | |
45 | else if ( volume < (uint64_t)10000 * 10000000000 ) | |
46 | return(((volume / 100) * (price / 100)) / 100000); | |
47 | else if ( volume < (uint64_t)100000 * 10000000000 ) | |
48 | return(((volume / 100) * (price / 1000)) / 10000); | |
49 | else if ( volume < (uint64_t)1000000 * 10000000000 ) | |
50 | return(((volume / 1000) * (price / 1000)) / 1000); | |
51 | else if ( volume < (uint64_t)10000000 * 10000000000 ) | |
52 | return(((volume / 1000) * (price / 10000)) / 100); | |
53 | else return(((volume / 10000) * (price / 10000)) / 10); | |
54 | } | |
55 | ||
a4ebaad7 | 56 | void pax_rank(uint64_t *ranked,uint32_t *pvals) |
57 | { | |
58 | int32_t i; uint64_t vals[32],sum = 0; | |
59 | for (i=0; i<32; i++) | |
60 | { | |
61 | vals[i] = komodo_paxvol(M1SUPPLY[i] / MINDENOMS[i],pvals[i]); | |
62 | sum += vals[i]; | |
63 | } | |
64 | for (i=0; i<32; i++) | |
65 | { | |
66 | ranked[i] = (vals[i] * 1000000000) / sum; | |
56d91e9c | 67 | //printf("%.6f ",(double)ranked[i]/1000000000.); |
a4ebaad7 | 68 | } |
56d91e9c | 69 | //printf("sum %llu\n",(long long)sum); |
a4ebaad7 | 70 | }; |
71 | ||
1e81ccb7 | 72 | int32_t dpow_readprices(uint8_t *data,uint32_t *timestampp,double *KMDBTCp,double *BTCUSDp,double *CNYUSDp,uint32_t *pvals) |
73 | { | |
1bf82154 | 74 | uint32_t kmdbtc,btcusd,cnyusd; int32_t i,n,nonz,len = 0; |
0201d1a6 | 75 | if ( data[0] == 'P' && data[5] == 35 ) |
76 | data++; | |
1e81ccb7 | 77 | len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)timestampp); |
78 | len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&n); | |
7eca18ee | 79 | if ( n != 35 ) |
7d59e5c9 | 80 | { |
81 | printf("dpow_readprices illegal n.%d\n",n); | |
82 | return(-1); | |
83 | } | |
1e81ccb7 | 84 | len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&kmdbtc); // /= 1000 |
85 | len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&btcusd); // *= 1000 | |
86 | len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&cnyusd); | |
87 | *KMDBTCp = ((double)kmdbtc / (1000000000. * 1000.)); | |
88 | *BTCUSDp = ((double)btcusd / (1000000000. / 1000.)); | |
89 | *CNYUSDp = ((double)cnyusd / 1000000000.); | |
1bf82154 | 90 | for (i=nonz=0; i<n-3; i++) |
1e81ccb7 | 91 | { |
1bf82154 | 92 | if ( pvals[i] != 0 ) |
93 | nonz++; | |
49df008c | 94 | //else if ( nonz != 0 ) |
95 | // printf("pvals[%d] is zero\n",i); | |
1e81ccb7 | 96 | len += iguana_rwnum(0,&data[len],sizeof(uint32_t),(void *)&pvals[i]); |
97 | //printf("%u ",pvals[i]); | |
98 | } | |
1bf82154 | 99 | if ( nonz < n-3 ) |
ef7b1ba6 | 100 | { |
49df008c | 101 | //printf("nonz.%d n.%d retval -1\n",nonz,n); |
1bf82154 | 102 | return(-1); |
ef7b1ba6 | 103 | } |
1e81ccb7 | 104 | pvals[i++] = kmdbtc; |
105 | pvals[i++] = btcusd; | |
106 | pvals[i++] = cnyusd; | |
107 | //printf("OP_RETURN prices\n"); | |
108 | return(n); | |
109 | } | |
110 | ||
d019c447 | 111 | int32_t komodo_pax_opreturn(uint8_t *opret,int32_t maxsize) |
112 | { | |
113 | static uint32_t lastcrc; | |
d351e231 | 114 | FILE *fp; char fname[512]; uint32_t crc32,check,timestamp; int32_t i,n=0,retval,fsize,len=0; uint8_t data[8192]; |
d019c447 | 115 | #ifdef WIN32 |
116 | sprintf(fname,"%s\\%s",GetDataDir(false).string().c_str(),(char *)"komodofeed"); | |
117 | #else | |
118 | sprintf(fname,"%s/%s",GetDataDir(false).string().c_str(),(char *)"komodofeed"); | |
119 | #endif | |
120 | if ( (fp= fopen(fname,"rb")) != 0 ) | |
121 | { | |
122 | fseek(fp,0,SEEK_END); | |
123 | fsize = (int32_t)ftell(fp); | |
124 | rewind(fp); | |
125 | if ( fsize <= maxsize-4 && fsize <= sizeof(data) && fsize > sizeof(crc32) ) | |
126 | { | |
127 | if ( (retval= (int32_t)fread(data,1,fsize,fp)) == fsize ) | |
128 | { | |
129 | len = iguana_rwnum(0,data,sizeof(crc32),(void *)&crc32); | |
130 | check = calc_crc32(0,data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); | |
131 | if ( check == crc32 ) | |
132 | { | |
133 | double KMDBTC,BTCUSD,CNYUSD; uint32_t pvals[128]; | |
1bf82154 | 134 | if ( dpow_readprices(&data[len],×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals) > 0 ) |
d019c447 | 135 | { |
d019c447 | 136 | if ( 0 && lastcrc != crc32 ) |
137 | { | |
1bf82154 | 138 | for (i=0; i<32; i++) |
139 | printf("%u ",pvals[i]); | |
140 | printf("t%u n.%d KMD %f BTC %f CNY %f (%f)\n",timestamp,n,KMDBTC,BTCUSD,CNYUSD,CNYUSD!=0?1./CNYUSD:0); | |
d019c447 | 141 | } |
1bf82154 | 142 | if ( timestamp > time(NULL)-600 ) |
143 | { | |
144 | n = komodo_opreturnscript(opret,'P',data+sizeof(crc32),(int32_t)(fsize-sizeof(crc32))); | |
145 | if ( 0 && lastcrc != crc32 ) | |
146 | { | |
147 | for (i=0; i<n; i++) | |
148 | printf("%02x",opret[i]); | |
149 | printf(" coinbase opret[%d] crc32.%u:%u\n",n,crc32,check); | |
150 | } | |
151 | } //else printf("t%u too old for %u\n",timestamp,(uint32_t)time(NULL)); | |
152 | lastcrc = crc32; | |
153 | } | |
d019c447 | 154 | } else printf("crc32 %u mismatch %u\n",crc32,check); |
155 | } else printf("fread.%d error != fsize.%d\n",retval,fsize); | |
156 | } else printf("fsize.%d > maxsize.%d or data[%d]\n",fsize,maxsize,(int32_t)sizeof(data)); | |
157 | fclose(fp); | |
158 | } | |
159 | return(n); | |
160 | } | |
161 | ||
1e81ccb7 | 162 | /*uint32_t PAX_val32(double val) |
163 | { | |
164 | uint32_t val32 = 0; struct price_resolution price; | |
165 | if ( (price.Pval= val*1000000000) != 0 ) | |
166 | { | |
167 | if ( price.Pval > 0xffffffff ) | |
168 | printf("Pval overflow error %lld\n",(long long)price.Pval); | |
169 | else val32 = (uint32_t)price.Pval; | |
170 | } | |
171 | return(val32); | |
172 | }*/ | |
173 | ||
57abdbaf | 174 | int32_t PAX_pubkey(int32_t rwflag,uint8_t *pubkey33,uint8_t *addrtypep,uint8_t rmd160[20],char fiat[4],uint8_t *shortflagp,int64_t *fiatoshisp) |
d019c447 | 175 | { |
57abdbaf | 176 | if ( rwflag != 0 ) |
177 | { | |
178 | memset(pubkey33,0,33); | |
179 | pubkey33[0] = 0x02 | (*shortflagp != 0); | |
180 | memcpy(&pubkey33[1],fiat,3); | |
181 | iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); | |
182 | pubkey33[12] = *addrtypep; | |
183 | memcpy(&pubkey33[13],rmd160,20); | |
184 | } | |
185 | else | |
186 | { | |
187 | *shortflagp = (pubkey33[0] == 0x03); | |
188 | memcpy(fiat,&pubkey33[1],4); | |
189 | iguana_rwnum(rwflag,&pubkey33[4],sizeof(*fiatoshisp),(void *)fiatoshisp); | |
190 | if ( *shortflagp != 0 ) | |
191 | *fiatoshisp = -(*fiatoshisp); | |
192 | *addrtypep = pubkey33[12]; | |
193 | memcpy(rmd160,&pubkey33[13],20); | |
194 | } | |
d351e231 | 195 | return(33); |
d019c447 | 196 | } |
197 | ||
1e81ccb7 | 198 | double PAX_val(uint32_t pval,int32_t baseid) |
199 | { | |
200 | //printf("PAX_val baseid.%d pval.%u\n",baseid,pval); | |
201 | if ( baseid >= 0 && baseid < MAX_CURRENCIES ) | |
202 | return(((double)pval / 1000000000.) / MINDENOMS[baseid]); | |
203 | return(0.); | |
204 | } | |
205 | ||
206 | void komodo_pvals(int32_t height,uint32_t *pvals,uint8_t numpvals) | |
207 | { | |
5c481612 | 208 | int32_t i,nonz; uint32_t kmdbtc,btcusd,cnyusd; double KMDBTC,BTCUSD,CNYUSD; |
1e81ccb7 | 209 | if ( numpvals >= 35 ) |
210 | { | |
211 | for (nonz=i=0; i<32; i++) | |
212 | { | |
213 | if ( pvals[i] != 0 ) | |
214 | nonz++; | |
215 | //printf("%u ",pvals[i]); | |
216 | } | |
217 | if ( nonz == 32 ) | |
218 | { | |
219 | kmdbtc = pvals[i++]; | |
220 | btcusd = pvals[i++]; | |
221 | cnyusd = pvals[i++]; | |
5c481612 | 222 | KMDBTC = ((double)kmdbtc / (1000000000. * 1000.)); |
223 | BTCUSD = ((double)btcusd / (1000000000. / 1000.)); | |
224 | CNYUSD = ((double)cnyusd / 1000000000.); | |
1e81ccb7 | 225 | PVALS = (uint32_t *)realloc(PVALS,(NUM_PRICES+1) * sizeof(*PVALS) * 36); |
226 | PVALS[36 * NUM_PRICES] = height; | |
227 | memcpy(&PVALS[36 * NUM_PRICES + 1],pvals,sizeof(*pvals) * 35); | |
228 | NUM_PRICES++; | |
5c481612 | 229 | if ( 0 ) |
230 | printf("OP_RETURN.%d KMD %.8f BTC %.6f CNY %.6f NUM_PRICES.%d (%llu %llu %llu)\n",height,KMDBTC,BTCUSD,CNYUSD,NUM_PRICES,(long long)kmdbtc,(long long)btcusd,(long long)cnyusd); | |
1e81ccb7 | 231 | } |
232 | } | |
233 | } | |
234 | ||
235 | int32_t komodo_baseid(char *origbase) | |
236 | { | |
237 | int32_t i; char base[64]; | |
238 | for (i=0; origbase[i]!=0&&i<sizeof(base); i++) | |
239 | base[i] = toupper((int32_t)(origbase[i] & 0xff)); | |
240 | base[i] = 0; | |
241 | for (i=0; i<=MAX_CURRENCIES; i++) | |
242 | if ( strcmp(CURRENCIES[i],base) == 0 ) | |
243 | return(i); | |
244 | printf("illegal base.(%s) %s\n",origbase,base); | |
245 | return(-1); | |
246 | } | |
247 | ||
d019c447 | 248 | uint64_t komodo_paxcalc(uint32_t *pvals,int32_t baseid,int32_t relid,uint64_t basevolume) |
a4ebaad7 | 249 | { |
d351e231 | 250 | uint32_t pvalb,pvalr,kmdbtc,btcusd; uint64_t usdvol,baseusd,usdkmd,baserel,ranked[32]; |
3ba8f923 | 251 | if ( basevolume > 1000000*COIN ) |
2e4514ce | 252 | return(0); |
a4ebaad7 | 253 | if ( (pvalb= pvals[baseid]) != 0 ) |
254 | { | |
255 | if ( relid == MAX_CURRENCIES ) | |
256 | { | |
257 | kmdbtc = pvals[MAX_CURRENCIES]; | |
258 | btcusd = pvals[MAX_CURRENCIES + 1]; | |
259 | if ( pvals[USD] != 0 && kmdbtc != 0 && btcusd != 0 ) | |
260 | { | |
261 | baseusd = ((uint64_t)pvalb * 1000000000) / pvals[USD]; | |
74fcb540 | 262 | usdvol = komodo_paxvol(basevolume,baseusd) / MINDENOMS[baseid]; |
048ae852 | 263 | usdkmd = ((uint64_t)btcusd * 1000000000) / kmdbtc; |
a4ebaad7 | 264 | //printf("base -> USD %llu, BTC %llu KMDUSD %llu\n",(long long)baseusd,(long long)btcusd,(long long)kmdusd); |
048ae852 | 265 | printf("usdkmd.%llu basevolume.%llu baseusd.%llu paxvol.%llu usdvol.%llu\n",(long long)usdkmd,(long long)basevolume,(long long)baseusd,(long long)komodo_paxvol(basevolume,baseusd),(long long)usdvol); |
74fcb540 | 266 | return(MINDENOMS[USD] * komodo_paxvol(usdvol,usdkmd)); |
a4ebaad7 | 267 | } |
268 | } | |
269 | else if ( baseid == relid ) | |
270 | { | |
56d91e9c | 271 | if ( baseid != MAX_CURRENCIES ) |
272 | { | |
273 | pax_rank(ranked,pvals); | |
d836ec3f | 274 | return(10 * ranked[baseid]); // map to percentage |
56d91e9c | 275 | } |
a4ebaad7 | 276 | } |
277 | else if ( (pvalr= pvals[relid]) != 0 ) | |
278 | { | |
279 | baserel = ((uint64_t)pvalb * 1000000000) / pvalr; | |
d019c447 | 280 | return(komodo_paxvol(basevolume,baserel)); |
a4ebaad7 | 281 | } |
282 | } | |
08ef004d | 283 | return(0); |
a4ebaad7 | 284 | } |
285 | ||
d019c447 | 286 | uint64_t komodo_paxprice(int32_t height,char *base,char *rel,uint64_t basevolume) |
1e81ccb7 | 287 | { |
c149d44c | 288 | int32_t baseid=-1,relid=-1,i; uint32_t *ptr; |
1e81ccb7 | 289 | if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) |
290 | { | |
291 | for (i=NUM_PRICES-1; i>=0; i--) | |
292 | { | |
293 | ptr = &PVALS[36 * i]; | |
294 | if ( *ptr < height ) | |
d019c447 | 295 | return(komodo_paxcalc(&ptr[1],baseid,relid,basevolume)); |
1e81ccb7 | 296 | } |
297 | } else printf("paxprice invalid base.%s %d, rel.%s %d\n",base,baseid,rel,relid); | |
298 | return(0); | |
299 | } | |
300 | ||
d836ec3f | 301 | int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel) |
a4ebaad7 | 302 | { |
b20a5d7f | 303 | int32_t baseid=-1,relid=-1,i,num = 0; uint32_t *ptr; |
a4ebaad7 | 304 | if ( (baseid= komodo_baseid(base)) >= 0 && (relid= komodo_baseid(rel)) >= 0 ) |
305 | { | |
306 | for (i=NUM_PRICES-1; i>=0; i--) | |
307 | { | |
308 | ptr = &PVALS[36 * i]; | |
56d91e9c | 309 | heights[num] = *ptr; |
310 | prices[num] = komodo_paxcalc(&ptr[1],baseid,relid,COIN); | |
311 | num++; | |
312 | if ( num >= max ) | |
313 | return(num); | |
a4ebaad7 | 314 | } |
315 | } | |
56d91e9c | 316 | return(num); |
a4ebaad7 | 317 | } |
318 | ||
cd1fcb48 | 319 | void komodo_paxpricefeed(int32_t height,uint8_t *pricefeed,int32_t opretlen) |
47e5cbc1 | 320 | { |
321 | double KMDBTC,BTCUSD,CNYUSD; uint32_t numpvals,timestamp,pvals[128]; uint256 zero; | |
322 | numpvals = dpow_readprices(pricefeed,×tamp,&KMDBTC,&BTCUSD,&CNYUSD,pvals); | |
323 | memset(&zero,0,sizeof(zero)); | |
30df2e00 | 324 | komodo_stateupdate(height,0,0,0,zero,0,0,pvals,numpvals,0,0,0,0); |
47e5cbc1 | 325 | printf("komodo_paxpricefeed vout OP_RETURN.%d prices numpvals.%d opretlen.%d\n",height,numpvals,opretlen); |
326 | } | |
327 | ||
d95bcb64 | 328 | uint64_t PAX_fiatdest(int32_t tokomodo,char *destaddr,uint8_t pubkey33[33],char *coinaddr,int32_t height,char *origbase,int64_t fiatoshis) |
1e81ccb7 | 329 | { |
7c6f8298 | 330 | uint8_t shortflag = 0; char base[4]; int32_t i,baseid; uint8_t addrtype,rmd160[20]; uint64_t komodoshis = 0; |
331 | if ( (baseid= komodo_baseid(origbase)) < 0 || baseid == MAX_CURRENCIES ) | |
d019c447 | 332 | return(0); |
3ba8f923 | 333 | for (i=0; i<3; i++) |
334 | base[i] = toupper(origbase[i]); | |
335 | base[i] = 0; | |
30e79ca6 | 336 | if ( fiatoshis < 0 ) |
337 | shortflag = 1, fiatoshis = -fiatoshis; | |
3ba8f923 | 338 | komodoshis = komodo_paxprice(height,base,(char *)"KMD",(uint64_t)fiatoshis); |
d019c447 | 339 | if ( bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr) == 20 ) |
1e81ccb7 | 340 | { |
7c6f8298 | 341 | PAX_pubkey(1,pubkey33,&addrtype,rmd160,base,&shortflag,tokomodo != 0 ? &komodoshis : &fiatoshis); |
d019c447 | 342 | bitcoin_address(destaddr,KOMODO_PUBTYPE,pubkey33,33); |
1e81ccb7 | 343 | } |
d019c447 | 344 | return(komodoshis); |
1e81ccb7 | 345 | } |