Browse Source

fsm

release/v0.1
jl777 9 years ago
parent
commit
5de0902665
  1. 158
      deprecated/obsolete.h
  2. 4
      iguana/SuperNET_category.c
  3. 24
      iguana/exchanges/bitcoin.c
  4. 8
      iguana/exchanges777.h
  5. 10
      iguana/iguana_exchanges.c
  6. 378
      iguana/iguana_instantdex.c
  7. 324
      iguana/swaps/iguana_BTCswap.c

158
deprecated/obsolete.h

@ -13407,5 +13407,163 @@ len = 0;
} }
} }
} }
/*cJSON *instantdex_acceptsendjson(struct instantdex_accept *ap)
{
cJSON *json = cJSON_CreateObject();
jaddstr(json,"b",ap->offer.base);
jaddstr(json,"r",ap->offer.rel);
jaddnum(json,"n",ap->offer.nonce);
jaddnum(json,"e",ap->offer.expiration);
jaddnum(json,"s",ap->offer.myside);
jaddnum(json,"d",ap->offer.acceptdir);
jadd64bits(json,"p",ap->offer.price64);
jadd64bits(json,"v",ap->offer.basevolume64);
jadd64bits(json,"o",ap->offer.offer64);
jadd64bits(json,"id",ap->orderid);
return(json);
}*/
if ( A->offer.price64 != 0 )
{
if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,A->orderid,"*","*",1)) != 0 )
{
swap->state++;
A->info = swap;
printf(">>>>>>>>>> PENDING ORDER %llu\n",(long long)A->orderid);
}
}
if ( ap == 0 )
{
printf("couldnt find accept?? dir.%d orderid.%llu\n",ap->offer.acceptdir,(long long)A->orderid);
free(swap);
return(clonestr("{\"error\":\"couldnt find order just created\"}"));
}
if ( strncmp(cmdstr,"BTC",3) == 0 )
else if ( strncmp(cmdstr,"NXT",3) == 0 )
retstr = instantdex_NXTswap(myinfo,exchange,&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,serdata,datalen);
else if ( strncmp(cmdstr,"ALT",3) == 0 )
retstr = instantdex_ALTswap(myinfo,exchange,&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,serdata,datalen);
else if ( strncmp(cmdstr,"PAX",3) == 0 )
retstr = instantdex_PAXswap(myinfo,exchanges777_find("PAX"),&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,serdata,datalen);
else return(clonestr("{\"error\":\"unrecognized atomic swap family\"}"));
if ( ap != 0 )
{
ap->info = A.info;
ap->pendingvolume64 = A.pendingvolume64;
}
//printf("after swap ap.%p (%s)\n",ap,retstr);
return(retstr);
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 *serdata,int32_t serdatalen) // receiving side
{
uint64_t satoshis[2]; int32_t offerdir = 0; double minperc; uint64_t insurance,relsatoshis;
struct instantdex_accept *ap; struct bitcoin_swapinfo *swap = 0; bits256 orderhash,traderpub;
struct iguana_info *coinbtc,*altcoin; cJSON *newjson=0; char *retstr=0;
relsatoshis = instantdex_relsatoshis(A->offer.price64,A->offer.basevolume64);
traderpub = jbits256(argjson,"traderpub");
if ( (minperc= jdouble(argjson,"p")) < INSTANTDEX_MINPERC )
minperc = INSTANTDEX_MINPERC;
coinbtc = iguana_coinfind("BTC");
insurance = (satoshis[1] * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee prevents papercut attack
offerdir = instantdex_bidaskdir(A);
vcalc_sha256(0,orderhash.bytes,(void *)&A->offer,sizeof(ap->offer));
swap = A->info;
if ( bits256_cmp(traderpub,myinfo->myaddr.persistent) == 0 )
{
printf("got my own packet\n");
return(clonestr("{\"result\":\"got my own packet\"}"));
}
printf("T.%d [%s] got %s.(%s/%s) %.8f vol %.8f %llu offerside.%d offerdir.%d swap.%p decksize.%ld/datalen.%d\n",bits256_cmp(traderpub,myinfo->myaddr.persistent),swap!=0?swap->nextstate:"",cmdstr,A->offer.base,A->offer.rel,dstr(A->offer.price64),dstr(A->offer.basevolume64),(long long)A->orderid,A->offer.myside,A->offer.acceptdir,A->info,sizeof(swap->deck),serdatalen);
if ( exchange == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap null exchange ptr\"}"));
if ( (altcoin= iguana_coinfind(A->offer.base)) == 0 || coinbtc == 0 )
{
printf("other.%p coinbtc.%p (%s/%s)\n",altcoin,coinbtc,A->offer.base,A->offer.rel);
return(clonestr("{\"error\":\"instantdex_BTCswap cant find btc or other coin info\"}"));
}
if ( strcmp(A->offer.rel,"BTC") != 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap offer non BTC rel\"}"));
if ( orderhash.txid != A->orderid )
return(clonestr("{\"error\":\"txid mismatches orderid\"}"));
if ( strcmp(cmdstr,"offer") == 0 ) // receiver is networkwide
{
if ( A->offer.expiration < (time(NULL) + INSTANTDEX_DURATION) )
return(clonestr("{\"error\":\"instantdex_BTCswap offer too close to expiration\"}"));
if ( (ap= instantdex_acceptable(myinfo,exchange,A,acct777_nxt64bits(traderpub),minperc)) != 0 )
{
if ( A->info == 0 )
{
swap = calloc(1,sizeof(struct bitcoin_swapinfo));
swap->choosei = swap->otherschoosei = -1;
swap->othertrader = traderpub;
if ( offerdir > 0 )
swap->bidid = A->orderid;
else swap->askid = A->orderid;
swap->isbob = (A->offer.myside ^ 1);
printf("%p SET ISBOB.%d orderid.%llu\n",ap,swap->isbob,(long long)A->orderid);
}
char str[65]; printf("GOT OFFER! %p (%s/%s) other.%s myside.%d next.%s\n",A->info,A->offer.base,A->offer.rel,bits256_str(str,traderpub),swap->isbob,swap->nextstate);
if ( (A->info= swap) != 0 )
{
ap->info = swap;
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,orderhash,A,1)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap offer null newjson\"}"));
else
{
// verify feetx
instantdex_pendingnotice(myinfo,exchange,ap,A->offer.basevolume64);
if ( (retstr= instantdex_choosei(swap,newjson,argjson,serdata,serdatalen)) != 0 )
{
return(retstr);
}
else
{
// generate feetx to send
if ( swap->isbob != 0 )
strcpy(swap->nextstate,"step2");
else strcpy(swap->nextstate,"step3");
return(instantdex_sendcmd(myinfo,&A->offer,newjson,"BTCstep1",traderpub,INSTANTDEX_HOPS,swap->deck,sizeof(swap->deck)));
}
}
} else return(clonestr("{\"error\":\"couldnt allocate swap info\"}"));
}
else
{
printf("no matching trade for %llu -> InstantDEX_minaccept isbob.%d\n",(long long)A->orderid,A->offer.myside);
if ( instantdex_offerfind(myinfo,exchange,0,0,A->orderid,"*","*",1) == 0 )
{
ap = calloc(1,sizeof(*ap));
*ap = *A;
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0);
return(clonestr("{\"result\":\"added new order to orderbook\"}"));
} else return(clonestr("{\"result\":\"order was already in orderbook\"}"));
}
}
else if ( swap == 0 )
return(clonestr("{\"error\":\"no swap info\"}"));
if ( offerdir > 0 )
swap->bidid = A->orderid;
else swap->askid = A->orderid;
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",A->offer.base,A->offer.rel,dstr(A->offer.price64),dstr(A->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] = A->offer.basevolume64;
swap->satoshis[1] = relsatoshis;
swap->insurance = (relsatoshis * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee
if ( swap->minperc < minperc )
swap->minperc = minperc;
return(instantdex_statemachine(myinfo,exchange,A,cmdstr,swap,argjson,serdata,serdatalen,altcoin,coinbtc));
}
#endif #endif

4
iguana/SuperNET_category.c

@ -325,8 +325,8 @@ char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag
broadcastflag = category_broadcastflag(myinfo,categoryhash,subhash,broadcastflag); broadcastflag = category_broadcastflag(myinfo,categoryhash,subhash,broadcastflag);
maxdelay = category_maxdelay(myinfo,categoryhash,subhash,maxdelay); maxdelay = category_maxdelay(myinfo,categoryhash,subhash,maxdelay);
retstr = SuperNET_DHTsend(myinfo,0,categoryhash,subhash,hexmsg,maxdelay,broadcastflag,plaintext); retstr = SuperNET_DHTsend(myinfo,0,categoryhash,subhash,hexmsg,maxdelay,broadcastflag,plaintext);
if ( 0 && argjson != 0 ) //if ( 0 && argjson != 0 )
SuperNET_hexmsgprocess(myinfo,retjson,argjson,hexmsg,remoteaddr); // SuperNET_hexmsgprocess(myinfo,retjson,argjson,hexmsg,remoteaddr);
if ( hexmsg != message) if ( hexmsg != message)
free(hexmsg); free(hexmsg);
if ( retjson != 0 ) if ( retjson != 0 )

