You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1343 lines
58 KiB

8 years ago
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
// included from basilisk.c
8 years ago
/* https://bitcointalk.org/index.php?topic=1340621.msg13828271#msg13828271
https://bitcointalk.org/index.php?topic=1364951
Tier Nolan's approach is followed with the following changes:
a) instead of cutting 1000 keypairs, only INSTANTDEX_DECKSIZE are a
b) instead of sending the entire 256 bits, it is truncated to 64 bits. With odds of collision being so low, it is dwarfed by the ~0.1% insurance factor.
c) D is set to 100x the insurance rate of 1/777 12.87% + BTC amount
d) insurance is added to Bob's payment, which is after the deposit and bailin
e) BEFORE Bob broadcasts deposit, Alice broadcasts BTC denominated fee in cltv so if trade isnt done fee is reclaimed
*/
/*
both fees are standard payments: OP_DUP OP_HASH160 FEE_RMD160 OP_EQUALVERIFY OP_CHECKSIG
Alice altpayment: OP_2 <alice_pubM> <bob_pubN> OP_2 OP_CHECKMULTISIG
Bob deposit:
OP_IF
<now + INSTANTDEX_LOCKTIME*2> OP_CLTV OP_DROP <alice_pubA0> OP_CHECKSIG
OP_ELSE
OP_HASH160 <hash(bob_privN)> OP_EQUALVERIFY <bob_pubB0> OP_CHECKSIG
OP_ENDIF
Bob paytx:
OP_IF
<now + INSTANTDEX_LOCKTIME> OP_CLTV OP_DROP <bob_pubB1> OP_CHECKSIG
OP_ELSE
OP_HASH160 <hash(alice_privM)> OP_EQUALVERIFY <alice_pubA0> OP_CHECKSIG
OP_ENDIF
Naming convention are pubAi are alice's pubkeys (seems only pubA0 and not pubA1)
pubBi are Bob's pubkeys
privN is Bob's privkey from the cut and choose deck as selected by Alice
privM is Alice's counterpart
pubN and pubM are the corresponding pubkeys for these chosen privkeys
Alice timeout event is triggered if INSTANTDEX_LOCKTIME elapses from the start of a FSM instance. Bob timeout event is triggered after INSTANTDEX_LOCKTIME*2
*/
8 years ago
//#define BASILISK_DISABLETX
8 years ago
#define SCRIPT_OP_IF 0x63
#define SCRIPT_OP_ELSE 0x67
#define SCRIPT_OP_ENDIF 0x68
int32_t basilisk_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;
}
8 years ago
char str[65]; printf("bobtx dflag.%d %s\n",depositflag,bits256_str(str,cltvpub));
8 years ago
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 basilisk_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);
}
8 years ago
8 years ago
int32_t basilisk_numconfirms(struct supernet_info *myinfo,struct basilisk_rawtx *rawtx)
{
cJSON *argjson,*valuearray=0,*item; char *valstr; int32_t numconfirms,height,i,n;
8 years ago
#ifdef BASILISK_DISABLETX
8 years ago
return(10);
8 years ago
#endif
8 years ago
argjson = cJSON_CreateObject();
jaddbits256(argjson,"txid",rawtx->actualtxid);
jaddnum(argjson,"vout",0);
jaddstr(argjson,"coin",rawtx->coin->symbol);
if ( (valstr= basilisk_value(myinfo,rawtx->coin,0,0,myinfo->myaddr.persistent,argjson,0)) != 0 )
{
char str[65]; printf("%s %s valstr.(%s)\n",rawtx->name,bits256_str(str,rawtx->actualtxid),valstr);
if ( (valuearray= cJSON_Parse(valstr)) != 0 )
{
if ( is_cJSON_Array(valuearray) != 0 )
{
n = cJSON_GetArraySize(valuearray);
for (i=0; i<n; i++)
{
item = jitem(valuearray,i);
height = jint(valuearray,"height");
numconfirms = jint(valuearray,"numconfirms");
if ( height > 0 && numconfirms >= 0 )
{
free_json(argjson);
free_json(valuearray);
free(valstr);
printf("%s height.%d -> numconfirms.%d\n",bits256_str(str,rawtx->actualtxid),height,numconfirms);
}
}
}
}
}
free_json(argjson);
if ( valuearray != 0 )
free_json(valuearray);
free(valstr);
return(-1);
}
bits256 basilisk_swap_broadcast(char *name,struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,uint8_t *data,int32_t datalen)
{
bits256 txid; char *signedtx;
memset(txid.bytes,0,sizeof(txid));
if ( data != 0 && datalen != 0 )
{
8 years ago
#ifdef BASILISK_DISABLETX
8 years ago
txid = bits256_doublesha256(0,data,datalen);
return(txid);
8 years ago
#endif
8 years ago
signedtx = malloc(datalen*2 + 1);
init_hexbytes_noT(signedtx,data,datalen);
txid = iguana_sendrawtransaction(myinfo,coin,signedtx);
char str[65]; printf("%s <- sendrawtransaction %s.(%s)\n",name,signedtx,bits256_str(str,txid));
free(signedtx);
}
return(txid);
}
8 years ago
int32_t basilisk_rawtx_spend(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen)
8 years ago
{
8 years ago
char *rawtxbytes,*signedtx,hexstr[999],wifstr[128]; cJSON *txobj,*vins,*item,*sobj,*privkeys; int32_t retval = -1; struct vin_info V; uint32_t locktime=0;
8 years ago
memset(&V,0,sizeof(V));
8 years ago
if ( dest == &swap->aliceclaim )
locktime = swap->locktime + INSTANTDEX_LOCKTIME;
8 years ago
V.signers[0].privkey = privkey;
8 years ago
bitcoin_pubkey33(myinfo->ctx,V.signers[0].pubkey,privkey);
8 years ago
privkeys = cJSON_CreateArray();
bitcoin_priv2wif(wifstr,privkey,rawtx->coin->chain->wiftype);
jaddistr(privkeys,wifstr);
8 years ago
if ( privkey2 != 0 )
{
V.signers[1].privkey = *privkey2;
8 years ago
bitcoin_pubkey33(myinfo->ctx,V.signers[1].pubkey,*privkey2);
8 years ago
bitcoin_priv2wif(wifstr,*privkey2,rawtx->coin->chain->wiftype);
jaddistr(privkeys,wifstr);
8 years ago
V.N = V.M = 2;
char str[65]; printf("add second privkey.(%s) %s\n",jprint(privkeys,0),bits256_str(str,*privkey2));
} else V.N = V.M = 1;
8 years ago
V.suppress_pubkeys = dest->suppress_pubkeys;
8 years ago
if ( userdata != 0 && userdatalen > 0 )
{
memcpy(V.userdata,userdata,userdatalen);
8 years ago
V.userdatalen = userdatalen;
8 years ago
}
8 years ago
txobj = bitcoin_txcreate(rawtx->coin->chain->isPoS,locktime,rawtx->coin->chain->locktime_txversion);
8 years ago
vins = cJSON_CreateArray();
item = cJSON_CreateObject();
8 years ago
if ( bits256_nonz(rawtx->actualtxid) != 0 )
jaddbits256(item,"txid",rawtx->actualtxid);
else jaddbits256(item,"txid",rawtx->signedtxid);
8 years ago
jaddnum(item,"vout",0);
sobj = cJSON_CreateObject();
init_hexbytes_noT(hexstr,rawtx->spendscript,rawtx->spendlen);
jaddstr(sobj,"hex",hexstr);
jadd(item,"scriptPubKey",sobj);
8 years ago
if ( locktime != 0 )
jaddnum(item,"sequence",0);
8 years ago
jaddi(vins,item);
jdelete(txobj,"vin");
jadd(txobj,"vin",vins);
8 years ago
printf("basilisk_rawtx_spend locktime.%u/%u for %s spendscript.%s -> %s, suppress.%d\n",rawtx->locktime,dest->locktime,rawtx->name,hexstr,dest->name,dest->suppress_pubkeys);
8 years ago
txobj = bitcoin_txoutput(txobj,dest->spendscript,dest->spendlen,dest->amount);
if ( (rawtxbytes= bitcoin_json2hex(myinfo,rawtx->coin,&dest->txid,txobj,&V)) != 0 )
{
8 years ago
//printf("spend rawtx.(%s) userdatalen.%d\n",rawtxbytes,userdatalen);
8 years ago
if ( (signedtx= iguana_signrawtx(myinfo,rawtx->coin,&dest->signedtxid,&dest->completed,vins,rawtxbytes,privkeys,&V)) != 0 )
{
8 years ago
//printf("rawtx spend signedtx.(%s)\n",signedtx);
8 years ago
dest->datalen = (int32_t)strlen(signedtx) >> 1;
dest->txbytes = calloc(1,dest->datalen);
decode_hex(dest->txbytes,dest->datalen,signedtx);
free(signedtx);
retval = 0;
}
free(rawtxbytes);
}
free_json(privkeys);
free_json(txobj);
return(retval);
}
8 years ago
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)
{
8 years ago
// add verification
swap->otherfee.txbytes = calloc(1,datalen);
memcpy(swap->otherfee.txbytes,data,datalen);
8 years ago
swap->otherfee.actualtxid = swap->otherfee.signedtxid = bits256_doublesha256(0,data,datalen);
8 years ago
return(0);
}
8 years ago
int32_t basilisk_rawtx_spendscript(struct supernet_info *myinfo,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *data,int32_t datalen)
{
int32_t retval=-1,hexlen,n; cJSON *txobj,*skey,*vouts,*vout; char *hexstr;
if ( rawtx->txbytes == 0 )
{
rawtx->txbytes = calloc(1,datalen);
memcpy(rawtx->txbytes,data,datalen);
rawtx->datalen = datalen;
}
else if ( datalen != rawtx->datalen || memcmp(rawtx->txbytes,data,datalen) != 0 )
{
printf("%s rawtx data compare error, len %d vs %d\n",rawtx->name,rawtx->datalen,datalen);
return(-1);
}
if ( (txobj= bitcoin_data2json(rawtx->coin,&rawtx->signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),rawtx->txbytes,rawtx->datalen)) != 0 )
{
8 years ago
rawtx->actualtxid = rawtx->signedtxid;
char str[65]; printf("got txid.%s\n",bits256_str(str,rawtx->signedtxid));
8 years ago
rawtx->locktime = rawtx->msgtx.lock_time;
8 years ago
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n )
{
vout = jitem(vouts,v);
if ( j64bits(vout,"satoshis") == rawtx->amount && (skey= jobj(vout,"scriptPubKey")) != 0 && (hexstr= jstr(skey,"hex")) != 0 )
{
if ( (hexlen= (int32_t)strlen(hexstr) >> 1) < sizeof(rawtx->spendscript) )
{
decode_hex(rawtx->spendscript,hexlen,hexstr);
rawtx->spendlen = hexlen;
retval = 0;
}
} else printf("%s ERROR.(%s)\n",rawtx->name,jprint(txobj,0));
}
free_json(txobj);
}
return(retval);
}
8 years ago
int32_t basilisk_verify_bobdeposit(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
8 years ago
uint8_t userdata[512]; int32_t len = 0;
8 years ago
if ( basilisk_rawtx_spendscript(myinfo,&swap->bobdeposit,0,data,datalen) == 0 )
{
userdata[len++] = 0x51; // true -> if path
return(basilisk_rawtx_spend(myinfo,swap,&swap->aliceclaim,&swap->bobdeposit,swap->myprivs[0],0,userdata,len));
} else return(-1);
8 years ago
}
int32_t basilisk_bobdeposit_refund(struct supernet_info *myinfo,struct basilisk_swap *swap)
{
uint8_t userdata[512]; int32_t i,len = 0;
userdata[len++] = sizeof(swap->privBn);
for (i=0; i<sizeof(swap->privBn); i++)
8 years ago
userdata[len++] = swap->privBn.bytes[sizeof(swap->privBn) - 1 - i];
8 years ago
userdata[len++] = 0; // false -> else path
return(basilisk_rawtx_spend(myinfo,swap,&swap->bobrefund,&swap->bobdeposit,swap->myprivs[0],0,userdata,len));
}
int32_t basilisk_bobpayment_reclaim(struct supernet_info *myinfo,struct basilisk_swap *swap)
{
uint8_t userdata[512]; int32_t len = 0;
8 years ago
userdata[len++] = 0x51; // true -> if path
8 years ago
return(basilisk_rawtx_spend(myinfo,swap,&swap->bobreclaim,&swap->bobpayment,swap->myprivs[1],0,userdata,len));
8 years ago
}
int32_t basilisk_verify_bobpaid(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
8 years ago
uint8_t userdata[512]; int32_t i,len = 0;
8 years ago
if ( basilisk_rawtx_spendscript(myinfo,&swap->bobpayment,0,data,datalen) == 0 )
{
// OP_HASH160 <hash(alice_privM)> OP_EQUALVERIFY <alice_pubA0> OP_CHECKSIG
userdata[len++] = sizeof(swap->privAm);
for (i=0; i<sizeof(swap->privAm); i++)
userdata[len++] = swap->privAm.bytes[sizeof(swap->privAm) - 1 - i];
userdata[len++] = 0; // false -> else path
char str[65]; printf("bobpaid.(%s)\n",bits256_str(str,swap->privAm));
return(basilisk_rawtx_spend(myinfo,swap,&swap->alicespend,&swap->bobpayment,swap->myprivs[0],0,userdata,len));
} else return(-1);
8 years ago
}
int32_t basilisk_alicepayment_spend(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *dest)
{
return(basilisk_rawtx_spend(myinfo,swap,dest,&swap->alicepayment,swap->privAm,&swap->privBn,0,0));
8 years ago
}
int32_t basilisk_verify_alicepaid(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
8 years ago
if ( basilisk_rawtx_spendscript(myinfo,&swap->alicepayment,0,data,datalen) == 0 )
return(0);
else return(-1);
8 years ago
}
8 years ago
int32_t basilisk_privAm_extract(struct supernet_info *myinfo,struct basilisk_swap *swap)
8 years ago
{
8 years ago
// need to scan blockchain for alicespend of bobpayment
// search for swap->bobpayment.actualtxid in spends
8 years ago
if ( bits256_nonz(swap->privAm) != 0 && swap->bobspend.txbytes == 0 )
{
char str[65]; printf("have privAm.%s\n",bits256_str(str,swap->privAm));
return(basilisk_alicepayment_spend(myinfo,swap,&swap->bobspend));
}
8 years ago
return(-1);
}
8 years ago
8 years ago
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_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);
if ( basilisk_verify_pubpair(&wrongfirstbyte,swap,swap->choosei,pubkey33[0],pubi,txid) == 0 )
{
if ( swap->iambob != 0 )
swap->privAm = privkey;
else swap->privBn = privkey;
8 years ago
char str[65]; printf("privi verified.(%s)\n",bits256_str(str,privkey));
8 years ago
return(0);
}
}
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);
}
int32_t basilisk_privBn_extract(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
8 years ago
{
// need to scan blockchain for bobrefund
// search for swap->bobrefund.actualtxid in spends
8 years ago
if ( basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_privi) == 0 )
{
if ( bits256_nonz(swap->privBn) != 0 && swap->alicereclaim.txbytes == 0 )
{
char str[65]; printf("have privBn.%s\n",bits256_str(str,swap->privBn));
return(basilisk_alicepayment_spend(myinfo,swap,&swap->alicereclaim));
}
}
8 years ago
return(-1);
}
8 years ago
// end of coin protocol dependent
8 years ago
bits256 instantdex_derivekeypair(struct supernet_info *myinfo,bits256 *newprivp,uint8_t pubkey[33],bits256 privkey,bits256 orderhash)
{
bits256 sharedsecret;
sharedsecret = curve25519_shared(privkey,orderhash);
vcalc_sha256cat(newprivp->bytes,orderhash.bytes,sizeof(orderhash),sharedsecret.bytes,sizeof(sharedsecret));
return(bitcoin_pubkey33(myinfo->ctx,pubkey,*newprivp));
}
int32_t instantdex_pubkeyargs(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t numpubs,bits256 privkey,bits256 hash,int32_t firstbyte)
{
char buf[3]; int32_t i,n,m,len=0; bits256 pubi; uint64_t txid; uint8_t secret160[20],pubkey[33];
sprintf(buf,"%c0",'A' - 0x02 + firstbyte);
if ( numpubs > 2 )
{
if ( swap->numpubs+2 >= numpubs )
return(numpubs);
printf(">>>>>> start generating %s\n",buf);
}
for (i=n=m=0; i<numpubs*100 && n<numpubs; i++)
{
pubi = instantdex_derivekeypair(myinfo,&privkey,pubkey,privkey,hash);
//printf("i.%d n.%d numpubs.%d %02x vs %02x\n",i,n,numpubs,pubkey[0],firstbyte);
if ( pubkey[0] != firstbyte )
continue;
if ( n < 2 )
{
if ( bits256_nonz(swap->mypubs[n]) == 0 )
{
swap->myprivs[n] = privkey;
memcpy(swap->mypubs[n].bytes,pubkey+1,sizeof(bits256));
8 years ago
if ( swap->iambob != 0 )
{
if ( n == 0 )
swap->pubB0 = swap->mypubs[n];
else if ( n == 1 )
swap->pubB1 = swap->mypubs[n];
}
else if ( swap->iambob == 0 )
{
if ( n == 0 )
swap->pubA0 = swap->mypubs[n];
else if ( n == 1 )
swap->pubA1 = swap->mypubs[n];
}
8 years ago
}
}
8 years ago
if ( m < INSTANTDEX_DECKSIZE )
8 years ago
{
swap->privkeys[m] = privkey;
calc_rmd160_sha256(secret160,privkey.bytes,sizeof(privkey));
memcpy(&txid,secret160,sizeof(txid));
len += iguana_rwnum(1,(uint8_t *)&swap->deck[m][0],sizeof(txid),&txid);
len += iguana_rwnum(1,(uint8_t *)&swap->deck[m][1],sizeof(pubi.txid),&pubi.txid);
m++;
if ( m > swap->numpubs )
swap->numpubs = m;
}
n++;
}
if ( n > 2 || m > 2 )
printf("n.%d m.%d len.%d numpubs.%d\n",n,m,len,swap->numpubs);
return(n);
}
8 years ago
int32_t basilisk_rawtx_return(struct supernet_info *myinfo,struct basilisk_rawtx *rawtx,cJSON *item,cJSON *privkeyarray,int32_t lockinputs)
{
8 years ago
char *signedtx,*txbytes; cJSON *vins; int32_t i,n,retval = -1;
8 years ago
if ( (txbytes= jstr(item,"rawtx")) != 0 && (vins= jobj(item,"vins")) != 0 )
{
8 years ago
if ( (signedtx= iguana_signrawtx(myinfo,rawtx->coin,&rawtx->signedtxid,&rawtx->completed,vins,txbytes,privkeyarray,0)) != 0 )
8 years ago
{
if ( lockinputs != 0 )
8 years ago
{
8 years ago
iguana_unspentslock(myinfo,rawtx->coin,vins);
8 years ago
if ( (n= cJSON_GetArraySize(vins)) != 0 )
{
bits256 txid; int32_t vout;
for (i=0; i<n; i++)
{
item = jitem(vins,i);
txid = jbits256(item,"txid");
8 years ago
vout = jint(item,"vout");
8 years ago
if ( bits256_nonz(txid) != 0 )
{
char str[65]; printf("call addspend.(%s) v.%d\n",bits256_str(str,txid),vout);
8 years ago
basilisk_addspend(myinfo,rawtx->coin->symbol,txid,vout,1);
8 years ago
}
}
}
}
8 years ago
rawtx->datalen = (int32_t)strlen(signedtx) >> 1;
rawtx->txbytes = calloc(1,rawtx->datalen);
decode_hex(rawtx->txbytes,rawtx->datalen,signedtx);
8 years ago
//printf("SIGNEDTX.(%s)\n",signedtx);
8 years ago
free(signedtx);
retval = 0;
} else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll
}
return(retval);
}
8 years ago
int32_t basilisk_rawtx_gen(char *str,struct supernet_info *myinfo,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf)
8 years ago
{
8 years ago
struct iguana_waddress *waddr; struct iguana_waccount *wacct; char coinaddr[64],wifstr[64],*retstr,scriptstr[1024]; uint32_t basilisktag; int32_t flag,i,n,retval = -1; cJSON *valsobj,*retarray=0,*privkeyarray,*addresses;
8 years ago
if ( (waddr= iguana_getaccountaddress(myinfo,rawtx->coin,0,0,rawtx->coin->changeaddr,"change")) == 0 )
8 years ago
{
8 years ago
printf("no change addr error\n");
return(-1);
8 years ago
}
8 years ago
init_hexbytes_noT(scriptstr,script,scriptlen);
8 years ago
privkeyarray = cJSON_CreateArray();
8 years ago
addresses = cJSON_CreateArray();
if ( rawtx->coin->changeaddr[0] == 0 )
bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->chain->pubtype,waddr->rmd160,20);
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 )
8 years ago
{
8 years ago
bitcoin_priv2wif(wifstr,waddr->privkey,rawtx->coin->chain->wiftype);
8 years ago
jaddistr(privkeyarray,waddr->wifstr);
8 years ago
}
8 years ago
basilisktag = (uint32_t)rand();
jaddistr(addresses,coinaddr);
valsobj = cJSON_CreateObject();
8 years ago
//jadd(valsobj,"addresses",addresses);
8 years ago
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);
8 years ago
rawtx->locktime = locktime;
printf("%s locktime.%u\n",rawtx->name,locktime);
8 years ago
if ( (retstr= basilisk_bitcoinrawtx(myinfo,rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj)) != 0 )
8 years ago
{
8 years ago
printf("%s got.(%s)\n",str,retstr);
8 years ago
flag = 0;
8 years ago
if ( (retarray= cJSON_Parse(retstr)) != 0 )
8 years ago
{
8 years ago
if ( is_cJSON_Array(retarray) != 0 )
8 years ago
{
8 years ago
n = cJSON_GetArraySize(retarray);
for (i=0; i<n; i++)
{
if ( (retval= basilisk_rawtx_return(myinfo,rawtx,jitem(retarray,i),privkeyarray,lockinputs)) == 0 )
break;
}
} else retval = basilisk_rawtx_return(myinfo,rawtx,retarray,privkeyarray,lockinputs);
free(retarray);
} else printf("error parsing.(%s)\n",retstr);
8 years ago
free(retstr);
8 years ago
} else printf("error creating %s feetx\n",iambob != 0 ? "BOB" : "ALICE");
8 years ago
free_json(privkeyarray);
8 years ago
free_json(valsobj);
8 years ago
printf("rawtx retval.%d\n",retval);
8 years ago
return(retval);
}
8 years ago
void basilisk_rawtx_setparms(char *name,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)
8 years ago
{
8 years ago
strcpy(rawtx->name,name);
8 years ago
rawtx->coin = coin;
rawtx->numconfirms = numconfirms;
8 years ago
if ( (rawtx->amount= satoshis) < 10000 )
rawtx->amount = 10000;
8 years ago
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);
8 years ago
printf("%s spendlen.%d %s <- %.8f\n",name,rawtx->spendlen,rawtx->destaddr,dstr(rawtx->amount));
} else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->vouttype,rawtx->destaddr);
8 years ago
}
struct basilisk_swap *bitcoin_swapinit(struct supernet_info *myinfo,struct basilisk_swap *swap)
{
8 years ago
struct iguana_info *coin; uint8_t *alicepub33=0,*bobpub33=0; int32_t x = -1;
8 years ago
if ( strcmp("BTC",swap->req.src) == 0 )
{
swap->bobcoin = iguana_coinfind("BTC");
swap->bobsatoshis = swap->req.srcamount;
swap->bobconfirms = (1 + sqrt(dstr(swap->bobsatoshis) * .1));
swap->alicecoin = iguana_coinfind(swap->req.dest);
swap->alicesatoshis = swap->req.destamount;
swap->aliceconfirms = swap->bobconfirms * 3;
}
else if ( strcmp("BTC",swap->req.dest) == 0 )
{
swap->bobcoin = iguana_coinfind("BTC");
swap->bobsatoshis = swap->req.destamount;
swap->bobconfirms = (1 + sqrt(dstr(swap->bobsatoshis) * .1));
swap->alicecoin = iguana_coinfind(swap->req.src);
swap->alicesatoshis = swap->req.srcamount;
swap->aliceconfirms = swap->bobconfirms * 3;
}
else
{
if ( (coin= iguana_coinfind(swap->req.src)) != 0 )
{
if ( coin->chain->havecltv != 0 )
{
swap->bobcoin = coin;
swap->bobsatoshis = swap->req.srcamount;
swap->alicecoin = iguana_coinfind(swap->req.dest);
swap->alicesatoshis = swap->req.destamount;
}
else if ( (coin= iguana_coinfind(swap->req.dest)) != 0 )
{
if ( coin->chain->havecltv != 0 )
{
swap->bobcoin = coin;
swap->bobsatoshis = swap->req.destamount;
swap->alicecoin = iguana_coinfind(swap->req.src);
swap->alicesatoshis = swap->req.srcamount;
}
}
}
}
if ( swap->bobcoin == 0 || swap->alicecoin == 0 )
{
printf("missing BTC.%p or missing alicecoin.%p\n",swap->bobcoin,swap->alicecoin);
free(swap);
return(0);
}
if ( swap->bobconfirms == 0 )
swap->bobconfirms = swap->bobcoin->chain->minconfirms;
if ( swap->aliceconfirms == 0 )
swap->aliceconfirms = swap->alicecoin->chain->minconfirms;
8 years ago
if ( (swap->bobinsurance= (swap->bobsatoshis / INSTANTDEX_INSURANCEDIV)) < 10000 )
swap->bobinsurance = 10000;
if ( (swap->aliceinsurance= (swap->alicesatoshis / INSTANTDEX_INSURANCEDIV)) < 10000 )
swap->aliceinsurance = 10000;
8 years ago
strcpy(swap->bobstr,swap->bobcoin->symbol);
strcpy(swap->alicestr,swap->alicecoin->symbol);
swap->started = (uint32_t)time(NULL);
swap->expiration = swap->req.timestamp + INSTANTDEX_LOCKTIME*2;
8 years ago
swap->locktime = swap->req.timestamp + INSTANTDEX_LOCKTIME;
8 years ago
OS_randombytes((uint8_t *)&swap->choosei,sizeof(swap->choosei));
if ( swap->choosei < 0 )
swap->choosei = -swap->choosei;
swap->choosei %= INSTANTDEX_DECKSIZE;
swap->otherchoosei = -1;
8 years ago
swap->myhash = myinfo->myaddr.persistent;
if ( bits256_cmp(swap->myhash,swap->req.hash) == 0 )
{
swap->otherhash = swap->req.desthash;
if ( strcmp(swap->req.src,swap->bobstr) == 0 )
swap->iambob = 1;
8 years ago
else if ( strcmp(swap->req.dest,swap->alicestr) == 0 )
8 years ago
{
printf("neither bob nor alice error\n");
return(0);
}
}
else if ( bits256_cmp(swap->myhash,swap->req.desthash) == 0 )
{
swap->otherhash = swap->req.hash;
if ( strcmp(swap->req.dest,swap->bobstr) == 0 )
swap->iambob = 1;
else if ( strcmp(swap->req.src,swap->alicestr) != 0 )
{
printf("neither alice nor bob error\n");
return(0);
}
}
else
{
printf("neither src nor dest error\n");
return(0);
}
8 years ago
if ( bits256_nonz(myinfo->persistent_priv) == 0 || (x= instantdex_pubkeyargs(myinfo,swap,2 + INSTANTDEX_DECKSIZE,myinfo->persistent_priv,swap->myhash,0x02+swap->iambob)) != 2 + INSTANTDEX_DECKSIZE )
8 years ago
{
8 years ago
printf("couldnt generate privkeys %d\n",x);
8 years ago
return(0);
}
8 years ago
if ( swap->iambob != 0 )
{
8 years ago
basilisk_rawtx_setparms("myfee",myinfo,swap,&swap->myfee,swap->bobcoin,0,0,swap->bobsatoshis/INSTANTDEX_DECKSIZE,0,0);
basilisk_rawtx_setparms("otherfee",myinfo,swap,&swap->otherfee,swap->alicecoin,0,0,swap->alicesatoshis/INSTANTDEX_DECKSIZE,0,0);
8 years ago
bobpub33 = myinfo->persistent_pubkey33;
}
else
{
8 years ago
basilisk_rawtx_setparms("otherfee",myinfo,swap,&swap->otherfee,swap->bobcoin,0,0,swap->bobsatoshis/INSTANTDEX_DECKSIZE,0,0);
basilisk_rawtx_setparms("myfee",myinfo,swap,&swap->myfee,swap->alicecoin,0,0,swap->alicesatoshis/INSTANTDEX_DECKSIZE,0,0);
8 years ago
alicepub33 = myinfo->persistent_pubkey33;
}
8 years ago
basilisk_rawtx_setparms("bobdeposit",myinfo,swap,&swap->bobdeposit,swap->bobcoin,swap->bobconfirms,0,swap->bobsatoshis*1.1,4,0);
basilisk_rawtx_setparms("bobrefund",myinfo,swap,&swap->bobrefund,swap->bobcoin,1,4,swap->bobsatoshis*1.1-swap->bobcoin->txfee,1,bobpub33);
8 years ago
swap->bobrefund.suppress_pubkeys = 1;
8 years ago
basilisk_rawtx_setparms("aliceclaim",myinfo,swap,&swap->aliceclaim,swap->bobcoin,1,4,swap->bobsatoshis*1.1-swap->bobcoin->txfee,1,alicepub33);
8 years ago
swap->aliceclaim.suppress_pubkeys = 1;
8 years ago
basilisk_rawtx_setparms("bobpayment",myinfo,swap,&swap->bobpayment,swap->bobcoin,swap->bobconfirms,0,swap->bobsatoshis,3,0);
basilisk_rawtx_setparms("alicespend",myinfo,swap,&swap->alicespend,swap->bobcoin,swap->bobconfirms,3,swap->bobsatoshis - swap->bobcoin->txfee,1,alicepub33);
8 years ago
swap->alicespend.suppress_pubkeys = 1;
8 years ago
basilisk_rawtx_setparms("bobreclaim",myinfo,swap,&swap->bobreclaim,swap->bobcoin,swap->bobconfirms,3,swap->bobsatoshis - swap->bobcoin->txfee,1,bobpub33);
8 years ago
swap->bobreclaim.suppress_pubkeys = 1;
8 years ago
basilisk_rawtx_setparms("alicepayment",myinfo,swap,&swap->alicepayment,swap->alicecoin,swap->aliceconfirms,0,swap->alicesatoshis,2,0);
basilisk_rawtx_setparms("bobspend",myinfo,swap,&swap->bobspend,swap->alicecoin,swap->aliceconfirms,2,swap->alicesatoshis-swap->alicecoin->txfee,1,bobpub33);
8 years ago
swap->bobspend.suppress_pubkeys = 1;
8 years ago
basilisk_rawtx_setparms("alicereclaim",myinfo,swap,&swap->alicereclaim,swap->alicecoin,swap->aliceconfirms,2,swap->alicesatoshis-swap->alicecoin->txfee,1,alicepub33);
8 years ago
swap->alicereclaim.suppress_pubkeys = 1;
8 years ago
swap->sleeptime = 3 - swap->iambob;
8 years ago
return(swap);
}
// end of alice/bob code
8 years ago
void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx)
{
if ( rawtx->txbytes != 0 )
free(rawtx->txbytes), rawtx->txbytes = 0;
}
8 years ago
void basilisk_swap_finished(struct supernet_info *myinfo,struct basilisk_swap *swap)
{
swap->finished = (uint32_t)time(NULL);
// save to permanent storage
8 years ago
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);
8 years ago
basilisk_rawtx_purge(&swap->bobrefund);
8 years ago
}
void basilisk_swap_purge(struct supernet_info *myinfo,struct basilisk_swap *swap)
{
int32_t i,n;
8 years ago
// while still in orderbook, wait
return;
8 years ago
portable_mutex_lock(&myinfo->DEX_swapmutex);
n = myinfo->numswaps;
for (i=0; i<n; i++)
if ( myinfo->swaps[i] == swap )
{
myinfo->swaps[i] = myinfo->swaps[--myinfo->numswaps];
myinfo->swaps[myinfo->numswaps] = 0;
basilisk_swap_finished(myinfo,swap);
break;
}
portable_mutex_unlock(&myinfo->DEX_swapmutex);
}
8 years ago
int32_t basilisk_verify_statebits(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
iguana_rwnum(0,data,sizeof(swap->otherstatebits),&swap->otherstatebits);
return(0);
}
8 years ago
int32_t basilisk_verify_choosei(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
8 years ago
int32_t otherchoosei=-1,i,len = 0;
8 years ago
if ( datalen == sizeof(otherchoosei)+sizeof(bits256)*2 )
8 years ago
{
8 years ago
len += iguana_rwnum(0,data,sizeof(otherchoosei),&otherchoosei);
if ( otherchoosei >= 0 && otherchoosei < INSTANTDEX_DECKSIZE )
{
printf("otherchoosei.%d\n",otherchoosei);
swap->otherchoosei = otherchoosei;
if ( swap->iambob != 0 )
{
for (i=0; i<32; i++)
swap->pubA0.bytes[i] = data[len++];
for (i=0; i<32; i++)
swap->pubA1.bytes[i] = data[len++];
8 years ago
char str[65]; printf("GOT pubA0/1 %s\n",bits256_str(str,swap->pubA0));
8 years ago
}
else
{
for (i=0; i<32; i++)
swap->pubB0.bytes[i] = data[len++];
for (i=0; i<32; i++)
swap->pubB1.bytes[i] = data[len++];
}
return(0);
}
8 years ago
}
8 years ago
printf("illegal otherchoosei.%d datalen.%d vs %d\n",otherchoosei,datalen,(int32_t)(sizeof(otherchoosei)+sizeof(bits256)*2));
8 years ago
return(-1);
8 years ago
}
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;
8 years ago
printf("verify otherdeck\n");
8 years ago
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_privkeys(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t datalen)
{
8 years ago
int32_t i,j,wrongfirstbyte=0,errs=0,len = 0; bits256 otherpriv,pubi; uint8_t secret160[20],otherpubkey[33]; uint64_t txid;
8 years ago
printf("verify privkeys choosei.%d otherchoosei.%d datalen.%d vs %d\n",swap->choosei,swap->otherchoosei,datalen,(int32_t)sizeof(swap->privkeys)+20+32);
if ( swap->cutverified == 0 && swap->otherchoosei >= 0 && datalen == sizeof(swap->privkeys)+20+32 )
8 years ago
{
8 years ago
for (i=errs=0; i<sizeof(swap->privkeys)/sizeof(*swap->privkeys); i++)
8 years ago
{
for (j=0; j<32; j++)
otherpriv.bytes[j] = data[len++];
8 years ago
if ( i != swap->choosei )
8 years ago
{
pubi = bitcoin_pubkey33(myinfo->ctx,otherpubkey,otherpriv);
calc_rmd160_sha256(secret160,otherpriv.bytes,sizeof(otherpriv));
memcpy(&txid,secret160,sizeof(txid));
8 years ago
errs += basilisk_verify_pubpair(&wrongfirstbyte,swap,i,otherpubkey[0],pubi,txid);
8 years ago
}
8 years ago
}
if ( errs == 0 && wrongfirstbyte == 0 )
8 years ago
{
8 years ago
swap->cutverified = 1, printf("CUT VERIFIED\n");
8 years ago
if ( swap->iambob != 0 )
{
8 years ago
for (i=0; i<32; i++)
swap->pubAm.bytes[i] = data[len++];
8 years ago
for (i=0; i<20; i++)
swap->secretAm[i] = data[len++];
}
else
{
8 years ago
for (i=0; i<32; i++)
swap->pubBn.bytes[i] = data[len++];
8 years ago
for (i=0; i<20; i++)
swap->secretBn[i] = data[len++];
}
} else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs);
8 years ago
}
8 years ago
printf("privkeys errs.%d wrongfirstbyte.%d\n",errs,wrongfirstbyte);
8 years ago
return(errs);
}
8 years ago
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);
}
8 years ago
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 )
{
8 years ago
rawtx->actualtxid = basilisk_swap_broadcast(rawtx->name,myinfo,swap,rawtx->coin,rawtx->txbytes,rawtx->datalen);
8 years ago
char str[65],str2[65]; printf("rawtxsend %s vs %s\n",bits256_str(str,rawtx->signedtxid),bits256_str(str2,rawtx->actualtxid));
8 years ago
if ( bits256_nonz(rawtx->actualtxid) != 0 && msgbits != 0 )
return(basilisk_swapsend(myinfo,swap,msgbits,rawtx->txbytes,rawtx->datalen,nextbits));
8 years ago
else return(nextbits);
8 years ago
} else printf("error from basilisk_swapdata_rawtx %p len.%d\n",rawtx->txbytes,rawtx->datalen);
8 years ago
return(0);
}
8 years ago
void basilisk_swap01(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
int32_t datalen;
datalen = basilisk_swapdata_deck(myinfo,swap,data,maxlen);
8 years ago
printf("send deck.%d\n",datalen);
8 years ago
swap->statebits |= basilisk_swapsend(myinfo,swap,0x02,data,datalen,0x01);
}
void basilisk_swap02(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
8 years ago
basilisk_swap01(myinfo,swap,data,maxlen);
8 years ago
printf("check for other deck\n");
8 years ago
if ( basilisk_swapget(myinfo,swap,0x02,data,maxlen,basilisk_verify_otherdeck) == 0 )
swap->statebits |= 0x02;
}
void basilisk_swap04(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
8 years ago
int32_t i,datalen; char str[65];
8 years ago
//if ( (rand() % 10) == 0 )
8 years ago
basilisk_swap02(myinfo,swap,data,maxlen);
8 years ago
datalen = iguana_rwnum(1,data,sizeof(swap->choosei),&swap->choosei);
if ( swap->iambob != 0 )
{
for (i=0; i<32; i++)
data[datalen++] = swap->pubB0.bytes[i];
for (i=0; i<32; i++)
data[datalen++] = swap->pubB1.bytes[i];
8 years ago
printf("SEND pubB0/1 %s\n",bits256_str(str,swap->pubB0));
8 years ago
}
else
{
for (i=0; i<32; i++)
data[datalen++] = swap->pubA0.bytes[i];
for (i=0; i<32; i++)
data[datalen++] = swap->pubA1.bytes[i];
8 years ago
printf("SEND pubA0/1 %s\n",bits256_str(str,swap->pubA0));
8 years ago
}
swap->statebits |= basilisk_swapsend(myinfo,swap,0x08,data,datalen,0x04);
}
void basilisk_swap08(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
8 years ago
uint8_t pubkey33[33]; char str[65];
8 years ago
//if ( (rand() % 10) == 0 )
8 years ago
basilisk_swap04(myinfo,swap,data,maxlen);
printf("check otherchoosei\n");
8 years ago
if ( basilisk_swapget(myinfo,swap,0x08,data,maxlen,basilisk_verify_choosei) == 0 )
{
if ( swap->iambob != 0 )
{
8 years ago
if ( bits256_nonz(swap->privBn) == 0 )
{
swap->privBn = swap->privkeys[swap->otherchoosei];
memset(&swap->privkeys[swap->otherchoosei],0,sizeof(swap->privkeys[swap->otherchoosei]));
calc_rmd160_sha256(swap->secretBn,swap->privBn.bytes,sizeof(swap->privBn));
swap->pubBn = bitcoin_pubkey33(myinfo->ctx,pubkey33,swap->privBn);
printf("set privBn.%s\n",bits256_str(str,swap->privBn));
}
8 years ago
}
else
{
8 years ago
if ( bits256_nonz(swap->privAm) == 0 )
{
swap->privAm = swap->privkeys[swap->otherchoosei];
memset(&swap->privkeys[swap->otherchoosei],0,sizeof(swap->privkeys[swap->otherchoosei]));
calc_rmd160_sha256(swap->secretAm,swap->privAm.bytes,sizeof(swap->privAm));
swap->pubAm = bitcoin_pubkey33(myinfo->ctx,pubkey33,swap->privAm);
printf("set privAm.%s\n",bits256_str(str,swap->privAm));
}
8 years ago
}
swap->statebits |= 0x08;
}
}
void basilisk_swap10(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
{
int32_t i,j,datalen;
8 years ago
if ( (rand() % 10) == 0 )
basilisk_swap08(myinfo,swap,data,maxlen);
8 years ago
datalen = 0;
for (i=0; i<sizeof(swap->privkeys)/sizeof(*swap->privkeys); i++)
{
for (j=0; j<32; j++)
data[datalen++] = (i == swap->otherchoosei) ? 0 : swap->privkeys[i].bytes[j];
}
if ( swap->iambob != 0 )
{
for (i=0; i<32; i++)
data[datalen++] = swap->pubBn.bytes[i];
for (i=0; i<20; i++)
data[datalen++] = swap->secretBn[i];
}
else
{
for (i=0; i<32; i++)
data[datalen++] = swap->pubAm.bytes[i];
for (i=0; i<20; i++)
data[datalen++] = swap->secretAm[i];
}
8 years ago
printf("send privkeys.%d\n",datalen);
8 years ago
swap->statebits |= basilisk_swapsend(myinfo,swap,0x20,data,datalen,0x10);
}
8 years ago
void basilisk_alicepayment(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn)
{
alicepayment->spendlen = basilisk_alicescript(alicepayment->spendscript,0,alicepayment->destaddr,coin->chain->p2shtype,pubAm,pubBn);
basilisk_rawtx_gen("alicepayment",myinfo,0,1,alicepayment,alicepayment->locktime,alicepayment->spendscript,alicepayment->spendlen,coin->chain->txfee,1);
}
8 years ago
void basilisk_swaploop(void *_swap)
{
8 years ago
uint8_t *data; int32_t i,j,maxlen,datalen; struct supernet_info *myinfo; struct basilisk_swap *swap = _swap;
8 years ago
myinfo = swap->myinfo;
8 years ago
fprintf(stderr,"start swap\n");
8 years ago
maxlen = 1024*1024 + sizeof(*swap);
8 years ago
data = malloc(maxlen);
while ( time(NULL) < swap->expiration )
{
8 years ago
fprintf(stderr,"r%u/q%u swapstate.%x\n",swap->req.requestid,swap->req.quoteid,swap->statebits);
8 years ago
if ( (swap->statebits & 0x01) == 0 ) // send pubkeys
8 years ago
basilisk_swap01(myinfo,swap,data,maxlen);
8 years ago
else if ( (swap->statebits & 0x02) == 0 ) // wait for pubkeys
8 years ago
basilisk_swap02(myinfo,swap,data,maxlen);
8 years ago
else if ( (swap->statebits & 0x04) == 0 ) // send choosei
8 years ago
basilisk_swap04(myinfo,swap,data,maxlen);
8 years ago
else if ( (swap->statebits & 0x08) == 0 ) // wait for choosei
8 years ago
basilisk_swap08(myinfo,swap,data,maxlen);
8 years ago
else if ( (swap->statebits & 0x10) == 0 && swap->otherchoosei >= 0 && swap->otherchoosei < INSTANTDEX_DECKSIZE ) // send all but one privkeys
8 years ago
basilisk_swap10(myinfo,swap,data,maxlen);
8 years ago
else if ( (swap->statebits & 0x20) == 0 ) // wait for all but one privkeys
{
8 years ago
if ( basilisk_swapget(myinfo,swap,0x20,data,maxlen,basilisk_verify_privkeys) == 0 )
swap->statebits |= 0x20;
8 years ago
}
8 years ago
else if ( (swap->statebits & 0x40) == 0 ) // send fee
8 years ago
{
8 years ago
if ( swap->myfee.txbytes == 0 )
{
8 years ago
for (i=0; i<20; i++)
printf("%02x",swap->secretAm[i]);
printf(" <- secretAm\n");
8 years ago
for (i=0; i<32; i++)
printf("%02x",swap->pubAm.bytes[i]);
printf(" <- pubAm\n");
8 years ago
for (i=0; i<20; i++)
printf("%02x",swap->secretBn[i]);
printf(" <- secretBn\n");
8 years ago
for (i=0; i<32; i++)
printf("%02x",swap->pubBn.bytes[i]);
printf(" <- pubBn\n");
8 years ago
for (i=0; i<32; i++)
printf("%02x",swap->pubA0.bytes[i]);
printf(" <- pubA0\n");
for (i=0; i<32; i++)
printf("%02x",swap->pubA1.bytes[i]);
printf(" <- pubA1\n");
for (i=0; i<32; i++)
printf("%02x",swap->pubB0.bytes[i]);
printf(" <- pubB0\n");
for (i=0; i<32; i++)
printf("%02x",swap->pubB1.bytes[i]);
printf(" <- pubB1\n");
8 years ago
if ( swap->iambob != 0 )
{
8 years ago
swap->bobpayment.spendlen = basilisk_bobscript(swap->bobpayment.spendscript,0,&swap->bobpayment.locktime,&swap->bobpayment.secretstart,swap,0);
8 years ago
swap->bobdeposit.spendlen = basilisk_bobscript(swap->bobdeposit.spendscript,0,&swap->bobdeposit.locktime,&swap->bobdeposit.secretstart,swap,1);
8 years ago
basilisk_rawtx_gen("deposit",myinfo,1,1,&swap->bobdeposit,swap->bobdeposit.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.spendlen,swap->bobdeposit.coin->chain->txfee,1);
basilisk_rawtx_gen("payment",myinfo,1,1,&swap->bobpayment,swap->bobpayment.locktime,swap->bobpayment.spendscript,swap->bobpayment.spendlen,swap->bobpayment.coin->chain->txfee,1);
8 years ago
if ( swap->bobdeposit.txbytes == 0 || swap->bobdeposit.spendlen == 0 || swap->bobpayment.txbytes == 0 || swap->bobpayment.spendlen == 0 )
{
printf("error bob generating deposit.%d or payment.%d\n",swap->bobdeposit.spendlen,swap->bobpayment.spendlen);
break;
}
}
else
{
8 years ago
basilisk_alicepayment(myinfo,swap->alicepayment.coin,&swap->alicepayment,swap->pubAm,swap->pubBn);
8 years ago
if ( swap->alicepayment.txbytes == 0 || swap->alicepayment.spendlen == 0 )
{
printf("error alice generating payment.%d\n",swap->alicepayment.spendlen);
break;
}
8 years ago
}
8 years ago
if ( basilisk_rawtx_gen("myfee",myinfo,swap->iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.spendlen,swap->myfee.coin->chain->txfee,1) == 0 )
8 years ago
swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40);
else
{
printf("error creating myfee\n");
break;
}
}
8 years ago
}
8 years ago
else if ( (swap->statebits & 0x80) == 0 ) // wait for fee
{
8 years ago
if ( basilisk_swapget(myinfo,swap,0x80,data,maxlen,basilisk_verify_otherfee) == 0 )
8 years ago
{
// verify and submit otherfee
swap->statebits |= 0x80;
8 years ago
swap->sleeptime = 1;
8 years ago
}
8 years ago
else if ( swap->sleeptime < 60 )
swap->sleeptime++;
8 years ago
}
else // both sides have setup required data and paid txfee
{
8 years ago
if ( swap->sleeptime < 60 )
swap->sleeptime++;
8 years ago
if ( swap->iambob != 0 )
{
if ( (swap->statebits & 0x100) == 0 )
8 years ago
{
8 years ago
swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x200,data,maxlen,&swap->bobdeposit,0x100);
8 years ago
basilisk_bobdeposit_refund(myinfo,swap);
8 years ago
swap->sleeptime = 1;
}
8 years ago
// [BLOCKING: altfound] make sure altpayment is confirmed and send payment
else if ( (swap->statebits & 0x1000) == 0 )
{
8 years ago
if ( basilisk_swapget(myinfo,swap,0x1000,data,maxlen,basilisk_verify_alicepaid) == 0 )
8 years ago
{
swap->statebits |= 0x1000;
8 years ago
swap->sleeptime = 1;
8 years ago
}
}
else if ( (swap->statebits & 0x2000) == 0 )
{
8 years ago
if ( basilisk_numconfirms(myinfo,&swap->alicepayment) >= swap->aliceconfirms )
8 years ago
{
8 years ago
swap->statebits |= 0x2000;
8 years ago
swap->sleeptime = 1;
}
8 years ago
}
else if ( (swap->statebits & 0x4000) == 0 )
8 years ago
{
8 years ago
swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000);
8 years ago
basilisk_bobpayment_reclaim(myinfo,swap);
8 years ago
swap->sleeptime = 1;
}
8 years ago
// [BLOCKING: privM] Bob waits for privAm either from Alice or alice blockchain
8 years ago
else if ( (swap->statebits & 0x40000) == 0 )
{
8 years ago
if ( basilisk_swapget(myinfo,swap,0x40000,data,maxlen,basilisk_verify_privi) == 0 ) // divulges privAm
{
swap->sleeptime = 1;
swap->statebits |= 0x40000;
8 years ago
basilisk_alicepayment_spend(myinfo,swap,&swap->bobspend);
8 years ago
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobspend,0x40000) == 0 )
8 years ago
printf("Bob error spending alice payment\n");
8 years ago
else
{
basilisk_swap_balancingtrade(myinfo,swap,1);
printf("Bob spends alicepayment\n");
}
8 years ago
break;
8 years ago
}
else if ( basilisk_privAm_extract(myinfo,swap) == 0 )
8 years ago
{
8 years ago
swap->sleeptime = 1;
8 years ago
swap->statebits |= 0x40000;
8 years ago
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobspend,0x40000) == 0 )
printf("Bob error spending alice payment after privAm\n");
8 years ago
else
{
basilisk_swap_balancingtrade(myinfo,swap,1);
printf("Bob spends alicepayment\n");
}
8 years ago
break;
8 years ago
}
8 years ago
else if ( swap->bobpayment.locktime != 0 && time(NULL) > swap->bobpayment.locktime )
8 years ago
{
8 years ago
// submit reclaim of payment
8 years ago
swap->sleeptime = 1;
8 years ago
swap->statebits |= (0x40000 | 0x80000);
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobreclaim,0) == 0 )
printf("Bob error reclaiming own payment after alice timed out\n");
8 years ago
else printf("Bob reclaimed own payment\n");
break;
8 years ago
}
8 years ago
}
else if ( (swap->statebits & 0x80000) == 0 )
{
if ( basilisk_numconfirms(myinfo,&swap->bobspend) >= swap->aliceconfirms )
8 years ago
{
8 years ago
swap->sleeptime = 1;
8 years ago
swap->statebits |= 0x80000 | 0x100000;
printf("Bob confirms spend of Alice's payment\n");
break;
8 years ago
}
}
8 years ago
else if ( (swap->statebits & 0x100000) == 0 )
8 years ago
{
8 years ago
if ( basilisk_numconfirms(myinfo,&swap->bobreclaim) >= 1 )
8 years ago
{
8 years ago
swap->sleeptime = 1;
8 years ago
swap->statebits |= 0x100000;
printf("Bob confirms reclain of payment\n");
break;
8 years ago
}
}
}
else
{
// [BLOCKING: depfound] Alice waits for deposit to confirm and sends altpayment
8 years ago
if ( swap->bobdeposit.locktime != 0 && time(NULL) > swap->bobdeposit.locktime )
8 years ago
{
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->aliceclaim,0) == 0 )
8 years ago
printf("Alice couldnt claim deposit\n");
else printf("Alice claimed deposit\n");
8 years ago
break;
}
else if ( basilisk_privBn_extract(myinfo,swap,data,maxlen) == 0 )
{
swap->sleeptime = 1;
swap->statebits |= 0x80000000;
8 years ago
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicereclaim,0x80000000) == 0 )
8 years ago
printf("Alice error sending alicereclaim\n");
8 years ago
else printf("Alice reclaimed her payment\n");
8 years ago
break;
8 years ago
}
else if ( (swap->statebits & 0x200) == 0 )
8 years ago
{
8 years ago
swap->sleeptime = 1;
8 years ago
if ( basilisk_swapget(myinfo,swap,0x200,data,maxlen,basilisk_verify_bobdeposit) == 0 )
8 years ago
{
// verify deposit and submit, set confirmed height
swap->statebits |= 0x200;
}
}
else if ( (swap->statebits & 0x400) == 0 )
{
8 years ago
if ( basilisk_numconfirms(myinfo,&swap->bobdeposit) >= swap->bobconfirms )
8 years ago
{
8 years ago
swap->statebits |= 0x400;
8 years ago
swap->sleeptime = 1;
}
8 years ago
}
else if ( (swap->statebits & 0x800) == 0 )
8 years ago
{
8 years ago
swap->sleeptime = 1;
8 years ago
swap->statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x1000,data,maxlen,&swap->alicepayment,0x800);
8 years ago
}
8 years ago
// [BLOCKING: payfound] make sure payment is confrmed and send in spend or see bob's reclaim and claim
8 years ago
else if ( (swap->statebits & 0x8000) == 0 )
{
8 years ago
if ( basilisk_swapget(myinfo,swap,0x8000,data,maxlen,basilisk_verify_bobpaid) == 0 )
8 years ago
{
// verify payment and submit, set confirmed height
8 years ago
swap->sleeptime = 1;
8 years ago
swap->statebits |= 0x8000;
}
}
else if ( (swap->statebits & 0x10000) == 0 )
{
8 years ago
if ( basilisk_numconfirms(myinfo,&swap->bobpayment) >= swap->bobconfirms )
8 years ago
{
8 years ago
swap->statebits |= 0x10000;
swap->sleeptime = 1;
8 years ago
}
}
else if ( (swap->statebits & 0x20000) == 0 )
{
8 years ago
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);
8 years ago
swap->sleeptime = 1;
8 years ago
basilisk_swap_balancingtrade(myinfo,swap,0);
8 years ago
}
8 years ago
}
else if ( (swap->statebits & 0x40000) == 0 )
{
8 years ago
if ( basilisk_numconfirms(myinfo,&swap->alicespend) >= swap->bobconfirms )
{
8 years ago
swap->sleeptime = 1;
8 years ago
swap->statebits |= 0x40000;
8 years ago
printf("Alice confirms spend of Bob's payment\n");
8 years ago
break;
8 years ago
}
8 years ago
}
}
}
8 years ago
if ( 1 || myinfo->RELAYID >= 0 )
8 years ago
sleep(1);
8 years ago
else
{
if ( swap->sleeptime > 0 )
sleep(swap->sleeptime);
}
8 years ago
}
8 years ago
if ( swap->iambob != 0 )
{
8 years ago
for (j=datalen=0; j<32; j++)
data[datalen++] = swap->privBn.bytes[j];
basilisk_swapsend(myinfo,swap,0x80000000,data,datalen,0x80000000);
printf("BOB reclaims refund\n");
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobrefund,0x80000000) == 0 ) // use secretBn
8 years ago
{
printf("Bob submit error getting refund of deposit\n");
}
}
printf("%s swap finished statebits %x\n",swap->iambob!=0?"BOB":"ALICE",swap->statebits);
8 years ago
basilisk_swap_purge(myinfo,swap);
}
8 years ago
struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,struct basilisk_request *rp)
8 years ago
{
int32_t i; struct basilisk_swap *swap = 0;
portable_mutex_lock(&myinfo->DEX_swapmutex);
for (i=0; i<myinfo->numswaps; i++)
if ( myinfo->swaps[i]->req.requestid == rp->requestid )
{
printf("basilisk_thread_start error trying to start requestid.%u which is already started\n",rp->requestid);
break;
}
if ( i == myinfo->numswaps && i < sizeof(myinfo->swaps)/sizeof(*myinfo->swaps) )
{
swap = calloc(1,sizeof(*swap));
swap->req = *rp;
swap->myinfo = myinfo;
8 years ago
printf("START swap requestid.%u\n",rp->requestid);
8 years ago
if ( bitcoin_swapinit(myinfo,swap) != 0 )
8 years ago
{
8 years ago
fprintf(stderr,"launch.%d %d\n",myinfo->numswaps,(int32_t)(sizeof(myinfo->swaps)/sizeof(*myinfo->swaps)));
8 years ago
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)basilisk_swaploop,(void *)swap) != 0 )
{
}
8 years ago
myinfo->swaps[myinfo->numswaps++] = swap;
8 years ago
}
8 years ago
}
portable_mutex_unlock(&myinfo->DEX_swapmutex);
return(swap);
}