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

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);
maxdelay = category_maxdelay(myinfo,categoryhash,subhash,maxdelay);
retstr = SuperNET_DHTsend(myinfo,0,categoryhash,subhash,hexmsg,maxdelay,broadcastflag,plaintext);
if ( 0 && argjson != 0 )
SuperNET_hexmsgprocess(myinfo,retjson,argjson,hexmsg,remoteaddr);
//if ( 0 && argjson != 0 )
// SuperNET_hexmsgprocess(myinfo,retjson,argjson,hexmsg,remoteaddr);
if ( hexmsg != message)
free(hexmsg);
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);
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;
printf("\n--------------------\n");
@ -1375,7 +1375,6 @@ rawtxstr = refstr;
V = 0;
vpnstr[0] = 0;
memset(&msgtx,0,sizeof(msgtx));
if ( len < maxsize )
{
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;
bids = 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();
cJSON_AddItemToObject(retjson,"bids",bids);
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);
jaddstr(json,"BTC",myinfo->myaddr.BTC);
//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 )
{
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);
} else printf("null return from btcoffer\n");
} else printf("couldnt find just added offer\n");
json = cJSON_CreateObject();
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");
@ -1570,7 +1566,7 @@ char *ORDERSTATUS(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson
{
struct instantdex_accept *ap; cJSON *retjson;
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();
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 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);
retjson = cJSON_CreateObject();
@ -1598,7 +1594,7 @@ char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
struct supernet_info *myinfo = SuperNET_accountfind(argjson);
bids = cJSON_CreateArray();
asks = cJSON_CreateArray();
instantdex_offerfind(myinfo,exchange,bids,asks,0,"*","*");
instantdex_offerfind(myinfo,exchange,bids,asks,0,"*","*",1);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jadd(retjson,"bids",bids);

8
iguana/exchanges777.h

@ -52,7 +52,7 @@ struct exchange_info
uint32_t exchangeid,pollgap,lastpoll;
uint64_t lastnonce,exchangebits; double commission;
void *privatedata;
CURL *cHandle; queue_t requestQ,pricesQ,pendingQ[2],tradebotsQ,acceptableQ;
CURL *cHandle; queue_t requestQ,pricesQ,pendingQ,tradebotsQ,acceptableQ;
};
struct instantdex_msghdr
@ -98,7 +98,7 @@ struct instantdex_accept
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);
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 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);
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

10
iguana/iguana_exchanges.c

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

378
iguana/iguana_instantdex.c