24
iguana/exchanges/bitcoin.c

@ -705,7 +705,7 @@ int32_t iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp,uint8_t *
scriptlen = iguana_scriptgen(coin,&vp->M,&vp->N,vp->coinaddr,script,asmstr,vp->rmd160,vp->type,(const struct vin_info *)vp,vout); scriptlen = iguana_scriptgen(coin,&vp->M,&vp->N,vp->coinaddr,script,asmstr,vp->rmd160,vp->type,(const struct vin_info *)vp,vout);
if ( scriptlen != pk_scriptlen || (scriptlen != 0 && memcmp(script,pk_script,scriptlen) != 0) ) if ( scriptlen != pk_scriptlen || (scriptlen != 0 && memcmp(script,pk_script,scriptlen) != 0) )
{ {
if ( vp->type != IGUANA_SCRIPT_OPRETURN && vp->type != IGUANA_SCRIPT_DATA ) if ( vp->type != IGUANA_SCRIPT_OPRETURN && vp->type != IGUANA_SCRIPT_DATA && vp->type != IGUANA_SCRIPT_STRANGE )
{ {
int32_t i; int32_t i;
printf("\n--------------------\n"); printf("\n--------------------\n");
@ -1375,7 +1375,6 @@ rawtxstr = refstr;
V = 0; V = 0;
vpnstr[0] = 0; vpnstr[0] = 0;
memset(&msgtx,0,sizeof(msgtx)); memset(&msgtx,0,sizeof(msgtx));
if ( len < maxsize ) if ( len < maxsize )
{ {
decode_hex(serialized,len,rawtxstr); decode_hex(serialized,len,rawtxstr);
@ -1466,7 +1465,7 @@ double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchang
cJSON *retjson,*bids,*asks; double hbla; cJSON *retjson,*bids,*asks; double hbla;
bids = cJSON_CreateArray(); bids = cJSON_CreateArray();
asks = cJSON_CreateArray(); asks = cJSON_CreateArray();
instantdex_offerfind(SuperNET_MYINFO(0),exchange,bids,asks,0,base,rel); instantdex_offerfind(SuperNET_MYINFO(0),exchange,bids,asks,0,base,rel,1);
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
cJSON_AddItemToObject(retjson,"bids",bids); cJSON_AddItemToObject(retjson,"bids",bids);
cJSON_AddItemToObject(retjson,"asks",asks); cJSON_AddItemToObject(retjson,"asks",asks);
@ -1542,19 +1541,16 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha
jaddnum(json,"volume",volume); jaddnum(json,"volume",volume);
jaddstr(json,"BTC",myinfo->myaddr.BTC); jaddstr(json,"BTC",myinfo->myaddr.BTC);
//printf("trade dir.%d (%s/%s) %.6f vol %.8f\n",dir,base,"BTC",price,volume); //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 ) if ( (str= instantdex_queueaccept(myinfo,&ap,exchange,base,"BTC",price,volume,-dir,dir > 0 ? "BTC" : base,INSTANTDEX_OFFERDURATION,myinfo->myaddr.nxt64bits,0)) != 0 )
{ {
if ( (tmp= cJSON_Parse(str)) != 0 ) if ( (tmp= cJSON_Parse(str)) != 0 )
{ {
txid = j64bits(json,"orderid"); txid = j64bits(json,"orderid");
if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,txid,"*","*")) != 0 ) if ( (str= instantdex_btcoffer(myinfo,exchange,ap,json)) != 0 )
{ {
if ( (str= instantdex_btcoffer(myinfo,exchange,ap)) != 0 ) json = cJSON_CreateObject();
{ jaddstr(json,"BTCoffer",str);
json = cJSON_CreateObject(); } else printf("null return from btcoffer\n");
jaddstr(json,"BTCoffer",str);
} else printf("null return from btcoffer\n");
} else printf("couldnt find just added offer\n");
free_json(tmp); free_json(tmp);
} else printf("queueaccept return parse error.(%s)\n",str); } else printf("queueaccept return parse error.(%s)\n",str);
} else printf("null return queueaccept\n"); } else printf("null return queueaccept\n");
@ -1570,7 +1566,7 @@ char *ORDERSTATUS(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson
{ {
struct instantdex_accept *ap; cJSON *retjson; struct instantdex_accept *ap; cJSON *retjson;
struct supernet_info *myinfo = SuperNET_accountfind(argjson); struct supernet_info *myinfo = SuperNET_accountfind(argjson);
if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,orderid,"*","*")) != 0 ) if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,orderid,"*","*",1)) != 0 )
{ {
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
jadd(retjson,"result",instantdex_acceptjson(ap)); jadd(retjson,"result",instantdex_acceptjson(ap));
@ -1582,7 +1578,7 @@ char *CANCELORDER(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson
{ {
struct instantdex_accept *ap; cJSON *retjson; struct instantdex_accept *ap; cJSON *retjson;
struct supernet_info *myinfo = SuperNET_accountfind(argjson); struct supernet_info *myinfo = SuperNET_accountfind(argjson);
if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,orderid,"*","*")) != 0 ) if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,orderid,"*","*",1)) != 0 )
{ {
ap->dead = (uint32_t)time(NULL); ap->dead = (uint32_t)time(NULL);
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
@ -1598,7 +1594,7 @@ char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
struct supernet_info *myinfo = SuperNET_accountfind(argjson); struct supernet_info *myinfo = SuperNET_accountfind(argjson);
bids = cJSON_CreateArray(); bids = cJSON_CreateArray();
asks = cJSON_CreateArray(); asks = cJSON_CreateArray();
instantdex_offerfind(myinfo,exchange,bids,asks,0,"*","*"); instantdex_offerfind(myinfo,exchange,bids,asks,0,"*","*",1);
retjson = cJSON_CreateObject(); retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success"); jaddstr(retjson,"result","success");
jadd(retjson,"bids",bids); jadd(retjson,"bids",bids);

8
iguana/exchanges777.h

@ -52,7 +52,7 @@ struct exchange_info
uint32_t exchangeid,pollgap,lastpoll; uint32_t exchangeid,pollgap,lastpoll;
uint64_t lastnonce,exchangebits; double commission; uint64_t lastnonce,exchangebits; double commission;
void *privatedata; void *privatedata;
CURL *cHandle; queue_t requestQ,pricesQ,pendingQ[2],tradebotsQ,acceptableQ; CURL *cHandle; queue_t requestQ,pricesQ,pendingQ,tradebotsQ,acceptableQ;
}; };
struct instantdex_msghdr struct instantdex_msghdr
@ -98,7 +98,7 @@ struct instantdex_accept
struct instantdex_offer offer; struct instantdex_offer offer;
}; };
struct instantdex_accept *instantdex_offerfind(struct supernet_info *myinfo,struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel); 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_acceptjson(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); struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits,double minperc);
@ -117,9 +117,9 @@ 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 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); 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); 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);
void instantdex_update(struct supernet_info *myinfo); 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_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_btcoffer(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap); // Bob sending to network (Alice) char *instantdex_btcoffer(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,cJSON *argjson); // Bob sending to network (Alice)
#endif #endif

10
iguana/iguana_exchanges.c

