diff --git a/crypto777/iguana_utils.c b/crypto777/iguana_utils.c index 4729b4781..b1cac334b 100755 --- a/crypto777/iguana_utils.c +++ b/crypto777/iguana_utils.c @@ -133,9 +133,9 @@ int32_t bitweight(uint64_t x) return(wt); } -void calc_OP_HASH160(char hexstr[41],uint8_t hash160[20],char *pubkey) +void calc_OP_HASH160(char hexstr[41],uint8_t rmd160[20],char *pubkey) { - uint8_t sha256[32],buf[4096]; int32_t len; + uint8_t buf[4096]; int32_t len; len = (int32_t)strlen(pubkey)/2; if ( len > sizeof(buf) ) { @@ -143,17 +143,16 @@ void calc_OP_HASH160(char hexstr[41],uint8_t hash160[20],char *pubkey) return; } decode_hex(buf,len,pubkey); - vcalc_sha256(0,sha256,buf,len); - calc_rmd160(0,hash160,sha256,sizeof(sha256)); + calc_rmd160_sha256(rmd160,buf,len); if ( 0 ) { int i; for (i=0; i<20; i++) - printf("%02x",hash160[i]); + printf("%02x",rmd160[i]); printf("<- (%s)\n",pubkey); } if ( hexstr != 0 ) - init_hexbytes_noT(hexstr,hash160,20); + init_hexbytes_noT(hexstr,rmd160,20); } double _dxblend(double *destp,double val,double decay) diff --git a/iguana/SuperNET.c b/iguana/SuperNET.c index 959fb74fd..0c26824da 100644 --- a/iguana/SuperNET.c +++ b/iguana/SuperNET.c @@ -564,9 +564,10 @@ char *SuperNET_DHTsend(struct supernet_info *myinfo,uint64_t destipbits,bits256 jaddbits256(json,"subhash",subhash); if ( SuperNET_hexmsgfind(myinfo,categoryhash,subhash,hexmsg,1) >= 0 ) { - //char str[65]; printf("duplicate hex.(%s) for %s\n",hexmsg,bits256_str(str,categoryhash)); + char str[65]; printf("duplicate hex.(%s) for %s\n",hexmsg,bits256_str(str,categoryhash)); return(clonestr("{\"error\":\"duplicate packet rejected\"}")); } + else SuperNET_hexmsgadd(myinfo,categoryhash,subhash,hexmsg,tai_now(),0); jsonstr = jprint(json,1); if ( broadcastflag != 0 || destipbits == 0 ) { @@ -919,6 +920,18 @@ cJSON *SuperNET_rosettajson(bits256 privkey,int32_t showprivs) #include "../includes/iguana_apidefs.h" +STRING_ARG(SuperNET,addr2rmd160,address) +{ + uint8_t addrtype,rmd160[20]; char rmdstr[41]; cJSON *retjson; + bitcoin_addr2rmd160(&addrtype,rmd160,address); + init_hexbytes_noT(rmdstr,rmd160,sizeof(rmd160)); + retjson = cJSON_CreateObject(); + jaddstr(retjson,"result",rmdstr); + jaddnum(retjson,"addrtype",addrtype); + jaddstr(retjson,"address",address); + return(jprint(retjson,1)); +} + HASH_AND_INT(SuperNET,priv2pub,privkey,addrtype) { cJSON *retjson; bits256 pub; uint8_t pubkey[33]; char coinaddr[64]; @@ -1221,7 +1234,7 @@ THREE_STRINGS(SuperNET,announce,category,subcategory,message) if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); categoryhash = calc_categoryhashes(&subhash,category,subcategory); - return(SuperNET_categorymulticast(myinfo,0,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext"))); + return(SuperNET_categorymulticast(myinfo,0,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext"),json,remoteaddr)); } THREE_STRINGS(SuperNET,survey,category,subcategory,message) @@ -1230,7 +1243,7 @@ THREE_STRINGS(SuperNET,survey,category,subcategory,message) if ( remoteaddr != 0 ) return(clonestr("{\"error\":\"no remote\"}")); categoryhash = calc_categoryhashes(&subhash,category,subcategory); - return(SuperNET_categorymulticast(myinfo,1,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext"))); + return(SuperNET_categorymulticast(myinfo,1,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext"),json,remoteaddr)); } STRING_ARG(SuperNET,wif2priv,wif) @@ -1299,9 +1312,49 @@ ZERO_ARGS(SuperNET,activehandle) retjson = SuperNET_rosettajson(myinfo->persistent_priv,0); jaddstr(retjson,"result","success"); jaddstr(retjson,"handle",myinfo->handle); + SuperNET_MYINFOadd(myinfo); return(jprint(retjson,1)); } +struct supernet_info *SuperNET_accountfind(cJSON *json) +{ + int32_t num; char *decryptstr; struct supernet_info M,*myinfo; struct iguana_info *coin = 0; + char *password,*permanentfile,*passphrase,*remoteaddr,*perspriv; + myinfo = 0; + if ( (password= jstr(json,"password")) == 0 ) + password = ""; + if ( (permanentfile= jstr(json,"permanentfile")) == 0 ) + permanentfile = ""; + if ( (passphrase= jstr(json,"passphrase")) == 0 ) + passphrase = ""; + remoteaddr = jstr(json,"remoteaddr"); + if ( (passphrase == 0 || passphrase[0] == 0) && (decryptstr= SuperNET_decryptjson(IGUANA_CALLARGS,password,permanentfile)) != 0 ) + { + if ( (json= cJSON_Parse(decryptstr)) != 0 ) + { + memset(&M,0,sizeof(M)); + if ( (perspriv= jstr(json,"persistent_priv")) != 0 && strlen(perspriv) == sizeof(bits256)*2 ) + { + M.persistent_priv = bits256_conv(perspriv); + SuperNET_setkeys(&M,0,0,0); + myinfo = SuperNET_MYINFOfind(&num,M.myaddr.persistent); + printf("found account.(%s) %s %llu\n",myinfo!=0?myinfo->handle:"",M.myaddr.NXTADDR,(long long)M.myaddr.nxt64bits); + return(myinfo); + } + else if ( (passphrase= jstr(json,"result")) != 0 || (passphrase= jstr(json,"passphrase")) != 0 ) + { + SuperNET_setkeys(&M,passphrase,(int32_t)strlen(passphrase),1); + myinfo = SuperNET_MYINFOfind(&num,M.myaddr.persistent); + printf("found account.(%s) %s %llu\n",myinfo!=0?myinfo->handle:"",M.myaddr.NXTADDR,(long long)M.myaddr.nxt64bits); + return(myinfo); + } else printf("no passphrase in (%s)\n",jprint(json,0)); + free_json(json); + } else printf("cant parse.(%s)\n",decryptstr); + free(decryptstr); + } + return(SuperNET_MYINFO(0)); +} + FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase) { char *str,*decryptstr = 0; cJSON *argjson; diff --git a/iguana/SuperNET.h b/iguana/SuperNET.h index 34920028e..c0c1af8e4 100644 --- a/iguana/SuperNET.h +++ b/iguana/SuperNET.h @@ -122,6 +122,15 @@ struct category_msg { struct queueitem DL; struct tai t; uint64_t remoteipbits; struct exchange_quote { uint64_t satoshis,orderid,offerNXT,exchangebits; double price,volume; uint32_t timestamp,val; }; +struct bitcoin_unspent { bits256 txid,privkeys[16]; uint64_t value; int32_t vout; }; +struct bitcoin_spend +{ + char changeaddr[64]; + int32_t numinputs; + int64_t txfee,input_satoshis,satoshis,change,netamount; + struct bitcoin_unspent inputs[]; +}; + void expand_epbits(char *endpoint,struct endpoint epbits); struct endpoint calc_epbits(char *transport,uint32_t ipbits,uint16_t port,int32_t type); @@ -143,7 +152,7 @@ cJSON *SuperNET_argjson(cJSON *json); void *category_info(bits256 categoryhash,bits256 subhash); void *category_infoset(bits256 categoryhash,bits256 subhash,void *info); struct category_info *category_find(bits256 categoryhash,bits256 subhash); -void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *json,char *hexmsg,char *remoteaddr); +void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *retjson,cJSON *json,char *hexmsg,char *remoteaddr); struct category_info *category_processfunc(bits256 categoryhash,char *(*process_func)(struct supernet_info *myinfo,void *data,int32_t datalen,char *remoteaddr)); char *pangea_hexmsg(struct supernet_info *myinfo,void *data,int32_t len,char *remoteaddr); void pangea_queues(struct supernet_info *myinfo); @@ -157,7 +166,7 @@ void *category_subscribe(struct supernet_info *myinfo,bits256 category,bits256 s struct category_msg *category_gethexmsg(struct supernet_info *myinfo,bits256 categoryhash,bits256 subhash); char *SuperNET_htmlstr(char *fname,char *htmlstr,int32_t maxsize,char *agentstr); -char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag,bits256 categoryhash,bits256 subcategory,char *message,int32_t maxdelay,int32_t broadcastflag,int32_t plaintext); +char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag,bits256 categoryhash,bits256 subhash,char *message,int32_t maxdelay,int32_t broadcastflag,int32_t plaintext,cJSON *argjson,char *remoteaddr); bits256 calc_categoryhashes(bits256 *subhashp,char *category,char *subcategory); struct category_chain *category_chain_functions(struct supernet_info *myinfo,bits256 categoryhash,bits256 subhash,int32_t hashlen,int32_t addrlen,void *hash_func,void *stake_func,void *hit_func,void *default_func); #define category_default_latest() (*cchain->default_func)(cchain,'L',0,0,0,0,zero) @@ -172,6 +181,10 @@ char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey,int32_t le uint8_t *cards777_recover(uint8_t *shares[],uint8_t *sharenrs,int32_t M,int32_t numcards,int32_t N); int32_t cards777_calcmofn(uint8_t *allshares,uint8_t *myshares[],uint8_t *sharenrs,int32_t M,bits256 *xoverz,int32_t numcards,int32_t N); int32_t init_sharenrs(unsigned char sharenrs[255],unsigned char *orig,int32_t m,int32_t n); +struct supernet_info *SuperNET_MYINFOfind(int32_t *nump,bits256 pubkey); +void SuperNET_MYINFOadd(struct supernet_info *myinfo); +struct supernet_info *SuperNET_accountfind(cJSON *argjson); +int32_t SuperNET_MYINFOS(struct supernet_info **myinfos,int32_t max); #endif diff --git a/iguana/SuperNET_category.c b/iguana/SuperNET_category.c index 0aaff35e6..734ec250c 100644 --- a/iguana/SuperNET_category.c +++ b/iguana/SuperNET_category.c @@ -311,9 +311,9 @@ int32_t category_broadcastflag(struct supernet_info *myinfo,bits256 category,bit return(broadcastflag); } -char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag,bits256 categoryhash,bits256 subhash,char *message,int32_t maxdelay,int32_t broadcastflag,int32_t plaintext) +char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag,bits256 categoryhash,bits256 subhash,char *message,int32_t maxdelay,int32_t broadcastflag,int32_t plaintext,cJSON *argjson,char *remoteaddr) { - char *hexmsg,*retstr; int32_t len; + char *hexmsg,*retstr; int32_t len; cJSON *retjson = cJSON_CreateObject(); len = (int32_t)strlen(message); //char str[65]; printf("multicast.(%s)\n",bits256_str(str,categoryhash)); if ( is_hexstr(message,len) == 0 ) @@ -325,8 +325,16 @@ char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag broadcastflag = category_broadcastflag(myinfo,categoryhash,subhash,broadcastflag); maxdelay = category_maxdelay(myinfo,categoryhash,subhash,maxdelay); retstr = SuperNET_DHTsend(myinfo,0,categoryhash,subhash,hexmsg,maxdelay,broadcastflag,plaintext); + if ( 0 && argjson != 0 ) + SuperNET_hexmsgprocess(myinfo,retjson,argjson,hexmsg,remoteaddr); if ( hexmsg != message) free(hexmsg); + if ( retjson != 0 ) + { + if ( retstr != 0 ) + jaddstr(retjson,"result",retstr); + retstr = jprint(retjson,1); + } return(retstr); } diff --git a/iguana/SuperNET_hexmsg.c b/iguana/SuperNET_hexmsg.c index 2ce8c3fd6..0b5e5a952 100644 --- a/iguana/SuperNET_hexmsg.c +++ b/iguana/SuperNET_hexmsg.c @@ -73,7 +73,7 @@ void SuperNET_hexmsgadd(struct supernet_info *myinfo,bits256 categoryhash,bits25 //printf("HEXMSG.(%s).%llx -> %s\n",hexmsg,(long long)subhash.txid,str); } -void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *json,char *hexmsg,char *remoteaddr) +void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *retjson,cJSON *json,char *hexmsg,char *remoteaddr) { int32_t len,flag=0; char *str; uint8_t _buf[8192],*buf = _buf; bits256 categoryhash; struct category_info *cat; if ( hexmsg != 0 ) @@ -91,7 +91,11 @@ void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *json,char *hexms if ( cat->processfunc != 0 ) { if ( (str= (*cat->processfunc)(myinfo,buf,len,remoteaddr)) != 0 ) - free(str); + { + if ( retjson != 0 ) + jaddstr(retjson,"processfunc",str); + else free(str); + } flag = 1; //printf("PROCESSFUNC\n"); } diff --git a/iguana/SuperNET_keys.c b/iguana/SuperNET_keys.c index efd6bb6b6..ed624f356 100644 --- a/iguana/SuperNET_keys.c +++ b/iguana/SuperNET_keys.c @@ -190,7 +190,7 @@ cJSON *SuperNET_decryptedjson(char *passphrase,int32_t passsize,bits256 walletha wallet2shared = SuperNET_wallet2shared(wallethash,wallet2priv); wallet2pub = curve25519(wallet2shared,curve25519_basepoint9()); sprintf(fname,"confs/%s",bits256_str(str,wallet2pub)); - printf("fname.(%s) wallet2shared.%s\n",fname,bits256_str(str,wallet2pub)); + //printf("fname.(%s) wallet2shared.%s\n",fname,bits256_str(str,wallet2pub)); if ( (confstr= OS_filestr(&allocsize,fname)) != 0 ) { if ( (filejson= cJSON_Parse(confstr)) != 0 ) diff --git a/iguana/exchanges/bitcoin.c b/iguana/exchanges/bitcoin.c index f9d03d329..8f9ae59a3 100755 --- a/iguana/exchanges/bitcoin.c +++ b/iguana/exchanges/bitcoin.c @@ -183,14 +183,19 @@ int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr return(0); } +void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen) +{ + bits256 hash; + vcalc_sha256(0,hash.bytes,data,datalen); + calc_rmd160(0,rmd160,hash.bytes,sizeof(hash)); +} + char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey,int32_t len) { int32_t i; uint8_t data[25]; bits256 hash; char checkaddr[65]; if ( len != 20 ) - { - vcalc_sha256(0,hash.bytes,pubkey,len); - calc_rmd160(0,data+1,hash.bytes,sizeof(hash)); - } else memcpy(data+1,pubkey,20); + calc_rmd160_sha256(data+1,pubkey,len); + else memcpy(data+1,pubkey,20); btc_convrmd160(checkaddr,addrtype,data+1); //for (i=0; i<20; i++) // printf("%02x",data[i+1]); @@ -399,7 +404,7 @@ int32_t bitcoin_checklocktimeverify(uint8_t *script,int32_t n,uint32_t locktime) int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp) { - uint8_t sha256[32]; int32_t i,plen; + int32_t i,plen; script[n++] = 0x50 + vp->M; for (i=0; iN; i++) { @@ -411,8 +416,7 @@ int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t } script[n++] = 0x50 + vp->N; script[n++] = SCRIPT_OP_CHECKMULTISIG; - vcalc_sha256(0,sha256,script,n); - calc_rmd160(0,p2sh_rmd160,sha256,sizeof(sha256)); + calc_rmd160_sha256(p2sh_rmd160,script,n); return(n); } @@ -484,7 +488,7 @@ int32_t bitcoin_cltvscript(uint8_t p2shtype,char *ps2h_coinaddr,uint8_t p2sh_rmd // OP_ELSE // OP_HASH160 secret160 OP_EQUALVERIFY OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG // standard spend // OP_ENDIF - uint8_t sha256[32],rmd160A[20],rmd160B[20],addrtypeA,addrtypeB; + uint8_t rmd160A[20],rmd160B[20],addrtypeA,addrtypeB; bitcoin_addr2rmd160(&addrtypeA,rmd160A,senderaddr); bitcoin_addr2rmd160(&addrtypeB,rmd160B,otheraddr); script[n++] = SCRIPT_OP_IF; @@ -494,8 +498,7 @@ int32_t bitcoin_cltvscript(uint8_t p2shtype,char *ps2h_coinaddr,uint8_t p2sh_rmd n = bitcoin_revealsecret160(script,n,secret160); n = bitcoin_standardspend(script,n,rmd160B); script[n++] = SCRIPT_OP_ENDIF; - vcalc_sha256(0,sha256,script,n); - calc_rmd160(0,p2sh_rmd160,sha256,sizeof(sha256)); + calc_rmd160_sha256(p2sh_rmd160,script,n); bitcoin_address(ps2h_coinaddr,p2shtype,p2sh_rmd160,20); return(n); } @@ -584,8 +587,9 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp) { if ( zero_rmd160[0] == 0 ) { - vcalc_sha256(0,sha256,vp->spendscript,vp->spendlen); // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - calc_rmd160(0,zero_rmd160,sha256,sizeof(sha256)); // b472a266d0bd89c13706a4132ccfb16f7c3b9fcb + calc_rmd160_sha256(zero_rmd160,vp->spendscript,vp->spendlen); + //vcalc_sha256(0,sha256,vp->spendscript,vp->spendlen); // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + //calc_rmd160(0,zero_rmd160,sha256,sizeof(sha256)); // b472a266d0bd89c13706a4132ccfb16f7c3b9fcb init_hexbytes_noT(hexstr,zero_rmd160,20); char str[65]; printf("iguana_calcrmd160 zero len %s -> %s\n",bits256_str(str,*(bits256 *)sha256),hexstr); } @@ -613,8 +617,7 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp) else if ( vp->spendscript[0] > 0 && vp->spendscript[0] < 76 && vp->spendscript[vp->spendlen-1] == SCRIPT_OP_CHECKSIG && vp->spendscript[0] == vp->spendlen-2 ) { memcpy(vp->signers[0].pubkey,&vp->spendscript[1],vp->spendscript[0]); - vcalc_sha256(0,sha256,vp->signers[0].pubkey,vp->spendscript[0]); - calc_rmd160(0,vp->rmd160,sha256,sizeof(sha256)); + calc_rmd160_sha256(vp->rmd160,vp->signers[0].pubkey,vp->spendscript[0]); return(IGUANA_SCRIPT_76AC); } else if ( vp->spendscript[0] == SCRIPT_OP_HASH160 && vp->spendscript[1] == 0x14 && vp->spendlen == 23 && vp->spendscript[22] == SCRIPT_OP_EQUAL ) @@ -635,8 +638,7 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp) return(-1); } memcpy(vp->signers[i].pubkey,script,plen); - vcalc_sha256(0,sha256,vp->signers[i].pubkey,plen); - calc_rmd160(0,vp->signers[i].rmd160,sha256,sizeof(sha256)); + calc_rmd160_sha256(vp->signers[i].rmd160,vp->signers[i].pubkey,plen); bitcoin_address(vp->signers[i].coinaddr,coin->chain->pubtype,vp->signers[i].pubkey,plen); } if ( (int32_t)((long)script - (long)vp->spendscript) == vp->spendlen-2 ) @@ -645,8 +647,7 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp) vp->M = m; //printf("M.%d N.%d\n",m,n); } - vcalc_sha256(0,sha256,vp->spendscript,vp->spendlen); - calc_rmd160(0,vp->rmd160,sha256,sizeof(sha256)); + calc_rmd160_sha256(vp->rmd160,vp->spendscript,vp->spendlen); if ( n == 3 ) { if ( m == 3 ) @@ -685,8 +686,7 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp) fprintf(fp,"%s\n",hexstr), fflush(fp); } else sprintf(hexstr,"pkscript overflowed %ld\n",(long)sizeof(hexstr)); } - vcalc_sha256(0,sha256,vp->spendscript,vp->spendlen); - calc_rmd160(0,vp->rmd160,sha256,sizeof(sha256)); + calc_rmd160_sha256(vp->rmd160,vp->spendscript,vp->spendlen); return(type); } @@ -1040,21 +1040,9 @@ char *iguana_rawtxbytes(struct iguana_info *coin,cJSON *json,struct iguana_msgtx return(txbytes); } -/* - struct vin_signer { bits256 privkey; uint8_t siglen,sig[80],rmd160[20],pubkey[66]; }; - - struct vin_info - { - struct iguana_msgvin vin; - int32_t M,N,validmask,spendlen,p2shflag; - struct vin_signer signers[16]; - uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE]; - }; - */ - int32_t bitcoin_scriptget(struct iguana_info *coin,int32_t *hashtypep,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t type) { - char asmstr[IGUANA_MAXSCRIPTSIZE*3]; int32_t j,n,siglen,plen; uint8_t sha256[32]; + char asmstr[IGUANA_MAXSCRIPTSIZE*3]; int32_t j,n,siglen,plen; j = n = 0; *hashtypep = SIGHASH_ALL; while ( (siglen= scriptsig[n]) >= 70 && siglen <= 73 && n+siglen+1 < len && j < 16 ) @@ -1073,8 +1061,7 @@ int32_t bitcoin_scriptget(struct iguana_info *coin,int32_t *hashtypep,struct vin while ( ((plen= scriptsig[n]) == 33 || plen == 65 ) && j < 16 ) { memcpy(vp->signers[j].pubkey,&scriptsig[n+1],plen); - vcalc_sha256(0,sha256,vp->signers[j].pubkey,plen); - calc_rmd160(0,vp->signers[j].rmd160,sha256,sizeof(sha256)); + calc_rmd160_sha256(vp->signers[j].rmd160,vp->signers[j].pubkey,plen); if ( j == 0 ) memcpy(vp->rmd160,vp->signers[j].rmd160,20); n += (plen + 1); @@ -1248,6 +1235,30 @@ char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson) return(txbytes); } +cJSON *bitcoin_hex2json(struct iguana_info *coin,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes) +{ + int32_t n,len; char vpnstr[64]; struct iguana_msgtx M; uint8_t *serialized; cJSON *txobj; + txobj = cJSON_CreateObject(); + if ( msgtx == 0 ) + { + msgtx = &M; + memset(msgtx,0,sizeof(M)); + } + len = (int32_t)strlen(txbytes) >> 1; + serialized = malloc(len); + decode_hex(serialized,len,txbytes); + vpnstr[0] = 0; + memset(txidp,0,sizeof(*txidp)); + //char str[65]; printf("%d of %d: %s\n",i,msg.txn_count,bits256_str(str,tx.txid)); + if ( (n= iguana_rwmsgtx(coin,0,txobj,serialized,len,msgtx,txidp,vpnstr)) <= 0 ) + { + free_json(txobj); + txobj = 0; + } + free(serialized); + return(txobj); +} + cJSON *bitcoin_createtx(struct iguana_info *coin,int32_t locktime) { cJSON *json = cJSON_CreateObject(); @@ -1447,9 +1458,10 @@ static char *BASERELS[][2] = { {"btcd","btc"}, {"nxt","btc"}, {"asset","btc"} }; double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert) { cJSON *retjson,*bids,*asks; double hbla; + struct supernet_info *myinfo = SuperNET_accountfind(argjson); bids = cJSON_CreateArray(); asks = cJSON_CreateArray(); - instantdex_acceptablefind(exchange,bids,asks,0,base,rel); + instantdex_acceptablefind(myinfo,exchange,bids,asks,0,base,rel); retjson = cJSON_CreateObject(); cJSON_AddItemToObject(retjson,"bids",bids); cJSON_AddItemToObject(retjson,"asks",asks); @@ -1460,11 +1472,13 @@ double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchang char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson) { + //struct supernet_info *myinfo = SuperNET_accountfind(argjson); return(clonestr("{\"error\":\"bitcoin is not yet\"}")); } cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson) { + //struct supernet_info *myinfo = SuperNET_accountfind(argjson); return(cJSON_Parse("{\"error\":\"bitcoin is not yet\"}")); } @@ -1481,9 +1495,11 @@ 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) { - struct instantdex_accept *ap; char *str,coinaddr[64]; uint64_t txid = 0; cJSON *json; + char *str,coinaddr[64]; uint64_t txid = 0; cJSON *tmp,*json=0; struct supernet_info *myinfo; uint8_t pubkey[33]; struct iguana_info *other; int32_t hops = 3; - myinfo = SuperNET_MYINFO(0); + myinfo = SuperNET_accountfind(argjson); + if ( retstrp != 0 ) + *retstrp = 0; if ( strcmp(base,"BTC") == 0 || strcmp(base,"btc") == 0 ) { base = rel; @@ -1494,54 +1510,49 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha } if ( is_valid_BTCother(base) != 0 && (strcmp(rel,"BTC") == 0 || strcmp(rel,"btc") == 0) ) { - ap = 0;//instantdex_acceptable(exchange,base,rel,"BTC",dir,price,volume); if ( dotrade == 0 ) { if ( retstrp != 0 ) - { - if ( ap != 0 ) - *retstrp = jprint(instantdex_acceptjson(ap),1); - else *retstrp = clonestr("{\"result\":\"would issue new trade\"}"); - } + *retstrp = clonestr("{\"result\":\"would issue new trade\"}"); } else { - if ( ap != 0 ) + if ( (other= iguana_coinfind(base)) != 0 ) { - // issue matching response + bitcoin_pubkey33(pubkey,myinfo->persistent_priv); + bitcoin_address(coinaddr,other->chain->pubtype,pubkey,sizeof(pubkey)); + jaddstr(argjson,base,coinaddr); } - else if ( dir < 0 ) + else if ( strcmp(base,"NXT") == 0 || (is_decimalstr(base) > 0 && strlen(base) > 13) ) { - printf("bitcoin sell is not yet\n"); + printf("NXT is not yet\n"); return(0); } - else + else return(0); + json = cJSON_CreateObject(); + jaddstr(json,"base",base); + jaddstr(json,"rel","BTC"); + jaddnum(json,dir > 0 ? "maxprice" : "minprice",price); + jaddnum(json,"volume",volume); + jaddstr(json,"BTC",myinfo->myaddr.BTC); + //printf("trade dir.%d (%s/%s) %.6f vol %.8f\n",dir,base,"BTC",price,volume); + if ( (str= instantdex_sendcmd(myinfo,json,"BTCoffer",myinfo->ipaddr,hops)) != 0 ) { json = cJSON_CreateObject(); - jaddstr(json,"base",base); - jaddstr(json,"rel","BTC"); - jaddnum(json,"maxprice",price); - jaddnum(json,"volume",volume); - if ( (other= iguana_coinfind(base)) != 0 ) - { - bitcoin_pubkey33(pubkey,myinfo->persistent_priv); - bitcoin_address(coinaddr,other->chain->pubtype,pubkey,sizeof(pubkey)); - jaddstr(argjson,base,coinaddr); - } - jaddstr(json,"BTC",myinfo->myaddr.BTC); - if ( (str= instantdex_sendcmd(myinfo,json,"BTCoffer",myinfo->ipaddr,hops)) != 0 ) - free(str); - free_json(json); - if ( (str= instantdex_queueaccept(exchange,base,"BTC",price,volume,-1,"BTC",INSTANTDEX_OFFERDURATION)) != 0 ) + jaddstr(json,"BTCoffer",str); + } + if ( (str= instantdex_queueaccept(myinfo,exchange,base,"BTC",price,volume,-dir,dir > 0 ? "BTC" : base,INSTANTDEX_OFFERDURATION)) != 0 ) + { + jaddstr(json,"queue",str); + if ( (tmp= cJSON_Parse(str)) != 0 ) { - if ( (json= cJSON_Parse(str)) != 0 ) - { - txid = j64bits(json,"orderid"); - free_json(json); - } - free(str); + txid = j64bits(json,"orderid"); + free_json(tmp); } } + if ( retstrp != 0 ) + *retstrp = jprint(json,1); + else free_json(json); } } return(txid); @@ -1550,7 +1561,8 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha char *ORDERSTATUS(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson) { struct instantdex_accept *ap; cJSON *retjson; - if ( (ap= instantdex_acceptablefind(exchange,0,0,orderid,"*","*")) != 0 ) + struct supernet_info *myinfo = SuperNET_accountfind(argjson); + if ( (ap= instantdex_acceptablefind(myinfo,exchange,0,0,orderid,"*","*")) != 0 ) { retjson = cJSON_CreateObject(); jadd(retjson,"result",instantdex_acceptjson(ap)); @@ -1561,7 +1573,8 @@ char *ORDERSTATUS(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson char *CANCELORDER(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson) { struct instantdex_accept *ap; cJSON *retjson; - if ( (ap= instantdex_acceptablefind(exchange,0,0,orderid,"*","*")) != 0 ) + struct supernet_info *myinfo = SuperNET_accountfind(argjson); + if ( (ap= instantdex_acceptablefind(myinfo,exchange,0,0,orderid,"*","*")) != 0 ) { ap->dead = (uint32_t)time(NULL); retjson = cJSON_CreateObject(); @@ -1574,9 +1587,10 @@ char *CANCELORDER(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson) { cJSON *retjson,*bids,*asks; + struct supernet_info *myinfo = SuperNET_accountfind(argjson); bids = cJSON_CreateArray(); asks = cJSON_CreateArray(); - instantdex_acceptablefind(exchange,bids,asks,0,"*","*"); + instantdex_acceptablefind(myinfo,exchange,bids,asks,0,"*","*"); retjson = cJSON_CreateObject(); jaddstr(retjson,"result","success"); jadd(retjson,"bids",bids); @@ -1586,11 +1600,13 @@ char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson) char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson) { + //struct supernet_info *myinfo = SuperNET_accountfind(argjson); return(clonestr("{\"error\":\"bitcoin is not yet\"}")); } char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson) { + //struct supernet_info *myinfo = SuperNET_accountfind(argjson); return(clonestr("{\"error\":\"bitcoin is not yet\"}")); } diff --git a/iguana/exchanges/bitcoin.h b/iguana/exchanges/bitcoin.h index 7d46eb4f7..38499e005 100755 --- a/iguana/exchanges/bitcoin.h +++ b/iguana/exchanges/bitcoin.h @@ -50,12 +50,6 @@ int32_t bitcoin_cltvscript(uint8_t p2shtype,char *ps2h_coinaddr,uint8_t p2sh_rmd int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr); char *bitcoin_cltvtx(struct iguana_info *coin,char *changeaddr,char *senderaddr,char *senders_otheraddr,char *otheraddr,uint32_t locktime,uint64_t satoshis,bits256 txid,int32_t vout,uint64_t inputsatoshis,bits256 privkey); int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp); -cJSON *bitcoin_createtx(struct iguana_info *coin,int32_t locktime); -cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis); -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); -cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequence); -int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V); -char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson); int32_t bitcoin_pubkeyspend(uint8_t *script,int32_t n,uint8_t pubkey[66]); int32_t bitcoin_p2shspend(uint8_t *script,int32_t n,uint8_t rmd160[20]); diff --git a/iguana/exchanges777.h b/iguana/exchanges777.h index 60c320bbd..d6b8b6cf9 100755 --- a/iguana/exchanges777.h +++ b/iguana/exchanges777.h @@ -20,6 +20,7 @@ #include #include #define INSTANTDEX_OFFERDURATION 300 +#define INSTANTDEX_LOCKTIME 3600 #define EXCHANGES777_MINPOLLGAP 3 #define EXCHANGES777_MAXDEPTH 200 @@ -89,21 +90,12 @@ struct exchange_request struct exchange_quote bidasks[]; }; -struct bitcoin_unspent { bits256 txid,privkey; uint64_t value; int32_t vout; }; -struct bitcoin_spend -{ - char changeaddr[64]; - int32_t numinputs; - int64_t txfee,input_satoshis,satoshis,change,netamount; - struct bitcoin_unspent inputs[]; -}; - struct instantdex_entry { char base[24],rel[24]; uint64_t price64,basevolume64,offer64; uint32_t expiration,nonce; char myside,acceptdir; }; -struct instantdex_accept { struct queueitem DL; cJSON *statusjson; uint64_t pendingvolume64,orderid; uint32_t dead; struct instantdex_entry A; }; +struct instantdex_accept { struct queueitem DL; void *info; uint64_t pendingvolume64,orderid; uint32_t dead; struct instantdex_entry A; }; -struct instantdex_accept *instantdex_acceptablefind(struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel); +struct instantdex_accept *instantdex_acceptablefind(struct supernet_info *myinfo,struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel); cJSON *instantdex_acceptjson(struct instantdex_accept *ap); -struct instantdex_accept *instantdex_acceptable(struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits); +struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits); void *curl_post(void **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3); char *instantdex_sendcmd(struct supernet_info *myinfo,cJSON *argjson,char *cmdstr,char *ipaddr,int32_t hops); @@ -121,6 +113,7 @@ double truefx_price(struct exchange_info *exchange,char *base,char *rel,struct e double fxcm_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert); double instaforex_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert); -char *instantdex_queueaccept(struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *myside,int32_t duration); +char *instantdex_queueaccept(struct supernet_info *myinfo,struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *mysidestr,int32_t duration); +void instantdex_update(struct supernet_info *myinfo); #endif diff --git a/iguana/iguana777.c b/iguana/iguana777.c index a06b1f67e..c8c1341f4 100755 --- a/iguana/iguana777.c +++ b/iguana/iguana777.c @@ -421,7 +421,7 @@ void iguana_coinloop(void *arg) } } if ( flag == 0 ) - usleep(coin->polltimeout * 1000); + usleep(coin->polltimeout * 10000); } } diff --git a/iguana/iguana777.h b/iguana/iguana777.h index fbce35bf0..b197494ae 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -743,6 +743,18 @@ cJSON *iguana_blockjson(struct iguana_info *coin,struct iguana_block *block,int3 //int32_t iguana_sig(uint8_t *sig,int32_t maxsize,uint8_t *data,int32_t datalen,bits256 privkey); //int32_t iguana_ver(uint8_t *sig,int32_t siglen,uint8_t *data,int32_t datalen,bits256 pubkey); //int32_t iguana_ver(uint8_t *sig,int32_t siglen,uint8_t *data,int32_t datalen,uint8_t *pubkey); +void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen); +int32_t bitcoin_checklocktimeverify(uint8_t *script,int32_t n,uint32_t locktime); +struct bitcoin_spend *iguana_spendset(struct supernet_info *myinfo,struct iguana_info *coin,int64_t satoshis,int64_t insurance); +cJSON *bitcoin_hex2json(struct iguana_info *coin,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes); +cJSON *iguana_signtx(struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj); +cJSON *bitcoin_createtx(struct iguana_info *coin,int32_t locktime); +cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis); +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); +cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequence); +int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V); +char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson); +int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr); extern queue_t bundlesQ; diff --git a/iguana/iguana_blocks.c b/iguana/iguana_blocks.c index 13f1390e8..30feeb0cd 100755 --- a/iguana/iguana_blocks.c +++ b/iguana/iguana_blocks.c @@ -347,9 +347,9 @@ struct iguana_block *_iguana_chainlink(struct iguana_info *coin,struct iguana_bl } if ( coin->started != 0 && (block->height % coin->chain->bundlesize) == 10 ) { - printf("savehdrs\n"); + //printf("savehdrs\n"); iguana_savehdrs(coin); - printf("done savehdrs\n"); + //printf("done savehdrs\n"); } } } diff --git a/iguana/iguana_exchanges.c b/iguana/iguana_exchanges.c index 3e8c65735..da9284c91 100755 --- a/iguana/iguana_exchanges.c +++ b/iguana/iguana_exchanges.c @@ -58,8 +58,8 @@ cJSON *exchanges777_quotejson(struct exchange_quote *quote,int32_t allflag,doubl jaddstr(json,"time",utc_str(str,quote->timestamp)); if ( quote->orderid > 0 ) jadd64bits(json,"orderid",quote->orderid); - if ( quote->offerNXT > 0 ) - jadd64bits(json,"offerNXT",quote->offerNXT); + //if ( quote->offerNXT != 0 ) + jadd64bits(json,"offerer",quote->offerNXT); return(json); } else return(cJSON_CreateNumber(quote->price)); } @@ -245,6 +245,7 @@ void exchanges777_json_quotes(struct exchange_info *exchange,double commission,c volume = jdouble(item,"volume"); timestamp = juint(item,"timestamp"); orderid = j64bits(item,"orderid"); + offerNXT = j64bits(item,"offerer"); } if ( price == 0. || volume == 0. ) continue; @@ -533,11 +534,13 @@ char *exchanges777_process(struct exchange_info *exchange,int32_t *retvalp,struc orderid = (*exchange->issue.trade)(req->dotrade,&retstr,exchange,base,rel,polarity * req->dir,price,volume,req->argjson); if ( retstr == 0 ) { - retjson = cJSON_CreateObject(); + req->orderid = orderid; + retstr = (*exchange->issue.orderstatus)(exchange,req->orderid,req->argjson); + /*retjson = cJSON_CreateObject(); if ( orderid != 0 ) jadd64bits(retjson,"result",orderid); else jaddstr(retjson,"error","no return value from trade call"); - retstr = jprint(retjson,1); + retstr = jprint(retjson,1);*/ } } break; @@ -907,7 +910,7 @@ struct exchange_info *exchange_create(char *exchangestr,cJSON *argjson) struct exchange_info *exchanges777_info(char *exchangestr,int32_t sleepflag,cJSON *json,char *remoteaddr) { struct exchange_info *exchange; - if ( remoteaddr != 0 ) + if ( remoteaddr != 0 || exchangestr == 0 ) return(0); if ( (exchange= exchanges777_find(exchangestr)) == 0 ) { @@ -956,116 +959,153 @@ void exchanges777_init(struct supernet_info *myinfo,cJSON *exchanges,int32_t sle THREE_STRINGS_AND_THREE_INTS(InstantDEX,orderbook,exchange,base,rel,depth,allfields,ignore) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) - return(exchanges777_Qprices(ptr,base,rel,juint(json,"maxseconds"),allfields,depth,json,0,ptr->commission)); - else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( remoteaddr == 0 ) + { + instantdex_update(myinfo); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + return(exchanges777_Qprices(ptr,base,rel,juint(json,"maxseconds"),allfields,depth,json,0,ptr->commission)); + else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,buy,exchange,base,rel,price,volume,dotrade) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) - return(exchanges777_Qtrade(ptr,base,rel,juint(json,"maxseconds"),dotrade,1,price,volume,json)); - else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( remoteaddr == 0 ) + { + instantdex_update(myinfo); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + return(exchanges777_Qtrade(ptr,base,rel,juint(json,"maxseconds"),dotrade,1,price,volume,json)); + else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,sell,exchange,base,rel,price,volume,dotrade) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) - return(exchanges777_Qtrade(ptr,base,rel,juint(json,"maxseconds"),dotrade,-1,price,volume,json)); - else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( remoteaddr == 0 ) + { + instantdex_update(myinfo); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + return(exchanges777_Qtrade(ptr,base,rel,juint(json,"maxseconds"),dotrade,-1,price,volume,json)); + else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } THREE_STRINGS_AND_DOUBLE(InstantDEX,withdraw,exchange,base,destaddr,amount) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) - return(exchanges777_Qrequest(ptr,'W',base,0,juint(json,"maxseconds"),0,destaddr,amount,json)); - else return(clonestr("{\"error\":\"cant find or create exchange\"}")); -} - -THREE_STRINGS(InstantDEX,supports,exchange,base,rel) -{ - struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) - return(exchanges777_Qrequest(ptr,'S',base,rel,juint(json,"maxseconds"),0,0,0,json)); - else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( remoteaddr == 0 ) + { + instantdex_update(myinfo); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + return(exchanges777_Qrequest(ptr,'W',base,0,juint(json,"maxseconds"),0,destaddr,amount,json)); + else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } TWO_STRINGS(InstantDEX,balance,exchange,base) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) - return(exchanges777_Qrequest(ptr,'B',base,0,juint(json,"maxseconds"),0,0,0,json)); - else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( remoteaddr == 0 ) + { + instantdex_update(myinfo); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + return(exchanges777_Qrequest(ptr,'B',base,0,juint(json,"maxseconds"),0,0,0,json)); + else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } TWO_STRINGS(InstantDEX,orderstatus,exchange,orderid) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) - return(exchanges777_Qrequest(ptr,'P',0,0,juint(json,"maxseconds"),calc_nxt64bits(orderid),0,0,json)); - else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( remoteaddr == 0 ) + { + instantdex_update(myinfo); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + return(exchanges777_Qrequest(ptr,'P',0,0,juint(json,"maxseconds"),calc_nxt64bits(orderid),0,0,json)); + else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } TWO_STRINGS(InstantDEX,cancelorder,exchange,orderid) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) - return(exchanges777_Qrequest(ptr,'C',0,0,juint(json,"maxseconds"),calc_nxt64bits(orderid),0,0,json)); - else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( remoteaddr == 0 ) + { + instantdex_update(myinfo); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + return(exchanges777_Qrequest(ptr,'C',0,0,juint(json,"maxseconds"),calc_nxt64bits(orderid),0,0,json)); + else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } STRING_ARG(InstantDEX,openorders,exchange) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) - return(exchanges777_Qrequest(ptr,'O',0,0,juint(json,"maxseconds"),0,0,0,json)); - else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( remoteaddr == 0 ) + { + instantdex_update(myinfo); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + return(exchanges777_Qrequest(ptr,'O',0,0,juint(json,"maxseconds"),0,0,0,json)); + else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } STRING_ARG(InstantDEX,tradehistory,exchange) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) - return(exchanges777_Qrequest(ptr,'H',0,0,juint(json,"maxseconds"),0,0,0,json)); - else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( remoteaddr == 0 ) + { + instantdex_update(myinfo); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + return(exchanges777_Qrequest(ptr,'H',0,0,juint(json,"maxseconds"),0,0,0,json)); + else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } THREE_STRINGS(InstantDEX,apikeypair,exchange,apikey,apisecret) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + if ( remoteaddr == 0 ) { - if ( apikey != 0 && apikey[0] != 0 && apisecret != 0 && apisecret[0] != 0 ) + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) { - safecopy(ptr->apikey,apikey,sizeof(ptr->apikey)); - safecopy(ptr->apisecret,apisecret,sizeof(ptr->apisecret)); - return(clonestr("{\"result\":\"set apikey and apisecret\"}")); - } else return(clonestr("{\"error\":\"need both userid and password\"}")); - } else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( apikey != 0 && apikey[0] != 0 && apisecret != 0 && apisecret[0] != 0 ) + { + safecopy(ptr->apikey,apikey,sizeof(ptr->apikey)); + safecopy(ptr->apisecret,apisecret,sizeof(ptr->apisecret)); + return(clonestr("{\"result\":\"set apikey and apisecret\"}")); + } else return(clonestr("{\"error\":\"need both userid and password\"}")); + } else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } THREE_STRINGS(InstantDEX,setuserid,exchange,userid,tradepassword) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + if ( remoteaddr == 0 ) { - safecopy(ptr->userid,userid,sizeof(ptr->userid)); - safecopy(ptr->tradepassword,tradepassword,sizeof(ptr->tradepassword)); - return(clonestr("{\"result\":\"set userid and/or tradepassword\"}")); - } else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + { + safecopy(ptr->userid,userid,sizeof(ptr->userid)); + safecopy(ptr->tradepassword,tradepassword,sizeof(ptr->tradepassword)); + return(clonestr("{\"result\":\"set userid and/or tradepassword\"}")); + } else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } STRING_AND_INT(InstantDEX,pollgap,exchange,pollgap) { struct exchange_info *ptr; - if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + if ( remoteaddr == 0 ) { - ptr->pollgap = pollgap; - return(clonestr("{\"result\":\"set pollgap\"}")); - } else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + { + ptr->pollgap = pollgap; + return(clonestr("{\"result\":\"set pollgap\"}")); + } else return(clonestr("{\"error\":\"cant find or create exchange\"}")); + } else return(clonestr("{\"error\":\"no remote for this API\"}")); } ZERO_ARGS(InstantDEX,allexchanges) @@ -1078,6 +1118,14 @@ ZERO_ARGS(InstantDEX,allexchanges) return(jprint(retjson,1)); } +THREE_STRINGS(InstantDEX,supports,exchange,base,rel) +{ + struct exchange_info *ptr; + if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 ) + return(exchanges777_Qrequest(ptr,'S',base,rel,juint(json,"maxseconds"),0,0,0,json)); + else return(clonestr("{\"error\":\"cant find or create exchange\"}")); +} + STRING_ARG(InstantDEX,allpairs,exchange) { struct exchange_info *ptr; diff --git a/iguana/iguana_instantdex.c b/iguana/iguana_instantdex.c index 0a0b31359..3752e05ea 100755 --- a/iguana/iguana_instantdex.c +++ b/iguana/iguana_instantdex.c @@ -82,37 +82,43 @@ struct instantdex_msghdr *instantdex_msgcreate(struct supernet_info *myinfo,stru char *instantdex_sendcmd(struct supernet_info *myinfo,cJSON *argjson,char *cmdstr,char *ipaddr,int32_t hops) { - char *reqstr,hexstr[8192]; uint8_t _msg[4096]; uint64_t nxt64bits; int32_t i,datalen; + char *reqstr,*hexstr,*retstr; uint64_t nxt64bits; int32_t i,datalen; bits256 instantdexhash; struct instantdex_msghdr *msg; - msg = (struct instantdex_msghdr *)_msg; - memset(msg,0,sizeof(*msg)); instantdexhash = calc_categoryhashes(0,"InstantDEX",0); category_subscribe(myinfo,instantdexhash,GENESIS_PUBKEY); //if ( ipaddr == 0 || ipaddr[0] == 0 || strncmp(ipaddr,"127.0.0.1",strlen("127.0.0.1")) == 0 ) // return(clonestr("{\"error\":\"no ipaddr, need to send your ipaddr for now\"}")); jaddstr(argjson,"cmd",cmdstr); - for (i=0; icmd); i++) - if ( (msg->cmd[i]= cmdstr[i]) == 0 ) - break; jaddstr(argjson,"agent","SuperNET"); jaddstr(argjson,"method","DHT"); - jaddstr(argjson,"traderip",ipaddr); + jaddstr(argjson,"handle",myinfo->handle); jaddbits256(argjson,"categoryhash",instantdexhash); jaddbits256(argjson,"traderpub",myinfo->myaddr.persistent); nxt64bits = acct777_nxt64bits(myinfo->myaddr.persistent); - reqstr = jprint(argjson,1); + reqstr = jprint(argjson,0); datalen = (int32_t)(strlen(reqstr) + 1); + msg = calloc(1,sizeof(*msg) + datalen); + for (i=0; icmd); i++) + if ( (msg->cmd[i]= cmdstr[i]) == 0 ) + break; memcpy(msg->serialized,reqstr,datalen); free(reqstr); - if ( (datalen+sizeof(*msg))*2+1 < sizeof(hexstr) && instantdex_msgcreate(myinfo,msg,datalen) != 0 ) + if ( instantdex_msgcreate(myinfo,msg,datalen) != 0 ) { - printf("instantdex send.(%s)\n",cmdstr); + //printf("instantdex send.(%s)\n",jprint(argjson,0)); + hexstr = malloc(msg->sig.allocsize*2 + 1); init_hexbytes_noT(hexstr,(uint8_t *)msg,msg->sig.allocsize); - return(SuperNET_categorymulticast(myinfo,0,instantdexhash,GENESIS_PUBKEY,hexstr,0,hops,1)); + retstr = SuperNET_categorymulticast(myinfo,0,instantdexhash,GENESIS_PUBKEY,hexstr,0,hops,1,argjson,0); + free_json(argjson); + free(hexstr); + free(msg); + return(retstr); } else { - printf("cant msgcreate\n"); + free_json(argjson); + free(msg); + printf("cant msgcreate datalen.%d\n",datalen); return(clonestr("{\"error\":\"couldnt create instantdex message\"}")); } } @@ -242,7 +248,7 @@ cJSON *instantdex_acceptjson(struct instantdex_accept *ap) return(item); } -struct instantdex_accept *instantdex_acceptablefind(struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel) +struct instantdex_accept *instantdex_acceptablefind(struct supernet_info *myinfo,struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel) { struct instantdex_accept PAD,*ap,*retap = 0; uint32_t now; cJSON *item; char *type; now = (uint32_t)time(NULL); @@ -252,13 +258,15 @@ struct instantdex_accept *instantdex_acceptablefind(struct exchange_info *exchan { if ( now < ap->A.expiration && ap->dead == 0 ) { + printf("find cmps %d %d %d %d %d %d\n",strcmp(base,"*") == 0,strcmp(base,ap->A.base) == 0,strcmp(rel,"*") == 0,strcmp(rel,ap->A.rel) == 0,orderid == 0,orderid == ap->orderid); if ( (strcmp(base,"*") == 0 || strcmp(base,ap->A.base) == 0) && (strcmp(rel,"*") == 0 || strcmp(rel,ap->A.rel) == 0) && (orderid == 0 || orderid == ap->orderid) ) { + printf("found match\n"); retap = ap; } if ( (item= instantdex_acceptjson(ap)) != 0 ) { - //printf("item.(%s)\n",jprint(item,0)); + printf("item.(%s)\n",jprint(item,0)); if ( (type= jstr(item,"type")) != 0 ) { if ( strcmp(type,"bid") == 0 && bids != 0 ) @@ -273,7 +281,7 @@ struct instantdex_accept *instantdex_acceptablefind(struct exchange_info *exchan return(retap); } -struct instantdex_accept *instantdex_acceptable(struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits) +struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits) { struct instantdex_accept PAD,*ap,*retap = 0; uint64_t bestprice64 = 0; uint32_t now; int32_t offerdir; @@ -283,12 +291,15 @@ struct instantdex_accept *instantdex_acceptable(struct exchange_info *exchange,s offerdir = instantdex_bidaskdir(A); while ( (ap= queue_dequeue(&exchange->acceptableQ,0)) != 0 && ap != &PAD ) { - if ( now < ap->A.expiration && ap->dead == 0 ) + if ( now < ap->A.expiration && ap->dead == 0 && (offerbits == 0 || offerbits != ap->A.offer64) ) { - if ( (offerbits == 0 || offerbits != A->A.offer64) && A->A.basevolume64 > 0. && (strcmp(A->A.base,"*") == 0 || strcmp(A->A.base,ap->A.base) == 0) && (strcmp(A->A.rel,"*") == 0 || strcmp(A->A.rel,ap->A.rel) == 0) && A->A.basevolume64 <= (ap->A.basevolume64 - ap->pendingvolume64) && offerdir*instantdex_bidaskdir(ap) < 0 ) + printf("check offerbits.%llu vs %llu: %d %d %d %d %d %d %d %d\n",(long long)offerbits,(long long)ap->A.offer64,A->A.basevolume64 > 0.,strcmp(A->A.base,"*") == 0 ,strcmp(A->A.base,ap->A.base) == 0, strcmp(A->A.rel,"*") == 0 ,strcmp(A->A.rel,ap->A.rel) == 0,A->A.basevolume64 <= (ap->A.basevolume64 - ap->pendingvolume64),offerdir,instantdex_bidaskdir(ap)); + if ( A->A.basevolume64 > 0. && (strcmp(A->A.base,"*") == 0 || strcmp(A->A.base,ap->A.base) == 0) && (strcmp(A->A.rel,"*") == 0 || strcmp(A->A.rel,ap->A.rel) == 0) && A->A.basevolume64 <= (ap->A.basevolume64 - ap->pendingvolume64) && offerdir*instantdex_bidaskdir(ap) < 0 ) { - if ( offerdir == 0 || A->A.price64 == 0 || ((offerdir > 0 && ap->A.price64 > A->A.price64) || (offerdir < 0 && ap->A.price64 < A->A.price64)) ) + printf("passed first cmp: %d %d %d %d\n",offerdir == 0,A->A.price64 == 0,(offerdir > 0 && ap->A.price64 >= A->A.price64),(offerdir < 0 && ap->A.price64 <= A->A.price64)); + if ( offerdir == 0 || A->A.price64 == 0 || ((offerdir > 0 && ap->A.price64 >= A->A.price64) || (offerdir < 0 && ap->A.price64 <= A->A.price64)) ) { + printf("passed second cmp: offerdir.%d best %.8f ap %.8f\n",offerdir,dstr(bestprice64),dstr(ap->A.price64)); if ( bestprice64 == 0 || (offerdir < 0 && ap->A.price64 < bestprice64) || (offerdir > 0 && ap->A.price64 > bestprice64) ) { printf("found better price %f vs %f\n",dstr(ap->A.price64),dstr(bestprice64)); @@ -315,42 +326,16 @@ struct instantdex_accept *instantdex_acceptable(struct exchange_info *exchange,s // NXT node verifies bitcoin txbytes has proper payment and cashes in with onetimepubkey // BTC* node approves phased tx with onetimepubkey -int32_t instantdex_acceptextract(struct instantdex_accept *ap,cJSON *argjson) -{ - char *base,*rel; bits256 hash; - memset(ap,0,sizeof(*ap)); - if ( (base= jstr(argjson,"b")) != 0 ) - safecopy(ap->A.base,base,sizeof(ap->A.base)); - if ( (rel= jstr(argjson,"r")) != 0 ) - safecopy(ap->A.rel,rel,sizeof(ap->A.rel)); - ap->A.nonce = juint(argjson,"n"); - ap->A.expiration = juint(argjson,"e"); - ap->A.myside = juint(argjson,"s"); - ap->A.acceptdir = jint(argjson,"d"); - ap->A.offer64 = j64bits(argjson,"o"); - ap->A.price64 = j64bits(argjson,"p"); - ap->A.basevolume64 = j64bits(argjson,"v"); - vcalc_sha256(0,hash.bytes,(void *)&ap->A,sizeof(ap->A)); - ap->orderid = j64bits(argjson,"i"); - if ( hash.txid != ap->orderid ) - { - int32_t i; - for (i=0; iorderid); - return(-1); - } - return(0); -} - bits256 instantdex_acceptset(struct instantdex_accept *ap,char *base,char *rel,int32_t duration,int32_t myside,int32_t acceptdir,double price,double volume,uint64_t offerbits) { bits256 hash; memset(ap,0,sizeof(*ap)); safecopy(ap->A.base,base,sizeof(ap->A.base)); - safecopy(ap->A.rel,base,sizeof(ap->A.rel)); + safecopy(ap->A.rel,rel,sizeof(ap->A.rel)); OS_randombytes((uint8_t *)&ap->A.nonce,sizeof(ap->A.nonce)); - ap->A.expiration = (uint32_t)time(NULL) + duration; + if ( duration < 1000000000 ) + ap->A.expiration = (uint32_t)time(NULL) + duration; + else ap->A.expiration = duration; ap->A.offer64 = offerbits; ap->A.myside = myside; ap->A.acceptdir = acceptdir; @@ -358,9 +343,67 @@ bits256 instantdex_acceptset(struct instantdex_accept *ap,char *base,char *rel,i ap->A.basevolume64 = volume * SATOSHIDEN; vcalc_sha256(0,hash.bytes,(void *)&ap->A,sizeof(ap->A)); ap->orderid = hash.txid; + //printf("(%s/%s) acceptdir.%d myside.%d\n",base,rel,acceptdir,myside); return(hash); } +int32_t instantdex_acceptextract(struct instantdex_accept *ap,cJSON *argjson) +{ + char *base,*rel; bits256 hash,traderpub; double price,volume; int32_t baserel,acceptdir,num; + struct supernet_info *myinfo; + memset(ap,0,sizeof(*ap)); + if ( (base= jstr(argjson,"base")) != 0 ) + { + volume = jdouble(argjson,"volume"); + if ( (rel= jstr(argjson,"rel")) != 0 ) + safecopy(ap->A.rel,rel,sizeof(ap->A.rel)); + if ( (price= jdouble(argjson,"maxprice")) > SMALLVAL ) + { + baserel = 1; + acceptdir = -1; + } + else if ( (price= jdouble(argjson,"minprice")) > SMALLVAL ) + { + baserel = 0; + acceptdir = 1; + } else return(-1); + //printf("price %f vol %f baserel.%d acceptdir.%d\n",price,volume,baserel,acceptdir); + traderpub = jbits256(argjson,"traderpub"); + if ( (myinfo= SuperNET_MYINFOfind(&num,traderpub)) != 0 ) + hash = instantdex_acceptset(ap,base,rel,INSTANTDEX_LOCKTIME*2,baserel,acceptdir,price,volume,myinfo->myaddr.nxt64bits); + else + { + char str[65]; printf("cant find account for (%s)\n",bits256_str(str,traderpub)); + return(-1); + } + } + else + { + if ( (base= jstr(argjson,"b")) != 0 ) + safecopy(ap->A.base,base,sizeof(ap->A.base)); + if ( (rel= jstr(argjson,"r")) != 0 ) + safecopy(ap->A.rel,rel,sizeof(ap->A.rel)); + ap->A.nonce = juint(argjson,"n"); + ap->A.expiration = juint(argjson,"e"); + ap->A.myside = juint(argjson,"s"); + ap->A.acceptdir = jint(argjson,"d"); + ap->A.offer64 = j64bits(argjson,"o"); + ap->A.price64 = j64bits(argjson,"p"); + ap->A.basevolume64 = j64bits(argjson,"v"); + vcalc_sha256(0,hash.bytes,(void *)&ap->A,sizeof(ap->A)); + ap->orderid = j64bits(argjson,"id"); + } + if ( hash.txid != ap->orderid ) + { + int32_t i; + for (i=0; iorderid); + return(-1); + } + return(0); +} + cJSON *instantdex_acceptsendjson(struct instantdex_accept *ap) { cJSON *json = cJSON_CreateObject(); @@ -373,7 +416,7 @@ cJSON *instantdex_acceptsendjson(struct instantdex_accept *ap) jadd64bits(json,"p",ap->A.price64); jadd64bits(json,"v",ap->A.basevolume64); jadd64bits(json,"o",ap->A.offer64); - jadd64bits(json,"i",ap->orderid); + jadd64bits(json,"id",ap->orderid); return(json); } @@ -391,9 +434,9 @@ char *instantdex_parse(struct supernet_info *myinfo,struct instantdex_msghdr *ms if ( argjson != 0 ) { memset(&A,0,sizeof(A)); - if ( (traderip= jstr(argjson,"traderip")) != 0 && strcmp(traderip,myinfo->ipaddr) == 0 ) + if ( (remoteaddr != 0 && strcmp(remoteaddr,myinfo->ipaddr) == 0) || ((traderip= jstr(argjson,"traderip")) != 0 && strcmp(traderip,myinfo->ipaddr) == 0) ) { - printf("got my own request\n"); + printf("got my own request.(%s)\n",jprint(argjson,0)); if ( instantdex_acceptextract(&A,argjson) < 0 ) return(clonestr("{\"error\":\"hash txid mismatches orderid\"}")); return(clonestr("{\"result\":\"got my own request\"}")); @@ -401,10 +444,15 @@ char *instantdex_parse(struct supernet_info *myinfo,struct instantdex_msghdr *ms if ( (orderidstr= jstr(argjson,"id")) != 0 ) { orderid = calc_nxt64bits(orderidstr); - if ( (ap= instantdex_acceptablefind(exchange,0,0,orderid,"*","*")) != 0 ) + printf("orderid.%llu\n",(long long)orderid); + if ( (ap= instantdex_acceptablefind(myinfo,exchange,0,0,orderid,"*","*")) != 0 ) + { + printf("found existing\n"); A = *ap; + } } else if ( instantdex_acceptextract(&A,argjson) < 0 ) return(clonestr("{\"error\":\"hash txid mismatches orderid\"}")); + printf("call (%s/%s) swap baserel.%d acceptdir.%d\n",A.A.base,A.A.rel,A.A.myside,A.A.acceptdir); if ( strncmp(cmdstr,"BTC",3) == 0 ) retstr = instantdex_BTCswap(myinfo,exchange,&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,data,datalen); else if ( strncmp(cmdstr,"NXT",3) == 0 ) @@ -413,20 +461,23 @@ char *instantdex_parse(struct supernet_info *myinfo,struct instantdex_msghdr *ms retstr = instantdex_ALTswap(myinfo,exchange,&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,data,datalen); else if ( strncmp(cmdstr,"PAX",3) == 0 ) retstr = instantdex_PAXswap(myinfo,exchanges777_find("PAX"),&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,data,datalen); + else return(clonestr("{\"error\":\"unrecognized atomic swap family\"}")); if ( ap != 0 ) { - ap->statusjson = A.statusjson; + ap->info = A.info; ap->pendingvolume64 = A.pendingvolume64; } - else return(clonestr("{\"error\":\"unrecognized atomic swap family\"}")); + printf("after swap ap.%p (%s)\n",ap,retstr); + return(retstr); } return(clonestr("{\"error\":\"request needs argjson\"}")); } char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char *remoteaddr) { - struct instantdex_msghdr *msg = ptr; cJSON *argjson; int32_t n,datalen,newlen,flag = 0; - uint64_t signerbits; uint8_t *data; uint8_t tmp[sizeof(msg->sig)]; char *retstr = 0; + struct instantdex_msghdr *msg = ptr; cJSON *argjson; int32_t i,num,n,datalen,newlen,flag = 0; + uint8_t *data; struct supernet_info *myinfos[64]; + uint64_t signerbits; uint8_t tmp[sizeof(msg->sig)]; char *retstr = 0; cJSON *retjson,*item; acct777_rwsig(0,(void *)&msg->sig,(void *)tmp); memcpy(&msg->sig,tmp,sizeof(msg->sig)); datalen = len - (int32_t)sizeof(msg->sig); @@ -443,9 +494,11 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char else if ( (signerbits= acct777_validate(&msg->sig,acct777_msgprivkey(data,datalen),msg->sig.pubkey)) != 0 ) { flag++; - printf("InstantDEX_hexmsg <<<<<<<<<<<<< sigsize.%ld VALIDATED [%ld] len.%d t%u allocsize.%d (%s) [%d]\n",sizeof(msg->sig),(long)data-(long)msg,datalen,msg->sig.timestamp,msg->sig.allocsize,(char *)msg->serialized,data[datalen-1]); + //printf("InstantDEX_hexmsg <<<<<<<<<<<<< sigsize.%ld VALIDATED [%ld] len.%d t%u allocsize.%d (%s) [%d]\n",sizeof(msg->sig),(long)data-(long)msg,datalen,msg->sig.timestamp,msg->sig.allocsize,(char *)msg->serialized,data[datalen-1]); if ( data[datalen-1] == 0 && (argjson= cJSON_Parse((char *)msg->serialized)) != 0 ) - retstr = instantdex_parse(myinfo,msg,argjson,remoteaddr,signerbits,data,datalen); + { + + } else { newlen = (int32_t)(msg->sig.allocsize - sizeof(*msg)); @@ -461,8 +514,31 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char else data = 0; } } - if ( data != 0 ) - retstr = instantdex_parse(myinfo,msg,argjson,remoteaddr,signerbits,data,newlen); + } + if ( data != 0 || argjson != 0 ) + { + printf("CALL instantdex_parse.(%s)\n",argjson!=0?jprint(argjson,0):""); + retjson = cJSON_CreateArray(); + if ( (num= SuperNET_MYINFOS(myinfos,sizeof(myinfos)/sizeof(*myinfos))) == 0 ) + { + myinfos[0] = myinfo; + num = 1; + } + for (i=0; imyaddr.persistent)); + if ( (retstr= instantdex_parse(myinfo,msg,argjson,remoteaddr,signerbits,data,newlen)) != 0 ) + { + item = cJSON_CreateObject(); + jaddstr(item,"result",retstr); + if ( myinfo->handle[0] != 0 ) + jaddstr(item,"handle",myinfo->handle); + jaddbits256(item,"traderpub",myinfo->myaddr.persistent); + jaddi(retjson,item); + } + } + retstr = jprint(retjson,1); } } if ( argjson != 0 ) @@ -470,9 +546,9 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char return(retstr); } -char *instantdex_queueaccept(struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *mysidestr,int32_t duration) +char *instantdex_queueaccept(struct supernet_info *myinfo,struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *mysidestr,int32_t duration) { - struct instantdex_accept *ap; int32_t myside; struct supernet_info *myinfo = SuperNET_MYINFO(0); + struct instantdex_accept *ap; int32_t myside; if ( exchange != 0 ) { ap = calloc(1,sizeof(*ap)); @@ -480,7 +556,11 @@ char *instantdex_queueaccept(struct exchange_info *exchange,char *base,char *rel myside = 0; else if ( strcmp(mysidestr,rel) == 0 ) myside = 1; - else myside = -1; + else + { + myside = -1; + printf("myside.(%s) != base.%s or rel.%s\n",mysidestr,base,rel); + } instantdex_acceptset(ap,base,rel,duration,myside,acceptdir,price,basevolume,myinfo->myaddr.nxt64bits); queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0); return(jprint(instantdex_acceptjson(ap),1)); @@ -488,23 +568,41 @@ char *instantdex_queueaccept(struct exchange_info *exchange,char *base,char *rel else return(clonestr("{\"error\":\"invalid exchange\"}")); } +void instantdex_update(struct supernet_info *myinfo) +{ + struct instantdex_msghdr *pm; struct category_msg *m; bits256 instantdexhash; char *str,remote[64]; + instantdexhash = calc_categoryhashes(0,"InstantDEX",0); + while ( (m= category_gethexmsg(myinfo,instantdexhash,GENESIS_PUBKEY)) != 0 ) + { + pm = (struct instantdex_msghdr *)m->msg; + if ( m->remoteipbits != 0 ) + expand_ipbits(remote,m->remoteipbits); + else remote[0] = 0; + if ( (str= InstantDEX_hexmsg(myinfo,pm,m->len,remote)) != 0 ) + free(str); + free(m); + } +} + #include "../includes/iguana_apidefs.h" TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,maxaccept,base,rel,maxprice,basevolume) { + myinfo = SuperNET_accountfind(json); if ( remoteaddr == 0 ) - return(instantdex_queueaccept(exchanges777_find("bitcoin"),base,rel,maxprice,basevolume,-1,rel,INSTANTDEX_OFFERDURATION)); + return(instantdex_queueaccept(myinfo,exchanges777_find("bitcoin"),base,rel,maxprice,basevolume,-1,rel,INSTANTDEX_OFFERDURATION)); else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}")); } TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,minaccept,base,rel,minprice,basevolume) { + myinfo = SuperNET_accountfind(json); if ( remoteaddr == 0 ) - return(instantdex_queueaccept(exchanges777_find("bitcoin"),base,rel,minprice,basevolume,1,base,INSTANTDEX_OFFERDURATION)); + return(instantdex_queueaccept(myinfo,exchanges777_find("bitcoin"),base,rel,minprice,basevolume,1,base,INSTANTDEX_OFFERDURATION)); else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}")); } -TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,BTCoffer,othercoin,otherassetid,maxprice,othervolume) +/*TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,BTCoffer,othercoin,otherassetid,maxprice,othervolume) { if ( remoteaddr == 0 ) return(instantdex_btcoffer(myinfo,exchanges777_find("bitcoin"),othercoin[0] != 0 ? othercoin : otherassetid,othervolume,maxprice)); @@ -549,6 +647,6 @@ STRING_AND_TWO_DOUBLES(InstantDEX,NXToffer,assetid,minprice,basevolume) return(instantdex_sendcmd(myinfo,argjson,"NXToffer",myinfo->ipaddr,hops)); } else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}")); } - +*/ #include "../includes/iguana_apiundefs.h" diff --git a/iguana/iguana_recv.c b/iguana/iguana_recv.c index 1bdfd61ba..fee4929d9 100755 --- a/iguana/iguana_recv.c +++ b/iguana/iguana_recv.c @@ -326,7 +326,7 @@ void iguana_bundlespeculate(struct iguana_info *coin,struct iguana_bundle *bp,in if ( bp->numhashes < bp->n && bundlei == 0 && bp->speculative == 0 && bp->bundleheight < coin->longestchain-coin->chain->bundlesize ) { char str[65]; bits256_str(str,bp->hashes[0]); - printf("Afound block -> %d %d hdr.%s\n",bp->bundleheight,coin->longestchain-coin->chain->bundlesize,str); + //printf("Afound block -> %d %d hdr.%s\n",bp->bundleheight,coin->longestchain-coin->chain->bundlesize,str); queue_enqueue("hdrsQ",&coin->hdrsQ,queueitem(str),1); } else if ( bp->speculative != 0 && bundlei < bp->numspec && memcmp(hash2.bytes,bp->speculative[bundlei].bytes,sizeof(hash2)) == 0 ) @@ -371,7 +371,7 @@ int32_t iguana_bundleiters(struct iguana_info *coin,struct iguana_bundle *bp,int if ( pend >= coin->MAXPENDING*coin->MAXPEERS ) { sleep(10000); - printf("SKIP pend.%d vs %d: ITERATE bundle.%d n.%d r.%d s.%d finished.%d timelimit.%d\n",pend,coin->MAXPENDING*coin->MAXPEERS,bp->bundleheight,bp->n,bp->numrecv,bp->numsaved,bp->emitfinish,timelimit); + //printf("SKIP pend.%d vs %d: ITERATE bundle.%d n.%d r.%d s.%d finished.%d timelimit.%d\n",pend,coin->MAXPENDING*coin->MAXPEERS,bp->bundleheight,bp->n,bp->numrecv,bp->numsaved,bp->emitfinish,timelimit); iguana_bundleQ(coin,bp,counter == 0 ? bp->n*5 : bp->n*2); return(0); } @@ -404,7 +404,7 @@ int32_t iguana_bundleiters(struct iguana_info *coin,struct iguana_bundle *bp,int break; usleep(10000); } - //if ( 0 && counter > 0 ) + if ( 0 && counter > 0 ) printf("ITERATE bundle.%d h.%d n.%d r.%d s.%d finished.%d issued.%d\n",bp->bundleheight,bp->numhashes,bp->n,bp->numrecv,bp->numsaved,bp->emitfinish,counter); if ( bp->emitfinish == 0 ) { @@ -508,14 +508,14 @@ struct iguana_bundlereq *iguana_recvblockhdrs(struct iguana_info *coin,struct ig firstbp = bp; if ( bundlei == i+1 && bp == firstbp ) match++; - else printf("recvhdr: ht.%d[%d] vs i.%d\n",bp->bundleheight,bundlei,i); + //else printf("recvhdr: ht.%d[%d] vs i.%d\n",bp->bundleheight,bundlei,i); } } if ( firstbp != 0 && match == coin->chain->bundlesize-1 && n == firstbp->n ) { if ( firstbp->queued == 0 ) { - printf("firstbp blockQ %d\n",firstbp->bundleheight); + //printf("firstbp blockQ %d\n",firstbp->bundleheight); iguana_bundleQ(coin,firstbp,1000 + 10*(rand() % (int32_t)(1+sqrt(firstbp->bundleheight)))); } } else printf("match.%d vs n.%d bp->n.%d ht.%d\n",match,n,firstbp->n,firstbp->bundleheight); diff --git a/iguana/iguana_tx.c b/iguana/iguana_tx.c index edf4ed131..b9d156b16 100755 --- a/iguana/iguana_tx.c +++ b/iguana/iguana_tx.c @@ -336,4 +336,115 @@ cJSON *iguana_blockjson(struct iguana_info *coin,struct iguana_block *block,int3 return(jprint(retitem,1)); }*/ +struct bitcoin_unspent *iguana_bestfit(struct iguana_info *coin,struct bitcoin_unspent *unspents,int32_t numunspents,uint64_t value,int32_t mode) +{ + int32_t i; uint64_t above,below,gap,atx_value; struct bitcoin_unspent *vin,*abovevin,*belowvin; + abovevin = belowvin = 0; + for (above=below=i=0; ivalue; + //printf("(%.8f vs %.8f)\n",dstr(atx_value),dstr(value)); + if ( atx_value == value ) + return(vin); + else if ( atx_value > value ) + { + gap = (atx_value - value); + if ( above == 0 || gap < above ) + { + above = gap; + abovevin = vin; + } + } + else if ( mode == 0 ) + { + gap = (value - atx_value); + if ( below == 0 || gap < below ) + { + below = gap; + belowvin = vin; + } + } + } + if ( (vin= (abovevin != 0) ? abovevin : belowvin) == 0 && mode == 1 ) + vin = unspents; + return(vin); +} + +struct bitcoin_unspent *iguana_unspentsget(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *numunspentsp) +{ + struct bitcoin_unspent *ups = calloc(1,sizeof(*ups)); //uint8_t addrtype; + // struct bitcoin_unspent { bits256 txid,privkey; uint64_t value; int32_t vout; }; + *numunspentsp = 0; + return(ups); +} +struct bitcoin_spend *iguana_spendset(struct supernet_info *myinfo,struct iguana_info *coin,int64_t amount,int64_t txfee) +{ + int32_t i,mode,numunspents,maxinputs = 1024; int64_t remains; struct bitcoin_unspent *ptr,*up; + struct bitcoin_unspent *ups; struct bitcoin_spend *spend; + if ( (ups= iguana_unspentsget(myinfo,coin,&numunspents)) == 0 ) + return(0); + spend = calloc(1,sizeof(*spend) + sizeof(*spend->inputs) * maxinputs); + spend->txfee = txfee; + remains = txfee + amount; + spend->satoshis = remains; + ptr = spend->inputs; + for (i=0; i=0; mode--) + if ( (up= iguana_bestfit(coin,ups,numunspents,remains,mode)) != 0 ) + break; + if ( up != 0 ) + { + spend->input_satoshis += up->value; + spend->inputs[spend->numinputs++] = *up; + if ( spend->input_satoshis >= spend->satoshis ) + { + spend->netamount = (spend->input_satoshis - spend->satoshis); + spend->change = (spend->input_satoshis - spend->netamount); + printf("numinputs %d sum %.8f vs amount %.8f change %.8f -> txfee %.8f\n",spend->numinputs,dstr(spend->input_satoshis),dstr(amount),dstr(spend->change),dstr(spend->input_satoshis - spend->change - spend->netamount)); + break; + } + remains -= up->value; + } else break; + } + if ( spend->input_satoshis >= spend->satoshis ) + { + spend = realloc(spend,sizeof(*spend) + sizeof(*spend->inputs) * spend->numinputs); + return(spend); + } + else + { + free(spend); + return(0); + } +} + +cJSON *iguana_signtx(struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj) +{ + int32_t i,j; char *rawtxstr; struct vin_info V; bits256 txid; + for (i=0; inuminputs; i++) + bitcoin_addinput(coin,txobj,spend->inputs[i].txid,spend->inputs[i].vout,0xffffffff); + for (i=0; inuminputs; i++) // N times less efficient, but for small number of inputs ok + { + if ( *signedtxp != 0 ) + { + free_json(txobj); + txobj = bitcoin_hex2json(coin,&txid,0,*signedtxp); + free(*signedtxp); + } + if ( (rawtxstr= bitcoin_json2hex(coin,&txid,txobj)) != 0 ) + { + memset(&V,0,sizeof(V)); + for (j=0; jinputs[i].privkeys)/sizeof(*spend->inputs[i].privkeys); j++) + if ( bits256_nonz(spend->inputs[i].privkeys[j]) > 0 ) + V.signers[j].privkey = spend->inputs[i].privkeys[j]; + bitcoin_verifytx(coin,txidp,signedtxp,rawtxstr,&V); + free(rawtxstr); + } else break; + } + if ( *signedtxp != 0 && i != spend->numinputs ) + free(*signedtxp), *signedtxp = 0; + return(txobj); +} diff --git a/iguana/main.c b/iguana/main.c index 6cd550b2f..fb509030e 100644 --- a/iguana/main.c +++ b/iguana/main.c @@ -38,7 +38,7 @@ struct iguana_info *Coins[IGUANA_MAXCOINS]; int32_t USE_JAY,FIRST_EXTERNAL,IGUANA_disableNXT,Debuglevel; uint32_t prices777_NXTBLOCK,MAX_DEPTH = 100; queue_t helperQ,jsonQ,finishedQ,bundlesQ; -struct supernet_info MYINFO; +struct supernet_info MYINFO,**MYINFOS; static int32_t initflag; cJSON *API_json; #ifdef __linux__ @@ -107,6 +107,45 @@ struct supernet_info *SuperNET_MYINFO(char *passphrase) return(0); } +struct supernet_info *SuperNET_MYINFOfind(int32_t *nump,bits256 pubkey) +{ + int32_t i; + *nump = 0; + if ( MYINFOS != 0 ) + { + for (i=0; MYINFOS[i]!=0; i++) + { + *nump = i; + if ( bits256_cmp(pubkey,MYINFOS[i]->myaddr.persistent) == 0 ) + return(MYINFOS[i]); + } + *nump = i; + } + return(0); +} + +int32_t SuperNET_MYINFOS(struct supernet_info **myinfos,int32_t max) +{ + int32_t i; + for (i=0; imyaddr.persistent) == 0 ) + { + MYINFOS = realloc(MYINFOS,(num + 2) * sizeof(*MYINFOS)); + char str[65]; printf("MYNFOadd[%d] <- %s\n",num,bits256_str(str,myinfo->myaddr.persistent)); + MYINFOS[num] = calloc(1,sizeof(*myinfo)); + *MYINFOS[num] = *myinfo; + MYINFOS[++num] = 0; + } +} + char *iguana_JSON(char *jsonstr) { char *retstr=0; cJSON *json; @@ -205,7 +244,7 @@ char *SuperNET_processJSON(struct supernet_info *myinfo,cJSON *json,char *remote timeout = IGUANA_JSONTIMEOUT; if ( (method= jstr(json,"method")) != 0 && strcmp(method,"DHT") == 0 && remoteaddr != 0 ) { - SuperNET_hexmsgprocess(myinfo,json,jstr(json,"hexmsg"),remoteaddr); + SuperNET_hexmsgprocess(myinfo,0,json,jstr(json,"hexmsg"),remoteaddr); return(clonestr("{\"result\":\"processed remote DHT\"}")); } jsonstr = jprint(json,0); @@ -1102,16 +1141,21 @@ void iguana_main(void *arg) char *str; strcpy(MYINFO.rpcsymbol,"BTCD"); iguana_launchcoin(MYINFO.rpcsymbol,cJSON_Parse("{}")); - - if ( 1 && (str= SuperNET_JSON(&MYINFO,cJSON_Parse("{\"wallet\":\"password\",\"agent\":\"iguana\",\"method\":\"addcoin\",\"services\":128,\"maxpeers\":3,\"newcoin\":\"BTCD\",\"active\":0}"),0)) != 0 ) + if ( 1 && (str= SuperNET_JSON(&MYINFO,cJSON_Parse("{\"agent\":\"iguana\",\"method\":\"addcoin\",\"services\":128,\"maxpeers\":3,\"newcoin\":\"BTCD\",\"active\":0}"),0)) != 0 ) { - printf("got.(%s)\n",str); free(str); + if ( (str= SuperNET_JSON(&MYINFO,cJSON_Parse("{\"agent\":\"iguana\",\"method\":\"addcoin\",\"services\":128,\"maxpeers\":3,\"newcoin\":\"BTC\",\"active\":0}"),0)) != 0 ) + { + free(str); + if ( 0 && (str= SuperNET_JSON(&MYINFO,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"alice\",\"password\":\"alice\",\"passphrase\":\"alice\"}"),0)) != 0 ) + { + free(str); + if ( (str= SuperNET_JSON(&MYINFO,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"bob\",\"password\":\"bob\",\"passphrase\":\"bob\"}"),0)) != 0 ) + free(str); + } + } } sleep(1); - static bits256 txid; - bitcoin_txtest(iguana_coinfind(MYINFO.rpcsymbol),"000",txid); - //getchar(); #endif } if ( arg != 0 ) diff --git a/iguana/pangea_api.c b/iguana/pangea_api.c index 7f0be1cff..3b16651b3 100755 --- a/iguana/pangea_api.c +++ b/iguana/pangea_api.c @@ -263,7 +263,7 @@ char *pangea_jsondatacmd(struct supernet_info *myinfo,bits256 tablehash,struct p { printf("pangea send.(%s)\n",cmdstr); init_hexbytes_noT(hexstr,(uint8_t *)pm,pm->sig.allocsize); - return(SuperNET_categorymulticast(myinfo,0,pangeahash,tablehash,hexstr,0,2,1)); + return(SuperNET_categorymulticast(myinfo,0,pangeahash,tablehash,hexstr,0,2,1,argjson,0)); } else { @@ -291,7 +291,7 @@ void pangea_sendcmd(struct supernet_info *myinfo,struct table_info *tp,char *cmd loopback = 1; if ( destplayer < 0 ) { - if ( (str= SuperNET_categorymulticast(myinfo,0,tp->G.gamehash,tp->G.tablehash,hexstr,0,2,plaintext)) != 0 ) + if ( (str= SuperNET_categorymulticast(myinfo,0,tp->G.gamehash,tp->G.tablehash,hexstr,0,2,plaintext,0,0)) != 0 ) free(str); loopback = 1; } @@ -541,16 +541,16 @@ char *pangea_hexmsg(struct supernet_info *myinfo,void *data,int32_t len,char *re void pangea_update(struct supernet_info *myinfo) { - struct pangea_msghdr *pm; struct category_msg *m; bits256 pangeahash; char remoteaddr[64]; + struct pangea_msghdr *pm; struct category_msg *m; bits256 pangeahash; char remoteaddr[64],*str; pangeahash = calc_categoryhashes(0,"pangea",0); while ( (m= category_gethexmsg(myinfo,pangeahash,GENESIS_PUBKEY)) != 0 ) { pm = (struct pangea_msghdr *)m->msg; if ( m->remoteipbits != 0 ) expand_ipbits(remoteaddr,m->remoteipbits); - if ( pangea_hexmsg(myinfo,pm,m->len,remoteaddr) > 0 ) - { - } + else remoteaddr[0] = 0; + if ( (str= pangea_hexmsg(myinfo,pm,m->len,remoteaddr)) != 0 ) + free(str); free(m); } } diff --git a/iguana/pnacl/Release/iguana.nmf b/iguana/pnacl/Release/iguana.nmf new file mode 100644 index 000000000..9d37ed227 --- /dev/null +++ b/iguana/pnacl/Release/iguana.nmf @@ -0,0 +1,12 @@ +{ + "program": { + "portable": { + "pnacl-translate": { + "url": "iguana.pexe" + }, + "pnacl-debug": { + "url": "iguana_unstripped.bc" + } + } + } +} diff --git a/iguana/pnacl/Release/iguana.pexe b/iguana/pnacl/Release/iguana.pexe new file mode 100644 index 000000000..d0190b2f6 Binary files /dev/null and b/iguana/pnacl/Release/iguana.pexe differ diff --git a/iguana/swaps/iguana_BTCswap.c b/iguana/swaps/iguana_BTCswap.c index bcdfde0b7..6269e1dea 100755 --- a/iguana/swaps/iguana_BTCswap.c +++ b/iguana/swaps/iguana_BTCswap.c @@ -14,23 +14,117 @@ ******************************************************************************/ #include "../exchanges/bitcoin.h" +/* https://bitcointalk.org/index.php?topic=1340621.msg13828271#msg13828271 +Tier Nolan's approach is followed with the following changes: + a) instead of cutting 1000 keypairs, only 777 are a + b) instead of sending the entire 256 bits, it is truncated to 64 bits. With odds of collision being so low, it is dwarfed by the ~0.1% insurance factor. + c) D is set to 100x the insurance rate of 1/777 12.87% + BTC amount + d) insurance is added to Bob's payment, which is after the deposit and bailin + e) BEFORE Bob broadcasts deposit, Alice broadcasts BTC denominated fee in cltv so if trade isnt done fee is reclaimed +*/ + +#define INSTANTDEX_INSURANCERATE (1. / 777.) +#define INSTANTDEX_PUBEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" +#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" +#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" +#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" +#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf" + +struct bitcoin_swapinfo +{ + bits256 privkeys[777],mypubs[2],otherpubs[2],pubBn,pubAm,dtxid,ptxid,aptxid,astxid,stxid,ftxid; + uint64_t otherscut[777][2]; + int32_t isbob,choosei,otherschoosei,state,cutverified,otherverifiedcut; + char altmsigaddr[64],*deposit,*payment,*altpayment,*altspend,*spendtx,*feetx; +}; + +int32_t instantdex_outputinsurance(struct iguana_info *coin,cJSON *txobj,int64_t insurance,uint64_t nonce) +{ + uint8_t rmd160[20],script[128]; int32_t n; + decode_hex(rmd160,sizeof(rmd160),(nonce % 10) == 0 ? TIERNOLAN_RMD160 : INSTANTDEX_RMD160); + n = bitcoin_standardspend(script,0,rmd160); + bitcoin_addoutput(coin,txobj,script,n,insurance); + return(n); +} + /* -bitcoin_pubkey33(pubkey,myinfo->persistent_priv); -bitcoin_address(coinaddr,other->chain->pubtype,pubkey,sizeof(pubkey)); -bitcoin_addr2rmd160(&addrtype,secret160,coinaddr); -scriptlen = bitcoin_cltvscript(coinbtc->chain->p2shtype,p2sh_coinaddr,p2sh_rmd160,script,0,senderaddr,otheraddr,secret160,locktime); -if ( jobj(argjson,"p2sh") != 0 ) + Alice fee: + OP_IF + OP_CLTV OP_DROP INSTANTDEX OP_CHECKSIG + OP_ELSE + OP_CLTV OP_DROP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG + OP_ENDIF + + Bob deposit: + instantdex_bobscript(script,0,(uint32_t)(time(NULL)+INSTANTDEX_LOCKTIME*2),pubA0,privBn,pubB0); + OP_IF + OP_CLTV OP_DROP OP_CHECKSIG + OP_ELSE + OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG + OP_ENDIF + +Bobpays: + instantdex_bobscript(script,0,(uint32_t)(time(NULL)+INSTANTDEX_LOCKTIME),pubB1,privAm,pubA0); +OP_IF + OP_CLTV OP_DROP OP_CHECKSIG +OP_ELSE + OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG +OP_ENDIF +*/ + +int32_t instantdex_bobscript(uint8_t *script,int32_t n,int32_t *secretstartp,uint32_t locktime,bits256 cltvpub,uint8_t secret160[20],bits256 destpub) { - if ( strcmp(jstr(argjson,"p2sh"),p2sh_coinaddr) != 0 ) + uint8_t pubkeyA[33],pubkeyB[33]; + memcpy(pubkeyA+1,cltvpub.bytes,sizeof(cltvpub)), pubkeyA[0] = 0x02; + memcpy(pubkeyB+1,destpub.bytes,sizeof(destpub)), pubkeyB[0] = 0x03; + script[n++] = SCRIPT_OP_IF; + n = bitcoin_checklocktimeverify(script,n,locktime); + 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); +} + +// OP_2 OP_2 OP_CHECKMULTISIG +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); +} + +char *instantdex_bobtx(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,bits256 pubA0,bits256 pubB0,bits256 privBn,uint32_t reftime,int64_t amount,int32_t depositflag) +{ + cJSON *txobj; int32_t n,secretstart; char *signedtx = 0; + uint8_t script[1024],secret[20]; struct bitcoin_spend *spend; int64_t insurance; uint32_t locktime; + locktime = (uint32_t)(reftime + INSTANTDEX_LOCKTIME * (1 + depositflag)); + txobj = bitcoin_createtx(coin,locktime); + insurance = (amount * INSTANTDEX_INSURANCERATE + coin->chain->txfee); // txfee prevents dust attack + if ( (spend= iguana_spendset(myinfo,coin,amount + insurance,coin->chain->txfee)) != 0 ) { - printf("mismatched p2sh.(%s) vs (%s)\n",jstr(argjson,"p2sh"),p2sh_coinaddr); - return(clonestr("{\"error\":\"instantdex_BTCswap base or rel mismatch\"}")); + calc_rmd160_sha256(secret,privBn.bytes,sizeof(privBn)); + n = instantdex_bobscript(script,0,&secretstart,locktime,pubA0,secret,pubB0); + bitcoin_addoutput(coin,txobj,script,n,amount + depositflag*insurance*100); + if ( depositflag == 0 ) + instantdex_outputinsurance(coin,txobj,insurance,pubB0.txid); + txobj = iguana_signtx(coin,txidp,&signedtx,spend,txobj); + if ( signedtx != 0 ) + printf("bob deposit.%s\n",signedtx); + else printf("error signing bobdeposit numinputs.%d\n",spend->numinputs); + free(spend); } + free_json(txobj); + return(signedtx); } -*/ -#define INSTANTDEX_DONATION 2000 - -// https://github.com/TierNolan/bips/blob/bip4x/bip-atom.mediawiki uint64_t instantdex_relsatoshis(uint64_t price,uint64_t volume) { @@ -39,143 +133,580 @@ uint64_t instantdex_relsatoshis(uint64_t price,uint64_t volume) else return(dstr(price) * volume); } +int32_t instantdex_paymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,struct instantdex_accept *A,cJSON *argjson,int32_t depositflag) +{ + cJSON *txobj; bits256 txid; uint32_t n,locktime; int32_t i,secretstart,retval = -1; uint64_t x; + struct iguana_msgtx msgtx; uint8_t script[512],rmd160[20]; int64_t insurance,relsatoshis,amount; + if ( jstr(argjson,depositflag != 0 ? "deposit" : "payment") != 0 ) + { + relsatoshis = instantdex_relsatoshis(A->A.price64,A->A.basevolume64); + insurance = (relsatoshis * INSTANTDEX_INSURANCERATE + coin->chain->txfee); // txfee prevents dust attack + if ( depositflag != 0 ) + { + swap->deposit = clonestr(jstr(argjson,"deposit")); + swap->dtxid = jbits256(argjson,"dtxid"); + swap->pubBn = jbits256(argjson,"pubBn"); + insurance *= 100; + } + amount = relsatoshis + insurance; + if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->deposit)) != 0 ) + { + locktime = A->A.expiration; + if ( depositflag == 0 ) + memset(rmd160,0,sizeof(rmd160)); + else calc_rmd160_sha256(rmd160,swap->privkeys[0].bytes,sizeof(rmd160)); + n = instantdex_bobscript(script,0,&secretstart,locktime,swap->mypubs[0],rmd160,swap->otherpubs[0]); + if ( msgtx.lock_time == locktime && msgtx.vouts[0].value == amount && n == msgtx.vouts[0].pk_scriptlen ) + { + memcpy(&script[secretstart],&msgtx.vouts[0].pk_script[secretstart],20); + if ( memcmp(script,msgtx.vouts[0].pk_script,n) == 0 ) + { + iguana_rwnum(0,&script[secretstart],sizeof(x),&x); + printf("deposit script verified x.%llx vs otherscut %llx\n",(long long)x,(long long)swap->otherscut[swap->choosei][0]); + if ( x == swap->otherscut[swap->choosei][0] ) + { + if ( depositflag == 0 ) + { + decode_hex(rmd160,sizeof(rmd160),(swap->otherpubs[0].txid % 10) == 0 ? TIERNOLAN_RMD160 : INSTANTDEX_RMD160); + n = bitcoin_standardspend(script,0,rmd160); + if ( msgtx.vouts[1].value == insurance && n == msgtx.vouts[1].pk_scriptlen && memcmp(script,msgtx.vouts[1].pk_script,n) == 0 ) + retval = 0; + } else retval = 0; + } + else printf("deposit script verified but secret mismatch x.%llx vs otherscut %llx\n",(long long)x,(long long)swap->otherscut[swap->choosei][0]); + } + else + { + for (i=0; ichain->txfee); // txfee prevents dust attack + if ( (spend= iguana_spendset(myinfo,altcoin,amount + insurance,altcoin->chain->txfee)) != 0 ) + { + //instantdex_outputinsurance(altcoin,txobj,insurance); + n = instantdex_alicescript(script,0,msigaddr,altcoin->chain->p2shtype,pubAm,pubBn); + bitcoin_addoutput(altcoin,txobj,script,n,amount); + txobj = iguana_signtx(altcoin,txidp,&signedtx,spend,txobj); + if ( signedtx != 0 ) + printf("alice payment.%s\n",signedtx); + else printf("error signing alicetx numinputs.%d\n",spend->numinputs); + free(spend); + } + free_json(txobj); + return(signedtx); +} + +int32_t instantdex_altpaymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,struct instantdex_accept *A,cJSON *argjson) +{ + cJSON *txobj; bits256 txid; uint32_t n; int32_t i,retval = -1; + struct iguana_msgtx msgtx; uint8_t script[512]; char *altmsigaddr,msigaddr[64]; + if ( jstr(argjson,"altpayment") != 0 && (altmsigaddr= jstr(argjson,"altmsigaddr")) != 0 ) + { + swap->altpayment = clonestr(jstr(argjson,"altpayment")); + swap->aptxid = jbits256(argjson,"aptxid"); + swap->pubAm = jbits256(argjson,"pubAm"); + if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->altpayment)) != 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("deposit script verified\n"); + } + else + { + for (i=0; ipendingvolume64 -= A->A.basevolume64; +} + bits256 instantdex_sharedpub256(bits256 *sharedprivp,uint8_t pubkey[33],bits256 privkey,bits256 hash,int32_t n) { - bits256 shared,iters; int32_t i; + bits256 shared,iters; iters = shared = curve25519_shared(privkey,hash); - for (i=0; ibytes,shared.bytes,sizeof(shared),iters.bytes,sizeof(iters)); return(bitcoin_pubkey33(pubkey,*sharedprivp)); } -int32_t instantdex_pubkeyargs(bits256 *sharedprivs,cJSON *argjson,int32_t numpubs,bits256 privkey,bits256 hash,int32_t firstbyte) +int32_t instantdex_pubkeyargs(bits256 *sharedprivs,cJSON *newjson,int32_t numpubs,bits256 privkey,bits256 hash,int32_t firstbyte) { - char buf[3]; int32_t i,n; bits256 tmp; uint8_t pubkey[33]; + char buf[3],*hexstr=0; int32_t i,n,len=0; bits256 pubi; uint64_t txid; uint8_t secret160[20],pubkey[33],*hex=0; + if ( numpubs > 2 ) + { + if ( (hexstr= malloc(777 * sizeof(uint64_t) * 2 * 2 + 1)) == 0 ) + return(-1); + if ( (hex= malloc(777 * sizeof(uint64_t) * 2)) == 0 ) + return(-1); + } sprintf(buf,"%c0",'A' - 0x02 + firstbyte); - for (i=n=0; i 2 ) + { + sprintf(buf+1,"%d",n); + jaddbits256(newjson,buf,pubi); + } + else + { + calc_rmd160_sha256(secret160,sharedprivs[n].bytes,sizeof(sharedprivs[n])); + memcpy(&txid,secret160,sizeof(txid)); + len += iguana_rwnum(1,&hex[len],sizeof(txid),&txid); + len += iguana_rwnum(1,&hex[len],sizeof(pubi.txid),&pubi.txid); + } + n++; + } + if ( n > 2 && newjson != 0 && len > 0 ) + { + init_hexbytes_noT(hexstr,hex,len); + jaddstr(newjson,"cut",hexstr); } + if ( hex != 0 ) + free(hex); + if ( hexstr != 0 ) + free(hexstr); return(n); } -int32_t bitcoin_2of2spendscript(int32_t *paymentlenp,uint8_t *paymentscript,uint8_t *msigscript,bits256 pub0,bits256 pub1) +char *instantdex_choosei(struct bitcoin_swapinfo *swap,cJSON *newjson,cJSON *argjson) { - struct vin_info V; uint8_t p2sh_rmd160[20]; int32_t p2shlen; - memset(&V,0,sizeof(V)); - V.M = V.N = 2; - memcpy(V.signers[0].pubkey+1,pub0.bytes,sizeof(pub0)), V.signers[0].pubkey[0] = 0x02; - memcpy(V.signers[1].pubkey+1,pub1.bytes,sizeof(pub1)), V.signers[1].pubkey[0] = 0x03; - p2shlen = bitcoin_MofNspendscript(p2sh_rmd160,msigscript,0,&V); - *paymentlenp = bitcoin_p2shspend(paymentscript,0,p2sh_rmd160); - return(p2shlen); + char *cutstr; int32_t i,j,max,len = 0; uint64_t x; + if ( swap->choosei < 0 && (cutstr= jstr(argjson,"cut")) != 0 ) + { + max = (int32_t)(sizeof(swap->otherscut) / sizeof(*swap->otherscut)); + if ( strlen(cutstr) == sizeof(swap->otherscut)*2 ) + { + decode_hex((uint8_t *)swap->otherscut,sizeof(swap->otherscut),cutstr); + for (i=0; iotherscut[i][j],sizeof(x),&x); + swap->otherscut[i][j] = x; + } + } else return(clonestr("{\"error\":\"instantdex_BTCswap offer wrong cutsize\"}")); + OS_randombytes((uint8_t *)&swap->choosei,sizeof(swap->choosei)); + swap->choosei %= max; + jaddnum(newjson,"mychoosei",swap->choosei); + return(0); + } else return(clonestr("{\"error\":\"instantdex_BTCswap offer no cut\"}")); +} + +void instantdex_getpubs(struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson) +{ + char fields[2][2][3]; int32_t i,j,myind,otherind; + memset(fields,0,sizeof(fields)); + fields[0][0][0] = fields[0][1][0] = 'A'; + fields[1][0][0] = fields[1][1][0] = 'B'; + for (i=0; i<2; i++) + for (j=0; j<2; j++) + fields[i][j][1] = '0' + j; + myind = swap->isbob; + otherind = (myind ^ 1); + for (j=0; j<2; j++) + { + if ( bits256_nonz(swap->mypubs[j]) == 0 && jobj(argjson,fields[myind][j]) != 0 ) + swap->mypubs[j] = jbits256(newjson,fields[myind][j]); + if ( bits256_nonz(swap->otherpubs[j]) == 0 && jobj(argjson,fields[otherind][j]) != 0 ) + swap->otherpubs[j] = jbits256(argjson,fields[otherind][j]); + } } -struct bitcoin_unspent *instantdex_bestfit(struct iguana_info *coin,struct bitcoin_unspent *unspents,int32_t numunspents,uint64_t value,int32_t mode) +cJSON *instantdex_newjson(struct supernet_info *myinfo,struct bitcoin_swapinfo *swap,cJSON *argjson,bits256 hash,struct instantdex_accept *A,int32_t flag777,int32_t sendprivs) { - int32_t i; uint64_t above,below,gap,atx_value; struct bitcoin_unspent *vin,*abovevin,*belowvin; - abovevin = belowvin = 0; - for (above=below=i=0; ivalue; - //printf("(%.8f vs %.8f)\n",dstr(atx_value),dstr(value)); - if ( atx_value == value ) - return(vin); - else if ( atx_value > value ) + cJSON *newjson; char serstr[sizeof(bits256)*2+1],*hexstr=0; int32_t i,wrongfirstbyte,errs; + bits256 hashpriv,pubi,otherpriv,*privs=0; uint8_t serialized[sizeof(bits256)],otherpubkey[33]; + newjson = instantdex_acceptsendjson(A); + printf("acceptsend.(%s)\n",jprint(newjson,0)); + if ( swap->otherschoosei < 0 && jobj(argjson,"mychoosei") != 0 ) + { + printf("otherschoosei.%d\n",swap->otherschoosei); + if ( (swap->otherschoosei= juint(argjson,"mychoosei")) >= sizeof(swap->otherscut)/sizeof(*swap->otherscut) ) + swap->otherschoosei = -1; + } + if ( juint(argjson,"verified") != 0 ) + swap->otherverifiedcut = 1; + printf("otherverified.%d\n",swap->otherverifiedcut); + if ( jobj(argjson,"myprivs") != 0 && swap->cutverified == 0 ) + { + printf("got privs\n"); + if ( (privs= calloc(1,sizeof(*swap->privkeys))) == 0 ) + printf("instantdex_newjson couldnt allocate hex\n"); + else if ( (hexstr= jstr(argjson,"myprivs")) == 0 || strlen(hexstr) != sizeof(swap->privkeys)*2 ) + printf("instantdex_newjson other's privkeys wrong size\n"); + else { - gap = (atx_value - value); - if ( above == 0 || gap < above ) + for (i=wrongfirstbyte=errs=0; iprivkeys)/sizeof(*swap->privkeys); i++) { - above = gap; - abovevin = vin; + memcpy(serstr,&hexstr[i * sizeof(bits256)],sizeof(bits256)); + decode_hex(serialized,sizeof(bits256),serstr); + iguana_rwbignum(0,serialized,sizeof(otherpriv),otherpriv.bytes); + if ( i == swap->choosei ) + { + if ( bits256_nonz(otherpriv) != 0 ) + { + printf("got privkey in slot.%d my choosi??\n",i); + errs++; + } + continue; + } + pubi = bitcoin_pubkey33(otherpubkey,otherpriv); + vcalc_sha256(0,hashpriv.bytes,otherpriv.bytes,sizeof(otherpriv)); + if ( otherpubkey[0] != (swap->isbob ^ 1) + 0x02 ) + { + wrongfirstbyte++; + printf("wrongfirstbyte[%d] %02x\n",i,otherpubkey[0]); + } + else if ( swap->otherscut[i][0] != hashpriv.txid ) + { + printf("otherscut[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherscut[i][0],(long long)hashpriv.txid); + errs++; + } + else if ( swap->otherscut[i][1] != pubi.txid ) + { + printf("otherscut[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherscut[i][1],(long long)pubi.txid); + errs++; + } } + if ( errs == 0 && wrongfirstbyte == 0 ) + swap->cutverified = 1; + else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs); } - else if ( mode == 0 ) + } + jaddnum(newjson,"verified",swap->otherverifiedcut); + printf("otherverified.%d\n",swap->otherverifiedcut); + if ( instantdex_pubkeyargs(swap->privkeys,newjson,2+flag777*777,myinfo->persistent_priv,hash,0x02 + swap->isbob) != 2+flag777*777 ) + { + printf("error generating pubkeyargs\n"); + return(0); + } + printf("call getpubs\n"); + instantdex_getpubs(swap,argjson,newjson); + if ( sendprivs != 0 ) + { + printf("sendprivs.%d\n",sendprivs); + if ( swap->otherschoosei < 0 ) + printf("instantdex_newjson otherschoosei < 0 when sendprivs != 0\n"); + else { - gap = (value - atx_value); - if ( below == 0 || gap < below ) + if ( privs == 0 && (privs= calloc(1,sizeof(*swap->privkeys))) == 0 ) + printf("instantdex_newjson couldnt allocate hex\n"); + else if ( hexstr == 0 && (hexstr= malloc(sizeof(*swap->privkeys) * 2 + 1)) == 0 ) + printf("instantdex_newjson couldnt allocate hexstr\n"); + else { - below = gap; - belowvin = vin; + memcpy(privs,swap->privkeys,sizeof(*swap->privkeys)); + memset(privs[swap->otherschoosei].bytes,0,sizeof(*privs)); + for (i=0; iprivkeys)/sizeof(*swap->privkeys); i++) + { + iguana_rwbignum(1,serialized,sizeof(privs[i]),privs[i].bytes); + memcpy(privs[i].bytes,serialized,sizeof(privs[i])); + } + init_hexbytes_noT(hexstr,privs[0].bytes,sizeof(swap->privkeys)); + jaddstr(newjson,"myprivs",hexstr); } } } - if ( (vin= (abovevin != 0) ? abovevin : belowvin) == 0 && mode == 1 ) - vin = unspents; - return(vin); + if ( privs != 0 ) + free(privs); + if ( hexstr != 0 ) + free(hexstr); + return(newjson); } -struct bitcoin_unspent *iguana_unspentsget(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *numunspentsp) +char *instantdex_btcoffer(struct supernet_info *myinfo,struct exchange_info *exchange,char *othercoin,double othervolume,double price,int32_t dir) // Bob sending to network (Alice) { - struct bitcoin_unspent *ups = calloc(1,sizeof(*ups)); //uint8_t addrtype; - // struct bitcoin_unspent { bits256 txid,privkey; uint64_t value; int32_t vout; }; - *numunspentsp = 0; - return(ups); + char *str; struct iguana_info *other; int32_t isbob = 1; struct bitcoin_swapinfo *swap; + struct instantdex_accept checkA,A,*ap = 0; cJSON *newjson; bits256 hash; + if ( othercoin == 0 || (other= iguana_coinfind(othercoin)) == 0 ) + return(clonestr("{\"error\":\"invalid othercoin\"}")); + hash = instantdex_acceptset(&A,othercoin,"BTC",INSTANTDEX_LOCKTIME*2,dir < 0 ? 1 : 0,-dir,price,othervolume,myinfo->myaddr.nxt64bits); + newjson = instantdex_acceptsendjson(&A); + if ( instantdex_acceptextract(&checkA,newjson) < 0 ) + { + int32_t i; + for (i=0; iisbob = dir > 0, swap->choosei = swap->otherschoosei = -1; + if ( instantdex_pubkeyargs(swap->privkeys,newjson,777+2,myinfo->persistent_priv,hash,0x02+isbob) != 4 ) + return(clonestr("{\"error\":\"highly unlikely run of 02 pubkeys\"}")); + if ( price > SMALLVAL ) + { + if ( dir > 0 && (str= InstantDEX_maxaccept(myinfo,0,newjson,0,othercoin,"BTC",price,othervolume)) != 0 ) + free(str); + else if ( dir < 0 && (str= InstantDEX_minaccept(myinfo,0,newjson,0,othercoin,"BTC",price,othervolume)) != 0 ) + free(str); + if ( (ap= instantdex_acceptablefind(myinfo,exchange,0,0,A.orderid,"*","*")) != 0 ) + { + swap->state++; + ap->info = swap; + } + } + if ( ap == 0 ) + { + printf("couldnt find accept??\n"); + free(swap); + return(clonestr("{\"error\":\"couldnt find order just created\"}")); + } else return(instantdex_sendcmd(myinfo,newjson,"BTCoffer",myinfo->ipaddr,INSTANTDEX_HOPS)); } -struct bitcoin_spend *instantdex_spendset(struct supernet_info *myinfo,struct iguana_info *coin,uint64_t satoshis,uint64_t donation) +char *instantdex_BTCswap(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,char *cmdstr,struct instantdex_msghdr *msg,cJSON *argjson,char *remoteaddr,uint64_t signerbits,uint8_t *data,int32_t datalen) // receiving side { - int32_t i,mode,numunspents,maxinputs = 1024; int64_t remains; struct bitcoin_unspent *ptr,*up; - struct bitcoin_unspent *ups; struct bitcoin_spend *spend; - if ( (ups= iguana_unspentsget(myinfo,coin,&numunspents)) == 0 ) - return(0); - spend = calloc(1,sizeof(*spend) + sizeof(*spend->inputs) * maxinputs); - spend->satoshis = satoshis; - spend->txfee = coin->chain->txfee; - if ( strcmp(coin->symbol,"BTC") == 0 ) - remains = spend->txfee + spend->satoshis + donation; - ptr = spend->inputs; - for (i=0; i=0; mode--) - if ( (up= instantdex_bestfit(coin,ups,numunspents,remains,mode)) != 0 ) - break; - if ( up != 0 ) + char *retstr=0; uint64_t satoshis[2]; int32_t reftime,offerdir = 0; + struct instantdex_accept *ap; struct bitcoin_swapinfo *swap = 0; bits256 hash; + struct iguana_info *coinbtc,*altcoin; cJSON *newjson=0; uint8_t pubkey[33]; + if ( exchange == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap null exchange ptr\"}")); + offerdir = instantdex_bidaskdir(A); + coinbtc = iguana_coinfind("BTC"); + if ( (altcoin= iguana_coinfind(A->A.base)) == 0 || coinbtc == 0 ) + { + printf("other.%p coinbtc.%p (%s/%s)\n",altcoin,coinbtc,A->A.base,A->A.rel); + return(clonestr("{\"error\":\"instantdex_BTCswap cant find btc or other coin info\"}")); + } + reftime = (uint32_t)(A->A.expiration - INSTANTDEX_LOCKTIME*2); + if ( strcmp(A->A.rel,"BTC") != 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap offer non BTC rel\"}")); + vcalc_sha256(0,hash.bytes,(void *)&A->A,sizeof(ap->A)); + if ( hash.txid != A->orderid ) + return(clonestr("{\"error\":\"txid mismatches orderid\"}")); + satoshis[0] = A->A.basevolume64; + satoshis[1] = instantdex_relsatoshis(A->A.price64,A->A.basevolume64); + swap = A->info; + if ( swap == 0 && strcmp(cmdstr,"offer") != 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap no swap info after offer\"}")); + printf("got offer.(%s) offerside.%d offerdir.%d swap.%p\n",jprint(argjson,0),A->A.myside,A->A.acceptdir,A->info); + if ( strcmp(cmdstr,"offer") == 0 && A->info == 0 ) // sender is Bob, receiver is network (Alice) + { + if ( A->A.expiration < (time(NULL) + INSTANTDEX_DURATION) ) + return(clonestr("{\"error\":\"instantdex_BTCswap offer too close to expiration\"}")); + if ( (ap= instantdex_acceptable(myinfo,exchange,A,myinfo->myaddr.nxt64bits)) != 0 ) { - spend->input_satoshis += up->value; - spend->inputs[spend->numinputs++] = *up; - if ( spend->input_satoshis >= satoshis ) + printf("FOUND MATCH! %p (%s/%s)\n",A->info,A->A.base,A->A.rel); + if ( A->info == 0 ) { - spend->netamount = (spend->input_satoshis - spend->txfee - donation); - spend->change = (spend->input_satoshis - spend->netamount); - printf("numinputs %d sum %.8f vs satoshis %.8f change %.8f -> txfee %.8f\n",spend->numinputs,dstr(spend->input_satoshis),dstr(satoshis),dstr(spend->change),dstr(spend->input_satoshis - spend->change - spend->netamount)); - break; + swap = calloc(1,sizeof(struct bitcoin_swapinfo)); + swap->choosei = swap->otherschoosei = -1; + swap->state++; } - remains -= up->value; - } else break; + if ( (A->info= swap) != 0 ) + { + if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,1,0)) == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap offer null newjson\"}")); + else + { + //printf("NEWJSON.(%s)\n",jprint(newjson,0)); + instantdex_pendingnotice(myinfo,exchange,ap,A); + if ( (retstr= instantdex_choosei(swap,argjson,newjson)) != 0 ) + { + printf("Choosei.%s\n",retstr); + return(retstr); + } + else return(instantdex_sendcmd(myinfo,newjson,"BTCstep1",myinfo->ipaddr,INSTANTDEX_HOPS)); + } + } + } + else + { + printf("no matching trade.(%s) -> InstantDEX_minaccept\n",jprint(argjson,0)); + retstr = instantdex_queueaccept(myinfo,exchange,A->A.base,A->A.rel,dstr(A->A.price64),dstr(A->A.basevolume64),A->A.acceptdir,A->A.myside == 0 ? A->A.base : A->A.rel,A->A.expiration); + } + } + else if ( strcmp(cmdstr,"step1") == 0 && swap->state == 1 ) // either + { + printf("got step1, should have other's choosei\n"); + if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,1)) == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap step1 null newjson\"}")); + else if ( swap->otherschoosei < 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap step1, no didnt choosei\"}")); + else + { + swap->state++; + if ( (retstr= instantdex_choosei(swap,argjson,newjson)) != 0 ) + return(retstr); + if ( swap->isbob == 0 ) + { + int64_t insurance = (satoshis[1] * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee prevents dust attack + if ( (swap->feetx= instantdex_bobtx(myinfo,coinbtc,&swap->ftxid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->otherschoosei],reftime,insurance,1)) != 0 ) + { + jaddstr(newjson,"feetx",swap->feetx); + jaddbits256(newjson,"ftxid",swap->ftxid); + // broadcast to network + } + } + return(instantdex_sendcmd(myinfo,newjson,swap->isbob != 0 ? "BTCstep1" : "BTCstep2",myinfo->ipaddr,INSTANTDEX_HOPS)); + } } - if ( spend->input_satoshis >= (satoshis + spend->txfee) ) + else if ( strcmp(cmdstr,"step2") == 0 && swap->isbob != 0 && swap->state == 2 ) // Bob { - spend = realloc(spend,sizeof(*spend) + sizeof(*spend->inputs) * spend->numinputs); - return(spend); + printf("got step2, should have other's privkeys\n"); + if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,0)) == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap step2 null newjson\"}")); + else if ( swap->cutverified == 0 || swap->otherverifiedcut == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap step2, both sides didnt validate\"}")); + else //if ( instantdex_feeverify() == 0 ) + { + swap->state++; + //char *instantdex_bobtx(myinfo,coin,&paytxid,pubA0,pubB0,privAm,reftime,relsatoshis,0); + if ( (swap->deposit= instantdex_bobtx(myinfo,coinbtc,&swap->dtxid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->otherschoosei],reftime,satoshis[swap->isbob],1)) != 0 ) + { + jaddstr(newjson,"deposit",swap->deposit); + jaddbits256(newjson,"dtxid",swap->dtxid); + jaddbits256(newjson,"pubBn",bitcoin_pubkey33(pubkey,swap->privkeys[swap->otherschoosei])); + // broadcast to network + return(instantdex_sendcmd(myinfo,newjson,"BTCstep3",myinfo->ipaddr,INSTANTDEX_HOPS)); + } else return(clonestr("{\"error\":\"instantdex_BTCswap Bob step2, cant create deposit\"}")); + } //else return(clonestr("{\"error\":\"instantdex_BTCswap step2 invalid fee\"}")); } - else + else if ( strcmp(cmdstr,"step3") == 0 && swap->isbob == 0 && swap->state == 2 ) // Alice { - free(spend); - return(0); + printf("Alice got step3 should have Bob's choosei\n"); + if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,0)) == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap Alice step3 null newjson\"}")); + else if ( swap->cutverified == 0 || swap->otherverifiedcut == 0 || bits256_nonz(swap->pubBn) == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap step3, both sides didnt validate\"}")); + else if ( instantdex_paymentverify(myinfo,coinbtc,swap,A,argjson,1) == 0 ) + { + swap->state++; + //char *instantdex_alicetx(myinfo,altcoin,&alicetxid,pubAm,pubBn,satoshis); + swap->pubAm = bitcoin_pubkey33(pubkey,swap->privkeys[swap->otherschoosei]); + if ( (swap->altpayment= instantdex_alicetx(myinfo,altcoin,swap->altmsigaddr,&swap->aptxid,swap->pubAm,swap->pubBn,satoshis[swap->isbob])) != 0 ) + { + jaddstr(newjson,"altpayment",swap->altpayment); + jaddstr(newjson,"altmsigaddr",swap->altmsigaddr); + jaddbits256(newjson,"aptxid",swap->aptxid); + jaddbits256(newjson,"pubAm",swap->pubAm); + // broadcast to network + return(instantdex_sendcmd(myinfo,newjson,"BTCstep4",myinfo->ipaddr,INSTANTDEX_HOPS)); + } else return(clonestr("{\"error\":\"instantdex_BTCswap Alice step3, error making altpay\"}")); + } else return(clonestr("{\"error\":\"instantdex_BTCswap Alice step3, invalid deposit\"}")); + } + else if ( strcmp(cmdstr,"step4") == 0 && swap->isbob != 0 && swap->state == 3 ) // Bob + { + printf("Bob got step4 should have Alice's altpayment\n"); + if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,0)) == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap Bob step4 null newjson\"}")); + else if ( bits256_nonz(swap->pubAm) == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap step4, no pubAm\"}")); + else if ( instantdex_altpaymentverify(myinfo,altcoin,swap,A,argjson) == 0 ) + { + swap->state++; + if ( (swap->deposit= instantdex_bobtx(myinfo,coinbtc,&swap->ptxid,swap->mypubs[1],swap->otherpubs[0],swap->privkeys[swap->otherschoosei],reftime,satoshis[swap->isbob],0)) != 0 ) + { + jaddstr(newjson,"payment",swap->payment); + jaddbits256(newjson,"ptxid",swap->ptxid); + // broadcast to network + return(instantdex_sendcmd(myinfo,newjson,"BTCstep5",myinfo->ipaddr,INSTANTDEX_HOPS)); + } else return(clonestr("{\"error\":\"instantdex_BTCswap Bob step4, cant create payment\"}")); + } else return(clonestr("{\"error\":\"instantdex_BTCswap Alice step3, invalid deposit\"}")); + } + else if ( strcmp(cmdstr,"step5") == 0 && swap->isbob == 0 && swap->state == 4 ) // Alice + { + printf("Alice got step5 should have Bob's payment\n"); + if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,0)) == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap Alice step5 null newjson\"}")); + else if ( instantdex_paymentverify(myinfo,coinbtc,swap,A,argjson,0) == 0 ) + { + swap->state++; + /*if ( (swap->spendtx= instantdex_spendpayment(myinfo,coinbtc,&swap->stxid,swap,argjson,newjson)) != 0 ) + { + // broadcast to network + return(instantdex_sendcmd(myinfo,newjson,"BTCstep6",myinfo->ipaddr,INSTANTDEX_HOPS)); + } else return(clonestr("{\"error\":\"instantdex_BTCswap Alice step5, cant spend payment\"}"));*/ + } else return(clonestr("{\"error\":\"instantdex_BTCswap Bob step6, invalid payment\"}")); } + else if ( strcmp(cmdstr,"step6") == 0 ) // Bob + { + printf("Bob got step6 should have Alice's privkey\n"); + if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,0)) == 0 ) + return(clonestr("{\"error\":\"instantdex_BTCswap Bob step6 null newjson\"}")); + /*else if ( instantdex_spendverify(myinfo,coinbtc,swap,A,argjson,0) == 0 ) + { + if ( (swap->altspend= instantdex_spendaltpayment(myinfo,altcoin,&swap->astxid,swap,argjson,newjson)) != 0 ) + { + jaddstr(newjson,"altspend",swap->altspend); + jaddbits256(newjson,"astxid",swap->astxid); + // broadcast to network + return(clonestr("{\"result\":\"Bob finished atomic swap\"}")); + } else return(clonestr("{\"error\":\"instantdex_BTCswap Bob step6, cant spend altpayment\"}")); + } else return(clonestr("{\"error\":\"instantdex_BTCswap Bob step6, invalid spend\"}"));*/ + } + else retstr = clonestr("{\"error\":\"BTC swap got unrecognized command\"}"); + if ( retstr == 0 ) + retstr = clonestr("{\"error\":\"BTC swap null retstr\"}"); + if ( swap != 0 ) + printf("BTCSWAP.(%s) isbob.%d state.%d verified.(%d %d)\n",retstr,swap->isbob,swap->state,swap->cutverified,swap->otherverifiedcut); + else printf("BTCSWAP.(%s)\n",retstr); + return(retstr); +} + +#ifdef oldway +// https://github.com/TierNolan/bips/blob/bip4x/bip-atom.mediawiki + +int32_t bitcoin_2of2spendscript(int32_t *paymentlenp,uint8_t *paymentscript,uint8_t *msigscript,bits256 pub0,bits256 pub1) +{ + struct vin_info V; uint8_t p2sh_rmd160[20]; int32_t p2shlen; + memset(&V,0,sizeof(V)); + V.M = V.N = 2; + memcpy(V.signers[0].pubkey+1,pub0.bytes,sizeof(pub0)), V.signers[0].pubkey[0] = 0x02; + memcpy(V.signers[1].pubkey+1,pub1.bytes,sizeof(pub1)), V.signers[1].pubkey[0] = 0x03; + p2shlen = bitcoin_MofNspendscript(p2sh_rmd160,msigscript,0,&V); + *paymentlenp = bitcoin_p2shspend(paymentscript,0,p2sh_rmd160); + return(p2shlen); } /* -Name: Bob.Bail.In + Name: Bob.Bail.In Input value: B + 2*fb + change Input source: (From Bob's coins, multiple inputs are allowed) vout0 value: B, ScriptPubKey 0: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL vout1 value: fb, ScriptPubKey 1: OP_HASH160 Hash160(x) OP_EQUALVERIFY pub-A1 OP_CHECKSIG vout2 value: change, ScriptPubKey 2: <= 100 bytes P2SH Redeem: OP_2 pub-A1 pub-B1 OP_2 OP_CHECKMULTISIG -Name: Alice.Bail.In + Name: Alice.Bail.In vins: A + 2*fa + change, Input source: (From Alice's altcoins, multiple inputs are allowed) vout0 value: A, ScriptPubKey 0: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL vout1 value: fa, ScriptPubKey 1: OP_HASH160 Hash160(x) OP_EQUAL vout2 value: change, ScriptPubKey 2: <= 100 bytes -*/ + */ char *instantdex_bailintx(struct iguana_info *coin,bits256 *txidp,struct bitcoin_spend *spend,bits256 A0,bits256 B0,uint8_t x[20],int32_t isbob) { uint64_t change; char *rawtxstr,*signedtx; struct vin_info *V; bits256 txid,signedtxid; @@ -211,12 +742,11 @@ char *instantdex_bailintx(struct iguana_info *coin,bits256 *txidp,struct bitcoin cJSON *instantdex_bailinspend(struct iguana_info *coin,bits256 privkey,uint64_t amount) { - bits256 hash; int32_t n; cJSON *txobj; + int32_t n; cJSON *txobj; int32_t scriptv0len; uint8_t p2shscript[256],rmd160[20],scriptv0[128],pubkey[35]; bitcoin_pubkey33(pubkey,privkey); n = bitcoin_pubkeyspend(p2shscript,0,pubkey); - vcalc_sha256(0,hash.bytes,p2shscript,n); - calc_rmd160(0,rmd160,hash.bytes,sizeof(hash.bytes)); + calc_rmd160_sha256(rmd160,p2shscript,n); scriptv0len = bitcoin_p2shspend(scriptv0,0,rmd160); txobj = bitcoin_createtx(coin,0); bitcoin_addoutput(coin,txobj,scriptv0,scriptv0len,amount); @@ -224,16 +754,16 @@ cJSON *instantdex_bailinspend(struct iguana_info *coin,bits256 privkey,uint64_t } /* -Name: Bob.Payout -vin0: A, Input source: Alice.Bail.In:0 -vin1: fa, Input source: Alice.Bail.In:1 -vout0: A, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-B2 OP_CHECKSIG + Name: Bob.Payout + vin0: A, Input source: Alice.Bail.In:0 + vin1: fa, Input source: Alice.Bail.In:1 + vout0: A, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-B2 OP_CHECKSIG Name: Alice.Payout -vin0: B, Input source: Bob.Bail.In:0 -vin1: fb, Input source: Bob.Bail.In:1 -vout0: B, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-A2 OP_CHECKSIG -*/ + vin0: B, Input source: Bob.Bail.In:0 + vin1: fb, Input source: Bob.Bail.In:1 + vout0: B, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-A2 OP_CHECKSIG + */ char *instantdex_bailinsign(struct iguana_info *coin,bits256 bailinpriv,char *sigstr,int32_t *siglenp,bits256 *txidp,struct vin_info *V,cJSON *txobj,int32_t isbob) { @@ -252,7 +782,6 @@ char *instantdex_bailinsign(struct iguana_info *coin,bits256 bailinpriv,char *si return(signedtx); } - char *instantdex_payouttx(struct iguana_info *coin,char *sigstr,int32_t *siglenp,bits256 *txidp,bits256 *sharedprivs,bits256 bailintxid,int64_t amount,int64_t txfee,int32_t isbob,char *othersigstr) { struct vin_info V; cJSON *txobj; @@ -270,16 +799,16 @@ char *instantdex_payouttx(struct iguana_info *coin,char *sigstr,int32_t *siglenp } /* -Name: Alice.Refund -vin0: A, Input source: Alice.Bail.In:0 -vout0: A - fa, ScriptPubKey: OP_HASH160 Hash160(P2SH) OP_EQUAL; P2SH Redeem: pub-A3 OP_CHECKSIG -Locktime: current block height + ((T/2)/(altcoin block rate)) + Name: Alice.Refund + vin0: A, Input source: Alice.Bail.In:0 + vout0: A - fa, ScriptPubKey: OP_HASH160 Hash160(P2SH) OP_EQUAL; P2SH Redeem: pub-A3 OP_CHECKSIG + Locktime: current block height + ((T/2)/(altcoin block rate)) -Name: Bob.Refund -vin0: B, Input source: Bob.Bail.In:0 -vout0: B - fb, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-B3 OP_CHECKSIG -Locktime: (current block height) + (T / 10 minutes) -*/ + Name: Bob.Refund + vin0: B, Input source: Bob.Bail.In:0 + vout0: B - fb, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-B3 OP_CHECKSIG + Locktime: (current block height) + (T / 10 minutes) + */ char *instantdex_refundtx(struct iguana_info *coin,bits256 *txidp,bits256 bailinpriv,bits256 priv2,bits256 bailintxid,int64_t amount,int64_t txfee,int32_t isbob) { char sigstr[256]; int32_t siglen; struct vin_info V; cJSON *txobj; @@ -290,70 +819,14 @@ char *instantdex_refundtx(struct iguana_info *coin,bits256 *txidp,bits256 bailin int32_t instantdex_calcx20(char hexstr[41],uint8_t *p2shscript,uint8_t firstbyte,bits256 pub) { - uint8_t pubkey[33],rmd160[20]; int32_t n; bits256 hash; + uint8_t pubkey[33],rmd160[20]; int32_t n; memcpy(pubkey+1,pub.bytes,sizeof(pub)), pubkey[0] = firstbyte; n = bitcoin_pubkeyspend(p2shscript,0,pubkey); - vcalc_sha256(0,hash.bytes,p2shscript,n); - calc_rmd160(0,rmd160,hash.bytes,sizeof(hash.bytes)); + calc_rmd160_sha256(rmd160,p2shscript,n); init_hexbytes_noT(hexstr,rmd160,sizeof(rmd160)); return(n); } -char *instantdex_btcoffer(struct supernet_info *myinfo,struct exchange_info *exchange,char *othercoin,double othervolume,double maxprice) // Bob sending to network (Alice) -{ - char *str,coinaddr[64],xstr[41]; uint8_t xscript[64]; struct iguana_info *other; int32_t isbob = 1; - struct instantdex_accept checkA,A; cJSON *newjson; bits256 hash,pub3,sharedprivs[4]; - if ( othercoin == 0 || (other= iguana_coinfind(othercoin)) == 0 ) - return(clonestr("{\"error\":\"invalid othercoin\"}")); - hash = instantdex_acceptset(&A,othercoin,"BTC",INSTANTDEX_OFFERDURATION,1,-1,maxprice,othervolume,myinfo->myaddr.nxt64bits); - newjson = instantdex_acceptsendjson(&A); - if ( instantdex_acceptextract(&checkA,newjson) < 0 ) - { - int32_t i; - for (i=0; ipersistent_priv,hash,0x02+isbob) != 4 ) - return(clonestr("{\"error\":\"highly unlikely run of 02 pubkeys\"}")); - pub3 = jbits256(newjson,"B3"); - jdelete(newjson,"B3"); - instantdex_calcx20(xstr,xscript,0x02+isbob,pub3); - jaddstr(newjson,"x",xstr); - if ( coinaddr[0] != 0 ) - jaddstr(newjson,othercoin,coinaddr); - if ( maxprice > 0. ) - { - if ( (str= InstantDEX_maxaccept(myinfo,0,newjson,0,othercoin,"BTC",maxprice,othervolume)) != 0 ) - free(str); - } - return(instantdex_sendcmd(myinfo,newjson,"BTCoffer",myinfo->ipaddr,INSTANTDEX_HOPS)); -} - -void instantdex_pendingnotice(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,struct instantdex_accept *A) -{ - printf("need to start monitoring thread\n"); - ap->pendingvolume64 -= A->A.basevolume64; -} - -cJSON *instantdex_newjson(struct supernet_info *myinfo,bits256 *A0p,bits256 *B0p,bits256 *sharedprivs,uint8_t secret160[20],int32_t isbob,cJSON *argjson,bits256 hash,struct instantdex_accept *A) -{ - cJSON *newjson; char *xstr; - newjson = instantdex_acceptsendjson(A); - if ( instantdex_pubkeyargs(sharedprivs,newjson,3+isbob,myinfo->persistent_priv,hash,0x02+isbob) != 3 ) - return(0); - if ( isbob == 0 ) - *A0p = jbits256(newjson,"A0"); - else *A0p = jbits256(argjson,"A0"); - *B0p = jbits256(argjson,"B0"); - if ( (xstr= jstr(argjson,"x")) != 0 ) - { - decode_hex(secret160,20,xstr); - jaddstr(newjson,"x",xstr); - } - return(newjson); -} - char *instantdex_bailinrefund(struct supernet_info *myinfo,struct iguana_info *coin,struct exchange_info *exchange,struct instantdex_accept *A,char *nextcmd,uint8_t secret160[20],cJSON *newjson,int32_t isbob,bits256 A0,bits256 B0,bits256 *sharedprivs) { struct bitcoin_spend *spend; char *bailintx,*refundtx,field[64]; bits256 bailintxid,refundtxid; @@ -416,8 +889,11 @@ char *instantdex_BTCswap(struct supernet_info *myinfo,struct exchange_info *exch return(clonestr("{\"error\":\"instantdex_BTCswap null exchange ptr\"}")); offerdir = instantdex_bidaskdir(A); if ( (other= iguana_coinfind(A->A.base)) == 0 || (coinbtc= iguana_coinfind("BTC")) == 0 ) + { + printf("other.%p coinbtc.%p (%s/%s)\n",other,coinbtc,A->A.base,A->A.rel); return(clonestr("{\"error\":\"instantdex_BTCswap cant find btc or other coin info\"}")); - locktime = (uint32_t)(A->A.expiration + INSTANTDEX_OFFERDURATION); + } + locktime = (uint32_t)(A->A.expiration + INSTANTDEX_LOCKTIME); if ( strcmp(A->A.rel,"BTC") != 0 ) return(clonestr("{\"error\":\"instantdex_BTCswap offer non BTC rel\"}")); vcalc_sha256(0,hash.bytes,(void *)&A->A,sizeof(ap->A)); @@ -454,7 +930,7 @@ char *instantdex_BTCswap(struct supernet_info *myinfo,struct exchange_info *exch isbob = 1; newjson = instantdex_payout(myinfo,coinbtc,exchange,A,secret160,isbob,&A0,&B0,sharedprivs,hash,satoshis,argjson); return(instantdex_bailinrefund(myinfo,coinbtc,exchange,A,"BTCaccept",secret160,newjson,isbob,A0,B0,sharedprivs)); - } + } else if ( strcmp(cmdstr,"accept") == 0 ) // sender is Bob, receiver is Alice { isbob = 0; @@ -489,3 +965,6 @@ char *instantdex_BTCswap(struct supernet_info *myinfo,struct exchange_info *exch retstr = clonestr("{\"error\":\"BTC swap null retstr\"}"); return(retstr); } + +#endif + diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index ac259c825..3d854778f 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -17,11 +17,12 @@ STRING_ARG(SuperNET,bitcoinrpc,setcoin); ZERO_ARGS(SuperNET,myipaddr); STRING_ARG(SuperNET,setmyipaddr,ipaddr); -TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,BTCoffer,othercoin,otherassetid,maxprice,othervolume); 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,BTCoffer,othercoin,otherassetid,maxprice,othervolume); STRING_AND_TWO_DOUBLES(InstantDEX,ALToffer,basecoin,minprice,basevolume); -STRING_AND_TWO_DOUBLES(InstantDEX,NXToffer,assetid,minprice,basevolume); +STRING_AND_TWO_DOUBLES(InstantDEX,NXToffer,assetid,minprice,basevolume);*/ HASH_AND_STRING(ramchain,verifytx,txid,txbytes); INT_ARG(ramchain,getblockhash,height); @@ -94,6 +95,7 @@ THREE_STRINGS(SuperNET,rosetta,passphrase,pin,showprivkey); ZERO_ARGS(SuperNET,keypair); HASH_AND_INT(SuperNET,priv2pub,privkey,addrtype); STRING_ARG(SuperNET,wif2priv,wif); +STRING_ARG(SuperNET,addr2rmd160,address); TWOHASHES_AND_STRING(SuperNET,cipher,privkey,destpubkey,message); TWOHASHES_AND_STRING(SuperNET,decipher,privkey,srcpubkey,cipherstr);