diff --git a/basilisk/basilisk.c b/basilisk/basilisk.c index b15ee8d35..dfd7f7bb5 100755 --- a/basilisk/basilisk.c +++ b/basilisk/basilisk.c @@ -15,9 +15,7 @@ #include "../iguana/iguana777.h" -//typedef char *basilisk_coinfunc(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen); typedef char *basilisk_servicefunc(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk); -//typedef struct basilisk_item *basilisk_requestfunc(struct basilisk_item *Lptr,struct supernet_info *myinfo,bits256 hash,cJSON *valsobj,uint8_t *data,int32_t datalen); uint32_t basilisk_calcnonce(struct supernet_info *myinfo,uint8_t *data,int32_t datalen,uint32_t nBits) { @@ -132,6 +130,13 @@ struct basilisk_item *basilisk_itemcreate(struct supernet_info *myinfo,char *CMD return(ptr); } +int32_t basilisk_specialrelay_CMD(char *CMD) +{ + if ( strcmp(CMD,"BLK") == 0 || strcmp(CMD,"MEM") == 0 || strcmp(CMD,"GTX") == 0 || strcmp(CMD,"OUT") == 0 || strcmp(CMD,"MSG") == 0 ) + return(1); + else return(0); +} + int32_t basilisk_sendcmd(struct supernet_info *myinfo,char *destipaddr,char *type,uint32_t *basilisktagp,int32_t encryptflag,int32_t delaymillis,uint8_t *data,int32_t datalen,int32_t fanout,uint32_t nBits) // data must be offset by sizeof(iguana_msghdr)+sizeof(basilisktag) { int32_t i,r,l,s,val,n=0,retval = -1; char cmd[12]; struct iguana_info *coin,*tmp; struct iguana_peer *addr; bits256 hash; uint32_t *alreadysent; @@ -187,7 +192,7 @@ int32_t basilisk_sendcmd(struct supernet_info *myinfo,char *destipaddr,char *typ printf("%s %s s.%d vs n.%d iguana.%d\n",coin->symbol,addr->ipaddr,s,n,addr->supernet); if ( addr->usock >= 0 ) { - if ( strcmp(type,"BLK") == 0 ) + if ( basilisk_specialrelay_CMD(type) > 0 ) { for (s=0; snumrelays; s++) if ( addr->ipbits != myinfo->myaddr.myipbits && myinfo->relays[s].ipbits == addr->ipbits ) @@ -204,7 +209,7 @@ int32_t basilisk_sendcmd(struct supernet_info *myinfo,char *destipaddr,char *typ continue; if ( s == n && (addr->supernet != 0 || addr->basilisk != 0) && (destipaddr == 0 || strcmp(addr->ipaddr,destipaddr) == 0) ) { - //printf("i.%d l.%d [%s].tag%d send %s.(%s) [%x] datalen.%d addr->supernet.%u basilisk.%u to (%s).%d destip.%s\n",i,l,cmd,*(uint32_t *)data,type,(char *)&data[4],*(int32_t *)&data[datalen-4],datalen,addr->supernet,addr->basilisk,addr->ipaddr,addr->A.port,destipaddr!=0?destipaddr:"broadcast"); + printf("i.%d l.%d [%s].tag%d send %s.(%s) [%x] datalen.%d addr->supernet.%u basilisk.%u to (%s).%d destip.%s\n",i,l,cmd,*(uint32_t *)data,type,(char *)&data[4],*(int32_t *)&data[datalen-4],datalen,addr->supernet,addr->basilisk,addr->ipaddr,addr->A.port,destipaddr!=0?destipaddr:"broadcast"); if ( encryptflag != 0 && bits256_nonz(addr->pubkey) != 0 ) { void *ptr; uint8_t *cipher,space[8192]; int32_t cipherlen; bits256 privkey; @@ -548,9 +553,9 @@ void basilisk_msgprocess(struct supernet_info *myinfo,void *_addr,uint32_t sende // gecko chains { (void *)"GET", &basilisk_respond_geckoget }, // requests headers, block or tx { (void *)"HDR", &basilisk_respond_geckoheaders }, // reports headers - { (void *)"BLK", &basilisk_respond_geckoblock }, // reports block - { (void *)"MEM", &basilisk_respond_mempool }, // reports mempool - { (void *)"GTX", &basilisk_respond_geckotx }, // reports tx + { (void *)"BLK", &basilisk_respond_geckoblock }, // reports virtchain block + { (void *)"MEM", &basilisk_respond_mempool }, // reports virtchain mempool + { (void *)"GTX", &basilisk_respond_geckotx }, // reports virtchain tx { (void *)"ADD", &basilisk_respond_addrelay }, // relays register with each other bus { (void *)"DEX", &basilisk_respond_DEX }, @@ -761,7 +766,7 @@ void basilisks_loop(void *arg) } } portable_mutex_unlock(&myinfo->messagemutex); - usleep(100000); + usleep(1000000); } } diff --git a/basilisk/basilisk.h b/basilisk/basilisk.h index 5b95792bd..04f8b19b8 100755 --- a/basilisk/basilisk.h +++ b/basilisk/basilisk.h @@ -32,7 +32,7 @@ #define INSTANTDEX_DECKSIZE 777 #define INSTANTDEX_LOCKTIME (7200 + 600*2) #define INSTANTDEX_INSURANCEDIV ((7 * INSTANTDEX_DECKSIZE) >> 3) -#define INSTANTDEX_PUBEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" +#define INSTANTDEX_PUBKEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" #define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" #define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" #define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" @@ -50,12 +50,15 @@ struct basilisk_request bits256 desthash; } __attribute__((packed)); -struct bitcoin_statetx +struct basilisk_rawtx { - bits256 txid; + bits256 txid,actualtxid; + struct iguana_info *coin; uint64_t amount,change,inputsum; - char destaddr[64]; - char txbytes[]; + int32_t datalen,vintype,vouttype,numconfirms,spendlen,secretstart; + uint32_t locktime; + char destaddr[64]; uint8_t addrtype,pubkey33[33],rmd160[20],spendscript[512]; + uint8_t *txbytes; }; struct basilisk_swap @@ -72,7 +75,7 @@ struct basilisk_swap int32_t choosei,otherchoosei,cutverified,otherverifiedcut,numpubs,havestate,otherhavestate; uint8_t secretAm[20],secretBn[20]; - struct bitcoin_statetx *deposit,*payment,*alicepayment,*myfee,*otherfee,*reclaim; + struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,alicereclaim,alicespend,bobreclaim,bobspend; }; struct basilisk_value { bits256 txid; int64_t value; int32_t height; int16_t vout; char coinaddr[64]; }; diff --git a/basilisk/basilisk_DEX.c b/basilisk/basilisk_DEX.c index a5ee67ab3..922f252c1 100755 --- a/basilisk/basilisk_DEX.c +++ b/basilisk/basilisk_DEX.c @@ -452,7 +452,7 @@ ZERO_ARGS(InstantDEX,allcoins) STRING_ARG(InstantDEX,available,source) { - if ( (coin= iguana_coinfind(source)) != 0 ) + if ( source != 0 && source[0] != 0 && (coin= iguana_coinfind(source)) != 0 ) { if ( myinfo->expiration != 0 ) return(bitcoinrpc_getbalance(myinfo,coin,json,remoteaddr,"*",coin->chain->minconfirms,1,1<<30)); @@ -473,6 +473,12 @@ HASH_ARRAY_STRING(InstantDEX,request,hash,vals,hexstr) return(basilisk_standardservice("DEX",myinfo,0,myinfo->myaddr.persistent,vals,"",1)); } +INT_ARG(InstantDEX,automatched,requestid) +{ + // return quoteid + return(clonestr("{\"result\":\"automatched not yet\"}")); +} + INT_ARG(InstantDEX,incoming,requestid) { cJSON *vals; char *retstr; diff --git a/basilisk/basilisk_MSG.c b/basilisk/basilisk_MSG.c index f471424ba..f1f82834f 100755 --- a/basilisk/basilisk_MSG.c +++ b/basilisk/basilisk_MSG.c @@ -148,7 +148,7 @@ HASH_ARRAY_STRING(basilisk,getmessage,hash,vals,hexstr) HASH_ARRAY_STRING(basilisk,sendmessage,hash,vals,hexstr) { - return(basilisk_standardservice("OUT",myinfo,0,myinfo->myaddr.persistent,vals,hexstr,1)); + return(basilisk_standardservice("OUT",myinfo,0,hash,vals,hexstr,1)); } #include "../includes/iguana_apiundefs.h" diff --git a/basilisk/basilisk_bitcoin.c b/basilisk/basilisk_bitcoin.c index 2bc997ea1..7f82c770b 100755 --- a/basilisk/basilisk_bitcoin.c +++ b/basilisk/basilisk_bitcoin.c @@ -649,117 +649,66 @@ void *basilisk_bitcoinrawtx(struct basilisk_item *Lptr,struct supernet_info *myi return(basilisk_issueremote(myinfo,0,&numsent,"RAW",coin->symbol,1,valsobj,juint(valsobj,"fanout"),juint(valsobj,"minresults"),basilisktag,timeoutmillis,coin->basilisk_rawtxmetric,0,0,0,BASILISK_DEFAULTDIFF)); } -#ifdef later -int32_t instantdex_outputinsurance(char *coinaddr,uint8_t addrtype,uint8_t *script,int64_t insurance,uint64_t r,uint64_t dest) -{ - uint8_t rmd160[20]; int32_t n = 0; - decode_hex(rmd160,sizeof(rmd160),(dest % 10) == 9 ? TIERNOLAN_RMD160 : INSTANTDEX_RMD160); - //script[n++] = sizeof(r); - //n += iguana_rwnum(1,&script[n],sizeof(r),&r); - //script[n++] = SCRIPT_OP_DROP; - bitcoin_address(coinaddr,addrtype,rmd160,20); - n = bitcoin_standardspend(script,n,rmd160); - return(n); -} +#define SCRIPT_OP_IF 0x63 +#define SCRIPT_OP_ELSE 0x67 +#define SCRIPT_OP_ENDIF 0x68 -void iguana_addinputs(struct iguana_info *coin,struct bitcoin_spend *spend,cJSON *txobj,uint32_t sequence) +int32_t basilisk_bobscript(uint8_t *script,int32_t n,uint32_t *locktimep,int32_t *secretstartp,struct basilisk_swap *swap,int32_t depositflag) { - int32_t i,j,plen; uint8_t *pubkeyptrs[16]; - for (i=0; inuminputs; i++) - { - spend->inputs[i].sequence = sequence; - for (j=0; j<16; j++) - { - if ( (plen= bitcoin_pubkeylen(spend->inputs[i].pubkeys[j])) < 0 ) - break; - pubkeyptrs[j] = spend->inputs[i].pubkeys[j]; - } - bitcoin_txinput(coin,txobj,spend->inputs[i].txid,spend->inputs[i].vout,spend->inputs[i].sequence,spend->inputs[i].spendscript,spend->inputs[i].spendlen,spend->inputs[i].p2shscript,spend->inputs[i].p2shlen,j>0?pubkeyptrs:0,j); + uint8_t pubkeyA[33],pubkeyB[33],*secret160; bits256 cltvpub,destpub; int32_t i; + *locktimep = swap->locktime; + if ( depositflag != 0 ) + { + *locktimep += INSTANTDEX_LOCKTIME; + cltvpub = swap->pubA0; + destpub = swap->pubB0; + secret160 = swap->secretBn; + pubkeyA[0] = 0x02; + pubkeyB[0] = 0x03; } -} - -struct bitcoin_statetx *instantdex_signtx(char *str,struct supernet_info *myinfo,struct iguana_info *coin,uint32_t locktime,char *scriptstr,int64_t satoshis,int64_t txfee,int32_t minconf,int32_t myside) -{ - struct iguana_waddress *waddr; struct iguana_waccount *wacct; struct bitcoin_statetx *tx=0; char coinaddr[64],wifstr[64]; char *rawtx=0,*signedtx,*retstr; bits256 signedtxid; uint32_t basilisktag; int32_t flag,completed; cJSON *valsobj,*vins=0,*retjson=0,*privkey,*addresses; - if ( (waddr= iguana_getaccountaddress(myinfo,coin,0,0,coin->changeaddr,"change")) == 0 ) - { - printf("no change addr error\n"); - return(0); - } - privkey = cJSON_CreateArray(); - addresses = cJSON_CreateArray(); - if ( coin->changeaddr[0] == 0 ) - bitcoin_address(coin->changeaddr,coin->chain->pubtype,waddr->rmd160,20); - //bitcoin_pubkey33(myinfo->ctx,pubkey33,myinfo->persistent_priv); - bitcoin_address(coinaddr,coin->chain->pubtype,myinfo->persistent_pubkey33,33); - //printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr); - if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 ) + else { - bitcoin_priv2wif(wifstr,waddr->privkey,coin->chain->wiftype); - jaddistr(privkey,waddr->wifstr); + cltvpub = swap->pubB1; + destpub = swap->pubA0; + secret160 = swap->secretAm; + pubkeyA[0] = 0x03; + pubkeyB[0] = 0x02; } - basilisktag = (uint32_t)rand(); - jaddistr(addresses,coinaddr); - valsobj = cJSON_CreateObject(); - jadd(valsobj,"addresses",addresses); - jaddstr(valsobj,"coin",coin->symbol); - jaddstr(valsobj,"spendscript",scriptstr); - jaddstr(valsobj,"changeaddr",coin->changeaddr); - jadd64bits(valsobj,"satoshis",satoshis); - jadd64bits(valsobj,"txfee",txfee); - jaddnum(valsobj,"minconf",minconf); - jaddnum(valsobj,"basilisktag",basilisktag); - jaddnum(valsobj,"locktime",locktime); - jaddnum(valsobj,"timeout",30000); - if ( (retstr= basilisk_rawtx(myinfo,coin,0,0,myinfo->myaddr.persistent,valsobj,"")) != 0 ) - { - //printf("%s got.(%s)\n",str,retstr); - flag = 0; - if ( (retjson= cJSON_Parse(retstr)) != 0 ) - { - if ( (rawtx= jstr(retjson,"rawtx")) != 0 && (vins= jobj(retjson,"vins")) != 0 ) - flag = 1; - else printf("missing rawtx.%p or vins.%p\n",rawtx,vins); - } else printf("error parsing.(%s)\n",retstr); - if ( flag != 0 && vins != 0 ) - { - //printf("vins.(%s)\n",jprint(vins,0)); - if ( (signedtx= iguana_signrawtx(myinfo,coin,&signedtxid,&completed,vins,rawtx,privkey)) != 0 ) - { - iguana_unspentslock(myinfo,coin,vins); - tx = calloc(1,sizeof(*tx) + strlen(signedtx) + 1); - strcpy(tx->txbytes,signedtx); - tx->txid = signedtxid; - printf("%s %s.%s\n",myside != 0 ? "BOB" : "ALICE",str,signedtx); - free(signedtx); - } else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll - } - if ( retjson != 0 ) - free_json(retjson); - if ( flag == 2 ) - { - free_json(vins); - printf("Free rawtx\n"); - free(rawtx); - } - free(retstr); - } else printf("error creating %s feetx\n",myside != 0 ? "BOB" : "ALICE"); - free_json(addresses); - return(tx); + if ( bits256_nonz(cltvpub) == 0 || bits256_nonz(destpub) == 0 ) + return(-1); + for (i=0; i<20; i++) + if ( secret160[i] != 0 ) + break; + if ( i == 20 ) + return(-1); + memcpy(pubkeyA+1,cltvpub.bytes,sizeof(cltvpub)); + memcpy(pubkeyB+1,destpub.bytes,sizeof(destpub)); + script[n++] = SCRIPT_OP_IF; + n = bitcoin_checklocktimeverify(script,n,*locktimep); + n = bitcoin_pubkeyspend(script,n,pubkeyA); + script[n++] = SCRIPT_OP_ELSE; + if ( secretstartp != 0 ) + *secretstartp = n + 2; + n = bitcoin_revealsecret160(script,n,secret160); + n = bitcoin_pubkeyspend(script,n,pubkeyB); + script[n++] = SCRIPT_OP_ENDIF; + return(n); } -struct bitcoin_statetx *instantdex_feetx(struct supernet_info *myinfo,struct instantdex_accept *A,struct basilisk_swap *swap,struct iguana_info *coin) +int32_t basilisk_alicescript(uint8_t *script,int32_t n,char *msigaddr,uint8_t altps2h,bits256 pubAm,bits256 pubBn) { - int32_t n; uint8_t paymentscript[128]; char scriptstr[512],coinaddr[64]; struct bitcoin_statetx *ptr = 0; uint64_t r; - r = swap->mine.orderid; - n = instantdex_outputinsurance(coinaddr,coin->chain->pubtype,paymentscript,swap->insurance + swap->bobcoin->chain->txfee,r,r * (strcmp("BTC",coin->symbol) == 0)); - init_hexbytes_noT(scriptstr,paymentscript,n); - printf("instantdex_feetx %s %.8f (%s)\n",coin->symbol,dstr(swap->insurance + swap->bobcoin->chain->txfee),scriptstr); - if ( (ptr= instantdex_signtx("feetx",myinfo,coin,0,scriptstr,swap->insurance + swap->bobcoin->chain->txfee,coin->txfee,0,A->offer.myside)) != 0 ) - strcpy(ptr->destaddr,coinaddr); - return(ptr); + 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); } +#ifdef later + int32_t instantdex_feetxverify(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_swap *swap,cJSON *argjson) { cJSON *txobj; bits256 txid; uint32_t n; int32_t i,retval = -1,extralen=65536; int64_t insurance; uint64_t r; @@ -968,7 +917,8 @@ HASH_ARRAY_STRING(basilisk,rawtx,hash,vals,hexstr) { if ( (coin= iguana_coinfind(symbol)) != 0 ) { - basilisktag = juint(vals,"basilisktag"); + if ( (basilisktag= juint(vals,"basilisktag")) == 0 ) + basilisktag = rand(); if ( juint(vals,"burn") == 0 ) jaddnum(vals,"burn",0.0001); if ( (timeoutmillis= juint(vals,"timeout")) <= 0 ) diff --git a/basilisk/basilisk_swap.c b/basilisk/basilisk_swap.c index eb3360040..2976cc59e 100755 --- a/basilisk/basilisk_swap.c +++ b/basilisk/basilisk_swap.c @@ -15,11 +15,58 @@ // included from basilisk.c -int32_t iguana_numconfirms(struct supernet_info *myinfo,struct iguana_info *coin,bits256 txid) +struct basilisk_rawtx *basilisk_swapdata_rawtx(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx) +{ + if ( rawtx->txbytes != 0 && rawtx->datalen <= maxlen ) + { + memcpy(data,rawtx->txbytes,rawtx->datalen); + return(rawtx); + } + return(0); +} + +int32_t basilisk_verify_otherfee(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + return(0); +} + +int32_t basilisk_verify_bobdeposit(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + return(0); +} + +int32_t basilisk_verify_bobpaid(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + return(0); +} + +int32_t basilisk_verify_alicepaid(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + return(0); +} + +int32_t basilisk_numconfirms(struct supernet_info *myinfo,struct basilisk_rawtx *rawtx) { return(10); } +bits256 basilisk_swap_broadcast(struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,uint8_t *data,int32_t datalen) +{ + bits256 txid; + memset(txid.bytes,0,sizeof(txid)); + return(txid); +} + +/*reclaim_tx +{ + find vout of (re)claim + construct vin spend + splice together tx +}*/ + +// end of coin protocol dependent + + bits256 instantdex_derivekeypair(struct supernet_info *myinfo,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash) { bits256 sharedsecret; @@ -70,102 +117,110 @@ int32_t instantdex_pubkeyargs(struct supernet_info *myinfo,struct basilisk_swap return(n); } -char *instantdex_choosei(struct basilisk_swap *swap,cJSON *newjson,cJSON *argjson,uint8_t *serdata,int32_t datalen) +int32_t basilisk_rawtx_gen(char *str,struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf) { - int32_t i,j,max,len = 0; uint64_t x; - if ( swap->choosei < 0 && serdata != 0 && datalen == sizeof(swap->deck) ) + struct iguana_waddress *waddr; struct iguana_waccount *wacct; char coinaddr[64],wifstr[64],*txbytes=0,*signedtx,*retstr,scriptstr[1024]; bits256 signedtxid; uint32_t basilisktag; int32_t flag,completed,retval = -1; cJSON *valsobj,*vins=0,*retjson=0,*privkey,*addresses; + if ( (waddr= iguana_getaccountaddress(myinfo,rawtx->coin,0,0,rawtx->coin->changeaddr,"change")) == 0 ) { - max = (int32_t)(sizeof(swap->otherdeck) / sizeof(*swap->otherdeck)); - for (i=0; iotherdeck[i][j],sizeof(x),&serdata[len]); - OS_randombytes((uint8_t *)&swap->choosei,sizeof(swap->choosei)); - if ( swap->choosei < 0 ) - swap->choosei = -swap->choosei; - swap->choosei %= max; - jaddnum(newjson,"mychoosei",swap->choosei); - printf(" %s send mychoosei.%d of max.%d deck.(%llx %llx)\n",swap->iambob!=0?"BOB":"alice",swap->choosei,max,(long long)swap->otherdeck[0][0],(long long)swap->otherdeck[0][1]); - return(0); + printf("no change addr error\n"); + return(-1); } - else + init_hexbytes_noT(scriptstr,script,scriptlen); + privkey = cJSON_CreateArray(); + addresses = cJSON_CreateArray(); + if ( rawtx->coin->changeaddr[0] == 0 ) + bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->chain->pubtype,waddr->rmd160,20); + //bitcoin_pubkey33(myinfo->ctx,pubkey33,myinfo->persistent_priv); + bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33); + //printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr); + if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 ) { - printf("choosei.%d or null serdata.%p or invalid datalen.%d vs %d\n",swap->choosei,serdata,datalen,(int32_t)sizeof(swap->deck)); - return(clonestr("{\"error\":\"instantdex_BTCswap offer no cut\"}")); + bitcoin_priv2wif(wifstr,waddr->privkey,rawtx->coin->chain->wiftype); + jaddistr(privkey,waddr->wifstr); } -} - -void instantdex_privkeyextract(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *serdata,int32_t serdatalen) -{ - int32_t i,j,wrongfirstbyte,errs,len = 0; bits256 otherpriv,pubi; uint8_t secret160[20],otherpubkey[33],pubkey[33]; uint64_t txid; - if ( swap->cutverified == 0 && swap->choosei >= 0 && serdatalen == sizeof(swap->privkeys) ) + basilisktag = (uint32_t)rand(); + jaddistr(addresses,coinaddr); + valsobj = cJSON_CreateObject(); + jadd(valsobj,"addresses",addresses); + jaddstr(valsobj,"coin",rawtx->coin->symbol); + jaddstr(valsobj,"spendscript",scriptstr); + jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr); + jadd64bits(valsobj,"satoshis",rawtx->amount); + jadd64bits(valsobj,"txfee",txfee); + jaddnum(valsobj,"minconf",minconf); + jaddnum(valsobj,"locktime",locktime); + jaddnum(valsobj,"timeout",30000); + if ( (retstr= basilisk_rawtx(myinfo,rawtx->coin,0,0,myinfo->myaddr.persistent,valsobj,"")) != 0 ) { - for (i=wrongfirstbyte=errs=0; iprivkeys)/sizeof(*swap->privkeys); i++) + //printf("%s got.(%s)\n",str,retstr); + flag = 0; + if ( (retjson= cJSON_Parse(retstr)) != 0 ) { - for (j=0; j<32; j++) - otherpriv.bytes[j] = serdata[len++]; - if ( i == swap->choosei ) - { - if ( bits256_nonz(otherpriv) != 0 ) - { - printf("got privkey in slot.%d my choosei??\n",i); - errs++; - } - if ( swap->iambob != 0 ) - { - if ( otherpubkey[0] == 0x02 ) - { - if ( bits256_nonz(swap->privkeys[i]) != 0 ) - { - swap->privBn = swap->privkeys[i]; - calc_rmd160_sha256(swap->secretBn,swap->privBn.bytes,sizeof(swap->privBn)); - printf("set secretBn\n"); - swap->pubBn = bitcoin_pubkey33(myinfo->ctx,pubkey,swap->privBn); - } - } else printf("wrong first byte.%02x\n",otherpubkey[0]); - } - else - { - if ( otherpubkey[0] == 0x03 ) - { - if ( bits256_nonz(swap->privkeys[i]) != 0 ) - { - swap->privAm = swap->privkeys[i]; - calc_rmd160_sha256(swap->secretAm,swap->privAm.bytes,sizeof(swap->privAm)); - printf("set secretAm\n"); - swap->pubAm = bitcoin_pubkey33(myinfo->ctx,pubkey,swap->privAm); - } - } else printf("wrong first byte.%02x\n",otherpubkey[0]); - } - continue; - } - pubi = bitcoin_pubkey33(myinfo->ctx,otherpubkey,otherpriv); - calc_rmd160_sha256(secret160,otherpriv.bytes,sizeof(otherpriv)); - memcpy(&txid,secret160,sizeof(txid)); - if ( otherpubkey[0] != (swap->iambob ^ 1) + 0x02 ) - { - wrongfirstbyte++; - printf("wrongfirstbyte[%d] %02x\n",i,otherpubkey[0]); - } - else if ( swap->otherdeck[i][1] != pubi.txid ) - { - printf("otherdeck[%d] priv ->pub mismatch %llx != %llx\n",i,(long long)swap->otherdeck[i][1],(long long)pubi.txid); - errs++; - } - else if ( swap->otherdeck[i][0] != txid ) + if ( (txbytes= jstr(retjson,"rawtx")) != 0 && (vins= jobj(retjson,"vins")) != 0 ) + flag = 1; + else printf("missing rawtx.%p or vins.%p (%s)\n",txbytes,vins,retstr); + } else printf("error parsing.(%s)\n",retstr); + if ( flag != 0 && vins != 0 ) + { + //printf("vins.(%s)\n",jprint(vins,0)); + if ( (signedtx= iguana_signrawtx(myinfo,rawtx->coin,&signedtxid,&completed,vins,txbytes,privkey)) != 0 ) { - printf("otherdeck[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherdeck[i][0],(long long)txid); - errs++; - } + if ( lockinputs != 0 ) + iguana_unspentslock(myinfo,rawtx->coin,vins); + rawtx->datalen = (int32_t)strlen(signedtx) >> 1; + rawtx->txbytes = calloc(1,rawtx->datalen); + decode_hex(rawtx->txbytes,rawtx->datalen,signedtx); + printf("%s %s.%s\n",swap->iambob != 0 ? "BOB" : "ALICE",str,signedtx); + free(signedtx); + retval = 0; + } else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll } - if ( errs == 0 && wrongfirstbyte == 0 ) - swap->cutverified = 1, printf("CUT VERIFIED\n"); - else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs); + if ( retjson != 0 ) + free_json(retjson); + if ( flag == 2 ) + { + free_json(vins); + printf("Free rawtx\n"); + free(txbytes); + } + free(retstr); + } else printf("error creating %s feetx\n",swap->iambob != 0 ? "BOB" : "ALICE"); + free_json(addresses); + free_json(valsobj); + return(retval); +} + +void basilisk_rawtx_setparms(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,struct iguana_info *coin,int32_t numconfirms,int32_t vintype,uint64_t satoshis,int32_t vouttype,uint8_t *pubkey33) +{ + rawtx->coin = coin; + rawtx->numconfirms = numconfirms; + rawtx->amount = satoshis; + rawtx->vintype = vintype; // 0 -> std, 2 -> 2of2, 3 -> spend bobpayment, 4 -> spend bobdeposit + rawtx->vouttype = vouttype; // 0 -> fee, 1 -> std, 2 -> 2of2, 3 -> bobpayment, 4 -> bobdeposit + if ( rawtx->vouttype == 0 ) + { + if ( strcmp(coin->symbol,"BTC") == 0 && (swap->req.quoteid % 10) == 0 ) + decode_hex(rawtx->rmd160,20,TIERNOLAN_RMD160); + else decode_hex(rawtx->rmd160,20,INSTANTDEX_RMD160); + bitcoin_address(rawtx->destaddr,rawtx->coin->chain->pubtype,rawtx->rmd160,20); + } + if ( pubkey33 != 0 ) + { + memcpy(rawtx->pubkey33,pubkey33,33); + bitcoin_address(rawtx->destaddr,rawtx->coin->chain->pubtype,rawtx->pubkey33,33); + bitcoin_addr2rmd160(&rawtx->addrtype,rawtx->rmd160,rawtx->destaddr); + } + if ( rawtx->vouttype <= 1 && rawtx->destaddr[0] != 0 ) + { + rawtx->spendlen = bitcoin_standardspend(rawtx->spendscript,0,rawtx->rmd160); + if ( vintype == 0 && basilisk_rawtx_gen("setparms",myinfo,swap,1,rawtx,0,rawtx->spendscript,rawtx->spendlen,coin->chain->txfee,1) < 0 ) + printf("error generating vintype.%d vouttype.%d -> %s\n",vintype,vouttype,rawtx->destaddr); } } struct basilisk_swap *bitcoin_swapinit(struct supernet_info *myinfo,struct basilisk_swap *swap) { - struct iguana_info *coin; + struct iguana_info *coin; uint8_t *alicepub33=0,*bobpub33=0; if ( strcmp("BTC",swap->req.src) == 0 ) { swap->bobcoin = iguana_coinfind("BTC"); @@ -224,7 +279,11 @@ struct basilisk_swap *bitcoin_swapinit(struct supernet_info *myinfo,struct basil swap->started = (uint32_t)time(NULL); swap->expiration = swap->req.timestamp + INSTANTDEX_LOCKTIME*2; swap->locktime = swap->expiration + INSTANTDEX_LOCKTIME; - swap->choosei = swap->otherchoosei = -1; + OS_randombytes((uint8_t *)&swap->choosei,sizeof(swap->choosei)); + if ( swap->choosei < 0 ) + swap->choosei = -swap->choosei; + swap->choosei %= INSTANTDEX_DECKSIZE; + swap->otherchoosei = -1; swap->myhash = myinfo->myaddr.persistent; if ( bits256_cmp(swap->myhash,swap->req.hash) == 0 ) { @@ -258,14 +317,48 @@ struct basilisk_swap *bitcoin_swapinit(struct supernet_info *myinfo,struct basil printf("couldnt generate privkeys\n"); return(0); } + if ( swap->iambob != 0 ) + { + basilisk_rawtx_setparms(myinfo,swap,&swap->myfee,swap->bobcoin,0,0,swap->bobsatoshis/INSTANTDEX_DECKSIZE,0,0); + basilisk_rawtx_setparms(myinfo,swap,&swap->otherfee,swap->alicecoin,0,0,swap->alicesatoshis/INSTANTDEX_DECKSIZE,0,0); + bobpub33 = myinfo->persistent_pubkey33; + } + else + { + basilisk_rawtx_setparms(myinfo,swap,&swap->otherfee,swap->bobcoin,0,0,swap->bobsatoshis/INSTANTDEX_DECKSIZE,0,0); + basilisk_rawtx_setparms(myinfo,swap,&swap->myfee,swap->alicecoin,0,0,swap->alicesatoshis/INSTANTDEX_DECKSIZE,0,0); + alicepub33 = myinfo->persistent_pubkey33; + } + basilisk_rawtx_setparms(myinfo,swap,&swap->bobdeposit,swap->bobcoin,swap->bobconfirms,0,swap->bobsatoshis*1.1,4,0); + basilisk_rawtx_setparms(myinfo,swap,&swap->bobpayment,swap->bobcoin,swap->bobconfirms,0,swap->bobsatoshis,3,0); + basilisk_rawtx_setparms(myinfo,swap,&swap->alicespend,swap->bobcoin,swap->bobconfirms,3,swap->bobsatoshis - swap->bobcoin->txfee,1,alicepub33); + basilisk_rawtx_setparms(myinfo,swap,&swap->bobreclaim,swap->bobcoin,swap->bobconfirms,4,swap->bobsatoshis*1.1 - swap->bobcoin->txfee,1,bobpub33); + basilisk_rawtx_setparms(myinfo,swap,&swap->alicepayment,swap->alicecoin,swap->aliceconfirms,0,swap->alicesatoshis,2,0); + basilisk_rawtx_setparms(myinfo,swap,&swap->alicereclaim,swap->alicecoin,swap->aliceconfirms,2,swap->alicesatoshis-swap->alicecoin->txfee,1,alicepub33); + basilisk_rawtx_setparms(myinfo,swap,&swap->bobspend,swap->alicecoin,swap->aliceconfirms,2,swap->alicesatoshis-swap->alicecoin->txfee,1,bobpub33); return(swap); } // end of alice/bob code +void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx) +{ + if ( rawtx->txbytes != 0 ) + free(rawtx->txbytes), rawtx->txbytes = 0; +} + void basilisk_swap_finished(struct supernet_info *myinfo,struct basilisk_swap *swap) { swap->finished = (uint32_t)time(NULL); // save to permanent storage + basilisk_rawtx_purge(&swap->bobdeposit); + basilisk_rawtx_purge(&swap->bobpayment); + basilisk_rawtx_purge(&swap->alicepayment); + basilisk_rawtx_purge(&swap->myfee); + basilisk_rawtx_purge(&swap->otherfee); + basilisk_rawtx_purge(&swap->alicereclaim); + basilisk_rawtx_purge(&swap->alicespend); + basilisk_rawtx_purge(&swap->bobreclaim); + basilisk_rawtx_purge(&swap->bobspend); } void basilisk_swap_purge(struct supernet_info *myinfo,struct basilisk_swap *swap) @@ -284,67 +377,199 @@ void basilisk_swap_purge(struct supernet_info *myinfo,struct basilisk_swap *swap portable_mutex_unlock(&myinfo->DEX_swapmutex); } +uint32_t basilisk_swapsend(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t nextbits) +{ + if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,msgbits,data,datalen) == 0 ) + return(nextbits); + else return(0); +} + +int32_t basilisk_verify_choosei(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + int32_t otherchoosei; + iguana_rwnum(0,data,sizeof(otherchoosei),&otherchoosei); + if ( otherchoosei >= 0 && otherchoosei < INSTANTDEX_DECKSIZE ) + { + swap->otherchoosei = otherchoosei; + return(0); + } else return(-1); +} + +int32_t basilisk_swapdata_deck(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen) +{ + int32_t i,datalen = 0; + for (i=0; ideck)/sizeof(swap->deck[0][0]); i++) + datalen += iguana_rwnum(1,&data[datalen],sizeof(swap->deck[i>>1][i&1]),&swap->deck[i>>1][i&1]); + return(datalen); +} + +int32_t basilisk_verify_otherdeck(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + int32_t i,len = 0; + for (i=0; iotherdeck)/sizeof(swap->otherdeck[0][0]); i++) + len += iguana_rwnum(0,&data[len],sizeof(swap->otherdeck[i>>1][i&1]),&swap->otherdeck[i>>1][i&1]); + return(0); +} + +int32_t basilisk_verify_pubpair(int32_t *wrongfirstbytep,struct basilisk_swap *swap,int32_t ind,uint8_t pub0,bits256 pubi,uint64_t txid) +{ + if ( pub0 != (swap->iambob ^ 1) + 0x02 ) + { + (*wrongfirstbytep)++; + printf("wrongfirstbyte[%d] %02x\n",ind,pub0); + return(-1); + } + else if ( swap->otherdeck[ind][1] != pubi.txid ) + { + printf("otherdeck[%d] priv ->pub mismatch %llx != %llx\n",ind,(long long)swap->otherdeck[ind][1],(long long)pubi.txid); + return(-1); + } + else if ( swap->otherdeck[ind][0] != txid ) + { + printf("otherdeck[%d] priv mismatch %llx != %llx\n",ind,(long long)swap->otherdeck[ind][0],(long long)txid); + return(-1); + } + return(0); +} + +int32_t basilisk_verify_privkeys(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + int32_t i,j,wrongfirstbyte,errs=0,len = 0; bits256 otherpriv,pubi; uint8_t secret160[20],otherpubkey[33],pubkey[33]; uint64_t txid; + if ( swap->cutverified == 0 && swap->choosei >= 0 && datalen == sizeof(swap->privkeys) ) + { + for (i=wrongfirstbyte=errs=0; iprivkeys)/sizeof(*swap->privkeys); i++) + { + for (j=0; j<32; j++) + otherpriv.bytes[j] = data[len++]; + pubi = bitcoin_pubkey33(myinfo->ctx,otherpubkey,otherpriv); + calc_rmd160_sha256(secret160,otherpriv.bytes,sizeof(otherpriv)); + memcpy(&txid,secret160,sizeof(txid)); + if ( i == swap->choosei ) + { + if ( bits256_nonz(otherpriv) != 0 ) + { + printf("got privkey in slot.%d my choosei??\n",i); + errs++; + } + if ( swap->iambob != 0 ) + { + if ( otherpubkey[0] == 0x02 ) + { + if ( bits256_nonz(swap->privkeys[i]) != 0 ) + { + swap->privBn = swap->privkeys[i]; + calc_rmd160_sha256(swap->secretBn,swap->privBn.bytes,sizeof(swap->privBn)); + printf("set secretBn\n"); + swap->pubBn = bitcoin_pubkey33(myinfo->ctx,pubkey,swap->privBn); + } + } else printf("wrong first byte.%02x\n",otherpubkey[0]); + } + else + { + if ( otherpubkey[0] == 0x03 ) + { + if ( bits256_nonz(swap->privkeys[i]) != 0 ) + { + swap->privAm = swap->privkeys[i]; + calc_rmd160_sha256(swap->secretAm,swap->privAm.bytes,sizeof(swap->privAm)); + printf("set secretAm\n"); + swap->pubAm = bitcoin_pubkey33(myinfo->ctx,pubkey,swap->privAm); + } + } else printf("wrong first byte.%02x\n",otherpubkey[0]); + } + continue; + } + errs += basilisk_verify_pubpair(&wrongfirstbyte,swap,i,otherpubkey[0],pubi,txid); + } + if ( errs == 0 && wrongfirstbyte == 0 ) + swap->cutverified = 1, printf("CUT VERIFIED\n"); + else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs); + } + return(errs); +} + +int32_t basilisk_verify_privi(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen) +{ + int32_t j,wrongfirstbyte,len = 0; bits256 privkey,pubi; uint8_t secret160[20],pubkey33[33]; uint64_t txid; + if ( datalen == sizeof(bits256) ) + { + for (j=0; j<32; j++) + privkey.bytes[j] = data[len++]; + calc_rmd160_sha256(secret160,privkey.bytes,sizeof(privkey)); + memcpy(&txid,secret160,sizeof(txid)); + pubi = bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey); + return(basilisk_verify_pubpair(&wrongfirstbyte,swap,swap->choosei,pubkey33[0],pubi,txid)); + } else return(-1); +} + +int32_t basilisk_swapget(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,int32_t (*basilisk_verify_func)(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen)) +{ + int32_t datalen; + if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,msgbits,data,maxlen)) > 0 ) + return((*basilisk_verify_func)(myinfo,swap,data,datalen)); + else return(-1); +} + +uint32_t basilisk_swapdata_rawtxsend(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits) +{ + if ( basilisk_swapdata_rawtx(myinfo,swap,data,maxlen,rawtx) != 0 ) + { + rawtx->actualtxid = basilisk_swap_broadcast(myinfo,swap,rawtx->coin,rawtx->txbytes,rawtx->datalen); + if ( bits256_nonz(rawtx->actualtxid) != 0 && msgbits != 0 ) + return(basilisk_swapsend(myinfo,swap,msgbits,rawtx->txbytes,rawtx->datalen,nextbits)); + } + return(0); +} + void basilisk_swaploop(void *_swap) { - uint8_t *data; int32_t maxlen,datalen,numconfirms; struct supernet_info *myinfo; struct basilisk_swap *swap = _swap; + uint8_t *data; int32_t i,j,maxlen,datalen,numconfirms; struct supernet_info *myinfo; struct basilisk_swap *swap = _swap; myinfo = swap->myinfo; printf("start swap\n"); maxlen = sizeof(*swap); data = malloc(maxlen); while ( time(NULL) < swap->expiration ) { - // iterate swap statemachine + printf("swapstate.%x\n",swap->statebits); if ( (swap->statebits & 0x01) == 0 ) // wait for pubkeys { - if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x01,data,maxlen)) == sizeof(swap->otherdeck) ) - { + if ( basilisk_swapget(myinfo,swap,0x01,data,maxlen,basilisk_verify_otherdeck) == 0 ) swap->statebits |= 0x01; - } } else if ( (swap->statebits & 0x02) == 0 ) // send pubkeys { - datalen = sizeof(swap->deck); - if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x01,data,datalen) == 0 ) - swap->statebits |= 0x02; + datalen = basilisk_swapdata_deck(myinfo,swap,data,maxlen); + swap->statebits |= basilisk_swapsend(myinfo,swap,0x01,data,datalen,0x02); } else if ( (swap->statebits & 0x04) == 0 ) // wait for choosei { - datalen = sizeof(swap->otherchoosei); - if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x04,data,maxlen)) > 0 ) - { - // set otherchoosei + if ( basilisk_swapget(myinfo,swap,0x04,data,maxlen,basilisk_verify_choosei) == 0 ) swap->statebits |= 0x04; - } } else if ( (swap->statebits & 0x08) == 0 ) // send choosei { - datalen = sizeof(swap->choosei); - if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x04,data,datalen) == 0 ) - swap->statebits |= 0x08; + iguana_rwnum(1,data,sizeof(swap->choosei),&swap->choosei); + swap->statebits |= basilisk_swapsend(myinfo,swap,0x04,data,datalen,0x08); } else if ( (swap->statebits & 0x10) == 0 ) // wait for all but one privkeys { - if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x10,data,maxlen)) == sizeof(swap->privkeys) ) - { - // verify privkeys + if ( basilisk_swapget(myinfo,swap,0x10,data,maxlen,basilisk_verify_privkeys) == 0 ) swap->statebits |= 0x10; - } } else if ( (swap->statebits & 0x20) == 0 ) // send all but one privkeys { - datalen = sizeof(swap->privkeys); - if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x10,data,datalen) == 0 ) - swap->statebits |= 0x20; + for (i=0; iotherchoosei) ? 0 : swap->privkeys[i].bytes[j]; + } + swap->statebits |= basilisk_swapsend(myinfo,swap,0x10,data,datalen,0x20); } else if ( (swap->statebits & 0x40) == 0 ) // send fee - { - datalen = (int32_t)strlen(swap->myfee->txbytes) >> 1; - if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x80,data,datalen) == 0 ) - swap->statebits |= 0x40; - } + swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40); else if ( (swap->statebits & 0x80) == 0 ) // wait for fee { - if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x80,data,maxlen)) > 0 ) + if ( basilisk_swapget(myinfo,swap,0x80,data,maxlen,basilisk_verify_otherfee) == 0 ) { // verify and submit otherfee swap->statebits |= 0x80; @@ -354,16 +579,16 @@ void basilisk_swaploop(void *_swap) { if ( swap->iambob != 0 ) { + swap->bobdeposit.spendlen = basilisk_bobscript(swap->bobdeposit.spendscript,0,&swap->bobdeposit.locktime,&swap->bobdeposit.secretstart,swap,1); + basilisk_rawtx_gen("deposit",myinfo,swap,1,&swap->bobdeposit,swap->bobdeposit.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.spendlen,swap->bobdeposit.coin->chain->txfee,1); + swap->bobpayment.spendlen = basilisk_bobscript(swap->bobpayment.spendscript,0,&swap->bobpayment.locktime,&swap->bobpayment.secretstart,swap,0); + basilisk_rawtx_gen("payment",myinfo,swap,1,&swap->bobpayment,swap->bobpayment.locktime,swap->bobpayment.spendscript,swap->bobpayment.spendlen,swap->bobpayment.coin->chain->txfee,1); if ( (swap->statebits & 0x100) == 0 ) - { - datalen = (int32_t)strlen(swap->deposit->txbytes) >> 1; - if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x200,data,datalen) == 0 ) - swap->statebits |= 0x100; - } + swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x200,data,maxlen,&swap->bobdeposit,0x100); // [BLOCKING: altfound] make sure altpayment is confirmed and send payment else if ( (swap->statebits & 0x1000) == 0 ) { - if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x1000,data,maxlen)) > 0 ) + if ( basilisk_swapget(myinfo,swap,0x1000,data,maxlen,basilisk_verify_alicepaid) == 0 ) { // verify alicepayment and submit, set confirmed height swap->statebits |= 0x1000; @@ -371,29 +596,25 @@ void basilisk_swaploop(void *_swap) } else if ( (swap->statebits & 0x2000) == 0 ) { - if ( iguana_numconfirms(myinfo,swap->alicecoin,swap->alicepayment->txid) >= swap->aliceconfirms ) + if ( basilisk_numconfirms(myinfo,&swap->alicepayment) >= swap->aliceconfirms ) swap->statebits |= 0x2000; } else if ( (swap->statebits & 0x4000) == 0 ) - { - datalen = (int32_t)strlen(swap->payment->txbytes) >> 1; - if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x8000,data,datalen) == 0 ) - swap->statebits |= 0x4000; - } - // [BLOCKING: privM] Bob waits for privM either from Alice or alice blockchain + swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000); + // [BLOCKING: privM] Bob waits for privM either from Alice or alice blockchain else if ( (swap->statebits & 0x40000) == 0 ) { - if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x40000,data,maxlen)) > 0 ) + if ( basilisk_swapget(myinfo,swap,0x40000,data,maxlen,basilisk_verify_privi) == 0 ) { // submit claim swap->statebits |= 0x40000; } - else if ( iguana_numconfirms(myinfo,swap->alicecoin,swap->alicepayment->txid) >= 0 ) + else if ( basilisk_numconfirms(myinfo,&swap->alicespend) >= 0 ) { // submit claim swap->statebits |= 0x40000; } - else if ( time(NULL) > swap->locktime ) + else if ( time(NULL) > (swap->started+swap->locktime) ) { // submit reclaim of deposittxid swap->statebits |= 0x40000; @@ -401,7 +622,7 @@ void basilisk_swaploop(void *_swap) } else if ( (swap->statebits & 0x80000) == 0 ) { - if ( (numconfirms= iguana_numconfirms(myinfo,swap->alicecoin,swap->alicepayment->txid)) >= 0 ) + if ( (numconfirms= basilisk_numconfirms(myinfo,&swap->alicepayment)) >= 0 ) { if ( numconfirms >= swap->aliceconfirms ) swap->statebits |= 0x80000; @@ -411,10 +632,12 @@ void basilisk_swaploop(void *_swap) } else { + swap->alicepayment.spendlen = basilisk_alicescript(swap->alicepayment.spendscript,0,swap->alicepayment.destaddr,swap->alicepayment.coin->chain->p2shtype,swap->pubAm,swap->pubBn); + basilisk_rawtx_gen("alicepayment",myinfo,swap,1,&swap->alicepayment,swap->alicepayment.locktime,swap->alicepayment.spendscript,swap->alicepayment.spendlen,swap->alicepayment.coin->chain->txfee,1); // [BLOCKING: depfound] Alice waits for deposit to confirm and sends altpayment if ( (swap->statebits & 0x200) == 0 ) { - if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x200,data,maxlen)) > 0 ) + if ( basilisk_swapget(myinfo,swap,0x200,data,maxlen,basilisk_verify_bobdeposit) == 0 ) { // verify deposit and submit, set confirmed height swap->statebits |= 0x200; @@ -422,24 +645,20 @@ void basilisk_swaploop(void *_swap) } else if ( (swap->statebits & 0x400) == 0 ) { - if ( iguana_numconfirms(myinfo,swap->bobcoin,swap->deposit->txid) >= swap->bobconfirms ) + if ( basilisk_numconfirms(myinfo,&swap->bobdeposit) >= swap->bobconfirms ) swap->statebits |= 0x400; } else if ( (swap->statebits & 0x800) == 0 ) - { - datalen = (int32_t)strlen(swap->alicepayment->txbytes) >> 1; - if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x1000,data,datalen) == 0 ) - swap->statebits |= 0x800; - } + swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x1000,data,maxlen,&swap->alicepayment,0x800); // [BLOCKING: payfound] make sure payment is confrmed and send in claim or see bob's reclaim and reclaim else if ( (swap->statebits & 0x8000) == 0 ) { - if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x8000,data,maxlen)) > 0 ) + if ( basilisk_swapget(myinfo,swap,0x8000,data,maxlen,basilisk_verify_bobpaid) == 0 ) { // verify payment and submit, set confirmed height swap->statebits |= 0x8000; } - else if ( iguana_numconfirms(myinfo,swap->bobcoin,swap->deposit->txid) >= 0 ) + else if ( basilisk_numconfirms(myinfo,&swap->bobreclaim) >= 0 ) { // reclaim and exit swap->reclaimed = 1; @@ -448,25 +667,26 @@ void basilisk_swaploop(void *_swap) } else if ( (swap->statebits & 0x10000) == 0 ) { - if ( swap->reclaim != 0 ) + if ( swap->reclaimed != 0 ) { - if ( iguana_numconfirms(myinfo,swap->alicecoin,swap->reclaim->txid) >= swap->aliceconfirms ) + if ( basilisk_numconfirms(myinfo,&swap->alicereclaim) >= swap->aliceconfirms ) swap->statebits |= 0x10000; } - else if ( iguana_numconfirms(myinfo,swap->bobcoin,swap->payment->txid) >= swap->bobconfirms ) + else if ( basilisk_numconfirms(myinfo,&swap->bobpayment) >= swap->bobconfirms ) swap->statebits |= 0x10000; } else if ( (swap->statebits & 0x20000) == 0 ) { - // send privM - // submit claim - datalen = sizeof(swap->privAm); - if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x40000,data,datalen) == 0 ) - swap->statebits |= 0x20000; + if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicespend,0x20000) != 0 ) + { + for (j=datalen=0; j<32; j++) + data[datalen++] = swap->privAm.bytes[j]; + swap->statebits |= basilisk_swapsend(myinfo,swap,0x40000,data,datalen,0x20000); + } } else if ( (swap->statebits & 0x40000) == 0 ) { - if ( iguana_numconfirms(myinfo,swap->alicecoin,swap->payment->txid) >= swap->bobconfirms ) + if ( basilisk_numconfirms(myinfo,&swap->bobpayment) >= swap->bobconfirms ) swap->statebits |= 0x40000; } } diff --git a/iguana/iguana_scripts.c b/iguana/iguana_scripts.c index 468458f5b..82f74858e 100755 --- a/iguana/iguana_scripts.c +++ b/iguana/iguana_scripts.c @@ -95,60 +95,6 @@ int32_t bitcoin_p2shscript(uint8_t *script,int32_t n,const uint8_t *p2shscript,c return(n); } -int32_t instantdex_bobscript(uint8_t *script,int32_t n,uint32_t *locktimep,int32_t *secretstartp,struct basilisk_swap *swap,int32_t depositflag) -{ - uint8_t pubkeyA[33],pubkeyB[33],*secret160; bits256 cltvpub,destpub; int32_t i; - *locktimep = swap->locktime; - if ( depositflag != 0 ) - { - *locktimep += INSTANTDEX_LOCKTIME; - cltvpub = swap->pubA0; - destpub = swap->pubB0; - secret160 = swap->secretBn; - pubkeyA[0] = 0x02; - pubkeyB[0] = 0x03; - } - else - { - cltvpub = swap->pubB1; - destpub = swap->pubA0; - secret160 = swap->secretAm; - pubkeyA[0] = 0x03; - pubkeyB[0] = 0x02; - } - if ( bits256_nonz(cltvpub) == 0 || bits256_nonz(destpub) == 0 ) - return(-1); - for (i=0; i<20; i++) - if ( secret160[i] != 0 ) - break; - if ( i == 20 ) - return(-1); - memcpy(pubkeyA+1,cltvpub.bytes,sizeof(cltvpub)); - memcpy(pubkeyB+1,destpub.bytes,sizeof(destpub)); - script[n++] = SCRIPT_OP_IF; - n = bitcoin_checklocktimeverify(script,n,*locktimep); - n = bitcoin_pubkeyspend(script,n,pubkeyA); - script[n++] = SCRIPT_OP_ELSE; - if ( secretstartp != 0 ) - *secretstartp = n + 2; - n = bitcoin_revealsecret160(script,n,secret160); - n = bitcoin_pubkeyspend(script,n,pubkeyB); - script[n++] = SCRIPT_OP_ENDIF; - return(n); -} - -int32_t instantdex_alicescript(uint8_t *script,int32_t n,char *msigaddr,uint8_t altps2h,bits256 pubAm,bits256 pubBn) -{ - uint8_t p2sh160[20]; struct vin_info V; - memset(&V,0,sizeof(V)); - memcpy(&V.signers[0].pubkey[1],pubAm.bytes,sizeof(pubAm)), V.signers[0].pubkey[0] = 0x02; - memcpy(&V.signers[1].pubkey[1],pubBn.bytes,sizeof(pubBn)), V.signers[1].pubkey[0] = 0x03; - V.M = V.N = 2; - n = bitcoin_MofNspendscript(p2sh160,script,n,&V); - bitcoin_address(msigaddr,altps2h,p2sh160,sizeof(p2sh160)); - return(n); -} - int32_t bitcoin_changescript(struct iguana_info *coin,uint8_t *changescript,int32_t n,uint64_t *changep,char *changeaddr,uint64_t inputsatoshis,uint64_t satoshis,uint64_t txfee) { uint8_t addrtype,rmd160[20]; int32_t len; diff --git a/iguana/tests/allcoins b/iguana/tests/allcoins new file mode 100755 index 000000000..1454b39b7 --- /dev/null +++ b/iguana/tests/allcoins @@ -0,0 +1 @@ +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"InstantDEX\",\"method\":\"allcoins\"}" diff --git a/iguana/tests/request b/iguana/tests/request index 510ec2efb..db4bf1264 100755 --- a/iguana/tests/request +++ b/iguana/tests/request @@ -1,2 +1,2 @@ -curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"InstantDEX\",\"method\":\"request\",\"message\":\"message\",\"dest\":\"BTC\",\"source\":\"BTCD\",\"amount\":0.01}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"InstantDEX\",\"method\":\"request\",\"vals\":{\"source\":\"BTCD\",\"amount\":1,\"dest\":\"BTC\",\"minprice\":0.003,\"autoflag\":1}}" diff --git a/includes/iguana_apideclares.h b/includes/iguana_apideclares.h index 29846306e..f59e2e532 100755 --- a/includes/iguana_apideclares.h +++ b/includes/iguana_apideclares.h @@ -15,10 +15,11 @@ ZERO_ARGS(InstantDEX,allcoins); STRING_ARG(InstantDEX,available,source); -//THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,request,message,dest,source,amount,mindestamount,autoflag); HASH_ARRAY_STRING(InstantDEX,request,hash,vals,hexstr); INT_ARG(InstantDEX,incoming,requestid); +INT_ARG(InstantDEX,automatched,requestid); + TWO_INTS(InstantDEX,accept,requestid,quoteid); TWO_INTS(InstantDEX,swapstatus,requestid,quoteid); diff --git a/includes/iguana_funcs.h b/includes/iguana_funcs.h index 17c90f945..9bc37a9f7 100755 --- a/includes/iguana_funcs.h +++ b/includes/iguana_funcs.h @@ -530,6 +530,7 @@ void iguana_RTramchainalloc(char *fname,struct iguana_info *coin,struct iguana_b void iguana_update_balances(struct iguana_info *coin); void iguana_RTspendvectors(struct iguana_info *coin,struct iguana_bundle *bp); double instantdex_avehbla(struct supernet_info *myinfo,double retvals[4],char *base,char *rel,double basevolume); +int32_t bitcoin_revealsecret160(uint8_t *script,int32_t n,uint8_t secret160[20]); #include "../includes/iguana_api.h"