Browse Source

test

release/v0.1
jl777 9 years ago
parent
commit
33c0b3ad4e
  1. 21
      basilisk/basilisk.c
  2. 15
      basilisk/basilisk.h
  3. 8
      basilisk/basilisk_DEX.c
  4. 2
      basilisk/basilisk_MSG.c
  5. 154
      basilisk/basilisk_bitcoin.c
  6. 516
      basilisk/basilisk_swap.c
  7. 54
      iguana/iguana_scripts.c
  8. 1
      iguana/tests/allcoins
  9. 2
      iguana/tests/request
  10. 3
      includes/iguana_apideclares.h
  11. 1
      includes/iguana_funcs.h

21
basilisk/basilisk.c

@ -15,9 +15,7 @@
#include "../iguana/iguana777.h" #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 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) 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); 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 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; 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); printf("%s %s s.%d vs n.%d iguana.%d\n",coin->symbol,addr->ipaddr,s,n,addr->supernet);
if ( addr->usock >= 0 ) if ( addr->usock >= 0 )
{ {
if ( strcmp(type,"BLK") == 0 ) if ( basilisk_specialrelay_CMD(type) > 0 )
{ {
for (s=0; s<myinfo->numrelays; s++) for (s=0; s<myinfo->numrelays; s++)
if ( addr->ipbits != myinfo->myaddr.myipbits && myinfo->relays[s].ipbits == addr->ipbits ) 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; continue;
if ( s == n && (addr->supernet != 0 || addr->basilisk != 0) && (destipaddr == 0 || strcmp(addr->ipaddr,destipaddr) == 0) ) 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 ) if ( encryptflag != 0 && bits256_nonz(addr->pubkey) != 0 )
{ {
void *ptr; uint8_t *cipher,space[8192]; int32_t cipherlen; bits256 privkey; 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 // gecko chains
{ (void *)"GET", &basilisk_respond_geckoget }, // requests headers, block or tx { (void *)"GET", &basilisk_respond_geckoget }, // requests headers, block or tx
{ (void *)"HDR", &basilisk_respond_geckoheaders }, // reports headers { (void *)"HDR", &basilisk_respond_geckoheaders }, // reports headers
{ (void *)"BLK", &basilisk_respond_geckoblock }, // reports block { (void *)"BLK", &basilisk_respond_geckoblock }, // reports virtchain block
{ (void *)"MEM", &basilisk_respond_mempool }, // reports mempool { (void *)"MEM", &basilisk_respond_mempool }, // reports virtchain mempool
{ (void *)"GTX", &basilisk_respond_geckotx }, // reports tx { (void *)"GTX", &basilisk_respond_geckotx }, // reports virtchain tx
{ (void *)"ADD", &basilisk_respond_addrelay }, // relays register with each other bus { (void *)"ADD", &basilisk_respond_addrelay }, // relays register with each other bus
{ (void *)"DEX", &basilisk_respond_DEX }, { (void *)"DEX", &basilisk_respond_DEX },
@ -761,7 +766,7 @@ void basilisks_loop(void *arg)
} }
} }
portable_mutex_unlock(&myinfo->messagemutex); portable_mutex_unlock(&myinfo->messagemutex);
usleep(100000); usleep(1000000);
} }
} }

15
basilisk/basilisk.h