@ -635,9 +635,10 @@ void exchanges777_loop(void *ptr)
{ {
if ( retstr != 0 ) if ( retstr != 0 )
free(retstr); free(retstr);
if ( retval == EXCHANGE777_ISPENDING ) //if ( retval == EXCHANGE777_ISPENDING )
queue_enqueue("Xpending",&exchange->pendingQ[0],&req->DL,0), flag++; // queue_enqueue("Xpending",&exchange->pendingQ,&req->DL,0), flag++;
else if ( retval == EXCHANGE777_REQUEUE ) //else
if ( retval == EXCHANGE777_REQUEUE )
queue_enqueue("requeue",&exchange->requestQ,&req->DL,0); queue_enqueue("requeue",&exchange->requestQ,&req->DL,0);
else else
{ {
@ -889,8 +890,7 @@ struct exchange_info *exchange_create(char *exchangestr,cJSON *argjson)
iguana_initQ(&exchange->requestQ,"request"); iguana_initQ(&exchange->requestQ,"request");
iguana_initQ(&exchange->acceptableQ,"acceptable"); iguana_initQ(&exchange->acceptableQ,"acceptable");
iguana_initQ(&exchange->tradebotsQ,"tradebots"); iguana_initQ(&exchange->tradebotsQ,"tradebots");
iguana_initQ(&exchange->pendingQ[0],"pending0"); iguana_initQ(&exchange->pendingQ,"pending");
iguana_initQ(&exchange->pendingQ[1],"pending1");
exchange->exchangeid = exchangeid; exchange->exchangeid = exchangeid;
safecopy(exchange->name,exchangestr,sizeof(exchange->name)); safecopy(exchange->name,exchangestr,sizeof(exchange->name));
exchange->exchangebits = stringbits(exchange->name); exchange->exchangebits = stringbits(exchange->name);

378
iguana/iguana_instantdex.c

@ -20,6 +20,120 @@
#define INSTANTDEX_HOPS 2 #define INSTANTDEX_HOPS 2
#define INSTANTDEX_DURATION 60 #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.
struct instantdex_event { char cmdstr[24],sendcmd[16]; struct instantdex_stateinfo *nextstate; };
struct instantdex_stateinfo
{
char name[24];
cJSON *(*process)(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,uint8_t **serdatap,int32_t *serdatalenp);
cJSON *(*timeout)(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,uint8_t **serdatap,int32_t *serdatalenp);
struct instantdex_stateinfo *timeoutevent,*errorevent;
struct instantdex_event *events; int32_t numevents;
};
struct bitcoin_swapinfo
{
bits256 privkeys[777],mypubs[2],otherpubs[2],privAm,pubAm,privBn,pubBn;
bits256 orderhash,dtxid,ptxid,aptxid,astxid,stxid,ftxid,othertrader;
uint64_t otherscut[777][2],deck[777][2],satoshis[2],insurance,bidid,askid;
int32_t isbob,choosei,otherschoosei,cutverified,otherverifiedcut;
double minperc;
char altmsigaddr[64],*deposit,*payment,*altpayment,*altspend,*spendtx,*feetx;
struct instantdex_stateinfo *state; uint32_t expiration;
};
struct instantdex_stateinfo *BTC_states; int32_t BTC_numstates;
cJSON *instantdex_defaultprocess(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,uint8_t **serdatap,int32_t *serdatalenp)
{
cJSON *newjson=0; uint8_t *serdata = *serdatap; int32_t serdatalen = *serdatalenp;
*serdatap = 0, *serdatalenp = 0;
if ( serdata != 0 && serdatalen > 0 )
{
serdata[serdatalen-1] = 0;
}
return(newjson);
}
cJSON *instantdex_defaulttimeout(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,uint8_t **serdatap,int32_t *serdatalenp)
{
cJSON *newjson=0; uint8_t *serdata = *serdatap; int32_t serdatalen = *serdatalenp;
*serdatap = 0, *serdatalenp = 0;
if ( serdata != 0 && serdatalen > 0 )
{
serdata[serdatalen-1] = 0;
}
return(newjson);
}
struct instantdex_stateinfo instantdex_errorstate = { "error", instantdex_defaultprocess, instantdex_defaulttimeout };
struct instantdex_stateinfo instantdex_timeoutstate = { "timeout", instantdex_defaultprocess, instantdex_defaulttimeout };
struct instantdex_stateinfo *instantdex_statefind(struct instantdex_stateinfo *states,int32_t numstates,char *statename)
{
int32_t i; struct instantdex_stateinfo *state = 0;
if ( states != 0 && statename != 0 && numstates > 0 )
{
for (i=0; i<numstates; i++)
{
if ( (state= &states[i]) != 0 && strcmp(state->name,statename) == 0 )
return(state);
}
}
return(0);
}
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,uint8_t **serdatap,int32_t *serdatalenp),cJSON *(*timeout_func)(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,uint8_t **serdatap,int32_t *serdatalenp),char *timeoutstr,char *errorstr)
{
struct instantdex_stateinfo *timeoutstate,*errorstate,*state = 0;
if ( (state= instantdex_statefind(states,*numstatesp,name)) == 0 )
{
states = realloc(states,sizeof(*states) * (*numstatesp + 1));
state = &states[*numstatesp];
strcpy(state->name,name);
if ( (errorstate= instantdex_statefind(states,*numstatesp,errorstr)) == 0 )
errorstate = &instantdex_errorstate;
state->errorevent = errorstate;
if ( (timeoutstate= instantdex_statefind(states,*numstatesp,timeoutstr)) == 0 )
timeoutstate = &instantdex_timeoutstate;
state->timeoutevent = timeoutstate;
if ( (state->process= process_func) == 0 )
state->process = instantdex_defaultprocess;
if ( (state->timeout= timeout_func) == 0 )
state->timeout = instantdex_defaulttimeout;
(*numstatesp)++;
} else printf("statecreate error!!! (%s) already exists\n",name);
return(state);
}
struct instantdex_event *instantdex_addevent(struct instantdex_stateinfo *states,int32_t numstates,char *statename,char *cmdstr,char *sendcmd,char *nextstatename)
{
struct instantdex_stateinfo *nextstate,*state;
if ( (state= instantdex_statefind(states,numstates,statename)) != 0 && (nextstate= instantdex_statefind(states,numstates,nextstatename)) != 0 )
{
if ( (state->events= realloc(state->events,(state->numevents + 1) * sizeof(*state->events))) != 0 )
{
strcpy(state->events[state->numevents].cmdstr,cmdstr);
strcpy(state->events[state->numevents].sendcmd,sendcmd);
state->events[state->numevents].nextstate = nextstate;
state->numevents++;
}
return(state->events);
}
else
{
printf("cant add event (%s -> %s) without existing state and nextstate\n",statename,nextstatename);
return(0);
}
}
cJSON *InstantDEX_argjson(char *reference,char *message,char *othercoinaddr,char *otherNXTaddr,int32_t iter,int32_t val,int32_t val2) cJSON *InstantDEX_argjson(char *reference,char *message,char *othercoinaddr,char *otherNXTaddr,int32_t iter,int32_t val,int32_t val2)
{ {
cJSON *argjson = cJSON_CreateObject(); cJSON *argjson = cJSON_CreateObject();
@ -166,15 +280,12 @@ char *instantdex_sendcmd(struct supernet_info *myinfo,struct instantdex_offer *o
hexstr = malloc(msg->sig.allocsize*2 + 1); hexstr = malloc(msg->sig.allocsize*2 + 1);
init_hexbytes_noT(hexstr,(uint8_t *)msg,msg->sig.allocsize); init_hexbytes_noT(hexstr,(uint8_t *)msg,msg->sig.allocsize);
retstr = SuperNET_categorymulticast(myinfo,0,instantdexhash,desthash,hexstr,0,hops,1,argjson,0); retstr = SuperNET_categorymulticast(myinfo,0,instantdexhash,desthash,hexstr,0,hops,1,argjson,0);
free_json(argjson); free_json(argjson), free(hexstr), free(msg);
free(hexstr);
free(msg);
return(retstr); return(retstr);
} }
else else
{ {
free_json(argjson); free_json(argjson), free(msg);
free(msg);
printf("cant msgcreate datalen.%d\n",datalen); printf("cant msgcreate datalen.%d\n",datalen);
return(clonestr("{\"error\":\"couldnt create instantdex message\"}")); return(clonestr("{\"error\":\"couldnt create instantdex message\"}"));
} }
@ -318,7 +429,29 @@ cJSON *instantdex_acceptjson(struct instantdex_accept *ap)
return(item); return(item);
} }
struct instantdex_accept *instantdex_offerfind(struct supernet_info *myinfo,struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel) struct instantdex_accept *instantdex_pendingfind(struct supernet_info *myinfo,struct exchange_info *exchange,uint64_t orderid)
{
struct instantdex_accept PAD,*ap,*retap = 0; uint32_t now;
now = (uint32_t)time(NULL);
memset(&PAD,0,sizeof(PAD));
queue_enqueue("pendingQ",&exchange->pendingQ,&PAD.DL,0);
while ( (ap= queue_dequeue(&exchange->pendingQ,0)) != 0 && ap != &PAD )
{
if ( now < ap->offer.expiration && ap->dead == 0 )
{
if ( orderid == ap->orderid )
retap = ap;
}
else
{
printf("expired pending, need to take action\n");
}
queue_enqueue("pendingQ",&exchange->pendingQ,&PAD.DL,0);
}
return(retap);
}
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)
{ {
struct instantdex_accept PAD,*ap,*retap = 0; uint32_t now; cJSON *item; char *type; struct instantdex_accept PAD,*ap,*retap = 0; uint32_t now; cJSON *item; char *type;
now = (uint32_t)time(NULL); now = (uint32_t)time(NULL);
@ -331,7 +464,9 @@ struct instantdex_accept *instantdex_offerfind(struct supernet_info *myinfo,stru
//printf("find cmps %d %d %d %d %d %d\n",strcmp(base,"*") == 0,strcmp(base,ap->offer.base) == 0,strcmp(rel,"*") == 0,strcmp(rel,ap->offer.rel) == 0,orderid == 0,orderid == ap->orderid); //printf("find cmps %d %d %d %d %d %d\n",strcmp(base,"*") == 0,strcmp(base,ap->offer.base) == 0,strcmp(rel,"*") == 0,strcmp(rel,ap->offer.rel) == 0,orderid == 0,orderid == ap->orderid);
if ( (strcmp(base,"*") == 0 || strcmp(base,ap->offer.base) == 0) && (strcmp(rel,"*") == 0 || strcmp(rel,ap->offer.rel) == 0) && (orderid == 0 || orderid == ap->orderid) ) if ( (strcmp(base,"*") == 0 || strcmp(base,ap->offer.base) == 0) && (strcmp(rel,"*") == 0 || strcmp(rel,ap->offer.rel) == 0) && (orderid == 0 || orderid == ap->orderid) )
{ {
//printf("found match\n"); printf("found match.%p\n",ap);
if ( requeue == 0 && retap != 0 )
queue_enqueue("acceptableQ",&exchange->acceptableQ,&retap->DL,0);
retap = ap; retap = ap;
} }
if ( (item= instantdex_acceptjson(ap)) != 0 ) if ( (item= instantdex_acceptjson(ap)) != 0 )
@ -345,7 +480,11 @@ struct instantdex_accept *instantdex_offerfind(struct supernet_info *myinfo,stru
jaddi(asks,item); jaddi(asks,item);
} }
} }
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0); if ( ap != retap || requeue != 0 )
{
printf("requeue.%p\n",ap);
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0);
}
} else free(ap); } else free(ap);
} }
return(retap); return(retap);
@ -376,11 +515,14 @@ struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,str
{ {
//printf("found better price %f vs %f\n",dstr(ap->offer.price64),dstr(bestprice64)); //printf("found better price %f vs %f\n",dstr(ap->offer.price64),dstr(bestprice64));
bestprice64 = ap->offer.price64; bestprice64 = ap->offer.price64;
if ( retap != 0 )
queue_enqueue("acceptableQ",&exchange->acceptableQ,&retap->DL,0);
retap = ap; retap = ap;
} }
} }
} }
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0); if ( ap != retap)
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0);
} else free(ap); } else free(ap);
} }
return(retap); return(retap);
@ -474,73 +616,196 @@ int32_t instantdex_acceptextract(struct instantdex_accept *ap,cJSON *argjson)
return(0); return(0);
} }
/*cJSON *instantdex_acceptsendjson(struct instantdex_accept *ap)
{
cJSON *json = cJSON_CreateObject();
jaddstr(json,"b",ap->offer.base);
jaddstr(json,"r",ap->offer.rel);
jaddnum(json,"n",ap->offer.nonce);
jaddnum(json,"e",ap->offer.expiration);
jaddnum(json,"s",ap->offer.myside);
jaddnum(json,"d",ap->offer.acceptdir);
jadd64bits(json,"p",ap->offer.price64);
jadd64bits(json,"v",ap->offer.basevolume64);
jadd64bits(json,"o",ap->offer.offer64);
jadd64bits(json,"id",ap->orderid);
return(json);
}*/
#include "swaps/iguana_BTCswap.c" #include "swaps/iguana_BTCswap.c"
#include "swaps/iguana_ALTswap.c" #include "swaps/iguana_ALTswap.c"
#include "swaps/iguana_NXTswap.c" #include "swaps/iguana_NXTswap.c"
#include "swaps/iguana_PAXswap.c" #include "swaps/iguana_PAXswap.c"
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 datalen) char *instantdex_swapset(struct supernet_info *myinfo,struct instantdex_accept *A,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= A->info) == 0 )
return(clonestr("{\"error\":\"no swapinfo set\"}"));
relsatoshis = instantdex_relsatoshis(A->offer.price64,A->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(A);
vcalc_sha256(0,orderhash.bytes,(void *)&A->offer,sizeof(A->offer));
if ( offerdir > 0 )
swap->bidid = A->orderid;
else swap->askid = A->orderid;
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",A->offer.base,A->offer.rel,dstr(A->offer.price64),dstr(A->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] = A->offer.basevolume64;
swap->satoshis[1] = relsatoshis;
swap->insurance = (relsatoshis * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee
if ( swap->minperc < minperc )
swap->minperc = minperc;
return(0);
}
char *instantdex_btcoffer(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson) // Bob sending to network (Alice)
{
struct iguana_info *other; struct bitcoin_swapinfo *swap; int32_t isbob; cJSON *newjson; char *retstr;
if ( strcmp(A->offer.rel,"BTC") != 0 )
{
printf("rel not BTC?!\n");
return(clonestr("{\"error\":\"invalid othercoin\"}"));
}
else if ( (other= iguana_coinfind(A->offer.base)) == 0 )
return(clonestr("{\"error\":\"invalid othercoin\"}"));
else if ( A->offer.price64 <= 0 || A->offer.basevolume64 <= 0 )
{
printf("illegal price %.8f or volume %.8f\n",dstr(A->offer.price64),dstr(A->offer.basevolume64));
return(clonestr("{\"error\":\"illegal price or volume\"}"));
}
isbob = (A->offer.myside == 1);
swap = calloc(1,sizeof(struct bitcoin_swapinfo)), swap->isbob = isbob, swap->choosei = swap->otherschoosei = -1;
A->info = swap;
if ( (retstr= instantdex_swapset(myinfo,A,argjson)) != 0 )
return(retstr);
A->orderid = swap->orderhash.txid;
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,swap->orderhash,A,1)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap offer null newjson\"}"));
if ( instantdex_pubkeyargs(swap,newjson,777+2,myinfo->persistent_priv,swap->orderhash,0x02+isbob) != 777+2 )
{
printf("error from pubkeyargs\n");
free(swap), free(A);
return(clonestr("{\"error\":\"highly unlikely run of 02 pubkeys\"}"));
}
else
{
queue_enqueue("pendingQ",&exchange->pendingQ,&A->DL,0);
swap->state = instantdex_statefind(BTC_states,BTC_numstates,swap->isbob != 0 ? "BOB_sentoffer" : "ALICE_sentoffer");
return(instantdex_sendcmd(myinfo,&A->offer,newjson,"BTCoffer",GENESIS_PUBKEY,INSTANTDEX_HOPS,swap->deck,sizeof(swap->deck)));
}
}
char *instantdex_gotoffer(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,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 orderhash,traderpub;
struct iguana_info *coinbtc,*altcoin; cJSON *newjson=0; char *retstr=0;
swap = A->info;
coinbtc = iguana_coinfind("BTC");
traderpub = jbits256(argjson,"traderpub");
if ( bits256_cmp(traderpub,myinfo->myaddr.persistent) == 0 )
{
printf("got my own packet\n");
return(clonestr("{\"result\":\"got my own packet\"}"));
}
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),A->offer.base,A->offer.rel,dstr(A->offer.price64),dstr(A->offer.basevolume64),(long long)A->orderid,A->offer.myside,A->offer.acceptdir,A->info,sizeof(swap->deck),serdatalen);
if ( exchange == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap null exchange ptr\"}"));
if ( (altcoin= iguana_coinfind(A->offer.base)) == 0 || coinbtc == 0 )
{
printf("other.%p coinbtc.%p (%s/%s)\n",altcoin,coinbtc,A->offer.base,A->offer.rel);
return(clonestr("{\"error\":\"instantdex_BTCswap cant find btc or other coin info\"}"));
}
if ( strcmp(A->offer.rel,"BTC") != 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap offer non BTC rel\"}"));
if ( A->offer.expiration < (time(NULL) + INSTANTDEX_DURATION) )
return(clonestr("{\"error\":\"instantdex_BTCswap offer too close to expiration\"}"));
if ( A->info == 0 )
{
A->info = swap = calloc(1,sizeof(struct bitcoin_swapinfo));
swap->choosei = swap->otherschoosei = -1;
swap->isbob = (A->offer.myside ^ 1);
if ( (retstr= instantdex_swapset(myinfo,A,argjson)) != 0 )
return(retstr);
if ( instantdex_pubkeyargs(swap,newjson,2+777,myinfo->persistent_priv,swap->orderhash,0x02 + swap->isbob) != 2+777 )
{
printf("error generating pubkeyargs\n");
return(0);
}
char str[65]; printf("GOT OFFER! %p (%s/%s) other.%s myside.%d\n",A->info,A->offer.base,A->offer.rel,bits256_str(str,traderpub),swap->isbob);
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,orderhash,A,1)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap offer null newjson\"}"));
else
{
// verify feetx
instantdex_pendingnotice(myinfo,exchange,A,A->offer.basevolume64);
if ( (retstr= instantdex_choosei(swap,newjson,argjson,serdata,serdatalen)) != 0 )
return(retstr);
else
{
// generate feetx to send
swap->state = instantdex_statefind(BTC_states,BTC_numstates,swap->isbob != 0 ? "BOB_gotoffer" : "ALICE_gotoffer");
return(instantdex_sendcmd(myinfo,&A->offer,newjson,"BTCchose",traderpub,INSTANTDEX_HOPS,swap->deck,sizeof(swap->deck)));
}
}
} else return(clonestr("{\"error\":\"couldnt allocate swap info\"}"));
}
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; char cmdstr[16]; struct exchange_info *exchange; double minperc;
struct instantdex_accept A,*ap = 0; bits256 traderpub; struct instantdex_accept A,*ap = 0; bits256 traderpub;
if ( BTC_states == 0 )
BTC_states = BTC_initFSM(&BTC_numstates);
exchange = exchanges777_find("bitcoin"); exchange = exchanges777_find("bitcoin");
memset(cmdstr,0,sizeof(cmdstr)), memcpy(cmdstr,msg->cmd,sizeof(msg->cmd)); memset(cmdstr,0,sizeof(cmdstr)), memcpy(cmdstr,msg->cmd,sizeof(msg->cmd));
if ( argjson != 0 ) if ( argjson != 0 )
{ {
traderpub = jbits256(argjson,"traderpub"); traderpub = jbits256(argjson,"traderpub");
memset(&A,0,sizeof(A)); memset(&A,0,sizeof(A));
A.offer = *offer;
if ( j64bits(argjson,"id") != orderhash.txid ) if ( j64bits(argjson,"id") != orderhash.txid )
{ {
printf("orderhash %llu mismatch id.%llu\n",(long long)orderhash.txid,(long long)j64bits(argjson,"id")); printf("orderhash %llu mismatch id.%llu\n",(long long)orderhash.txid,(long long)j64bits(argjson,"id"));
return(clonestr("{\"error\":\"orderhash mismatch\"}")); return(clonestr("{\"error\":\"orderhash mismatch\"}"));
} }
//char str[65],str2[65]; A.offer = *offer;
/**/
//else printf("got mismatched traderpub.%s vs %s\n",bits256_str(str,traderpub),bits256_str(str2,myinfo->myaddr.persistent));
A.orderid = orderhash.txid; A.orderid = orderhash.txid;
if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,A.orderid,"*","*")) != 0 ) if ( strcmp(cmdstr,"BTCoffer") == 0 )
{ {
A = *ap; if ( (minperc= jdouble(argjson,"p")) < INSTANTDEX_MINPERC )
minperc = INSTANTDEX_MINPERC;
if ( (ap= instantdex_acceptable(myinfo,exchange,&A,acct777_nxt64bits(traderpub),minperc)) != 0 )
{
return(instantdex_gotoffer(myinfo,exchange,ap,msg,argjson,remoteaddr,signerbits,serdata,serdatalen));
}
else
{
printf("no matching trade for %llu -> InstantDEX_minaccept isbob.%d\n",(long long)A.orderid,A.offer.myside);
if ( instantdex_offerfind(myinfo,exchange,0,0,A.orderid,"*","*",1) == 0 )
{
ap = calloc(1,sizeof(*ap));
*ap = A;
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0);
return(clonestr("{\"result\":\"added new order to orderbook\"}"));
} else return(clonestr("{\"result\":\"order was already in orderbook\"}"));
}
} }
else if ( strcmp(cmdstr+3,"offer") != 0 ) else if ( (ap= instantdex_pendingfind(myinfo,exchange,A.orderid)) != 0 )
{ {
printf("cant find existing order.%llu that matches\n",(long long)A.orderid); if ( ap->info == 0 )
return(clonestr("{\"error\":\"cant find matching order\"}")); {
printf("null swap for orderid.%llu\n",(long long)ap->orderid);
return(clonestr("{\"error\":\"no swap for orderid\"}"));
}
return(instantdex_statemachine(myinfo,exchange,ap,cmdstr,argjson,serdata,serdatalen));
} }
//printf("call (%s/%s) swap baserel.%d acceptdir.%d\n",A.offer.base,A.offer.rel,A.offer.myside,A.offer.acceptdir); else
if ( strncmp(cmdstr,"BTC",3) == 0 )
retstr = instantdex_BTCswap(myinfo,exchange,&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,serdata,datalen);
else if ( strncmp(cmdstr,"NXT",3) == 0 )
retstr = instantdex_NXTswap(myinfo,exchange,&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,serdata,datalen);
else if ( strncmp(cmdstr,"ALT",3) == 0 )
retstr = instantdex_ALTswap(myinfo,exchange,&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,serdata,datalen);
else if ( strncmp(cmdstr,"PAX",3) == 0 )
retstr = instantdex_PAXswap(myinfo,exchanges777_find("PAX"),&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,serdata,datalen);
else return(clonestr("{\"error\":\"unrecognized atomic swap family\"}"));
if ( ap != 0 )
{ {
ap->info = A.info; printf("cant find existing order.%llu that matches\n",(long long)A.orderid);
ap->pendingvolume64 = A.pendingvolume64; return(clonestr("{\"error\":\"cant find matching order\"}"));
} }
//printf("after swap ap.%p (%s)\n",ap,retstr);
return(retstr);
} }
return(clonestr("{\"error\":\"request needs argjson\"}")); return(clonestr("{\"error\":\"request needs argjson\"}"));
} }
@ -551,6 +816,8 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char
uint8_t *serdata; struct supernet_info *myinfos[64]; struct instantdex_offer rawoffer; uint8_t *serdata; struct supernet_info *myinfos[64]; struct instantdex_offer rawoffer;
bits256 orderhash; uint64_t signerbits; uint8_t tmp[sizeof(msg->sig)]; char *retstr = 0; bits256 orderhash; uint64_t signerbits; uint8_t tmp[sizeof(msg->sig)]; char *retstr = 0;
cJSON *retjson,*item,*argjson = 0; cJSON *retjson,*item,*argjson = 0;
if ( BTC_states == 0 )
BTC_states = BTC_initFSM(&BTC_numstates);
datalen = len - (int32_t)sizeof(msg->sig); datalen = len - (int32_t)sizeof(msg->sig);
serdata = (void *)((long)msg + sizeof(msg->sig)); serdata = (void *)((long)msg + sizeof(msg->sig));
//printf("a signed datalen.%d allocsize.%d crc.%x\n",datalen,msg->sig.allocsize,calc_crc32(0,serdata,datalen)); //printf("a signed datalen.%d allocsize.%d crc.%x\n",datalen,msg->sig.allocsize,calc_crc32(0,serdata,datalen));
@ -619,7 +886,7 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char
return(retstr); 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) 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)
{ {
struct instantdex_accept *ap; int32_t myside; char *retstr; struct instantdex_accept *ap; int32_t myside; char *retstr;
*aptrp = 0; *aptrp = 0;
@ -636,7 +903,8 @@ char *instantdex_queueaccept(struct supernet_info *myinfo,struct instantdex_acce
printf("myside.(%s) != base.%s or rel.%s\n",mysidestr,base,rel); 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);
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0); if ( queueflag != 0 )
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0);
retstr = jprint(instantdex_acceptjson(ap),1); retstr = jprint(instantdex_acceptjson(ap),1);
//printf("acceptableQ %llu (%s)\n",(long long)ap->orderid,retstr); //printf("acceptableQ %llu (%s)\n",(long long)ap->orderid,retstr);
return(retstr); return(retstr);
@ -670,7 +938,7 @@ TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,maxaccept,base,rel,maxprice,basevolume)
struct instantdex_accept *ap; struct instantdex_accept *ap;
myinfo = SuperNET_accountfind(json); myinfo = SuperNET_accountfind(json);
if ( remoteaddr == 0 ) if ( remoteaddr == 0 )
return(instantdex_queueaccept(myinfo,&ap,exchanges777_find("bitcoin"),base,rel,maxprice,basevolume,-1,rel,INSTANTDEX_OFFERDURATION,myinfo->myaddr.nxt64bits)); 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!\"}")); else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}"));
} }
@ -679,7 +947,7 @@ TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,minaccept,base,rel,minprice,basevolume)
struct instantdex_accept *ap; struct instantdex_accept *ap;
myinfo = SuperNET_accountfind(json); myinfo = SuperNET_accountfind(json);
if ( remoteaddr == 0 ) if ( remoteaddr == 0 )
return(instantdex_queueaccept(myinfo,&ap,exchanges777_find("bitcoin"),base,rel,minprice,basevolume,1,base,INSTANTDEX_OFFERDURATION,myinfo->myaddr.nxt64bits)); 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!\"}")); else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}"));
} }
#include "../includes/iguana_apiundefs.h" #include "../includes/iguana_apiundefs.h"

