Skip to content

Commit 8dc4196

Browse files
authored
Merge pull request jl777#878 from jl777/FSM
FSM
2 parents ac903b5 + b9de835 commit 8dc4196

File tree

6 files changed

+410
-26
lines changed

6 files changed

+410
-26
lines changed

src/cc/CCGateways.h

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
2525
std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount);
2626
std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount);
2727
std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,std::vector<uint8_t> withdrawpub,int64_t amount);
28+
UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin);
29+
std::string GatewaysMarkdone(uint64_t txfee,uint256 withdrawtxid);
2830

2931
// CCcustom
3032
UniValue GatewaysInfo(uint256 bindtxid);

src/cc/dapps/oraclefeed.c

+232-8
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ uint64_t get_btcusd()
310310

311311
cJSON *get_komodocli(char **retstrp,char *acname,char *method,char *arg0,char *arg1,char *arg2)
312312
{
313-
long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,*fname = "/tmp/komodocli";
313+
long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,fname[256];
314+
sprintf(fname,"/tmp/oraclefeed.%s",method);
314315
if ( acname[0] != 0 )
315316
sprintf(cmdstr,"./komodo-cli -ac_name=%s %s %s %s %s > %s\n",acname,method,arg0,arg1,arg2,fname);
316317
else sprintf(cmdstr,"./komodo-cli %s %s %s %s > %s\n",method,arg0,arg1,arg2,fname);
@@ -344,13 +345,36 @@ bits256 komodobroadcast(char *acname,cJSON *hexjson)
344345
retstr[64] = 0;
345346
decode_hex(txid.bytes,32,retstr);
346347
}
347-
fprintf(stderr,"txid.(%s)\n",bits256_str(str,txid));
348+
fprintf(stderr,"broadcast %s txid.(%s)\n",acname,bits256_str(str,txid));
348349
free(retstr);
349350
}
350351
}
351352
return(txid);
352353
}
353354