@ -32,7 +32,7 @@
#define INSTANTDEX_DECKSIZE 777 #define INSTANTDEX_DECKSIZE 777
#define INSTANTDEX_LOCKTIME (7200 + 600*2) #define INSTANTDEX_LOCKTIME (7200 + 600*2)
#define INSTANTDEX_INSURANCEDIV ((7 * INSTANTDEX_DECKSIZE) >> 3) #define INSTANTDEX_INSURANCEDIV ((7 * INSTANTDEX_DECKSIZE) >> 3)
#define INSTANTDEX_PUBEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06" #define INSTANTDEX_PUBKEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06"
#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f" #define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f"
#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146" #define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146"
#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu" #define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu"
@ -50,12 +50,15 @@ struct basilisk_request
bits256 desthash; bits256 desthash;
} __attribute__((packed)); } __attribute__((packed));
struct bitcoin_statetx struct basilisk_rawtx
{ {
bits256 txid; bits256 txid,actualtxid;
struct iguana_info *coin;
uint64_t amount,change,inputsum; uint64_t amount,change,inputsum;
char destaddr[64]; int32_t datalen,vintype,vouttype,numconfirms,spendlen,secretstart;
char txbytes[]; uint32_t locktime;
char destaddr[64]; uint8_t addrtype,pubkey33[33],rmd160[20],spendscript[512];
uint8_t *txbytes;
}; };
struct basilisk_swap struct basilisk_swap
@ -72,7 +75,7 @@ struct basilisk_swap
int32_t choosei,otherchoosei,cutverified,otherverifiedcut,numpubs,havestate,otherhavestate; int32_t choosei,otherchoosei,cutverified,otherverifiedcut,numpubs,havestate,otherhavestate;
uint8_t secretAm[20],secretBn[20]; 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]; }; struct basilisk_value { bits256 txid; int64_t value; int32_t height; int16_t vout; char coinaddr[64]; };

8
basilisk/basilisk_DEX.c

