]> Git Repo - VerusCoin.git/blob - src/komodo_gateway.h
test
[VerusCoin.git] / src / komodo_gateway.h
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  ******************************************************************************/
15
16 // paxdeposit equivalent in reverse makes opreturn and KMD does the same in reverse
17
18 int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base)
19 {
20     int32_t baseid; struct komodo_state *sp; int64_t netliability,maxallowed;
21     *available = *deposited = *issued = *withdrawn = *approved = *redeemed = 0;
22     if ( (baseid= komodo_baseid(base)) >= 0 )
23     {
24         if ( (sp= komodo_stateptrget(base)) != 0 )
25         {
26             *deposited = sp->deposited;
27             *issued = sp->issued;
28             *withdrawn = sp->withdrawn;
29             *approved = sp->approved;
30             *redeemed = sp->redeemed;
31             netliability = (sp->deposited - sp->withdrawn) - sp->shorted;
32             maxallowed = komodo_maxallowed(baseid);
33             if ( netliability < maxallowed )
34                 *available = (maxallowed - netliability);
35             //printf("%p %s %.8f %.8f %.8f %.8f %.8f\n",sp,base,dstr(*deposited),dstr(*issued),dstr(*withdrawn),dstr(*approved),dstr(*redeemed));
36             return(0);
37         } else printf("pax_fiatstatus cant get basesp.%s\n",base);
38     } else printf("pax_fiatstatus illegal base.%s\n",base);
39     return(-1);
40 }
41
42 void pax_keyset(uint8_t *buf,uint256 txid,uint16_t vout,uint8_t type)
43 {
44     memcpy(buf,&txid,32);
45     memcpy(&buf[32],&vout,2);
46     buf[34] = type;
47 }
48
49 struct pax_transaction *komodo_paxfind(uint256 txid,uint16_t vout,uint8_t type)
50 {
51     struct pax_transaction *pax; uint8_t buf[35];
52     pthread_mutex_lock(&komodo_mutex);
53     pax_keyset(buf,txid,vout,type);
54     HASH_FIND(hh,PAX,buf,sizeof(buf),pax);
55     pthread_mutex_unlock(&komodo_mutex);
56     return(pax);
57 }
58
59 struct pax_transaction *komodo_paxfinds(uint256 txid,uint16_t vout)
60 {
61     struct pax_transaction *pax; int32_t i; uint8_t types[] = { 'D', 'I', 'W', 'A', 'X' };
62     for (i=0; i<sizeof(types)/sizeof(*types); i++)
63         if ( (pax= komodo_paxfind(txid,vout,types[i])) != 0 )
64             return(pax);
65     return(0);
66 }
67
68 struct pax_transaction *komodo_paxmark(int32_t height,uint256 txid,uint16_t vout,uint8_t type,int32_t mark)
69 {
70     struct pax_transaction *pax; uint8_t buf[35];
71     pthread_mutex_lock(&komodo_mutex);
72     pax_keyset(buf,txid,vout,type);
73     HASH_FIND(hh,PAX,buf,sizeof(buf),pax);
74     if ( pax == 0 )
75     {
76         pax = (struct pax_transaction *)calloc(1,sizeof(*pax));
77         pax->txid = txid;
78         pax->vout = vout;
79         pax->type = type;
80         memcpy(pax->buf,buf,sizeof(pax->buf));
81         HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax);
82         //printf("ht.%d create pax.%p mark.%d\n",height,pax,mark);
83     }
84     if ( pax != 0 )
85         pax->marked = mark;
86     pthread_mutex_unlock(&komodo_mutex);
87     return(pax);
88 }
89
90 void komodo_gateway_deposit(char *coinaddr,uint64_t value,char *symbol,uint64_t fiatoshis,uint8_t *rmd160,uint256 txid,uint16_t vout,uint8_t type,int32_t height,int32_t otherheight,char *source,int32_t approved) // assetchain context
91 {
92     struct pax_transaction *pax; uint8_t buf[35]; int32_t addflag = 0; struct komodo_state *sp; char str[16],dest[16],*s;
93     sp = komodo_stateptr(str,dest);
94     pthread_mutex_lock(&komodo_mutex);
95     pax_keyset(buf,txid,vout,type);
96     HASH_FIND(hh,PAX,buf,sizeof(buf),pax);
97     if ( pax == 0 )
98     {
99         pax = (struct pax_transaction *)calloc(1,sizeof(*pax));
100         pax->txid = txid;
101         pax->vout = vout;
102         pax->type = type;
103         memcpy(pax->buf,buf,sizeof(pax->buf));
104         HASH_ADD_KEYPTR(hh,PAX,pax->buf,sizeof(pax->buf),pax);
105         addflag = 1;
106         if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 )
107         {
108             int32_t i; for (i=0; i<32; i++)
109                 printf("%02x",((uint8_t *)&txid)[i]);
110             printf(" v.%d [%s] kht.%d ht.%d create pax.%p symbol.%s source.%s\n",vout,ASSETCHAINS_SYMBOL,height,otherheight,pax,symbol,source);
111         }
112     }
113     pthread_mutex_unlock(&komodo_mutex);
114     if ( coinaddr != 0 )
115     {
116         strcpy(pax->coinaddr,coinaddr);
117         if ( value != 0 )
118             pax->komodoshis = value;
119         if ( symbol != 0 )
120             strcpy(pax->symbol,symbol);
121         if ( source != 0 )
122             strcpy(pax->source,source);
123         if ( fiatoshis != 0 )
124             pax->fiatoshis = fiatoshis;
125         if ( rmd160 != 0 )
126             memcpy(pax->rmd160,rmd160,20);
127         if ( height != 0 )
128             pax->height = height;
129         if ( otherheight != 0 )
130             pax->otherheight = otherheight;
131     }
132     else
133     {
134         pax->marked = height;
135         //printf("pax.%p MARK DEPOSIT ht.%d other.%d\n",pax,height,otherheight);
136     }
137 }
138
139 int32_t komodo_rwapproval(int32_t rwflag,uint8_t *opretbuf,struct pax_transaction *pax)
140 {
141     int32_t i,len = 0;
142     if ( rwflag == 1 )
143     {
144         for (i=0; i<32; i++)
145             opretbuf[len++] = ((uint8_t *)&pax->txid)[i];
146         opretbuf[len++] = pax->vout & 0xff;
147         opretbuf[len++] = (pax->vout >> 8) & 0xff;
148     }
149     else
150     {
151         for (i=0; i<32; i++)
152             ((uint8_t *)&pax->txid)[i] = opretbuf[len++];
153         //for (i=0; i<32; i++)
154         //    printf("%02x",((uint8_t *)&pax->txid)[31-i]);
155         pax->vout = opretbuf[len++];
156         pax->vout += ((uint32_t)opretbuf[len++] << 8);
157         //printf(" txid v.%d\n",pax->vout);
158     }
159     len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->komodoshis),&pax->komodoshis);
160     len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->fiatoshis),&pax->fiatoshis);
161     len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->height),&pax->height);
162     len += iguana_rwnum(rwflag,&opretbuf[len],sizeof(pax->otherheight),&pax->otherheight);
163     if ( rwflag != 0 )
164     {
165         memcpy(&opretbuf[len],pax->rmd160,20), len += 20;
166         for (i=0; i<4; i++)
167             opretbuf[len++] = pax->source[i];
168     }
169     else
170     {
171         memcpy(pax->rmd160,&opretbuf[len],20), len += 20;
172         for (i=0; i<4; i++)
173             pax->source[i] = opretbuf[len++];
174     }
175     return(len);
176 }
177
178 int32_t komodo_issued_opreturn(char *base,uint256 *txids,uint16_t *vouts,int64_t *values,int64_t *srcvalues,int32_t *kmdheights,int32_t *otherheights,int8_t *baseids,uint8_t *rmd160s,uint8_t *opretbuf,int32_t opretlen,int32_t iskomodo)
179 {
180     struct pax_transaction p,*pax; int32_t i,n=0,j,len=0,incr,height,otherheight; uint8_t type,rmd160[20]; uint64_t fiatoshis; char symbol[16];
181     incr = 34 + (iskomodo * (2*sizeof(fiatoshis) + 2*sizeof(height) + 20 + 4));
182     for (i=0; i<4; i++)
183         base[i] = opretbuf[opretlen-4+i];
184     //for (i=0; i<opretlen; i++)
185     //    printf("%02x",opretbuf[i]);
186     //printf(" opretlen.%d (%s)\n",opretlen,base);
187     //printf(" opretlen.%d vs %d incr.%d\n",opretlen,(int32_t)(2*sizeof(fiatoshis) + 2*sizeof(height) + 20 + 4),incr);
188     //if ( ASSETCHAINS_SYMBOL[0] == 0 || strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0 )
189     {
190         type = opretbuf[0];
191         opretbuf++, opretlen--;
192         for (n=0; n<opretlen/incr; n++)
193         {
194             if ( iskomodo != 0 )
195             {
196                 memset(&p,0,sizeof(p));
197                 len += komodo_rwapproval(0,&opretbuf[len],&p);
198                 if ( values != 0 && srcvalues != 0 && kmdheights != 0 && otherheights != 0 && baseids != 0 && rmd160s != 0 )
199                 {
200                     txids[n] = p.txid;
201                     vouts[n] = p.vout;
202                     values[n] = (strcmp("KMD",base) == 0) ? p.komodoshis : p.fiatoshis;
203                     srcvalues[n] = (strcmp("KMD",base) == 0) ? p.fiatoshis : p.komodoshis;
204                     kmdheights[n] = p.height;
205                     otherheights[n] = p.otherheight;
206                     memcpy(&rmd160s[n * 20],p.rmd160,20);
207                     baseids[n] = komodo_baseid(p.source);
208                     if ( 0 )
209                     {
210                         char coinaddr[64];
211                         bitcoin_address(coinaddr,60,&rmd160s[n * 20],20);
212                         printf(">>>>>>> %s: (%s) fiat %.8f kmdheight.%d other.%d -> %s %.8f\n",type=='A'?"approvedA":"issuedX",baseids[n]>=0?CURRENCIES[baseids[n]]:"???",dstr(p.fiatoshis),kmdheights[n],otherheights[n],coinaddr,dstr(values[n]));
213                     }
214                 }
215             }
216             else
217             {
218                 for (j=0; j<32; j++)
219                 {
220                     ((uint8_t *)&txids[n])[j] = opretbuf[len++];
221                     //printf("%02x",((uint8_t *)&txids[n])[j]);
222                 }
223                 vouts[n] = opretbuf[len++];
224                 vouts[n] = (opretbuf[len++] << 8) | vouts[n];
225                 baseids[n] = komodo_baseid(base);
226                 if ( (pax= komodo_paxfinds(txids[n],vouts[n])) != 0 )
227                 {
228                     values[n] = (strcmp("KMD",base) == 0) ? pax->komodoshis : pax->fiatoshis;
229                     srcvalues[n] = (strcmp("KMD",base) == 0) ? pax->fiatoshis : pax->komodoshis;
230                     kmdheights[n] = pax->height;
231                     otherheights[n] = pax->otherheight;
232                     memcpy(&rmd160s[n * 20],pax->rmd160,20);
233                 }
234             }
235             //printf(" komodo_issued_opreturn issuedtxid v%d i.%d opretlen.%d\n",vouts[n],n,opretlen);
236         }
237     }
238     return(n);
239 }
240
241 uint64_t komodo_paxtotal()
242 {
243     struct pax_transaction *pax,*pax2,*tmp,*tmp2; char symbol[16],dest[16],*str; int32_t i,ht; int64_t checktoshis; uint64_t seed,total = 0; struct komodo_state *basesp;
244     if ( komodo_isrealtime(&ht) == 0 )
245         return(0);
246     else
247     {
248         HASH_ITER(hh,PAX,pax,tmp)
249         {
250             if ( pax->type == 'A' || pax->type == 'D' || pax->type == 'X' )
251                 str = pax->symbol;
252             else str = pax->source;
253             basesp = komodo_stateptrget(str);
254             if ( basesp != 0 && pax->didstats == 0 )
255             {
256                 if ( pax->type == 'I' && (pax2= komodo_paxfind(pax->txid,pax->vout,pax->type == 'I' ? 'D' : 'W')) != 0 )
257                 {
258                     if ( pax2->fiatoshis != 0 )
259                     {
260                         pax->komodoshis = pax2->komodoshis;
261                         pax->fiatoshis = pax2->fiatoshis;
262                         basesp->issued += pax->fiatoshis;
263                         pax->didstats = 1;
264                         if ( strcmp(str,ASSETCHAINS_SYMBOL) == 0 )
265                             printf("########### %p issued %s += %.8f kmdheight.%d %.8f other.%d\n",basesp,str,dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight);
266                         pax2->marked = pax->height;
267                         pax->marked = pax->height;
268                     }
269                 }
270                 else if ( pax->type == 'W' )
271                 {
272                     printf("got WITHDRAW.%s kmd.%d ht.%d %.8f\n",str,pax->height,pax->otherheight,dstr(pax->fiatoshis));
273                 }
274             }
275         }
276     }
277     komodo_stateptr(symbol,dest);
278     HASH_ITER(hh,PAX,pax,tmp)
279     {
280         pax->ready = 0;
281         //printf("pax.%s marked.%d %.8f -> %.8f\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis));
282         if ( strcmp(symbol,pax->symbol) == 0 )
283         {
284             if ( pax->marked == 0 )
285             {
286                 if ( komodo_is_issuer() != 0 )
287                     total += pax->fiatoshis;
288                 else if ( pax->approved != 0 )
289                 {
290                     if ( pax->validated != 0 )
291                         total += pax->komodoshis;
292                     else
293                     {
294                         seed = 0;
295                         checktoshis = komodo_paxprice(&seed,pax->height,pax->source,(char *)"KMD",(uint64_t)pax->fiatoshis);
296                         //printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",pax->height,pax->symbol,(double)pax->fiatoshis/COIN,(double)pax->komodoshis/COIN,(double)checktoshis/COIN);
297                         //printf(" v%d %.8f k.%d ht.%d\n",pax->vout,dstr(pax->komodoshis),pax->height,pax->otherheight);
298                         if ( seed != 0 )
299                         {
300                             if ( checktoshis == pax->komodoshis )
301                             {
302                                 total += pax->komodoshis;
303                                 pax->validated = pax->komodoshis;
304                                 pax->ready = 1;
305                             } else pax->marked = pax->height;
306                         }
307                     }
308                 }
309             }
310         }
311     }
312     //printf("paxtotal %.8f\n",dstr(total));
313     return(total);
314 }
315
316 int32_t komodo_pending_withdraws(char *opretstr)
317 {
318     struct pax_transaction *pax,*tmp; uint8_t opretbuf[16384]; int32_t ht,len=0; uint64_t total = 0;
319     if ( komodo_isrealtime(&ht) == 0 || ASSETCHAINS_SYMBOL[0] != 0 )
320         return(0);
321     HASH_ITER(hh,PAX,pax,tmp)
322     {
323         //printf("pax %s marked.%u approved.%u\n",pax->symbol,pax->marked,pax->approved);
324         if ( pax->marked == 0 && strcmp((char *)"KMD",pax->symbol) == 0 && pax->approved == 0 )
325         {
326             // add 'A' opreturn entry
327             if ( len == 0 )
328                 opretbuf[len++] = 'A';
329             len += komodo_rwapproval(1,&opretbuf[len],pax);
330             //printf("%s.(marked.%u approved.%d) %p\n",pax->source,pax->marked,pax->approved,pax);
331         }
332     }
333     if ( len > 0 )
334         init_hexbytes_noT(opretstr,opretbuf,len);
335     else opretstr[0] = 0;
336     fprintf(stderr,"komodo_pending_withdraws len.%d PAXTOTAL %.8f\n",len,dstr(komodo_paxtotal()));
337     return(len);
338 }
339
340 int32_t komodo_gateway_deposits(CMutableTransaction *txNew,char *base,int32_t tokomodo)
341 {
342     struct pax_transaction *pax,*tmp; char symbol[16],dest[16]; uint8_t *script,opcode,opret[16384],data[16384]; int32_t i,baseid,ht,len=0,opretlen=0,numvouts=1; struct komodo_state *sp; uint64_t available,deposited,issued,withdrawn,approved,redeemed,mask;
343     sp = komodo_stateptr(symbol,dest);
344     strcpy(symbol,base);
345     PENDING_KOMODO_TX = 0;
346     if ( tokomodo == 0 )
347     {
348         opcode = 'I';
349         if ( komodo_isrealtime(&ht) == 0 )
350             return(0);
351     } else opcode = 'X';
352     HASH_ITER(hh,PAX,pax,tmp)
353     {
354         //printf("pax.%s marked.%d %.8f -> %.8f\n",pax->symbol,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis));
355         if ( strcmp(symbol,"KMD") == 0 && pax->approved == 0 )
356             continue;
357         //else if ( strcmp(symbol,"KMD") != 0 )
358         {
359 #ifdef KOMODO_ASSETCHAINS_WAITNOTARIZE
360             struct komodo_state *kmdsp = komodo_stateptrget((char *)"KMD");
361             if ( kmdsp != 0 && kmdsp->NOTARIZED_HEIGHT >= pax->height ) // assumes same chain as notarize
362                 pax->validated = pax->komodoshis; //kmdsp->NOTARIZED_HEIGHT;
363 #endif
364         }
365         if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis )
366         {
367             printf("miner: skip %s %.8f when avail %.8f\n",symbol,dstr(pax->fiatoshis),dstr(available));
368             continue;
369         }
370         if ( pax->marked != 0 )
371             continue;
372         if ( strcmp(pax->symbol,symbol) != 0 || pax->validated == 0 )
373         {
374             //printf("pax->symbol.%s != %s or null pax->validated %.8f\n",pax->symbol,symbol,dstr(pax->validated));
375             continue;
376         }
377         if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
378             printf("pax.%s marked.%d %.8f -> %.8f\n",ASSETCHAINS_SYMBOL,pax->marked,dstr(pax->komodoshis),dstr(pax->fiatoshis));
379         txNew->vout.resize(numvouts+1);
380         txNew->vout[numvouts].nValue = (opcode == 'I') ? pax->fiatoshis : pax->komodoshis;
381         txNew->vout[numvouts].scriptPubKey.resize(25);
382         script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0];
383         *script++ = 0x76;
384         *script++ = 0xa9;
385         *script++ = 20;
386         memcpy(script,pax->rmd160,20), script += 20;
387         *script++ = 0x88;
388         *script++ = 0xac;
389         if ( tokomodo == 0 )
390         {
391             for (i=0; i<32; i++)
392                 data[len++] = ((uint8_t *)&pax->txid)[i];
393             data[len++] = pax->vout & 0xff;
394             data[len++] = (pax->vout >> 8) & 0xff;
395             PENDING_KOMODO_TX += pax->fiatoshis;
396         }
397         else
398         {
399             len += komodo_rwapproval(1,&data[len],pax);
400             PENDING_KOMODO_TX += pax->komodoshis;
401             //printf(" vout.%u DEPOSIT %.8f <- pax.%s pending %.8f | ",pax->vout,(double)txNew->vout[numvouts].nValue/COIN,symbol,dstr(PENDING_KOMODO_TX));
402         }
403         if ( numvouts++ >= 64 )
404             break;
405     }
406     if ( numvouts > 1 )
407     {
408         if ( tokomodo != 0 )
409             strcpy(symbol,(char *)"KMD");
410         for (i=0; symbol[i]!=0; i++)
411             data[len++] = symbol[i];
412         data[len++] = 0;
413         opretlen = komodo_opreturnscript(opret,opcode,data,len);
414         txNew->vout.resize(numvouts+1);
415         txNew->vout[numvouts].nValue = 0;
416         txNew->vout[numvouts].scriptPubKey.resize(opretlen);
417         script = (uint8_t *)&txNew->vout[numvouts].scriptPubKey[0];
418         memcpy(script,opret,opretlen);
419         printf("MINER deposits.%d (%s) vouts.%d %.8f opretlen.%d\n",tokomodo,ASSETCHAINS_SYMBOL,numvouts,dstr(PENDING_KOMODO_TX),opretlen);
420         return(1);
421     }
422     return(0);
423 }
424
425 int32_t komodo_check_deposit(int32_t height,const CBlock& block) // verify above block is valid pax pricing
426 {
427     int32_t i,j,n,num,opretlen,offset=1,errs=0,matched=0,kmdheights[64],otherheights[64]; uint256 hash,txids[64]; char symbol[16],base[16]; uint16_t vouts[64]; int8_t baseids[64]; uint8_t *script,opcode,rmd160s[64*20]; uint64_t available,deposited,issued,withdrawn,approved,redeemed; int64_t values[64],srcvalues[64]; struct pax_transaction *pax;
428     memset(baseids,0xff,sizeof(baseids));
429     memset(values,0,sizeof(values));
430     memset(srcvalues,0,sizeof(srcvalues));
431     memset(rmd160s,0,sizeof(rmd160s));
432     memset(kmdheights,0,sizeof(kmdheights));
433     memset(otherheights,0,sizeof(otherheights));
434     n = block.vtx[0].vout.size();
435     script = (uint8_t *)block.vtx[0].vout[n-1].scriptPubKey.data();
436     if ( n <= 2 || script[0] != 0x6a )
437         return(0);
438     offset += komodo_scriptitemlen(&opretlen,&script[offset]);
439     if ( ASSETCHAINS_SYMBOL[0] == 0 )
440     {
441         //for (i=0; i<opretlen; i++)
442         //    printf("%02x",script[i]);
443         //printf(" height.%d checkdeposit n.%d [%02x] [%c] %d vs %d\n",height,n,script[0],script[offset],script[offset],'X');
444         opcode = 'X';
445         strcpy(symbol,(char *)"KMD");
446     }
447     else
448     {
449         strcpy(symbol,ASSETCHAINS_SYMBOL);
450         opcode = 'I';
451     }
452     if ( script[offset] == opcode && opretlen < block.vtx[0].vout[n-1].scriptPubKey.size() )
453     {
454         if ( (num= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,&script[offset],opretlen,opcode == 'X')) > 0 )
455         {
456             for (i=1; i<n-1; i++)
457             {
458                 if ( (pax= komodo_paxfinds(txids[i-1],vouts[i-1])) != 0 )
459                 {
460                     pax->type = opcode;
461                     if ( opcode == 'I' && pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,symbol) != 0 || available < pax->fiatoshis )
462                     {
463                         printf("checkdeposit: skip %s %.8f when avail %.8f\n",pax->symbol,dstr(pax->fiatoshis),dstr(available));
464                         continue;
465                     }
466                     if ( ((opcode == 'I' && (pax->fiatoshis == 0 || pax->fiatoshis == block.vtx[0].vout[i].nValue)) || (opcode == 'X' && (pax->komodoshis == 0 || pax->komodoshis == block.vtx[0].vout[i].nValue))) )
467                     {
468                         if ( pax->marked != 0 && height >= 80820 )
469                         {
470                             printf("%c errs.%d i.%d match %.8f vs %.8f pax.%p\n",opcode,errs,i,dstr(opcode == 'I' ? pax->fiatoshis : pax->komodoshis),dstr(block.vtx[0].vout[i].nValue),pax);
471                             errs++;
472                         } else matched++;
473                     }
474                     else
475                     {
476                         for (j=0; j<32; j++)
477                             printf("%02x",((uint8_t *)&txids[i-1])[j]);
478                         printf(" cant paxfind %c txid\n",opcode);
479                         printf("%c errs.%d i.%d match %.8f vs %.8f pax.%p\n",opcode,errs,i,dstr(opcode == 'I' ? pax->fiatoshis : pax->komodoshis),dstr(block.vtx[0].vout[i].nValue),pax);
480                     }
481                 }
482                 else
483                 {
484                     hash = block.GetHash();
485                     for (j=0; j<32; j++)
486                         printf("%02x",((uint8_t *)&hash)[j]);
487                     printf(" ht.%d blockhash X couldnt find vout.[%d]\n",height,i);
488                 }
489             }
490             if ( matched != num )
491             {
492                 printf("WOULD REJECT %s: ht.%d (%c) matched.%d vs num.%d\n",symbol,height,opcode,matched,num);
493                 // can easily happen depending on order of loading
494                 if ( height > 110000 ) //&& opcode == 'X' )
495                 {
496                     printf("REJECT: ht.%d (%c) matched.%d vs num.%d\n",height,opcode,matched,num);
497                     return(-1);
498                 }
499             }
500         }
501         //printf("opretlen.%d num.%d\n",opretlen,num);
502     }
503     return(0);
504 }
505
506 int32_t komodo_paxcmp(char *symbol,int32_t kmdheight,uint64_t value,uint64_t checkvalue,uint64_t seed)
507 {
508     int32_t ratio;
509     if ( seed == 0 && checkvalue != 0 )
510     {
511         ratio = ((value << 6) / checkvalue);
512         if ( ratio >= 63 && ratio <= 65 )
513             return(0);
514         else
515         {
516             if ( kmdheight >= 86150 )
517                 printf("ht.%d ignore mismatched %s value %lld vs checkvalue %lld -> ratio.%d\n",kmdheight,symbol,(long long)value,(long long)checkvalue,ratio);
518             return(-1);
519         }
520     }
521     else if ( checkvalue != 0 )
522     {
523         ratio = ((value << 10) / checkvalue);
524         if ( ratio >= 1023 && ratio <= 1025 )
525             return(0);
526     }
527     return(value != checkvalue);
528 }
529
530 const char *komodo_opreturn(int32_t height,uint64_t value,uint8_t *opretbuf,int32_t opretlen,uint256 txid,uint16_t vout,char *source)
531 {
532     uint8_t rmd160[20],rmd160s[64*20],addrtype,shortflag,pubkey33[33]; int32_t didstats,i,j,n,len,tokomodo,kmdheight,otherheights[64],kmdheights[64]; int8_t baseids[64]; char base[4],coinaddr[64],destaddr[64]; uint256 txids[64]; uint16_t vouts[64]; uint64_t convtoshis,seed; int64_t fiatoshis,komodoshis,checktoshis,values[64],srcvalues[64]; struct pax_transaction *pax,*pax2; struct komodo_state *basesp; double diff;
533     const char *typestr = "unknown";
534     memset(baseids,0xff,sizeof(baseids));
535     memset(values,0,sizeof(values));
536     memset(srcvalues,0,sizeof(srcvalues));
537     memset(rmd160s,0,sizeof(rmd160s));
538     memset(kmdheights,0,sizeof(kmdheights));
539     memset(otherheights,0,sizeof(otherheights));
540     tokomodo = (komodo_is_issuer() == 0);
541     if ( opretbuf[0] == 'D' )
542     {
543         tokomodo = 0;
544         if ( opretlen == 38 ) // any KMD tx
545         {
546             iguana_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight);
547             memset(base,0,sizeof(base));
548             PAX_pubkey(0,&opretbuf[1],&addrtype,rmd160,base,&shortflag,&fiatoshis);
549             bitcoin_address(coinaddr,addrtype,rmd160,20);
550             checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,kmdheight,base,fiatoshis);
551             typestr = "deposit";
552             if ( kmdheight <= height )
553             {
554                 didstats = 0;
555                 if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 )
556                 {
557                     printf("(%s) (%s) kmdheight.%d vs height.%d check %.8f vs %.8f tokomodo.%d %d seed.%llx\n",ASSETCHAINS_SYMBOL,base,kmdheight,height,dstr(checktoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed);
558                     for (i=0; i<32; i++)
559                         printf("%02x",((uint8_t *)&txid)[i]);
560                     printf(" <- txid.v%u ",vout);
561                     for (i=0; i<33; i++)
562                         printf("%02x",pubkey33[i]);
563                     printf(" checkpubkey check %.8f v %.8f dest.(%s) kmdheight.%d height.%d\n",dstr(checktoshis),dstr(value),destaddr,kmdheight,height);
564                 }
565                 if ( komodo_paxcmp(base,kmdheight,value,checktoshis,seed) == 0 )
566                 {
567                     if ( (pax= komodo_paxfind(txid,vout,'D')) == 0 )
568                     {
569                         if ( (basesp= komodo_stateptrget(base)) != 0 )
570                         {
571                             basesp->deposited += fiatoshis;
572                             didstats = 1;
573                             if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 )
574                                 printf("########### %p deposited %s += %.8f kmdheight.%d %.8f\n",basesp,base,dstr(fiatoshis),kmdheight,dstr(value));
575                         } else printf("cant get stateptr.(%s)\n",base);
576                         komodo_gateway_deposit(coinaddr,value,base,fiatoshis,rmd160,txid,vout,'D',kmdheight,height,(char *)"KMD",0);
577                     }
578                     if ( (pax= komodo_paxfind(txid,vout,'D')) != 0 )
579                     {
580                         pax->height = kmdheight;
581                         pax->validated = value;
582                         pax->komodoshis = value;
583                         pax->fiatoshis = fiatoshis;
584                         if ( didstats == 0 && pax->didstats == 0 )
585                         {
586                             if ( (basesp= komodo_stateptrget(base)) != 0 )
587                             {
588                                 basesp->deposited += fiatoshis;
589                                 didstats = 1;
590                                 if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 )
591                                     printf("########### %p deposited %s += %.8f/%.8f kmdheight.%d/%d %.8f/%.8f\n",basesp,base,dstr(fiatoshis),dstr(pax->fiatoshis),kmdheight,pax->height,dstr(value),dstr(pax->komodoshis));
592                             }
593                         }
594                         if ( didstats != 0 )
595                             pax->didstats = 1;
596                         if ( (pax2= komodo_paxfind(txid,vout,'I')) != 0 )
597                         {
598                             pax2->fiatoshis = pax->fiatoshis;
599                             pax2->komodoshis = pax->komodoshis;
600                             pax->marked = pax2->marked = pax->height;
601                             pax->otherheight = height;
602                             if ( pax2->didstats == 0 )
603                             {
604                                 if ( (basesp= komodo_stateptrget(base)) != 0 )
605                                 {
606                                     basesp->issued += pax2->fiatoshis;
607                                     pax2->didstats = 1;
608                                     if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 )
609                                         printf("########### %p issueda %s += %.8f kmdheight.%d %.8f other.%d\n",basesp,base,dstr(pax2->fiatoshis),pax2->height,dstr(pax2->komodoshis),pax2->otherheight);
610                                 }
611                             }
612                         }
613                     }
614                 }
615                 else if ( kmdheight > 91800 )
616                     printf("pax %s deposit %.8f rejected kmdheight.%d %.8f KMD\n",base,dstr(fiatoshis),kmdheight,dstr(value));
617             }
618         }
619     }
620     else if ( opretbuf[0] == 'I' )
621     {
622         tokomodo = 0;
623         if ( strncmp((char *)"KMD",(char *)&opretbuf[opretlen-4],3) != 0 )
624         {
625             if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,0)) > 0 )
626             {
627                 for (i=0; i<n; i++)
628                 {
629                     if ( baseids[i] < 0 )
630                     {
631                         printf("%d of %d illegal baseid.%d\n",i,n,baseids[i]);
632                         continue;
633                     }
634                     bitcoin_address(coinaddr,60,&rmd160s[i*20],20);
635                     komodo_gateway_deposit(coinaddr,0,0,0,0,txids[i],vouts[i],'I',height,0,CURRENCIES[baseids[i]],0);
636                     komodo_paxmark(height,txids[i],vouts[i],'I',height);
637                     if ( (pax= komodo_paxfind(txids[i],vouts[i],'I')) != 0 )
638                     {
639                         pax->type = opretbuf[0];
640                         strcpy(pax->source,(char *)&opretbuf[opretlen-4]);
641                         if ( (pax2= komodo_paxfind(txids[i],vouts[i],'D')) != 0 )
642                         {
643                             // realtime path?
644                             pax->fiatoshis = pax2->fiatoshis;
645                             pax->komodoshis = pax2->komodoshis;
646                             pax->marked = pax2->marked = pax2->height;
647                             if ( pax->didstats == 0 )
648                             {
649                                 if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 )
650                                 {
651                                     basesp->issued += pax->fiatoshis;
652                                     pax->didstats = 1;
653                                     pax->height = pax2->height;
654                                     pax->otherheight = height;
655                                     if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 )
656                                         printf("########### %p issuedb %s += %.8f kmdheight.%d %.8f other.%d\n",basesp,CURRENCIES[baseids[i]],dstr(pax->fiatoshis),pax->height,dstr(pax->komodoshis),pax->otherheight);
657                                 }
658                             }
659                         }
660                         komodo_paxmark(pax->height,txids[i],vouts[i],'D',height);
661                     }
662                 }
663             } else printf("opreturn none issued?\n");
664         }
665     }
666     else if ( opretbuf[0] == 'W' )//&& opretlen >= 38 )
667     {
668         tokomodo = 1;
669         iguana_rwnum(0,&opretbuf[34],sizeof(kmdheight),&kmdheight);
670         memset(base,0,sizeof(base));
671         PAX_pubkey(0,&opretbuf[1],&addrtype,rmd160,base,&shortflag,&komodoshis);
672         bitcoin_address(coinaddr,addrtype,rmd160,20);
673         checktoshis = PAX_fiatdest(&seed,tokomodo,destaddr,pubkey33,coinaddr,kmdheight,base,value);
674         typestr = "withdraw";
675         if ( strcmp(base,"RUB") == 0 )
676             printf("RUB WITHDRAW %s.height.%d vs height.%d check %.8f/%.8f vs %.8f tokomodo.%d %d seed.%llx -> (%s) len.%d\n",ASSETCHAINS_SYMBOL,kmdheight,height,dstr(checktoshis),dstr(komodoshis),dstr(value),komodo_is_issuer(),strncmp(ASSETCHAINS_SYMBOL,base,strlen(base)) == 0,(long long)seed,coinaddr,opretlen);
677         didstats = 0;
678         if ( komodo_paxcmp(base,kmdheight,komodoshis,checktoshis,seed) == 0 )
679         {
680             if ( value != 0 && ((pax= komodo_paxfind(txid,vout,'W')) == 0 || pax->didstats == 0) )
681             {
682                 if ( (basesp= komodo_stateptrget(base)) != 0 )
683                 {
684                     basesp->withdrawn += value;
685                     didstats = 1;
686                     if ( strcmp(base,ASSETCHAINS_SYMBOL) == 0 )
687                         printf("########### %p withdrawn %s += %.8f\n",basesp,base,dstr(value));
688                 }
689                 if ( strcmp(base,"RUB") == 0 )
690                     printf("notarize %s %.8f -> %.8f kmd.%d other.%d\n",ASSETCHAINS_SYMBOL,dstr(value),dstr(komodoshis),kmdheight,height);
691             }
692             komodo_gateway_deposit(coinaddr,0,(char *)"KMD",value,rmd160,txid,vout,'W',kmdheight,height,source,0);
693             if ( (pax= komodo_paxfind(txid,vout,'W')) != 0 )
694                  pax->type = opretbuf[0];
695         } else printf("withdraw %s paxcmp ht.%d %d error value %.8f -> %.8f vs %.8f\n",base,kmdheight,height,dstr(value),dstr(komodoshis),dstr(checktoshis));
696     }
697     else if ( tokomodo != 0 && opretbuf[0] == 'A' )
698     {
699         tokomodo = 1;
700         if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
701         {
702             for (i=0; i<opretlen; i++)
703                 printf("%02x",opretbuf[i]);
704             printf(" opret[%c] else path tokomodo.%d ht.%d before %.8f\n",opretbuf[0],tokomodo,height,dstr(komodo_paxtotal()));
705         }
706         if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,1)) > 0 )
707         {
708             for (i=0; i<n; i++)
709             {
710                 if ( baseids[i] < 0 )
711                     continue;
712                 didstats = 0;
713                 seed = 0;
714                 checktoshis = komodo_paxprice(&seed,kmdheights[i],CURRENCIES[baseids[i]],(char *)"KMD",(uint64_t)srcvalues[i]);
715                 /*printf("PAX_fiatdest ht.%d price %s %.8f -> KMD %.8f vs %.8f\n",kmdheights[i],CURRENCIES[baseids[i]],(double)srcvalues[i]/COIN,(double)values[i]/COIN,(double)checktoshis/COIN);
716                  for (j=0; j<32; j++)
717                  printf("%02x",((uint8_t *)&txids[i])[j]);
718                  printf(" v%d %.8f k.%d ht.%d base.%d\n",vouts[i],dstr(values[i]),kmdheights[i],otherheights[i],baseids[i]);*/
719                 if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) == 0 )
720                 {
721                     bitcoin_address(coinaddr,60,&rmd160s[i*20],20);
722                     komodo_gateway_deposit(coinaddr,values[i],CURRENCIES[baseids[i]],srcvalues[i],&rmd160s[i*20],txids[i],vouts[i],'A',kmdheights[i],otherheights[i],CURRENCIES[baseids[i]],kmdheights[i]);
723                     komodo_paxmark(height,txids[i],vouts[i],'W',height);
724                     komodo_paxmark(height,txids[i],vouts[i],'A',height);
725                     if ( srcvalues[i] != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 )
726                     {
727                         basesp->approved += srcvalues[i];
728                         didstats = 1;
729                         if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 )
730                             printf("########### %p approved %s += %.8f\n",basesp,CURRENCIES[baseids[i]],dstr(srcvalues[i]));
731                     }
732                     //printf(" i.%d (%s) <- %.8f ADDFLAG APPROVED\n",i,coinaddr,dstr(values[i]));
733                 }
734                 else if ( pax->didstats == 0 && srcvalues[i] != 0 )
735                 {
736                     if ( (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 )
737                     {
738                         basesp->approved += srcvalues[i];
739                         didstats = 1;
740                         if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 )
741                             printf("########### %p approved %s += %.8f\n",basesp,CURRENCIES[baseids[i]],dstr(srcvalues[i]));
742                     }
743                 } //else printf(" i.%d of n.%d pax.%p baseids[] %d\n",i,n,pax,baseids[i]);
744                 if ( (pax= komodo_paxfind(txids[i],vouts[i],'A')) != 0 )
745                 {
746                     pax->type = opretbuf[0];
747                     pax->approved = kmdheights[i];
748                     if ( didstats != 0 )
749                         pax->didstats = 1;
750                     if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 )
751                         printf(" i.%d approved.%d <<<<<<<<<<<<< APPROVED %p\n",i,kmdheights[i],pax);
752                 }
753             }
754         }
755         //printf("extra.[%d] after %.8f\n",n,dstr(komodo_paxtotal()));
756     }
757     else if ( opretbuf[0] == 'X' )
758     {
759         tokomodo = 1;
760         if ( (n= komodo_issued_opreturn(base,txids,vouts,values,srcvalues,kmdheights,otherheights,baseids,rmd160s,opretbuf,opretlen,1)) > 0 )
761         {
762             for (i=0; i<n; i++)
763             {
764                 if ( baseids[i] < 0 )
765                     continue;
766                 bitcoin_address(coinaddr,60,&rmd160s[i*20],20);
767                 komodo_gateway_deposit(coinaddr,0,0,0,0,txids[i],vouts[i],'X',height,0,(char *)"KMD",0);
768                 komodo_paxmark(height,txids[i],vouts[i],'W',height);
769                 komodo_paxmark(height,txids[i],vouts[i],'A',height);
770                 komodo_paxmark(height,txids[i],vouts[i],'X',height);
771                 if ( (pax= komodo_paxfind(txids[i],vouts[i],'X')) != 0 )
772                 {
773                     pax->type = opretbuf[0];
774                     if ( baseids[i] >= 0 && srcvalues[i] != 0 && (basesp= komodo_stateptrget(CURRENCIES[baseids[i]])) != 0 )
775                     {
776                         basesp->redeemed += srcvalues[i];
777                         pax->didstats = 1;
778                         if ( strcmp(CURRENCIES[baseids[i]],ASSETCHAINS_SYMBOL) == 0 )
779                             printf("########### %p redeemed %s += %.8f\n",basesp,CURRENCIES[baseids[i]],dstr(srcvalues[i]));
780                     }
781                 }
782             }
783         } //else printf("komodo_issued_opreturn returned %d\n",n);
784     }
785     return(typestr);
786 }
787
788 void komodo_passport_iteration()
789 {
790     static long lastpos[34]; static char userpass[33][1024];
791     FILE *fp; int32_t baseid,isrealtime,refid,blocks,longest; struct komodo_state *sp,*refsp; char *retstr,fname[512],*base,symbol[16],dest[16]; uint32_t buf[3]; cJSON *infoobj,*result; uint64_t RTmask = 0;
792     while ( KOMODO_INITDONE == 0 )
793     {
794         fprintf(stderr,"PASSPORT iteration waiting for KOMODO_INITDONE\n");
795         sleep(3);
796     }
797     refsp = komodo_stateptr(symbol,dest);
798     if ( ASSETCHAINS_SYMBOL[0] == 0 )
799         refid = 33;
800     else refid = komodo_baseid(ASSETCHAINS_SYMBOL)+1; // illegal base -> baseid.-1 -> 0
801     //printf("PASSPORT %s refid.%d\n",ASSETCHAINS_SYMBOL,refid);
802     for (baseid=32; baseid>=0; baseid--)
803     {
804         sp = 0;
805         isrealtime = 0;
806         base = (char *)CURRENCIES[baseid];
807         if ( baseid+1 != refid )
808         {
809             komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"komodostate");
810             komodo_nameset(symbol,dest,base);
811             if ( (fp= fopen(fname,"rb")) != 0 && (sp= komodo_stateptrget(symbol)) != 0 )
812             {
813                 fseek(fp,0,SEEK_END);
814                 if ( ftell(fp) > lastpos[baseid] )
815                 {
816                     if ( 0 && lastpos[baseid] == 0 && strcmp(symbol,"KMD") == 0 )
817                         printf("passport refid.%d %s fname.(%s) base.%s\n",refid,symbol,fname,base);
818                     fseek(fp,lastpos[baseid],SEEK_SET);
819                     while ( komodo_parsestatefile(sp,fp,symbol,dest) >= 0 )
820                         ;
821                     lastpos[baseid] = ftell(fp);
822                     if ( 0 && lastpos[baseid] == 0 && strcmp(symbol,"KMD") == 0 )
823                         printf("from.(%s) lastpos[%s] %ld\n",ASSETCHAINS_SYMBOL,CURRENCIES[baseid],lastpos[baseid]);
824                 } //else fprintf(stderr,"%s.%ld ",CURRENCIES[baseid],ftell(fp));
825                 fclose(fp);
826             }
827             komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime");
828             if ( (fp= fopen(fname,"rb")) != 0 )
829             {
830                 if ( fread(buf,1,sizeof(buf),fp) == sizeof(buf) )
831                 {
832                     sp->CURRENT_HEIGHT = buf[0];
833                     if ( buf[0] != 0 && buf[0] == buf[1] && buf[2] > time(NULL)-60 )
834                     {
835                         isrealtime = 1;
836                         RTmask |= (1LL << baseid);
837                         memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1]));
838                     } //else fprintf(stderr,"%s not RT\n",base);
839                 } //else fprintf(stderr,"%s size error RT\n",base);
840                 fclose(fp);
841             } //else fprintf(stderr,"%s open error RT\n",base);
842         }
843         else
844         {
845             komodo_statefname(fname,baseid<32?base:(char *)"",(char *)"realtime");
846             if ( (fp= fopen(fname,"wb")) != 0 )
847             {
848                 buf[0] = (uint32_t)chainActive.Tip()->nHeight;
849                 buf[1] = (uint32_t)komodo_longestchain();
850                 if ( buf[0] != 0 && buf[0] == buf[1] )
851                 {
852                     buf[2] = (uint32_t)time(NULL);
853                     RTmask |= (1LL << baseid) | 1;
854                     memcpy(refsp->RTbufs[baseid+1],buf,sizeof(refsp->RTbufs[baseid+1]));
855                     if ( refid != 0 )
856                         memcpy(refsp->RTbufs[0],buf,sizeof(refsp->RTbufs[0]));
857                 }
858                 if ( fwrite(buf,1,sizeof(buf),fp) != sizeof(buf) )
859                     fprintf(stderr,"[%s] %s error writing realtime\n",ASSETCHAINS_SYMBOL,base);
860                 fclose(fp);
861             } else fprintf(stderr,"%s create error RT\n",base);
862         }
863         if ( sp != 0 && isrealtime == 0 )
864             refsp->RTbufs[0][2] = 0;
865     }
866     komodo_paxtotal();
867     refsp->RTmask = RTmask;
868     KOMODO_PASSPORT_INITDONE = 1;
869 }
870
This page took 0.072784 seconds and 4 git commands to generate.