324
iguana/swaps/iguana_BTCswap.c

@ -23,24 +23,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 e) BEFORE Bob broadcasts deposit, Alice broadcasts BTC denominated fee in cltv so if trade isnt done fee is reclaimed
*/ */
#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.
struct bitcoin_swapinfo
{
bits256 privkeys[777],mypubs[2],otherpubs[2];
bits256 orderhash,privAm,pubAm,privBn,pubBn,dtxid,ptxid,aptxid,astxid,stxid,ftxid,othertrader;
uint64_t otherscut[777][2],deck[777][2],satoshis[2],insurance,bidid,askid;
int32_t isbob,choosei,otherschoosei,state,cutverified,otherverifiedcut;
double minperc;
char altmsigaddr[64],nextstate[16],*deposit,*payment,*altpayment,*altspend,*spendtx,*feetx;
};
int32_t instantdex_outputinsurance(struct iguana_info *coin,cJSON *txobj,int64_t insurance,uint64_t nonce) int32_t instantdex_outputinsurance(struct iguana_info *coin,cJSON *txobj,int64_t insurance,uint64_t nonce)
{ {
uint8_t rmd160[20],script[128]; int32_t n; uint8_t rmd160[20],script[128]; int32_t n;
@ -249,10 +231,10 @@ int32_t instantdex_altpaymentverify(struct supernet_info *myinfo,struct iguana_i
return(retval); return(retval);
} }
void instantdex_pendingnotice(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,struct instantdex_accept *A) void instantdex_pendingnotice(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,uint64_t basevolume64)
{ {
// printf("need to start monitoring thread\n"); // printf("need to start monitoring thread\n");
ap->pendingvolume64 -= A->offer.basevolume64; ap->pendingvolume64 -= basevolume64;
} }
bits256 instantdex_derivekeypair(bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) bits256 instantdex_derivekeypair(bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash)
@ -277,7 +259,8 @@ int32_t instantdex_pubkeyargs(struct bitcoin_swapinfo *swap,cJSON *newjson,int32
if ( n < 2 && numpubs > 2 ) if ( n < 2 && numpubs > 2 )
{ {
sprintf(buf+1,"%d",n); sprintf(buf+1,"%d",n);
jaddbits256(newjson,buf,pubi); if ( jobj(newjson,buf) == 0 )
jaddbits256(newjson,buf,pubi);
} }
else else
{ {
@ -388,7 +371,7 @@ cJSON *instantdex_newjson(struct supernet_info *myinfo,struct bitcoin_swapinfo *
{ {
cJSON *newjson; cJSON *newjson;
newjson = cJSON_CreateObject(); newjson = cJSON_CreateObject();
//printf("acceptsend.(%s)\n",jprint(newjson,0)); //printf("acceptsend.(%s)\n",jprint(newjson,0));
if ( swap->otherschoosei < 0 && jobj(argjson,"mychoosei") != 0 ) if ( swap->otherschoosei < 0 && jobj(argjson,"mychoosei") != 0 )
{ {
//printf("otherschoosei.%d\n",swap->otherschoosei); //printf("otherschoosei.%d\n",swap->otherschoosei);
@ -398,20 +381,145 @@ cJSON *instantdex_newjson(struct supernet_info *myinfo,struct bitcoin_swapinfo *
if ( juint(argjson,"verified") != 0 ) if ( juint(argjson,"verified") != 0 )
swap->otherverifiedcut = 1; swap->otherverifiedcut = 1;
jaddnum(newjson,"verified",swap->otherverifiedcut); jaddnum(newjson,"verified",swap->otherverifiedcut);
if ( instantdex_pubkeyargs(swap,newjson,2+flag777*777,myinfo->persistent_priv,hash,0x02 + swap->isbob) != 2+flag777*777 ) if ( instantdex_pubkeyargs(swap,newjson,2,myinfo->persistent_priv,swap->orderhash,0x02+swap->isbob) == 2 )
instantdex_getpubs(swap,argjson,newjson);
else printf("ERROR: couldnt generate pubkeys\n");
return(newjson);
}
cJSON *BOB_processfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,uint8_t **serdatap,int32_t *serdatalenp)
{
cJSON *newjson=0; uint8_t *serdata = *serdatap; int32_t serdatalen = *serdatalenp;
*serdatap = 0, *serdatalenp = 0;
uint32_t reftime;
reftime = (uint32_t)(A->offer.expiration - INSTANTDEX_LOCKTIME*2);
if ( serdata != 0 && serdatalen > 0 )
{ {
printf("error generating pubkeyargs\n"); serdata[serdatalen-1] = 0;
return(0);
} }
instantdex_getpubs(swap,argjson,newjson);
return(newjson); return(newjson);
} }
char *instantdex_statemachine(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,char *cmdstr,struct bitcoin_swapinfo *swap,cJSON *argjson,uint8_t *serdata,int32_t serdatalen,struct iguana_info *altcoin,struct iguana_info *coinbtc) cJSON *ALICE_processfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,cJSON *argjson,uint8_t **serdatap,int32_t *serdatalenp)
{ {
uint32_t reftime; cJSON *newjson; char *retstr = 0; cJSON *newjson=0; uint8_t *serdata = *serdatap; int32_t serdatalen = *serdatalenp;
reftime = (uint32_t)(A->offer.expiration - INSTANTDEX_LOCKTIME*2); *serdatap = 0, *serdatalenp = 0;
printf("%llu/%llu cmd.(%s) vs next.(%s)\n",(long long)swap->bidid,(long long)swap->askid,cmdstr,swap->nextstate); if ( serdata != 0 && serdatalen > 0 )
{
serdata[serdatalen-1] = 0;
}
return(newjson);
}
struct instantdex_stateinfo *BTC_initFSM(int32_t *n)
{
struct instantdex_stateinfo *s = 0;
*n = 0;
// Four initial states are BOB_sentoffer, ALICE_gotoffer, ALICE_sentoffer, BOB_gotoffer
// the initiator includes signed feetx and deck of 777 keypairs
// the responder chooses one of 777 and returns it with "BTCchose" message
//
// "BTCabcde are message events from other party (message events capped at length 8)
// "lowercas" are special events, <TX> types: <fee>, <dep>osit, <alt>payment, <acl> is altcoin claim
// "<TX>found" means the other party's is confirmed at user specified confidence level
// BTC_cleanup state just unwinds pending swap as nothing has been committed yet
s = instantdex_statecreate(s,n,"BTC_cleanup",BOB_processfunc,0,0,0);
s = instantdex_statecreate(s,n,"BOB_claimdeposit",BOB_processfunc,0,0,0);
s = instantdex_statecreate(s,n,"ALICE_reclaim",BOB_processfunc,0,0,0);
s = instantdex_statecreate(s,n,"BOB_sentoffer",BOB_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"BOB_sentoffer","BTCchose","BTCprivs","BOB_sentprivs");
s = instantdex_statecreate(s,n,"BOB_sentprivs",BOB_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"BOB_sentprivs","feefound","BTCdeptx","BOB_sentdeposit");
s = instantdex_statecreate(s,n,"ALICE_gotoffer",ALICE_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"ALICE_gotoffer","BTCchose","BTCprivs","ALICE_waitdeptx");
s = instantdex_statecreate(s,n,"ALICE_waitdeptx",ALICE_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"ALICE_waitdeptx","BTCdeptx",0,"ALICE_wait3");
// following states cover all permutations of the three required events to make altpayment
s = instantdex_statecreate(s,n,"ALICE_wait3",ALICE_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"ALICE_wait3","feefound",0,"ALICE_waitdeposit_privs");
instantdex_addevent(s,*n,"ALICE_wait3","depfound",0,"ALICE_waitfee_privs");
instantdex_addevent(s,*n,"ALICE_wait3","BTCprivs",0,"ALICE_waitfee_deposit");
s = instantdex_statecreate(s,n,"ALICE_waitfee_privs",ALICE_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"ALICE_waitfee_privs","feefound",0,"ALICE_waitprivs");
instantdex_addevent(s,*n,"ALICE_waitfee_privs","BTCprivs",0,"ALICE_waitfee");
s = instantdex_statecreate(s,n,"ALICE_waitdeposit_privs",ALICE_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"ALICE_waitdeposit_privs","depfound",0,"ALICE_waitprivs");
instantdex_addevent(s,*n,"ALICE_waitdeposit_privs","BTCprivs",0,"ALICE_waitdeposit");
s = instantdex_statecreate(s,n,"ALICE_waitfee_deposit",ALICE_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"ALICE_waitfee_deposit","depfound",0,"ALICE_waitfee");
instantdex_addevent(s,*n,"ALICE_waitfee_deposit","feefound",0,"ALICE_waitdeposit");
// wait for last event and send out altpayment
s = instantdex_statecreate(s,n,"ALICE_waitprivs",ALICE_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"ALICE_waitprivs","BTCprivs","BTCalttx","ALICE_sentalt");
s = instantdex_statecreate(s,n,"ALICE_waitfee",ALICE_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"ALICE_waitfee","feefound","BTCalttx","ALICE_sentalt");
s = instantdex_statecreate(s,n,"ALICE_waitdeposit",ALICE_processfunc,0,"BTC_cleanup",0);
instantdex_addevent(s,*n,"ALICE_waitdeposit","depfound","BTCalttx","ALICE_sentalt");
// now Bob's turn to make sure altpayment is confirmed and send real payment
s = instantdex_statecreate(s,n,"BOB_sentdeposit",BOB_processfunc,0,"BTC_claimdeposit",0);
instantdex_addevent(s,*n,"BOB_sentdeposit","BTCalttx",0,"BOB_altconfirm");
s = instantdex_statecreate(s,n,"BOB_altconfirm",BOB_processfunc,0,"BTC_claimdeposit",0);
instantdex_addevent(s,*n,"BOB_altconfirm","altfound","BTCpaytx","BOB_sentpayment");
s = instantdex_statecreate(s,n,"ALICE_sentalt",ALICE_processfunc,0,"BTC_claimdeposit",0);
instantdex_addevent(s,*n,"ALICE_sentalt","BTCpaytx",0,"ALICE_waitconfirms");
s = instantdex_statecreate(s,n,"ALICE_waitconfirms",ALICE_processfunc,0,"BTC_claimdeposit",0);
instantdex_addevent(s,*n,"ALICE_waitconfirms","bobfound",0,"ALICE_reclaim");
instantdex_addevent(s,*n,"ALICE_waitconfirms","payfound","BTCprivM","ALICE_claimedbtc");
// if BTCprivM doesnt come in, altcoin needs to be monitored for alice's claim
s = instantdex_statecreate(s,n,"BOB_sentpayment",BOB_processfunc,0,"BTC_claimdeposit",0);
instantdex_addevent(s,*n,"BOB_sentpayment","aclfound","BTCdone","BOB_claimedalt");
instantdex_addevent(s,*n,"BOB_sentpayment","BTCprivM","BTCdone","BOB_claimedalt");
return(s);
}
char *instantdex_statemachine(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,char *cmdstr,cJSON *argjson,uint8_t *serdata,int32_t serdatalen)
{
uint32_t i; struct iguana_info *altcoin,*coinbtc; cJSON *newjson;
struct bitcoin_swapinfo *swap = A->info; struct instantdex_stateinfo *state = swap->state;
if ( state == 0 || swap == 0 || (coinbtc= iguana_coinfind("BTC")) == 0 || (altcoin= iguana_coinfind(A->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);
if ( swap->expiration != 0 && time(NULL) > swap->expiration )
{
swap->state = state->timeoutevent;
if ( (newjson= (*state->timeout)(myinfo,exchange,A,argjson,&serdata,&serdatalen)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap null return from timeoutfunc\"}"));
return(jprint(newjson,1));
}
for (i=0; i<state->numevents; i++)
{
if ( strcmp(cmdstr,state->events[i].cmdstr) == 0 )
{
if ( (newjson= (*state->process)(myinfo,exchange,A,argjson,&serdata,&serdatalen)) == 0 )
{
swap->state = state->errorevent;
return(clonestr("{\"error\":\"instantdex_statemachine: null return\"}"));
}
else
{
swap->state = state->events[i].nextstate;
if ( state->events[i].sendcmd != 0 )
return(instantdex_sendcmd(myinfo,&A->offer,newjson,state->events[i].sendcmd,swap->othertrader,INSTANTDEX_HOPS,serdata,serdatalen));
else return(clonestr("{\"result\":\"instantdex_statemachine: processed\"}"));
}
}
}
return(clonestr("{\"error\":\"instantdex_statemachine: unexpected state\"}"));
}
#ifdef xxx
if ( strcmp(cmdstr,"step1") == 0 && strcmp(swap->nextstate,cmdstr) == 0 ) // either if ( strcmp(cmdstr,"step1") == 0 && strcmp(swap->nextstate,cmdstr) == 0 ) // either
{ {
printf("%s got step1, should have other's choosei\n",swap->isbob!=0?"BOB":"alice"); printf("%s got step1, should have other's choosei\n",swap->isbob!=0?"BOB":"alice");
@ -426,7 +534,6 @@ char *instantdex_statemachine(struct supernet_info *myinfo,struct exchange_info
swap->privAm = swap->privkeys[swap->otherschoosei]; swap->privAm = swap->privkeys[swap->otherschoosei];
else swap->privBn = swap->privkeys[swap->otherschoosei]; else swap->privBn = swap->privkeys[swap->otherschoosei];
memset(&swap->privkeys[swap->otherschoosei],0,sizeof(swap->privkeys[swap->otherschoosei])); memset(&swap->privkeys[swap->otherschoosei],0,sizeof(swap->privkeys[swap->otherschoosei]));
swap->state++;
if ( (retstr= instantdex_choosei(swap,newjson,argjson,serdata,serdatalen)) != 0 ) if ( (retstr= instantdex_choosei(swap,newjson,argjson,serdata,serdatalen)) != 0 )
return(retstr); return(retstr);
/*if ( swap->isbob == 0 ) /*if ( swap->isbob == 0 )
@ -463,7 +570,6 @@ char *instantdex_statemachine(struct supernet_info *myinfo,struct exchange_info
return(clonestr("{\"error\":\"instantdex_BTCswap step2, both sides didnt validate\"}")); return(clonestr("{\"error\":\"instantdex_BTCswap step2, both sides didnt validate\"}"));
else else
{ {
swap->state++;
if ( (swap->deposit= instantdex_bobtx(myinfo,coinbtc,&swap->dtxid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->otherschoosei],reftime,swap->satoshis[swap->isbob],1)) != 0 ) if ( (swap->deposit= instantdex_bobtx(myinfo,coinbtc,&swap->dtxid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->otherschoosei],reftime,swap->satoshis[swap->isbob],1)) != 0 )
{ {
jaddstr(newjson,"deposit",swap->deposit); jaddstr(newjson,"deposit",swap->deposit);
@ -489,7 +595,6 @@ char *instantdex_statemachine(struct supernet_info *myinfo,struct exchange_info
return(clonestr("{\"error\":\"instantdex_BTCswap step3, both sides didnt validate\"}")); return(clonestr("{\"error\":\"instantdex_BTCswap step3, both sides didnt validate\"}"));
else if ( instantdex_paymentverify(myinfo,coinbtc,swap,A,argjson,1) == 0 ) else if ( instantdex_paymentverify(myinfo,coinbtc,swap,A,argjson,1) == 0 )
{ {
swap->state++;
//swap->pubAm = bitcoin_pubkey33(pubkey,swap->privkeys[swap->otherschoosei]); //swap->pubAm = bitcoin_pubkey33(pubkey,swap->privkeys[swap->otherschoosei]);
if ( (swap->altpayment= instantdex_alicetx(myinfo,altcoin,swap->altmsigaddr,&swap->aptxid,swap->pubAm,swap->pubBn,swap->satoshis[swap->isbob])) != 0 ) if ( (swap->altpayment= instantdex_alicetx(myinfo,altcoin,swap->altmsigaddr,&swap->aptxid,swap->pubAm,swap->pubBn,swap->satoshis[swap->isbob])) != 0 )
{ {
@ -514,7 +619,6 @@ char *instantdex_statemachine(struct supernet_info *myinfo,struct exchange_info
return(clonestr("{\"error\":\"instantdex_BTCswap step4, no pubAm\"}")); return(clonestr("{\"error\":\"instantdex_BTCswap step4, no pubAm\"}"));
else if ( instantdex_altpaymentverify(myinfo,altcoin,swap,A,argjson) == 0 ) else if ( instantdex_altpaymentverify(myinfo,altcoin,swap,A,argjson) == 0 )
{ {
swap->state++;
if ( (swap->deposit= instantdex_bobtx(myinfo,coinbtc,&swap->ptxid,swap->mypubs[1],swap->otherpubs[0],swap->privkeys[swap->otherschoosei],reftime,swap->satoshis[swap->isbob],0)) != 0 ) if ( (swap->deposit= instantdex_bobtx(myinfo,coinbtc,&swap->ptxid,swap->mypubs[1],swap->otherpubs[0],swap->privkeys[swap->otherschoosei],reftime,swap->satoshis[swap->isbob],0)) != 0 )
{ {
jaddstr(newjson,"payment",swap->payment); jaddstr(newjson,"payment",swap->payment);
@ -532,7 +636,6 @@ char *instantdex_statemachine(struct supernet_info *myinfo,struct exchange_info
return(clonestr("{\"error\":\"instantdex_BTCswap Alice step5 null newjson\"}")); return(clonestr("{\"error\":\"instantdex_BTCswap Alice step5 null newjson\"}"));
else if ( instantdex_paymentverify(myinfo,coinbtc,swap,A,argjson,0) == 0 ) else if ( instantdex_paymentverify(myinfo,coinbtc,swap,A,argjson,0) == 0 )
{ {
swap->state++;
strcpy(swap->nextstate,"step7"); strcpy(swap->nextstate,"step7");
/*if ( (swap->spendtx= instantdex_spendpayment(myinfo,coinbtc,&swap->stxid,swap,argjson,newjson)) != 0 ) /*if ( (swap->spendtx= instantdex_spendpayment(myinfo,coinbtc,&swap->stxid,swap,argjson,newjson)) != 0 )
{ {
@ -567,157 +670,10 @@ char *instantdex_statemachine(struct supernet_info *myinfo,struct exchange_info
if ( retstr == 0 ) if ( retstr == 0 )
retstr = clonestr("{\"error\":\"BTC swap null retstr\"}"); retstr = clonestr("{\"error\":\"BTC swap null retstr\"}");
if ( swap != 0 ) if ( swap != 0 )
printf("BTCSWAP next.(%s) (%s) isbob.%d state.%d verified.(%d %d)\n",swap->nextstate,cmdstr,swap->isbob,swap->state,swap->cutverified,swap->otherverifiedcut); printf("BTCSWAP next.(%s) (%s) isbob.%d nextstate.%s verified.(%d %d)\n",swap->nextstate,cmdstr,swap->isbob,swap->nextstate,swap->cutverified,swap->otherverifiedcut);
else printf("BTCSWAP.(%s)\n",retstr); else printf("BTCSWAP.(%s)\n",retstr);
return(retstr); return(retstr);
} #endif
char *instantdex_btcoffer(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A) // Bob sending to network (Alice)
{
struct iguana_info *other; struct bitcoin_swapinfo *swap; int32_t isbob;
cJSON *newjson; bits256 orderhash; struct instantdex_accept *ap = 0;
if ( strcmp(A->offer.rel,"BTC") != 0 )
{
printf("rel not BTC?!\n");
return(clonestr("{\"error\":\"invalid othercoin\"}"));
}
else if ( (other= iguana_coinfind(A->offer.base)) == 0 )
return(clonestr("{\"error\":\"invalid othercoin\"}"));
else if ( A->offer.price64 <= 0 || A->offer.basevolume64 <= 0 )
{
printf("illegal price %.8f or volume %.8f\n",dstr(A->offer.price64),dstr(A->offer.basevolume64));
return(clonestr("{\"error\":\"illegal price or volume\"}"));
}
isbob = (A->offer.myside == 1);
newjson = cJSON_CreateObject();
swap = calloc(1,sizeof(struct bitcoin_swapinfo)), swap->isbob = isbob, swap->choosei = swap->otherschoosei = -1;
strcpy(swap->nextstate,"step1");
vcalc_sha256(0,orderhash.bytes,(uint8_t *)&A->offer,sizeof(A->offer));
if ( instantdex_pubkeyargs(swap,newjson,777+2,myinfo->persistent_priv,orderhash,0x02+isbob) != 777+2 )
{
printf("error from pubkeyargs\n");
free(swap);
return(clonestr("{\"error\":\"highly unlikely run of 02 pubkeys\"}"));
}
if ( A->offer.price64 != 0 )
{
if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,A->orderid,"*","*")) != 0 )
{
swap->state++;
A->info = swap;
printf(">>>>>>>>>> PENDING ORDER %llu\n",(long long)A->orderid);
}
}
if ( ap == 0 )
{
printf("couldnt find accept?? dir.%d orderid.%llu\n",ap->offer.acceptdir,(long long)A->orderid);
free(swap);
return(clonestr("{\"error\":\"couldnt find order just created\"}"));
}
else return(instantdex_sendcmd(myinfo,&ap->offer,newjson,"BTCoffer",GENESIS_PUBKEY,INSTANTDEX_HOPS,swap->deck,sizeof(swap->deck)));
}
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 *serdata,int32_t serdatalen) // receiving side
{
uint64_t satoshis[2]; int32_t offerdir = 0; double minperc; uint64_t insurance,relsatoshis;
struct instantdex_accept *ap; struct bitcoin_swapinfo *swap = 0; bits256 orderhash,traderpub;
struct iguana_info *coinbtc,*altcoin; cJSON *newjson=0; char *retstr=0;
relsatoshis = instantdex_relsatoshis(A->offer.price64,A->offer.basevolume64);
traderpub = jbits256(argjson,"traderpub");
if ( (minperc= jdouble(argjson,"p")) < INSTANTDEX_MINPERC )
minperc = INSTANTDEX_MINPERC;
coinbtc = iguana_coinfind("BTC");
insurance = (satoshis[1] * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee prevents papercut attack
offerdir = instantdex_bidaskdir(A);
vcalc_sha256(0,orderhash.bytes,(void *)&A->offer,sizeof(ap->offer));
swap = A->info;
if ( bits256_cmp(traderpub,myinfo->myaddr.persistent) == 0 )
{
printf("got my own packet\n");
return(clonestr("{\"result\":\"got my own packet\"}"));
}
printf("T.%d [%s] got %s.(%s/%s) %.8f vol %.8f %llu offerside.%d offerdir.%d swap.%p decksize.%ld/datalen.%d\n",bits256_cmp(traderpub,myinfo->myaddr.persistent),swap!=0?swap->nextstate:"",cmdstr,A->offer.base,A->offer.rel,dstr(A->offer.price64),dstr(A->offer.basevolume64),(long long)A->orderid,A->offer.myside,A->offer.acceptdir,A->info,sizeof(swap->deck),serdatalen);
if ( exchange == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap null exchange ptr\"}"));
if ( (altcoin= iguana_coinfind(A->offer.base)) == 0 || coinbtc == 0 )
{
printf("other.%p coinbtc.%p (%s/%s)\n",altcoin,coinbtc,A->offer.base,A->offer.rel);
return(clonestr("{\"error\":\"instantdex_BTCswap cant find btc or other coin info\"}"));
}
if ( strcmp(A->offer.rel,"BTC") != 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap offer non BTC rel\"}"));
if ( orderhash.txid != A->orderid )
return(clonestr("{\"error\":\"txid mismatches orderid\"}"));
//if ( (swap= A->info) == 0 && strcmp(cmdstr,"offer") != 0 )
// return(clonestr("{\"error\":\"instantdex_BTCswap no swap info after offer\"}"));
if ( strcmp(cmdstr,"offer") == 0 && A->info == 0 ) // receiver is networkwide
{
if ( A->offer.expiration < (time(NULL) + INSTANTDEX_DURATION) )
return(clonestr("{\"error\":\"instantdex_BTCswap offer too close to expiration\"}"));
if ( (ap= instantdex_acceptable(myinfo,exchange,A,acct777_nxt64bits(traderpub),minperc)) != 0 )
{
if ( A->info == 0 )
{
swap = calloc(1,sizeof(struct bitcoin_swapinfo));
swap->choosei = swap->otherschoosei = -1;
swap->state++;
swap->othertrader = traderpub;
if ( offerdir > 0 )
swap->bidid = A->orderid;
else swap->askid = A->orderid;
swap->isbob = (A->offer.myside ^ 1);
printf("%p SET ISBOB.%d orderid.%llu\n",ap,swap->isbob,(long long)A->orderid);
}
char str[65]; printf("FOUND MATCH! %p (%s/%s) other.%s myside.%d next.%s\n",A->info,A->offer.base,A->offer.rel,bits256_str(str,traderpub),swap->isbob,swap->nextstate);
if ( (A->info= swap) != 0 )
{
ap->info = swap;
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,orderhash,A,1)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap offer null newjson\"}"));
else
{
// verify feetx
instantdex_pendingnotice(myinfo,exchange,ap,A);
if ( (retstr= instantdex_choosei(swap,newjson,argjson,serdata,serdatalen)) != 0 )
{
return(retstr);
}
else
{
// generate feetx to send
if ( swap->isbob != 0 )
strcpy(swap->nextstate,"step2");
else strcpy(swap->nextstate,"step3");
return(instantdex_sendcmd(myinfo,&A->offer,newjson,"BTCstep1",traderpub,INSTANTDEX_HOPS,swap->deck,sizeof(swap->deck)));
}
}
} else return(clonestr("{\"error\":\"couldnt allocate swap info\"}"));
}
else
{
printf("no matching trade for %llu -> InstantDEX_minaccept isbob.%d\n",(long long)A->orderid,A->offer.myside);
if ( instantdex_offerfind(myinfo,exchange,0,0,A->orderid,"*","*") == 0 )
{
ap = calloc(1,sizeof(*ap));
*ap = *A;
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0);
return(clonestr("{\"result\":\"added new order to orderbook\"}"));
} else return(clonestr("{\"result\":\"order was already in orderbook\"}"));
}
}
else if ( swap == 0 )
return(clonestr("{\"error\":\"no swap info\"}"));
if ( offerdir > 0 )
swap->bidid = A->orderid;
else swap->askid = A->orderid;
swap->satoshis[0] = A->offer.basevolume64;
swap->satoshis[1] = relsatoshis;
swap->insurance = (relsatoshis * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee
swap->orderhash = orderhash;
if ( swap->minperc < minperc )
swap->minperc = minperc;
return(instantdex_statemachine(myinfo,exchange,A,cmdstr,swap,argjson,serdata,serdatalen,altcoin,coinbtc));
}
#ifdef oldway #ifdef oldway
// https://github.com/TierNolan/bips/blob/bip4x/bip-atom.mediawiki // https://github.com/TierNolan/bips/blob/bip4x/bip-atom.mediawiki

Loading…
Cancel
Save