@ -452,7 +452,7 @@ ZERO_ARGS(InstantDEX,allcoins)
STRING_ARG(InstantDEX,available,source) 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 ) if ( myinfo->expiration != 0 )
return(bitcoinrpc_getbalance(myinfo,coin,json,remoteaddr,"*",coin->chain->minconfirms,1,1<<30)); 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)); 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) INT_ARG(InstantDEX,incoming,requestid)
{ {
cJSON *vals; char *retstr; cJSON *vals; char *retstr;

2
basilisk/basilisk_MSG.c

@ -148,7 +148,7 @@ HASH_ARRAY_STRING(basilisk,getmessage,hash,vals,hexstr)
HASH_ARRAY_STRING(basilisk,sendmessage,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" #include "../includes/iguana_apiundefs.h"

154
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)); 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 #define SCRIPT_OP_IF 0x63
int32_t instantdex_outputinsurance(char *coinaddr,uint8_t addrtype,uint8_t *script,int64_t insurance,uint64_t r,uint64_t dest) #define SCRIPT_OP_ELSE 0x67
{ #define SCRIPT_OP_ENDIF 0x68
uint8_t rmd160[20]; int32_t n = 0;
decode_hex(rmd160,sizeof(rmd160),(dest % 10) == 9 ? TIERNOLAN_RMD160 : INSTANTDEX_RMD160);
//script[n++] = sizeof(r);
//n += iguana_rwnum(1,&script[n],sizeof(r),&r);
//script[n++] = SCRIPT_OP_DROP;
bitcoin_address(coinaddr,addrtype,rmd160,20);
n = bitcoin_standardspend(script,n,rmd160);
return(n);
}
void iguana_addinputs(struct iguana_info *coin,struct bitcoin_spend *spend,cJSON *txobj,uint32_t sequence) int32_t 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]; uint8_t pubkeyA[33],pubkeyB[33],*secret160; bits256 cltvpub,destpub; int32_t i;
for (i=0; i<spend->numinputs; i++) *locktimep = swap->locktime;
{ if ( depositflag != 0 )
spend->inputs[i].sequence = sequence; {
for (j=0; j<16; j++) *locktimep += INSTANTDEX_LOCKTIME;
{ cltvpub = swap->pubA0;
if ( (plen= bitcoin_pubkeylen(spend->inputs[i].pubkeys[j])) < 0 ) destpub = swap->pubB0;
break; secret160 = swap->secretBn;
pubkeyptrs[j] = spend->inputs[i].pubkeys[j]; pubkeyA[0] = 0x02;
} pubkeyB[0] = 0x03;
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);
} }
} else
struct bitcoin_statetx *instantdex_signtx(char *str,struct supernet_info *myinfo,struct iguana_info *coin,uint32_t locktime,char *scriptstr,int64_t satoshis,int64_t txfee,int32_t minconf,int32_t myside)
{
struct iguana_waddress *waddr; struct iguana_waccount *wacct; struct bitcoin_statetx *tx=0; char coinaddr[64],wifstr[64]; char *rawtx=0,*signedtx,*retstr; bits256 signedtxid; uint32_t basilisktag; int32_t flag,completed; cJSON *valsobj,*vins=0,*retjson=0,*privkey,*addresses;
if ( (waddr= iguana_getaccountaddress(myinfo,coin,0,0,coin->changeaddr,"change")) == 0 )
{
printf("no change addr error\n");
return(0);
}
privkey = cJSON_CreateArray();
addresses = cJSON_CreateArray();
if ( coin->changeaddr[0] == 0 )
bitcoin_address(coin->changeaddr,coin->chain->pubtype,waddr->rmd160,20);
//bitcoin_pubkey33(myinfo->ctx,pubkey33,myinfo->persistent_priv);
bitcoin_address(coinaddr,coin->chain->pubtype,myinfo->persistent_pubkey33,33);
//printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr);
if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 )
{ {
bitcoin_priv2wif(wifstr,waddr->privkey,coin->chain->wiftype); cltvpub = swap->pubB1;
jaddistr(privkey,waddr->wifstr); destpub = swap->pubA0;
secret160 = swap->secretAm;
pubkeyA[0] = 0x03;
pubkeyB[0] = 0x02;
} }
basilisktag = (uint32_t)rand(); if ( bits256_nonz(cltvpub) == 0 || bits256_nonz(destpub) == 0 )
jaddistr(addresses,coinaddr); return(-1);
valsobj = cJSON_CreateObject(); for (i=0; i<20; i++)
jadd(valsobj,"addresses",addresses); if ( secret160[i] != 0 )
jaddstr(valsobj,"coin",coin->symbol); break;
jaddstr(valsobj,"spendscript",scriptstr); if ( i == 20 )
jaddstr(valsobj,"changeaddr",coin->changeaddr); return(-1);
jadd64bits(valsobj,"satoshis",satoshis); memcpy(pubkeyA+1,cltvpub.bytes,sizeof(cltvpub));
jadd64bits(valsobj,"txfee",txfee); memcpy(pubkeyB+1,destpub.bytes,sizeof(destpub));
jaddnum(valsobj,"minconf",minconf); script[n++] = SCRIPT_OP_IF;
jaddnum(valsobj,"basilisktag",basilisktag); n = bitcoin_checklocktimeverify(script,n,*locktimep);
jaddnum(valsobj,"locktime",locktime); n = bitcoin_pubkeyspend(script,n,pubkeyA);
jaddnum(valsobj,"timeout",30000); script[n++] = SCRIPT_OP_ELSE;
if ( (retstr= basilisk_rawtx(myinfo,coin,0,0,myinfo->myaddr.persistent,valsobj,"")) != 0 ) if ( secretstartp != 0 )
{ *secretstartp = n + 2;
//printf("%s got.(%s)\n",str,retstr); n = bitcoin_revealsecret160(script,n,secret160);
flag = 0; n = bitcoin_pubkeyspend(script,n,pubkeyB);
if ( (retjson= cJSON_Parse(retstr)) != 0 ) script[n++] = SCRIPT_OP_ENDIF;
{ return(n);
if ( (rawtx= jstr(retjson,"rawtx")) != 0 && (vins= jobj(retjson,"vins")) != 0 )
flag = 1;
else printf("missing rawtx.%p or vins.%p\n",rawtx,vins);
} else printf("error parsing.(%s)\n",retstr);
if ( flag != 0 && vins != 0 )
{
//printf("vins.(%s)\n",jprint(vins,0));
if ( (signedtx= iguana_signrawtx(myinfo,coin,&signedtxid,&completed,vins,rawtx,privkey)) != 0 )
{
iguana_unspentslock(myinfo,coin,vins);
tx = calloc(1,sizeof(*tx) + strlen(signedtx) + 1);
strcpy(tx->txbytes,signedtx);
tx->txid = signedtxid;
printf("%s %s.%s\n",myside != 0 ? "BOB" : "ALICE",str,signedtx);
free(signedtx);
} else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll
}
if ( retjson != 0 )
free_json(retjson);
if ( flag == 2 )
{
free_json(vins);
printf("Free rawtx\n");
free(rawtx);
}
free(retstr);
} else printf("error creating %s feetx\n",myside != 0 ? "BOB" : "ALICE");
free_json(addresses);
return(tx);
} }
struct bitcoin_statetx *instantdex_feetx(struct supernet_info *myinfo,struct instantdex_accept *A,struct basilisk_swap *swap,struct iguana_info *coin) int32_t 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; uint8_t p2sh160[20]; struct vin_info V;
r = swap->mine.orderid; memset(&V,0,sizeof(V));
n = instantdex_outputinsurance(coinaddr,coin->chain->pubtype,paymentscript,swap->insurance + swap->bobcoin->chain->txfee,r,r * (strcmp("BTC",coin->symbol) == 0)); memcpy(&V.signers[0].pubkey[1],pubAm.bytes,sizeof(pubAm)), V.signers[0].pubkey[0] = 0x02;
init_hexbytes_noT(scriptstr,paymentscript,n); memcpy(&V.signers[1].pubkey[1],pubBn.bytes,sizeof(pubBn)), V.signers[1].pubkey[0] = 0x03;
printf("instantdex_feetx %s %.8f (%s)\n",coin->symbol,dstr(swap->insurance + swap->bobcoin->chain->txfee),scriptstr); V.M = V.N = 2;
if ( (ptr= instantdex_signtx("feetx",myinfo,coin,0,scriptstr,swap->insurance + swap->bobcoin->chain->txfee,coin->txfee,0,A->offer.myside)) != 0 ) n = bitcoin_MofNspendscript(p2sh160,script,n,&V);
strcpy(ptr->destaddr,coinaddr); bitcoin_address(msigaddr,altps2h,p2sh160,sizeof(p2sh160));
return(ptr); return(n);
} }
#ifdef later
int32_t instantdex_feetxverify(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_swap *swap,cJSON *argjson) 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; 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 ) if ( (coin= iguana_coinfind(symbol)) != 0 )
{ {
basilisktag = juint(vals,"basilisktag"); if ( (basilisktag= juint(vals,"basilisktag")) == 0 )
basilisktag = rand();
if ( juint(vals,"burn") == 0 ) if ( juint(vals,"burn") == 0 )
jaddnum(vals,"burn",0.0001); jaddnum(vals,"burn",0.0001);
if ( (timeoutmillis= juint(vals,"timeout")) <= 0 ) if ( (timeoutmillis= juint(vals,"timeout")) <= 0 )

516
basilisk/basilisk_swap.c

@ -15,11 +15,58 @@
// included from basilisk.c // 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); 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 instantdex_derivekeypair(struct supernet_info *myinfo,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash)
{ {
bits256 sharedsecret; bits256 sharedsecret;
@ -70,102 +117,110 @@ int32_t instantdex_pubkeyargs(struct supernet_info *myinfo,struct basilisk_swap
return(n); 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; 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 ( swap->choosei < 0 && serdata != 0 && datalen == sizeof(swap->deck) ) if ( (waddr= iguana_getaccountaddress(myinfo,rawtx->coin,0,0,rawtx->coin->changeaddr,"change")) == 0 )
{ {
max = (int32_t)(sizeof(swap->otherdeck) / sizeof(*swap->otherdeck)); printf("no change addr error\n");
for (i=0; i<max; i++) return(-1);
for (j=0; j<2; j++)
len += iguana_rwnum(1,(uint8_t *)&swap->otherdeck[i][j],sizeof(x),&serdata[len]);
OS_randombytes((uint8_t *)&swap->choosei,sizeof(swap->choosei));
if ( swap->choosei < 0 )
swap->choosei = -swap->choosei;
swap->choosei %= max;
jaddnum(newjson,"mychoosei",swap->choosei);
printf(" %s send mychoosei.%d of max.%d deck.(%llx %llx)\n",swap->iambob!=0?"BOB":"alice",swap->choosei,max,(long long)swap->otherdeck[0][0],(long long)swap->otherdeck[0][1]);
return(0);
} }
else 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)); bitcoin_priv2wif(wifstr,waddr->privkey,rawtx->coin->chain->wiftype);
return(clonestr("{\"error\":\"instantdex_BTCswap offer no cut\"}")); jaddistr(privkey,waddr->wifstr);
} }
} basilisktag = (uint32_t)rand();
jaddistr(addresses,coinaddr);
void instantdex_privkeyextract(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *serdata,int32_t serdatalen) valsobj = cJSON_CreateObject();
{ jadd(valsobj,"addresses",addresses);
int32_t i,j,wrongfirstbyte,errs,len = 0; bits256 otherpriv,pubi; uint8_t secret160[20],otherpubkey[33],pubkey[33]; uint64_t txid; jaddstr(valsobj,"coin",rawtx->coin->symbol);
if ( swap->cutverified == 0 && swap->choosei >= 0 && serdatalen == sizeof(swap->privkeys) ) 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; i<sizeof(swap->privkeys)/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++) if ( (txbytes= jstr(retjson,"rawtx")) != 0 && (vins= jobj(retjson,"vins")) != 0 )
otherpriv.bytes[j] = serdata[len++]; flag = 1;
if ( i == swap->choosei ) else printf("missing rawtx.%p or vins.%p (%s)\n",txbytes,vins,retstr);
{ } else printf("error parsing.(%s)\n",retstr);
if ( bits256_nonz(otherpriv) != 0 ) if ( flag != 0 && vins != 0 )
{ {
printf("got privkey in slot.%d my choosei??\n",i); //printf("vins.(%s)\n",jprint(vins,0));
errs++; if ( (signedtx= iguana_signrawtx(myinfo,rawtx->coin,&signedtxid,&completed,vins,txbytes,privkey)) != 0 )
}
if ( swap->iambob != 0 )
{
if ( otherpubkey[0] == 0x02 )
{
if ( bits256_nonz(swap->privkeys[i]) != 0 )
{
swap->privBn = swap->privkeys[i];
calc_rmd160_sha256(swap->secretBn,swap->privBn.bytes,sizeof(swap->privBn));
printf("set secretBn\n");
swap->pubBn = bitcoin_pubkey33(myinfo->ctx,pubkey,swap->privBn);
}
} else printf("wrong first byte.%02x\n",otherpubkey[0]);
}
else
{
if ( otherpubkey[0] == 0x03 )
{
if ( bits256_nonz(swap->privkeys[i]) != 0 )
{
swap->privAm = swap->privkeys[i];
calc_rmd160_sha256(swap->secretAm,swap->privAm.bytes,sizeof(swap->privAm));
printf("set secretAm\n");
swap->pubAm = bitcoin_pubkey33(myinfo->ctx,pubkey,swap->privAm);
}
} else printf("wrong first byte.%02x\n",otherpubkey[0]);
}
continue;
}
pubi = bitcoin_pubkey33(myinfo->ctx,otherpubkey,otherpriv);
calc_rmd160_sha256(secret160,otherpriv.bytes,sizeof(otherpriv));
memcpy(&txid,secret160,sizeof(txid));
if ( otherpubkey[0] != (swap->iambob ^ 1) + 0x02 )
{
wrongfirstbyte++;
printf("wrongfirstbyte[%d] %02x\n",i,otherpubkey[0]);
}
else if ( swap->otherdeck[i][1] != pubi.txid )
{
printf("otherdeck[%d] priv ->pub mismatch %llx != %llx\n",i,(long long)swap->otherdeck[i][1],(long long)pubi.txid);
errs++;
}
else if ( swap->otherdeck[i][0] != txid )
{ {
printf("otherdeck[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherdeck[i][0],(long long)txid); if ( lockinputs != 0 )
errs++; 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 ) if ( retjson != 0 )
swap->cutverified = 1, printf("CUT VERIFIED\n"); free_json(retjson);
else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs); 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 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 ) if ( strcmp("BTC",swap->req.src) == 0 )
{ {
swap->bobcoin = iguana_coinfind("BTC"); 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->started = (uint32_t)time(NULL);
swap->expiration = swap->req.timestamp + INSTANTDEX_LOCKTIME*2; swap->expiration = swap->req.timestamp + INSTANTDEX_LOCKTIME*2;
swap->locktime = swap->expiration + INSTANTDEX_LOCKTIME; 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; swap->myhash = myinfo->myaddr.persistent;
if ( bits256_cmp(swap->myhash,swap->req.hash) == 0 ) 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"); printf("couldnt generate privkeys\n");
return(0); 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); return(swap);
} }
// end of alice/bob code // 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) void basilisk_swap_finished(struct supernet_info *myinfo,struct basilisk_swap *swap)
{ {
swap->finished = (uint32_t)time(NULL); swap->finished = (uint32_t)time(NULL);
// save to permanent storage // 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) 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); 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; i<sizeof(swap->deck)/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; i<sizeof(swap->otherdeck)/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; i<sizeof(swap->privkeys)/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) 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; myinfo = swap->myinfo;
printf("start swap\n"); printf("start swap\n");
maxlen = sizeof(*swap); maxlen = sizeof(*swap);
data = malloc(maxlen); data = malloc(maxlen);
while ( time(NULL) < swap->expiration ) while ( time(NULL) < swap->expiration )
{ {
// iterate swap statemachine printf("swapstate.%x\n",swap->statebits);
if ( (swap->statebits & 0x01) == 0 ) // wait for pubkeys 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; swap->statebits |= 0x01;
}
} }
else if ( (swap->statebits & 0x02) == 0 ) // send pubkeys else if ( (swap->statebits & 0x02) == 0 ) // send pubkeys
{ {
datalen = sizeof(swap->deck); datalen = basilisk_swapdata_deck(myinfo,swap,data,maxlen);
if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x01,data,datalen) == 0 ) swap->statebits |= basilisk_swapsend(myinfo,swap,0x01,data,datalen,0x02);
swap->statebits |= 0x02;
} }
else if ( (swap->statebits & 0x04) == 0 ) // wait for choosei else if ( (swap->statebits & 0x04) == 0 ) // wait for choosei
{ {
datalen = sizeof(swap->otherchoosei); if ( basilisk_swapget(myinfo,swap,0x04,data,maxlen,basilisk_verify_choosei) == 0 )
if ( (datalen= basilisk_channelget(myinfo,myinfo->myaddr.persistent,swap->req.quoteid,0x04,data,maxlen)) > 0 )
{
// set otherchoosei
swap->statebits |= 0x04; swap->statebits |= 0x04;
}
} }
else if ( (swap->statebits & 0x08) == 0 ) // send choosei else if ( (swap->statebits & 0x08) == 0 ) // send choosei
{ {
datalen = sizeof(swap->choosei); iguana_rwnum(1,data,sizeof(swap->choosei),&swap->choosei);
if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x04,data,datalen) == 0 ) swap->statebits |= basilisk_swapsend(myinfo,swap,0x04,data,datalen,0x08);
swap->statebits |= 0x08;
} }
else if ( (swap->statebits & 0x10) == 0 ) // wait for all but one privkeys 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) ) if ( basilisk_swapget(myinfo,swap,0x10,data,maxlen,basilisk_verify_privkeys) == 0 )
{
// verify privkeys
swap->statebits |= 0x10; swap->statebits |= 0x10;
}
} }
else if ( (swap->statebits & 0x20) == 0 ) // send all but one privkeys else if ( (swap->statebits & 0x20) == 0 ) // send all but one privkeys
{ {
datalen = sizeof(swap->privkeys); for (i=0; i<INSTANTDEX_DECKSIZE; i++)
if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x10,data,datalen) == 0 ) {
swap->statebits |= 0x20; for (j=0; j<32; j++)
data[datalen++] = (i == swap->otherchoosei) ? 0 : swap->privkeys[i].bytes[j];
}
swap->statebits |= basilisk_swapsend(myinfo,swap,0x10,data,datalen,0x20);
} }
else if ( (swap->statebits & 0x40) == 0 ) // send fee else if ( (swap->statebits & 0x40) == 0 ) // send fee
{ swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40);
datalen = (int32_t)strlen(swap->myfee->txbytes) >> 1;
if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x80,data,datalen) == 0 )
swap->statebits |= 0x40;
}
else if ( (swap->statebits & 0x80) == 0 ) // wait for fee 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 // verify and submit otherfee
swap->statebits |= 0x80; swap->statebits |= 0x80;
@ -354,16 +579,16 @@ void basilisk_swaploop(void *_swap)
{ {
if ( swap->iambob != 0 ) 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 ) if ( (swap->statebits & 0x100) == 0 )
{ swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x200,data,maxlen,&swap->bobdeposit,0x100);
datalen = (int32_t)strlen(swap->deposit->txbytes) >> 1;
if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x200,data,datalen) == 0 )
swap->statebits |= 0x100;
}
// [BLOCKING: altfound] make sure altpayment is confirmed and send payment // [BLOCKING: altfound] make sure altpayment is confirmed and send payment
else if ( (swap->statebits & 0x1000) == 0 ) 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 // verify alicepayment and submit, set confirmed height
swap->statebits |= 0x1000; swap->statebits |= 0x1000;
@ -371,29 +596,25 @@ void basilisk_swaploop(void *_swap)
} }
else if ( (swap->statebits & 0x2000) == 0 ) 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; swap->statebits |= 0x2000;
} }
else if ( (swap->statebits & 0x4000) == 0 ) else if ( (swap->statebits & 0x4000) == 0 )
{ swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000);
datalen = (int32_t)strlen(swap->payment->txbytes) >> 1; // [BLOCKING: privM] Bob waits for privM either from Alice or alice blockchain
if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x8000,data,datalen) == 0 )
swap->statebits |= 0x4000;
}
// [BLOCKING: privM] Bob waits for privM either from Alice or alice blockchain
else if ( (swap->statebits & 0x40000) == 0 ) 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 // submit claim
swap->statebits |= 0x40000; swap->statebits |= 0x40000;
} }
else if ( iguana_numconfirms(myinfo,swap->alicecoin,swap->alicepayment->txid) >= 0 ) else if ( basilisk_numconfirms(myinfo,&swap->alicespend) >= 0 )
{ {
// submit claim // submit claim
swap->statebits |= 0x40000; swap->statebits |= 0x40000;
} }
else if ( time(NULL) > swap->locktime ) else if ( time(NULL) > (swap->started+swap->locktime) )
{ {
// submit reclaim of deposittxid // submit reclaim of deposittxid
swap->statebits |= 0x40000; swap->statebits |= 0x40000;
@ -401,7 +622,7 @@ void basilisk_swaploop(void *_swap)
} }
else if ( (swap->statebits & 0x80000) == 0 ) 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 ) if ( numconfirms >= swap->aliceconfirms )
swap->statebits |= 0x80000; swap->statebits |= 0x80000;
@ -411,10 +632,12 @@ void basilisk_swaploop(void *_swap)
} }
else 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 // [BLOCKING: depfound] Alice waits for deposit to confirm and sends altpayment
if ( (swap->statebits & 0x200) == 0 ) 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 // verify deposit and submit, set confirmed height
swap->statebits |= 0x200; swap->statebits |= 0x200;
@ -422,24 +645,20 @@ void basilisk_swaploop(void *_swap)
} }
else if ( (swap->statebits & 0x400) == 0 ) 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; swap->statebits |= 0x400;
} }
else if ( (swap->statebits & 0x800) == 0 ) else if ( (swap->statebits & 0x800) == 0 )
{ swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x1000,data,maxlen,&swap->alicepayment,0x800);
datalen = (int32_t)strlen(swap->alicepayment->txbytes) >> 1;
if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x1000,data,datalen) == 0 )
swap->statebits |= 0x800;
}
// [BLOCKING: payfound] make sure payment is confrmed and send in claim or see bob's reclaim and reclaim // [BLOCKING: payfound] make sure payment is confrmed and send in claim or see bob's reclaim and reclaim
else if ( (swap->statebits & 0x8000) == 0 ) 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 // verify payment and submit, set confirmed height
swap->statebits |= 0x8000; 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 // reclaim and exit
swap->reclaimed = 1; swap->reclaimed = 1;
@ -448,25 +667,26 @@ void basilisk_swaploop(void *_swap)
} }
else if ( (swap->statebits & 0x10000) == 0 ) 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; 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; swap->statebits |= 0x10000;
} }
else if ( (swap->statebits & 0x20000) == 0 ) else if ( (swap->statebits & 0x20000) == 0 )
{ {
// send privM if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicespend,0x20000) != 0 )
// submit claim {
datalen = sizeof(swap->privAm); for (j=datalen=0; j<32; j++)
if ( basilisk_channelsend(myinfo,swap->otherhash,swap->req.quoteid,0x40000,data,datalen) == 0 ) data[datalen++] = swap->privAm.bytes[j];
swap->statebits |= 0x20000; swap->statebits |= basilisk_swapsend(myinfo,swap,0x40000,data,datalen,0x20000);
}
} }
else if ( (swap->statebits & 0x40000) == 0 ) 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; swap->statebits |= 0x40000;
} }
} }

54
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); 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) 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; uint8_t addrtype,rmd160[20]; int32_t len;

1
iguana/tests/allcoins

@ -0,0 +1 @@
curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"InstantDEX\",\"method\":\"allcoins\"}"

2
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}}"

3
includes/iguana_apideclares.h

@ -15,10 +15,11 @@
ZERO_ARGS(InstantDEX,allcoins); ZERO_ARGS(InstantDEX,allcoins);
STRING_ARG(InstantDEX,available,source); 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); HASH_ARRAY_STRING(InstantDEX,request,hash,vals,hexstr);
INT_ARG(InstantDEX,incoming,requestid); INT_ARG(InstantDEX,incoming,requestid);
INT_ARG(InstantDEX,automatched,requestid);
TWO_INTS(InstantDEX,accept,requestid,quoteid); TWO_INTS(InstantDEX,accept,requestid,quoteid);
TWO_INTS(InstantDEX,swapstatus,requestid,quoteid); TWO_INTS(InstantDEX,swapstatus,requestid,quoteid);

1
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_update_balances(struct iguana_info *coin);
void iguana_RTspendvectors(struct iguana_info *coin,struct iguana_bundle *bp); 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); 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" #include "../includes/iguana_api.h"

Loading…
Cancel
Save