355+
bits256 sendtoaddress(char *acname,char *destaddr,int64_t satoshis)
356+
{
357+
char numstr[32],*retstr,str[65]; cJSON *retjson; bits256 txid;
358+
memset(txid.bytes,0,sizeof(txid));
359+
sprintf(numstr,"%.8f",(double)satoshis/SATOSHIDEN);
360+
if ( (retjson= get_komodocli(&retstr,acname,"sendtoaddress",destaddr,numstr,"")) != 0 )
361+
{
362+
fprintf(stderr,"unexpected sendrawtransaction json.(%s)\n",jprint(retjson,0));
363+
free_json(retjson);
364+
}
365+
else if ( retstr != 0 )
366+
{
367+
if ( strlen(retstr) >= 64 )
368+
{
369+
retstr[64] = 0;
370+
decode_hex(txid.bytes,32,retstr);
371+
}
372+
fprintf(stderr,"sendtoaddress %s %.8f txid.(%s)\n",destaddr,(double)satoshis/SATOSHIDEN,bits256_str(str,txid));
373+
free(retstr);
374+
}
375+
return(txid);
376+
}
377+
354378
int32_t get_KMDheight(char *acname)
355379
{
356380
cJSON *retjson; char *retstr; int32_t height=0;
@@ -430,6 +454,206 @@ int32_t get_KMDheader(bits256 *blockhashp,bits256 *merklerootp,int32_t prevheigh
430454
return(0);
431455
}
432456

457+
cJSON *get_gatewayspending(char *acname,char *oraclestxidstr,char *coin)
458+
{
459+
cJSON *retjson; char *retstr;
460+
if ( (retjson= get_komodocli(&retstr,acname,"gatewayspending",oraclestxidstr,coin,"")) != 0 )
461+
{
462+
//printf("pending.(%s)\n",jprint(retjson,0));
463+
return(retjson);
464+
}
465+
else if ( retstr != 0 )
466+
{
467+
fprintf(stderr,"get_gatewayspending.(%s) error.(%s)\n",acname,retstr);
468+
free(retstr);
469+
}
470+
return(0);
471+
}
472+
473+
cJSON *get_rawmempool(char *acname)
474+
{
475+
cJSON *retjson; char *retstr;
476+
if ( (retjson= get_komodocli(&retstr,acname,"getrawmempool","","","")) != 0 )
477+
{
478+
//printf("mempool.(%s)\n",jprint(retjson,0));
479+
return(retjson);
480+
}
481+
else if ( retstr != 0 )
482+
{
483+
fprintf(stderr,"get_rawmempool.(%s) error.(%s)\n",acname,retstr);
484+
free(retstr);
485+
}
486+
return(0);
487+
}
488+
489+
cJSON *get_addressutxos(char *acname,char *coinaddr)
490+
{
491+
cJSON *retjson; char *retstr,jsonbuf[256];
492+
sprintf(jsonbuf,"{\\\"addresses\\\":[\\\"%s\\\"]}",coinaddr);
493+
if ( (retjson= get_komodocli(&retstr,acname,"getaddressutxos",jsonbuf,"","")) != 0 )
494+
{
495+
//printf("addressutxos.(%s)\n",jprint(retjson,0));
496+
return(retjson);
497+
}
498+
else if ( retstr != 0 )
499+
{
500+
fprintf(stderr,"get_addressutxos.(%s) error.(%s)\n",acname,retstr);
501+
free(retstr);
502+
}
503+
return(0);
504+
}
505+
506+
cJSON *get_rawtransaction(char *acname,bits256 txid)
507+
{
508+
cJSON *retjson; char *retstr,str[65];
509+
if ( (retjson= get_komodocli(&retstr,acname,"getrawtransaction",bits256_str(str,txid),"1","")) != 0 )
510+
{
511+
return(retjson);
512+
}
513+
else if ( retstr != 0 )
514+
{
515+
fprintf(stderr,"get_rawtransaction.(%s) error.(%s)\n",acname,retstr);
516+
free(retstr);
517+
}
518+
return(0);
519+
}
520+
521+
void gatewaysmarkdone(char *acname,bits256 txid)
522+
{
523+
char str[65],*retstr; cJSON *retjson;
524+
printf("spend %s %s/v2 as marker\n",acname,bits256_str(str,txid));
525+
if ( (retjson= get_komodocli(&retstr,acname,"gatewaysmarkdone",bits256_str(str,txid),"","")) != 0 )
526+
{
527+
komodobroadcast(acname,retjson);
528+
free_json(retjson);
529+
}
530+
else if ( retstr != 0 )
531+
{
532+
printf("error parsing gatewaysmarkdone.(%s)\n",retstr);
533+
free(retstr);
534+
}
535+
}
536+
537+
int32_t tx_has_voutaddress(char *acname,bits256 txid,char *coinaddr)
538+
{
539+
cJSON *txobj,*vouts,*vout,*sobj,*addresses; char *addr,str[65]; int32_t i,j,n,numvouts,retval = 0;
540+
if ( (txobj= get_rawtransaction(acname,txid)) != 0 )
541+
{
542+
if ( (vouts= jarray(&numvouts,txobj,"vout")) != 0 )
543+
{
544+
for (i=0; i<numvouts; i++)
545+
{
546+
vout = jitem(vouts,i);
547+
if ( (sobj= jobj(vout,"scriptPubKey")) != 0 )
548+
{
549+
if ( (addresses= jarray(&n,sobj,"addresses")) != 0 )
550+
{
551+
for (j=0; j<n; j++)
552+
{
553+
addr = jstri(addresses,j);
554+
if ( strcmp(addr,coinaddr) == 0 )
555+
{
556+
//fprintf(stderr,"found %s in %s v%d\n",coinaddr,bits256_str(str,txid),i);
557+
retval = 1;
558+
}
559+
}
560+
}
561+
}
562+
}
563+
}
564+
free_json(txobj);
565+
}
566+
return(retval);
567+
}
568+
569+
int32_t coinaddrexists(char *acname,char *coinaddr)
570+
{
571+
cJSON *array; bits256 txid; int32_t i,n,num=0;
572+
if ( (array= get_addressutxos(acname,coinaddr)) != 0 )
573+
{
574+
num = cJSON_GetArraySize(array);
575+
free_json(array);
576+
} else return(-1);
577+
if ( num == 0 )
578+
{
579+
if ( (array= get_rawmempool(acname)) != 0 )
580+
{
581+
if ( (n= cJSON_GetArraySize(array)) != 0 )
582+
{
583+
for (i=0; i<n; i++)
584+
{
585+
txid = jbits256i(array,i);
586+
if ( tx_has_voutaddress(acname,txid,coinaddr) > 0 )
587+
{
588+
num = 1;
589+
break;
590+
}
591+
}
592+
}
593+
free_json(array);
594+
} else return(-1);
595+
}
596+
return(num);
597+
}
598+
599+
void update_gatewayspending(char *acname,char *oraclestxidstr,char *coin)
600+
{
601+
// check queue to prevent duplicate
602+
// check KMD chain and mempool for txidaddr
603+
// if txidaddr exists properly, spend the marker (txid.2)
604+
// create withdraw tx and sign it
605+
/// if enough sigs, sendrawtransaction and when it confirms spend marker (txid.2)
606+
/// if not enough sigs, post partially signed to acname with marker2
607+
// monitor marker2, for the partially signed withdraws
608+
cJSON *retjson,*pending,*item; char str[65],*coinstr,*txidaddr,*signeraddr,*withdrawaddr; int32_t i,n,retval,processed = 0; bits256 txid,withtxid,origtxid; int64_t satoshis;
609+
if ( (retjson= get_gatewayspending(acname,oraclestxidstr,coin)) != 0 )
610+
{
611+
if ( jint(retjson,"queueflag") != 0 && (coinstr= jstr(retjson,"coin")) != 0 && strcmp(coinstr,coin) == 0 )
612+
{
613+
if ( (pending= jarray(&n,retjson,"pending")) != 0 )
614+
{
615+
for (i=0; i<n; i++)
616+
{
617+
if ( processed != 0 ) // avoid out of utxo conditions
618+
break;
619+
item = jitem(pending,i);
620+
origtxid = jbits256(item,"txid");
621+
//process item.0 {"txid":"10ec8f4dad6903df6b249b361b879ac77b0617caad7629b97e10f29fa7e99a9b","txidaddr":"RMbite4TGugVmkGmu76ytPHDEQZQGSUjxz","withdrawaddr":"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc","amount":"1.00000000","depositaddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj","signeraddr":"RHV2As4rox97BuE3LK96vMeNY8VsGRTmBj"}
622+
if ( (txidaddr= jstr(item,"txidaddr")) != 0 && (withdrawaddr= jstr(item,"withdrawaddr")) != 0 && (signeraddr= jstr(item,"signeraddr")) != 0 )
623+
{
624+
if ( (satoshis= jdouble(item,"amount")*SATOSHIDEN) != 0 && (retval= coinaddrexists(acname,txidaddr)) == 0 )
625+
{
626+
// this is less errors but more expensive: ./komodo-cli z_sendmany "signeraddr" '[{"address":"<txidaddr>","amount":0.0001},{"address":"<withdrawaddr>","amount":<withamount>}]'
627+
txid = sendtoaddress(acname,txidaddr,10000);
628+
if ( bits256_nonz(txid) != 0 && coinaddrexists(acname,txidaddr) > 0 )
629+
{
630+
// the actual withdraw
631+
withtxid = sendtoaddress(strcmp("KMD",coin)==0?"":coin,withdrawaddr,satoshis);
632+
if ( bits256_nonz(withtxid) != 0 )
633+
{
634+
fprintf(stderr,"withdraw %s %s %s %.8f processed\n",coin,bits256_str(str,withtxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
635+
gatewaysmarkdone(acname,origtxid);
636+
processed++;
637+
}
638+
else
639+
{
640+
fprintf(stderr,"ERROR withdraw %s %s %s %.8f processed\n",coin,bits256_str(str,withtxid),withdrawaddr,(double)satoshis/SATOSHIDEN);
641+
}
642+
} else fprintf(stderr,"error sending %s txidaddr.%s -> %s exists.%d\n",acname,txidaddr,bits256_str(str,txid),coinaddrexists(acname,txidaddr));
643+
}
644+
else if ( retval > 0 )
645+
{
646+
fprintf(stderr,"already did withdraw %s %s %.8f processed\n",coin,withdrawaddr,(double)satoshis/SATOSHIDEN);
647+
gatewaysmarkdone(acname,origtxid);
648+
}
649+
}
650+
}
651+
}
652+
}
653+
free_json(retjson);
654+
}
655+
}
656+
433657
int32_t get_oracledata(int32_t prevheight,char *hexstr,int32_t maxsize,char *format)
434658
{
435659
int32_t i; uint32_t height; uint64_t price; bits256 blockhash,merkleroot;
@@ -483,22 +707,21 @@ oraclesdata 17a841a919c284cea8a676f34e793da002e606f19a9258a3190bed12d5aaa3ff 034
483707
484708
*/
485709

486-
//#define ORACLETXID "4895f631316a649e216153aee7a574bd281686265dc4e8d37597f72353facac3"
487-
//#define MYPUBKEY "02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92"
488-
//#define ACNAME "ORCL"
710+
// ./a.out AT5 1f1aefcca2bdea8196cfd77337fb21de22d200ddea977c2f9e8742c55829d808 02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92 Ihh e6c99f79d4afb216aa8063658b4222edb773dd24bb0f8e91bd4ef341f3e47e5e
489711

490712
int32_t main(int32_t argc,char **argv)
491713
{
492-
cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,n,height,prevheight = 0; char *format,*acname,*oraclestr,*pkstr,*pubstr,*retstr,*retstr2,hexstr[4096]; uint64_t price; bits256 txid;
493-
if ( argc != 5 )
714+
cJSON *clijson,*clijson2,*regjson,*item; int32_t acheight,i,retval,n,height,prevheight = 0; char *format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,hexstr[4096]; uint64_t price; bits256 txid;
715+
if ( argc != 6 )
494716
{
495-
printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT\nPowered by CoinDesk (%s) %.8f\n","https://www.coindesk.com/price/",dstr(get_btcusd()));
717+
printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID\nPowered by CoinDesk (%s) %.8f\n","https://www.coindesk.com/price/",dstr(get_btcusd()));
496718
return(-1);
497719
}
498720
acname = argv[1];
499721
oraclestr = argv[2];
500722
pkstr = argv[3];
501723
format = argv[4];
724+
bindtxidstr = argv[5];
502725
if ( strncmp(format,"Ihh",3) != 0 && format[0] != 'L' )
503726
{
504727
printf("only formats of L and Ihh are supported now\n");
@@ -528,6 +751,7 @@ int32_t main(int32_t argc,char **argv)
528751
prevheight = height;
529752
acheight = get_KMDheight(acname);
530753
printf("ht.%d <- %s\n",height,hexstr);
754+
update_gatewayspending(acname,bindtxidstr,"KMD");
531755
}
532756
free_json(clijson2);
533757
}

0 commit comments

Comments
 (0)