@ -20,6 +20,120 @@
#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.
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 *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);
init_hexbytes_noT(hexstr,(uint8_t *)msg,msg->sig.allocsize);
retstr = SuperNET_categorymulticast(myinfo,0,instantdexhash,desthash,hexstr,0,hops,1,argjson,0);
free_json(argjson);
free(hexstr);
free(msg);
free_json(argjson), free(hexstr), free(msg);
return(retstr);
}
else
{
free_json(argjson);
free(msg);
free_json(argjson), free(msg);
printf("cant msgcreate datalen.%d\n",datalen);
return(clonestr("{\"error\":\"couldnt create instantdex message\"}"));
}
@ -318,7 +429,29 @@ cJSON *instantdex_acceptjson(struct instantdex_accept *ap)
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;
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);
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;
}
if ( (item= instantdex_acceptjson(ap)) != 0 )
@ -345,7 +480,11 @@ struct instantdex_accept *instantdex_offerfind(struct supernet_info *myinfo,stru
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);
}
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));
bestprice64 = ap->offer.price64;
if ( retap != 0 )
queue_enqueue("acceptableQ",&exchange->acceptableQ,&retap->DL,0);
retap = ap;
}
}
}
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0);
if ( ap != retap)
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0);
} else free(ap);
}
return(retap);
@ -474,73 +616,196 @@ int32_t instantdex_acceptextract(struct instantdex_accept *ap,cJSON *argjson)
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_ALTswap.c"
#include "swaps/iguana_NXTswap.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;
if ( BTC_states == 0 )
BTC_states = BTC_initFSM(&BTC_numstates);
exchange = exchanges777_find("bitcoin");
memset(cmdstr,0,sizeof(cmdstr)), memcpy(cmdstr,msg->cmd,sizeof(msg->cmd));
if ( argjson != 0 )
{
traderpub = jbits256(argjson,"traderpub");
memset(&A,0,sizeof(A));
A.offer = *offer;
if ( j64bits(argjson,"id") != orderhash.txid )
{
printf("orderhash %llu mismatch id.%llu\n",(long long)orderhash.txid,(long long)j64bits(argjson,"id"));
return(clonestr("{\"error\":\"orderhash mismatch\"}"));
}
//char str[65],str2[65];
/**/
//else printf("got mismatched traderpub.%s vs %s\n",bits256_str(str,traderpub),bits256_str(str2,myinfo->myaddr.persistent));
A.offer = *offer;
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);
return(clonestr("{\"error\":\"cant find matching order\"}"));
if ( ap->info == 0 )
{
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);
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 )
else
{
ap->info = A.info;
ap->pendingvolume64 = A.pendingvolume64;
printf("cant find existing order.%llu that matches\n",(long long)A.orderid);
return(clonestr("{\"error\":\"cant find matching order\"}"));
}
//printf("after swap ap.%p (%s)\n",ap,retstr);
return(retstr);
}
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;
bits256 orderhash; uint64_t signerbits; uint8_t tmp[sizeof(msg->sig)]; char *retstr = 0;
cJSON *retjson,*item,*argjson = 0;
if ( BTC_states == 0 )
BTC_states = BTC_initFSM(&BTC_numstates);
datalen = len - (int32_t)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));
@ -619,7 +886,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)
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;
*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);
}
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);
//printf("acceptableQ %llu (%s)\n",(long long)ap->orderid,retstr);
return(retstr);
@ -670,7 +938,7 @@ TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,maxaccept,base,rel,maxprice,basevolume)
struct instantdex_accept *ap;
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));
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!\"}"));
}
@ -679,7 +947,7 @@ TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,minaccept,base,rel,minprice,basevolume)
struct instantdex_accept *ap;
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));
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!\"}"));
}
#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
*/
#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)
{
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);
}
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");
ap->pendingvolume64 -= A->offer.basevolume64;
ap->pendingvolume64 -= basevolume64;
}
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 )
{
sprintf(buf+1,"%d",n);
jaddbits256(newjson,buf,pubi);
if ( jobj(newjson,buf) == 0 )
jaddbits256(newjson,buf,pubi);
}
else
{
@ -388,7 +371,7 @@ cJSON *instantdex_newjson(struct supernet_info *myinfo,struct bitcoin_swapinfo *
{
cJSON *newjson;
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 )
{
//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 )
swap->otherverifiedcut = 1;
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");
return(0);
serdata[serdatalen-1] = 0;
}
instantdex_getpubs(swap,argjson,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;
reftime = (uint32_t)(A->offer.expiration - INSTANTDEX_LOCKTIME*2);
printf("%llu/%llu cmd.(%s) vs next.(%s)\n",(long long)swap->bidid,(long long)swap->askid,cmdstr,swap->nextstate);
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 *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
{
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];
else swap->privBn = 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 )
return(retstr);
/*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\"}"));
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 )
{
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\"}"));
else if ( instantdex_paymentverify(myinfo,coinbtc,swap,A,argjson,1) == 0 )
{
swap->state++;
//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 )
{
@ -514,7 +619,6 @@ char *instantdex_statemachine(struct supernet_info *myinfo,struct exchange_info
return(clonestr("{\"error\":\"instantdex_BTCswap step4, no pubAm\"}"));
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 )
{
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\"}"));
else if ( instantdex_paymentverify(myinfo,coinbtc,swap,A,argjson,0) == 0 )
{
swap->state++;
strcpy(swap->nextstate,"step7");
/*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 )
retstr = clonestr("{\"error\":\"BTC swap null retstr\"}");
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);
return(retstr);
}
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));
}
#endif
#ifdef oldway
// https://github.com/TierNolan/bips/blob/bip4x/bip-atom.mediawiki

Loading…
Cancel
Save