diff --git a/basilisk/basilisk.c b/basilisk/basilisk.c index bc34e1b3f..f3f727045 100755 --- a/basilisk/basilisk.c +++ b/basilisk/basilisk.c @@ -392,48 +392,12 @@ int32_t basilisk_relayid(struct supernet_info *myinfo,uint32_t ipbits) #include "basilisk_ether.c" #include "basilisk_waves.c" #include "basilisk_lisk.c" -#include "basilisk_CMD.c" + +#include "basilisk_MSG.c" +#include "basilisk_swap.c" #include "basilisk_DEX.c" #include "basilisk_ping.c" - -#include "../includes/iguana_apidefs.h" -#include "../includes/iguana_apideclares.h" - -HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr) -{ - return(basilisk_standardservice("BAL",myinfo,0,hash,vals,hexstr,1)); - //return(basilisk_standardcmd(myinfo,"BAL",activecoin,remoteaddr,basilisktag,vals,coin->basilisk_balances,coin->basilisk_balancesmetric)); -} - -HASH_ARRAY_STRING(basilisk,value,hash,vals,hexstr) -{ - return(basilisk_standardservice("VAL",myinfo,0,hash,vals,hexstr,1)); - //return(basilisk_standardcmd(myinfo,"VAL",activecoin,remoteaddr,basilisktag,vals,coin->basilisk_value,coin->basilisk_valuemetric)); -} - -HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr) -{ - char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis; - if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 ) - { - if ( (coin= iguana_coinfind(symbol)) != 0 ) - { - basilisktag = juint(vals,"basilisktag"); - if ( juint(vals,"burn") == 0 ) - jaddnum(vals,"burn",0.0001); - if ( (timeoutmillis= juint(vals,"timeout")) <= 0 ) - timeoutmillis = BASILISK_TIMEOUT; - if ( (ptr= basilisk_bitcoinrawtx(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 ) - { - retstr = ptr->retstr; - } - if ( ptr != &Lptr ) - free(ptr); - } - } - return(retstr); -} -#include "../includes/iguana_apiundefs.h" +#include "basilisk_CMD.c" void basilisk_functions(struct iguana_info *coin,int32_t protocol) { @@ -579,23 +543,20 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t sende { (void *)"BYE", &basilisk_respond_goodbye }, // disconnect // gecko chains - //{ (void *)"NEW", &basilisk_respond_newgeckochain }, // creates new virtual gecko chain - ///{ (void *)"GEN", &basilisk_respond_geckogenesis }, // returns genesis list { (void *)"GET", &basilisk_respond_geckoget }, // requests headers, block or tx { (void *)"HDR", &basilisk_respond_geckoheaders }, // reports headers { (void *)"BLK", &basilisk_respond_geckoblock }, // reports block { (void *)"MEM", &basilisk_respond_mempool }, // reports mempool { (void *)"GTX", &basilisk_respond_geckotx }, // reports tx - //{ (void *)"SEQ", &basilisk_respond_hashstamps }, // BTCD and BTC recent hashes from timestamp - // unencrypted low level functions, used by higher level protocols and virtual network funcs { (void *)"ADD", &basilisk_respond_addrelay }, // relays register with each other bus - //{ (void *)"RLY", &basilisk_respond_relays }, { (void *)"DEX", &basilisk_respond_DEX }, { (void *)"RID", &basilisk_respond_RID }, - { (void *)"CHS", &basilisk_respond_CHS }, - { (void *)"QID", &basilisk_respond_QID }, + { (void *)"ACC", &basilisk_respond_ACC }, + { (void *)"OUT", &basilisk_respond_OUT }, // send MSG to hash/id/num + { (void *)"MSG", &basilisk_respond_MSG }, // get MSG (hash, id, num) + // encrypted data for jumblr { (void *)"HOP", &basilisk_respond_forward }, // message forwarding { (void *)"BOX", &basilisk_respond_mailbox }, // create/send/check mailbox pubkey @@ -748,7 +709,7 @@ void basilisk_p2p(void *_myinfo,void *_addr,char *senderip,uint8_t *data,int32_t void basilisks_loop(void *arg) { - struct iguana_info *virt,*tmpcoin,*btcd; struct basilisk_item *tmp,*pending; int32_t iter,maxmillis,flag=0; struct supernet_info *myinfo = arg; + struct iguana_info *virt,*tmpcoin,*btcd; struct basilisk_message *msg,*tmpmsg; struct basilisk_item *tmp,*pending; uint32_t now; int32_t iter,maxmillis,flag=0; struct supernet_info *myinfo = arg; iter = 0; while ( 1 ) { @@ -783,18 +744,32 @@ void basilisks_loop(void *arg) //for (i=0; iRELAYNODE == 0 && coin->VALIDATENODE == 0 && coin->active != 0 && coin->chain->userpass[0] != 0 && coin->MAXPEERS == 1 ) // basilisk_bitcoinscan(coin,blockspace,&RAWMEM); + basilisk_requests_poll(myinfo); + now = (uint32_t)time(NULL); + portable_mutex_lock(&myinfo->messagemutex); + HASH_ITER(hh,myinfo->messagetable,msg,tmpmsg) + { + if ( now > msg->expiration ) + { + printf("delete expired message.%p\n",msg); + HASH_DELETE(hh,myinfo->messagetable,msg); + free(msg); + } + } + portable_mutex_unlock(&myinfo->messagemutex); usleep(100000); } } void basilisks_init(struct supernet_info *myinfo) { - //iguana_initQ(&myinfo->basilisks.submitQ,"submitQ"); - //iguana_initQ(&myinfo->basilisks.resultsQ,"resultsQ"); + iguana_initQ(&myinfo->msgQ,"messageQ"); portable_mutex_init(&myinfo->allcoins_mutex); portable_mutex_init(&myinfo->basilisk_mutex); portable_mutex_init(&myinfo->DEX_mutex); + portable_mutex_init(&myinfo->DEX_swapmutex); portable_mutex_init(&myinfo->DEX_reqmutex); portable_mutex_init(&myinfo->gecko_mutex); + portable_mutex_init(&myinfo->messagemutex); myinfo->basilisks.launched = iguana_launch(iguana_coinfind("BTCD"),"basilisks_loop",basilisks_loop,myinfo,IGUANA_PERMTHREAD); } diff --git a/basilisk/basilisk.h b/basilisk/basilisk.h index 8a2fea17c..5b95792bd 100755 --- a/basilisk/basilisk.h +++ b/basilisk/basilisk.h @@ -29,6 +29,52 @@ //#define BASILISK_MAXBLOCKLAG 600 #define BASILISK_HDROFFSET ((int32_t)(sizeof(bits256)+sizeof(struct iguana_msghdr)+sizeof(uint32_t))) +#define INSTANTDEX_DECKSIZE 777 +#define INSTANTDEX_LOCKTIME (7200 + 600*2) +#define INSTANTDEX_INSURANCEDIV ((7 * INSTANTDEX_DECKSIZE) >> 3) +#define INSTANTDEX_PUBEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" +#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" +#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" +#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" +#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" + +struct basilisk_request +{ + uint32_t requestid,timestamp,quoteid; + uint64_t srcamount; + bits256 hash; + char src[8],dest[8]; + char volatile_start,message[43]; + uint64_t destamount; + uint32_t relaybits; + bits256 desthash; +} __attribute__((packed)); + +struct bitcoin_statetx +{ + bits256 txid; + uint64_t amount,change,inputsum; + char destaddr[64]; + char txbytes[]; +}; + +struct basilisk_swap +{ + struct basilisk_request req; + struct supernet_info *myinfo; bits256 myhash,otherhash; + uint32_t statebits,started,expiration,finished,dead,reftime,locktime; + struct iguana_info *bobcoin,*alicecoin; char bobstr[64],alicestr[64]; + int32_t bobconfirms,aliceconfirms,iambob,reclaimed; + uint64_t alicesatoshis,bobsatoshis,bobinsurance,aliceinsurance; + + bits256 privkeys[INSTANTDEX_DECKSIZE],myprivs[2],mypubs[2],otherpubs[2],pubA0,pubB0,pubB1,privAm,pubAm,privBn,pubBn; + uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; + int32_t choosei,otherchoosei,cutverified,otherverifiedcut,numpubs,havestate,otherhavestate; + uint8_t secretAm[20],secretBn[20]; + + struct bitcoin_statetx *deposit,*payment,*alicepayment,*myfee,*otherfee,*reclaim; +}; + struct basilisk_value { bits256 txid; int64_t value; int32_t height; int16_t vout; char coinaddr[64]; }; struct basilisk_item @@ -39,6 +85,8 @@ struct basilisk_item char symbol[32],CMD[4],remoteaddr[64],*retstr; }; +struct basilisk_message { struct queueitem DL; UT_hash_handle hh; uint32_t datalen,expiration; uint8_t key[63],keylen; uint8_t data[]; }; + struct basilisk_info { //queue_t resultsQ,submitQ; @@ -47,15 +95,6 @@ struct basilisk_info struct basilisk_value values[8192]; int32_t numvalues; }; -struct basilisk_request -{ - uint32_t crc,timestamp,requestid,quoteid; - uint64_t srcamount,destamount; - bits256 hash; - char src[8],dest[8],message[48]; - uint32_t relaybits; -} __attribute__((packed)); - struct basilisk_relaystatus { uint8_t pingdelay; diff --git a/basilisk/basilisk_DEX.c b/basilisk/basilisk_DEX.c index 23cdbcf94..92ab67d5d 100755 --- a/basilisk/basilisk_DEX.c +++ b/basilisk/basilisk_DEX.c @@ -14,54 +14,83 @@ ******************************************************************************/ // included from basilisk.c +// requestid is invariant for a specific request +// quoteid is invariant for a specific request after dest fields are set + +uint32_t basilisk_requestid(struct basilisk_request *rp) +{ + struct basilisk_request R; + R = *rp; + memset(&R,0,(long)&R.volatile_start - (long)&R); + return(calc_crc32(0,(void *)((long)&R + sizeof(R.requestid)),sizeof(R) - sizeof(R.requestid))); +} + +uint32_t basilisk_quoteid(struct basilisk_request *rp) +{ + struct basilisk_request R; + R = *rp; + memset(R.message,0,sizeof(R.message)); + R.relaybits = 0; + return(calc_crc32(0,(void *)((long)&R + sizeof(R.requestid)),sizeof(R) - sizeof(R.requestid))); +} int32_t basilisk_rwDEXquote(int32_t rwflag,uint8_t *serialized,struct basilisk_request *rp) { int32_t len = 0; - len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->crc),&rp->crc); // must be 1st - len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->timestamp),&rp->timestamp); // must be 2nd len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->requestid),&rp->requestid); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->timestamp),&rp->timestamp); // must be 2nd len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->quoteid),&rp->quoteid); len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->srcamount),&rp->srcamount); - len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->destamount),&rp->destamount); len += iguana_rwbignum(rwflag,&serialized[len],sizeof(rp->hash),rp->hash.bytes); len += iguana_rwvarstr(rwflag,&serialized[len],sizeof(rp->src)-1,rp->src); - len += iguana_rwvarstr(rwflag,&serialized[len],sizeof(rp->src)-1,rp->dest); - len += iguana_rwvarstr(rwflag,&serialized[len],128,rp->message); + len += iguana_rwvarstr(rwflag,&serialized[len],sizeof(rp->dest)-1,rp->dest); + len += iguana_rwbignum(rwflag,&serialized[len],sizeof(rp->desthash),rp->desthash.bytes); + len += iguana_rwnum(rwflag,&serialized[len],sizeof(rp->destamount),&rp->destamount); + len += iguana_rwvarstr(rwflag,&serialized[len],sizeof(rp->message)-1,rp->message); + if ( rp->quoteid != 0 && basilisk_quoteid(rp) != rp->quoteid ) + printf("basilisk_rwDEXquote: quoteid.%u mismatch %u\n",basilisk_quoteid(rp),rp->quoteid); + if ( basilisk_quoteid(rp) != rp->requestid ) + printf("basilisk_rwDEXquote: requestid.%u mismatch %u\n",basilisk_requestid(rp),rp->requestid); return(len); } -int32_t basilisk_request_enqueue(struct supernet_info *myinfo,bits256 hash,char *src,uint64_t srcamount,char *dest,uint64_t destamount,char *message,uint32_t requestid,uint32_t quoteid) +uint32_t basilisk_request_enqueue(struct supernet_info *myinfo,int32_t queueflag,struct basilisk_request *finalR,bits256 hash,char *src,uint64_t srcamount,bits256 desthash,char *dest,uint64_t destamount,char *message,int32_t calcquoteid) { uint8_t serialized[256]; int32_t len; struct queueitem *item; struct basilisk_request R; memset(&R,0,sizeof(R)); R.timestamp = (uint32_t)time(NULL); R.hash = hash; R.srcamount = srcamount; - R.destamount = destamount; - R.requestid = requestid; - R.quoteid = quoteid; strncpy(R.src,src,sizeof(R.src)-1); strncpy(R.dest,dest,sizeof(R.dest)-1); if ( message != 0 ) + { + if ( strlen(message) > sizeof(R.message)-1 ) + printf("message.(%s) too long\n",message); strncpy(R.message,message,sizeof(R.message)-1); - R.crc = calc_crc32(0,(void *)((long)&R + sizeof(R.crc)),sizeof(R) - sizeof(R.crc)); + } + R.desthash = desthash; + R.destamount = destamount; + if ( calcquoteid != 0 ) + R.quoteid = basilisk_quoteid(&R); + R.requestid = basilisk_requestid(&R); + *finalR = R; len = basilisk_rwDEXquote(1,serialized+1,&R); - serialized[0] = len; - if ( (item= calloc(1,sizeof(*item) + len + 1)) != 0 ) + if ( queueflag != 0 && (item= calloc(1,sizeof(*item) + len + 1)) != 0 ) { + serialized[0] = len; memcpy(&item[1],serialized,len + 1); portable_mutex_lock(&myinfo->DEX_mutex); DL_APPEND(myinfo->DEX_quotes,item); portable_mutex_unlock(&myinfo->DEX_mutex); - return(0); + return(R.requestid); } - return(-1); + return(0); } cJSON *basilisk_requestjson(uint32_t relaybits,struct basilisk_request *rp) { - char ipaddr[64]; cJSON *item = cJSON_CreateObject(); + char ipaddr[64]; cJSON *msgobj,*item = cJSON_CreateObject(); expand_ipbits(ipaddr,relaybits); jaddstr(item,"relay",ipaddr); jaddbits256(item,"hash",rp->hash); @@ -74,46 +103,68 @@ cJSON *basilisk_requestjson(uint32_t relaybits,struct basilisk_request *rp) jaddnum(item,"timestamp",rp->timestamp); jaddnum(item,"requestid",rp->requestid); jaddnum(item,"quoteid",rp->quoteid); - if ( rp->message[0] != 0 ) - jaddstr(item,"message",rp->message); + if ( rp->message[0] != 0 && (msgobj= cJSON_Parse(rp->message)) != 0 ) + jadd(item,"message",msgobj); return(item); } +char *basilisk_start(struct supernet_info *myinfo,struct basilisk_request *rp,uint32_t statebits) +{ + cJSON *retjson; struct basilisk_request R; char msgjsonstr[64]; + sprintf(msgjsonstr,"{\"state\":%u\"}",statebits); + if ( basilisk_request_enqueue(myinfo,1,&R,rp->hash,rp->src,rp->srcamount,rp->desthash,rp->dest,rp->destamount,msgjsonstr,myinfo->RELAYID < 0) == rp->requestid ) + { + if ( myinfo->RELAYID >= 0 && (bits256_cmp(rp->hash,myinfo->myaddr.persistent) == 0 || bits256_cmp(rp->desthash,myinfo->myaddr.persistent) == 0) ) + { + printf("START thread to complete %u/%u for (%s %.8f) <- (%s %.8f)\n",rp->requestid,R.quoteid,rp->src,dstr(rp->srcamount),rp->dest,dstr(rp->destamount)); + if ( basilisk_thread_start(myinfo,&R) != 0 ) + { + basilisk_request_enqueue(myinfo,1,&R,rp->hash,rp->src,rp->srcamount,rp->desthash,rp->dest,rp->destamount,msgjsonstr,1); + return(clonestr("{\"result\":\"started atomic swap thread\"}")); + } + else return(clonestr("{\"error\":\"couldnt atomic swap thread\"}")); + } + else if ( myinfo->RELAYID < 0 ) + { + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result","basilisk node needs to start atomic thread locally"); + jadd(retjson,"req",basilisk_requestjson(myinfo->myaddr.myipbits,rp)); + return(jprint(retjson,1)); + } else return(clonestr("{\"error\":\"unexpected basilisk_start not mine and amrelay\"}")); + } else return(clonestr("{\"error\":\"couldnt enqueue chosen\"}")); +} +// end of swap code + struct basilisk_request *basilisk_parsejson(struct basilisk_request *rp,cJSON *reqjson) { + uint32_t requestid,quoteid; char *msgstr; memset(rp,0,sizeof(*rp)); rp->hash = jbits256(reqjson,"hash"); rp->srcamount = j64bits(reqjson,"srcamount"); rp->destamount = j64bits(reqjson,"destamount"); - rp->requestid = juint(reqjson,"requestid"); - rp->quoteid = juint(reqjson,"quoteid"); + requestid = juint(reqjson,"requestid"); + quoteid = juint(reqjson,"quoteid"); rp->timestamp = juint(reqjson,"timestamp"); safecopy(rp->src,jstr(reqjson,"src"),sizeof(rp->src)); safecopy(rp->dest,jstr(reqjson,"dest"),sizeof(rp->dest)); - safecopy(rp->message,jstr(reqjson,"message"),sizeof(rp->message)); - rp->crc = calc_crc32(0,(void *)((long)rp + sizeof(rp->crc)),sizeof(*rp) - sizeof(rp->crc)); - return(rp); -} - -char *basilisk_choose(struct supernet_info *myinfo,bits256 hash,struct basilisk_request *other,uint64_t destamount,uint32_t quoteid) -{ - cJSON *retjson; - if ( basilisk_request_enqueue(myinfo,hash,other->src,other->srcamount,other->dest,destamount,"start",other->requestid,quoteid) == 0 ) + if ( jobj(reqjson,"message") != 0 ) { - if ( bits256_cmp(hash,myinfo->myaddr.persistent) == 0 ) - { - printf("START thread to complete %u/%u for (%s %.8f) <- (%s %.8f)\n",other->requestid,quoteid,other->src,dstr(other->srcamount),other->dest,dstr(other->destamount)); - // other, myinfo->myaddr.persistent, destamount, quoteid - return(clonestr("{\"result\":\"started atomic thread\"}")); - } - else - { - retjson = cJSON_CreateObject(); - jaddstr(retjson,"result","need to start atomic thread"); - jadd(retjson,"other",basilisk_requestjson(myinfo->myaddr.myipbits,other)); - return(jprint(retjson,1)); - } - } else return(clonestr("{\"error\":\"couldnt enqueue chosen\"}")); + msgstr = jprint(jobj(reqjson,"message"),0); + if ( strlen(msgstr) > sizeof(rp->message)-1 ) + printf("basilisk_parsejson msgstr.(%s) too long\n",msgstr); + safecopy(rp->message,msgstr,sizeof(rp->message)); + free(msgstr); + } + if ( quoteid != 0 ) + { + rp->quoteid = basilisk_quoteid(rp); + if ( quoteid != rp->quoteid ) + printf("basilisk_parsejson quoteid.%u != %u error\n",quoteid,rp->quoteid); + } + rp->requestid = basilisk_requestid(rp); + if ( requestid != rp->requestid ) + printf("basilisk_parsejson requestid.%u != %u error\n",requestid,rp->requestid); + return(rp); } struct basilisk_relay *basilisk_request_ensure(struct supernet_info *myinfo,uint32_t senderipbits,int32_t numrequests) @@ -148,12 +199,12 @@ int32_t basilisk_ping_processDEX(struct supernet_info *myinfo,uint32_t senderipb { memcpy(serialized,&data[len],clen); len += basilisk_rwDEXquote(0,serialized,&R); - crc = calc_crc32(0,(void *)((long)&R + sizeof(R.crc)),sizeof(R) - sizeof(R.crc)); - if ( crc == R.crc ) + crc = basilisk_requestid(&R); + if ( crc == R.requestid ) { relay->requests[relay->numrequests++] = R; printf("(%s (%s %.8f) -> (%s %.8f) r.%u q.%u) ",R.message,R.src,dstr(R.srcamount),R.dest,dstr(R.destamount),R.requestid,R.quoteid); - } else printf("crc.%08x error vs %08x\n",crc,R.crc); + } else printf("crc.%08x error vs %08x\n",crc,R.requestid); } else printf("relay num.%d >= max.%d\n",relay->numrequests,relay->maxrequests); } else len += clen; } @@ -201,6 +252,30 @@ int32_t basilisk_ping_genDEX(struct supernet_info *myinfo,uint8_t *data,int32_t return(datalen); } +static int _cmp_requests(const void *a,const void *b) +{ +#define uint32_a (*(struct basilisk_request *)a).requestid +#define uint32_b (*(struct basilisk_request *)b).requestid + if ( uint32_b > uint32_a ) + return(1); + else if ( uint32_b < uint32_a ) + return(-1); + else + { +#undef uint32_a +#undef uint32_b +#define uint32_a (*(struct basilisk_request *)a).quoteid +#define uint32_b (*(struct basilisk_request *)b).quoteid + if ( uint32_b > uint32_a ) + return(1); + else if ( uint32_b < uint32_a ) + return(-1); + } + return(0); +#undef uint32_a +#undef uint32_b +} + struct basilisk_request *_basilisk_requests_uniq(struct supernet_info *myinfo,int32_t *nump,uint8_t *space,int32_t spacesize) { int32_t i,j,n,k,m; struct basilisk_relay *relay; struct basilisk_request *requests,*rp; @@ -228,10 +303,20 @@ struct basilisk_request *_basilisk_requests_uniq(struct supernet_info *myinfo,in } } } + qsort(requests,m,sizeof(*requests),_cmp_requests); *nump = m; return(requests); } +char *basilisk_respond_swapstatus(struct supernet_info *myinfo,bits256 hash,uint32_t requestid,uint32_t quoteid) +{ + cJSON *array,*retjson; + array = cJSON_CreateArray(); + retjson = cJSON_CreateObject(); + jadd(retjson,"result",array); + return(jprint(retjson,1)); +} + char *basilisk_respond_requests(struct supernet_info *myinfo,bits256 hash,uint32_t requestid,uint32_t quoteid) { int32_t i,num=0; cJSON *retjson,*array; struct basilisk_request *requests,*rp; uint8_t space[16384]; @@ -242,7 +327,7 @@ char *basilisk_respond_requests(struct supernet_info *myinfo,bits256 hash,uint32 for (i=0; irequestid == requestid) && ((quoteid == 0 && rp->quoteid != 0) || quoteid == rp->quoteid) ) + if ( rp->requestid == requestid && (quoteid == 0 || quoteid == rp->quoteid) && (bits256_cmp(hash,rp->hash) == 0 || bits256_cmp(hash,rp->desthash) == 0) ) jaddi(array,basilisk_requestjson(rp->relaybits,rp)); } } @@ -254,71 +339,82 @@ char *basilisk_respond_requests(struct supernet_info *myinfo,bits256 hash,uint32 return(jprint(retjson,1)); } -char *basilisk_respond_choose(struct supernet_info *myinfo,bits256 hash,uint32_t requestid,uint64_t destamount) +char *basilisk_respond_accept(struct supernet_info *myinfo,uint32_t requestid,uint32_t quoteid,char *msgjsonstr) { - int32_t i,num=0,alreadythere = 0; uint32_t quoteid; char *retstr; struct basilisk_request *requests,*rp,*resprp=0; uint8_t space[16384]; - quoteid = (requestid ^ hash.uints[0]); + int32_t i,num=0; char *retstr=0; struct basilisk_request *requests,*rp; uint8_t space[16384]; portable_mutex_lock(&myinfo->DEX_reqmutex); if ( (requests= _basilisk_requests_uniq(myinfo,&num,space,sizeof(space))) != 0 ) { for (i=0; irequestid == requestid ) + if ( rp->requestid == requestid && rp->quoteid == quoteid ) { - if ( rp->quoteid == 0 ) - resprp = rp; - else if ( rp->quoteid == quoteid ) - { - alreadythere = 1; - break; - } + retstr = basilisk_start(myinfo,rp,1); + break; } } } + portable_mutex_unlock(&myinfo->DEX_reqmutex); if ( requests != (void *)space ) free(requests); - if ( alreadythere == 0 ) - { - if ( resprp == 0 ) - retstr = clonestr("{\"error\":\"couldnt find to requestid to choose\"}"); - else retstr = basilisk_choose(myinfo,hash,resprp,destamount,quoteid); - } else retstr = clonestr("{\"result\":\"quoteid already there\"}"); - portable_mutex_unlock(&myinfo->DEX_reqmutex); + if ( retstr == 0 ) + retstr = clonestr("{\"error\":\"couldnt find to requestid to choose\"}"); return(retstr); } -// respond to incoming RID, CHS, DEX, QST +// respond to incoming RID, ACC, DEX, QST char *basilisk_respond_RID(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk) { return(basilisk_respond_requests(myinfo,hash,juint(valsobj,"requestid"),0)); } -char *basilisk_respond_QID(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk) +char *basilisk_respond_SWP(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk) { - return(basilisk_respond_requests(myinfo,hash,juint(valsobj,"requestid"),juint(valsobj,"quoteid"))); + return(basilisk_respond_swapstatus(myinfo,hash,juint(valsobj,"requestid"),juint(valsobj,"quoteid"))); } -char *basilisk_respond_CHS(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk) +char *basilisk_respond_ACC(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk) { - uint32_t requestid; uint64_t destamount; - if ( (requestid= juint(valsobj,"requestid")) != 0 && (destamount= j64bits(valsobj,"destamount")) != 0 ) - return(basilisk_respond_choose(myinfo,hash,requestid,destamount)); + uint32_t requestid,quoteid; char *retstr,*msgstr=0; + if ( (requestid= juint(valsobj,"requestid")) != 0 && (quoteid= juint(valsobj,"quoteid")) != 0 ) + { + if ( jobj(valsobj,"message") != 0 ) + msgstr = jprint(jobj(valsobj,"message"),0); + retstr = basilisk_respond_accept(myinfo,requestid,quoteid,msgstr); + if ( msgstr != 0 ) + free(msgstr); + return(retstr); + } return(clonestr("{\"error\":\"need nonzero requestid and quoteid\"}")); } char *basilisk_respond_DEX(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk) { - char *dest,*src,*retstr=0,buf[256]; uint32_t zero=0; uint64_t satoshis; + char *dest,*src,*msgstr=0,*retstr=0,buf[256]; uint32_t requestid,i; uint64_t destamount=0,satoshis; bits256 desthash; struct basilisk_request R; if ( (dest= jstr(valsobj,"dest")) != 0 && (src= jstr(valsobj,"src")) != 0 && (satoshis= j64bits(valsobj,"satoshis")) != 0 ) { + memset(desthash.bytes,0,sizeof(desthash)); + if ( (destamount= j64bits(valsobj,"destsatoshis")) != 0 ) + { + desthash = jbits256(valsobj,"desthash"); + for (i=0; i<4; i++) + if ( desthash.ulongs[i] != 0 ) + break; + if ( i != 4 ) + destamount = 0; + } char str[65]; printf("DEX.(%s %.8f) -> %s %s\n",src,dstr(satoshis),dest,bits256_str(str,hash)); - if ( basilisk_request_enqueue(myinfo,hash,src,satoshis,dest,0,jstr(valsobj,"msg"),basilisktag,zero) == 0 ) + if ( jobj(valsobj,"message") != 0 ) + msgstr = jprint(jobj(valsobj,"message"),0); + if ( (requestid= basilisk_request_enqueue(myinfo,1,&R,hash,src,satoshis,desthash,dest,destamount,msgstr,destamount != 0)) != 0 ) { - sprintf(buf,"{\"result\":\"DEX request added\",\"request\":%u}",basilisktag); + sprintf(buf,"{\"result\":\"DEX request added\",\"request\":%u}",requestid); retstr = clonestr(buf); } else retstr = clonestr("{\"error\":\"DEX quote couldnt be created\"}"); + if ( msgstr != 0 ) + free(msgstr); } return(retstr); } @@ -326,6 +422,19 @@ char *basilisk_respond_DEX(struct supernet_info *myinfo,char *CMD,void *addr,cha #include "../includes/iguana_apidefs.h" #include "../includes/iguana_apideclares.h" +THREE_STRINGS_AND_DOUBLE(tradebot,aveprice,comment,base,rel,basevolume) +{ + double retvals[4],aveprice; cJSON *retjson = cJSON_CreateObject(); + aveprice = instantdex_avehbla(myinfo,retvals,base,rel,basevolume); + jaddstr(retjson,"result","success"); + jaddnum(retjson,"aveprice",aveprice); + jaddnum(retjson,"avebid",retvals[0]); + jaddnum(retjson,"bidvol",retvals[1]); + jaddnum(retjson,"aveask",retvals[2]); + jaddnum(retjson,"askvol",retvals[3]); + return(jprint(retjson,1)); +} + ZERO_ARGS(InstantDEX,allcoins) { struct iguana_info *tmp; cJSON *array,*retjson = cJSON_CreateObject(); @@ -348,17 +457,17 @@ STRING_ARG(InstantDEX,available,source) } else return(clonestr("{\"error\":\"specified coin is not active\"}")); } -THREE_STRINGS_AND_DOUBLE(InstantDEX,request,message,dest,source,amount) +HASH_ARRAY_STRING(InstantDEX,request,hash,vals,hexstr) { - struct basilisk_request R; char *retstr; cJSON *vals = cJSON_CreateObject(); - jaddstr(vals,"dest",dest); - jaddstr(vals,"src",source); - if ( strlen(message) < sizeof(R.message) ) - jaddstr(vals,"msg",message); - jadd64bits(vals,"satoshis",amount * SATOSHIDEN); - retstr = basilisk_standardservice("DEX",myinfo,0,myinfo->myaddr.persistent,vals,"",1); - free_json(vals); - return(retstr); + cJSON *msgobj = cJSON_CreateObject(); + jadd64bits(msgobj,"min",jdouble(vals,"minprice") * jdouble(vals,"amount") * SATOSHIDEN); + jaddnum(msgobj,"auto",juint(vals,"autoflag")); + jadd(vals,"message",msgobj); + if ( jobj(vals,"desthash") == 0 ) + jaddbits256(vals,"desthash",hash); + jadd64bits(vals,"satoshis",jdouble(vals,"amount") * SATOSHIDEN); + jadd64bits(vals,"destsatoshis",jdouble(vals,"destamount") * SATOSHIDEN); + return(basilisk_standardservice("DEX",myinfo,0,myinfo->myaddr.persistent,vals,"",1)); } INT_ARG(InstantDEX,incoming,requestid) @@ -377,42 +486,41 @@ INT_ARG(InstantDEX,incoming,requestid) } } -TWO_INTS(InstantDEX,qstatus,requestid,quoteid) +TWO_INTS(InstantDEX,swapstatus,requestid,quoteid) { cJSON *vals; char *retstr; if ( myinfo->RELAYID >= 0 ) - return(basilisk_respond_requests(myinfo,myinfo->myaddr.persistent,requestid,quoteid)); + return(basilisk_respond_swapstatus(myinfo,myinfo->myaddr.persistent,requestid,quoteid)); else { vals = cJSON_CreateObject(); jaddnum(vals,"quoteid",quoteid); jaddbits256(vals,"hash",myinfo->myaddr.persistent); - retstr = basilisk_standardservice("QST",myinfo,0,myinfo->myaddr.persistent,vals,"",1); + retstr = basilisk_standardservice("SWP",myinfo,0,myinfo->myaddr.persistent,vals,"",1); free_json(vals); return(retstr); } } -INT_AND_DOUBLE(InstantDEX,choose,requestid,destamount) +TWO_INTS(InstantDEX,accept,requestid,quoteid) { - cJSON *vals,*retjson; char *retstr; struct basilisk_request R,*other; uint32_t quoteid; + struct basilisk_request R,*other; cJSON *vals,*retjson; char *retstr,*msgjsonstr = "{\"state\":1}"; if ( myinfo->RELAYID >= 0 ) - return(basilisk_respond_choose(myinfo,myinfo->myaddr.persistent,requestid,destamount*SATOSHIDEN)); + return(basilisk_respond_accept(myinfo,requestid,quoteid,msgjsonstr)); else { - quoteid = (requestid ^ myinfo->myaddr.persistent.uints[0]); vals = cJSON_CreateObject(); - jaddnum(vals,"requestid",requestid); jaddnum(vals,"quoteid",quoteid); - jadd64bits(vals,"destamount",destamount*SATOSHIDEN); - jaddbits256(vals,"hash",myinfo->myaddr.persistent); - if ( (retstr= basilisk_standardservice("CHS",myinfo,0,myinfo->myaddr.persistent,vals,"",1)) != 0 ) + jaddnum(vals,"requestid",requestid); + jadd(vals,"message",cJSON_Parse(msgjsonstr)); + if ( (retstr= basilisk_standardservice("ACC",myinfo,0,myinfo->myaddr.persistent,vals,"",1)) != 0 ) { if ( (retjson= cJSON_Parse(retstr)) != 0 ) { - other = basilisk_parsejson(&R,jobj(retjson,"other")); - // other, myinfo->myaddr.persistent, destamount, quoteid - printf("START thread to complete %u/%u for (%s %.8f) <- (%s %.8f)\n",other->requestid,quoteid,other->src,dstr(other->srcamount),other->dest,dstr(other->destamount)); + other = basilisk_parsejson(&R,jobj(retjson,"req")); + if ( basilisk_thread_start(myinfo,other) != 0 ) + printf("START thread to complete %u/%u for %s %.8f) <- (%s %.8f)\n",other->requestid,R.quoteid,other->src,dstr(other->srcamount),other->dest,dstr(other->destamount)); + else printf("ERROR starting atomic swap thread\n"); free(retjson); } } @@ -422,62 +530,136 @@ INT_AND_DOUBLE(InstantDEX,choose,requestid,destamount) } #include "../includes/iguana_apiundefs.h" -int32_t basilisk_request_pending(struct supernet_info *myinfo,struct basilisk_request *rp,uint32_t requestid) +int32_t basilisk_request_cmpref(struct basilisk_request *ref,struct basilisk_request *rp) { - int32_t i,j,n,alreadystarted = 0; struct basilisk_relay *relay; uint32_t quoteid; - quoteid = (requestid ^ myinfo->myaddr.persistent.uints[0]); - portable_mutex_lock(&myinfo->DEX_reqmutex); - for (j=0; jnumrelays; j++) + if ( bits256_cmp(rp->hash,ref->hash) != 0 || memcmp(rp->src,ref->src,sizeof(ref->src)) != 0 || memcmp(rp->dest,ref->dest,sizeof(ref->dest)) != 0 || rp->srcamount != ref->srcamount || rp->timestamp != ref->timestamp ) { - relay = &myinfo->relays[j]; - if ( (n= relay->numrequests) > 0 ) + printf("basilisk_request_listprocess mismatched hash\n"); + return(-1); + } else return(0); +} + +double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk_request *issueR,struct basilisk_request *list,int32_t n) +{ + int32_t i,noquoteflag=0,havequoteflag=0,myrequest=0,maxi=-1,autoflag=0; cJSON *statejson,*msgobj=0; uint64_t destamount,minamount = 0,maxamount = 0; uint32_t pendingid,statebits; struct basilisk_swap *active; double metric = 0.; + memset(issueR,0,sizeof(*issueR)); + printf("need to verify null quoteid is list[0]\n"); + if ( (active= basilisk_request_started(myinfo,list[0].requestid)) != 0 ) + pendingid = active->req.quoteid; + if ( bits256_cmp(myinfo->myaddr.persistent,list[0].hash) == 0 ) // my request + myrequest = 1; + if ( list[0].message[0] != 0 && (msgobj= cJSON_Parse(list[0].message)) != 0 ) + { + autoflag = juint(msgobj,"auto"); + minamount = j64bits(msgobj,"min"); + } + for (i=0; irequests[i].requestid == requestid && relay->requests[i].quoteid == quoteid ) + if ( list[i].destamount > maxamount ) { - alreadystarted = 1; - break; + maxamount = list[i].destamount; + maxi = i; } } + else if ( active != 0 && pendingid == list[i].quoteid ) + { + if ( (statejson= cJSON_Parse(list[i].message)) != 0 ) + { + statebits = juint(statejson,"state"); + if ( bitweight(statebits) > bitweight(active->statebits) ) + { + // advance statemachine + //active->statebits = statebits; + printf("req statbits.%x -> %x\n",active->statebits,statebits); + } + free(statejson); + } + } + } else noquoteflag++; + } + if ( myrequest == 0 && pendingid == 0 && noquoteflag != 0 ) + { + double retvals[4],aveprice; + aveprice = instantdex_avehbla(myinfo,retvals,list[0].src,list[0].dest,dstr(list[0].srcamount)); + destamount = 0.99 * aveprice * list[0].srcamount; + if ( destamount >= maxamount && destamount >= minamount ) + { + metric = 1.; + *issueR = list[0]; + issueR->desthash = myinfo->myaddr.persistent; + issueR->destamount = destamount; } } - portable_mutex_unlock(&myinfo->DEX_reqmutex); - return(alreadystarted); -} - -void basilisk_request_check(struct supernet_info *myinfo,struct basilisk_request *rp) -{ - double retvals[4],aveprice; struct basilisk_request R; struct iguana_info *src,*dest; char message[128]; uint32_t quoteid; - if ( (src= iguana_coinfind(rp->src)) != 0 && (dest= iguana_coinfind(rp->dest)) != 0 ) + else if ( myrequest != 0 && pendingid == 0 && maxi >= 0 ) // automatch best quote { - if ( basilisk_request_pending(myinfo,&R,rp->requestid) == 0 ) + if ( maxamount > minamount && autoflag != 0 && time(NULL) > BASILISK_DEXDURATION/2 ) { - aveprice = instantdex_avehbla(myinfo,retvals,rp->src,rp->dest,dstr(rp->srcamount)); - quoteid = rp->requestid ^ myinfo->myaddr.persistent.uints[0]; - sprintf(message,"{\"price\":%.8f,\"requestid\":%u,\"quoteid\":%u}",aveprice,rp->requestid,quoteid); - if ( basilisk_request_enqueue(myinfo,myinfo->myaddr.persistent,rp->src,rp->srcamount*aveprice,rp->dest,rp->srcamount*aveprice,message,rp->requestid,quoteid) < 0 ) - printf("error creating quoteid\n"); + printf("automatch quoteid.%u triggered %.8f > %.8f\n",list[maxi].quoteid,dstr(maxamount),dstr(minamount)); + *issueR = list[maxi]; + if ( minamount > 0 ) + metric = (dstr(maxamount) / dstr(minamount)) - 1.; + else metric = 1.; } } + if ( msgobj != 0 ) + free_json(msgobj); + return(metric); } void basilisk_requests_poll(struct supernet_info *myinfo) { - char *retstr; cJSON *retjson,*array,*item; int32_t i,n; + char *retstr; cJSON *retjson,*array,*item; int32_t i,n,m; struct basilisk_request tmpR,R,issueR,refR,list[BASILISK_MAXRELAYS*10]; double metric=0.,hwm = 0.; + memset(&issueR,0,sizeof(issueR)); if ( (retstr= InstantDEX_incoming(myinfo,0,0,0,0)) != 0 ) { if ( (retjson= cJSON_Parse(retstr)) != 0 ) { if ( (array= jarray(&n,retjson,"result")) != 0 ) { - for (i=0; i hwm ) + issueR = tmpR, hwm = metric; + m = 0; + } + } + if ( m < sizeof(list)/sizeof(*list) ) + basilisk_parsejson(&list[m++],item); } + if ( m > 0 && m < sizeof(list)/sizeof(*list) ) + if ( (metric= basilisk_request_listprocess(myinfo,&tmpR,list,m)) > hwm ) + issueR = tmpR, hwm = metric; } free_json(retjson); } free(retstr); } + if ( hwm > 0. ) + { + if ( bits256_cmp(myinfo->myaddr.persistent,issueR.hash) == 0 ) // my request + { + if ( (retstr= InstantDEX_accept(myinfo,0,0,0,issueR.requestid,issueR.quoteid)) != 0 ) + free(retstr); + } + else if ( issueR.quoteid == 0 ) + { + if ( (retstr= basilisk_start(myinfo,&issueR,0)) != 0 ) + free(retstr); + } else printf("basilisk_requests_poll unexpected hwm issueR\n"); + } } diff --git a/basilisk/basilisk_MSG.c b/basilisk/basilisk_MSG.c new file mode 100755 index 000000000..15fbc5c92 --- /dev/null +++ b/basilisk/basilisk_MSG.c @@ -0,0 +1,178 @@ +/****************************************************************************** + * Copyright © 2014-2016 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +// included from basilisk.c + +char *basilisk_respond_sendmessage(struct supernet_info *myinfo,uint8_t *key,int32_t keylen,uint8_t *data,int32_t datalen,int32_t sendping) +{ + struct basilisk_message *msg; + msg = calloc(1,sizeof(*msg) + datalen); + msg->expiration = (uint32_t)time(NULL) + INSTANTDEX_LOCKTIME*2; + memcpy(msg->key,key,keylen); + msg->datalen = datalen; + memcpy(msg->data,data,datalen); + portable_mutex_lock(&myinfo->messagemutex); + HASH_ADD_KEYPTR(hh,myinfo->messagetable,msg->key,msg->keylen,msg); + portable_mutex_unlock(&myinfo->messagemutex); + if ( sendping != 0 ) + { + queue_enqueue("basilisk_message",&myinfo->msgQ,&msg->DL,0); + return(clonestr("{\"result\":\"message added to hashtable\"}")); + } else return(0); +} + +int32_t basilisk_ping_processMSG(struct supernet_info *myinfo,uint32_t senderipbits,uint8_t *data,int32_t datalen) +{ + int32_t i,msglen,len=0; uint8_t num,keylen,*msg,*key; + if ( (num= data[len++]) > 0 ) + { + for (i=0; i sizeof(msg->key) && (msg= queue_dequeue(&myinfo->msgQ,0)) != 0 ) // oneshot ping + { + data[datalen++] = 1; + data[datalen++] = msg->keylen; + memcpy(&data[datalen],msg->key,msg->keylen), datalen += msg->keylen; + iguana_rwnum(1,data,sizeof(msg->datalen),&msg->datalen); + if ( maxlen > datalen+msg->datalen ) + memcpy(&data[datalen],msg->data,msg->datalen), datalen += msg->datalen; + else + { + printf("basilisk_ping_genMSG message doesnt fit %d vs %d\n",maxlen,datalen+msg->datalen); + datalen = 0; + } + } data[datalen++] = 0; + return(datalen); +} + +char *basilisk_respond_getmessage(struct supernet_info *myinfo,uint8_t *key,int32_t keylen) +{ + cJSON *retjson; struct basilisk_message *msg; char *ptr = 0,strbuf[16384]; + retjson = cJSON_CreateObject(); + portable_mutex_lock(&myinfo->messagemutex); + HASH_FIND(hh,myinfo->messagetable,key,keylen,msg); + if ( msg != 0 ) + { + if ( basilisk_addhexstr(&ptr,retjson,strbuf,sizeof(strbuf),msg->data,msg->datalen) != 0 ) + jaddstr(retjson,"result","success"); + else jaddstr(retjson,"error","couldnt add message"); + } else jaddstr(retjson,"error","no message"); + portable_mutex_unlock(&myinfo->messagemutex); + return(jprint(retjson,1)); +} + +// respond to incoming OUT, MSG + +int32_t basilisk_messagekey(uint8_t *key,bits256 hash,cJSON *valsobj) +{ + uint32_t channel,msgid; int32_t keylen = 0; + channel = juint(valsobj,"channel"); + msgid = juint(valsobj,"msgid"); + keylen += iguana_rwbignum(1,&key[keylen],sizeof(hash),hash.bytes); + keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&channel); + keylen += iguana_rwnum(1,&key[keylen],sizeof(uint32_t),&msgid); + return(keylen); +} + +char *basilisk_respond_OUT(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk) +{ + int32_t keylen; uint8_t key[64]; + keylen = basilisk_messagekey(key,hash,valsobj); + return(basilisk_respond_sendmessage(myinfo,key,keylen,data,datalen,1)); +} + +char *basilisk_respond_MSG(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk) +{ + int32_t keylen; uint8_t key[64]; + keylen = basilisk_messagekey(key,hash,valsobj); + return(basilisk_respond_getmessage(myinfo,key,keylen)); +} + +#include "../includes/iguana_apidefs.h" +#include "../includes/iguana_apideclares.h" +HASH_ARRAY_STRING(basilisk,getmessage,hash,vals,hexstr) +{ + return(basilisk_standardservice("MSG",myinfo,0,hash,vals,hexstr,1)); +} + +HASH_ARRAY_STRING(basilisk,sendmessage,hash,vals,hexstr) +{ + return(basilisk_standardservice("OUT",myinfo,0,hash,vals,hexstr,1)); +} +#include "../includes/iguana_apiundefs.h" + +int32_t basilisk_channelsend(struct supernet_info *myinfo,bits256 hash,uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen) +{ + char *retstr,*hexstr,strbuf[16384],*ptr = 0; int32_t retval = -1; cJSON *retjson,*valsobj; + if ( (hexstr= basilisk_addhexstr(&ptr,0,strbuf,sizeof(strbuf),data,datalen)) != 0 ) + { + valsobj = cJSON_CreateObject(); + jaddnum(valsobj,"channel",channel); + jaddnum(valsobj,"msgid",msgid); + if ( (retstr= basilisk_sendmessage(myinfo,0,0,0,hash,valsobj,hexstr)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( jobj(retjson,"error") == 0 ) + retval = 0; + free_json(retjson); + } + free(retstr); + } + free_json(valsobj); + if ( ptr != 0 ) + free(ptr); + } + return(retval); +} + +int32_t basilisk_channelget(struct supernet_info *myinfo,bits256 hash,uint32_t channel,uint32_t msgid,uint8_t *data,int32_t maxlen) +{ + char *retstr,*hexstr; cJSON *valsobj,*retjson; int32_t datalen,retval = -1; + valsobj = cJSON_CreateObject(); + jaddnum(valsobj,"channel",channel); + jaddnum(valsobj,"msgid",msgid); + if ( (retstr= basilisk_getmessage(myinfo,0,0,0,hash,valsobj,0)) != 0 ) + { + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (hexstr= jstr(retjson,"data")) != 0 && (datalen= is_hexstr(hexstr,0)) > 0 ) + { + if ( datalen < maxlen ) + { + decode_hex(data,datalen,hexstr); + retval = datalen; + } + } + free_json(retjson); + } + free(retstr); + } + free_json(valsobj); + return(retval); +} diff --git a/basilisk/basilisk_bitcoin.c b/basilisk/basilisk_bitcoin.c index 09c2a4ea5..2bc997ea1 100755 --- a/basilisk/basilisk_bitcoin.c +++ b/basilisk/basilisk_bitcoin.c @@ -13,13 +13,13 @@ * * ******************************************************************************/ -struct bitcoin_rawtxdependents +/*struct bitcoin_rawtxdependents { int64_t spentsatoshis,outputsum,cost,change; int32_t numptrs,numresults; char **results,*coinaddrs; struct basilisk_item *ptrs[]; -}; +};*/ #ifdef bitcoincancalculatebalances int64_t bitcoin_value(struct iguana_info *coin,bits256 txid,int16_t vout,char *coinaddr) @@ -649,3 +649,338 @@ void *basilisk_bitcoinrawtx(struct basilisk_item *Lptr,struct supernet_info *myi return(basilisk_issueremote(myinfo,0,&numsent,"RAW",coin->symbol,1,valsobj,juint(valsobj,"fanout"),juint(valsobj,"minresults"),basilisktag,timeoutmillis,coin->basilisk_rawtxmetric,0,0,0,BASILISK_DEFAULTDIFF)); } +#ifdef later +int32_t instantdex_outputinsurance(char *coinaddr,uint8_t addrtype,uint8_t *script,int64_t insurance,uint64_t r,uint64_t dest) +{ + uint8_t rmd160[20]; int32_t n = 0; + decode_hex(rmd160,sizeof(rmd160),(dest % 10) == 9 ? TIERNOLAN_RMD160 : INSTANTDEX_RMD160); + //script[n++] = sizeof(r); + //n += iguana_rwnum(1,&script[n],sizeof(r),&r); + //script[n++] = SCRIPT_OP_DROP; + bitcoin_address(coinaddr,addrtype,rmd160,20); + n = bitcoin_standardspend(script,n,rmd160); + return(n); +} + +void iguana_addinputs(struct iguana_info *coin,struct bitcoin_spend *spend,cJSON *txobj,uint32_t sequence) +{ + int32_t i,j,plen; uint8_t *pubkeyptrs[16]; + for (i=0; inuminputs; i++) + { + spend->inputs[i].sequence = sequence; + for (j=0; j<16; j++) + { + if ( (plen= bitcoin_pubkeylen(spend->inputs[i].pubkeys[j])) < 0 ) + break; + pubkeyptrs[j] = spend->inputs[i].pubkeys[j]; + } + bitcoin_txinput(coin,txobj,spend->inputs[i].txid,spend->inputs[i].vout,spend->inputs[i].sequence,spend->inputs[i].spendscript,spend->inputs[i].spendlen,spend->inputs[i].p2shscript,spend->inputs[i].p2shlen,j>0?pubkeyptrs:0,j); + } +} + +struct bitcoin_statetx *instantdex_signtx(char *str,struct supernet_info *myinfo,struct iguana_info *coin,uint32_t locktime,char *scriptstr,int64_t satoshis,int64_t txfee,int32_t minconf,int32_t myside) +{ + struct iguana_waddress *waddr; struct iguana_waccount *wacct; struct bitcoin_statetx *tx=0; char coinaddr[64],wifstr[64]; char *rawtx=0,*signedtx,*retstr; bits256 signedtxid; uint32_t basilisktag; int32_t flag,completed; cJSON *valsobj,*vins=0,*retjson=0,*privkey,*addresses; + if ( (waddr= iguana_getaccountaddress(myinfo,coin,0,0,coin->changeaddr,"change")) == 0 ) + { + printf("no change addr error\n"); + return(0); + } + privkey = cJSON_CreateArray(); + addresses = cJSON_CreateArray(); + if ( coin->changeaddr[0] == 0 ) + bitcoin_address(coin->changeaddr,coin->chain->pubtype,waddr->rmd160,20); + //bitcoin_pubkey33(myinfo->ctx,pubkey33,myinfo->persistent_priv); + bitcoin_address(coinaddr,coin->chain->pubtype,myinfo->persistent_pubkey33,33); + //printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr); + if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 ) + { + bitcoin_priv2wif(wifstr,waddr->privkey,coin->chain->wiftype); + jaddistr(privkey,waddr->wifstr); + } + basilisktag = (uint32_t)rand(); + jaddistr(addresses,coinaddr); + valsobj = cJSON_CreateObject(); + jadd(valsobj,"addresses",addresses); + jaddstr(valsobj,"coin",coin->symbol); + jaddstr(valsobj,"spendscript",scriptstr); + jaddstr(valsobj,"changeaddr",coin->changeaddr); + jadd64bits(valsobj,"satoshis",satoshis); + jadd64bits(valsobj,"txfee",txfee); + jaddnum(valsobj,"minconf",minconf); + jaddnum(valsobj,"basilisktag",basilisktag); + jaddnum(valsobj,"locktime",locktime); + jaddnum(valsobj,"timeout",30000); + if ( (retstr= basilisk_rawtx(myinfo,coin,0,0,myinfo->myaddr.persistent,valsobj,"")) != 0 ) + { + //printf("%s got.(%s)\n",str,retstr); + flag = 0; + if ( (retjson= cJSON_Parse(retstr)) != 0 ) + { + if ( (rawtx= jstr(retjson,"rawtx")) != 0 && (vins= jobj(retjson,"vins")) != 0 ) + flag = 1; + else printf("missing rawtx.%p or vins.%p\n",rawtx,vins); + } else printf("error parsing.(%s)\n",retstr); + if ( flag != 0 && vins != 0 ) + { + //printf("vins.(%s)\n",jprint(vins,0)); + if ( (signedtx= iguana_signrawtx(myinfo,coin,&signedtxid,&completed,vins,rawtx,privkey)) != 0 ) + { + iguana_unspentslock(myinfo,coin,vins); + tx = calloc(1,sizeof(*tx) + strlen(signedtx) + 1); + strcpy(tx->txbytes,signedtx); + tx->txid = signedtxid; + printf("%s %s.%s\n",myside != 0 ? "BOB" : "ALICE",str,signedtx); + free(signedtx); + } else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll + } + if ( retjson != 0 ) + free_json(retjson); + if ( flag == 2 ) + { + free_json(vins); + printf("Free rawtx\n"); + free(rawtx); + } + free(retstr); + } else printf("error creating %s feetx\n",myside != 0 ? "BOB" : "ALICE"); + free_json(addresses); + return(tx); +} + +struct bitcoin_statetx *instantdex_feetx(struct supernet_info *myinfo,struct instantdex_accept *A,struct basilisk_swap *swap,struct iguana_info *coin) +{ + int32_t n; uint8_t paymentscript[128]; char scriptstr[512],coinaddr[64]; struct bitcoin_statetx *ptr = 0; uint64_t r; + r = swap->mine.orderid; + n = instantdex_outputinsurance(coinaddr,coin->chain->pubtype,paymentscript,swap->insurance + swap->bobcoin->chain->txfee,r,r * (strcmp("BTC",coin->symbol) == 0)); + init_hexbytes_noT(scriptstr,paymentscript,n); + printf("instantdex_feetx %s %.8f (%s)\n",coin->symbol,dstr(swap->insurance + swap->bobcoin->chain->txfee),scriptstr); + if ( (ptr= instantdex_signtx("feetx",myinfo,coin,0,scriptstr,swap->insurance + swap->bobcoin->chain->txfee,coin->txfee,0,A->offer.myside)) != 0 ) + strcpy(ptr->destaddr,coinaddr); + return(ptr); +} + +int32_t instantdex_feetxverify(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_swap *swap,cJSON *argjson) +{ + cJSON *txobj; bits256 txid; uint32_t n; int32_t i,retval = -1,extralen=65536; int64_t insurance; uint64_t r; + struct iguana_msgtx msgtx; uint8_t script[512],serialized[8192],*extraspace=0; char coinaddr[64]; + if ( swap->otherfee != 0 ) + { + extraspace = calloc(1,extralen); + if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->otherfee->txbytes,extraspace,extralen,serialized)) != 0 ) + { + r = swap->other.orderid; + if ( strcmp(coin->symbol,"BTC") == 0 ) + insurance = swap->insurance + swap->bobcoin->chain->txfee; + else insurance = swap->altinsurance + swap->alicecoin->chain->txfee; + n = instantdex_outputinsurance(coinaddr,coin->chain->pubtype,script,insurance,r,r * (strcmp("BTC",coin->symbol) == 0)); + if ( n == msgtx.vouts[0].pk_scriptlen ) + { + if ( memcmp(script,msgtx.vouts[0].pk_script,n) == 0 ) + { + printf("feetx script verified.(%s)\n",swap->otherfee->txbytes); + retval = 0; + } + else + { + for (i=0; iotherfee->txbytes); + } else printf("no feetx to verify\n"); + if ( extraspace != 0 ) + free(extraspace); + return(retval); +} + +struct bitcoin_statetx *instantdex_bobtx(struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,int64_t amount,int32_t depositflag) +{ + int32_t n,secretstart; struct bitcoin_statetx *ptr = 0; uint8_t script[1024]; uint32_t locktime; int64_t satoshis; char scriptstr[512]; + if ( coin == 0 ) + return(0); + satoshis = amount + depositflag*swap->insurance*100 + swap->bobcoin->chain->txfee; + n = instantdex_bobscript(script,0,&locktime,&secretstart,swap,depositflag); + if ( n < 0 ) + { + printf("instantdex_bobtx couldnt generate bobscript deposit.%d\n",depositflag); + return(0); + } + printf("locktime.%u amount %.8f satoshis %.8f\n",locktime,dstr(amount),dstr(satoshis)); + init_hexbytes_noT(scriptstr,script,n); + if ( (ptr= instantdex_signtx(depositflag != 0 ? "deposit" : "payment",myinfo,coin,locktime,scriptstr,satoshis,coin->txfee,swap->mine.minconfirms,swap->mine.offer.myside)) != 0 ) + { + bitcoin_address(ptr->destaddr,coin->chain->p2shtype,script,n); + printf("BOBTX.%d (%s) -> %s\n",depositflag,ptr->txbytes,ptr->destaddr); + } else printf("sign error for bottx\n"); + return(ptr); +} + +int32_t instantdex_paymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_swap *swap,cJSON *argjson,int32_t depositflag) +{ + cJSON *txobj; bits256 txid; uint32_t n,locktime; int32_t i,secretstart,retval = -1,extralen=65536; uint64_t x; + struct iguana_msgtx msgtx; uint8_t script[512],serialized[8192],*extraspace=0; int64_t amount; + if ( coin != 0 && swap->deposit != 0 ) + { + amount = swap->BTCsatoshis + depositflag*swap->insurance*100 + swap->bobcoin->chain->txfee; + if ( (n= instantdex_bobscript(script,0,&locktime,&secretstart,swap,depositflag)) <= 0 ) + return(retval); + extraspace = calloc(1,extralen); + if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->deposit->txbytes,extraspace,extralen,serialized)) != 0 ) + { + memcpy(&script[secretstart],&msgtx.vouts[0].pk_script[secretstart],20); + printf("locktime.%u amount %.8f satoshis %.8f\n",locktime,dstr(amount),dstr(amount)); + if ( msgtx.lock_time == locktime && msgtx.vouts[0].value == amount && n == msgtx.vouts[0].pk_scriptlen ) + { + if ( memcmp(script,msgtx.vouts[0].pk_script,n) == 0 ) + { + iguana_rwnum(0,&script[secretstart],sizeof(x),&x); + printf("deposit script verified\n"); + if ( x == swap->otherdeck[swap->choosei][0] ) + retval = 0; + else printf("deposit script verified but secret mismatch x.%llx vs otherdeck %llx\n",(long long)x,(long long)swap->otherdeck[swap->choosei][0]); + } + else + { + for (i=0; ialtpayment != 0 && (altmsigaddr= jstr(argjson,"altmsigaddr")) != 0 ) + { + extraspace = calloc(1,extralen); + if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->altpayment->txbytes,extraspace,extralen,serialized)) != 0 ) + { + n = instantdex_alicescript(script,0,msigaddr,coin->chain->p2shtype,swap->pubAm,swap->pubBn); + if ( strcmp(msigaddr,altmsigaddr) == 0 && n == msgtx.vouts[0].pk_scriptlen ) + { + if ( memcmp(script,msgtx.vouts[0].pk_script,n) == 0 ) + { + printf("altpayment script verified\n"); + retval = 0; + } + else + { + for (i=0; ialtpayment,altmsigaddr!=0?altmsigaddr:""); + if ( extraspace != 0 ) + free(extraspace); + return(retval); +} + +struct bitcoin_statetx *instantdex_alicetx(struct supernet_info *myinfo,struct iguana_info *alicecoin,char *msigaddr,bits256 pubAm,bits256 pubBn,int64_t amount,struct basilisk_swap *swap) +{ + int32_t n; uint8_t script[1024]; char scriptstr[2048]; struct bitcoin_statetx *ptr = 0; + if ( alicecoin != 0 ) + { + if ( bits256_nonz(pubAm) == 0 || bits256_nonz(pubBn) == 0 ) + { + printf("instantdex_bobtx null pubAm.%llx or pubBn.%llx\n",(long long)pubAm.txid,(long long)pubBn.txid); + return(0); + } + n = instantdex_alicescript(script,0,msigaddr,alicecoin->chain->p2shtype,pubAm,pubBn); + init_hexbytes_noT(scriptstr,script,n); + if ( (ptr= instantdex_signtx("altpayment",myinfo,alicecoin,0,scriptstr,amount,alicecoin->txfee,swap->mine.minconfirms,swap->mine.offer.myside)) != 0 ) + { + strcpy(ptr->destaddr,msigaddr); + printf("ALICETX (%s) -> %s\n",ptr->txbytes,ptr->destaddr); + } + } + return(ptr); +} + +cJSON *BTC_makeclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct basilisk_swap *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp) +{ + int32_t got_payment=1,bob_reclaimed=0; + *serdatap = 0, *serdatalenp = 0; + if ( instantdex_isbob(swap) == 0 ) + { + // [BLOCKING: payfound] now Alice's turn to make sure payment is confrmed and send in claim or see bob's reclaim and reclaim + if ( got_payment != 0 ) + { + //swap->privAm = swap->privkeys[swap->otherchoosei]; + // sign if/else payment + } + else if ( bob_reclaimed != 0 ) + { + + } + } + else + { + // [BLOCKING: privM] Bob waits for privM either from Alice or alt blockchain + if ( bits256_nonz(swap->privAm) != 0 ) + { + // a multisig tx for alicecoin + } + } + return(newjson); +} +#endif +#include "../includes/iguana_apidefs.h" +#include "../includes/iguana_apideclares.h" + +HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr) +{ + return(basilisk_standardservice("BAL",myinfo,0,hash,vals,hexstr,1)); +} + +HASH_ARRAY_STRING(basilisk,value,hash,vals,hexstr) +{ + return(basilisk_standardservice("VAL",myinfo,0,hash,vals,hexstr,1)); +} + +HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr) +{ + char *retstr=0,*symbol; uint32_t basilisktag; struct basilisk_item *ptr,Lptr; int32_t timeoutmillis; + if ( (symbol= jstr(vals,"symbol")) != 0 || (symbol= jstr(vals,"coin")) != 0 ) + { + if ( (coin= iguana_coinfind(symbol)) != 0 ) + { + basilisktag = juint(vals,"basilisktag"); + if ( juint(vals,"burn") == 0 ) + jaddnum(vals,"burn",0.0001); + if ( (timeoutmillis= juint(vals,"timeout")) <= 0 ) + timeoutmillis = BASILISK_TIMEOUT; + if ( (ptr= basilisk_bitcoinrawtx(&Lptr,myinfo,coin,remoteaddr,basilisktag,timeoutmillis,vals)) != 0 ) + { + retstr = ptr->retstr; + } + if ( ptr != &Lptr ) + free(ptr); + } + } + return(retstr); +} +#include "../includes/iguana_apiundefs.h" diff --git a/basilisk/basilisk_ping.c b/basilisk/basilisk_ping.c index a89e0a98b..9f8f27e9e 100755 --- a/basilisk/basilisk_ping.c +++ b/basilisk/basilisk_ping.c @@ -172,7 +172,10 @@ void basilisk_ping_process(struct supernet_info *myinfo,struct iguana_peer *addr len += n; } if ( len <= datalen-sizeof(sn) ) + { len += basilisk_ping_processDEX(myinfo,senderipbits,&data[len],datalen-len); + len += basilisk_ping_processMSG(myinfo,senderipbits,&data[len],datalen-len); + } if ( len != datalen ) printf("PING got %d, processed.%d from (%s)\n",datalen,len,ipbuf); //else printf("\n"); @@ -189,6 +192,7 @@ int32_t basilisk_ping_gen(struct supernet_info *myinfo,uint8_t *data,int32_t max for (i=0; inumrelays; i++) datalen += basilisk_ping_genrelay(myinfo,&data[datalen],maxlen - datalen,&myinfo->relays[i]); datalen += basilisk_ping_genDEX(myinfo,&data[datalen],maxlen - datalen); + datalen += basilisk_ping_genMSG(myinfo,&data[datalen],maxlen - datalen); //for (i=0; ibytes,orderhash.bytes,sizeof(orderhash),sharedsecret.bytes,sizeof(sharedsecret)); + return(bitcoin_pubkey33(myinfo->ctx,pubkey,*newprivp)); +} + +int32_t instantdex_pubkeyargs(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t numpubs,bits256 privkey,bits256 hash,int32_t firstbyte) +{ + char buf[3]; int32_t i,n,m,len=0; bits256 pubi; uint64_t txid; uint8_t secret160[20],pubkey[33]; + sprintf(buf,"%c0",'A' - 0x02 + firstbyte); + if ( numpubs > 2 ) + { + if ( swap->numpubs+2 >= numpubs ) + return(numpubs); + printf(">>>>>> start generating %s\n",buf); + } + for (i=n=m=0; imypubs[n]) == 0 ) + { + swap->myprivs[n] = privkey; + memcpy(swap->mypubs[n].bytes,pubkey+1,sizeof(bits256)); + } + } + if ( swap->numpubs < INSTANTDEX_DECKSIZE ) + { + swap->privkeys[m] = privkey; + calc_rmd160_sha256(secret160,privkey.bytes,sizeof(privkey)); + memcpy(&txid,secret160,sizeof(txid)); + len += iguana_rwnum(1,(uint8_t *)&swap->deck[m][0],sizeof(txid),&txid); + len += iguana_rwnum(1,(uint8_t *)&swap->deck[m][1],sizeof(pubi.txid),&pubi.txid); + m++; + if ( m > swap->numpubs ) + swap->numpubs = m; + } + n++; + } + if ( n > 2 || m > 2 ) + printf("n.%d m.%d len.%d numpubs.%d\n",n,m,len,swap->numpubs); + return(n); +} + +char *instantdex_choosei(struct basilisk_swap *swap,cJSON *newjson,cJSON *argjson,uint8_t *serdata,int32_t datalen) +{ + int32_t i,j,max,len = 0; uint64_t x; + if ( swap->choosei < 0 && serdata != 0 && datalen == sizeof(swap->deck) ) + { + max = (int32_t)(sizeof(swap->otherdeck) / sizeof(*swap->otherdeck)); + for (i=0; iotherdeck[i][j],sizeof(x),&serdata[len]); + OS_randombytes((uint8_t *)&swap->choosei,sizeof(swap->choosei)); + if ( swap->choosei < 0 ) + swap->choosei = -swap->choosei; + swap->choosei %= max; + jaddnum(newjson,"mychoosei",swap->choosei); + printf(" %s send mychoosei.%d of max.%d deck.(%llx %llx)\n",swap->iambob!=0?"BOB":"alice",swap->choosei,max,(long long)swap->otherdeck[0][0],(long long)swap->otherdeck[0][1]); + return(0); + } + else + { + printf("choosei.%d or null serdata.%p or invalid datalen.%d vs %d\n",swap->choosei,serdata,datalen,(int32_t)sizeof(swap->deck)); + return(clonestr("{\"error\":\"instantdex_BTCswap offer no cut\"}")); + } +} + +void instantdex_privkeyextract(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *serdata,int32_t serdatalen) +{ + int32_t i,j,wrongfirstbyte,errs,len = 0; bits256 otherpriv,pubi; uint8_t secret160[20],otherpubkey[33],pubkey[33]; uint64_t txid; + if ( swap->cutverified == 0 && swap->choosei >= 0 && serdatalen == sizeof(swap->privkeys) ) + { + for (i=wrongfirstbyte=errs=0; iprivkeys)/sizeof(*swap->privkeys); i++) + { + for (j=0; j<32; j++) + otherpriv.bytes[j] = serdata[len++]; + if ( i == swap->choosei ) + { + if ( bits256_nonz(otherpriv) != 0 ) + { + printf("got privkey in slot.%d my choosei??\n",i); + errs++; + } + if ( swap->iambob != 0 ) + { + if ( otherpubkey[0] == 0x02 ) + { + if ( bits256_nonz(swap->privkeys[i]) != 0 ) + { + swap->privBn = swap->privkeys[i]; + calc_rmd160_sha256(swap->secretBn,swap->privBn.bytes,sizeof(swap->privBn)); + printf("set secretBn\n"); + swap->pubBn = bitcoin_pubkey33(myinfo->ctx,pubkey,swap->privBn); + } + } else printf("wrong first byte.%02x\n",otherpubkey[0]); + } + else + { + if ( otherpubkey[0] == 0x03 ) + { + if ( bits256_nonz(swap->privkeys[i]) != 0 ) + { + swap->privAm = swap->privkeys[i]; + calc_rmd160_sha256(swap->secretAm,swap->privAm.bytes,sizeof(swap->privAm)); + printf("set secretAm\n"); + swap->pubAm = bitcoin_pubkey33(myinfo->ctx,pubkey,swap->privAm); + } + } else printf("wrong first byte.%02x\n",otherpubkey[0]); + } + continue; + } + pubi = bitcoin_pubkey33(myinfo->ctx,otherpubkey,otherpriv); + calc_rmd160_sha256(secret160,otherpriv.bytes,sizeof(otherpriv)); + memcpy(&txid,secret160,sizeof(txid)); + if ( otherpubkey[0] != (swap->iambob ^ 1) + 0x02 ) + { + wrongfirstbyte++; + printf("wrongfirstbyte[%d] %02x\n",i,otherpubkey[0]); + } + else if ( swap->otherdeck[i][1] != pubi.txid ) + { + printf("otherdeck[%d] priv ->pub mismatch %llx != %llx\n",i,(long long)swap->otherdeck[i][1],(long long)pubi.txid); + errs++; + } + else if ( swap->otherdeck[i][0] != txid ) + { + printf("otherdeck[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherdeck[i][0],(long long)txid); + errs++; + } + } + if ( errs == 0 && wrongfirstbyte == 0 ) + swap->cutverified = 1, printf("CUT VERIFIED\n"); + else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs); + } +} + +struct basilisk_swap *bitcoin_swapinit(struct supernet_info *myinfo,struct basilisk_swap *swap) +{ + struct iguana_info *coin; + if ( strcmp("BTC",swap->req.src) == 0 ) + { + swap->bobcoin = iguana_coinfind("BTC"); + swap->bobsatoshis = swap->req.srcamount; + swap->bobconfirms = (1 + sqrt(dstr(swap->bobsatoshis) * .1)); + swap->alicecoin = iguana_coinfind(swap->req.dest); + swap->alicesatoshis = swap->req.destamount; + swap->aliceconfirms = swap->bobconfirms * 3; + } + else if ( strcmp("BTC",swap->req.dest) == 0 ) + { + swap->bobcoin = iguana_coinfind("BTC"); + swap->bobsatoshis = swap->req.destamount; + swap->bobconfirms = (1 + sqrt(dstr(swap->bobsatoshis) * .1)); + swap->alicecoin = iguana_coinfind(swap->req.src); + swap->alicesatoshis = swap->req.srcamount; + swap->aliceconfirms = swap->bobconfirms * 3; + } + else + { + if ( (coin= iguana_coinfind(swap->req.src)) != 0 ) + { + if ( coin->chain->havecltv != 0 ) + { + swap->bobcoin = coin; + swap->bobsatoshis = swap->req.srcamount; + swap->alicecoin = iguana_coinfind(swap->req.dest); + swap->alicesatoshis = swap->req.destamount; + } + else if ( (coin= iguana_coinfind(swap->req.dest)) != 0 ) + { + if ( coin->chain->havecltv != 0 ) + { + swap->bobcoin = coin; + swap->bobsatoshis = swap->req.destamount; + swap->alicecoin = iguana_coinfind(swap->req.src); + swap->alicesatoshis = swap->req.srcamount; + } + } + } + } + if ( swap->bobcoin == 0 || swap->alicecoin == 0 ) + { + printf("missing BTC.%p or missing alicecoin.%p\n",swap->bobcoin,swap->alicecoin); + free(swap); + return(0); + } + if ( swap->bobconfirms == 0 ) + swap->bobconfirms = swap->bobcoin->chain->minconfirms; + if ( swap->aliceconfirms == 0 ) + swap->aliceconfirms = swap->alicecoin->chain->minconfirms; + swap->bobinsurance = (swap->bobsatoshis / INSTANTDEX_INSURANCEDIV); + swap->aliceinsurance = (swap->alicesatoshis / INSTANTDEX_INSURANCEDIV); + strcpy(swap->bobstr,swap->bobcoin->symbol); + strcpy(swap->alicestr,swap->alicecoin->symbol); + swap->started = (uint32_t)time(NULL); + swap->expiration = swap->req.timestamp + INSTANTDEX_LOCKTIME*2; + swap->locktime = swap->expiration + INSTANTDEX_LOCKTIME; + swap->choosei = swap->otherchoosei = -1; + swap->myhash = myinfo->myaddr.persistent; + if ( bits256_cmp(swap->myhash,swap->req.hash) == 0 ) + { + swap->otherhash = swap->req.desthash; + if ( strcmp(swap->req.src,swap->bobstr) == 0 ) + swap->iambob = 1; + else if ( strcmp(swap->req.dest,swap->alicestr) != 0 ) + { + printf("neither bob nor alice error\n"); + return(0); + } + } + else if ( bits256_cmp(swap->myhash,swap->req.desthash) == 0 ) + { + swap->otherhash = swap->req.hash; + if ( strcmp(swap->req.dest,swap->bobstr) == 0 ) + swap->iambob = 1; + else if ( strcmp(swap->req.src,swap->alicestr) != 0 ) + { + printf("neither alice nor bob error\n"); + return(0); + } + } + else + { + printf("neither src nor dest error\n"); + return(0); + } + if ( bits256_nonz(myinfo->persistent_priv) == 0 || instantdex_pubkeyargs(myinfo,swap,2 + INSTANTDEX_DECKSIZE,myinfo->persistent_priv,swap->myhash,0x02+swap->iambob) != 2 + INSTANTDEX_DECKSIZE ) + { + printf("couldnt generate privkeys\n"); + return(0); + } + return(swap); +} +// end of alice/bob code + +void basilisk_swap_finished(struct supernet_info *myinfo,struct basilisk_swap *swap) +{ + swap->finished = (uint32_t)time(NULL); + // save to permanent storage +} + +void basilisk_swap_purge(struct supernet_info *myinfo,struct basilisk_swap *swap) +{ + int32_t i,n; + portable_mutex_lock(&myinfo->DEX_swapmutex); + n = myinfo->numswaps; + for (i=0; iswaps[i] == swap ) + { + myinfo->swaps[i] = myinfo->swaps[--myinfo->numswaps]; + myinfo->swaps[myinfo->numswaps] = 0; + basilisk_swap_finished(myinfo,swap); + break; + } + portable_mutex_unlock(&myinfo->DEX_swapmutex); +} + +void basilisk_swaploop(void *_swap) +{ + uint8_t *data; int32_t maxlen,datalen,numconfirms; struct supernet_info *myinfo; struct basilisk_swap *swap = _swap; + myinfo = swap->myinfo; + printf("start swap\n"); + maxlen = sizeof(*swap); + data = malloc(maxlen); + while ( time(NULL) < swap->expiration ) + { + // iterate swap statemachine + if ( (swap->statebits & 0x01) == 0 ) // wait for pubkeys + { + if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x01,data,maxlen)) == sizeof(swap->otherdeck) ) + { + swap->statebits |= 0x01; + } + } + else if ( (swap->statebits & 0x02) == 0 ) // send pubkeys + { + datalen = sizeof(swap->deck); + if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x01,data,datalen) == 0 ) + swap->statebits |= 0x02; + } + else if ( (swap->statebits & 0x04) == 0 ) // wait for choosei + { + datalen = sizeof(swap->otherchoosei); + if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x04,data,maxlen)) > 0 ) + { + // set otherchoosei + swap->statebits |= 0x04; + } + } + else if ( (swap->statebits & 0x08) == 0 ) // send choosei + { + datalen = sizeof(swap->choosei); + if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x04,data,datalen) == 0 ) + swap->statebits |= 0x08; + } + else if ( (swap->statebits & 0x10) == 0 ) // wait for all but one privkeys + { + if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x10,data,maxlen)) == sizeof(swap->privkeys) ) + { + // verify privkeys + swap->statebits |= 0x10; + } + } + else if ( (swap->statebits & 0x20) == 0 ) // send all but one privkeys + { + datalen = sizeof(swap->privkeys); + if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x10,data,datalen) == 0 ) + swap->statebits |= 0x20; + } + else if ( (swap->statebits & 0x40) == 0 ) // send fee + { + datalen = strlen(swap->myfee->txbytes); + if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x80,data,datalen) == 0 ) + swap->statebits |= 0x40; + } + else if ( (swap->statebits & 0x80) == 0 ) // wait for fee + { + if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x80,data,maxlen)) > 0 ) + { + // verify and submit otherfee + swap->statebits |= 0x80; + } + } + else // both sides have setup required data and paid txfee + { + if ( swap->iambob != 0 ) + { + if ( (swap->statebits & 0x100) == 0 ) + { + datalen = strlen(swap->deposit->txbytes); + if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x200,data,datalen) == 0 ) + swap->statebits |= 0x100; + } + // [BLOCKING: altfound] make sure altpayment is confirmed and send payment + else if ( (swap->statebits & 0x1000) == 0 ) + { + if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x1000,data,maxlen)) > 0 ) + { + // verify alicepayment and submit, set confirmed height + swap->statebits |= 0x1000; + } + } + else if ( (swap->statebits & 0x2000) == 0 ) + { + if ( iguana_numconfirms(myinfo,swap->alicecoin,swap->alicepayment->txid) >= swap->aliceconfirms ) + swap->statebits |= 0x2000; + } + else if ( (swap->statebits & 0x4000) == 0 ) + { + datalen = strlen(swap->payment->txbytes); + if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x8000,data,datalen) == 0 ) + swap->statebits |= 0x4000; + } + // [BLOCKING: privM] Bob waits for privM either from Alice or alice blockchain + else if ( (swap->statebits & 0x40000) == 0 ) + { + if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x40000,data,maxlen)) > 0 ) + { + // submit claim + swap->statebits |= 0x40000; + } + else if ( iguana_numconfirms(myinfo,swap->alicecoin,swap->alicepayment->txid) >= 0 ) + { + // submit claim + swap->statebits |= 0x40000; + } + else if ( time(NULL) > swap->locktime ) + { + // submit reclaim of deposittxid + swap->statebits |= 0x40000; + } + } + else if ( (swap->statebits & 0x80000) == 0 ) + { + if ( (numconfirms= iguana_numconfirms(myinfo,swap->alicecoin,swap->alicepayment->txid)) >= 0 ) + { + if ( numconfirms >= swap->aliceconfirms ) + swap->statebits |= 0x80000; + else printf("detected alicepayment claim numconfirms.%d\n",numconfirms); + } + } + } + else + { + // [BLOCKING: depfound] Alice waits for deposit to confirm and sends altpayment + if ( (swap->statebits & 0x200) == 0 ) + { + if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x200,data,maxlen)) > 0 ) + { + // verify deposit and submit, set confirmed height + swap->statebits |= 0x200; + } + } + else if ( (swap->statebits & 0x400) == 0 ) + { + if ( iguana_numconfirms(myinfo,swap->bobcoin,swap->deposit->txid) >= swap->bobconfirms ) + swap->statebits |= 0x400; + } + else if ( (swap->statebits & 0x800) == 0 ) + { + datalen = strlen(swap->alicepayment->txbytes); + if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x1000,data,datalen) == 0 ) + swap->statebits |= 0x800; + } + // [BLOCKING: payfound] make sure payment is confrmed and send in claim or see bob's reclaim and reclaim + else if ( (swap->statebits & 0x8000) == 0 ) + { + if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x8000,data,maxlen)) > 0 ) + { + // verify payment and submit, set confirmed height + swap->statebits |= 0x8000; + } + else if ( iguana_numconfirms(myinfo,swap->bobcoin,swap->deposit->txid) >= 0 ) + { + // reclaim and exit + swap->reclaimed = 1; + swap->statebits |= 0x8000; + } + } + else if ( (swap->statebits & 0x10000) == 0 ) + { + if ( swap->reclaim != 0 ) + { + if ( iguana_numconfirms(myinfo,swap->alicecoin,swap->reclaim->txid) >= swap->aliceconfirms ) + swap->statebits |= 0x10000; + } + else if ( iguana_numconfirms(myinfo,swap->bobcoin,swap->payment->txid) >= swap->bobconfirms ) + swap->statebits |= 0x10000; + } + else if ( (swap->statebits & 0x20000) == 0 ) + { + // send privM + // submit claim + datalen = sizeof(swap->privAm); + if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x40000,data,datalen) == 0 ) + swap->statebits |= 0x20000; + } + else if ( (swap->statebits & 0x40000) == 0 ) + { + if ( iguana_numconfirms(myinfo,swap->alicecoin,swap->payment->txid) >= swap->bobconfirms ) + swap->statebits |= 0x40000; + } + } + } + sleep(3); + } + printf("swap finished statebits %x\n",swap->statebits); + basilisk_swap_purge(myinfo,swap); +} + +struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,struct basilisk_request *rp) +{ + int32_t i; struct basilisk_swap *swap = 0; + portable_mutex_lock(&myinfo->DEX_swapmutex); + for (i=0; inumswaps; i++) + if ( myinfo->swaps[i]->req.requestid == rp->requestid ) + { + printf("basilisk_thread_start error trying to start requestid.%u which is already started\n",rp->requestid); + break; + } + if ( i == myinfo->numswaps && i < sizeof(myinfo->swaps)/sizeof(*myinfo->swaps) ) + { + swap = calloc(1,sizeof(*swap)); + swap->req = *rp; + swap->myinfo = myinfo; + if ( bitcoin_swapinit(myinfo,swap) != 0 ) + { + myinfo->swaps[myinfo->numswaps++] = swap; + iguana_launch(iguana_coinfind("BTCD"),"basilisk_swaploop",basilisk_swaploop,swap,IGUANA_PERMTHREAD); + } else free(swap), swap = 0; + } + portable_mutex_unlock(&myinfo->DEX_swapmutex); + return(swap); +} + +struct basilisk_swap *basilisk_request_started(struct supernet_info *myinfo,uint32_t requestid) +{ + int32_t i; struct basilisk_swap *active = 0; + portable_mutex_lock(&myinfo->DEX_swapmutex); + for (i=0; inumswaps; i++) + if ( myinfo->swaps[i]->req.requestid == requestid ) + { + active = myinfo->swaps[i]; + break; + } + portable_mutex_unlock(&myinfo->DEX_swapmutex); + return(active); +} diff --git a/iguana/iguana_instantdex.c b/deprecated/iguana_instantdex.c similarity index 93% rename from iguana/iguana_instantdex.c rename to deprecated/iguana_instantdex.c index dd08d16a2..9f21a4309 100755 --- a/iguana/iguana_instantdex.c +++ b/deprecated/iguana_instantdex.c @@ -503,106 +503,6 @@ char *instantdex_sendcmd(struct supernet_info *myinfo,struct instantdex_offer *o }*/ } -int32_t instantdex_updatesources(struct exchange_info *exchange,struct exchange_quote *sortbuf,int32_t n,int32_t max,int32_t ind,int32_t dir,struct exchange_quote *quotes,int32_t numquotes) -{ - int32_t i; struct exchange_quote *quote; - //printf("instantdex_updatesources.%s update dir.%d numquotes.%d\n",exchange->name,dir,numquotes); - for (i=0; iprice,quote->volume); - if ( quote->price > SMALLVAL ) - { - sortbuf[n] = *quote; - sortbuf[n].val = ind; - sortbuf[n].exchangebits = exchange->exchangebits; - //printf("sortbuf[%d] <-\n",n*2); - if ( ++n >= max ) - break; - } - } - return(n); -} - -double instantdex_aveprice(struct supernet_info *myinfo,struct exchange_quote *sortbuf,int32_t max,double *totalvolp,char *base,char *rel,double basevolume,cJSON *argjson) -{ - char *str; double totalvol,pricesum; uint32_t timestamp; - struct exchange_quote quote; int32_t i,n,dir,num,depth = 100; - struct exchange_info *exchange; struct exchange_request *req,*active[64]; - timestamp = (uint32_t)time(NULL); - if ( basevolume < 0. ) - basevolume = -basevolume, dir = -1; - else dir = 1; - memset(sortbuf,0,sizeof(*sortbuf) * max); - if ( base != 0 && rel != 0 && basevolume > SMALLVAL ) - { - for (i=num=0; inumexchanges && num < sizeof(active)/sizeof(*active); i++) - { - if ( (exchange= myinfo->tradingexchanges[i]) != 0 ) - { - if ( (req= exchanges777_baserelfind(exchange,base,rel,'M')) == 0 ) - { - if ( (str= exchanges777_Qprices(exchange,base,rel,30,1,depth,argjson,1,exchange->commission)) != 0 ) - free(str); - req = exchanges777_baserelfind(exchange,base,rel,'M'); - } - if ( req == 0 ) - { - if ( (*exchange->issue.supports)(exchange,base,rel,argjson) != 0 ) - printf("unexpected null req.(%s %s) %s\n",base,rel,exchange->name); - } - else - { - //printf("active.%s\n",exchange->name); - active[num++] = req; - } - } - } - for (i=n=0; inumbids > 0 ) - n = instantdex_updatesources(active[i]->exchange,sortbuf,n,max,i,1,active[i]->bidasks,active[i]->numbids); - else if ( dir > 0 && active[i]->numasks > 0 ) - n = instantdex_updatesources(active[i]->exchange,sortbuf,n,max,i,-1,&active[i]->bidasks[1],active[i]->numasks); - } - //printf("dir.%d %s/%s numX.%d n.%d\n",dir,base,rel,num,n); - if ( dir < 0 ) - revsort64s(&sortbuf[0].satoshis,n,sizeof(*sortbuf)); - else sort64s(&sortbuf[0].satoshis,n,sizeof(*sortbuf)); - for (totalvol=pricesum=i=0; iexchange->name,pricesum/totalvol,totalvol); - } - } - if ( totalvol > 0. ) - { - *totalvolp = totalvol; - return(pricesum / totalvol); - } - } - *totalvolp = 0; - return(0); -} - -double instantdex_avehbla(struct supernet_info *myinfo,double retvals[4],char *base,char *rel,double basevolume) -{ - double avebid,aveask,bidvol,askvol; struct exchange_quote sortbuf[256]; cJSON *argjson; - argjson = cJSON_CreateObject(); - aveask = instantdex_aveprice(myinfo,sortbuf,sizeof(sortbuf)/sizeof(*sortbuf),&askvol,base,rel,basevolume,argjson); - avebid = instantdex_aveprice(myinfo,sortbuf,sizeof(sortbuf)/sizeof(*sortbuf),&bidvol,base,rel,-basevolume,argjson); - free_json(argjson); - retvals[0] = avebid, retvals[1] = bidvol, retvals[2] = aveask, retvals[3] = askvol; - if ( avebid > SMALLVAL && aveask > SMALLVAL ) - return((avebid + aveask) * .5); - else return(0); -} - int32_t instantdex_bidaskdir(struct instantdex_offer *offer) { if ( offer->myside == 0 && offer->acceptdir > 0 ) // base @@ -1567,6 +1467,7 @@ void instantdex_update(struct supernet_info *myinfo) }*/ } +/* #include "../includes/iguana_apidefs.h" TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,maxaccept,base,rel,maxprice,basevolume) @@ -1656,19 +1557,6 @@ THREE_STRINGS(atomic,claim,myorderid,otherid,txname) } } -THREE_STRINGS_AND_DOUBLE(tradebot,aveprice,comment,base,rel,basevolume) -{ - double retvals[4],aveprice; cJSON *retjson = cJSON_CreateObject(); - aveprice = instantdex_avehbla(myinfo,retvals,base,rel,basevolume); - jaddstr(retjson,"result","success"); - jaddnum(retjson,"aveprice",aveprice); - jaddnum(retjson,"avebid",retvals[0]); - jaddnum(retjson,"bidvol",retvals[1]); - jaddnum(retjson,"aveask",retvals[2]); - jaddnum(retjson,"askvol",retvals[3]); - return(jprint(retjson,1)); -} - cJSON *instantdex_reportjson(cJSON *item,char *name) { cJSON *newjson = cJSON_CreateObject(); uint64_t dateval; @@ -1719,4 +1607,4 @@ TWO_STRINGS(InstantDEX,events,base,rel) } #include "../includes/iguana_apiundefs.h" - +*/ diff --git a/deprecated/obsolete.h b/deprecated/obsolete.h index 7bd1e7d29..9da7bf365 100755 --- a/deprecated/obsolete.h +++ b/deprecated/obsolete.h @@ -18214,6 +18214,44 @@ len = 0; return(basilisk_waitresponse(myinfo,"RAW",coin->symbol,remoteaddr,&Lptr,vals,ptr)); } else return(clonestr("{\"error\":\"error issuing basilisk rawtx\"}")); } //else return(retstr);*/ + /*int32_t basilisk_request_pending(struct supernet_info *myinfo,struct basilisk_request *rp,uint32_t requestid) + { + int32_t i,j,n,alreadystarted = 0; struct basilisk_relay *relay; uint32_t quoteid; + portable_mutex_lock(&myinfo->DEX_reqmutex); + for (j=0; jnumrelays; j++) + { + relay = &myinfo->relays[j]; + if ( (n= relay->numrequests) > 0 ) + { + for (i=0; irequests[i].requestid == requestid && relay->requests[i].quoteid == quoteid ) + { + alreadystarted = 1; + break; + } + } + } + } + portable_mutex_unlock(&myinfo->DEX_reqmutex); + return(alreadystarted); + } + + void basilisk_request_check(struct supernet_info *myinfo,struct basilisk_request *rp) + { + double retvals[4],aveprice; struct basilisk_request R; struct iguana_info *src,*dest; char message[128]; uint32_t quoteid; + if ( (src= iguana_coinfind(rp->src)) != 0 && (dest= iguana_coinfind(rp->dest)) != 0 ) + { + if ( basilisk_request_pending(myinfo,&R,rp->requestid) == 0 ) + { + aveprice = instantdex_avehbla(myinfo,retvals,rp->src,rp->dest,dstr(rp->srcamount)); + quoteid = rp->requestid ^ myinfo->myaddr.persistent.uints[0]; + sprintf(message,"{\"price\":%.8f,\"requestid\":%u,\"quoteid\":%u}",aveprice,rp->requestid,quoteid); + if ( basilisk_request_enqueue(myinfo,rp->hash,rp->src,rp->srcamount*aveprice,myinfo->myaddr.persistent,rp->dest,rp->srcamount*aveprice,message,quoteid) != rp->requestid ) + printf("error creating quoteid\n"); + } + } + }*/ #endif #endif diff --git a/iguana/exchanges/bitcoin.c b/iguana/exchanges/bitcoin.c index b48cb9e2a..65252496a 100755 --- a/iguana/exchanges/bitcoin.c +++ b/iguana/exchanges/bitcoin.c @@ -418,7 +418,7 @@ double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchang myinfo = SuperNET_MYINFO(0); bids = cJSON_CreateArray(); asks = cJSON_CreateArray(); - instantdex_offerfind(myinfo,exchange,bids,asks,0,base,rel,0); + //instantdex_offerfind(myinfo,exchange,bids,asks,0,base,rel,0); //printf("bids.(%s) asks.(%s)\n",jprint(bids,0),jprint(asks,0)); retjson = cJSON_CreateObject(); cJSON_AddItemToObject(retjson,"bids",bids); @@ -494,12 +494,12 @@ int32_t is_valid_BTCother(char *other) uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson) { - char *str,*retstr,coinaddr[64]; int32_t added; uint64_t txid = 0; cJSON *json=0; struct instantdex_accept *ap; struct supernet_info *myinfo; struct iguana_info *other; - myinfo = SuperNET_MYINFO(0);//SuperNET_accountfind(argjson); + //char *str,*retstr,coinaddr[64]; int32_t added; uint64_t txid = 0; cJSON *json=0; struct instantdex_accept *ap; struct supernet_info *myinfo; struct iguana_info *other; + //myinfo = SuperNET_MYINFO(0);//SuperNET_accountfind(argjson); //printf("TRADE with myinfo.%p\n",myinfo); if ( retstrp != 0 ) *retstrp = 0; - if ( strcmp(base,"BTC") == 0 || strcmp(base,"btc") == 0 ) + /*if ( strcmp(base,"BTC") == 0 || strcmp(base,"btc") == 0 ) { base = rel; rel = "BTC"; @@ -547,32 +547,35 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha *retstrp = retstr; } } - return(txid); + return(txid);*/ + return(0); } char *ORDERSTATUS(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson) { - struct instantdex_accept *ap; struct bitcoin_swapinfo *swap; cJSON *retjson; + //struct instantdex_accept *ap; struct bitcoin_swapinfo *swap; + cJSON *retjson; retjson = cJSON_CreateObject(); struct supernet_info *myinfo;// = SuperNET_accountfind(argjson); myinfo = SuperNET_MYINFO(0);//SuperNET_accountfind(argjson); - if ( (swap= instantdex_statemachinefind(myinfo,exchange,orderid)) != 0 ) + /*if ( (swap= instantdex_statemachinefind(myinfo,exchange,orderid)) != 0 ) jadd(retjson,"result",instantdex_statemachinejson(swap)); else if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,orderid,"*","*",0)) != 0 ) jadd(retjson,"result",instantdex_acceptjson(ap)); else if ( (swap= instantdex_historyfind(myinfo,exchange,orderid)) != 0 ) jadd(retjson,"result",instantdex_historyjson(swap)); - else jaddstr(retjson,"error","couldnt find orderid"); + else jaddstr(retjson,"error","couldnt find orderid");*/ return(jprint(retjson,1)); } char *CANCELORDER(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson) { - struct instantdex_accept *ap = 0; cJSON *retjson; struct bitcoin_swapinfo *swap=0; - struct supernet_info *myinfo;// = SuperNET_accountfind(argjson); - myinfo = SuperNET_MYINFO(0);//SuperNET_accountfind(argjson); + //struct instantdex_accept *ap = 0; struct bitcoin_swapinfo *swap=0; + cJSON *retjson; + //struct supernet_info *myinfo;// = SuperNET_accountfind(argjson); + //myinfo = SuperNET_MYINFO(0);//SuperNET_accountfind(argjson); retjson = cJSON_CreateObject(); - if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,orderid,"*","*",0)) != 0 ) + /*if ( (ap= instantdex_offerfind(myinfo,exchange,0,0,orderid,"*","*",0)) != 0 ) { ap->dead = (uint32_t)time(NULL); jadd(retjson,"orderid",instantdex_acceptjson(ap)); @@ -582,7 +585,7 @@ char *CANCELORDER(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson { jadd(retjson,"orderid",instantdex_statemachinejson(swap)); jaddstr(retjson,"result","killed statemachine orderid, but might have pending"); - } + }*/ return(jprint(retjson,1)); } @@ -592,7 +595,7 @@ char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson) myinfo = SuperNET_MYINFO(0);//SuperNET_accountfind(argjson); bids = cJSON_CreateArray(); asks = cJSON_CreateArray(); - instantdex_offerfind(myinfo,exchange,bids,asks,0,"*","*",0); + //instantdex_offerfind(myinfo,exchange,bids,asks,0,"*","*",0); retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); jadd(retjson,"bids",bids); @@ -606,7 +609,7 @@ char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson) portable_mutex_lock(&exchange->mutexH); DL_FOREACH_SAFE(exchange->history,swap,tmp) { - jaddi(retjson,instantdex_historyjson(swap)); + //jaddi(retjson,instantdex_historyjson(swap)); } portable_mutex_unlock(&exchange->mutexH); return(jprint(retjson,1)); diff --git a/iguana/exchanges777.h b/iguana/exchanges777.h index 82803a5d5..02db64e06 100755 --- a/iguana/exchanges777.h +++ b/iguana/exchanges777.h @@ -42,7 +42,7 @@ #define INSTANTDEX_MINPERC 50 #define INSTANTDEX_OFFERDURATION 600 -#define INSTANTDEX_LOCKTIME 360 +//#define INSTANTDEX_LOCKTIME 3600 #define EXCHANGES777_MINPOLLGAP 1 #define EXCHANGES777_MAXDEPTH 200 @@ -133,13 +133,6 @@ struct instantdex_accept struct instantdex_offer offer; }; -struct bitcoin_statetx -{ - bits256 txid; - uint64_t amount,change,inputsum; - char destaddr[64]; - char txbytes[]; -}; struct instantdex_stateinfo { @@ -155,7 +148,7 @@ struct bitcoin_eventitem { struct queueitem DL; cJSON *argjson,*newjson; int32_t struct bitcoin_swapinfo { struct bitcoin_swapinfo *next,*prev; portable_mutex_t mutex; - queue_t eventsQ; struct bitcoin_eventitem *pollevent; + queue_t eventsQ; //struct bitcoin_eventitem *pollevent; bits256 privkeys[INSTANTDEX_DECKSIZE],myprivs[2],mypubs[2],otherpubs[2],pubA0,pubB0,pubB1,privAm,pubAm,privBn,pubBn; bits256 myorderhash,otherorderhash,mypubkey,othertrader,bothorderhash; uint64_t otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2]; diff --git a/iguana/iguana.sources b/iguana/iguana.sources index 7af8ca3e6..d9d3d8215 100755 --- a/iguana/iguana.sources +++ b/iguana/iguana.sources @@ -1,2 +1,2 @@ -SOURCES := iguana_bundles.c iguana_stake.c iguana_interpreter.c mini-gmp.c main.c iguana_payments.c iguana_spendvectors.c iguana_sign.c iguana_txidfind.c iguana_realtime.c iguana_volatiles.c peggy_price.c iguana_chains.c iguana_ramchain.c iguana_secp.c pangea_api.c peggy_ramkv.c iguana_exchanges.c iguana_recv.c pangea_bets.c peggy_serdes.c SuperNET_keys.c iguana_rpc.c pangea_hand.c peggy_tx.c cards777.c iguana_init.c iguana_scripts.c pangea_json.c peggy_txind.c iguana777.c iguana_instantdex.c iguana_tradebots.c pangea_summary.c peggy_update.c iguana_accept.c iguana_json.c iguana_tx.c peggy.c poker.c iguana_bitmap.c iguana_msg.c iguana_unspents.c peggy_accts.c ramchain_api.c iguana_blocks.c iguana_peers.c iguana_wallet.c peggy_consensus.c ../gecko/gecko.c ../basilisk/basilisk.c ../datachain/datachain.c secp256k1/src/secp256k1.c \ No newline at end of file +SOURCES := iguana_bundles.c iguana_stake.c iguana_interpreter.c mini-gmp.c main.c iguana_payments.c iguana_spendvectors.c iguana_sign.c iguana_txidfind.c iguana_realtime.c iguana_volatiles.c peggy_price.c iguana_chains.c iguana_ramchain.c iguana_secp.c pangea_api.c peggy_ramkv.c iguana_exchanges.c iguana_recv.c pangea_bets.c peggy_serdes.c SuperNET_keys.c iguana_rpc.c pangea_hand.c peggy_tx.c cards777.c iguana_init.c iguana_scripts.c pangea_json.c peggy_txind.c iguana777.c iguana_tradebots.c pangea_summary.c peggy_update.c iguana_accept.c iguana_json.c iguana_tx.c peggy.c poker.c iguana_bitmap.c iguana_msg.c iguana_unspents.c peggy_accts.c ramchain_api.c iguana_blocks.c iguana_peers.c iguana_wallet.c peggy_consensus.c ../gecko/gecko.c ../basilisk/basilisk.c ../datachain/datachain.c secp256k1/src/secp256k1.c \ No newline at end of file diff --git a/iguana/iguana_accept.c b/iguana/iguana_accept.c index b7ee495fb..6a11b6c8a 100755 --- a/iguana/iguana_accept.c +++ b/iguana/iguana_accept.c @@ -110,7 +110,7 @@ void iguana_acceptloop(void *args) coin->peers->active[i].A.port = cli_addr.sin_port; coin->peers->active[i].ready = (uint32_t)time(NULL); flag = 1; - instantdex_peerhas_clear(coin,&coin->peers->active[i]); + //instantdex_peerhas_clear(coin,&coin->peers->active[i]); //iguana_iAkill(coin,&coin->peers->active[i],0); //sleep(1); break; @@ -233,7 +233,7 @@ int32_t iguana_process_msgrequestQ(struct supernet_info *myinfo,struct iguana_in { } - else if ( msg->type == MSG_QUOTE ) + /*else if ( msg->type == MSG_QUOTE ) { if ( (len= instantdex_quoterequest(myinfo,coin,&coin->blockspace[sizeof(struct iguana_msghdr)],coin->blockspacesize,msg->addr,msg->hash2)) > 0 ) { @@ -241,7 +241,7 @@ int32_t iguana_process_msgrequestQ(struct supernet_info *myinfo,struct iguana_in //iguana_msgparser(coin,msg->addr,0,0,0,(void *)coin->blockspace,&coin->blockspace[sizeof(struct iguana_msghdr)],len); iguana_queue_send(msg->addr,0,coin->blockspace,"quote",len); } - } + }*/ } free(msg); } diff --git a/iguana/iguana_chains.c b/iguana/iguana_chains.c index c282876e5..c6127638b 100755 --- a/iguana/iguana_chains.c +++ b/iguana/iguana_chains.c @@ -300,6 +300,8 @@ void iguana_chainparms(struct iguana_chain *chain,cJSON *argjson) chain->estblocktime = juint(argjson,"blocktime"); if ( chain->estblocktime == 0 ) chain->estblocktime = 60; + if ( chain->havecltv == 0 ) + chain->havecltv = juint(argjson,"havecltv"); path = jstr(argjson,"path"); if ( jobj(argjson,"conf") == 0 ) conf[0] = 0; @@ -451,6 +453,7 @@ void iguana_chaininit(struct iguana_chain *chain,int32_t hasheaders,cJSON *argjs { chain->unitval = 0x1d; chain->txfee = 10000; + chain->havecltv = 1; } else chain->txfee = 1000000; if ( chain->unitval == 0 ) diff --git a/iguana/iguana_exchanges.c b/iguana/iguana_exchanges.c index 77233cd20..e79afe357 100755 --- a/iguana/iguana_exchanges.c +++ b/iguana/iguana_exchanges.c @@ -22,6 +22,106 @@ //char *Exchange_names[] = { "poloniex", "bittrex", "btc38", "huobi", "bitstamp", "bitfinex", "btce", "coinbase", "okcoin", "lakebtc", "quadriga", "truefx", "ecb", "instaforex", "fxcm", "yahoo" }; +int32_t instantdex_updatesources(struct exchange_info *exchange,struct exchange_quote *sortbuf,int32_t n,int32_t max,int32_t ind,int32_t dir,struct exchange_quote *quotes,int32_t numquotes) +{ + int32_t i; struct exchange_quote *quote; + //printf("instantdex_updatesources.%s update dir.%d numquotes.%d\n",exchange->name,dir,numquotes); + for (i=0; iprice,quote->volume); + if ( quote->price > SMALLVAL ) + { + sortbuf[n] = *quote; + sortbuf[n].val = ind; + sortbuf[n].exchangebits = exchange->exchangebits; + //printf("sortbuf[%d] <-\n",n*2); + if ( ++n >= max ) + break; + } + } + return(n); +} + +double instantdex_aveprice(struct supernet_info *myinfo,struct exchange_quote *sortbuf,int32_t max,double *totalvolp,char *base,char *rel,double basevolume,cJSON *argjson) +{ + char *str; double totalvol,pricesum; uint32_t timestamp; + struct exchange_quote quote; int32_t i,n,dir,num,depth = 100; + struct exchange_info *exchange; struct exchange_request *req,*active[64]; + timestamp = (uint32_t)time(NULL); + if ( basevolume < 0. ) + basevolume = -basevolume, dir = -1; + else dir = 1; + memset(sortbuf,0,sizeof(*sortbuf) * max); + if ( base != 0 && rel != 0 && basevolume > SMALLVAL ) + { + for (i=num=0; inumexchanges && num < sizeof(active)/sizeof(*active); i++) + { + if ( (exchange= myinfo->tradingexchanges[i]) != 0 ) + { + if ( (req= exchanges777_baserelfind(exchange,base,rel,'M')) == 0 ) + { + if ( (str= exchanges777_Qprices(exchange,base,rel,30,1,depth,argjson,1,exchange->commission)) != 0 ) + free(str); + req = exchanges777_baserelfind(exchange,base,rel,'M'); + } + if ( req == 0 ) + { + if ( (*exchange->issue.supports)(exchange,base,rel,argjson) != 0 ) + printf("unexpected null req.(%s %s) %s\n",base,rel,exchange->name); + } + else + { + //printf("active.%s\n",exchange->name); + active[num++] = req; + } + } + } + for (i=n=0; inumbids > 0 ) + n = instantdex_updatesources(active[i]->exchange,sortbuf,n,max,i,1,active[i]->bidasks,active[i]->numbids); + else if ( dir > 0 && active[i]->numasks > 0 ) + n = instantdex_updatesources(active[i]->exchange,sortbuf,n,max,i,-1,&active[i]->bidasks[1],active[i]->numasks); + } + //printf("dir.%d %s/%s numX.%d n.%d\n",dir,base,rel,num,n); + if ( dir < 0 ) + revsort64s(&sortbuf[0].satoshis,n,sizeof(*sortbuf)); + else sort64s(&sortbuf[0].satoshis,n,sizeof(*sortbuf)); + for (totalvol=pricesum=i=0; iexchange->name,pricesum/totalvol,totalvol); + } + } + if ( totalvol > 0. ) + { + *totalvolp = totalvol; + return(pricesum / totalvol); + } + } + *totalvolp = 0; + return(0); +} + +double instantdex_avehbla(struct supernet_info *myinfo,double retvals[4],char *base,char *rel,double basevolume) +{ + double avebid,aveask,bidvol,askvol; struct exchange_quote sortbuf[256]; cJSON *argjson; + argjson = cJSON_CreateObject(); + aveask = instantdex_aveprice(myinfo,sortbuf,sizeof(sortbuf)/sizeof(*sortbuf),&askvol,base,rel,basevolume,argjson); + avebid = instantdex_aveprice(myinfo,sortbuf,sizeof(sortbuf)/sizeof(*sortbuf),&bidvol,base,rel,-basevolume,argjson); + free_json(argjson); + retvals[0] = avebid, retvals[1] = bidvol, retvals[2] = aveask, retvals[3] = askvol; + if ( avebid > SMALLVAL && aveask > SMALLVAL ) + return((avebid + aveask) * .5); + else return(0); +} + void prices777_processprice(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth) { @@ -583,7 +683,7 @@ char *exchanges777_process(struct exchange_info *exchange,int32_t *retvalp,struc return(retstr); } -void iguana_statemachineupdate(struct supernet_info *myinfo,struct exchange_info *exchange) +/*void iguana_statemachineupdate(struct supernet_info *myinfo,struct exchange_info *exchange) { int32_t timemod,modwidth = 10; struct iguana_info *coin; struct bitcoin_swapinfo *swap,*tmp; struct iguana_bundlereq *req; timemod = time(NULL) % modwidth; @@ -603,7 +703,7 @@ void iguana_statemachineupdate(struct supernet_info *myinfo,struct exchange_info myfree(req->hashes,(req->n+1) * sizeof(*req->hashes)), req->hashes = 0; } //iguana_inv2poll(myinfo,coin); -} +}*/ void exchanges777_loop(void *ptr) { @@ -680,11 +780,11 @@ void exchanges777_loop(void *ptr) tradebot_timeslices(exchange); if ( time(NULL) > exchange->lastpoll+exchange->pollgap ) { - if ( strcmp(exchange->name,"bitcoin") == 0 ) + /*if ( strcmp(exchange->name,"bitcoin") == 0 ) { iguana_statemachineupdate(myinfo,exchange); //printf("InstantDEX call update\n"); - } + }*/ if ( (req= queue_dequeue(&exchange->pricesQ,0)) != 0 ) { //printf("check %s pricesQ (%s %s)\n",exchange->name,req->base,req->rel); @@ -943,7 +1043,7 @@ struct exchange_info *exchange_create(char *exchangestr,cJSON *argjson) exchange->commission *= .01; printf("ADDEXCHANGE.(%s) [%s, %s, %s] commission %.3f%% -> exchangeid.%d\n",exchangestr,exchange->apikey,exchange->userid,exchange->apisecret,exchange->commission * 100.,exchangeid); Exchanges[exchangeid] = exchange; - instantdex_FSMinit(); + //instantdex_FSMinit(); iguana_launch(0,"exchangeloop",(void *)exchanges777_loop,exchange,IGUANA_EXCHANGETHREAD); return(exchange); } diff --git a/iguana/iguana_msg.c b/iguana/iguana_msg.c index f397f2f37..f76290bb5 100755 --- a/iguana/iguana_msg.c +++ b/iguana/iguana_msg.c @@ -761,7 +761,7 @@ int32_t iguana_intvectors(struct iguana_info *coin,struct iguana_peer *addr,int3 } blockhashes[n++] = hash; } - else if ( type == MSG_QUOTE ) + /*else if ( type == MSG_QUOTE ) { if ( quotes == 0 ) { @@ -769,7 +769,7 @@ int32_t iguana_intvectors(struct iguana_info *coin,struct iguana_peer *addr,int3 q = 1; } quotes[q++] = hash; - } + }*/ else if ( type == MSG_FILTERED_BLOCK ) printf(" %d of %d: merkle.%llx\n",i,(int32_t)x,(long long)hash.txid); else printf("what type is %d\n",type); diff --git a/iguana/iguana_peers.c b/iguana/iguana_peers.c index b7322e4cd..cc32ac670 100755 --- a/iguana/iguana_peers.c +++ b/iguana/iguana_peers.c @@ -1147,7 +1147,7 @@ void iguana_dedicatedloop(struct supernet_info *myinfo,struct iguana_info *coin, printf("error creating peer's files\n"); return; } - instantdex_peerhas_clear(coin,addr); + //instantdex_peerhas_clear(coin,addr); #ifdef IGUANA_PEERALLOC int32_t i; int64_t remaining; struct OS_memspace *mem[sizeof(addr->SEROUT)/sizeof(*addr->SEROUT)]; for (i=0; iSEROUT)/sizeof(*addr->SEROUT); i++) diff --git a/iguana/iguana_scripts.c b/iguana/iguana_scripts.c index 82f74858e..468458f5b 100755 --- a/iguana/iguana_scripts.c +++ b/iguana/iguana_scripts.c @@ -95,6 +95,60 @@ int32_t bitcoin_p2shscript(uint8_t *script,int32_t n,const uint8_t *p2shscript,c return(n); } +int32_t instantdex_bobscript(uint8_t *script,int32_t n,uint32_t *locktimep,int32_t *secretstartp,struct basilisk_swap *swap,int32_t depositflag) +{ + uint8_t pubkeyA[33],pubkeyB[33],*secret160; bits256 cltvpub,destpub; int32_t i; + *locktimep = swap->locktime; + if ( depositflag != 0 ) + { + *locktimep += INSTANTDEX_LOCKTIME; + cltvpub = swap->pubA0; + destpub = swap->pubB0; + secret160 = swap->secretBn; + pubkeyA[0] = 0x02; + pubkeyB[0] = 0x03; + } + else + { + cltvpub = swap->pubB1; + destpub = swap->pubA0; + secret160 = swap->secretAm; + pubkeyA[0] = 0x03; + pubkeyB[0] = 0x02; + } + if ( bits256_nonz(cltvpub) == 0 || bits256_nonz(destpub) == 0 ) + return(-1); + for (i=0; i<20; i++) + if ( secret160[i] != 0 ) + break; + if ( i == 20 ) + return(-1); + memcpy(pubkeyA+1,cltvpub.bytes,sizeof(cltvpub)); + memcpy(pubkeyB+1,destpub.bytes,sizeof(destpub)); + script[n++] = SCRIPT_OP_IF; + n = bitcoin_checklocktimeverify(script,n,*locktimep); + n = bitcoin_pubkeyspend(script,n,pubkeyA); + script[n++] = SCRIPT_OP_ELSE; + if ( secretstartp != 0 ) + *secretstartp = n + 2; + n = bitcoin_revealsecret160(script,n,secret160); + n = bitcoin_pubkeyspend(script,n,pubkeyB); + script[n++] = SCRIPT_OP_ENDIF; + return(n); +} + +int32_t instantdex_alicescript(uint8_t *script,int32_t n,char *msigaddr,uint8_t altps2h,bits256 pubAm,bits256 pubBn) +{ + uint8_t p2sh160[20]; struct vin_info V; + memset(&V,0,sizeof(V)); + memcpy(&V.signers[0].pubkey[1],pubAm.bytes,sizeof(pubAm)), V.signers[0].pubkey[0] = 0x02; + memcpy(&V.signers[1].pubkey[1],pubBn.bytes,sizeof(pubBn)), V.signers[1].pubkey[0] = 0x03; + V.M = V.N = 2; + n = bitcoin_MofNspendscript(p2sh160,script,n,&V); + bitcoin_address(msigaddr,altps2h,p2sh160,sizeof(p2sh160)); + return(n); +} + int32_t bitcoin_changescript(struct iguana_info *coin,uint8_t *changescript,int32_t n,uint64_t *changep,char *changeaddr,uint64_t inputsatoshis,uint64_t satoshis,uint64_t txfee) { uint8_t addrtype,rmd160[20]; int32_t len; diff --git a/iguana/swaps/iguana_BTCswap.c b/iguana/swaps/iguana_BTCswap.c index 2fed19806..48b138761 100755 --- a/iguana/swaps/iguana_BTCswap.c +++ b/iguana/swaps/iguana_BTCswap.c @@ -1120,12 +1120,12 @@ char *instantdex_statemachine(struct instantdex_stateinfo *states,int32_t numsta } else { - if ( 0 && strcmp(cmdstr,"poll") != 0 ) + /*if ( 0 && strcmp(cmdstr,"poll") != 0 ) { if ( swap->pollevent != 0 ) instantdex_eventfree(swap->pollevent); swap->pollevent = instantdex_event("poll",argjson,newjson,serdata,serdatalen); - } + }*/ if ( jstr(newjson,"virtevent") != 0 ) { printf("VIRTEVENT.(%s)\n",jstr(newjson,"virtevent")); diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index 8adf3386c..29846306e 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -15,20 +15,22 @@ ZERO_ARGS(InstantDEX,allcoins); STRING_ARG(InstantDEX,available,source); -THREE_STRINGS_AND_DOUBLE(InstantDEX,request,message,dest,source,amount); +//THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,request,message,dest,source,amount,mindestamount,autoflag); +HASH_ARRAY_STRING(InstantDEX,request,hash,vals,hexstr); + INT_ARG(InstantDEX,incoming,requestid); -INT_AND_DOUBLE(InstantDEX,choose,requestid,destamount); -TWO_INTS(InstantDEX,qstatus,requestid,quoteid); +TWO_INTS(InstantDEX,accept,requestid,quoteid); +TWO_INTS(InstantDEX,swapstatus,requestid,quoteid); HASH_ARRAY_STRING(basilisk,genesis_opreturn,hash,vals,hexstr); HASH_ARRAY_STRING(basilisk,balances,hash,vals,hexstr); HASH_ARRAY_STRING(basilisk,value,hash,vals,hexstr); HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr); -//INT_AND_ARRAY(basilisk,result,basilisktag,vals); -//HASH_ARRAY_STRING(basilisk,geckogenesis,hash,vals,hexstr); -//HASH_ARRAY_STRING(basilisk,newgeckochain,hash,vals,hexstr); +HASH_ARRAY_STRING(basilisk,getmessage,hash,vals,hexstr); +HASH_ARRAY_STRING(basilisk,sendmessage,hash,vals,hexstr); + HASH_ARRAY_STRING(basilisk,geckoheaders,hash,vals,hexstr); HASH_ARRAY_STRING(basilisk,geckoblock,hash,vals,hexstr); HASH_ARRAY_STRING(basilisk,geckotx,hash,vals,hexstr); @@ -138,8 +140,8 @@ P2SH_SPENDAPI(iguana,spendmsig,activecoin,vintxid,vinvout,destaddress,destamount STRING_AND_INT(iguana,bundleaddresses,activecoin,height); STRING_AND_INT(iguana,bundlehashes,activecoin,height); -TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,minaccept,base,rel,minprice,basevolume); -TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,maxaccept,base,rel,maxprice,basevolume); +//TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,minaccept,base,rel,minprice,basevolume); +//TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,maxaccept,base,rel,maxprice,basevolume); THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,buy,exchange,base,rel,price,volume,dotrade); THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,sell,exchange,base,rel,price,volume,dotrade); THREE_STRINGS_AND_DOUBLE(InstantDEX,withdraw,exchange,base,destaddr,amount); @@ -153,13 +155,13 @@ STRING_ARG(InstantDEX,tradehistory,exchange); THREE_STRINGS_AND_THREE_INTS(InstantDEX,orderbook,exchange,base,rel,depth,allfields,ignore); STRING_AND_INT(InstantDEX,pollgap,exchange,pollgap); -TWO_STRINGS(InstantDEX,events,base,rel); +//TWO_STRINGS(InstantDEX,events,base,rel); ZERO_ARGS(InstantDEX,allexchanges); STRING_ARG(InstantDEX,allpairs,exchange); THREE_STRINGS(InstantDEX,supports,exchange,base,rel); -THREE_STRINGS(atomic,approve,myorderid,otherid,txname); -THREE_STRINGS(atomic,claim,myorderid,otherid,txname); +//THREE_STRINGS(atomic,approve,myorderid,otherid,txname); +//THREE_STRINGS(atomic,claim,myorderid,otherid,txname); //TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,proposal,reference,message,basetxid,reltxid,duration,flags); //TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS(InstantDEX,accept,reference,message,basetxid,reltxid,duration,flags); diff --git a/includes/iguana_defines.h b/includes/iguana_defines.h index d085b499e..d2ae3f483 100755 --- a/includes/iguana_defines.h +++ b/includes/iguana_defines.h @@ -150,7 +150,7 @@ extern int32_t IGUANA_NUMHELPERS; #define MSG_TX 1 #define MSG_BLOCK 2 #define MSG_FILTERED_BLOCK 3 -#define MSG_QUOTE 253 +//#define MSG_QUOTE 253 #define MSG_BUNDLE 254 #define MSG_BUNDLE_HEADERS 255 diff --git a/includes/iguana_structs.h b/includes/iguana_structs.h index 027009dc7..a9567a045 100755 --- a/includes/iguana_structs.h +++ b/includes/iguana_structs.h @@ -49,7 +49,7 @@ struct iguana_chain char use_addmultisig,do_opreturn; int32_t estblocktime,protover; bits256 genesishash2,PoWtarget,PoStargets[16]; int32_t numPoStargets,PoSheights[16]; - uint8_t zcash,auxpow,alertpubkey[65]; + uint8_t zcash,auxpow,havecltv,alertpubkey[65]; uint16_t targetspacing,targettimespan; uint32_t nBits,normal_txversion,locktime_txversion; }; @@ -463,8 +463,10 @@ struct supernet_info struct exchange_info *tradingexchanges[SUPERNET_MAXEXCHANGES]; int32_t numexchanges; struct iguana_waccount *wallet; struct iguana_info *allcoins; int32_t allcoins_being_added,allcoins_numvirts; - portable_mutex_t allcoins_mutex,gecko_mutex,basilisk_mutex,DEX_mutex,DEX_reqmutex; + portable_mutex_t allcoins_mutex,gecko_mutex,basilisk_mutex,DEX_mutex,DEX_reqmutex,DEX_swapmutex; struct queueitem *DEX_quotes; + struct basilisk_swap *swaps[256]; int32_t numswaps; + struct basilisk_message *messagetable; portable_mutex_t messagemutex; queue_t msgQ; void *ctx; uint8_t *pingbuf; struct delayedPoW_info dPoW;