diff --git a/deprecated/obsolete.h b/deprecated/obsolete.h index 42938968c..d87be369c 100644 --- a/deprecated/obsolete.h +++ b/deprecated/obsolete.h @@ -13721,5 +13721,183 @@ len = 0; else printf("BTCSWAP.(%s)\n",retstr); return(retstr); #endif + else if ( strcmp(cmdstr,"BTCdeckC") == 0 ) + { + if ( ap->info == 0 ) + { + printf("A (%s) null swap for orderid.%llu p.%p\n",cmdstr,(long long)ap->orderid,ap); + return(clonestr("{\"error\":\"no swap for orderid\"}")); + } + else + { + if ( ap->otherorderid == 0 ) + { + ap->otherorderid = ap->orderid; + ap->otheroffer = ap->offer; + ap->offer = A.offer; + ap->orderid = A.orderid; + ((struct bitcoin_swapinfo *)ap->info)->feetag64 = ap->orderid; + } + printf("add to statemachine\n"); + queue_enqueue("statemachineQ",&exchange->statemachineQ,&ap->DL,0); + newjson = instantdex_parseargjson(myinfo,exchange,ap,argjson,0); + if ( (retstr= instantdex_addfeetx(myinfo,newjson,ap,ap->info,"BOB_sentoffer","ALICE_sentoffer")) == 0 ) + { + return(instantdex_statemachine(BTC_states,BTC_numstates,myinfo,exchange,ap,cmdstr,argjson,newjson,serdata,serdatalen)); + } else return(clonestr("{\"error\":\"couldnt add fee\"}")); + } + /* + for (iter=0; iter<2; iter++) + { + while ( (m= category_gethexmsg(myinfo,instantdexhash,iter == 0 ? GENESIS_PUBKEY : myinfo->myaddr.persistent)) != 0 ) + { + //printf("gothexmsg len.%d\n",m->len); + pm = (struct instantdex_msghdr *)m->msg; + if ( m->remoteipbits != 0 ) + expand_ipbits(remote,m->remoteipbits); + else remote[0] = 0; + if ( (str= InstantDEX_hexmsg(myinfo,pm,m->len,remote)) != 0 ) + free(str); + free(m); + } + }*/ + + /* uint64_t satoshis[2]; int32_t offerdir = 0; double minperc; uint64_t insurance,relsatoshis; + bits256 orderhash,traderpub; struct iguana_info *coinbtc; + if ( (swap= ap->info) == 0 ) + return(clonestr("{\"error\":\"no swapinfo set\"}")); + relsatoshis = instantdex_BTCsatoshis(ap->offer.price64,ap->offer.basevolume64); + if ( (minperc= jdouble(argjson,"m")) < INSTANTDEX_MINPERC ) + minperc = INSTANTDEX_MINPERC; + offerdir = instantdex_bidaskdir(&ap->offer); + if ( 0 ) + { + int32_t i; + for (i=0; ioffer); i++) + printf("%02x ",((uint8_t *)&ap->offer)[i]); + printf("swapset.%llu\n",(long long)ap->orderid); + } + if ( offerdir > 0 ) + { + swap->bidid = ap->orderid; + swap->askid = ap->otherorderid; + } + else + { + swap->askid = ap->orderid; + swap->bidid = ap->otherorderid; + } + if ( bits256_nonz(swap->othertrader) == 0 ) + swap->othertrader = traderpub; + else if ( bits256_cmp(traderpub,swap->othertrader) != 0 ) + { + printf("competing offer received for (%s/%s) %.8f %.8f\n",ap->offer.base,ap->offer.rel,dstr(ap->offer.price64),dstr(ap->offer.basevolume64)); + return(clonestr("{\"error\":\"no competing offers for now\"}")); + } + if ( bits256_nonz(swap->orderhash) == 0 ) + swap->orderhash = orderhash; + else if ( bits256_cmp(orderhash,swap->orderhash) != 0 ) + { + printf("orderhash %llx mismatch %llx\n",(long long)swap->orderhash.txid,(long long)orderhash.txid); + return(clonestr("{\"error\":\"orderhash mismatch???\"}")); + } + swap->satoshis[0] = ap->offer.basevolume64; + swap->satoshis[1] = relsatoshis; + swap->insurance = (relsatoshis * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee + /* if ( ap->info == 0 ) + //printf("gotoffer SETSWAP for orderid.%llu (%s)\n",(long long)ap->orderid,jprint(argjson,0)); + swap->choosei = swap->otherschoosei = -1; + if ( (retstr= instantdex_swapset(myinfo,ap,argjson)) != 0 ) + return(retstr); + swap->feetag64 = ap->orderid;*/ + + /*char *instantdex_swapset(struct supernet_info *myinfo,struct instantdex_accept *ap,cJSON *argjson) + { + uint64_t satoshis[2]; int32_t offerdir = 0; double minperc; uint64_t insurance,relsatoshis; + struct bitcoin_swapinfo *swap; bits256 orderhash,traderpub; struct iguana_info *coinbtc; + if ( (swap= ap->info) == 0 ) + return(clonestr("{\"error\":\"no swapinfo set\"}")); + relsatoshis = instantdex_BTCsatoshis(ap->offer.price64,ap->offer.basevolume64); + traderpub = jbits256(argjson,"traderpub"); + if ( (minperc= jdouble(argjson,"m")) < INSTANTDEX_MINPERC ) + minperc = INSTANTDEX_MINPERC; + if ( (coinbtc= iguana_coinfind("BTC")) == 0 ) + return(clonestr("{\"error\":\"no BTC found\"}")); + insurance = (satoshis[1] * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); + offerdir = instantdex_bidaskdir(&ap->offer); + vcalc_sha256(0,orderhash.bytes,(void *)&ap->offer,sizeof(ap->offer)); + if ( 0 ) + { + int32_t i; + for (i=0; ioffer); i++) + printf("%02x ",((uint8_t *)&ap->offer)[i]); + printf("swapset.%llu\n",(long long)ap->orderid); + } + if ( offerdir > 0 ) + { + swap->bidid = ap->orderid; + swap->askid = ap->otherorderid; + } + else + { + swap->askid = ap->orderid; + swap->bidid = ap->otherorderid; + } + if ( bits256_nonz(swap->othertrader) == 0 ) + swap->othertrader = traderpub; + else if ( bits256_cmp(traderpub,swap->othertrader) != 0 ) + { + printf("competing offer received for (%s/%s) %.8f %.8f\n",ap->offer.base,ap->offer.rel,dstr(ap->offer.price64),dstr(ap->offer.basevolume64)); + return(clonestr("{\"error\":\"no competing offers for now\"}")); + } + if ( bits256_nonz(swap->orderhash) == 0 ) + swap->orderhash = orderhash; + else if ( bits256_cmp(orderhash,swap->orderhash) != 0 ) + { + printf("orderhash %llx mismatch %llx\n",(long long)swap->orderhash.txid,(long long)orderhash.txid); + return(clonestr("{\"error\":\"orderhash mismatch???\"}")); + } + swap->satoshis[0] = ap->offer.basevolume64; + swap->satoshis[1] = relsatoshis; + swap->insurance = (relsatoshis * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee + return(0); + } + + char *instantdex_sendoffer(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson) // Bob sending to network (Alice) + { + struct iguana_info *other; struct bitcoin_swapinfo *swap; int32_t isbob; cJSON *newjson; char *retstr; + if ( strcmp(ap->offer.rel,"BTC") != 0 ) + return(clonestr("{\"error\":\"invalid othercoin\"}")); + else if ( (other= iguana_coinfind(ap->offer.base)) == 0 ) + return(clonestr("{\"error\":\"invalid othercoin\"}")); + else if ( ap->offer.price64 <= 0 || ap->offer.basevolume64 <= 0 ) + return(clonestr("{\"error\":\"illegal price or volume\"}")); + isbob = (ap->offer.myside == 1); + swap = calloc(1,sizeof(struct bitcoin_swapinfo)); + swap->isbob = isbob; + swap->expiration = ap->offer.expiration;//(uint32_t)(time(NULL) + INSTANTDEX_LOCKTIME*isbob); + swap->choosei = swap->otherschoosei = -1; + swap->depositconfirms = swap->paymentconfirms = swap->altpaymentconfirms = swap->myfeeconfirms = swap->otherfeeconfirms = -1; + ap->info = swap; + printf("sendoffer SETSWAP for orderid.%llu ap.%p (%p)\n",(long long)ap->orderid,ap,swap); + if ( (retstr= instantdex_swapset(myinfo,ap,argjson)) != 0 ) + return(retstr); + ap->orderid = swap->orderhash.txid; + if ( (newjson= instantdex_parseargjson(myinfo,exchange,ap,argjson,1)) == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap offer null newjson\"}")); + else + { + //instantdex_bobtx(myinfo,iguana_coinfind("BTCD"),&swap->deposittxid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->choosei],ap->offer.expiration-INSTANTDEX_LOCKTIME*2,swap->satoshis[1],1); + //instantdex_alicetx(myinfo,iguana_coinfind("BTCD"),swap->altmsigaddr,&swap->altpaymenttxid,swap->pubAm,swap->pubBn,swap->satoshis[0]); + if ( 0 ) + { + int32_t i; + for (i=0; ioffer); i++) + printf("%02x ",((uint8_t *)&ap->offer)[i]); + printf("BTCoffer.%llu\n",(long long)ap->orderid); + } + return(instantdex_sendcmd(myinfo,&ap->offer,newjson,"BTCoffer",GENESIS_PUBKEY,INSTANTDEX_HOPS,swap->deck,sizeof(swap->deck))); + } + }*/ #endif diff --git a/iguana/exchanges/bitcoin.c b/iguana/exchanges/bitcoin.c index 2daf91664..5c64dd60e 100755 --- a/iguana/exchanges/bitcoin.c +++ b/iguana/exchanges/bitcoin.c @@ -2099,7 +2099,8 @@ int32_t is_valid_BTCother(char *other) uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson) { - char *str,coinaddr[64]; uint64_t txid = 0; cJSON *tmp,*json=0; struct instantdex_accept *ap; + char *str,*retstr,coinaddr[64]; uint64_t txid = 0; cJSON *json=0; + struct instantdex_accept *ap; struct supernet_info *myinfo; uint8_t pubkey[33]; struct iguana_info *other; myinfo = SuperNET_accountfind(argjson); //printf("TRADE with myinfo.%p\n",myinfo); @@ -2140,27 +2141,15 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha jaddnum(json,dir > 0 ? "maxprice" : "minprice",price); jaddnum(json,"volume",volume); jaddstr(json,"BTC",myinfo->myaddr.BTC); + jaddnum(json,"minperc",jdouble(argjson,"minperc")); //printf("trade dir.%d (%s/%s) %.6f vol %.8f\n",dir,base,"BTC",price,volume); - if ( (str= instantdex_queueaccept(myinfo,&ap,exchange,base,"BTC",price,volume,-dir,dir > 0 ? "BTC" : base,INSTANTDEX_OFFERDURATION,myinfo->myaddr.nxt64bits,0)) != 0 && ap != 0 ) - { - if ( (tmp= cJSON_Parse(str)) != 0 ) - { - txid = j64bits(json,"orderid"); - if ( (str= instantdex_sendoffer(myinfo,exchange,ap,json)) != 0 ) - { - printf("add.%llu to acceptableQ\n",(long long)txid); - queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0); - //queue_enqueue("statemachineQ",&exchange->statemachineQ,&ap->DL,0); - json = cJSON_CreateObject(); - printf("from TRADE\n"); - jaddstr(json,"BTCoffer",str); - } else printf("null return from btcoffer\n"); - free_json(tmp); - } else printf("queueaccept return parse error.(%s)\n",str); - } else printf("null return queueaccept\n"); + if ( (str= instantdex_createaccept(myinfo,&ap,exchange,base,"BTC",price,volume,-dir,dir > 0 ? "BTC" : base,INSTANTDEX_OFFERDURATION,myinfo->myaddr.nxt64bits,0,jdouble(argjson,"minperc"))) != 0 && ap != 0 ) + retstr = instantdex_checkoffer(myinfo,&txid,exchange,ap,json), free(str); + else printf("null return queueaccept\n"); if ( retstrp != 0 ) - *retstrp = jprint(json,1); - else free_json(json); + *retstrp = retstr != 0 ? retstr : jprint(json,0); + else free(retstr); + free_json(json); } } return(txid); @@ -2168,32 +2157,35 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha char *ORDERSTATUS(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson) { - struct instantdex_accept *ap; cJSON *retjson = cJSON_CreateObject(); + struct instantdex_accept *ap; struct bitcoin_swapinfo *swap; cJSON *retjson; + retjson = cJSON_CreateObject(); struct supernet_info *myinfo = SuperNET_accountfind(argjson); - if ( (ap= instantdex_statemachinefind(myinfo,exchange,orderid,1)) != 0 ) - jadd(retjson,"result",instantdex_statemachinejson(ap)); + if ( (swap= instantdex_statemachinefind(myinfo,exchange,orderid,1)) != 0 ) + jadd(retjson,"result",instantdex_statemachinejson(swap)); else if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,orderid,"*","*",1)) != 0 ) jadd(retjson,"result",instantdex_acceptjson(ap)); - else if ( (ap= instantdex_historyfind(myinfo,exchange,orderid)) != 0 ) - jadd(retjson,"result",instantdex_historyjson(ap)); + else if ( (swap= instantdex_historyfind(myinfo,exchange,orderid)) != 0 ) + jadd(retjson,"result",instantdex_historyjson(swap)); else jaddstr(retjson,"error","couldnt find orderid"); return(jprint(retjson,1)); } char *CANCELORDER(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson) { - struct instantdex_accept *ap = 0; cJSON *retjson; + struct instantdex_accept *ap = 0; cJSON *retjson; struct bitcoin_swapinfo *swap=0; struct supernet_info *myinfo = SuperNET_accountfind(argjson); retjson = cJSON_CreateObject(); if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,orderid,"*","*",1)) != 0 ) - jadd(retjson,"orderid",instantdex_acceptjson(ap)); - else if ( (ap= instantdex_statemachinefind(myinfo,exchange,orderid,1)) != 0 ) - jadd(retjson,"orderid",instantdex_statemachinejson(ap)); - if ( ap != 0 ) { ap->dead = (uint32_t)time(NULL); + jadd(retjson,"orderid",instantdex_acceptjson(ap)); jaddstr(retjson,"result","killed orderid, but might have pending"); - } else jaddstr(retjson,"error","couldnt find orderid"); + } + else if ( (swap= instantdex_statemachinefind(myinfo,exchange,orderid,1)) != 0 ) + { + jadd(retjson,"orderid",instantdex_statemachinejson(swap)); + jaddstr(retjson,"result","killed statemachine orderid, but might have pending"); + } return(jprint(retjson,1)); } @@ -2212,13 +2204,13 @@ char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson) char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson) { - struct instantdex_accept PAD,*ap; cJSON *retjson = cJSON_CreateArray(); + struct bitcoin_swapinfo PAD,*swap; cJSON *retjson = cJSON_CreateArray(); memset(&PAD,0,sizeof(PAD)); queue_enqueue("historyQ",&exchange->historyQ,&PAD.DL,0); - while ( (ap= queue_dequeue(&exchange->historyQ,0)) != 0 && ap != &PAD ) + while ( (swap= queue_dequeue(&exchange->historyQ,0)) != 0 && swap != &PAD ) { - jaddi(retjson,instantdex_historyjson(ap)); - queue_enqueue("historyQ",&exchange->historyQ,&ap->DL,0); + jaddi(retjson,instantdex_historyjson(swap)); + queue_enqueue("historyQ",&exchange->historyQ,&swap->DL,0); } return(jprint(retjson,1)); } diff --git a/iguana/exchanges/bitcoin.h b/iguana/exchanges/bitcoin.h index 2032b5d36..22b1b53a0 100755 --- a/iguana/exchanges/bitcoin.h +++ b/iguana/exchanges/bitcoin.h @@ -57,5 +57,7 @@ int32_t bitcoin_p2shspend(uint8_t *script,int32_t n,uint8_t rmd160[20]); int32_t bitcoin_revealsecret160(uint8_t *script,int32_t n,uint8_t secret160[20]); int32_t bitcoin_standardspend(uint8_t *script,int32_t n,uint8_t rmd160[20]); +cJSON *instantdex_statemachinejson(struct bitcoin_swapinfo *ap); + #endif diff --git a/iguana/exchanges777.h b/iguana/exchanges777.h index f5977720a..c5412b5cf 100755 --- a/iguana/exchanges777.h +++ b/iguana/exchanges777.h @@ -19,6 +19,18 @@ #include #include +#define INSTANTDEX_DECKSIZE 2000 +#define INSTANTDEX_HOPS 2 +#define INSTANTDEX_DURATION 60 + +#define INSTANTDEX_INSURANCERATE (1. / 777.) +#define INSTANTDEX_PUBEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" +#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" +#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" +#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" +#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" +#define INSTANTDEX_MINPERC 50. + #define INSTANTDEX_OFFERDURATION 300 #define INSTANTDEX_LOCKTIME 3600 @@ -90,19 +102,63 @@ struct exchange_request struct exchange_quote bidasks[]; }; -struct instantdex_offer { char base[24],rel[24]; uint64_t price64,basevolume64,offer64; uint32_t expiration,nonce; char myside,acceptdir; }; +struct instantdex_offer +{ + char base[24],rel[24]; + uint64_t price64,basevolume64,offer64; + uint32_t expiration,nonce; + char myside,acceptdir,minperc,pad; +}; + struct instantdex_accept { - struct queueitem DL; void *info; - uint64_t pendingvolume64,otherorderid,orderid,matchid; uint32_t dead; int32_t didstate; - struct instantdex_offer otheroffer,offer; + struct queueitem DL; + uint64_t pendingvolume64,orderid; + uint32_t dead; int32_t didstate; + struct instantdex_offer offer; }; +struct bitcoin_statetx +{ + bits256 txid; + uint64_t amount,change,inputsum; + double numconfirms; + char destaddr[64]; + char txbytes[]; +}; + +struct bitcoin_swapinfo +{ + struct queueitem DL; + struct instantdex_accept mine,other; + bits256 privkeys[INSTANTDEX_DECKSIZE+2],mypubs[2],otherpubs[2],privAm,pubAm,privBn,pubBn; + bits256 myorderhash,otherorderhash,mypubkey,othertrader; + uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; + uint64_t altsatoshis,BTCsatoshis,insurance,altpremium,matched64; + int32_t isinitiator,choosei,otherchoosei,cutverified,otherverifiedcut; + struct bitcoin_statetx *deposit,*payment,*altpayment,*myfee,*otherfee; + char expectedcmdstr[16],status[16]; + struct instantdex_stateinfo *state; uint32_t expiration,dead,reftime; +}; + +struct instantdex_event { char cmdstr[24],sendcmd[16]; int16_t nextstateind; }; + +struct instantdex_stateinfo +{ + char name[24]; int16_t ind,initialstate; + cJSON *(*process)(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp); + cJSON *(*timeout)(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp); + int16_t timeoutind,errorind; + struct instantdex_event *events; int32_t numevents; +}; + +#define instantdex_isbob(swap) (strcmp("BTC",swap->mine.offer.rel) == 0) + struct instantdex_accept *instantdex_offerfind(struct supernet_info *myinfo,struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel,int32_t requeue); cJSON *instantdex_acceptjson(struct instantdex_accept *ap); -cJSON *instantdex_statemachinejson(struct instantdex_accept *ap); -cJSON *instantdex_historyjson(struct instantdex_accept *ap); -struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits,double minperc); +cJSON *instantdex_historyjson(struct bitcoin_swapinfo *swap); +struct bitcoin_swapinfo *instantdex_historyfind(struct supernet_info *myinfo,struct exchange_info *exchange,uint64_t orderid); +struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,double minperc); void *curl_post(void **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3); char *exchanges777_Qprices(struct exchange_info *exchange,char *base,char *rel,int32_t maxseconds,int32_t allfields,int32_t depth,cJSON *argjson,int32_t monitor,double commission); @@ -119,12 +175,11 @@ double truefx_price(struct exchange_info *exchange,char *base,char *rel,struct e double fxcm_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert); double instaforex_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert); -char *instantdex_queueaccept(struct supernet_info *myinfo,struct instantdex_accept **aptrp,struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *mysidestr,int32_t duration,uint64_t txid,int32_t queueflag); +char *instantdex_createaccept(struct supernet_info *myinfo,struct instantdex_accept **aptrp,struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *mysidestr,int32_t duration,uint64_t offerer,int32_t queueflag,uint8_t minperc); void instantdex_update(struct supernet_info *myinfo); char *instantdex_sendcmd(struct supernet_info *myinfo,struct instantdex_offer *offer,cJSON *argjson,char *cmdstr,bits256 desthash,int32_t hops,void *extra,int32_t extralen); char *instantdex_sendoffer(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson); // Bob sending to network (Alice) -char *instantdex_selectqueue(struct exchange_info *exchange,struct instantdex_accept *ap,char *retstr); -struct instantdex_accept *instantdex_historyfind(struct supernet_info *myinfo,struct exchange_info *exchange,uint64_t orderid); -struct instantdex_accept *instantdex_statemachinefind(struct supernet_info *myinfo,struct exchange_info *exchange,uint64_t orderid,int32_t requeueflag); +struct bitcoin_swapinfo *instantdex_statemachinefind(struct supernet_info *myinfo,struct exchange_info *exchange,uint64_t orderid,int32_t requeueflag); +char *instantdex_checkoffer(struct supernet_info *myinfo,uint64_t *txidp,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *json); #endif diff --git a/iguana/iguana_instantdex.c b/iguana/iguana_instantdex.c index e33c6587d..a73f6efa0 100755 --- a/iguana/iguana_instantdex.c +++ b/iguana/iguana_instantdex.c @@ -17,40 +17,19 @@ #include "exchanges777.h" -#define INSTANTDEX_HOPS 2 -#define INSTANTDEX_DURATION 60 - -#define INSTANTDEX_INSURANCERATE (1. / 777.) -#define INSTANTDEX_PUBEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" -#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" -#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" -#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" -#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" -#define INSTANTDEX_MINPERC 50. -#define INSTANTDEX_DECKSIZE 1000 - -struct instantdex_event { char cmdstr[24],sendcmd[16]; int16_t nextstateind; }; +struct instantdex_stateinfo *BTC_states; int32_t BTC_numstates; -struct instantdex_stateinfo +int64_t instantdex_BTCsatoshis(int64_t price,int64_t volume) { - char name[24]; int16_t ind,initialstate; - cJSON *(*process)(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp); - cJSON *(*timeout)(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp); - int16_t timeoutind,errorind; - struct instantdex_event *events; int32_t numevents; -}; + if ( volume > price ) + return(price * dstr(volume)); + else return(dstr(price) * volume); +} -struct bitcoin_swapinfo +int64_t instantdex_insurance(struct iguana_info *coin,int64_t amount) { - bits256 privkeys[INSTANTDEX_DECKSIZE+2],mypubs[2],otherpubs[2],privAm,pubAm,privBn,pubBn; - bits256 orderhash,deposittxid,paymenttxid,altpaymenttxid,myfeetxid,otherfeetxid,othertrader; - uint64_t otherscut[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2],satoshis[2],insurance,bidid,askid,feetag64; - int32_t isbob,choosei,otherschoosei,cutverified,otherverifiedcut; - char altmsigaddr[64],expectedcmdstr[16],*deposit,*payment,*altpayment,*myfeetx,*otherfeetx; - double minperc,depositconfirms,paymentconfirms,altpaymentconfirms,myfeeconfirms,otherfeeconfirms; - struct instantdex_stateinfo *state; uint32_t expiration; -}; -struct instantdex_stateinfo *BTC_states; int32_t BTC_numstates; + return(amount * INSTANTDEX_INSURANCERATE + coin->chain->txfee); // insurance prevents attack +} void instantdex_swapfree(struct instantdex_accept *A,struct bitcoin_swapinfo *swap) { @@ -64,14 +43,14 @@ void instantdex_swapfree(struct instantdex_accept *A,struct bitcoin_swapinfo *sw free(swap->payment); if ( swap->altpayment != 0 ) free(swap->altpayment); - if ( swap->myfeetx != 0 ) - free(swap->myfeetx); - if ( swap->otherfeetx != 0 ) - free(swap->otherfeetx); + if ( swap->myfee != 0 ) + free(swap->myfee); + if ( swap->otherfee != 0 ) + free(swap->otherfee); } } -cJSON *instantdex_defaultprocess(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *instantdex_defaultprocess(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { uint8_t *serdata = *serdatap; int32_t serdatalen = *serdatalenp; *serdatap = 0, *serdatalenp = 0; @@ -82,7 +61,7 @@ cJSON *instantdex_defaultprocess(struct supernet_info *myinfo,struct exchange_in return(newjson); } //({"agent":"iguana","method":"addcoin","newcoin":"PPC","active":1,"maxpeers":128,"services":0,"poll":1,"RAM":4,"minoutput":100000,"minconfirms":3,"estblocktime":600,"path":"/data/ppcoin","conf":"/data/.ppcoin","txfee_satoshis":100000,"useaddmultisig":1,"hastimestamp":0,"userhome":"/data/SuperNET/iguana","pubval":"37","scriptval":"75","wiftype":"b7","netmagic":"e6e8e9e5","genesishash":"00000ffd590b1485b3caadc19b22e6379c733355108f107a430458cdf3407ab6","genesis":{"hashalgo":"sha256","version":1,"timestamp":1345084287,"nbits":"1d00ffff","nonce":2179302059,"merkleroot":"3c2d8f85fab4d17aac558cc648a1a58acff0de6deb890c29985690052c5993c2"},"p2p":9901,"rpc":9902}) -cJSON *instantdex_defaulttimeout(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *instantdex_defaulttimeout(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { uint8_t *serdata = *serdatap; int32_t serdatalen = *serdatalenp; *serdatap = 0, *serdatalenp = 0; @@ -128,7 +107,7 @@ void instantdex_stateinit(struct instantdex_stateinfo *states,int32_t numstates, state->timeout = instantdex_defaulttimeout; } -struct instantdex_stateinfo *instantdex_statecreate(struct instantdex_stateinfo *states,int32_t *numstatesp,char *name,cJSON *(*process_func)(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp),cJSON *(*timeout_func)(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp),char *timeoutstr,char *errorstr,int32_t initialstate) +struct instantdex_stateinfo *instantdex_statecreate(struct instantdex_stateinfo *states,int32_t *numstatesp,char *name,cJSON *(*process_func)(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp),cJSON *(*timeout_func)(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp),char *timeoutstr,char *errorstr,int32_t initialstate) { struct instantdex_stateinfo S,*state = 0; if ( (state= instantdex_statefind(states,*numstatesp,name)) == 0 ) @@ -524,6 +503,7 @@ cJSON *instantdex_offerjson(struct instantdex_offer *offer,uint64_t orderid) jaddnum(item,"timestamp",offer->expiration); jaddnum(item,"price",dstr(offer->price64)); jaddnum(item,"volume",dstr(offer->basevolume64)); + jaddnum(item,"minperc",offer->minperc); jaddnum(item,"nonce",offer->nonce); jaddnum(item,"expiresin",offer->expiration - time(NULL)); return(item); @@ -537,28 +517,59 @@ cJSON *instantdex_acceptjson(struct instantdex_accept *ap) if ( ap->dead != 0 ) jadd64bits(item,"dead",ap->dead); jadd(item,"offer",instantdex_offerjson(&ap->offer,ap->orderid)); - if ( ap->otherorderid != 0 ) + return(item); +} + +void instantdex_statetxjson(cJSON *array,char *name,struct bitcoin_statetx *tx) +{ + cJSON *item; + if ( tx != 0 ) { - jadd64bits(item,"otherid",ap->otherorderid); - jadd(item,"otheroffer",instantdex_offerjson(&ap->otheroffer,ap->otherorderid)); + item = cJSON_CreateObject(); + jaddbits256(item,"txid",tx->txid); + jaddnum(item,"inputsum",dstr(tx->inputsum)); + jaddnum(item,"amount",dstr(tx->amount)); + jaddnum(item,"change",dstr(tx->change)); + jaddnum(item,"txfee",dstr(tx->inputsum) - dstr(tx->amount) - dstr(tx->change)); + jaddnum(item,"confirms",dstr(tx->numconfirms)); + jaddstr(item,"destaddr",tx->destaddr); + jaddstr(item,"txbytes",tx->txbytes); + jadd(array,name,item); } - return(item); } -cJSON *instantdex_statemachinejson(struct instantdex_accept *ap) +cJSON *instantdex_statemachinejson(struct bitcoin_swapinfo *swap) { - struct bitcoin_swapinfo *swap = ap->info; cJSON *confirms,*retjson,*txs; + cJSON *retjson,*txs; int32_t isbob,mydir,otherdir; retjson = cJSON_CreateObject(); if ( swap != 0 ) { - jaddnum(retjson,"isbob",swap->isbob); + mydir = instantdex_bidaskdir(&swap->mine.offer); + otherdir = instantdex_bidaskdir(&swap->other.offer); + isbob = instantdex_isbob(swap); + jaddnum(retjson,"isbob",isbob); + jaddnum(retjson,"mydir",mydir); + jaddnum(retjson,"otherdir",otherdir); + jaddnum(retjson,"expiration",swap->expiration); + jaddnum(retjson,"insurance",dstr(swap->insurance)); + jaddnum(retjson,"baseamount",dstr(swap->altsatoshis)); + jaddnum(retjson,"BTCamount",dstr(swap->BTCsatoshis)); + jaddnum(retjson,"expiration",swap->expiration); + if ( swap->dead != 0 ) + jadd64bits(retjson,"dead",swap->dead); jaddbits256(retjson,"privAm",swap->privAm); jaddbits256(retjson,"pubAm",swap->pubAm); jaddbits256(retjson,"privBn",swap->privBn); jaddbits256(retjson,"pubBn",swap->pubBn); + + jaddbits256(retjson,"myorderhash",swap->myorderhash); + jaddnum(retjson,"choosei",swap->choosei); + jaddnum(retjson,"cutverified",swap->cutverified); jaddbits256(retjson,"othertrader",swap->othertrader); - jaddbits256(retjson,"orderhash",swap->orderhash); - if ( swap->isbob == 0 ) + jaddbits256(retjson,"otherorderhash",swap->otherorderhash); + jaddnum(retjson,"otherchoosei",swap->otherchoosei); + jaddnum(retjson,"otherverifiedcut",swap->otherverifiedcut); + if ( isbob == 0 ) { jaddbits256(retjson,"pubA0",swap->mypubs[0]); jaddbits256(retjson,"pubA1",swap->mypubs[1]); @@ -572,97 +583,92 @@ cJSON *instantdex_statemachinejson(struct instantdex_accept *ap) jaddbits256(retjson,"pubA0",swap->otherpubs[0]); jaddbits256(retjson,"pubA1",swap->otherpubs[1]); } - jaddnum(retjson,"choosei",swap->choosei); - jaddnum(retjson,"otherschoosei",swap->otherschoosei); - jaddnum(retjson,"otherschoosei",swap->otherschoosei); - jaddnum(retjson,"cutverified",swap->cutverified); - jaddnum(retjson,"otherverifiedcut",swap->otherverifiedcut); - - jaddnum(retjson,"expiration",swap->expiration); - jaddnum(retjson,"minperc",swap->minperc * 100.); - jaddnum(retjson,"insurance",dstr(swap->insurance)); - jaddnum(retjson,"baseamount",dstr(swap->satoshis[0])); - jaddnum(retjson,"BTCamount",dstr(swap->satoshis[1])); - jadd64bits(retjson,"bidid",swap->bidid); - jadd64bits(retjson,"askid",swap->askid); - jaddstr(retjson,"altmsigaddr",swap->altmsigaddr); + if ( mydir > 0 && otherdir < 0 ) + { + jadd64bits(retjson,"bidid",swap->mine.orderid); + jadd64bits(retjson,"askid",swap->other.orderid); + } + else if ( mydir < 0 && otherdir > 0 ) + { + jadd64bits(retjson,"askid",swap->mine.orderid); + jadd64bits(retjson,"bidid",swap->other.orderid); + } + if ( swap->matched64 == swap->mine.orderid ) + { + jadd(retjson,"initiator",instantdex_acceptjson(&swap->other)); + jadd(retjson,"matched",instantdex_acceptjson(&swap->mine)); + } + else if ( swap->matched64 == swap->other.orderid ) + { + jadd(retjson,"initiator",instantdex_acceptjson(&swap->mine)); + jadd(retjson,"matched",instantdex_acceptjson(&swap->other)); + } + else jaddstr(retjson,"initiator","illegal initiator missing"); if ( swap->state != 0 ) jaddstr(retjson,"state",swap->state->name); - jaddstr(retjson,"expected",swap->expectedcmdstr); - confirms = cJSON_CreateObject(); - jaddnum(confirms,"deposit",swap->depositconfirms); - jaddnum(confirms,"payment",swap->paymentconfirms); - jaddnum(confirms,"altpayment",swap->altpaymentconfirms); - jaddnum(confirms,"myfee",swap->myfeeconfirms); - jaddnum(confirms,"otherfee",swap->otherfeeconfirms); - jadd(retjson,"confirms",confirms); txs = cJSON_CreateObject(); - if ( swap->deposit != 0 ) - jaddstr(txs,"deposit",swap->deposit), jaddbits256(txs,"deposittxid",swap->deposittxid); - if ( swap->payment != 0 ) - jaddstr(txs,"payment",swap->payment), jaddbits256(txs,"paymenttxid",swap->paymenttxid); - if ( swap->altpayment != 0 ) - jaddstr(txs,"altpayment",swap->altpayment), jaddbits256(txs,"altpaymenttxid",swap->altpaymenttxid); - if ( swap->myfeetx != 0 ) - jaddstr(txs,"myfee",swap->myfeetx), jaddbits256(txs,"myfeetxid",swap->myfeetxid);; - if ( swap->otherfeetx != 0 ) - jaddstr(txs,"otherfee",swap->otherfeetx), jaddbits256(txs,"otherfeetxid",swap->otherfeetxid); - jadd(retjson,"txs",confirms); - jaddbits256(retjson,"othertrader",swap->othertrader); + instantdex_statetxjson(txs,"deposit",swap->deposit); + instantdex_statetxjson(txs,"payment",swap->payment); + instantdex_statetxjson(txs,"altpayment",swap->altpayment); + instantdex_statetxjson(txs,"myfee",swap->myfee); + instantdex_statetxjson(txs,"otherfee",swap->otherfee); + jadd(retjson,"txs",txs); + jaddstr(retjson,"status",swap->status); } - jadd(retjson,"swap",instantdex_acceptjson(ap)); return(retjson); } -cJSON *instantdex_historyjson(struct instantdex_accept *ap) +cJSON *instantdex_historyjson(struct bitcoin_swapinfo *swap) { // need to make sure accepts are put onto history queue when they are completed or deaded // also to make permanent copy (somewhere) - return(instantdex_acceptjson(ap)); + return(instantdex_statemachinejson(swap)); } -struct instantdex_accept *instantdex_historyfind(struct supernet_info *myinfo,struct exchange_info *exchange,uint64_t orderid) +struct bitcoin_swapinfo *instantdex_historyfind(struct supernet_info *myinfo,struct exchange_info *exchange,uint64_t orderid) { - struct instantdex_accept PAD,*ap,*retap = 0; uint32_t now; + struct bitcoin_swapinfo PAD,*swap,*retswap = 0; uint32_t now; now = (uint32_t)time(NULL); memset(&PAD,0,sizeof(PAD)); queue_enqueue("historyQ",&exchange->historyQ,&PAD.DL,0); - while ( (ap= queue_dequeue(&exchange->historyQ,0)) != 0 && ap != &PAD ) + while ( (swap= queue_dequeue(&exchange->historyQ,0)) != 0 && swap != &PAD ) { - if ( orderid == ap->orderid ) - retap = ap; - queue_enqueue("historyQ",&exchange->historyQ,&ap->DL,0); + if ( orderid == swap->mine.orderid ) + retswap = swap; + queue_enqueue("historyQ",&exchange->historyQ,&swap->DL,0); } - return(retap); + return(retswap); } -struct instantdex_accept *instantdex_statemachinefind(struct supernet_info *myinfo,struct exchange_info *exchange,uint64_t orderid,int32_t requeueflag) +struct bitcoin_swapinfo *instantdex_statemachinefind(struct supernet_info *myinfo,struct exchange_info *exchange,uint64_t orderid,int32_t requeueflag) { - struct instantdex_accept PAD,*ap,*retap = 0; uint32_t now; + struct bitcoin_swapinfo PAD,*swap,*retswap = 0; uint32_t now; now = (uint32_t)time(NULL); memset(&PAD,0,sizeof(PAD)); queue_enqueue("statemachineQ",&exchange->statemachineQ,&PAD.DL,0); - while ( (ap= queue_dequeue(&exchange->statemachineQ,0)) != 0 && ap != &PAD ) + while ( (swap= queue_dequeue(&exchange->statemachineQ,0)) != 0 && swap != &PAD ) { - if ( now < ap->offer.expiration && ap->dead == 0 ) + if ( now < swap->expiration && swap->mine.dead == 0 && swap->other.dead == 0 ) { - if ( orderid == ap->orderid ) + if ( orderid == swap->mine.orderid ) { - if ( retap != 0 && requeueflag == 0 ) - queue_enqueue("statemachineQ",&exchange->statemachineQ,&retap->DL,0); - retap = ap; + if ( retswap != 0 && requeueflag == 0 ) + queue_enqueue("statemachineQ",&exchange->statemachineQ,&retswap->DL,0); + retswap = swap; } } else { + strcpy(swap->status,"expired"); printf("expired pending, need to take action, send timeout event\n"); - free(ap); + queue_enqueue("historyQ",&exchange->historyQ,&swap->DL,0); + //bitcoin_freeswap(swap); continue; } - if ( ap != retap || requeueflag != 0 ) - queue_enqueue("statemachineQ",&exchange->statemachineQ,&ap->DL,0); + if ( swap != retswap || requeueflag != 0 ) + queue_enqueue("statemachineQ",&exchange->statemachineQ,&swap->DL,0); } - return(retap); + return(retswap); } struct instantdex_accept *instantdex_offerfind(struct supernet_info *myinfo,struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel,int32_t requeue) @@ -704,7 +710,7 @@ struct instantdex_accept *instantdex_offerfind(struct supernet_info *myinfo,stru return(retap); } -struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits,double minperc) +struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,double minperc) { struct instantdex_accept PAD,*ap,*retap = 0; double aveprice,retvals[4]; uint64_t minvol,bestprice64 = 0; uint32_t now; int32_t offerdir; @@ -716,9 +722,10 @@ struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,str minvol = A->offer.basevolume64 * minperc * .01; while ( (ap= queue_dequeue(&exchange->acceptableQ,0)) != 0 && ap != &PAD ) { - printf("check offerbits.%llu vs %llu: %d %d %d %d %d %d %d %d\n",(long long)offerbits,(long long)ap->offer.offer64,A->offer.basevolume64 > 0.,strcmp(A->offer.base,"*") == 0 ,strcmp(A->offer.base,ap->offer.base) == 0, strcmp(A->offer.rel,"*") == 0 ,strcmp(A->offer.rel,ap->offer.rel) == 0,A->offer.basevolume64 <= (ap->offer.basevolume64 - ap->pendingvolume64),offerdir,instantdex_bidaskdir(&ap->offer)); - if ( now < ap->offer.expiration && ap->dead == 0 && (offerbits == 0 || offerbits != ap->offer.offer64) ) + printf("check offerbits.%llu vs %llu: %d %d %d %d %d %d %d %d\n",(long long)myinfo->myaddr.nxt64bits,(long long)ap->offer.offer64,A->offer.basevolume64 > 0.,strcmp(A->offer.base,"*") == 0 ,strcmp(A->offer.base,ap->offer.base) == 0, strcmp(A->offer.rel,"*") == 0 ,strcmp(A->offer.rel,ap->offer.rel) == 0,A->offer.basevolume64 <= (ap->offer.basevolume64 - ap->pendingvolume64),offerdir,instantdex_bidaskdir(&ap->offer)); + if ( now < ap->offer.expiration && ap->dead == 0 && myinfo->myaddr.nxt64bits != ap->offer.offer64 ) { + printf("aveprice %.8f %.8f offerdir.%d first cmp: %d %d %d\n",aveprice,dstr(ap->offer.price64),offerdir,A->offer.price64 == 0,(offerdir > 0 && ap->offer.price64 >= A->offer.price64),(offerdir < 0 && ap->offer.price64 <= A->offer.price64)); if ( A->offer.basevolume64 > 0. && (strcmp(A->offer.base,"*") == 0 || strcmp(A->offer.base,ap->offer.base) == 0) && (strcmp(A->offer.rel,"*") == 0 || strcmp(A->offer.rel,ap->offer.rel) == 0) && minvol <= (ap->offer.basevolume64 - ap->pendingvolume64) && offerdir*instantdex_bidaskdir(&ap->offer) < 0 ) { printf("aveprice %.8f %.8f offerdir.%d first cmp: %d %d %d\n",aveprice,dstr(ap->offer.price64),offerdir,A->offer.price64 == 0,(offerdir > 0 && ap->offer.price64 >= A->offer.price64),(offerdir < 0 && ap->offer.price64 <= A->offer.price64)); @@ -754,7 +761,7 @@ struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,str // NXT node verifies bitcoin txbytes has proper payment and cashes in with onetimepubkey // BTC* node approves phased tx with onetimepubkey -bits256 instantdex_acceptset(struct instantdex_accept *ap,char *base,char *rel,int32_t duration,int32_t myside,int32_t acceptdir,double price,double volume,uint64_t offerbits,uint32_t nonce) +bits256 instantdex_acceptset(struct instantdex_accept *ap,char *base,char *rel,int32_t duration,int32_t myside,int32_t acceptdir,double price,double volume,uint64_t offerbits,uint32_t nonce,uint8_t minperc) { bits256 hash; memset(ap,0,sizeof(*ap)); @@ -769,6 +776,7 @@ bits256 instantdex_acceptset(struct instantdex_accept *ap,char *base,char *rel,i ap->offer.offer64 = offerbits; ap->offer.myside = myside; ap->offer.acceptdir = acceptdir; + ap->offer.minperc = minperc; ap->offer.price64 = price * SATOSHIDEN; ap->offer.basevolume64 = volume * SATOSHIDEN; vcalc_sha256(0,hash.bytes,(void *)&ap->offer,sizeof(ap->offer)); @@ -782,11 +790,15 @@ bits256 instantdex_acceptset(struct instantdex_accept *ap,char *base,char *rel,i int32_t instantdex_acceptextract(struct instantdex_accept *ap,cJSON *argjson) { - char *base,*rel; bits256 hash,traderpub; double price,volume; int32_t baserel,acceptdir; + char *base,*rel; bits256 hash,traderpub; double price,volume; int32_t baserel,acceptdir,minperc; memset(ap,0,sizeof(*ap)); if ( (base= jstr(argjson,"base")) != 0 ) { volume = jdouble(argjson,"volume"); + if ( (minperc= juint(argjson,"minperc")) < INSTANTDEX_MINPERC ) + minperc = INSTANTDEX_MINPERC; + else if ( minperc > 100 ) + minperc = 100; if ( (rel= jstr(argjson,"rel")) != 0 ) safecopy(ap->offer.rel,rel,sizeof(ap->offer.rel)); if ( (price= jdouble(argjson,"maxprice")) > SMALLVAL ) @@ -801,7 +813,7 @@ int32_t instantdex_acceptextract(struct instantdex_accept *ap,cJSON *argjson) } else return(-1); //printf("price %f vol %f baserel.%d acceptdir.%d\n",price,volume,baserel,acceptdir); traderpub = jbits256(argjson,"traderpub"); - hash = instantdex_acceptset(ap,base,rel,INSTANTDEX_LOCKTIME*2,baserel,acceptdir,price,volume,traderpub.txid,0); + hash = instantdex_acceptset(ap,base,rel,INSTANTDEX_LOCKTIME*2,baserel,acceptdir,price,volume,traderpub.txid,0,minperc); } else { @@ -816,6 +828,8 @@ int32_t instantdex_acceptextract(struct instantdex_accept *ap,cJSON *argjson) ap->offer.offer64 = j64bits(argjson,"o"); ap->offer.price64 = j64bits(argjson,"p"); ap->offer.basevolume64 = j64bits(argjson,"v"); + if ( (ap->offer.minperc= juint(argjson,"m")) < INSTANTDEX_MINPERC ) + ap->offer.minperc = INSTANTDEX_MINPERC; vcalc_sha256(0,hash.bytes,(void *)&ap->offer,sizeof(ap->offer)); ap->orderid = j64bits(argjson,"id"); } @@ -835,188 +849,113 @@ int32_t instantdex_acceptextract(struct instantdex_accept *ap,cJSON *argjson) #include "swaps/iguana_NXTswap.c" #include "swaps/iguana_PAXswap.c" -char *instantdex_swapset(struct supernet_info *myinfo,struct instantdex_accept *ap,cJSON *argjson) +struct bitcoin_swapinfo *bitcoin_swapinit(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *myap,struct instantdex_accept *otherap,int32_t aminitiator,cJSON *argjson) { - uint64_t satoshis[2]; int32_t offerdir = 0; double minperc; uint64_t insurance,relsatoshis; - struct bitcoin_swapinfo *swap; bits256 orderhash,traderpub; struct iguana_info *coinbtc; - if ( (swap= ap->info) == 0 ) - return(clonestr("{\"error\":\"no swapinfo set\"}")); - relsatoshis = instantdex_BTCsatoshis(ap->offer.price64,ap->offer.basevolume64); - traderpub = jbits256(argjson,"traderpub"); - if ( (minperc= jdouble(argjson,"p")) < INSTANTDEX_MINPERC ) - minperc = INSTANTDEX_MINPERC; - if ( (coinbtc= iguana_coinfind("BTC")) == 0 ) - return(clonestr("{\"error\":\"no BTC found\"}")); - insurance = (satoshis[1] * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee prevents papercut attack - offerdir = instantdex_bidaskdir(&ap->offer); - vcalc_sha256(0,orderhash.bytes,(void *)&ap->offer,sizeof(ap->offer)); - if ( 0 ) - { - int32_t i; - for (i=0; ioffer); i++) - printf("%02x ",((uint8_t *)&ap->offer)[i]); - printf("swapset.%llu\n",(long long)ap->orderid); - } - if ( offerdir > 0 ) + struct bitcoin_swapinfo *swap = 0; struct iguana_info *coinbtc,*altcoin; + swap = calloc(1,sizeof(struct bitcoin_swapinfo)); + swap->mine = *myap, swap->other = *otherap; + if ( (swap->isinitiator= aminitiator) != 0 ) { - swap->bidid = ap->orderid; - swap->askid = ap->otherorderid; + swap->matched64 = otherap->orderid; + swap->expiration = otherap->offer.expiration; } else { - swap->askid = ap->orderid; - swap->bidid = ap->otherorderid; + swap->matched64 = myap->orderid; + swap->expiration = myap->offer.expiration; } - if ( bits256_nonz(swap->othertrader) == 0 ) - swap->othertrader = traderpub; - else if ( bits256_cmp(traderpub,swap->othertrader) != 0 ) + swap->choosei = swap->otherchoosei = -1; + strcpy(swap->status,"pending"); + vcalc_sha256(0,swap->myorderhash.bytes,(void *)&swap->mine.offer,sizeof(swap->mine.offer)); + vcalc_sha256(0,swap->otherorderhash.bytes,(void *)&swap->other.offer,sizeof(swap->other.offer)); + swap->mypubkey = myinfo->myaddr.persistent; + swap->othertrader = jbits256(argjson,"traderpub"); + swap->altsatoshis = myap->offer.basevolume64; + swap->BTCsatoshis = instantdex_BTCsatoshis(myap->offer.price64,myap->offer.basevolume64); + if ( (coinbtc= iguana_coinfind("BTC")) == 0 || (altcoin= iguana_coinfind(swap->mine.offer.base)) == 0 ) { - printf("competing offer received for (%s/%s) %.8f %.8f\n",ap->offer.base,ap->offer.rel,dstr(ap->offer.price64),dstr(ap->offer.basevolume64)); - return(clonestr("{\"error\":\"no competing offers for now\"}")); + printf("cant find BTC or %s\n",swap->mine.offer.base); + return(0); } - if ( bits256_nonz(swap->orderhash) == 0 ) - swap->orderhash = orderhash; - else if ( bits256_cmp(orderhash,swap->orderhash) != 0 ) + swap->insurance = (swap->BTCsatoshis * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); + swap->altpremium = (swap->altsatoshis * INSTANTDEX_INSURANCERATE + altcoin->chain->txfee); + if ( myap->offer.myside != instantdex_isbob(swap) || otherap->offer.myside == instantdex_isbob(swap) ) { - printf("orderhash %llx mismatch %llx\n",(long long)swap->orderhash.txid,(long long)orderhash.txid); - return(clonestr("{\"error\":\"orderhash mismatch???\"}")); + printf("isbob error.(%d %d) %d\n",myap->offer.myside,otherap->offer.myside,instantdex_isbob(swap)); + return(0); } - swap->satoshis[0] = ap->offer.basevolume64; - swap->satoshis[1] = relsatoshis; - swap->insurance = (relsatoshis * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee - if ( swap->minperc < minperc ) - swap->minperc = minperc; - return(0); + return(swap); } -char *instantdex_addfeetx(struct supernet_info *myinfo,cJSON *newjson,struct instantdex_accept *ap,struct bitcoin_swapinfo *swap,char *bobstate,char *alicestate) +char *instantdex_checkoffer(struct supernet_info *myinfo,uint64_t *txidp,struct exchange_info *exchange,struct instantdex_accept *myap,cJSON *argjson) { - if ( (swap->myfeetx= instantdex_feetx(myinfo,&swap->myfeetxid,ap)) != 0 ) + char *retstr = 0; struct instantdex_accept *otherap; struct bitcoin_swapinfo *swap; cJSON *newjson; + *txidp = myap->orderid; + if ( (otherap= instantdex_acceptable(myinfo,exchange,myap,myap->offer.minperc)) == 0 ) { - jaddstr(newjson,"feetx",swap->myfeetx); - jaddbits256(newjson,"feetxid",swap->myfeetxid); - swap->state = instantdex_statefind(BTC_states,BTC_numstates,swap->isbob != 0 ? bobstate : alicestate); - return(0); + printf("add.%llu to acceptableQ\n",(long long)myap->orderid); + if ( (retstr= instantdex_sendcmd(myinfo,&myap->offer,argjson,"BTCoffer",GENESIS_PUBKEY,INSTANTDEX_HOPS,0,0)) != 0 ) + free(retstr); + queue_enqueue("acceptableQ",&exchange->acceptableQ,&myap->DL,0); + return(jprint(instantdex_offerjson(&myap->offer,myap->orderid),1)); } - return(clonestr("{\"error\":\"couldnt create feetx\"}")); -} - -char *instantdex_sendoffer(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson) // Bob sending to network (Alice) -{ - struct iguana_info *other; struct bitcoin_swapinfo *swap; int32_t isbob; cJSON *newjson; char *retstr; - if ( strcmp(ap->offer.rel,"BTC") != 0 ) - return(clonestr("{\"error\":\"invalid othercoin\"}")); - else if ( (other= iguana_coinfind(ap->offer.base)) == 0 ) - return(clonestr("{\"error\":\"invalid othercoin\"}")); - else if ( ap->offer.price64 <= 0 || ap->offer.basevolume64 <= 0 ) - return(clonestr("{\"error\":\"illegal price or volume\"}")); - isbob = (ap->offer.myside == 1); - swap = calloc(1,sizeof(struct bitcoin_swapinfo)); - swap->isbob = isbob; - swap->expiration = ap->offer.expiration;//(uint32_t)(time(NULL) + INSTANTDEX_LOCKTIME*isbob); - swap->choosei = swap->otherschoosei = -1; - swap->depositconfirms = swap->paymentconfirms = swap->altpaymentconfirms = swap->myfeeconfirms = swap->otherfeeconfirms = -1; - ap->info = swap; - printf("sendoffer SETSWAP for orderid.%llu ap.%p (%p)\n",(long long)ap->orderid,ap,swap); - if ( (retstr= instantdex_swapset(myinfo,ap,argjson)) != 0 ) - return(retstr); - ap->orderid = swap->orderhash.txid; - if ( (newjson= instantdex_parseargjson(myinfo,exchange,ap,argjson,1)) == 0 ) - return(clonestr("{\"error\":\"instantdex_BTCswap offer null newjson\"}")); else { - //instantdex_bobtx(myinfo,iguana_coinfind("BTCD"),&swap->deposittxid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->choosei],ap->offer.expiration-INSTANTDEX_LOCKTIME*2,swap->satoshis[1],1); - //instantdex_alicetx(myinfo,iguana_coinfind("BTCD"),swap->altmsigaddr,&swap->altpaymenttxid,swap->pubAm,swap->pubBn,swap->satoshis[0]); - if ( 0 ) - { - int32_t i; - for (i=0; ioffer); i++) - printf("%02x ",((uint8_t *)&ap->offer)[i]); - printf("BTCoffer.%llu\n",(long long)ap->orderid); - } - return(instantdex_sendcmd(myinfo,&ap->offer,newjson,"BTCoffer",GENESIS_PUBKEY,INSTANTDEX_HOPS,swap->deck,sizeof(swap->deck))); + swap = bitcoin_swapinit(myinfo,exchange,myap,otherap,1,argjson); + queue_enqueue("statemachineQ",&exchange->statemachineQ,&swap->DL,0); + if ( (newjson= instantdex_parseargjson(myinfo,exchange,swap,argjson,1)) == 0 ) + return(clonestr("{\"error\":\"instantdex_checkoffer null newjson\"}")); + return(instantdex_sendcmd(myinfo,&swap->mine.offer,newjson,"BTCoffer",GENESIS_PUBKEY,INSTANTDEX_HOPS,swap->deck,sizeof(swap->deck))); } + return(retstr); } -char *instantdex_gotoffer(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,struct instantdex_msghdr *msg,cJSON *argjson,char *remoteaddr,uint64_t signerbits,uint8_t *serdata,int32_t serdatalen) // receiving side +char *instantdex_gotoffer(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *myap,struct instantdex_accept *otherap,struct instantdex_msghdr *msg,cJSON *argjson,char *remoteaddr,uint64_t signerbits,uint8_t *serdata,int32_t serdatalen) // receiving side { struct bitcoin_swapinfo *swap = 0; bits256 traderpub; struct iguana_info *coinbtc,*altcoin; cJSON *newjson=0; char *retstr=0; - swap = ap->info; coinbtc = iguana_coinfind("BTC"); traderpub = jbits256(argjson,"traderpub"); if ( bits256_cmp(traderpub,myinfo->myaddr.persistent) == 0 ) { - printf("got my own gotoffer packet orderid.%llu\n",(long long)ap->orderid); + printf("got my own gotoffer packet orderid.%llu/%llu\n",(long long)myap->orderid,(long long)otherap->orderid); return(clonestr("{\"result\":\"got my own packet\"}")); } if ( 0 ) { int32_t i; - for (i=0; ioffer); i++) - printf("%02x ",((uint8_t *)&ap->offer)[i]); - printf("BTCoffer.%llu\n",(long long)ap->orderid); + for (i=0; ioffer); i++) + printf("%02x ",((uint8_t *)&otherap->offer)[i]); + printf("gotoffer.%llu\n",(long long)otherap->orderid); } - printf("T.%d got (%s/%s) %.8f vol %.8f %llu offerside.%d offerdir.%d swap.%p decksize.%ld/datalen.%d\n",bits256_cmp(traderpub,myinfo->myaddr.persistent),ap->offer.base,ap->offer.rel,dstr(ap->offer.price64),dstr(ap->offer.basevolume64),(long long)ap->orderid,ap->offer.myside,ap->offer.acceptdir,ap->info,sizeof(swap->deck),serdatalen); + //char str[65]; printf("GOT OFFER! orderid.%llu %p (%s/%s) other.%s myside.%d\n",(long long)ap->orderid,ap->info,ap->offer.base,ap->offer.rel,bits256_str(str,traderpub),swap->isbob);*/ + printf("T.%d got (%s/%s) %.8f vol %.8f %llu offerside.%d offerdir.%d decksize.%ld/datalen.%d\n",bits256_cmp(traderpub,myinfo->myaddr.persistent),myap->offer.base,myap->offer.rel,dstr(myap->offer.price64),dstr(myap->offer.basevolume64),(long long)myap->orderid,myap->offer.myside,myap->offer.acceptdir,sizeof(swap->deck),serdatalen); if ( exchange == 0 ) return(clonestr("{\"error\":\"instantdex_BTCswap null exchange ptr\"}")); - if ( (altcoin= iguana_coinfind(ap->offer.base)) == 0 || coinbtc == 0 ) + if ( (altcoin= iguana_coinfind(myap->offer.base)) == 0 || coinbtc == 0 ) return(clonestr("{\"error\":\"instantdex_BTCswap cant find btc or other coin info\"}")); - if ( strcmp(ap->offer.rel,"BTC") != 0 ) + if ( strcmp(myap->offer.rel,"BTC") != 0 ) return(clonestr("{\"error\":\"instantdex_BTCswap offer non BTC rel\"}")); - if ( ap->offer.expiration < (time(NULL) + INSTANTDEX_DURATION) ) + if ( myap->offer.expiration < (time(NULL) + INSTANTDEX_DURATION) || otherap->offer.expiration < (time(NULL) + INSTANTDEX_DURATION) ) return(clonestr("{\"error\":\"instantdex_BTCswap offer too close to expiration\"}")); - if ( ap->info == 0 ) - ap->info = swap = calloc(1,sizeof(struct bitcoin_swapinfo)); - //printf("gotoffer SETSWAP for orderid.%llu (%s)\n",(long long)ap->orderid,jprint(argjson,0)); - swap->choosei = swap->otherschoosei = -1; - swap->depositconfirms = swap->paymentconfirms = swap->altpaymentconfirms = swap->myfeeconfirms = swap->otherfeeconfirms = -1; - swap->isbob = (ap->offer.myside ^ 1); - if ( (retstr= instantdex_swapset(myinfo,ap,argjson)) != 0 ) - return(retstr); - swap->feetag64 = ap->orderid; - if ( instantdex_pubkeyargs(swap,newjson,2+INSTANTDEX_DECKSIZE,myinfo->persistent_priv,swap->orderhash,0x02 + swap->isbob) != 2+INSTANTDEX_DECKSIZE ) - return(clonestr("{\"error\":\"instantdex_BTCswap error creating pubkeyargs\"}")); - char str[65]; printf("GOT OFFER! orderid.%llu %p (%s/%s) other.%s myside.%d\n",(long long)ap->orderid,ap->info,ap->offer.base,ap->offer.rel,bits256_str(str,traderpub),swap->isbob); - if ( (newjson= instantdex_parseargjson(myinfo,exchange,ap,argjson,1)) == 0 ) + swap = bitcoin_swapinit(myinfo,exchange,myap,otherap,0,argjson); + if ( (newjson= instantdex_parseargjson(myinfo,exchange,swap,argjson,1)) == 0 ) return(clonestr("{\"error\":\"instantdex_BTCswap offer null newjson\"}")); - else if ( (retstr= instantdex_addfeetx(myinfo,newjson,ap,swap,"BOB_gotoffer","ALICE_gotoffer")) == 0 ) + else //if ( (retstr= instantdex_addfeetx(myinfo,newjson,ap,swap,"BOB_gotoffer","ALICE_gotoffer")) == 0 ) { - //instantdex_pendingnotice(myinfo,exchange,A,ap->offer.basevolume64); + queue_enqueue("statemachineQ",&exchange->statemachineQ,&swap->DL,0); if ( (retstr= instantdex_choosei(swap,newjson,argjson,serdata,serdatalen)) != 0 ) return(retstr); else { - return(instantdex_sendcmd(myinfo,&ap->offer,newjson,"BTCdeckC",traderpub,INSTANTDEX_HOPS,swap->deck,sizeof(swap->deck))); + return(instantdex_sendcmd(myinfo,&swap->mine.offer,newjson,"BTCdeckC",traderpub,INSTANTDEX_HOPS,swap->deck,sizeof(swap->deck))); } - } else return(retstr); -} - -char *instantdex_selectqueue(struct exchange_info *exchange,struct instantdex_accept *ap,char *retstr) -{ - cJSON *retjson; int32_t flag = 0; - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( jobj(retjson,"error") != 0 ) - { - printf("requeue acceptableQ gotoffer error.(%s)\n",jprint(retjson,0)); - instantdex_swapfree(0,ap->info); - ap->info = 0; - flag++; - queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0); - } - free_json(retjson); - } - if ( flag == 0 ) - { - printf("add orderid.%llu to statemachine\n",(long long)ap->orderid); - queue_enqueue("statemachineQ",&exchange->statemachineQ,&ap->DL,0); } return(retstr); } char *instantdex_parse(struct supernet_info *myinfo,struct instantdex_msghdr *msg,cJSON *argjson,char *remoteaddr,uint64_t signerbits,struct instantdex_offer *offer,bits256 orderhash,uint8_t *serdata,int32_t serdatalen) { - char cmdstr[16],*retstr; struct exchange_info *exchange; double minperc; struct instantdex_accept A,*ap = 0; bits256 traderpub; cJSON *newjson; + char cmdstr[16],*retstr; struct exchange_info *exchange; struct instantdex_accept A,*ap = 0; bits256 traderpub; cJSON *newjson; struct bitcoin_swapinfo *swap; if ( BTC_states == 0 ) BTC_states = BTC_initFSM(&BTC_numstates); exchange = exchanges777_find("bitcoin"); @@ -1033,51 +972,19 @@ char *instantdex_parse(struct supernet_info *myinfo,struct instantdex_msghdr *ms A.offer = *offer; A.orderid = orderhash.txid; printf("got.(%s) for %llu\n",cmdstr,(long long)A.orderid); - if ( strcmp(cmdstr,"BTCoffer") == 0 || strcmp(cmdstr,"BTCdeckC") == 0 ) + if ( (A.offer.minperc= jdouble(argjson,"p")) < INSTANTDEX_MINPERC ) + A.offer.minperc = INSTANTDEX_MINPERC; + else if ( A.offer.minperc > 100 ) + A.offer.minperc = 100; + if ( strcmp(cmdstr,"BTCoffer") == 0 ) // incoming { - if ( (minperc= jdouble(argjson,"p")) < INSTANTDEX_MINPERC ) - minperc = INSTANTDEX_MINPERC; - if ( (ap= instantdex_acceptable(myinfo,exchange,&A,myinfo->myaddr.nxt64bits,minperc)) != 0 ) + if ( (ap= instantdex_acceptable(myinfo,exchange,&A,A.offer.minperc)) != 0 ) { - if ( strcmp(cmdstr,"BTCoffer") == 0 ) + if ( (retstr= instantdex_gotoffer(myinfo,exchange,ap,&A,msg,argjson,remoteaddr,signerbits,serdata,serdatalen)) != 0 ) // adds to statemachine if no error { - if ( ap->otherorderid == 0 ) - { - ap->otherorderid = A.orderid; - ap->otheroffer = A.offer; - } - if ( (retstr= instantdex_gotoffer(myinfo,exchange,ap,msg,argjson,remoteaddr,signerbits,serdata,serdatalen)) != 0 ) // adds to statemachine if no error - { - //printf("from GOTOFFER\n"); - return(instantdex_selectqueue(exchange,ap,retstr)); - } - } - else - { - if ( ap->info == 0 ) - { - printf("A (%s) null swap for orderid.%llu p.%p\n",cmdstr,(long long)ap->orderid,ap); - return(clonestr("{\"error\":\"no swap for orderid\"}")); - } - else - { - if ( ap->otherorderid == 0 ) - { - ap->otherorderid = ap->orderid; - ap->otheroffer = ap->offer; - ap->offer = A.offer; - ap->orderid = A.orderid; - ((struct bitcoin_swapinfo *)ap->info)->feetag64 = ap->orderid; - } - printf("add to statemachine\n"); - queue_enqueue("statemachineQ",&exchange->statemachineQ,&ap->DL,0); - newjson = instantdex_parseargjson(myinfo,exchange,ap,argjson,0); - if ( (retstr= instantdex_addfeetx(myinfo,newjson,ap,ap->info,"BOB_sentoffer","ALICE_sentoffer")) == 0 ) - { - return(instantdex_statemachine(BTC_states,BTC_numstates,myinfo,exchange,ap,cmdstr,argjson,newjson,serdata,serdatalen)); - } else return(clonestr("{\"error\":\"couldnt add fee\"}")); - } - } + printf("from GOTOFFER.(%s)\n",retstr); + return(retstr); + } else return(clonestr("{\"error\":\"gotoffer error\"}")); } else { @@ -1092,22 +999,10 @@ char *instantdex_parse(struct supernet_info *myinfo,struct instantdex_msghdr *ms } else return(clonestr("{\"result\":\"order was already in orderbook\"}")); } } - else if ( (ap= instantdex_statemachinefind(myinfo,exchange,A.orderid,1)) != 0 || (ap= instantdex_offerfind(myinfo,exchange,0,0,A.orderid,"*","*",0)) != 0 ) + else if ( (swap= instantdex_statemachinefind(myinfo,exchange,A.orderid,1)) != 0 ) { - if ( ap->info == 0 ) - { - if ( strcmp(cmdstr,"BTCdeckC") != 0 ) - { - printf("B (%s) null swap for orderid.%llu p.%p\n",cmdstr,(long long)ap->orderid,ap); - return(clonestr("{\"error\":\"no swap for orderid\"}")); - } - else - { - printf("BTCdeckC ap.%p null info\n",ap->info); - } - } - newjson = instantdex_parseargjson(myinfo,exchange,ap,argjson,0); - return(instantdex_statemachine(BTC_states,BTC_numstates,myinfo,exchange,ap,cmdstr,argjson,newjson,serdata,serdatalen)); + newjson = instantdex_parseargjson(myinfo,exchange,swap,argjson,0); + return(instantdex_statemachine(BTC_states,BTC_numstates,myinfo,exchange,swap,cmdstr,argjson,newjson,serdata,serdatalen)); } else { @@ -1138,8 +1033,6 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char free_json(argjson); return(clonestr("{\"error\":\"string base packets deprecated\"}")); } - //printf("msg.%p len.%d data.%p datalen.%d crc.%u %s\n",msg,len,data,datalen,calc_crc32(0,(void *)msg,len),bits256_str(str,msg->sig.pubkey)); - //return(0); else if ( (signerbits= acct777_validate(&msg->sig,acct777_msgprivkey(serdata,datalen),msg->sig.pubkey)) != 0 || 1 ) { flag++; @@ -1197,7 +1090,7 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char return(retstr); } -char *instantdex_queueaccept(struct supernet_info *myinfo,struct instantdex_accept **aptrp,struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *mysidestr,int32_t duration,uint64_t offerer,int32_t queueflag) +char *instantdex_createaccept(struct supernet_info *myinfo,struct instantdex_accept **aptrp,struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *mysidestr,int32_t duration,uint64_t offerer,int32_t queueflag,uint8_t minperc) { struct instantdex_accept *ap; int32_t myside; char *retstr; *aptrp = 0; @@ -1213,7 +1106,7 @@ char *instantdex_queueaccept(struct supernet_info *myinfo,struct instantdex_acce myside = -1; printf("myside.(%s) != base.%s or rel.%s\n",mysidestr,base,rel); } - instantdex_acceptset(ap,base,rel,duration,myside,acceptdir,price,basevolume,offerer,0); + instantdex_acceptset(ap,base,rel,duration,myside,acceptdir,price,basevolume,offerer,0,minperc); if ( queueflag != 0 ) { printf("acceptableQ <- %llu\n",(long long)ap->orderid); @@ -1233,7 +1126,7 @@ void instantdex_update(struct supernet_info *myinfo) if ( (Q= category_Q(instantdexhash,myinfo->myaddr.persistent)) != 0 && queue_size(Q) > 0 && (item= Q->list) != 0 ) { m = (void *)item; - m= queue_dequeue(Q,0); + m = queue_dequeue(Q,0); pm = (struct instantdex_msghdr *)m->msg; //printf("loop cmd.(%s)\n",pm->cmd); //if ( m->remoteipbits == 0 && (m= queue_dequeue(Q,0)) ) @@ -1250,41 +1143,31 @@ void instantdex_update(struct supernet_info *myinfo) free(m); } } -/* - for (iter=0; iter<2; iter++) - { - while ( (m= category_gethexmsg(myinfo,instantdexhash,iter == 0 ? GENESIS_PUBKEY : myinfo->myaddr.persistent)) != 0 ) - { - //printf("gothexmsg len.%d\n",m->len); - pm = (struct instantdex_msghdr *)m->msg; - if ( m->remoteipbits != 0 ) - expand_ipbits(remote,m->remoteipbits); - else remote[0] = 0; - if ( (str= InstantDEX_hexmsg(myinfo,pm,m->len,remote)) != 0 ) - free(str); - free(m); - } - }*/ } #include "../includes/iguana_apidefs.h" TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,maxaccept,base,rel,maxprice,basevolume) { - struct instantdex_accept *ap; + struct instantdex_accept *ap; char *retstr; struct exchange_info *exchange; uint64_t txid; myinfo = SuperNET_accountfind(json); - if ( remoteaddr == 0 ) - return(instantdex_queueaccept(myinfo,&ap,exchanges777_find("bitcoin"),base,rel,maxprice,basevolume,-1,rel,INSTANTDEX_OFFERDURATION,myinfo->myaddr.nxt64bits,1)); - else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}")); + if ( remoteaddr == 0 && (exchange= exchanges777_find("bitcoin")) != 0 ) + { + retstr = instantdex_createaccept(myinfo,&ap,exchange,base,rel,maxprice,basevolume,-1,rel,INSTANTDEX_OFFERDURATION,myinfo->myaddr.nxt64bits,1,juint(json,"minperc")); + return(instantdex_checkoffer(myinfo,&txid,exchange,ap,json)); + + } else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}")); } TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,minaccept,base,rel,minprice,basevolume) { - struct instantdex_accept *ap; + struct instantdex_accept *ap; char *retstr; struct exchange_info *exchange; uint64_t txid; myinfo = SuperNET_accountfind(json); - if ( remoteaddr == 0 ) - return(instantdex_queueaccept(myinfo,&ap,exchanges777_find("bitcoin"),base,rel,minprice,basevolume,1,base,INSTANTDEX_OFFERDURATION,myinfo->myaddr.nxt64bits,1)); - else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}")); + if ( remoteaddr == 0 && (exchange= exchanges777_find("bitcoin")) != 0 ) + { + retstr = instantdex_createaccept(myinfo,&ap,exchanges777_find("bitcoin"),base,rel,minprice,basevolume,1,base,INSTANTDEX_OFFERDURATION,myinfo->myaddr.nxt64bits,1,juint(json,"minperc")); + return(instantdex_checkoffer(myinfo,&txid,exchange,ap,json)); + } else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}")); } THREE_STRINGS_AND_DOUBLE(atomic,offer,base,rel,orderid,basevolume) diff --git a/iguana/pnacl/Release/iguana.pexe b/iguana/pnacl/Release/iguana.pexe index 010f9ae6f..6011ada5c 100644 Binary files a/iguana/pnacl/Release/iguana.pexe and b/iguana/pnacl/Release/iguana.pexe differ diff --git a/iguana/swaps/iguana_BTCswap.c b/iguana/swaps/iguana_BTCswap.c index d62126216..2c6ab817f 100755 --- a/iguana/swaps/iguana_BTCswap.c +++ b/iguana/swaps/iguana_BTCswap.c @@ -25,18 +25,6 @@ Tier Nolan's approach is followed with the following changes: e) BEFORE Bob broadcasts deposit, Alice broadcasts BTC denominated fee in cltv so if trade isnt done fee is reclaimed */ -int64_t instantdex_BTCsatoshis(int64_t price,int64_t volume) -{ - if ( volume > price ) - return(price * dstr(volume)); - else return(dstr(price) * volume); -} - -int64_t instantdex_insurance(struct iguana_info *coin,int64_t amount) -{ - return(amount * INSTANTDEX_INSURANCERATE + coin->chain->txfee); // insurance prevents attack -} - /* both fees are standard payments: OP_DUP OP_HASH160 FEE_RMD160 OP_EQUALVERIFY OP_CHECKSIG @@ -104,9 +92,9 @@ void disp_tx(struct supernet_info *myinfo,struct iguana_info *coin,char *str,cha printf("disp_tx (%s) -> %s.(%s)\n",txbytes,str,jprint(txobj,1)); } -char *instantdex_feetx(struct supernet_info *myinfo,bits256 *txidp,struct instantdex_accept *A) +struct bitcoin_statetx *instantdex_feetx(struct supernet_info *myinfo,bits256 *txidp,struct instantdex_accept *A) { - int32_t n,len; char *feetx = 0; struct iguana_info *coin; cJSON *txobj; struct bitcoin_spend *spend; int64_t insurance; uint8_t paymentscript[128]; + int32_t n,len; char *feetx = 0; struct iguana_info *coin; cJSON *txobj; struct bitcoin_spend *spend; int64_t insurance; uint8_t paymentscript[128]; struct bitcoin_statetx *ptr = 0; if ( (coin= iguana_coinfind("BTCD")) != 0 ) { insurance = IGUANA_BTCDMULT * instantdex_insurance(coin,instantdex_BTCsatoshis(A->offer.price64,A->offer.basevolume64)); @@ -124,8 +112,11 @@ char *instantdex_feetx(struct supernet_info *myinfo,bits256 *txidp,struct instan txobj = iguana_signtx(coin,txidp,&feetx,spend,txobj); if ( feetx != 0 ) { + ptr = calloc(1,sizeof(*ptr) + strlen(feetx) + 1); + strcpy(ptr->txbytes,feetx); printf("%s feetx.%s\n",A->offer.myside != 0 ? "BOB" : "ALICE",feetx); //disp_tx(myinfo,coin,"feetx",feetx); + free(feetx); } else printf("error signing %s feetx numinputs.%d\n",A->offer.myside != 0 ? "BOB" : "ALICE",spend->numinputs); free(spend); @@ -135,26 +126,28 @@ char *instantdex_feetx(struct supernet_info *myinfo,bits256 *txidp,struct instan printf("no unspents to spend\n"); } } - return(feetx); + return(ptr); } -int32_t instantdex_feetxverify(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,struct instantdex_accept *A,cJSON *argjson) +int32_t instantdex_feetxverify(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,cJSON *argjson) { cJSON *txobj; bits256 txid; uint32_t n; int32_t i,retval = -1; int64_t insurance; struct iguana_msgtx msgtx; uint8_t script[512]; - if ( swap->otherfeetx != 0 && swap->otherfeeconfirms < 0 ) + if ( swap->otherfee != 0 && swap->otherfee->numconfirms < 0 ) { - if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->otherfeetx)) != 0 ) + if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->otherfee->txbytes)) != 0 ) { - insurance = IGUANA_BTCDMULT * instantdex_insurance(coin,instantdex_BTCsatoshis(A->offer.price64,A->offer.basevolume64)); - n = instantdex_outputinsurance(script,0,insurance,A->orderid); + insurance = swap->insurance;//instantdex_insurance(coin,swap->BTCsatoshis); + if ( strcmp(coin->symbol,"BTCD") == 0 ) + insurance *= IGUANA_BTCDMULT; + n = instantdex_outputinsurance(script,0,insurance,swap->matched64); if ( n == msgtx.vouts[0].pk_scriptlen ) { if ( memcmp(script,msgtx.vouts[0].pk_script,n) == 0 ) { //printf("feetx script verified.(%s)\n",swap->otherfeetx); retval = 0; - swap->otherfeeconfirms = 0; + swap->otherfee->numconfirms = 0.; } else { @@ -167,17 +160,28 @@ int32_t instantdex_feetxverify(struct supernet_info *myinfo,struct iguana_info * } } else printf("pk_scriptlen %d mismatch %d\n",msgtx.vouts[0].pk_scriptlen,n); free_json(txobj); - } else printf("error converting (%s) txobj\n",swap->otherfeetx); - } - else if ( swap->otherfeeconfirms >= 0 ) + } else printf("error converting (%s) txobj\n",swap->otherfee->txbytes); + } else if ( swap->otherfee != 0 && swap->otherfee->numconfirms >= 0 ) retval = 0; else printf("no feetx to verify\n"); return(retval); } -char *instantdex_bobtx(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,bits256 pub1,bits256 pub2,bits256 priv,uint32_t reftime,int64_t amount,int32_t depositflag) +char *instantdex_addfeetx(struct supernet_info *myinfo,cJSON *newjson,struct instantdex_accept *ap,struct bitcoin_swapinfo *swap,char *bobstate,char *alicestate) { - cJSON *txobj; int32_t n,secretstart; char *signedtx = 0; + if ( (swap->myfee= instantdex_feetx(myinfo,&swap->myfee->txid,ap)) != 0 ) + { + jaddstr(newjson,"feetx",swap->myfee->txbytes); + jaddbits256(newjson,"feetxid",swap->myfee->txid); + swap->state = instantdex_statefind(BTC_states,BTC_numstates,instantdex_isbob(swap) != 0 ? bobstate : alicestate); + return(0); + } + return(clonestr("{\"error\":\"couldnt create feetx\"}")); +} + +struct bitcoin_statetx *instantdex_bobtx(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,bits256 pub1,bits256 pub2,bits256 priv,uint32_t reftime,int64_t amount,int32_t depositflag) +{ + cJSON *txobj; int32_t n,secretstart; char *signedtx = 0; struct bitcoin_statetx *ptr = 0; uint8_t script[1024],secret[20]; struct bitcoin_spend *spend; uint32_t locktime; int64_t insurance; if ( coin == 0 ) return(0); @@ -193,28 +197,31 @@ char *instantdex_bobtx(struct supernet_info *myinfo,struct iguana_info *coin,bit txobj = iguana_signtx(coin,txidp,&signedtx,spend,txobj); if ( signedtx != 0 ) { + ptr = calloc(1,sizeof(*ptr) + strlen(signedtx) + 1); + strcpy(ptr->txbytes,signedtx); printf("bob deposit.%s\n",signedtx); //disp_tx(myinfo,coin,depositflag != 0 ? "deposit" : "payment",signedtx); + free(signedtx); } else printf("error signing bobdeposit numinputs.%d\n",spend->numinputs); free(spend); } free_json(txobj); - return(signedtx); + return(ptr); } -int32_t instantdex_paymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,struct instantdex_accept *A,cJSON *argjson,int32_t depositflag) +int32_t instantdex_paymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,cJSON *argjson,int32_t depositflag) { cJSON *txobj; bits256 txid; uint32_t n,locktime; int32_t i,secretstart,retval = -1; uint64_t x; struct iguana_msgtx msgtx; uint8_t script[512],rmd160[20]; int64_t relsatoshis,amount,insurance = 0; if ( coin != 0 && jstr(argjson,depositflag != 0 ? "deposit" : "payment") != 0 ) { - relsatoshis = instantdex_BTCsatoshis(A->offer.price64,A->offer.basevolume64); + relsatoshis = swap->altsatoshis; if ( depositflag != 0 ) insurance = 100 * (relsatoshis * INSTANTDEX_INSURANCERATE + coin->chain->txfee); amount = relsatoshis + insurance; - if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->deposit)) != 0 ) + if ( swap->deposit != 0 && (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->deposit->txbytes)) != 0 ) { - locktime = A->offer.expiration; + locktime = swap->expiration; if ( depositflag == 0 ) memset(rmd160,0,sizeof(rmd160)); else calc_rmd160_sha256(rmd160,swap->privkeys[0].bytes,sizeof(rmd160)); @@ -225,10 +232,10 @@ int32_t instantdex_paymentverify(struct supernet_info *myinfo,struct iguana_info if ( memcmp(script,msgtx.vouts[0].pk_script,n) == 0 ) { iguana_rwnum(0,&script[secretstart],sizeof(x),&x); - printf("deposit script verified x.%llx vs otherscut %llx\n",(long long)x,(long long)swap->otherscut[swap->choosei][0]); - if ( x == swap->otherscut[swap->choosei][0] ) + printf("deposit script verified x.%llx vs otherdeck %llx\n",(long long)x,(long long)swap->otherdeck[swap->choosei][0]); + if ( x == swap->otherdeck[swap->choosei][0] ) retval = 0; - else printf("deposit script verified but secret mismatch x.%llx vs otherscut %llx\n",(long long)x,(long long)swap->otherscut[swap->choosei][0]); + else printf("deposit script verified but secret mismatch x.%llx vs otherdeck %llx\n",(long long)x,(long long)swap->otherdeck[swap->choosei][0]); } else { @@ -246,13 +253,13 @@ int32_t instantdex_paymentverify(struct supernet_info *myinfo,struct iguana_info return(retval); } -int32_t instantdex_altpaymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,struct instantdex_accept *A,cJSON *argjson) +int32_t instantdex_altpaymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,cJSON *argjson) { cJSON *txobj; bits256 txid; uint32_t n; int32_t i,retval = -1; struct iguana_msgtx msgtx; uint8_t script[512]; char *altmsigaddr,msigaddr[64]; if ( jstr(argjson,"altpayment") != 0 && (altmsigaddr= jstr(argjson,"altmsigaddr")) != 0 ) { - if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->altpayment)) != 0 ) + if ( swap->altpayment != 0 && (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->altpayment->txbytes)) != 0 ) { n = instantdex_alicescript(script,0,msigaddr,coin->chain->p2shtype,swap->pubAm,swap->pubBn); if ( strcmp(msigaddr,altmsigaddr) == 0 && n == msgtx.vouts[0].pk_scriptlen ) @@ -277,9 +284,9 @@ int32_t instantdex_altpaymentverify(struct supernet_info *myinfo,struct iguana_i return(retval); } -char *instantdex_alicetx(struct supernet_info *myinfo,struct iguana_info *altcoin,char *msigaddr,bits256 *txidp,bits256 pubAm,bits256 pubBn,int64_t amount) +struct bitcoin_statetx *instantdex_alicetx(struct supernet_info *myinfo,struct iguana_info *altcoin,char *msigaddr,bits256 *txidp,bits256 pubAm,bits256 pubBn,int64_t amount) { - cJSON *txobj; int32_t n; char *signedtx = 0; uint8_t script[1024]; struct bitcoin_spend *spend; + cJSON *txobj; int32_t n; char *signedtx = 0; uint8_t script[1024]; struct bitcoin_spend *spend; struct bitcoin_statetx *ptr = 0; if ( altcoin != 0 && (spend= iguana_spendset(myinfo,altcoin,amount,altcoin->chain->txfee,0)) != 0 ) { txobj = bitcoin_createtx(altcoin,0); @@ -291,66 +298,76 @@ char *instantdex_alicetx(struct supernet_info *myinfo,struct iguana_info *altcoi { printf("alice payment.%s\n",signedtx); //disp_tx(myinfo,altcoin,"altpayment",signedtx); + ptr = calloc(1,sizeof(*ptr) + strlen(signedtx) + 1); + strcpy(ptr->txbytes,signedtx); + free(signedtx); } else printf("error signing alicetx numinputs.%d\n",spend->numinputs); free(spend); free_json(txobj); } - return(signedtx); + return(ptr); } -cJSON *BOB_reclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BOB_reclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; - printf("reclaim deposit.(%s) to %s\n",swap->deposit,myinfo->myaddr.BTC); + *serdatap = 0, *serdatalenp = 0; + if ( swap->deposit != 0 ) + printf("reclaim deposit.(%s) to %s\n",swap->deposit->txbytes,myinfo->myaddr.BTC); // reclaim deposit return(newjson); } -cJSON *BOB_feereclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BOB_feereclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; - printf("reclaim fee.(%s)\n",swap->deposit); + *serdatap = 0, *serdatalenp = 0; + if ( swap->myfee != 0 ) + printf("reclaim fee.(%s)\n",swap->myfee->txbytes); // reclaim deposit return(newjson); } -cJSON *BOB_claimaltfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BOB_claimaltfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; char altcoinaddr[64]; - printf("spend altpayment.(%s) -> %s\n",swap->altpayment,altcoinaddr); + *serdatap = 0, *serdatalenp = 0; char altcoinaddr[64]; + if ( swap->altpayment != 0 ) + printf("spend altpayment.(%s) -> %s\n",swap->altpayment->txbytes,altcoinaddr); // spend altpayment return(newjson); } -cJSON *ALICE_reclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *ALICE_reclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; char altcoinaddr[64]; + *serdatap = 0, *serdatalenp = 0; char altcoinaddr[64]; // reclaim altpayment - printf("reclaim altpayment.(%s) -> %s\n",swap->altpayment,altcoinaddr); + if ( swap->altpayment != 0 ) + printf("reclaim altpayment.(%s) -> %s\n",swap->altpayment->txbytes,altcoinaddr); return(newjson); } -cJSON *ALICE_feereclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *ALICE_feereclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; + *serdatap = 0, *serdatalenp = 0; // reclaim fee - printf("reclaim fee.(%s)\n",swap->myfeetx); + if ( swap->myfee != 0 ) + printf("reclaim fee.(%s)\n",swap->myfee->txbytes); return(newjson); } -cJSON *ALICE_claimdepositfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *ALICE_claimdepositfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; - printf("reclaim deposit.(%s)\n",swap->deposit); + *serdatap = 0, *serdatalenp = 0; + if ( swap->deposit != 0 ) + printf("reclaim deposit.(%s)\n",swap->deposit->txbytes); // reclaim deposit return(newjson); } -cJSON *ALICE_claimbtcfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *ALICE_claimbtcfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; - printf("spend BTC payment.(%s) -> %s\n",swap->payment,myinfo->myaddr.BTC); + *serdatap = 0, *serdatalenp = 0; + if ( swap->payment != 0 ) + printf("spend BTC payment.(%s) -> %s\n",swap->payment->txbytes,myinfo->myaddr.BTC); // spend BTC return(newjson); } @@ -404,16 +421,16 @@ char *instantdex_choosei(struct bitcoin_swapinfo *swap,cJSON *newjson,cJSON *arg int32_t i,j,max,len = 0; uint64_t x; if ( swap->choosei < 0 && serdata != 0 && datalen == sizeof(swap->deck) ) { - max = (int32_t)(sizeof(swap->otherscut) / sizeof(*swap->otherscut)); + max = (int32_t)(sizeof(swap->otherdeck) / sizeof(*swap->otherdeck)); for (i=0; iotherscut[i][j],sizeof(x),&serdata[len]); + len += iguana_rwnum(1,(uint8_t *)&swap->otherdeck[i][j],sizeof(x),&serdata[len]); OS_randombytes((uint8_t *)&swap->choosei,sizeof(swap->choosei)); if ( swap->choosei < 0 ) swap->choosei = -swap->choosei; swap->choosei %= max; jaddnum(newjson,"mychoosei",swap->choosei); - printf("%llu/%llu %s send mychoosei.%d of max.%d\n",(long long)swap->bidid,(long long)swap->askid,swap->isbob!=0?"BOB":"alice",swap->choosei,max); + printf("%llu/%llu %s send mychoosei.%d of max.%d\n",(long long)swap->mine.orderid,(long long)swap->other.orderid,instantdex_isbob(swap)!=0?"BOB":"alice",swap->choosei,max); return(0); } else @@ -432,7 +449,7 @@ void instantdex_getpubs(struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newj for (i=0; i<2; i++) for (j=0; j<2; j++) fields[i][j][1] = '0' + j; - myind = swap->isbob; + myind = instantdex_isbob(swap); otherind = (myind ^ 1); for (j=0; j<2; j++) { @@ -463,19 +480,19 @@ void instantdex_privkeyextract(struct supernet_info *myinfo,struct bitcoin_swapi } pubi = bitcoin_pubkey33(otherpubkey,otherpriv); vcalc_sha256(0,hashpriv.bytes,otherpriv.bytes,sizeof(otherpriv)); - if ( otherpubkey[0] != (swap->isbob ^ 1) + 0x02 ) + if ( otherpubkey[0] != (instantdex_isbob(swap) ^ 1) + 0x02 ) { wrongfirstbyte++; printf("wrongfirstbyte[%d] %02x\n",i,otherpubkey[0]); } - else if ( swap->otherscut[i][0] != hashpriv.txid ) + else if ( swap->otherdeck[i][0] != hashpriv.txid ) { - printf("otherscut[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherscut[i][0],(long long)hashpriv.txid); + printf("otherdeck[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherdeck[i][0],(long long)hashpriv.txid); errs++; } - else if ( swap->otherscut[i][1] != pubi.txid ) + else if ( swap->otherdeck[i][1] != pubi.txid ) { - printf("otherscut[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherscut[i][1],(long long)pubi.txid); + printf("otherdeck[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherdeck[i][1],(long long)pubi.txid); errs++; } } @@ -485,7 +502,7 @@ void instantdex_privkeyextract(struct supernet_info *myinfo,struct bitcoin_swapi } } -void instantdex_swaptxupdate(char **ptrp,bits256 *txidp,cJSON *argjson,char *txname,char *txidfield) +void instantdex_swaptxupdate(struct bitcoin_statetx **ptrp,cJSON *argjson,char *txname,char *txidfield) { char *str; if ( (str= jstr(argjson,txname)) != 0 ) @@ -495,8 +512,9 @@ void instantdex_swaptxupdate(char **ptrp,bits256 *txidp,cJSON *argjson,char *txn printf("got replacement %s? (%s)\n",txname,str); free(*ptrp); } - *txidp = jbits256(argjson,txidfield); - *ptrp = clonestr(str); + *ptrp = calloc(1,sizeof(**ptrp) + strlen(str) + 1); + strcpy((*ptrp)->txbytes,str); + (*ptrp)->txid = jbits256(argjson,txidfield); } } @@ -512,21 +530,21 @@ void instantdex_swapbits256update(bits256 *txidp,cJSON *argjson,char *fieldname) } } -cJSON *instantdex_parseargjson(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,int32_t deckflag) +cJSON *instantdex_parseargjson(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,int32_t deckflag) { - cJSON *newjson; struct bitcoin_swapinfo *swap; + cJSON *newjson; newjson = cJSON_CreateObject(); - if ( (swap= ap->info) == 0 ) + if ( swap == 0 ) jaddstr(newjson,"error","missing swap info"); else { - if ( swap->isbob != 0 ) + if ( instantdex_isbob(swap) != 0 ) { instantdex_swapbits256update(&swap->otherpubs[0],argjson,"pubA0"); instantdex_swapbits256update(&swap->otherpubs[1],argjson,"pubA1"); instantdex_swapbits256update(&swap->pubAm,argjson,"pubAm"); instantdex_swapbits256update(&swap->privAm,argjson,"privAm"); - instantdex_swaptxupdate(&swap->altpayment,&swap->altpaymenttxid,argjson,"altpayment","altpaymenttxid"); + instantdex_swaptxupdate(&swap->altpayment,argjson,"altpayment","altpaymenttxid"); } else { @@ -534,20 +552,20 @@ cJSON *instantdex_parseargjson(struct supernet_info *myinfo,struct exchange_info instantdex_swapbits256update(&swap->otherpubs[1],argjson,"pubB1"); instantdex_swapbits256update(&swap->pubBn,argjson,"pubBn"); instantdex_swapbits256update(&swap->privBn,argjson,"privBn"); - instantdex_swaptxupdate(&swap->deposit,&swap->deposittxid,argjson,"deposit","deposittxid"); - instantdex_swaptxupdate(&swap->payment,&swap->paymenttxid,argjson,"payment","paymenttxid"); + instantdex_swaptxupdate(&swap->deposit,argjson,"deposit","deposittxid"); + instantdex_swaptxupdate(&swap->payment,argjson,"payment","paymenttxid"); } - instantdex_swaptxupdate(&swap->otherfeetx,&swap->otherfeetxid,argjson,"feetx","feetxid"); - if ( swap->otherschoosei < 0 && jobj(argjson,"mychoosei") != 0 ) + instantdex_swaptxupdate(&swap->otherfee,argjson,"feetx","feetxid"); + if ( swap->otherchoosei < 0 && jobj(argjson,"mychoosei") != 0 ) { //printf("otherschoosei.%d\n",swap->otherschoosei); - if ( (swap->otherschoosei= juint(argjson,"mychoosei")) >= sizeof(swap->otherscut)/sizeof(*swap->otherscut) ) - swap->otherschoosei = -1; + if ( (swap->otherchoosei= juint(argjson,"mychoosei")) >= sizeof(swap->otherdeck)/sizeof(*swap->otherdeck) ) + swap->otherchoosei = -1; } if ( juint(argjson,"verified") != 0 ) swap->otherverifiedcut = 1; jaddnum(newjson,"verified",swap->otherverifiedcut); - if ( instantdex_pubkeyargs(swap,newjson,2 + deckflag*INSTANTDEX_DECKSIZE,myinfo->persistent_priv,swap->orderhash,0x02+swap->isbob) == 2 + deckflag*INSTANTDEX_DECKSIZE ) + if ( instantdex_pubkeyargs(swap,newjson,2 + deckflag*INSTANTDEX_DECKSIZE,myinfo->persistent_priv,swap->myorderhash,0x02+instantdex_isbob(swap)) == 2 + deckflag*INSTANTDEX_DECKSIZE ) instantdex_getpubs(swap,argjson,newjson); else printf("ERROR: couldnt generate pubkeys\n"); } @@ -561,73 +579,70 @@ double iguana_numconfs(struct iguana_info *coin,bits256 txid,int32_t height) else return(0.); // 0.5 if zeroconfs } -char *BTC_txconfirmed(struct supernet_info *myinfo,struct iguana_info *coin,struct instantdex_accept *ap,cJSON *newjson,bits256 txid,double *numconfirmsp,char *virtualevent,double requiredconfs) +char *BTC_txconfirmed(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,cJSON *newjson,bits256 txid,double *numconfirmsp,char *virtualevent,double requiredconfs) { - struct iguana_txid *tx,T; struct bitcoin_swapinfo *swap; int32_t height; char *retstr; double confs; - swap = ap->info; + struct iguana_txid *tx,T; int32_t height; char *retstr; double confs; *numconfirmsp = -1.; if ( coin != 0 && *numconfirmsp < 0 ) { if ( (tx= iguana_txidfind(coin,&height,&T,txid)) != 0 && (confs= iguana_numconfs(coin,txid,height)) >= requiredconfs ) { *numconfirmsp = confs; - if ( (retstr= instantdex_sendcmd(myinfo,&ap->offer,newjson,virtualevent,myinfo->myaddr.persistent,0,0,0)) != 0 ) + if ( (retstr= instantdex_sendcmd(myinfo,&swap->mine.offer,newjson,virtualevent,myinfo->myaddr.persistent,0,0,0)) != 0 ) return(retstr); } } return(0); } -cJSON *BTC_waitdeckCfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BTC_waitdeckCfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; + *serdatap = 0, *serdatalenp = 0; strcmp(swap->expectedcmdstr,"BTCdeckC"); - if ( instantdex_feetxverify(myinfo,iguana_coinfind("BTCD"),swap,ap,argjson) != 0 ) + if ( instantdex_feetxverify(myinfo,iguana_coinfind("BTCD"),swap,argjson) != 0 ) return(cJSON_Parse("{\"error\":\"feetx didnt verify\"}")); return(newjson); } -cJSON *BTC_waitprivCfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BTC_waitprivCfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - struct bitcoin_swapinfo *swap = ap->info; strcmp(swap->expectedcmdstr,"BTCprivC"); instantdex_privkeyextract(myinfo,swap,*serdatap,*serdatalenp); - if ( instantdex_feetxverify(myinfo,iguana_coinfind("BTCD"),swap,ap,argjson) != 0 ) + if ( instantdex_feetxverify(myinfo,iguana_coinfind("BTCD"),swap,argjson) != 0 ) return(cJSON_Parse("{\"error\":\"feetx didnt verify\"}")); *serdatap = 0, *serdatalenp = 0; return(newjson); } -cJSON *BOB_waitBTCalttxfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BOB_waitBTCalttxfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; + *serdatap = 0, *serdatalenp = 0; strcmp(swap->expectedcmdstr,"BTCalttx"); - if ( instantdex_altpaymentverify(myinfo,iguana_coinfind(ap->offer.base),swap,ap,argjson) != 0 ) + if ( instantdex_altpaymentverify(myinfo,iguana_coinfind(swap->mine.offer.base),swap,argjson) != 0 ) return(cJSON_Parse("{\"error\":\"altpayment didnt verify\"}")); return(newjson); } -cJSON *ALICE_waitBTCpaytxfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *ALICE_waitBTCpaytxfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; + *serdatap = 0, *serdatalenp = 0; strcmp(swap->expectedcmdstr,"BTCpaytx"); return(newjson); } -cJSON *BOB_waitfeefunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BOB_waitfeefunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - char *retstr; struct bitcoin_swapinfo *swap = ap->info; struct iguana_info *coinbtc; uint32_t reftime; + char *retstr; struct iguana_info *coinbtc; coinbtc = iguana_coinfind("BTC"); *serdatap = 0, *serdatalenp = 0; - reftime = (uint32_t)(ap->offer.expiration - INSTANTDEX_LOCKTIME*2); - if ( coinbtc != 0 && swap->deposit == 0 && (retstr= BTC_txconfirmed(myinfo,coinbtc,ap,newjson,swap->otherfeetxid,&swap->otherfeeconfirms,"feefound",0)) != 0 ) + if ( coinbtc != 0 && swap->deposit == 0 && (retstr= BTC_txconfirmed(myinfo,coinbtc,swap,newjson,swap->otherfee->txid,&swap->otherfee->numconfirms,"feefound",0)) != 0 ) { jaddstr(newjson,"feefound",retstr); - if ( (swap->deposit= instantdex_bobtx(myinfo,coinbtc,&swap->deposittxid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->choosei],reftime,swap->satoshis[1],1)) != 0 ) + if ( (swap->deposit= instantdex_bobtx(myinfo,coinbtc,&swap->deposit->txid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->choosei],swap->reftime,swap->BTCsatoshis,1)) != 0 ) { // broadcast deposit - jaddstr(newjson,"deposit",swap->deposit); - jaddbits256(newjson,"deposittxid",swap->deposittxid); + jaddstr(newjson,"deposit",swap->deposit->txbytes); + jaddbits256(newjson,"deposittxid",swap->deposit->txid); } else jaddstr(newjson,"error","couldnt create paymenttx"); return(newjson); @@ -635,31 +650,31 @@ cJSON *BOB_waitfeefunc(struct supernet_info *myinfo,struct exchange_info *exchan return(0); } -cJSON *BOB_waitprivMfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BOB_waitprivMfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - char *retstr; struct bitcoin_swapinfo *swap = ap->info; + char *retstr; strcmp(swap->expectedcmdstr,"BTCprivM"); - if ( swap->payment != 0 && (retstr= BTC_txconfirmed(myinfo,iguana_coinfind("BTC"),ap,newjson,swap->paymenttxid,&swap->paymentconfirms,"btcfound",0)) != 0 ) + if ( swap->payment != 0 && (retstr= BTC_txconfirmed(myinfo,iguana_coinfind("BTC"),swap,newjson,swap->payment->txid,&swap->payment->numconfirms,"btcfound",0)) != 0 ) jaddstr(newjson,"btcfound",retstr); printf("search for payment spend in blockchain\n"); *serdatap = 0, *serdatalenp = 0; return(newjson); } -cJSON *BOB_waitaltconfirmfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BOB_waitaltconfirmfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - char *retstr; struct bitcoin_swapinfo *swap = ap->info; struct iguana_info *altcoin; uint32_t reftime; - altcoin = iguana_coinfind(ap->offer.base); + char *retstr; struct iguana_info *altcoin; //uint32_t reftime; + altcoin = iguana_coinfind(swap->mine.offer.base); *serdatap = 0, *serdatalenp = 0; - reftime = (uint32_t)(ap->offer.expiration - INSTANTDEX_LOCKTIME*2); - if ( altcoin != 0 && swap->altpayment != 0 && (retstr= BTC_txconfirmed(myinfo,altcoin,ap,newjson,swap->altpaymenttxid,&swap->altpaymentconfirms,"altfound",altcoin->chain->minconfirms)) != 0 ) + //reftime = (uint32_t)(ap->offer.expiration - INSTANTDEX_LOCKTIME*2); + if ( altcoin != 0 && swap->altpayment != 0 && (retstr= BTC_txconfirmed(myinfo,altcoin,swap,newjson,swap->altpayment->txid,&swap->altpayment->numconfirms,"altfound",altcoin->chain->minconfirms)) != 0 ) { jaddstr(newjson,"altfound",retstr); - if ( (swap->payment= instantdex_bobtx(myinfo,altcoin,&swap->deposittxid,swap->mypubs[1],swap->otherpubs[0],swap->privkeys[swap->otherschoosei],reftime,swap->satoshis[1],0)) != 0 ) + if ( (swap->payment= instantdex_bobtx(myinfo,altcoin,&swap->payment->txid,swap->mypubs[1],swap->otherpubs[0],swap->privkeys[swap->otherchoosei],swap->reftime,swap->BTCsatoshis,0)) != 0 ) { // broadcast payment - jaddstr(newjson,"payment",swap->payment); - jaddbits256(newjson,"paymenttxid",swap->paymenttxid); + jaddstr(newjson,"payment",swap->payment->txbytes); + jaddbits256(newjson,"paymenttxid",swap->payment->txid); } else jaddstr(newjson,"error","couldnt create paymenttx"); return(newjson); @@ -667,56 +682,56 @@ cJSON *BOB_waitaltconfirmfunc(struct supernet_info *myinfo,struct exchange_info return(0); } -cJSON *BTC_waitprivsfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BTC_waitprivsfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - *serdatap = 0, *serdatalenp = 0; struct bitcoin_swapinfo *swap = ap->info; + *serdatap = 0, *serdatalenp = 0; strcmp(swap->expectedcmdstr,"BTCprivs"); instantdex_privkeyextract(myinfo,swap,*serdatap,*serdatalenp); return(newjson); } -cJSON *ALICE_waitfeefunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *ALICE_waitfeefunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - char *retstr; struct iguana_info *coinbtc; struct bitcoin_swapinfo *swap = ap->info; + char *retstr; struct iguana_info *coinbtc; coinbtc = iguana_coinfind("BTC"); *serdatap = 0, *serdatalenp = 0; - if ( swap->otherfeetx != 0 && (retstr= BTC_txconfirmed(myinfo,coinbtc,ap,newjson,swap->otherfeetxid,&swap->otherfeeconfirms,"feefound",0)) != 0 ) + if ( swap->otherfee != 0 && (retstr= BTC_txconfirmed(myinfo,coinbtc,swap,newjson,swap->otherfee->txid,&swap->otherfee->numconfirms,"feefound",0)) != 0 ) { jaddstr(newjson,"feefound",retstr); return(newjson); } else return(0); } -cJSON *ALICE_waitdepositfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *ALICE_waitdepositfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - char *retstr; struct iguana_info *coinbtc,*altcoin; struct bitcoin_swapinfo *swap = ap->info; + char *retstr; struct iguana_info *coinbtc,*altcoin; coinbtc = iguana_coinfind("BTC"); - altcoin = iguana_coinfind(ap->offer.rel); + altcoin = iguana_coinfind(swap->mine.offer.rel); *serdatap = 0, *serdatalenp = 0; - if ( swap->deposit != 0 && (retstr= BTC_txconfirmed(myinfo,coinbtc,ap,newjson,swap->deposittxid,&swap->depositconfirms,"depfound",0.5)) != 0 ) + if ( swap->deposit != 0 && (retstr= BTC_txconfirmed(myinfo,coinbtc,swap,newjson,swap->deposit->txid,&swap->deposit->numconfirms,"depfound",0.5)) != 0 ) { jaddstr(newjson,"depfound",retstr); - if ( instantdex_paymentverify(myinfo,iguana_coinfind("BTC"),swap,ap,argjson,1) != 0 ) + if ( instantdex_paymentverify(myinfo,iguana_coinfind("BTC"),swap,argjson,1) != 0 ) return(cJSON_Parse("{\"error\":\"deposit didnt verify\"}")); - if ( (swap->altpayment= instantdex_alicetx(myinfo,altcoin,swap->altmsigaddr,&swap->altpaymenttxid,swap->pubAm,swap->pubBn,swap->satoshis[0])) != 0 ) + if ( (swap->altpayment= instantdex_alicetx(myinfo,altcoin,swap->altpayment->destaddr,&swap->altpayment->txid,swap->pubAm,swap->pubBn,swap->altsatoshis)) != 0 ) { // broadcast altpayment - jaddstr(newjson,"altpayment",swap->altpayment); - jaddbits256(newjson,"altpaymenttxid",swap->altpaymenttxid); + jaddstr(newjson,"altpayment",swap->altpayment->txbytes); + jaddbits256(newjson,"altpaymenttxid",swap->altpayment->txid); } else return(cJSON_Parse("{\"error\":\"couldnt create altpayment\"}")); } return(newjson); } -cJSON *ALICE_waitpayconf_or_bobreclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *ALICE_waitpayconf_or_bobreclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { - char *retstr; double btcconfirms; struct iguana_info *coinbtc; struct bitcoin_swapinfo *swap = ap->info; + char *retstr; double btcconfirms; struct iguana_info *coinbtc; coinbtc = iguana_coinfind("BTC"); *serdatap = 0, *serdatalenp = 0; - if ( swap->satoshis[1] < SATOSHIDEN/10 ) + if ( swap->BTCsatoshis < SATOSHIDEN/10 ) btcconfirms = 0; - else btcconfirms = 1. + sqrt((double)swap->satoshis[1] / SATOSHIDEN); - if ( swap->payment != 0 && (retstr= BTC_txconfirmed(myinfo,coinbtc,ap,newjson,swap->paymenttxid,&swap->paymentconfirms,"payfound",btcconfirms)) != 0 ) + else btcconfirms = 1. + sqrt((double)swap->BTCsatoshis / SATOSHIDEN); + if ( swap->payment != 0 && (retstr= BTC_txconfirmed(myinfo,coinbtc,swap,newjson,swap->payment->txid,&swap->payment->numconfirms,"payfound",btcconfirms)) != 0 ) { jaddstr(newjson,"payfound",retstr); // if bobreclaimed is there, then reclaim altpayment @@ -725,11 +740,20 @@ cJSON *ALICE_waitpayconf_or_bobreclaimfunc(struct supernet_info *myinfo,struct e } else return(0); } -cJSON *BTC_cleanupfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +cJSON *BTC_cleanupfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +{ + *serdatap = 0, *serdatalenp = 0; + jaddstr(newjson,"error","need to cleanup"); + swap->dead = (uint32_t)time(NULL); + swap->mine.dead = (uint32_t)time(NULL); + swap->other.dead = (uint32_t)time(NULL); + return(newjson); +} + +cJSON *BTC_idlerecvfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) { *serdatap = 0, *serdatalenp = 0; jaddstr(newjson,"error","need to cleanup"); - ap->dead = (uint32_t)time(NULL); return(newjson); } @@ -791,6 +815,8 @@ struct instantdex_stateinfo *BTC_initFSM(int32_t *n) // end terminal [BLOCKING] states // need to create states before they can be referred to, that way a one pass FSM compile is possible + s = instantdex_statecreate(s,n,"BOB_gotoffer",BTC_waitprivCfunc,0,"BTC_cleanup",0,1); + s = instantdex_statecreate(s,n,"ALICE_gotoffer",BTC_waitprivCfunc,0,"BTC_cleanup",0,1); s = instantdex_statecreate(s,n,"BOB_sentprivs",BTC_waitprivsfunc,0,"BTC_cleanup",0,0); s = instantdex_statecreate(s,n,"BOB_waitfee",BOB_waitfeefunc,0,"BTC_cleanup",0,0); s = instantdex_statecreate(s,n,"BOB_sentdeposit",BOB_waitBTCalttxfunc,0,"BOB_reclaimed",0,0); @@ -804,13 +830,14 @@ struct instantdex_stateinfo *BTC_initFSM(int32_t *n) if ( 0 ) // following are implicit states and events handled externally to setup datastructures { - //s = instantdex_statecreate(s,n,"BOB_idle",BTC_idlefunc,0,0,0); - //s = instantdex_statecreate(s,n,"ALICE_idle",BTC_idlefunc,0,0,0); instantdex_addevent(s,*n,"BOB_idle","usrorder","BTCoffer","BOB_sentoffer"); // send deck instantdex_addevent(s,*n,"ALICE_idle","usrorder","BTCoffer","ALICE_sentoffer"); - instantdex_addevent(s,*n,"BOB_idle","BTCoffer","BTCdeckC","BOB_gotoffer"); // send deck + Chose - instantdex_addevent(s,*n,"ALICE_idle","BTCoffer","BTCdeckC","ALICE_gotoffer"); } + s = instantdex_statecreate(s,n,"BOB_idle",BTC_idlerecvfunc,0,"BTC_cleanup",0,1); + instantdex_addevent(s,*n,"BOB_idle","BTCoffer","BTCdeckC","BOB_gotoffer"); // send deck + Chose + s = instantdex_statecreate(s,n,"ALICE_idle",BTC_idlerecvfunc,0,"BTC_cleanup",0,1); + instantdex_addevent(s,*n,"ALICE_idle","BTCoffer","BTCdeckC","ALICE_gotoffer"); + // after offer is sent, wait for other side to choose and sent their deck, then send privs s = instantdex_statecreate(s,n,"BOB_sentoffer",BTC_waitdeckCfunc,0,"BTC_cleanup",0,1); s = instantdex_statecreate(s,n,"ALICE_sentoffer",BTC_waitdeckCfunc,0,"BTC_cleanup",0,1); @@ -874,16 +901,16 @@ struct instantdex_stateinfo *BTC_initFSM(int32_t *n) return(s); } -char *instantdex_statemachine(struct instantdex_stateinfo *states,int32_t numstates,struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,char *cmdstr,cJSON *argjson,cJSON *newjson,uint8_t *serdata,int32_t serdatalen) +char *instantdex_statemachine(struct instantdex_stateinfo *states,int32_t numstates,struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,char *cmdstr,cJSON *argjson,cJSON *newjson,uint8_t *serdata,int32_t serdatalen) { - uint32_t i; struct iguana_info *altcoin,*coinbtc; struct bitcoin_swapinfo *swap; struct instantdex_stateinfo *state; cJSON *origjson = newjson; - if ( (swap= A->info) == 0 || (state= swap->state) == 0 || (coinbtc= iguana_coinfind("BTC")) == 0 || (altcoin= iguana_coinfind(A->offer.base)) == 0 ) + uint32_t i; struct iguana_info *altcoin,*coinbtc; struct instantdex_stateinfo *state; cJSON *origjson = newjson; + if ( swap == 0 || (state= swap->state) == 0 || (coinbtc= iguana_coinfind("BTC")) == 0 || (altcoin= iguana_coinfind(swap->mine.offer.base)) == 0 ) return(clonestr("{\"error\":\"instantdex_BTCswap missing coin info\"}")); - printf("%llu/%llu cmd.(%s) state.(%s)\n",(long long)swap->bidid,(long long)swap->askid,cmdstr,swap->state->name); + printf("%llu/%llu cmd.(%s) state.(%s)\n",(long long)swap->mine.orderid,(long long)swap->other.orderid,cmdstr,swap->state->name); if ( swap->expiration != 0 && time(NULL) > swap->expiration ) { swap->state = &states[state->timeoutind]; - if ( (newjson= (*state->timeout)(myinfo,exchange,A,argjson,newjson,&serdata,&serdatalen)) == 0 ) + if ( (newjson= (*state->timeout)(myinfo,exchange,swap,argjson,newjson,&serdata,&serdatalen)) == 0 ) return(clonestr("{\"error\":\"instantdex_BTCswap null return from timeoutfunc\"}")); return(jprint(newjson,1)); } @@ -891,13 +918,13 @@ char *instantdex_statemachine(struct instantdex_stateinfo *states,int32_t numsta { if ( strcmp(cmdstr,state->events[i].cmdstr) == 0 ) { - if ( (newjson= (*state->process)(myinfo,exchange,A,argjson,newjson,&serdata,&serdatalen)) == 0 ) + if ( (newjson= (*state->process)(myinfo,exchange,swap,argjson,newjson,&serdata,&serdatalen)) == 0 ) { free_json(origjson); if ( strcmp("poll",state->events[i].sendcmd) == 0 ) { printf("poll event\n"); - return(instantdex_sendcmd(myinfo,&A->offer,newjson,state->events[i].sendcmd,myinfo->myaddr.persistent,0,serdata,serdatalen)); + return(instantdex_sendcmd(myinfo,&swap->mine.offer,newjson,state->events[i].sendcmd,myinfo->myaddr.persistent,0,serdata,serdatalen)); } else { @@ -913,7 +940,7 @@ char *instantdex_statemachine(struct instantdex_stateinfo *states,int32_t numsta if ( state->events[i].nextstateind > 1 ) { swap->state = &states[state->events[i].nextstateind]; - return(instantdex_sendcmd(myinfo,&A->offer,newjson,state->events[i].sendcmd,swap->othertrader,INSTANTDEX_HOPS,serdata,serdatalen)); + return(instantdex_sendcmd(myinfo,&swap->mine.offer,newjson,state->events[i].sendcmd,swap->othertrader,INSTANTDEX_HOPS,serdata,serdatalen)); } else return(clonestr("{\"error\":\"instantdex_statemachine: illegal state\"}")); } else return(clonestr("{\"result\":\"instantdex_statemachine: processed\"}")); } @@ -1124,7 +1151,7 @@ char *instantdex_advance(struct supernet_info *myinfo,bits256 *sharedprivs,int32 } else return(clonestr("{\"error\":\"instantdex_BTCswap advance cant find statusjson\"}")); } -void instantdex_pendingnotice(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,uint64_t basevolume64) +void instantdex_pendingnotice(struct supernet_info *myinfo,struct exchange_info *exchange,struct bitcoin_swapinfo *swap,uint64_t basevolume64) { // printf("need to start monitoring thread\n"); ap->pendingvolume64 -= basevolume64; @@ -1133,7 +1160,7 @@ void instantdex_pendingnotice(struct supernet_info *myinfo,struct exchange_info char *instantdex_BTCswap(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,char *cmdstr,struct instantdex_msghdr *msg,cJSON *argjson,char *remoteaddr,uint64_t signerbits,uint8_t *data,int32_t datalen) // receiving side { uint8_t secret160[20]; bits256 hash,traderpub,A0,B0,sharedprivs[4]; uint64_t satoshis[2]; - cJSON *newjson; struct instantdex_accept *ap; char *retstr=0,*str; + cJSON *newjson; char *retstr=0,*str; int32_t locktime,isbob=0,offerdir = 0; struct iguana_info *coinbtc,*other; if ( exchange == 0 ) return(clonestr("{\"error\":\"instantdex_BTCswap null exchange ptr\"}"));