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.
3754 lines
176 KiB
3754 lines
176 KiB
/******************************************************************************
|
|
* Copyright © 2014-2017 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. *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
/*
|
|
resume handling: list of tx broadcast, tx pending + required items, reconnect state machine or have statemachine assume off by one or state/otherstate specific handling
|
|
make sure to broadcast deposit before claiming refund, or to just skip it if neither is done
|
|
*/
|
|
|
|
#define DEX_SLEEP 10
|
|
#define BASILISK_DEFAULT_NUMCONFIRMS 5
|
|
|
|
// Todo: monitor blockchains, ie complete extracting scriptsig
|
|
// mode to autocreate required outputs
|
|
// more better LP commands
|
|
|
|
// depends on just three external functions:
|
|
// - basilisk_sendrawtransaction(myinfo,coin,signedtx);
|
|
// - basilisk_value(myinfo,rawtx->coin,0,0,myinfo->myaddr.persistent,argjson,0)
|
|
// basilisk_bitcoinrawtx(myinfo,rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj,V)
|
|
|
|
|
|
// included from basilisk.c
|
|
/* 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
|
|
*/
|
|
|
|
//#define DISABLE_CHECKSIG // unsolved MITM (evil peer)
|
|
|
|
/*
|
|
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:
|
|
#ifndef DISABLE_CHECKSIG
|
|
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
|
|
#else
|
|
OP_IF
|
|
<now + INSTANTDEX_LOCKTIME*2> OP_CLTV OP_DROP OP_SHA256 <sha256(alice_privA0)> OP_EQUAL
|
|
OP_ELSE
|
|
OP_HASH160 <hash(bob_privN)> OP_EQUALVERIFY OP_SHA256 <sha256(bob_privB0)> OP_EQUAL
|
|
OP_ENDIF
|
|
#endif
|
|
|
|
Bob paytx:
|
|
#ifndef DISABLE_CHECKSIG
|
|
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
|
|
#else
|
|
OP_IF
|
|
<now + INSTANTDEX_LOCKTIME> OP_CLTV OP_DROP OP_SHA256 <sha256(bob_privB1)> OP_EQUAL
|
|
OP_ELSE
|
|
OP_HASH160 <hash(alice_privM)> OP_EQUALVERIFY OP_SHA256 <sha256(alice_privA0)> OP_EQUAL
|
|
OP_ENDIF
|
|
#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
|
|
*/
|
|
|
|
/*
|
|
Bob sends bobdeposit and waits for alicepayment to confirm before sending bobpayment
|
|
Alice waits for bobdeposit to confirm and sends alicepayment
|
|
|
|
Alice spends bobpayment immediately divulging privAm
|
|
Bob spends alicepayment immediately after getting privAm and divulges privBn
|
|
|
|
Bob will spend bobdeposit after end of trade or INSTANTDEX_LOCKTIME, divulging privBn
|
|
Alice spends alicepayment as soon as privBn is seen
|
|
|
|
Bob will spend bobpayment after INSTANTDEX_LOCKTIME
|
|
Alice spends bobdeposit in 2*INSTANTDEX_LOCKTIME
|
|
*/
|
|
|
|
//Bobdeposit includes a covered put option for alicecoin, duration INSTANTDEX_LOCKTIME
|
|
//alicepayment includes a covered call option for alicecoin, duration (2*INSTANTDEX_LOCKTIME - elapsed)
|
|
|
|
|
|
/* in case of following states, some funds remain unclaimable, but all identified cases are due to one or both sides not spending when they were the only eligible party:
|
|
|
|
Bob failed to claim deposit during exclusive period and since alice put in the claim, the alicepayment is unspendable. if alice is nice, she can send privAm to Bob.
|
|
Apaymentspent.(0000000000000000000000000000000000000000000000000000000000000000) alice.0 bob.0
|
|
paymentspent.(f91da4e001360b95276448e7b01904d9ee4d15862c5af7f5c7a918df26030315) alice.0 bob.1
|
|
depositspent.(f34e04ad74e290f63f3d0bccb7d0d50abfa54eea58de38816fdc596a19767add) alice.1 bob.0
|
|
|
|
*/
|
|
|
|
int32_t basilisk_istrustedbob(struct supernet_info *myinfo,struct basilisk_swap *swap)
|
|
{
|
|
// for BTC and if trusted LP
|
|
return(0);
|
|
}
|
|
|
|
int32_t basilisk_priviextract(struct supernet_info *myinfo,struct iguana_info *coin,char *name,bits256 *destp,uint8_t secret160[20],bits256 srctxid,int32_t srcvout)
|
|
{
|
|
bits256 txid,privkey; char str[65]; int32_t i,vini,scriptlen; uint8_t rmd160[20],scriptsig[IGUANA_MAXSCRIPTSIZE];
|
|
memset(privkey.bytes,0,sizeof(privkey));
|
|
// use dex_listtransactions!
|
|
if ( (vini= iguana_vinifind(myinfo,coin,&txid,srctxid,srcvout)) >= 0 )
|
|
{
|
|
if ( (scriptlen= iguana_scriptsigextract(myinfo,coin,scriptsig,sizeof(scriptsig),txid,vini)) > 32 )
|
|
{
|
|
for (i=0; i<32; i++)
|
|
privkey.bytes[i] = scriptsig[scriptlen - 33 + i];
|
|
revcalc_rmd160_sha256(rmd160,privkey);//.bytes,sizeof(privkey));
|
|
if ( memcmp(secret160,rmd160,sizeof(rmd160)) == sizeof(rmd160) )
|
|
{
|
|
*destp = privkey;
|
|
printf("basilisk_priviextract found privi %s (%s)\n",name,bits256_str(str,privkey));
|
|
return(0);
|
|
}
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
void revcalc_rmd160_sha256(uint8_t rmd160[20],bits256 revhash)
|
|
{
|
|
bits256 hash; int32_t i;
|
|
for (i=0; i<32; i++)
|
|
hash.bytes[i] = revhash.bytes[31-i];
|
|
calc_rmd160_sha256(rmd160,hash.bytes,sizeof(hash));
|
|
}
|
|
|
|
bits256 revcalc_sha256(bits256 revhash)
|
|
{
|
|
bits256 hash,dest; int32_t i;
|
|
for (i=0; i<32; i++)
|
|
hash.bytes[i] = revhash.bytes[31-i];
|
|
vcalc_sha256(0,dest.bytes,hash.bytes,sizeof(hash));
|
|
return(dest);
|
|
}
|
|
|
|
#define SCRIPT_OP_IF 0x63
|
|
#define SCRIPT_OP_ELSE 0x67
|
|
#define SCRIPT_OP_ENDIF 0x68
|
|
|
|
bits256 basilisk_revealkey(bits256 privkey,bits256 pubkey)
|
|
{
|
|
bits256 reveal;
|
|
#ifdef DISABLE_CHECKSIG
|
|
vcalc_sha256(0,reveal.bytes,privkey.bytes,sizeof(privkey));
|
|
//reveal = revcalc_sha256(privkey);
|
|
char str[65],str2[65]; printf("priv.(%s) -> reveal.(%s)\n",bits256_str(str,privkey),bits256_str(str2,reveal));
|
|
#else
|
|
reveal = pubkey;
|
|
#endif
|
|
return(reveal);
|
|
}
|
|
|
|
int32_t basilisk_swap_bobredeemscript(int32_t depositflag,int32_t *secretstartp,uint8_t *redeemscript,uint32_t locktime,bits256 pubA0,bits256 pubB0,bits256 pubB1,bits256 privAm,bits256 privBn,uint8_t *secretAm,uint8_t *secretAm256,uint8_t *secretBn,uint8_t *secretBn256)
|
|
{
|
|
int32_t i,n=0; bits256 cltvpub,destpub,privkey; uint8_t pubkeyA[33],pubkeyB[33],*secret160,*secret256;
|
|
if ( depositflag != 0 )
|
|
{
|
|
pubkeyA[0] = 0x02, cltvpub = pubA0;
|
|
pubkeyB[0] = 0x03, destpub = pubB0;
|
|
privkey = privBn;
|
|
secret160 = secretBn;
|
|
secret256 = secretBn256;
|
|
}
|
|
else
|
|
{
|
|
pubkeyA[0] = 0x03, cltvpub = pubB1;
|
|
pubkeyB[0] = 0x02, destpub = pubA0;
|
|
privkey = privAm;
|
|
secret160 = secretAm;
|
|
secret256 = secretAm256;
|
|
}
|
|
//for (i=0; i<32; i++)
|
|
// printf("%02x",secret256[i]);
|
|
//printf(" <- secret256 depositflag.%d nonz.%d\n",depositflag,bits256_nonz(privkey));
|
|
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));
|
|
redeemscript[n++] = SCRIPT_OP_IF;
|
|
n = bitcoin_checklocktimeverify(redeemscript,n,locktime);
|
|
#ifdef DISABLE_CHECKSIG
|
|
n = bitcoin_secret256spend(redeemscript,n,cltvpub);
|
|
#else
|
|
n = bitcoin_pubkeyspend(redeemscript,n,pubkeyA);
|
|
#endif
|
|
redeemscript[n++] = SCRIPT_OP_ELSE;
|
|
if ( secretstartp != 0 )
|
|
*secretstartp = n + 2;
|
|
if ( 1 )
|
|
{
|
|
if ( 1 && bits256_nonz(privkey) != 0 )
|
|
{
|
|
uint8_t bufA[20],bufB[20];
|
|
revcalc_rmd160_sha256(bufA,privkey);
|
|
calc_rmd160_sha256(bufB,privkey.bytes,sizeof(privkey));
|
|
/*if ( memcmp(bufA,secret160,sizeof(bufA)) == 0 )
|
|
printf("MATCHES BUFA\n");
|
|
else if ( memcmp(bufB,secret160,sizeof(bufB)) == 0 )
|
|
printf("MATCHES BUFB\n");
|
|
else printf("secret160 matches neither\n");
|
|
for (i=0; i<20; i++)
|
|
printf("%02x",bufA[i]);
|
|
printf(" <- revcalc\n");
|
|
for (i=0; i<20; i++)
|
|
printf("%02x",bufB[i]);
|
|
printf(" <- calc\n");*/
|
|
memcpy(secret160,bufB,20);
|
|
}
|
|
n = bitcoin_secret160verify(redeemscript,n,secret160);
|
|
}
|
|
else
|
|
{
|
|
redeemscript[n++] = 0xa8;//IGUANA_OP_SHA256;
|
|
redeemscript[n++] = 0x20;
|
|
memcpy(&redeemscript[n],secret256,0x20), n += 0x20;
|
|
redeemscript[n++] = 0x88; //SCRIPT_OP_EQUALVERIFY;
|
|
}
|
|
#ifdef DISABLE_CHECKSIG
|
|
n = bitcoin_secret256spend(redeemscript,n,destpub);
|
|
#else
|
|
n = bitcoin_pubkeyspend(redeemscript,n,pubkeyB);
|
|
#endif
|
|
redeemscript[n++] = SCRIPT_OP_ENDIF;
|
|
return(n);
|
|
}
|
|
|
|
int32_t basilisk_bobscript(uint8_t *rmd160,uint8_t *redeemscript,int32_t *redeemlenp,uint8_t *script,int32_t n,uint32_t *locktimep,int32_t *secretstartp,struct basilisk_swapinfo *swap,int32_t depositflag)
|
|
{
|
|
if ( depositflag != 0 )
|
|
*locktimep = swap->started + swap->putduration + swap->callduration;
|
|
else *locktimep = swap->started + swap->putduration;
|
|
*redeemlenp = n = basilisk_swap_bobredeemscript(depositflag,secretstartp,redeemscript,*locktimep,swap->pubA0,swap->pubB0,swap->pubB1,swap->privAm,swap->privBn,swap->secretAm,swap->secretAm256,swap->secretBn,swap->secretBn256);
|
|
if ( n > 0 )
|
|
{
|
|
calc_rmd160_sha256(rmd160,redeemscript,n);
|
|
n = bitcoin_p2shspend(script,0,rmd160);
|
|
//for (i=0; i<n; i++)
|
|
// printf("%02x",script[i]);
|
|
//char str[65]; printf(" <- redeem.%d bobtx dflag.%d %s\n",n,depositflag,bits256_str(str,cltvpub));
|
|
}
|
|
return(n);
|
|
}
|
|
|
|
int32_t basilisk_alicescript(uint8_t *redeemscript,int32_t *redeemlenp,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;
|
|
*redeemlenp = bitcoin_MofNspendscript(p2sh160,redeemscript,n,&V);
|
|
bitcoin_address(msigaddr,altps2h,p2sh160,sizeof(p2sh160));
|
|
n = bitcoin_p2shspend(script,0,p2sh160);
|
|
//for (i=0; i<*redeemlenp; i++)
|
|
// printf("%02x",redeemscript[i]);
|
|
//printf(" <- redeemscript alicetx\n");
|
|
return(n);
|
|
}
|
|
|
|
int32_t basilisk_confirmsobj(cJSON *item)
|
|
{
|
|
int32_t height,numconfirms;
|
|
height = jint(item,"height");
|
|
numconfirms = jint(item,"numconfirms");
|
|
if ( height > 0 && numconfirms >= 0 )
|
|
return(numconfirms);
|
|
printf("basilisk_confirmsobj height.%d numconfirms.%d (%s)\n",height,numconfirms,jprint(item,0));
|
|
return(-1);
|
|
}
|
|
|
|
int32_t basilisk_numconfirms(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx)
|
|
{
|
|
cJSON *argjson,*valuearray=0; char *valstr; int32_t i,n,retval = -1;
|
|
#ifdef BASILISK_DISABLEWAITTX
|
|
return(100);
|
|
#endif
|
|
argjson = cJSON_CreateObject();
|
|
jaddbits256(argjson,"txid",rawtx->I.actualtxid);
|
|
jaddnum(argjson,"vout",0);
|
|
jaddstr(argjson,"coin",rawtx->coin->symbol);
|
|
if ( (valstr= basilisk_value(myinfo,rawtx->coin,0,0,swap->persistent_pubkey,argjson,0)) != 0 )
|
|
{
|
|
char str[65]; printf("basilisk_numconfirms required.%d %s %s valstr.(%s)\n",rawtx->I.numconfirms,rawtx->name,bits256_str(str,rawtx->I.actualtxid),valstr);
|
|
//basilisk_numconfirms required.0 alicespend 29a2a6b4a61b1da82096d533c71b6762d61a82ca771a633269d97c0ccb94fe85 valstr.({"result":"success","numconfirms":0,"address":"1JGvZ67oTdM7kCya4J8kj1uErbSRAoq3wH","satoshis":"1413818","value":0.01413818,"height":462440,"txid":"29a2a6b4a61b1da82096d533c71b6762d61a82ca771a633269d97c0ccb94fe85","vout":0,"coin":"BTC"})
|
|
|
|
if ( (valuearray= cJSON_Parse(valstr)) != 0 )
|
|
{
|
|
if ( valstr[0] == '[' && is_cJSON_Array(valuearray) != 0 )
|
|
{
|
|
n = cJSON_GetArraySize(valuearray);
|
|
for (i=0; i<n; i++)
|
|
{
|
|
printf("i.%d of n.%d\n",i,n);
|
|
if ( (retval= basilisk_confirmsobj(jitem(valuearray,i))) >= 0 )
|
|
break;
|
|
}
|
|
} else retval = basilisk_confirmsobj(valuearray);
|
|
free_json(valuearray);
|
|
} else printf("parse error\n");
|
|
free(valstr);
|
|
}
|
|
free_json(argjson);
|
|
printf("numconfirms.%d returned\n",retval);
|
|
return(retval);
|
|
}
|
|
|
|
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,*retstr; int32_t i;
|
|
memset(txid.bytes,0,sizeof(txid));
|
|
if ( data != 0 && datalen != 0 )
|
|
{
|
|
char str[65];
|
|
#ifdef BASILISK_DISABLESENDTX
|
|
txid = bits256_doublesha256(0,data,datalen);
|
|
printf("%s <- dont sendrawtransaction (%s)\n",name,bits256_str(str,txid));
|
|
return(txid);
|
|
#endif
|
|
signedtx = malloc(datalen*2 + 1);
|
|
init_hexbytes_noT(signedtx,data,datalen);
|
|
for (i=0; i<3; i++)
|
|
{
|
|
if ( (retstr= basilisk_sendrawtransaction(myinfo,coin,signedtx)) != 0 )
|
|
{
|
|
if ( is_hexstr(retstr,0) == 64 )
|
|
{
|
|
decode_hex(txid.bytes,32,retstr);
|
|
free(retstr);
|
|
printf("sendrawtransaction %s.(%s)\n",name,bits256_str(str,txid));
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
printf("sendrawtransaction %s error.(%s)\n",name,retstr);
|
|
free(retstr);
|
|
}
|
|
} else printf("sendrawtransaction %s got null return\n",name);
|
|
}
|
|
free(signedtx);
|
|
}
|
|
return(txid);
|
|
}
|
|
|
|
int32_t _basilisk_rawtx_sign(struct supernet_info *myinfo,int32_t height,uint32_t timestamp,uint32_t locktime,uint32_t sequenceid,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr)
|
|
{
|
|
char *rawtxbytes=0,*signedtx=0,hexstr[999],wifstr[128]; cJSON *txobj,*vins,*item,*sobj,*privkeys; int32_t needsig=1,retval = -1; struct vin_info *V;
|
|
V = calloc(256,sizeof(*V));
|
|
V[0].signers[0].privkey = privkey;
|
|
bitcoin_pubkey33(myinfo->ctx,V[0].signers[0].pubkey,privkey);
|
|
privkeys = cJSON_CreateArray();
|
|
bitcoin_priv2wif(wifstr,privkey,rawtx->coin->chain->wiftype);
|
|
jaddistr(privkeys,wifstr);
|
|
if ( privkey2 != 0 )
|
|
{
|
|
V[0].signers[1].privkey = *privkey2;
|
|
bitcoin_pubkey33(myinfo->ctx,V[0].signers[1].pubkey,*privkey2);
|
|
bitcoin_priv2wif(wifstr,*privkey2,rawtx->coin->chain->wiftype);
|
|
jaddistr(privkeys,wifstr);
|
|
V[0].N = V[0].M = 2;
|
|
//char str[65]; printf("add second privkey.(%s) %s\n",jprint(privkeys,0),bits256_str(str,*privkey2));
|
|
} else V[0].N = V[0].M = 1;
|
|
V[0].suppress_pubkeys = dest->I.suppress_pubkeys;
|
|
V[0].ignore_cltverr = ignore_cltverr;
|
|
if ( dest->I.redeemlen != 0 )
|
|
memcpy(V[0].p2shscript,dest->redeemscript,dest->I.redeemlen), V[0].p2shlen = dest->I.redeemlen;
|
|
txobj = bitcoin_txcreate(rawtx->coin->symbol,rawtx->coin->chain->isPoS,locktime,userdata == 0 ? 1 : 1,timestamp);//rawtx->coin->chain->locktime_txversion);
|
|
vins = cJSON_CreateArray();
|
|
item = cJSON_CreateObject();
|
|
if ( userdata != 0 && userdatalen > 0 )
|
|
{
|
|
memcpy(V[0].userdata,userdata,userdatalen);
|
|
V[0].userdatalen = userdatalen;
|
|
init_hexbytes_noT(hexstr,userdata,userdatalen);
|
|
jaddstr(item,"userdata",hexstr);
|
|
#ifdef DISABLE_CHECKSIG
|
|
needsig = 0;
|
|
#endif
|
|
}
|
|
//printf("rawtx B\n");
|
|
if ( bits256_nonz(rawtx->I.actualtxid) != 0 )
|
|
jaddbits256(item,"txid",rawtx->I.actualtxid);
|
|
else jaddbits256(item,"txid",rawtx->I.signedtxid);
|
|
jaddnum(item,"vout",0);
|
|
sobj = cJSON_CreateObject();
|
|
init_hexbytes_noT(hexstr,rawtx->spendscript,rawtx->I.spendlen);
|
|
jaddstr(sobj,"hex",hexstr);
|
|
jadd(item,"scriptPubKey",sobj);
|
|
jaddnum(item,"suppress",dest->I.suppress_pubkeys);
|
|
jaddnum(item,"sequence",sequenceid);
|
|
if ( (dest->I.redeemlen= rawtx->I.redeemlen) != 0 )
|
|
{
|
|
init_hexbytes_noT(hexstr,rawtx->redeemscript,rawtx->I.redeemlen);
|
|
memcpy(dest->redeemscript,rawtx->redeemscript,rawtx->I.redeemlen);
|
|
jaddstr(item,"redeemScript",hexstr);
|
|
}
|
|
jaddi(vins,item);
|
|
jdelete(txobj,"vin");
|
|
jadd(txobj,"vin",vins);
|
|
//printf("basilisk_rawtx_sign locktime.%u/%u for %s spendscript.%s -> %s, suppress.%d\n",rawtx->I.locktime,dest->I.locktime,rawtx->name,hexstr,dest->name,dest->I.suppress_pubkeys);
|
|
txobj = bitcoin_txoutput(txobj,dest->spendscript,dest->I.spendlen,dest->I.amount);
|
|
if ( (rawtxbytes= bitcoin_json2hex(myinfo,rawtx->coin,&dest->I.txid,txobj,V)) != 0 )
|
|
{
|
|
//printf("rawtx.(%s) vins.%p\n",rawtxbytes,vins);
|
|
if ( needsig == 0 )
|
|
signedtx = rawtxbytes;
|
|
if ( signedtx != 0 || (signedtx= iguana_signrawtx(myinfo,rawtx->coin,height,&dest->I.signedtxid,&dest->I.completed,vins,rawtxbytes,privkeys,V)) != 0 )
|
|
{
|
|
dest->I.datalen = (int32_t)strlen(signedtx) >> 1;
|
|
if ( dest->I.datalen <= sizeof(dest->txbytes) )
|
|
decode_hex(dest->txbytes,dest->I.datalen,signedtx);
|
|
else printf("DEX tx is too big %d vs %d\n",dest->I.datalen,(int32_t)sizeof(dest->txbytes));
|
|
if ( signedtx != rawtxbytes )
|
|
free(signedtx);
|
|
if ( dest->I.completed != 0 )
|
|
retval = 0;
|
|
else printf("couldnt complete sign transaction %s\n",rawtx->name);
|
|
} else printf("error signing\n");
|
|
free(rawtxbytes);
|
|
} else printf("error making rawtx\n");
|
|
free_json(privkeys);
|
|
free_json(txobj);
|
|
free(V);
|
|
return(retval);
|
|
}
|
|
|
|
int32_t basilisk_rawtx_sign(struct supernet_info *myinfo,int32_t height,struct basilisk_swap *swap,struct basilisk_rawtx *dest,struct basilisk_rawtx *rawtx,bits256 privkey,bits256 *privkey2,uint8_t *userdata,int32_t userdatalen,int32_t ignore_cltverr)
|
|
{
|
|
uint32_t timestamp,locktime=0,sequenceid = 0xffffffff;
|
|
timestamp = swap->I.started;
|
|
if ( dest == &swap->aliceclaim )
|
|
locktime = swap->bobdeposit.I.locktime + 1, sequenceid = 0;
|
|
else if ( dest == &swap->bobreclaim )
|
|
locktime = swap->bobpayment.I.locktime + 1, sequenceid = 0;
|
|
return(_basilisk_rawtx_sign(myinfo,height,timestamp,locktime,sequenceid,dest,rawtx,privkey,privkey2,userdata,userdatalen,ignore_cltverr));
|
|
}
|
|
|
|
cJSON *basilisk_privkeyarray(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *vins)
|
|
{
|
|
cJSON *privkeyarray,*item,*sobj; struct iguana_waddress *waddr; struct iguana_waccount *wacct; char coinaddr[64],account[128],wifstr[64],str[65],*hexstr; uint8_t script[1024]; int32_t i,n,len,vout; bits256 txid,privkey;
|
|
privkeyarray = cJSON_CreateArray();
|
|
//printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr);
|
|
if ( (n= cJSON_GetArraySize(vins)) > 0 )
|
|
{
|
|
for (i=0; i<n; i++)
|
|
{
|
|
item = jitem(vins,i);
|
|
txid = jbits256(item,"txid");
|
|
vout = jint(item,"vout");
|
|
if ( bits256_nonz(txid) != 0 && vout >= 0 )
|
|
{
|
|
iguana_txidcategory(myinfo,coin,account,coinaddr,txid,vout);
|
|
if ( coinaddr[0] == 0 && (sobj= jobj(item,"scriptPubKey")) != 0 && (hexstr= jstr(sobj,"hex")) != 0 && is_hexstr(hexstr,0) > 0 )
|
|
{
|
|
len = (int32_t)strlen(hexstr) >> 1;
|
|
if ( len < (sizeof(script) << 1) )
|
|
{
|
|
decode_hex(script,len,hexstr);
|
|
if ( len == 25 && script[0] == 0x76 && script[1] == 0xa9 && script[2] == 0x14 )
|
|
bitcoin_address(coinaddr,coin->chain->pubtype,script+3,20);
|
|
}
|
|
}
|
|
if ( coinaddr[0] != 0 )
|
|
{
|
|
if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 )
|
|
{
|
|
bitcoin_priv2wif(wifstr,waddr->privkey,coin->chain->wiftype);
|
|
jaddistr(privkeyarray,waddr->wifstr);
|
|
}
|
|
else if ( smartaddress(myinfo,&privkey,coinaddr) >= 0 )
|
|
{
|
|
bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype);
|
|
jaddistr(privkeyarray,wifstr);
|
|
}
|
|
else printf("cant find (%s) in wallet\n",coinaddr);
|
|
} else printf("cant coinaddr from (%s).v%d\n",bits256_str(str,txid),vout);
|
|
} else printf("invalid txid/vout %d of %d\n",i,n);
|
|
}
|
|
}
|
|
return(privkeyarray);
|
|
}
|
|
|
|
int32_t basilisk_rawtx_return(struct supernet_info *myinfo,int32_t height,struct basilisk_rawtx *rawtx,cJSON *item,int32_t lockinputs,struct vin_info *V)
|
|
{
|
|
char *signedtx,*txbytes; cJSON *vins,*privkeyarray; int32_t i,n,retval = -1;
|
|
if ( (txbytes= jstr(item,"rawtx")) != 0 && (vins= jobj(item,"vins")) != 0 )
|
|
{
|
|
privkeyarray = basilisk_privkeyarray(myinfo,rawtx->coin,vins);
|
|
if ( (signedtx= iguana_signrawtx(myinfo,rawtx->coin,height,&rawtx->I.signedtxid,&rawtx->I.completed,vins,txbytes,privkeyarray,V)) != 0 )
|
|
{
|
|
if ( lockinputs != 0 )
|
|
{
|
|
//printf("lockinputs\n");
|
|
iguana_RTunspentslock(myinfo,rawtx->coin,vins);
|
|
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");
|
|
vout = jint(item,"vout");
|
|
}
|
|
}
|
|
}
|
|
rawtx->I.datalen = (int32_t)strlen(signedtx) >> 1;
|
|
//rawtx->txbytes = calloc(1,rawtx->I.datalen);
|
|
decode_hex(rawtx->txbytes,rawtx->I.datalen,signedtx);
|
|
//printf("%s SIGNEDTX.(%s)\n",rawtx->name,signedtx);
|
|
free(signedtx);
|
|
retval = 0;
|
|
} else printf("error signrawtx\n"); //do a very short timeout so it finishes via local poll
|
|
free_json(privkeyarray);
|
|
}
|
|
return(retval);
|
|
}
|
|
|
|
int32_t _basilisk_rawtx_gen(char *str,struct supernet_info *myinfo,uint32_t swapstarted,uint8_t *pubkey33,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,int32_t delay)
|
|
{
|
|
char *retstr,*jsonstr,scriptstr[1024],coinaddr[64]; uint32_t basilisktag; int32_t flag,i,n,retval = -1; cJSON *addresses,*valsobj,*retarray=0; struct vin_info *V;
|
|
//bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33);
|
|
if ( rawtx->coin->changeaddr[0] == 0 )
|
|
{
|
|
bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->chain->pubtype,pubkey33,33);
|
|
printf("set change address.(%s)\n",rawtx->coin->changeaddr);
|
|
}
|
|
init_hexbytes_noT(scriptstr,script,scriptlen);
|
|
basilisktag = (uint32_t)rand();
|
|
valsobj = cJSON_CreateObject();
|
|
jaddstr(valsobj,"coin",rawtx->coin->symbol);
|
|
jaddstr(valsobj,"spendscript",scriptstr);
|
|
jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr);
|
|
jadd64bits(valsobj,"satoshis",rawtx->I.amount);
|
|
if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 )
|
|
txfee = 50000;
|
|
jadd64bits(valsobj,"txfee",txfee);
|
|
jaddnum(valsobj,"minconf",minconf);
|
|
if ( locktime == 0 )
|
|
locktime = (uint32_t)time(NULL) - 777;
|
|
jaddnum(valsobj,"locktime",locktime);
|
|
jaddnum(valsobj,"timeout",30000);
|
|
jaddnum(valsobj,"timestamp",swapstarted+delay);
|
|
addresses = cJSON_CreateArray();
|
|
bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,pubkey33,33);
|
|
jaddistr(addresses,coinaddr);
|
|
jadd(valsobj,"addresses",addresses);
|
|
rawtx->I.locktime = locktime;
|
|
printf("%s locktime.%u\n",rawtx->name,locktime);
|
|
V = calloc(256,sizeof(*V));
|
|
if ( (retstr= basilisk_bitcoinrawtx(myinfo,rawtx->coin,"",basilisktag,jint(valsobj,"timeout"),valsobj,V)) != 0 )
|
|
{
|
|
printf("%s %s basilisk_bitcoinrawtx.(%s) txfee %.8f\n",rawtx->name,str,retstr,dstr(txfee));
|
|
flag = 0;
|
|
if ( (retarray= cJSON_Parse(retstr)) != 0 )
|
|
{
|
|
if ( is_cJSON_Array(retarray) != 0 )
|
|
{
|
|
n = cJSON_GetArraySize(retarray);
|
|
for (i=0; i<n; i++)
|
|
{
|
|
if ( (retval= basilisk_rawtx_return(myinfo,rawtx->coin->longestchain,rawtx,jitem(retarray,i),lockinputs,V)) == 0 )
|
|
{
|
|
rawtx->vins = jduplicate(jobj(jitem(retarray,i),"vins"));
|
|
jsonstr = jprint(rawtx->vins,0);
|
|
safecopy(rawtx->vinstr,jsonstr,sizeof(rawtx->vinstr));
|
|
free(jsonstr);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retval = basilisk_rawtx_return(myinfo,rawtx->coin->longestchain,rawtx,retarray,lockinputs,V);
|
|
rawtx->vins = jduplicate(jobj(retarray,"vins"));
|
|
jsonstr = jprint(rawtx->vins,0);
|
|
safecopy(rawtx->vinstr,jsonstr,sizeof(rawtx->vinstr));
|
|
free(jsonstr);
|
|
}
|
|
free(retarray);
|
|
} else printf("error parsing.(%s)\n",retstr);
|
|
free(retstr);
|
|
} else printf("error creating %s %s\n",iambob != 0 ? "BOB" : "ALICE",rawtx->name);
|
|
free_json(valsobj);
|
|
free(V);
|
|
return(retval);
|
|
}
|
|
|
|
int32_t basilisk_rawtx_gen(char *str,struct supernet_info *myinfo,uint32_t swapstarted,uint8_t *pubkey33,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,int32_t delay)
|
|
{
|
|
int32_t retval,len; uint64_t newtxfee; struct iguana_info *coin;
|
|
if ( (coin= rawtx->coin) == 0 || strcmp(coin->symbol,"BTC") != 0 )
|
|
return(_basilisk_rawtx_gen(str,myinfo,swapstarted,pubkey33,iambob,lockinputs,rawtx,locktime,script,scriptlen,txfee,minconf,delay));
|
|
retval = _basilisk_rawtx_gen(str,myinfo,swapstarted,pubkey33,iambob,0,rawtx,locktime,script,scriptlen,txfee,minconf,delay);
|
|
len = rawtx->I.datalen;
|
|
if ( coin->estimatedfee == 0 )
|
|
coin->estimatedfee = iguana_getestimatedfee(myinfo,coin);
|
|
newtxfee = coin->estimatedfee * len;
|
|
if ( newtxfee > txfee )
|
|
{
|
|
retval = _basilisk_rawtx_gen(str,myinfo,swapstarted,pubkey33,iambob,lockinputs,rawtx,locktime,script,scriptlen,newtxfee,minconf,delay);
|
|
printf("txfee %.8f -> newtxfee %.8f\n",dstr(txfee),dstr(newtxfee));
|
|
}
|
|
return(retval);
|
|
}
|
|
|
|
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->I.datalen != 0 && rawtx->I.datalen <= maxlen )
|
|
{
|
|
memcpy(data,rawtx->txbytes,rawtx->I.datalen);
|
|
return(rawtx);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
int32_t basilisk_verify_otherfee(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
|
|
{
|
|
struct basilisk_swap *swap = ptr;
|
|
// add verification and broadcast
|
|
//swap->otherfee.txbytes = calloc(1,datalen);
|
|
memcpy(swap->otherfee.txbytes,data,datalen);
|
|
swap->otherfee.I.datalen = datalen;
|
|
swap->otherfee.I.actualtxid = swap->otherfee.I.signedtxid = bits256_doublesha256(0,data,datalen);
|
|
basilisk_txlog(myinfo,swap,&swap->otherfee,-1);
|
|
return(0);
|
|
}
|
|
|
|
int32_t basilisk_rawtx_spendscript(struct basilisk_swap *swap,int32_t height,struct basilisk_rawtx *rawtx,int32_t v,uint8_t *recvbuf,int32_t recvlen,int32_t suppress_pubkeys)
|
|
{
|
|
int32_t datalen=0,retval=-1,hexlen,n; uint8_t *data; cJSON *txobj,*skey,*vouts,*vout; char *hexstr; bits256 txid;
|
|
datalen = recvbuf[0];
|
|
datalen += (int32_t)recvbuf[1] << 8;
|
|
if ( datalen > 65536 )
|
|
return(-1);
|
|
rawtx->I.redeemlen = recvbuf[2];
|
|
data = &recvbuf[3];
|
|
if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 )
|
|
memcpy(rawtx->redeemscript,&data[datalen],rawtx->I.redeemlen);
|
|
//printf("recvlen.%d datalen.%d redeemlen.%d\n",recvlen,datalen,rawtx->redeemlen);
|
|
if ( rawtx->I.datalen == 0 )
|
|
{
|
|
//rawtx->txbytes = calloc(1,datalen);
|
|
memcpy(rawtx->txbytes,data,datalen);
|
|
rawtx->I.datalen = datalen;
|
|
}
|
|
else if ( datalen != rawtx->I.datalen || memcmp(rawtx->txbytes,data,datalen) != 0 )
|
|
{
|
|
int32_t i; for (i=0; i<datalen; i++)
|
|
printf("%02x",data[i]);
|
|
printf(" <- received\n");
|
|
for (i=0; i<rawtx->I.datalen; i++)
|
|
printf("%02x",rawtx->txbytes[i]);
|
|
printf(" <- rawtx\n");
|
|
printf("%s rawtx data compare error, len %d vs %d <<<<<<<<<< warning\n",rawtx->name,rawtx->I.datalen,datalen);
|
|
return(-1);
|
|
}
|
|
txid = bits256_doublesha256(0,data,datalen);
|
|
char str[65]; printf("rawtx.%s txid %s\n",rawtx->name,bits256_str(str,txid));
|
|
if ( bits256_cmp(txid,rawtx->I.actualtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 )
|
|
rawtx->I.actualtxid = txid;
|
|
if ( (txobj= bitcoin_data2json(rawtx->coin,height,&rawtx->I.signedtxid,&rawtx->msgtx,rawtx->extraspace,sizeof(rawtx->extraspace),data,datalen,0,suppress_pubkeys)) != 0 )
|
|
{
|
|
rawtx->I.actualtxid = rawtx->I.signedtxid;
|
|
//char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,rawtx->signedtxid),jprint(txobj,0));
|
|
rawtx->I.locktime = rawtx->msgtx.lock_time;
|
|
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && v < n )
|
|
{
|
|
vout = jitem(vouts,v);
|
|
if ( j64bits(vout,"satoshis") == rawtx->I.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->I.spendlen = hexlen;
|
|
bitcoin_address(rawtx->p2shaddr,rawtx->coin->chain->p2shtype,rawtx->spendscript,hexlen);
|
|
if ( swap != 0 )
|
|
basilisk_txlog(swap->myinfoptr,swap,rawtx,-1); // bobdeposit, bobpayment or alicepayment
|
|
retval = 0;
|
|
}
|
|
} else printf("%s ERROR.(%s)\n",rawtx->name,jprint(txobj,0));
|
|
}
|
|
free_json(txobj);
|
|
}
|
|
return(retval);
|
|
}
|
|
|
|
void basilisk_swap_coinaddr(struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,char *coinaddr,uint8_t *data,int32_t datalen)
|
|
{
|
|
cJSON *txobj,*vouts,*vout,*addresses,*item,*skey; uint8_t extraspace[8192]; bits256 signedtxid; struct iguana_msgtx msgtx; char *addr; int32_t n,m,suppress_pubkeys = 0;
|
|
if ( (txobj= bitcoin_data2json(coin,coin->longestchain,&signedtxid,&msgtx,extraspace,sizeof(extraspace),data,datalen,0,suppress_pubkeys)) != 0 )
|
|
{
|
|
//char str[65]; printf("got txid.%s (%s)\n",bits256_str(str,signedtxid),jprint(txobj,0));
|
|
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 )
|
|
{
|
|
vout = jitem(vouts,0);
|
|
//printf("VOUT.(%s)\n",jprint(vout,0));
|
|
if ( (skey= jobj(vout,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 )
|
|
{
|
|
item = jitem(addresses,0);
|
|
//printf("item.(%s)\n",jprint(item,0));
|
|
if ( (addr= jstr(item,0)) != 0 )
|
|
{
|
|
safecopy(coinaddr,addr,64);
|
|
//printf("extracted.(%s)\n",coinaddr);
|
|
}
|
|
}
|
|
}
|
|
free_json(txobj);
|
|
}
|
|
}
|
|
|
|
int32_t basilisk_swapuserdata(uint8_t *userdata,bits256 privkey,int32_t ifpath,bits256 signpriv,uint8_t *redeemscript,int32_t redeemlen)
|
|
{
|
|
int32_t i,len = 0;
|
|
#ifdef DISABLE_CHECKSIG
|
|
userdata[len++] = sizeof(signpriv);
|
|
for (i=0; i<sizeof(privkey); i++)
|
|
userdata[len++] = signpriv.bytes[i];
|
|
#endif
|
|
if ( bits256_nonz(privkey) != 0 )
|
|
{
|
|
userdata[len++] = sizeof(privkey);
|
|
for (i=0; i<sizeof(privkey); i++)
|
|
userdata[len++] = privkey.bytes[i];
|
|
}
|
|
userdata[len++] = 0x51 * ifpath; // ifpath == 1 -> if path, 0 -> else path
|
|
return(len);
|
|
}
|
|
|
|
/* 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*/
|
|
|
|
void basilisk_dontforget_userdata(char *userdataname,FILE *fp,uint8_t *script,int32_t scriptlen)
|
|
{
|
|
int32_t i; char scriptstr[513];
|
|
if ( scriptlen != 0 )
|
|
{
|
|
for (i=0; i<scriptlen; i++)
|
|
sprintf(&scriptstr[i << 1],"%02x",script[i]);
|
|
scriptstr[i << 1] = 0;
|
|
fprintf(fp,"\",\"%s\":\"%s\"",userdataname,scriptstr);
|
|
}
|
|
}
|
|
|
|
void basilisk_dontforget(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,int32_t locktime,bits256 triggertxid)
|
|
{
|
|
char zeroes[32],fname[512],str[65],coinaddr[64],secretAmstr[41],secretAm256str[65],secretBnstr[41],secretBn256str[65]; FILE *fp; int32_t i,len; uint8_t redeemscript[256],script[256];
|
|
sprintf(fname,"%s/SWAPS/%u-%u.%s",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid,rawtx->name), OS_compatible_path(fname);
|
|
coinaddr[0] = secretAmstr[0] = secretAm256str[0] = secretBnstr[0] = secretBn256str[0] = 0;
|
|
memset(zeroes,0,sizeof(zeroes));
|
|
if ( (fp= fopen(fname,"wb")) != 0 )
|
|
{
|
|
fprintf(fp,"{\"name\":\"%s\",\"coin\":\"%s\"",rawtx->name,rawtx->coin->symbol);
|
|
if ( rawtx->I.datalen > 0 )
|
|
{
|
|
fprintf(fp,",\"tx\":\"");
|
|
for (i=0; i<rawtx->I.datalen; i++)
|
|
fprintf(fp,"%02x",rawtx->txbytes[i]);
|
|
fprintf(fp,"\",\"txid\":\"%s\"",bits256_str(str,bits256_doublesha256(0,rawtx->txbytes,rawtx->I.datalen)));
|
|
if ( rawtx == &swap->bobdeposit || rawtx == &swap->bobpayment )
|
|
{
|
|
basilisk_swap_coinaddr(myinfo,swap,swap->bobcoin,coinaddr,rawtx->txbytes,rawtx->I.datalen);
|
|
if ( coinaddr[0] != 0 )
|
|
{
|
|
if ( rawtx == &swap->bobdeposit )
|
|
safecopy(swap->Bdeposit,coinaddr,sizeof(swap->Bdeposit));
|
|
else safecopy(swap->Bpayment,coinaddr,sizeof(swap->Bpayment));
|
|
}
|
|
}
|
|
}
|
|
if ( swap->Bdeposit[0] != 0 )
|
|
fprintf(fp,",\"%s\":\"%s\"","Bdeposit",swap->Bdeposit);
|
|
if ( swap->Bpayment[0] != 0 )
|
|
fprintf(fp,",\"%s\":\"%s\"","Bpayment",swap->Bpayment);
|
|
fprintf(fp,",\"expiration\":%u",swap->I.expiration);
|
|
fprintf(fp,",\"iambob\":%d",swap->I.iambob);
|
|
fprintf(fp,",\"bobcoin\":\"%s\"",swap->bobcoin->symbol);
|
|
fprintf(fp,",\"alicecoin\":\"%s\"",swap->alicecoin->symbol);
|
|
fprintf(fp,",\"lock\":%u",locktime);
|
|
fprintf(fp,",\"amount\":%.8f",dstr(rawtx->I.amount));
|
|
if ( bits256_nonz(triggertxid) != 0 )
|
|
fprintf(fp,",\"trigger\":\"%s\"",bits256_str(str,triggertxid));
|
|
if ( bits256_nonz(swap->I.pubAm) != 0 && bits256_nonz(swap->I.pubBn) != 0 )
|
|
{
|
|
basilisk_alicescript(redeemscript,&len,script,0,coinaddr,swap->alicecoin->chain->p2shtype,swap->I.pubAm,swap->I.pubBn);
|
|
fprintf(fp,",\"Apayment\":\"%s\"",coinaddr);
|
|
}
|
|
/*basilisk_dontforget_userdata("Aclaim",fp,swap->I.userdata_aliceclaim,swap->I.userdata_aliceclaimlen);
|
|
basilisk_dontforget_userdata("Areclaim",fp,swap->I.userdata_alicereclaim,swap->I.userdata_alicereclaimlen);
|
|
basilisk_dontforget_userdata("Aspend",fp,swap->I.userdata_alicespend,swap->I.userdata_alicespendlen);
|
|
basilisk_dontforget_userdata("Bspend",fp,swap->I.userdata_bobspend,swap->I.userdata_bobspendlen);
|
|
basilisk_dontforget_userdata("Breclaim",fp,swap->I.userdata_bobreclaim,swap->I.userdata_bobreclaimlen);
|
|
basilisk_dontforget_userdata("Brefund",fp,swap->I.userdata_bobrefund,swap->I.userdata_bobrefundlen);*/
|
|
fprintf(fp,"}\n");
|
|
fclose(fp);
|
|
}
|
|
sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname);
|
|
if ( (fp= fopen(fname,"wb")) != 0 )
|
|
{
|
|
fprintf(fp,"{\"src\":\"%s\",\"srcamount\":%.8f,\"dest\":\"%s\",\"destamount\":%.8f,\"requestid\":%u,\"quoteid\":%u,\"iambob\":%d,\"state\":%u,\"otherstate\":%u,\"expiration\":%u,\"dlocktime\":%u,\"plocktime\":%u",swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.requestid,swap->I.req.quoteid,swap->I.iambob,swap->I.statebits,swap->I.otherstatebits,swap->I.expiration,swap->bobdeposit.I.locktime,swap->bobpayment.I.locktime);
|
|
if ( memcmp(zeroes,swap->I.secretAm,20) != 0 )
|
|
{
|
|
init_hexbytes_noT(secretAmstr,swap->I.secretAm,20);
|
|
fprintf(fp,",\"secretAm\":\"%s\"",secretAmstr);
|
|
}
|
|
if ( memcmp(zeroes,swap->I.secretAm256,32) != 0 )
|
|
{
|
|
init_hexbytes_noT(secretAm256str,swap->I.secretAm256,32);
|
|
fprintf(fp,",\"secretAm256\":\"%s\"",secretAm256str);
|
|
}
|
|
if ( memcmp(zeroes,swap->I.secretBn,20) != 0 )
|
|
{
|
|
init_hexbytes_noT(secretBnstr,swap->I.secretBn,20);
|
|
fprintf(fp,",\"secretBn\":\"%s\"",secretBnstr);
|
|
}
|
|
if ( memcmp(zeroes,swap->I.secretBn256,32) != 0 )
|
|
{
|
|
init_hexbytes_noT(secretBn256str,swap->I.secretBn256,32);
|
|
fprintf(fp,",\"secretBn256\":\"%s\"",secretBn256str);
|
|
}
|
|
for (i=0; i<2; i++)
|
|
if ( bits256_nonz(swap->I.myprivs[i]) != 0 )
|
|
fprintf(fp,",\"myprivs%d\":\"%s\"",i,bits256_str(str,swap->I.myprivs[i]));
|
|
if ( bits256_nonz(swap->I.privAm) != 0 )
|
|
fprintf(fp,",\"privAm\":\"%s\"",bits256_str(str,swap->I.privAm));
|
|
if ( bits256_nonz(swap->I.privBn) != 0 )
|
|
fprintf(fp,",\"privBn\":\"%s\"",bits256_str(str,swap->I.privBn));
|
|
if ( bits256_nonz(swap->I.pubA0) != 0 )
|
|
fprintf(fp,",\"pubA0\":\"%s\"",bits256_str(str,swap->I.pubA0));
|
|
if ( bits256_nonz(swap->I.pubB0) != 0 )
|
|
fprintf(fp,",\"pubB0\":\"%s\"",bits256_str(str,swap->I.pubB0));
|
|
if ( bits256_nonz(swap->I.pubB1) != 0 )
|
|
fprintf(fp,",\"pubB1\":\"%s\"",bits256_str(str,swap->I.pubB1));
|
|
if ( bits256_nonz(swap->bobdeposit.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"Bdeposit\":\"%s\"",bits256_str(str,swap->bobdeposit.I.actualtxid));
|
|
if ( bits256_nonz(swap->bobrefund.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"Brefund\":\"%s\"",bits256_str(str,swap->bobrefund.I.actualtxid));
|
|
if ( bits256_nonz(swap->aliceclaim.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"Aclaim\":\"%s\"",bits256_str(str,swap->aliceclaim.I.actualtxid));
|
|
|
|
if ( bits256_nonz(swap->bobpayment.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"Bpayment\":\"%s\"",bits256_str(str,swap->bobpayment.I.actualtxid));
|
|
if ( bits256_nonz(swap->alicespend.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"Aspend\":\"%s\"",bits256_str(str,swap->alicespend.I.actualtxid));
|
|
if ( bits256_nonz(swap->bobreclaim.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"Breclaim\":\"%s\"",bits256_str(str,swap->bobreclaim.I.actualtxid));
|
|
|
|
if ( bits256_nonz(swap->alicepayment.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"Apayment\":\"%s\"",bits256_str(str,swap->alicepayment.I.actualtxid));
|
|
if ( bits256_nonz(swap->bobspend.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"Bspend\":\"%s\"",bits256_str(str,swap->bobspend.I.actualtxid));
|
|
if ( bits256_nonz(swap->alicereclaim.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"Areclaim\":\"%s\"",bits256_str(str,swap->alicereclaim.I.actualtxid));
|
|
|
|
if ( bits256_nonz(swap->otherfee.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"otherfee\":\"%s\"",bits256_str(str,swap->otherfee.I.actualtxid));
|
|
if ( bits256_nonz(swap->myfee.I.actualtxid) != 0 )
|
|
fprintf(fp,",\"myfee\":\"%s\"",bits256_str(str,swap->myfee.I.actualtxid));
|
|
fprintf(fp,",\"dest33\":\"");
|
|
for (i=0; i<33; i++)
|
|
fprintf(fp,"%02x",swap->persistent_pubkey33[i]);
|
|
fprintf(fp,"\"}\n");
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
void basilisk_dontforget_update(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx)
|
|
{
|
|
bits256 triggertxid;
|
|
memset(triggertxid.bytes,0,sizeof(triggertxid));
|
|
if ( rawtx == &swap->myfee )
|
|
basilisk_dontforget(myinfo,swap,&swap->myfee,0,triggertxid);
|
|
else if ( rawtx == &swap->otherfee )
|
|
basilisk_dontforget(myinfo,swap,&swap->otherfee,0,triggertxid);
|
|
else if ( rawtx == &swap->bobdeposit )
|
|
{
|
|
basilisk_dontforget(myinfo,swap,&swap->bobdeposit,0,triggertxid);
|
|
basilisk_dontforget(myinfo,swap,&swap->bobrefund,swap->bobdeposit.I.locktime,triggertxid);
|
|
}
|
|
else if ( rawtx == &swap->bobrefund )
|
|
basilisk_dontforget(myinfo,swap,&swap->bobrefund,swap->bobdeposit.I.locktime,triggertxid);
|
|
else if ( rawtx == &swap->aliceclaim )
|
|
{
|
|
basilisk_dontforget(myinfo,swap,&swap->bobrefund,0,triggertxid);
|
|
basilisk_dontforget(myinfo,swap,&swap->aliceclaim,0,swap->bobrefund.I.actualtxid);
|
|
}
|
|
else if ( rawtx == &swap->alicepayment )
|
|
{
|
|
basilisk_dontforget(myinfo,swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid);
|
|
}
|
|
else if ( rawtx == &swap->bobspend )
|
|
{
|
|
basilisk_dontforget(myinfo,swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid);
|
|
basilisk_dontforget(myinfo,swap,&swap->bobspend,0,swap->alicepayment.I.actualtxid);
|
|
}
|
|
else if ( rawtx == &swap->alicereclaim )
|
|
{
|
|
basilisk_dontforget(myinfo,swap,&swap->alicepayment,0,swap->bobdeposit.I.actualtxid);
|
|
basilisk_dontforget(myinfo,swap,&swap->alicereclaim,0,swap->bobrefund.I.actualtxid);
|
|
}
|
|
else if ( rawtx == &swap->bobpayment )
|
|
{
|
|
basilisk_dontforget(myinfo,swap,&swap->bobpayment,0,triggertxid);
|
|
basilisk_dontforget(myinfo,swap,&swap->bobreclaim,swap->bobpayment.I.locktime,triggertxid);
|
|
}
|
|
else if ( rawtx == &swap->alicespend )
|
|
{
|
|
basilisk_dontforget(myinfo,swap,&swap->bobpayment,0,triggertxid);
|
|
basilisk_dontforget(myinfo,swap,&swap->alicespend,0,triggertxid);
|
|
}
|
|
else if ( rawtx == &swap->bobreclaim )
|
|
basilisk_dontforget(myinfo,swap,&swap->bobreclaim,swap->bobpayment.I.locktime,triggertxid);
|
|
}
|
|
|
|
int32_t basilisk_verify_bobdeposit(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
|
|
{
|
|
uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero; struct basilisk_swap *swap = ptr;
|
|
if ( basilisk_rawtx_spendscript(swap,swap->bobcoin->longestchain,&swap->bobdeposit,0,data,datalen,0) == 0 )
|
|
{
|
|
swap->bobdeposit.I.signedtxid = basilisk_swap_broadcast(swap->bobdeposit.name,myinfo,swap,swap->bobdeposit.coin,swap->bobdeposit.txbytes,swap->bobdeposit.I.datalen);
|
|
if ( bits256_nonz(swap->bobdeposit.I.signedtxid) != 0 )
|
|
swap->depositunconf = 1;
|
|
basilisk_dontforget_update(myinfo,swap,&swap->bobdeposit);
|
|
len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
|
|
memcpy(swap->I.userdata_aliceclaim,userdata,len);
|
|
swap->I.userdata_aliceclaimlen = len;
|
|
if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->aliceclaim,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,1)) == 0 )
|
|
{
|
|
for (i=0; i<swap->bobdeposit.I.datalen; i++)
|
|
printf("%02x",swap->bobdeposit.txbytes[i]);
|
|
printf(" <- bobdeposit\n");
|
|
for (i=0; i<swap->aliceclaim.I.datalen; i++)
|
|
printf("%02x",swap->aliceclaim.txbytes[i]);
|
|
printf(" <- aliceclaim\n");
|
|
basilisk_txlog(myinfo,swap,&swap->aliceclaim,swap->I.putduration+swap->I.callduration);
|
|
return(retval);
|
|
}
|
|
}
|
|
printf("error with bobdeposit\n");
|
|
return(-1);
|
|
}
|
|
|
|
int32_t basilisk_bobdeposit_refund(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t delay)
|
|
{
|
|
uint8_t userdata[512]; int32_t i,retval,len = 0; char str[65];
|
|
len = basilisk_swapuserdata(userdata,swap->I.privBn,0,swap->I.myprivs[0],swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
|
|
memcpy(swap->I.userdata_bobrefund,userdata,len);
|
|
swap->I.userdata_bobrefundlen = len;
|
|
if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->bobrefund,&swap->bobdeposit,swap->I.myprivs[0],0,userdata,len,0)) == 0 )
|
|
{
|
|
for (i=0; i<swap->bobrefund.I.datalen; i++)
|
|
printf("%02x",swap->bobrefund.txbytes[i]);
|
|
printf(" <- bobrefund.(%s)\n",bits256_str(str,swap->bobrefund.I.txid));
|
|
basilisk_txlog(myinfo,swap,&swap->bobrefund,delay);
|
|
return(retval);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
/*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*/
|
|
|
|
int32_t basilisk_bobpayment_reclaim(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t delay)
|
|
{
|
|
uint8_t userdata[512]; int32_t i,retval,len = 0; static bits256 zero;
|
|
printf("basilisk_bobpayment_reclaim\n");
|
|
len = basilisk_swapuserdata(userdata,zero,1,swap->I.myprivs[1],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
|
|
memcpy(swap->I.userdata_bobreclaim,userdata,len);
|
|
swap->I.userdata_bobreclaimlen = len;
|
|
if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->bobreclaim,&swap->bobpayment,swap->I.myprivs[1],0,userdata,len,1)) == 0 )
|
|
{
|
|
for (i=0; i<swap->bobreclaim.I.datalen; i++)
|
|
printf("%02x",swap->bobreclaim.txbytes[i]);
|
|
printf(" <- bobreclaim\n");
|
|
basilisk_txlog(myinfo,swap,&swap->bobreclaim,delay);
|
|
return(retval);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
int32_t basilisk_verify_bobpaid(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
|
|
{
|
|
uint8_t userdata[512]; int32_t i,retval,len = 0; bits256 revAm; struct basilisk_swap *swap = ptr;
|
|
memset(revAm.bytes,0,sizeof(revAm));
|
|
if ( basilisk_rawtx_spendscript(swap,swap->bobcoin->longestchain,&swap->bobpayment,0,data,datalen,0) == 0 )
|
|
{
|
|
swap->bobpayment.I.signedtxid = basilisk_swap_broadcast(swap->bobpayment.name,myinfo,swap,swap->bobpayment.coin,swap->bobpayment.txbytes,swap->bobpayment.I.datalen);
|
|
if ( bits256_nonz(swap->bobpayment.I.signedtxid) != 0 )
|
|
swap->paymentunconf = 1;
|
|
basilisk_dontforget_update(myinfo,swap,&swap->bobpayment);
|
|
for (i=0; i<32; i++)
|
|
revAm.bytes[i] = swap->I.privAm.bytes[31-i];
|
|
len = basilisk_swapuserdata(userdata,revAm,0,swap->I.myprivs[0],swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
|
|
memcpy(swap->I.userdata_alicespend,userdata,len);
|
|
swap->I.userdata_alicespendlen = len;
|
|
char str[65],str2[65]; printf("bobpaid privAm.(%s) myprivs[0].(%s)\n",bits256_str(str,swap->I.privAm),bits256_str(str2,swap->I.myprivs[0]));
|
|
if ( (retval= basilisk_rawtx_sign(myinfo,swap->bobcoin->longestchain,swap,&swap->alicespend,&swap->bobpayment,swap->I.myprivs[0],0,userdata,len,1)) == 0 )
|
|
{
|
|
for (i=0; i<swap->bobpayment.I.datalen; i++)
|
|
printf("%02x",swap->bobpayment.txbytes[i]);
|
|
printf(" <- bobpayment\n");
|
|
for (i=0; i<swap->alicespend.I.datalen; i++)
|
|
printf("%02x",swap->alicespend.txbytes[i]);
|
|
printf(" <- alicespend\n\n");
|
|
swap->I.alicespent = 1;
|
|
basilisk_txlog(myinfo,swap,&swap->alicespend,-1);
|
|
return(retval);
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
void basilisk_alicepayment(struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,struct basilisk_rawtx *alicepayment,bits256 pubAm,bits256 pubBn)
|
|
{
|
|
alicepayment->I.spendlen = basilisk_alicescript(alicepayment->redeemscript,&alicepayment->I.redeemlen,alicepayment->spendscript,0,alicepayment->I.destaddr,coin->chain->p2shtype,pubAm,pubBn);
|
|
basilisk_rawtx_gen("alicepayment",myinfo,swap->I.started,swap->persistent_pubkey33,0,1,alicepayment,alicepayment->I.locktime,alicepayment->spendscript,alicepayment->I.spendlen,coin->chain->txfee,1,0);
|
|
}
|
|
|
|
int32_t basilisk_alicepayment_spend(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *dest)
|
|
{
|
|
int32_t i,retval;
|
|
printf("alicepayment_spend\n");
|
|
swap->alicepayment.I.spendlen = basilisk_alicescript(swap->alicepayment.redeemscript,&swap->alicepayment.I.redeemlen,swap->alicepayment.spendscript,0,swap->alicepayment.I.destaddr,swap->alicecoin->chain->p2shtype,swap->I.pubAm,swap->I.pubBn);
|
|
printf("alicepayment_spend len.%d\n",swap->alicepayment.I.spendlen);
|
|
if ( swap->I.iambob == 0 )
|
|
{
|
|
memcpy(swap->I.userdata_alicereclaim,swap->alicepayment.redeemscript,swap->alicepayment.I.spendlen);
|
|
swap->I.userdata_alicereclaimlen = swap->alicepayment.I.spendlen;
|
|
}
|
|
else
|
|
{
|
|
memcpy(swap->I.userdata_bobspend,swap->alicepayment.redeemscript,swap->alicepayment.I.spendlen);
|
|
swap->I.userdata_bobspendlen = swap->alicepayment.I.spendlen;
|
|
}
|
|
if ( (retval= basilisk_rawtx_sign(myinfo,swap->alicecoin->longestchain,swap,dest,&swap->alicepayment,swap->I.privAm,&swap->I.privBn,0,0,1)) == 0 )
|
|
{
|
|
for (i=0; i<dest->I.datalen; i++)
|
|
printf("%02x",dest->txbytes[i]);
|
|
printf(" <- msigspend\n\n");
|
|
if ( dest == &swap->bobspend )
|
|
swap->I.bobspent = 1;
|
|
basilisk_txlog(myinfo,swap,dest,0); // bobspend or alicereclaim
|
|
return(retval);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
int32_t basilisk_verify_alicepaid(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
|
|
{
|
|
struct basilisk_swap *swap = ptr;
|
|
if ( basilisk_rawtx_spendscript(swap,swap->alicecoin->longestchain,&swap->alicepayment,0,data,datalen,0) == 0 )
|
|
{
|
|
swap->alicepayment.I.signedtxid = basilisk_swap_broadcast(swap->alicepayment.name,myinfo,swap,swap->alicepayment.coin,swap->alicepayment.txbytes,swap->alicepayment.I.datalen);
|
|
if ( bits256_nonz(swap->alicepayment.I.signedtxid) != 0 )
|
|
swap->aliceunconf = 1;
|
|
basilisk_dontforget_update(myinfo,swap,&swap->alicepayment);
|
|
return(0);
|
|
}
|
|
else return(-1);
|
|
}
|
|
|
|
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->I.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_bobscripts_set(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t depositflag,int32_t genflag)
|
|
{
|
|
int32_t i,j; //char str[65];
|
|
if ( genflag != 0 && swap->I.iambob == 0 )
|
|
printf("basilisk_bobscripts_set WARNING: alice generating BOB tx\n");
|
|
if ( depositflag == 0 )
|
|
{
|
|
swap->bobpayment.I.spendlen = basilisk_bobscript(swap->bobpayment.I.rmd160,swap->bobpayment.redeemscript,&swap->bobpayment.I.redeemlen,swap->bobpayment.spendscript,0,&swap->bobpayment.I.locktime,&swap->bobpayment.I.secretstart,&swap->I,0);
|
|
bitcoin_address(swap->bobpayment.p2shaddr,swap->bobcoin->chain->p2shtype,swap->bobpayment.redeemscript,swap->bobpayment.I.redeemlen);
|
|
//for (i=0; i<swap->bobpayment.redeemlen; i++)
|
|
// printf("%02x",swap->bobpayment.redeemscript[i]);
|
|
//printf(" <- bobpayment.%d\n",i);
|
|
if ( genflag != 0 && bits256_nonz(*(bits256 *)swap->I.secretBn256) != 0 && swap->bobpayment.I.datalen == 0 )
|
|
{
|
|
for (i=0; i<3; i++)
|
|
{
|
|
//if ( swap->bobpayment.txbytes != 0 && swap->bobpayment.I.spendlen != 0 )
|
|
// break;
|
|
basilisk_rawtx_gen("payment",myinfo,swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobpayment,swap->bobpayment.I.locktime,swap->bobpayment.spendscript,swap->bobpayment.I.spendlen,swap->bobpayment.coin->chain->txfee,1,0);
|
|
if ( swap->bobpayment.I.spendlen == 0 || swap->bobpayment.I.datalen == 0 )
|
|
{
|
|
printf("error bob generating %p payment.%d\n",swap->bobpayment.txbytes,swap->bobpayment.I.spendlen);
|
|
sleep(DEX_SLEEP);
|
|
}
|
|
else
|
|
{
|
|
for (j=0; j<swap->bobpayment.I.datalen; j++)
|
|
printf("%02x",swap->bobpayment.txbytes[j]);
|
|
//printf(" <- bobpayment.%d\n",swap->bobpayment.datalen);
|
|
//for (j=0; j<swap->bobpayment.redeemlen; j++)
|
|
// printf("%02x",swap->bobpayment.redeemscript[j]);
|
|
//printf(" <- redeem.%d\n",swap->bobpayment.redeemlen);
|
|
printf(" <- GENERATED BOB PAYMENT.%d\n",swap->bobpayment.I.datalen);
|
|
iguana_unspents_mark(myinfo,swap->bobcoin,swap->bobpayment.vins);
|
|
basilisk_bobpayment_reclaim(myinfo,swap,swap->I.callduration);
|
|
printf("bobscripts set completed\n");
|
|
return(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
swap->bobdeposit.I.spendlen = basilisk_bobscript(swap->bobdeposit.I.rmd160,swap->bobdeposit.redeemscript,&swap->bobdeposit.I.redeemlen,swap->bobdeposit.spendscript,0,&swap->bobdeposit.I.locktime,&swap->bobdeposit.I.secretstart,&swap->I,1);
|
|
bitcoin_address(swap->bobdeposit.p2shaddr,swap->bobcoin->chain->p2shtype,swap->bobdeposit.redeemscript,swap->bobdeposit.I.redeemlen);
|
|
if ( genflag != 0 && (swap->bobdeposit.I.datalen == 0 || swap->bobrefund.I.datalen == 0) )
|
|
{
|
|
for (i=0; i<3; i++)
|
|
{
|
|
//if ( swap->bobdeposit.txbytes != 0 && swap->bobdeposit.I.spendlen != 0 )
|
|
// break;
|
|
basilisk_rawtx_gen("deposit",myinfo,swap->I.started,swap->persistent_pubkey33,1,1,&swap->bobdeposit,swap->bobdeposit.I.locktime,swap->bobdeposit.spendscript,swap->bobdeposit.I.spendlen,swap->bobdeposit.coin->chain->txfee,1,0);
|
|
if ( swap->bobdeposit.I.datalen == 0 || swap->bobdeposit.I.spendlen == 0 )
|
|
{
|
|
printf("error bob generating %p deposit.%d\n",swap->bobdeposit.txbytes,swap->bobdeposit.I.spendlen);
|
|
sleep(DEX_SLEEP);
|
|
}
|
|
else
|
|
{
|
|
for (j=0; j<swap->bobdeposit.I.datalen; j++)
|
|
printf("%02x",swap->bobdeposit.txbytes[j]);
|
|
printf(" <- GENERATED BOB DEPOSIT.%d\n",swap->bobdeposit.I.datalen);
|
|
//for (j=0; j<swap->bobdeposit.redeemlen; j++)
|
|
// printf("%02x",swap->bobdeposit.redeemscript[j]);
|
|
//printf(" <- redeem.%d\n",swap->bobdeposit.redeemlen);
|
|
//printf("GENERATED BOB DEPOSIT\n");
|
|
iguana_unspents_mark(myinfo,swap->bobcoin,swap->bobdeposit.vins);
|
|
basilisk_bobdeposit_refund(myinfo,swap,swap->I.putduration);
|
|
printf("bobscripts set completed\n");
|
|
return(0);
|
|
}
|
|
}
|
|
}
|
|
//for (i=0; i<swap->bobdeposit.redeemlen; i++)
|
|
// printf("%02x",swap->bobdeposit.redeemscript[i]);
|
|
//printf(" <- bobdeposit.%d\n",i);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
int32_t basilisk_verify_privi(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
|
|
{
|
|
int32_t j,wrongfirstbyte,len = 0; bits256 privkey,pubi; char str[65],str2[65]; uint8_t secret160[20],pubkey33[33]; uint64_t txid; struct basilisk_swap *swap = ptr;
|
|
memset(privkey.bytes,0,sizeof(privkey));
|
|
if ( datalen == sizeof(bits256) )
|
|
{
|
|
for (j=0; j<32; j++)
|
|
privkey.bytes[j] = data[len++];
|
|
revcalc_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->I.choosei,pubkey33[0],pubi,txid) == 0 )
|
|
{
|
|
if ( swap->I.iambob != 0 )
|
|
{
|
|
swap->I.privAm = privkey;
|
|
vcalc_sha256(0,swap->I.secretAm256,privkey.bytes,sizeof(privkey));
|
|
printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256));
|
|
basilisk_bobscripts_set(myinfo,swap,0,1);
|
|
}
|
|
else
|
|
{
|
|
swap->I.privBn = privkey;
|
|
vcalc_sha256(0,swap->I.secretBn256,privkey.bytes,sizeof(privkey));
|
|
printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256));
|
|
}
|
|
char str[65]; printf("privi verified.(%s)\n",bits256_str(str,privkey));
|
|
return(0);
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
int32_t basilisk_process_swapverify(struct supernet_info *myinfo,void *ptr,int32_t (*internal_func)(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen),uint32_t channel,uint32_t msgid,uint8_t *data,int32_t datalen,uint32_t expiration,uint32_t duration)
|
|
{
|
|
struct basilisk_swap *swap = ptr;
|
|
if ( internal_func != 0 )
|
|
return((*internal_func)(myinfo,swap,data,datalen));
|
|
else return(0);
|
|
}
|
|
|
|
void basilisk_swapgotdata(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t crc32,bits256 srchash,bits256 desthash,uint32_t quoteid,uint32_t msgbits,uint8_t *data,int32_t datalen,int32_t reinit)
|
|
{
|
|
int32_t i; struct basilisk_swapmessage *mp;
|
|
for (i=0; i<swap->nummessages; i++)
|
|
if ( crc32 == swap->messages[i].crc32 && msgbits == swap->messages[i].msgbits && bits256_cmp(srchash,swap->messages[i].srchash) == 0 && bits256_cmp(desthash,swap->messages[i].desthash) == 0 )
|
|
return;
|
|
//printf(" new message.[%d] datalen.%d Q.%x msg.%x [%llx]\n",swap->nummessages,datalen,quoteid,msgbits,*(long long *)data);
|
|
swap->messages = realloc(swap->messages,sizeof(*swap->messages) * (swap->nummessages + 1));
|
|
mp = &swap->messages[swap->nummessages++];
|
|
mp->crc32 = crc32;
|
|
mp->srchash = srchash;
|
|
mp->desthash = desthash;
|
|
mp->msgbits = msgbits;
|
|
mp->quoteid = quoteid;
|
|
mp->data = malloc(datalen);
|
|
mp->datalen = datalen;
|
|
memcpy(mp->data,data,datalen);
|
|
if ( reinit == 0 && swap->fp != 0 )
|
|
{
|
|
fwrite(mp,1,sizeof(*mp),swap->fp);
|
|
fwrite(data,1,datalen,swap->fp);
|
|
fflush(swap->fp);
|
|
}
|
|
}
|
|
|
|
FILE *basilisk_swap_save(struct supernet_info *myinfo,struct basilisk_swap *swap,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit)
|
|
{
|
|
FILE *fp=0; /*char fname[512];
|
|
sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,rp->requestid,rp->quoteid), OS_compatible_path(fname);
|
|
if ( (fp= fopen(fname,"rb+")) == 0 )
|
|
{
|
|
if ( (fp= fopen(fname,"wb+")) != 0 )
|
|
{
|
|
fwrite(privkey.bytes,1,sizeof(privkey),fp);
|
|
fwrite(rp,1,sizeof(*rp),fp);
|
|
fwrite(&statebits,1,sizeof(statebits),fp);
|
|
fwrite(&optionduration,1,sizeof(optionduration),fp);
|
|
fflush(fp);
|
|
}
|
|
}
|
|
else if ( reinit != 0 )
|
|
{
|
|
}*/
|
|
return(fp);
|
|
}
|
|
|
|
int32_t basilisk_swap_load(uint32_t requestid,uint32_t quoteid,bits256 *privkeyp,struct basilisk_request *rp,uint32_t *statebitsp,int32_t *optiondurationp)
|
|
{
|
|
FILE *fp=0; char fname[512]; int32_t retval = -1;
|
|
sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname);
|
|
if ( (fp= fopen(fname,"rb+")) != 0 )
|
|
{
|
|
if ( fread(privkeyp,1,sizeof(*privkeyp),fp) == sizeof(*privkeyp) &&
|
|
fread(rp,1,sizeof(*rp),fp) == sizeof(*rp) &&
|
|
fread(statebitsp,1,sizeof(*statebitsp),fp) == sizeof(*statebitsp) &&
|
|
fread(optiondurationp,1,sizeof(*optiondurationp),fp) == sizeof(*optiondurationp) )
|
|
retval = 0;
|
|
fclose(fp);
|
|
}
|
|
return(retval);
|
|
}
|
|
|
|
struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit);
|
|
|
|
void basilisk_swaps_init(struct supernet_info *myinfo)
|
|
{
|
|
char fname[512]; uint32_t iter,swapcompleted,requestid,quoteid,optionduration,statebits; FILE *fp; bits256 privkey;struct basilisk_request R; struct basilisk_swapmessage M; struct basilisk_swap *swap = 0;
|
|
sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname);
|
|
if ( (myinfo->swapsfp= fopen(fname,"rb+")) != 0 )
|
|
{
|
|
while ( fread(&requestid,1,sizeof(requestid),myinfo->swapsfp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),myinfo->swapsfp) == sizeof(quoteid) )
|
|
{
|
|
sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname);
|
|
printf("%s\n",fname);
|
|
if ( (fp= fopen(fname,"rb+")) != 0 ) // check to see if completed
|
|
{
|
|
memset(&M,0,sizeof(M));
|
|
swapcompleted = 1;
|
|
for (iter=0; iter<2; iter++)
|
|
{
|
|
if ( fread(privkey.bytes,1,sizeof(privkey),fp) == sizeof(privkey) &&
|
|
fread(&R,1,sizeof(R),fp) == sizeof(R) &&
|
|
fread(&statebits,1,sizeof(statebits),fp) == sizeof(statebits) &&
|
|
fread(&optionduration,1,sizeof(optionduration),fp) == sizeof(optionduration) )
|
|
{
|
|
while ( 0 && fread(&M,1,sizeof(M),fp) == sizeof(M) )
|
|
{
|
|
M.data = 0;
|
|
//printf("entry iter.%d crc32.%x datalen.%d\n",iter,M.crc32,M.datalen);
|
|
if ( M.datalen < 100000 )
|
|
{
|
|
M.data = malloc(M.datalen);
|
|
if ( fread(M.data,1,M.datalen,fp) == M.datalen )
|
|
{
|
|
if ( calc_crc32(0,M.data,M.datalen) == M.crc32 )
|
|
{
|
|
if ( iter == 1 )
|
|
{
|
|
if ( swap == 0 )
|
|
{
|
|
swap = basilisk_thread_start(myinfo,privkey,&R,statebits,optionduration,1);
|
|
swap->I.choosei = swap->I.otherchoosei = -1;
|
|
}
|
|
if ( swap != 0 )
|
|
basilisk_swapgotdata(myinfo,swap,M.crc32,M.srchash,M.desthash,M.quoteid,M.msgbits,M.data,M.datalen,1);
|
|
}
|
|
} else printf("crc mismatch %x vs %x\n",calc_crc32(0,M.data,M.datalen),M.crc32);
|
|
} else printf("error reading M.datalen %d\n",M.datalen);
|
|
free(M.data), M.data = 0;
|
|
}
|
|
}
|
|
}
|
|
if ( swapcompleted != 0 )
|
|
break;
|
|
rewind(fp);
|
|
}
|
|
}
|
|
}
|
|
} else myinfo->swapsfp = fopen(fname,"wb+");
|
|
}
|
|
|
|
void basilisk_psockinit(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t amlp);
|
|
|
|
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,void *ptr,uint8_t *data,int32_t datalen))
|
|
{
|
|
uint8_t *ptr; bits256 srchash,desthash; uint32_t crc32,_msgbits,quoteid; int32_t i,size,offset,retval = -1; struct basilisk_swapmessage *mp = 0;
|
|
while ( (size= nn_recv(swap->subsock,&ptr,NN_MSG,0)) >= 0 )
|
|
{
|
|
swap->lasttime = (uint32_t)time(NULL);
|
|
memset(srchash.bytes,0,sizeof(srchash));
|
|
memset(desthash.bytes,0,sizeof(desthash));
|
|
//printf("gotmsg.[%d] crc.%x\n",size,crc32);
|
|
offset = 0;
|
|
for (i=0; i<32; i++)
|
|
srchash.bytes[i] = ptr[offset++];
|
|
for (i=0; i<32; i++)
|
|
desthash.bytes[i] = ptr[offset++];
|
|
offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),"eid);
|
|
offset += iguana_rwnum(0,&ptr[offset],sizeof(uint32_t),&_msgbits);
|
|
if ( size > offset )
|
|
{
|
|
crc32 = calc_crc32(0,&ptr[offset],size-offset);
|
|
if ( size > offset )
|
|
{
|
|
//printf("size.%d offset.%d datalen.%d\n",size,offset,size-offset);
|
|
basilisk_swapgotdata(myinfo,swap,crc32,srchash,desthash,quoteid,_msgbits,&ptr[offset],size-offset,0);
|
|
}
|
|
}
|
|
else if ( bits256_nonz(srchash) == 0 && bits256_nonz(desthash) == 0 )
|
|
{
|
|
if ( swap->aborted == 0 )
|
|
{
|
|
swap->aborted = (uint32_t)time(NULL);
|
|
printf("got abort signal from other side\n");
|
|
}
|
|
} else printf("basilisk_swapget: got strange packet\n");
|
|
if ( ptr != 0 )
|
|
nn_freemsg(ptr), ptr = 0;
|
|
}
|
|
//char str[65],str2[65];
|
|
for (i=0; i<swap->nummessages; i++)
|
|
{
|
|
//printf("%d: %s vs %s\n",i,bits256_str(str,swap->messages[i].srchash),bits256_str(str2,swap->messages[i].desthash));
|
|
if ( bits256_cmp(swap->messages[i].desthash,swap->I.myhash) == 0 )
|
|
{
|
|
if ( swap->messages[i].msgbits == msgbits )
|
|
{
|
|
if ( swap->I.iambob == 0 && swap->lasttime != 0 && time(NULL) > swap->lasttime+360 )
|
|
{
|
|
printf("nothing received for a while from Bob, try new sockets\n");
|
|
if ( swap->pushsock >= 0 ) //
|
|
nn_close(swap->pushsock), swap->pushsock = -1;
|
|
if ( swap->subsock >= 0 ) //
|
|
nn_close(swap->subsock), swap->subsock = -1;
|
|
swap->connected = 0;
|
|
basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
|
|
}
|
|
mp = &swap->messages[i];
|
|
if ( msgbits != 0x80000000 )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( mp != 0 )
|
|
retval = (*basilisk_verify_func)(myinfo,swap,mp->data,mp->datalen);
|
|
//printf("mine/other %s vs %s\n",bits256_str(str,swap->I.myhash),bits256_str(str2,swap->I.otherhash));
|
|
return(retval);
|
|
}
|
|
|
|
uint32_t basilisk_swapsend(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t datalen,uint32_t nextbits,uint32_t crcs[2])
|
|
{
|
|
uint8_t *buf; int32_t sentbytes,offset=0,i;
|
|
buf = malloc(datalen + sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2);
|
|
for (i=0; i<32; i++)
|
|
buf[offset++] = swap->I.myhash.bytes[i];
|
|
for (i=0; i<32; i++)
|
|
buf[offset++] = swap->I.otherhash.bytes[i];
|
|
offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid);
|
|
offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits);
|
|
if ( datalen > 0 )
|
|
memcpy(&buf[offset],data,datalen), offset += datalen;
|
|
if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset )
|
|
{
|
|
printf("sentbytes.%d vs offset.%d\n",sentbytes,offset);
|
|
if ( sentbytes < 0 )
|
|
{
|
|
if ( swap->pushsock >= 0 )
|
|
nn_close(swap->pushsock), swap->pushsock = -1; //,
|
|
if ( swap->subsock >= 0 ) //
|
|
nn_close(swap->subsock), swap->subsock = -1;
|
|
swap->connected = swap->I.iambob != 0 ? -1 : 0;
|
|
swap->aborted = (uint32_t)time(NULL);
|
|
}
|
|
}
|
|
//else printf("send.[%d] %x offset.%d datalen.%d [%llx]\n",sentbytes,msgbits,offset,datalen,*(long long *)data);
|
|
free(buf);
|
|
return(nextbits);
|
|
}
|
|
|
|
void basilisk_swap_sendabort(struct supernet_info *myinfo,struct basilisk_swap *swap)
|
|
{
|
|
uint32_t msgbits = 0; uint8_t buf[sizeof(msgbits) + sizeof(swap->I.req.quoteid) + sizeof(bits256)*2]; int32_t sentbytes,offset=0;
|
|
memset(buf,0,sizeof(buf));
|
|
offset += iguana_rwnum(1,&buf[offset],sizeof(swap->I.req.quoteid),&swap->I.req.quoteid);
|
|
offset += iguana_rwnum(1,&buf[offset],sizeof(msgbits),&msgbits);
|
|
if ( (sentbytes= nn_send(swap->pushsock,buf,offset,0)) != offset )
|
|
{
|
|
if ( sentbytes < 0 )
|
|
{
|
|
if ( swap->pushsock >= 0 ) //
|
|
nn_close(swap->pushsock), swap->pushsock = -1;
|
|
if ( swap->subsock >= 0 ) //
|
|
nn_close(swap->subsock), swap->subsock = -1;
|
|
swap->connected = 0;
|
|
}
|
|
} else printf("basilisk_swap_sendabort\n");
|
|
}
|
|
|
|
int32_t basilisk_privBn_extract(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
|
|
{
|
|
if ( basilisk_priviextract(myinfo,swap->bobcoin,"privBn",&swap->I.privBn,swap->I.secretBn,swap->bobrefund.I.actualtxid,0) == 0 )
|
|
{
|
|
printf("extracted privBn from blockchain\n");
|
|
}
|
|
else if ( basilisk_swapget(myinfo,swap,0x40000000,data,maxlen,basilisk_verify_privi) == 0 )
|
|
{
|
|
}
|
|
if ( bits256_nonz(swap->I.privBn) != 0 && swap->alicereclaim.I.datalen == 0 )
|
|
{
|
|
char str[65]; printf("got privBn.%s\n",bits256_str(str,swap->I.privBn));
|
|
return(basilisk_alicepayment_spend(myinfo,swap,&swap->alicereclaim));
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
int32_t basilisk_privAm_extract(struct supernet_info *myinfo,struct basilisk_swap *swap)
|
|
{
|
|
if ( basilisk_priviextract(myinfo,swap->bobcoin,"privAm",&swap->I.privAm,swap->I.secretAm,swap->bobpayment.I.actualtxid,0) == 0 )
|
|
{
|
|
printf("extracted privAm from blockchain\n");
|
|
}
|
|
if ( bits256_nonz(swap->I.privAm) != 0 && swap->bobspend.I.datalen == 0 )
|
|
{
|
|
char str[65]; printf("got privAm.%s\n",bits256_str(str,swap->I.privAm));
|
|
return(basilisk_alicepayment_spend(myinfo,swap,&swap->bobspend));
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
bits256 instantdex_derivekeypair(void *ctx,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(ctx,pubkey,*newprivp));
|
|
}
|
|
|
|
int32_t instantdex_pubkeyargs(void *ctx,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,reveal; uint64_t txid; uint8_t secret160[20],pubkey[33];
|
|
sprintf(buf,"%c0",'A' - 0x02 + firstbyte);
|
|
if ( numpubs > 2 )
|
|
{
|
|
if ( swap->I.numpubs+2 >= numpubs )
|
|
return(numpubs);
|
|
//fprintf(stderr,">>>>>> start generating %s\n",buf);
|
|
}
|
|
for (i=n=m=0; i<numpubs*100 && n<numpubs; i++)
|
|
{
|
|
pubi = instantdex_derivekeypair(ctx,&privkey,pubkey,privkey,hash);
|
|
//fprintf(stderr,"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->I.mypubs[n]) == 0 )
|
|
{
|
|
swap->I.myprivs[n] = privkey;
|
|
memcpy(swap->I.mypubs[n].bytes,pubkey+1,sizeof(bits256));
|
|
reveal = basilisk_revealkey(privkey,swap->I.mypubs[n]);
|
|
if ( swap->I.iambob != 0 )
|
|
{
|
|
if ( n == 0 )
|
|
swap->I.pubB0 = reveal;
|
|
else if ( n == 1 )
|
|
swap->I.pubB1 = reveal;
|
|
}
|
|
else if ( swap->I.iambob == 0 )
|
|
{
|
|
if ( n == 0 )
|
|
swap->I.pubA0 = reveal;
|
|
else if ( n == 1 )
|
|
swap->I.pubA1 = reveal;
|
|
}
|
|
}
|
|
}
|
|
if ( m < INSTANTDEX_DECKSIZE )
|
|
{
|
|
swap->privkeys[m] = privkey;
|
|
revcalc_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->I.numpubs )
|
|
swap->I.numpubs = m;
|
|
}
|
|
n++;
|
|
}
|
|
if ( n > 2 || m > 2 )
|
|
printf("n.%d m.%d len.%d numpubs.%d\n",n,m,len,swap->I.numpubs);
|
|
return(n);
|
|
}
|
|
|
|
void basilisk_rawtx_setparms(char *name,uint32_t quoteid,struct basilisk_rawtx *rawtx,struct iguana_info *coin,int32_t numconfirms,int32_t vintype,uint64_t satoshis,int32_t vouttype,uint8_t *pubkey33,int32_t jumblrflag)
|
|
{
|
|
strcpy(rawtx->name,name);
|
|
rawtx->coin = coin;
|
|
strcpy(rawtx->I.coinstr,coin->symbol);
|
|
rawtx->I.numconfirms = numconfirms;
|
|
if ( (rawtx->I.amount= satoshis) < 50000 )
|
|
rawtx->I.amount = 50000;
|
|
rawtx->I.vintype = vintype; // 0 -> std, 2 -> 2of2, 3 -> spend bobpayment, 4 -> spend bobdeposit
|
|
rawtx->I.vouttype = vouttype; // 0 -> fee, 1 -> std, 2 -> 2of2, 3 -> bobpayment, 4 -> bobdeposit
|
|
if ( rawtx->I.vouttype == 0 )
|
|
{
|
|
if ( strcmp(coin->symbol,"BTC") == 0 && (quoteid % 10) == 0 )
|
|
decode_hex(rawtx->I.rmd160,20,TIERNOLAN_RMD160);
|
|
else decode_hex(rawtx->I.rmd160,20,INSTANTDEX_RMD160);
|
|
bitcoin_address(rawtx->I.destaddr,rawtx->coin->chain->pubtype,rawtx->I.rmd160,20);
|
|
}
|
|
if ( pubkey33 != 0 )
|
|
{
|
|
memcpy(rawtx->I.pubkey33,pubkey33,33);
|
|
bitcoin_address(rawtx->I.destaddr,rawtx->coin->chain->pubtype,rawtx->I.pubkey33,33);
|
|
bitcoin_addr2rmd160(&rawtx->I.addrtype,rawtx->I.rmd160,rawtx->I.destaddr);
|
|
}
|
|
if ( rawtx->I.vouttype <= 1 && rawtx->I.destaddr[0] != 0 )
|
|
{
|
|
rawtx->I.spendlen = bitcoin_standardspend(rawtx->spendscript,0,rawtx->I.rmd160);
|
|
printf("%s spendlen.%d %s <- %.8f\n",name,rawtx->I.spendlen,rawtx->I.destaddr,dstr(rawtx->I.amount));
|
|
} else printf("%s vouttype.%d destaddr.(%s)\n",name,rawtx->I.vouttype,rawtx->I.destaddr);
|
|
}
|
|
|
|
int32_t bitcoin_coinptrs(bits256 pubkey,struct iguana_info **bobcoinp,struct iguana_info **alicecoinp,char *src,char *dest,bits256 srchash,bits256 desthash)
|
|
{
|
|
struct iguana_info *coin = iguana_coinfind(src);
|
|
if ( coin == 0 || iguana_coinfind(dest) == 0 )
|
|
return(0);
|
|
*bobcoinp = *alicecoinp = 0;
|
|
*bobcoinp = iguana_coinfind(dest);
|
|
*alicecoinp = iguana_coinfind(src);
|
|
if ( bits256_cmp(pubkey,srchash) == 0 )
|
|
{
|
|
if ( strcmp(src,(*bobcoinp)->symbol) == 0 )
|
|
return(1);
|
|
else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 )
|
|
return(-1);
|
|
else return(0);
|
|
}
|
|
else if ( bits256_cmp(pubkey,desthash) == 0 )
|
|
{
|
|
if ( strcmp(src,(*bobcoinp)->symbol) == 0 )
|
|
return(-1);
|
|
else if ( strcmp(dest,(*alicecoinp)->symbol) == 0 )
|
|
return(1);
|
|
else return(0);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void basilisk_swap_saveupdate(struct supernet_info *myinfo,struct basilisk_swap *swap)
|
|
{
|
|
FILE *fp; char fname[512];
|
|
sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname);
|
|
if ( (fp= fopen(fname,"wb")) != 0 )
|
|
{
|
|
fwrite(&swap->I,1,sizeof(swap->I),fp);
|
|
/*fwrite(&swap->bobdeposit,1,sizeof(swap->bobdeposit),fp);
|
|
fwrite(&swap->bobpayment,1,sizeof(swap->bobpayment),fp);
|
|
fwrite(&swap->alicepayment,1,sizeof(swap->alicepayment),fp);
|
|
fwrite(&swap->myfee,1,sizeof(swap->myfee),fp);
|
|
fwrite(&swap->otherfee,1,sizeof(swap->otherfee),fp);
|
|
fwrite(&swap->aliceclaim,1,sizeof(swap->aliceclaim),fp);
|
|
fwrite(&swap->alicespend,1,sizeof(swap->alicespend),fp);
|
|
fwrite(&swap->bobreclaim,1,sizeof(swap->bobreclaim),fp);
|
|
fwrite(&swap->bobspend,1,sizeof(swap->bobspend),fp);
|
|
fwrite(&swap->bobrefund,1,sizeof(swap->bobrefund),fp);
|
|
fwrite(&swap->alicereclaim,1,sizeof(swap->alicereclaim),fp);*/
|
|
fwrite(swap->privkeys,1,sizeof(swap->privkeys),fp);
|
|
fwrite(swap->otherdeck,1,sizeof(swap->otherdeck),fp);
|
|
fwrite(swap->deck,1,sizeof(swap->deck),fp);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
int32_t basilisk_swap_loadtx(struct basilisk_rawtx *rawtx,FILE *fp,char *bobcoinstr,char *alicecoinstr)
|
|
{
|
|
if ( fread(rawtx,1,sizeof(*rawtx),fp) == sizeof(*rawtx) )
|
|
{
|
|
rawtx->coin = 0;
|
|
rawtx->vins = 0;
|
|
if ( strcmp(rawtx->I.coinstr,bobcoinstr) == 0 || strcmp(rawtx->I.coinstr,alicecoinstr) == 0 )
|
|
{
|
|
rawtx->coin = iguana_coinfind(rawtx->I.coinstr);
|
|
if ( rawtx->vinstr[0] != 0 )
|
|
rawtx->vins = cJSON_Parse(rawtx->vinstr);
|
|
printf("loaded.%s len.%d\n",rawtx->name,rawtx->I.datalen);
|
|
return(0);
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
struct basilisk_swap *bitcoin_swapinit(struct supernet_info *myinfo,bits256 privkey,uint8_t *pubkey33,bits256 pubkey25519,struct basilisk_swap *swap,int32_t optionduration,uint32_t statebits,int32_t reinit)
|
|
{
|
|
FILE *fp; char fname[512]; uint8_t *alicepub33=0,*bobpub33=0; int32_t errs=0,jumblrflag,x = -1;
|
|
if ( reinit != 0 )
|
|
{
|
|
sprintf(fname,"%s/SWAPS/%u-%u.swap",GLOBAL_DBDIR,swap->I.req.requestid,swap->I.req.quoteid), OS_compatible_path(fname);
|
|
printf("reinit.(%s)\n",fname);
|
|
if ( (fp= fopen(fname,"rb")) != 0 )
|
|
{
|
|
if ( fread(&swap->I,1,sizeof(swap->I),fp) != sizeof(swap->I) )
|
|
errs++;
|
|
if ( swap->bobcoin == 0 )
|
|
swap->bobcoin = iguana_coinfind(swap->I.req.dest);
|
|
if ( swap->alicecoin == 0 )
|
|
swap->alicecoin = iguana_coinfind(swap->I.req.src);
|
|
if ( swap->alicecoin != 0 && swap->bobcoin != 0 )
|
|
{
|
|
/*basilisk_swap_loadtx(&swap->bobdeposit,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
|
|
basilisk_swap_loadtx(&swap->bobpayment,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
|
|
basilisk_swap_loadtx(&swap->alicepayment,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
|
|
basilisk_swap_loadtx(&swap->myfee,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
|
|
basilisk_swap_loadtx(&swap->otherfee,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
|
|
basilisk_swap_loadtx(&swap->aliceclaim,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
|
|
basilisk_swap_loadtx(&swap->alicespend,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
|
|
basilisk_swap_loadtx(&swap->bobreclaim,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
|
|
basilisk_swap_loadtx(&swap->bobspend,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
|
|
basilisk_swap_loadtx(&swap->bobrefund,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);
|
|
basilisk_swap_loadtx(&swap->alicereclaim,fp,swap->bobcoin->symbol,swap->alicecoin->symbol);*/
|
|
} else printf("missing coins (%p %p)\n",swap->bobcoin,swap->alicecoin);
|
|
if ( fread(swap->privkeys,1,sizeof(swap->privkeys),fp) != sizeof(swap->privkeys) )
|
|
errs++;
|
|
if ( fread(swap->otherdeck,1,sizeof(swap->otherdeck),fp) != sizeof(swap->otherdeck) )
|
|
errs++;
|
|
if ( fread(swap->deck,1,sizeof(swap->deck),fp) != sizeof(swap->deck) )
|
|
errs++;
|
|
fclose(fp);
|
|
} else printf("cant find.(%s)\n",fname);
|
|
}
|
|
else
|
|
{
|
|
swap->I.putduration = swap->I.callduration = INSTANTDEX_LOCKTIME;
|
|
if ( optionduration < 0 )
|
|
swap->I.putduration -= optionduration;
|
|
else if ( optionduration > 0 )
|
|
swap->I.callduration += optionduration;
|
|
swap->I.bobsatoshis = swap->I.req.destamount;
|
|
swap->I.alicesatoshis = swap->I.req.srcamount;
|
|
if ( (swap->I.bobinsurance= (swap->I.bobsatoshis / INSTANTDEX_INSURANCEDIV)) < 50000 )
|
|
swap->I.bobinsurance = 50000;
|
|
if ( (swap->I.aliceinsurance= (swap->I.alicesatoshis / INSTANTDEX_INSURANCEDIV)) < 50000 )
|
|
swap->I.aliceinsurance = 50000;
|
|
strcpy(swap->I.bobstr,swap->I.req.dest);
|
|
strcpy(swap->I.alicestr,swap->I.req.src);
|
|
swap->I.started = (uint32_t)time(NULL);
|
|
swap->I.expiration = swap->I.req.timestamp + swap->I.putduration + swap->I.callduration;
|
|
OS_randombytes((uint8_t *)&swap->I.choosei,sizeof(swap->I.choosei));
|
|
if ( swap->I.choosei < 0 )
|
|
swap->I.choosei = -swap->I.choosei;
|
|
swap->I.choosei %= INSTANTDEX_DECKSIZE;
|
|
swap->I.otherchoosei = -1;
|
|
swap->I.myhash = pubkey25519;
|
|
if ( statebits != 0 )
|
|
{
|
|
swap->I.iambob = 0;
|
|
swap->I.otherhash = swap->I.req.desthash;
|
|
}
|
|
else
|
|
{
|
|
swap->I.iambob = 1;
|
|
swap->I.otherhash = swap->I.req.srchash;
|
|
}
|
|
if ( bits256_nonz(privkey) == 0 || (x= instantdex_pubkeyargs(myinfo->ctx,swap,2 + INSTANTDEX_DECKSIZE,privkey,swap->I.orderhash,0x02+swap->I.iambob)) != 2 + INSTANTDEX_DECKSIZE )
|
|
{
|
|
char str[65]; printf("couldnt generate privkeys %d %s\n",x,bits256_str(str,privkey));
|
|
return(0);
|
|
}
|
|
}
|
|
swap->bobcoin = iguana_coinfind(swap->I.req.dest);
|
|
swap->alicecoin = iguana_coinfind(swap->I.req.src);
|
|
if ( swap->bobcoin == 0 || swap->alicecoin == 0 )
|
|
{
|
|
printf("missing bobcoin.%p or missing alicecoin.%p src.%p dest.%p\n",swap->bobcoin,swap->alicecoin,iguana_coinfind(swap->I.req.src),iguana_coinfind(swap->I.req.dest));
|
|
free(swap);
|
|
return(0);
|
|
}
|
|
if ( strcmp("BTC",swap->bobcoin->symbol) == 0 )
|
|
{
|
|
swap->I.bobconfirms = (1*0 + sqrt(dstr(swap->I.bobsatoshis) * .1));
|
|
swap->I.aliceconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3);
|
|
}
|
|
else if ( strcmp("BTC",swap->alicecoin->symbol) == 0 )
|
|
{
|
|
swap->I.aliceconfirms = (1*0 + sqrt(dstr(swap->I.alicesatoshis) * .1));
|
|
swap->I.bobconfirms = MIN(BASILISK_DEFAULT_NUMCONFIRMS,swap->I.bobconfirms * 3);
|
|
}
|
|
else
|
|
{
|
|
swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
|
|
swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
|
|
}
|
|
/*if ( swap->I.bobconfirms == 0 )
|
|
swap->I.bobconfirms = swap->bobcoin->chain->minconfirms;
|
|
if ( swap->I.aliceconfirms == 0 )
|
|
swap->I.aliceconfirms = swap->alicecoin->chain->minconfirms;*/
|
|
jumblrflag = (bits256_cmp(pubkey25519,myinfo->jumblr_pubkey) == 0 || bits256_cmp(pubkey25519,myinfo->jumblr_depositkey) == 0);
|
|
printf(">>>>>>>>>> jumblrflag.%d <<<<<<<<< use smart address, %.8f bobconfs.%d, %.8f aliceconfs.%d\n",jumblrflag,dstr(swap->I.bobsatoshis),swap->I.bobconfirms,dstr(swap->I.alicesatoshis),swap->I.aliceconfirms);
|
|
if ( swap->I.iambob != 0 )
|
|
{
|
|
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_DECKSIZE,0,0,jumblrflag);
|
|
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_DECKSIZE,0,0,jumblrflag);
|
|
bobpub33 = pubkey33;
|
|
}
|
|
else
|
|
{
|
|
basilisk_rawtx_setparms("otherfee",swap->I.req.quoteid,&swap->otherfee,swap->bobcoin,0,0,swap->I.bobsatoshis/INSTANTDEX_DECKSIZE,0,0,jumblrflag);
|
|
basilisk_rawtx_setparms("myfee",swap->I.req.quoteid,&swap->myfee,swap->alicecoin,0,0,swap->I.alicesatoshis/INSTANTDEX_DECKSIZE,0,0,jumblrflag);
|
|
alicepub33 = pubkey33;
|
|
}
|
|
basilisk_rawtx_setparms("bobdeposit",swap->I.req.quoteid,&swap->bobdeposit,swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3) + swap->bobcoin->txfee,4,0,jumblrflag);
|
|
basilisk_rawtx_setparms("bobrefund",swap->I.req.quoteid,&swap->bobrefund,swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,bobpub33,jumblrflag);
|
|
swap->bobrefund.I.suppress_pubkeys = 1;
|
|
basilisk_rawtx_setparms("aliceclaim",swap->I.req.quoteid,&swap->aliceclaim,swap->bobcoin,1,4,swap->I.bobsatoshis + (swap->I.bobsatoshis>>3),1,alicepub33,jumblrflag);
|
|
swap->aliceclaim.I.suppress_pubkeys = 1;
|
|
swap->aliceclaim.I.locktime = swap->I.started + swap->I.putduration+swap->I.callduration + 1;
|
|
|
|
basilisk_rawtx_setparms("bobpayment",swap->I.req.quoteid,&swap->bobpayment,swap->bobcoin,swap->I.bobconfirms,0,swap->I.bobsatoshis + swap->bobcoin->txfee,3,0,jumblrflag);
|
|
basilisk_rawtx_setparms("alicespend",swap->I.req.quoteid,&swap->alicespend,swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,alicepub33,jumblrflag);
|
|
swap->alicespend.I.suppress_pubkeys = 1;
|
|
basilisk_rawtx_setparms("bobreclaim",swap->I.req.quoteid,&swap->bobreclaim,swap->bobcoin,swap->I.bobconfirms,3,swap->I.bobsatoshis,1,bobpub33,jumblrflag);
|
|
swap->bobreclaim.I.suppress_pubkeys = 1;
|
|
swap->bobreclaim.I.locktime = swap->I.started + swap->I.putduration + 1;
|
|
basilisk_rawtx_setparms("alicepayment",swap->I.req.quoteid,&swap->alicepayment,swap->alicecoin,swap->I.aliceconfirms,0,swap->I.alicesatoshis+swap->alicecoin->txfee,2,0,jumblrflag);
|
|
basilisk_rawtx_setparms("bobspend",swap->I.req.quoteid,&swap->bobspend,swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,bobpub33,jumblrflag);
|
|
swap->bobspend.I.suppress_pubkeys = 1;
|
|
basilisk_rawtx_setparms("alicereclaim",swap->I.req.quoteid,&swap->alicereclaim,swap->alicecoin,swap->I.aliceconfirms,2,swap->I.alicesatoshis,1,alicepub33,jumblrflag);
|
|
swap->alicereclaim.I.suppress_pubkeys = 1;
|
|
printf("IAMBOB.%d\n",swap->I.iambob);
|
|
|
|
return(swap);
|
|
}
|
|
// end of alice/bob code
|
|
|
|
void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx)
|
|
{
|
|
if ( rawtx->vins != 0 )
|
|
free_json(rawtx->vins);
|
|
//if ( rawtx->txbytes != 0 )
|
|
// free(rawtx->txbytes), rawtx->txbytes = 0;
|
|
}
|
|
|
|
void basilisk_swap_finished(struct supernet_info *myinfo,struct basilisk_swap *swap)
|
|
{
|
|
int32_t i;
|
|
swap->I.finished = (uint32_t)time(NULL);
|
|
// save to permanent storage
|
|
basilisk_rawtx_purge(&swap->bobdeposit);
|
|
basilisk_rawtx_purge(&swap->bobpayment);
|
|
basilisk_rawtx_purge(&swap->alicepayment);
|
|
basilisk_rawtx_purge(&swap->myfee);
|
|
basilisk_rawtx_purge(&swap->otherfee);
|
|
basilisk_rawtx_purge(&swap->aliceclaim);
|
|
basilisk_rawtx_purge(&swap->alicespend);
|
|
basilisk_rawtx_purge(&swap->bobreclaim);
|
|
basilisk_rawtx_purge(&swap->bobspend);
|
|
basilisk_rawtx_purge(&swap->bobrefund);
|
|
basilisk_rawtx_purge(&swap->alicereclaim);
|
|
for (i=0; i<swap->nummessages; i++)
|
|
if ( swap->messages[i].data != 0 )
|
|
free(swap->messages[i].data), swap->messages[i].data = 0;
|
|
free(swap->messages), swap->messages = 0;
|
|
swap->nummessages = 0;
|
|
}
|
|
|
|
void basilisk_swap_purge(struct supernet_info *myinfo,struct basilisk_swap *swap)
|
|
{
|
|
int32_t i,n;
|
|
// while still in orderbook, wait
|
|
return;
|
|
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);
|
|
}
|
|
|
|
int32_t basilisk_verify_otherstatebits(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
|
|
{
|
|
int32_t retval; struct basilisk_swap *swap = ptr;
|
|
if ( datalen == sizeof(swap->I.otherstatebits) )
|
|
{
|
|
retval = iguana_rwnum(0,data,sizeof(swap->I.otherstatebits),&swap->I.otherstatebits);
|
|
return(retval);
|
|
} else return(-1);
|
|
}
|
|
|
|
int32_t basilisk_verify_choosei(struct supernet_info *myinfo,void *ptr,uint8_t *data,int32_t datalen)
|
|
{
|
|
int32_t otherchoosei=-1,i,len = 0; struct basilisk_swap *swap = ptr;
|
|
if ( datalen == sizeof(otherchoosei)+sizeof(bits256)*2 )
|
|
{
|
|
len += iguana_rwnum(0,data,sizeof(otherchoosei),&otherchoosei);
|
|
if ( otherchoosei >= 0 && otherchoosei < INSTANTDEX_DECKSIZE )
|
|
{
|
|
//printf("otherchoosei.%d\n",otherchoosei);
|
|
swap->I.otherchoosei = otherchoosei;
|
|
if ( swap->I.iambob != 0 )
|
|
{
|
|
for (i=0; i<32; i++)
|
|
swap->I.pubA0.bytes[i] = data[len++];
|
|
for (i=0; i<32; i++)
|
|
swap->I.pubA1.bytes[i] = data[len++];
|
|
char str[65]; printf("GOT pubA0/1 %s\n",bits256_str(str,swap->I.pubA0));
|
|
}
|
|
else
|
|
{
|
|
for (i=0; i<32; i++)
|
|
swap->I.pubB0.bytes[i] = data[len++];
|
|
for (i=0; i<32; i++)
|
|
swap->I.pubB1.bytes[i] = data[len++];
|
|
}
|
|
return(0);
|
|
}
|
|
}
|
|
printf("illegal otherchoosei.%d datalen.%d vs %d\n",otherchoosei,datalen,(int32_t)(sizeof(otherchoosei)+sizeof(bits256)*2));
|
|
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,void *ptr,uint8_t *data,int32_t datalen)
|
|
{
|
|
int32_t i,len = 0; struct basilisk_swap *swap = ptr;
|
|
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,void *ptr,uint8_t *data,int32_t datalen)
|
|
{
|
|
int32_t i,j,wrongfirstbyte=0,errs=0,len = 0; bits256 otherpriv,pubi; uint8_t secret160[20],otherpubkey[33]; uint64_t txid; struct basilisk_swap *swap = ptr;
|
|
//printf("verify privkeys choosei.%d otherchoosei.%d datalen.%d vs %d\n",swap->choosei,swap->otherchoosei,datalen,(int32_t)sizeof(swap->privkeys)+20+32);
|
|
memset(otherpriv.bytes,0,sizeof(otherpriv));
|
|
if ( swap->I.cutverified == 0 && swap->I.otherchoosei >= 0 && datalen == sizeof(swap->privkeys)+20+2*32 )
|
|
{
|
|
for (i=errs=0; i<sizeof(swap->privkeys)/sizeof(*swap->privkeys); i++)
|
|
{
|
|
for (j=0; j<32; j++)
|
|
otherpriv.bytes[j] = data[len++];
|
|
if ( i != swap->I.choosei )
|
|
{
|
|
pubi = bitcoin_pubkey33(myinfo->ctx,otherpubkey,otherpriv);
|
|
revcalc_rmd160_sha256(secret160,otherpriv);//.bytes,sizeof(otherpriv));
|
|
memcpy(&txid,secret160,sizeof(txid));
|
|
errs += basilisk_verify_pubpair(&wrongfirstbyte,swap,i,otherpubkey[0],pubi,txid);
|
|
}
|
|
}
|
|
if ( errs == 0 && wrongfirstbyte == 0 )
|
|
{
|
|
swap->I.cutverified = 1, printf("CUT VERIFIED\n");
|
|
if ( swap->I.iambob != 0 )
|
|
{
|
|
for (i=0; i<32; i++)
|
|
swap->I.pubAm.bytes[i] = data[len++];
|
|
for (i=0; i<20; i++)
|
|
swap->I.secretAm[i] = data[len++];
|
|
for (i=0; i<32; i++)
|
|
swap->I.secretAm256[i] = data[len++];
|
|
basilisk_bobscripts_set(myinfo,swap,1,1);
|
|
}
|
|
else
|
|
{
|
|
for (i=0; i<32; i++)
|
|
swap->I.pubBn.bytes[i] = data[len++];
|
|
for (i=0; i<20; i++)
|
|
swap->I.secretBn[i] = data[len++];
|
|
for (i=0; i<32; i++)
|
|
swap->I.secretBn256[i] = data[len++];
|
|
//basilisk_bobscripts_set(myinfo,swap,0);
|
|
}
|
|
} else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs);
|
|
}
|
|
//printf("privkeys errs.%d wrongfirstbyte.%d\n",errs,wrongfirstbyte);
|
|
return(errs);
|
|
}
|
|
|
|
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,int32_t suppress_swapsend)
|
|
{
|
|
uint8_t sendbuf[32768]; int32_t sendlen;
|
|
if ( basilisk_swapdata_rawtx(myinfo,swap,data,maxlen,rawtx) != 0 )
|
|
{
|
|
if ( bits256_nonz(rawtx->I.signedtxid) != 0 && bits256_nonz(rawtx->I.actualtxid) == 0 )
|
|
{
|
|
char str[65],str2[65];
|
|
rawtx->I.actualtxid = basilisk_swap_broadcast(rawtx->name,myinfo,swap,rawtx->coin,rawtx->txbytes,rawtx->I.datalen);
|
|
if ( bits256_cmp(rawtx->I.actualtxid,rawtx->I.signedtxid) != 0 )
|
|
{
|
|
printf("%s rawtxsend %s vs %s\n",rawtx->name,bits256_str(str,rawtx->I.signedtxid),bits256_str(str2,rawtx->I.actualtxid));
|
|
rawtx->I.actualtxid = rawtx->I.signedtxid;
|
|
}
|
|
if ( bits256_nonz(rawtx->I.actualtxid) != 0 && msgbits != 0 )
|
|
{
|
|
sendlen = 0;
|
|
sendbuf[sendlen++] = rawtx->I.datalen & 0xff;
|
|
sendbuf[sendlen++] = (rawtx->I.datalen >> 8) & 0xff;
|
|
sendbuf[sendlen++] = rawtx->I.redeemlen;
|
|
memcpy(&sendbuf[sendlen],rawtx->txbytes,rawtx->I.datalen), sendlen += rawtx->I.datalen;
|
|
if ( rawtx->I.redeemlen > 0 && rawtx->I.redeemlen < 0x100 )
|
|
{
|
|
memcpy(&sendbuf[sendlen],rawtx->redeemscript,rawtx->I.redeemlen);
|
|
sendlen += rawtx->I.redeemlen;
|
|
}
|
|
basilisk_dontforget_update(myinfo,swap,rawtx);
|
|
//printf("sendlen.%d datalen.%d redeemlen.%d\n",sendlen,rawtx->datalen,rawtx->redeemlen);
|
|
if ( suppress_swapsend == 0 )
|
|
return(basilisk_swapsend(myinfo,swap,msgbits,sendbuf,sendlen,nextbits,rawtx->I.crcs));
|
|
else
|
|
{
|
|
printf("suppress swapsend %x\n",msgbits);
|
|
return(0);
|
|
}
|
|
}
|
|
}
|
|
return(nextbits);
|
|
} else printf("error from basilisk_swapdata_rawtx.%s %p len.%d\n",rawtx->name,rawtx->txbytes,rawtx->I.datalen);
|
|
return(0);
|
|
}
|
|
|
|
void basilisk_sendpubkeys(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);
|
|
printf("send deck.%d\n",datalen);
|
|
swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x02,data,datalen,0x01,swap->I.crcs_mypub);
|
|
}
|
|
|
|
int32_t basilisk_checkdeck(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
|
|
{
|
|
if ( (swap->I.statebits & 0x02) == 0 )
|
|
{
|
|
//printf("check for other deck\n");
|
|
if ( basilisk_swapget(myinfo,swap,0x02,data,maxlen,basilisk_verify_otherdeck) == 0 )
|
|
swap->I.statebits |= 0x02;
|
|
else return(-1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void basilisk_sendstate(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
|
|
{
|
|
int32_t datalen=0;
|
|
datalen = iguana_rwnum(1,data,sizeof(swap->I.statebits),&swap->I.statebits);
|
|
basilisk_swapsend(myinfo,swap,0x80000000,data,datalen,0,0);
|
|
}
|
|
|
|
void basilisk_sendchoosei(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
|
|
{
|
|
int32_t i,datalen; char str[65];
|
|
datalen = iguana_rwnum(1,data,sizeof(swap->I.choosei),&swap->I.choosei);
|
|
if ( swap->I.iambob != 0 )
|
|
{
|
|
for (i=0; i<32; i++)
|
|
data[datalen++] = swap->I.pubB0.bytes[i];
|
|
for (i=0; i<32; i++)
|
|
data[datalen++] = swap->I.pubB1.bytes[i];
|
|
printf("SEND pubB0/1 %s\n",bits256_str(str,swap->I.pubB0));
|
|
}
|
|
else
|
|
{
|
|
for (i=0; i<32; i++)
|
|
data[datalen++] = swap->I.pubA0.bytes[i];
|
|
for (i=0; i<32; i++)
|
|
data[datalen++] = swap->I.pubA1.bytes[i];
|
|
printf("SEND pubA0/1 %s\n",bits256_str(str,swap->I.pubA0));
|
|
}
|
|
swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x08,data,datalen,0x04,swap->I.crcs_mychoosei);
|
|
}
|
|
|
|
void basilisk_waitchoosei(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
|
|
{
|
|
uint8_t pubkey33[33]; char str[65],str2[65];
|
|
//printf("check otherchoosei\n");
|
|
if ( basilisk_swapget(myinfo,swap,0x08,data,maxlen,basilisk_verify_choosei) == 0 )
|
|
{
|
|
if ( swap->I.iambob != 0 )
|
|
{
|
|
if ( bits256_nonz(swap->I.privBn) == 0 )
|
|
{
|
|
swap->I.privBn = swap->privkeys[swap->I.otherchoosei];
|
|
memset(&swap->privkeys[swap->I.otherchoosei],0,sizeof(swap->privkeys[swap->I.otherchoosei]));
|
|
revcalc_rmd160_sha256(swap->I.secretBn,swap->I.privBn);//.bytes,sizeof(swap->privBn));
|
|
vcalc_sha256(0,swap->I.secretBn256,swap->I.privBn.bytes,sizeof(swap->I.privBn));
|
|
swap->I.pubBn = bitcoin_pubkey33(myinfo->ctx,pubkey33,swap->I.privBn);
|
|
printf("set privBn.%s %s\n",bits256_str(str,swap->I.privBn),bits256_str(str2,*(bits256 *)swap->I.secretBn256));
|
|
basilisk_bobscripts_set(myinfo,swap,1,1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( bits256_nonz(swap->I.privAm) == 0 )
|
|
{
|
|
swap->I.privAm = swap->privkeys[swap->I.otherchoosei];
|
|
memset(&swap->privkeys[swap->I.otherchoosei],0,sizeof(swap->privkeys[swap->I.otherchoosei]));
|
|
revcalc_rmd160_sha256(swap->I.secretAm,swap->I.privAm);//.bytes,sizeof(swap->privAm));
|
|
vcalc_sha256(0,swap->I.secretAm256,swap->I.privAm.bytes,sizeof(swap->I.privAm));
|
|
swap->I.pubAm = bitcoin_pubkey33(myinfo->ctx,pubkey33,swap->I.privAm);
|
|
char str[65],str2[65]; printf("set privAm.%s %s\n",bits256_str(str,swap->I.privAm),bits256_str(str2,*(bits256 *)swap->I.secretAm256));
|
|
//basilisk_bobscripts_set(myinfo,swap,0);
|
|
}
|
|
}
|
|
swap->I.statebits |= 0x08;
|
|
}
|
|
}
|
|
|
|
void basilisk_sendmostprivs(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
|
|
{
|
|
int32_t i,j,datalen;
|
|
datalen = 0;
|
|
for (i=0; i<sizeof(swap->privkeys)/sizeof(*swap->privkeys); i++)
|
|
{
|
|
for (j=0; j<32; j++)
|
|
data[datalen++] = (i == swap->I.otherchoosei) ? 0 : swap->privkeys[i].bytes[j];
|
|
}
|
|
if ( swap->I.iambob != 0 )
|
|
{
|
|
for (i=0; i<32; i++)
|
|
data[datalen++] = swap->I.pubBn.bytes[i];
|
|
for (i=0; i<20; i++)
|
|
data[datalen++] = swap->I.secretBn[i];
|
|
for (i=0; i<32; i++)
|
|
data[datalen++] = swap->I.secretBn256[i];
|
|
}
|
|
else
|
|
{
|
|
for (i=0; i<32; i++)
|
|
data[datalen++] = swap->I.pubAm.bytes[i];
|
|
for (i=0; i<20; i++)
|
|
data[datalen++] = swap->I.secretAm[i];
|
|
for (i=0; i<32; i++)
|
|
data[datalen++] = swap->I.secretAm256[i];
|
|
}
|
|
//printf("send privkeys.%d\n",datalen);
|
|
swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x20,data,datalen,0x10,swap->I.crcs_myprivs);
|
|
}
|
|
|
|
int32_t basilisk_swapiteration(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
|
|
{
|
|
int32_t j,datalen,retval = 0; uint32_t savestatebits=0,saveotherbits=0;
|
|
if ( swap->I.iambob != 0 )
|
|
swap->I.statebits |= 0x80;
|
|
while ( swap->aborted == 0 && ((swap->I.otherstatebits & 0x80) == 0 || (swap->I.statebits & 0x80) == 0) && retval == 0 && time(NULL) < swap->I.expiration )
|
|
{
|
|
if ( swap->connected == 0 )
|
|
basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
|
|
printf("D r%u/q%u swapstate.%x otherstate.%x remaining %d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,swap->I.otherstatebits,(int32_t)(swap->I.expiration-time(NULL)));
|
|
if ( swap->I.iambob != 0 && (swap->I.statebits & 0x80) == 0 ) // wait for fee
|
|
{
|
|
if ( basilisk_swapget(myinfo,swap,0x80,data,maxlen,basilisk_verify_otherfee) == 0 )
|
|
{
|
|
// verify and submit otherfee
|
|
swap->I.statebits |= 0x80;
|
|
basilisk_sendstate(myinfo,swap,data,maxlen);
|
|
}
|
|
}
|
|
else if ( swap->I.iambob == 0 )
|
|
swap->I.statebits |= 0x80;
|
|
basilisk_sendstate(myinfo,swap,data,maxlen);
|
|
basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
|
|
if ( (swap->I.otherstatebits & 0x80) != 0 && (swap->I.statebits & 0x80) != 0 )
|
|
break;
|
|
if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits )
|
|
sleep(DEX_SLEEP + (swap->I.iambob == 0)*1);
|
|
savestatebits = swap->I.statebits;
|
|
saveotherbits = swap->I.otherstatebits;
|
|
basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
|
|
basilisk_sendstate(myinfo,swap,data,maxlen);
|
|
if ( (swap->I.otherstatebits & 0x80) == 0 )
|
|
basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40,0);
|
|
}
|
|
basilisk_swap_saveupdate(myinfo,swap);
|
|
while ( swap->aborted == 0 && retval == 0 && time(NULL) < swap->I.expiration ) // both sides have setup required data and paid txfee
|
|
{
|
|
basilisk_swap_saveupdate(myinfo,swap);
|
|
if ( swap->connected == 0 )
|
|
basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
|
|
//if ( (rand() % 30) == 0 )
|
|
printf("E r%u/q%u swapstate.%x otherstate.%x remaining %d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,swap->I.otherstatebits,(int32_t)(swap->I.expiration-time(NULL)));
|
|
if ( swap->I.iambob != 0 )
|
|
{
|
|
//printf("BOB\n");
|
|
if ( (swap->I.statebits & 0x100) == 0 )
|
|
{
|
|
printf("send bobdeposit\n");
|
|
swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x200,data,maxlen,&swap->bobdeposit,0x100,0);
|
|
}
|
|
// [BLOCKING: altfound] make sure altpayment is confirmed and send payment
|
|
else if ( (swap->I.statebits & 0x1000) == 0 )
|
|
{
|
|
printf("check alicepayment\n");
|
|
if ( basilisk_swapget(myinfo,swap,0x1000,data,maxlen,basilisk_verify_alicepaid) == 0 )
|
|
{
|
|
swap->I.statebits |= 0x1000;
|
|
printf("got alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms);
|
|
}
|
|
}
|
|
else if ( (swap->I.statebits & 0x2000) == 0 )
|
|
{
|
|
if ( (swap->I.aliceconfirms == 0 && swap->aliceunconf != 0) || basilisk_numconfirms(myinfo,swap,&swap->alicepayment) >= swap->I.aliceconfirms )
|
|
{
|
|
swap->I.statebits |= 0x2000;
|
|
printf("alicepayment confirmed\n");
|
|
}
|
|
}
|
|
else if ( (swap->I.statebits & 0x4000) == 0 )
|
|
{
|
|
basilisk_bobscripts_set(myinfo,swap,0,1);
|
|
printf("send bobpayment\n");
|
|
swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x8000,data,maxlen,&swap->bobpayment,0x4000,0);
|
|
}
|
|
// [BLOCKING: privM] Bob waits for privAm either from Alice or alice blockchain
|
|
else if ( (swap->I.statebits & 0xc0000) != 0xc0000 )
|
|
{
|
|
if ( basilisk_swapget(myinfo,swap,0x40000,data,maxlen,basilisk_verify_privi) == 0 || basilisk_privAm_extract(myinfo,swap) == 0 ) // divulges privAm
|
|
{
|
|
//printf("got privi spend alicepayment, dont divulge privBn until bobspend propagated\n");
|
|
basilisk_alicepayment_spend(myinfo,swap,&swap->bobspend);
|
|
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobspend,0x40000,1) == 0 )
|
|
printf("Bob error spending alice payment\n");
|
|
else
|
|
{
|
|
tradebot_swap_balancingtrade(myinfo,swap,1);
|
|
printf("Bob spends alicepayment aliceconfirms.%d\n",swap->I.aliceconfirms);
|
|
swap->I.statebits |= 0x40000;
|
|
if ( basilisk_numconfirms(myinfo,swap,&swap->bobspend) >= swap->I.aliceconfirms )
|
|
{
|
|
printf("bobspend confirmed\n");
|
|
swap->I.statebits |= 0x80000;
|
|
printf("Bob confirming spend of Alice's payment\n");
|
|
sleep(DEX_SLEEP);
|
|
}
|
|
retval = 1;
|
|
}
|
|
}
|
|
}
|
|
if ( swap->bobpayment.I.locktime != 0 && time(NULL) > swap->bobpayment.I.locktime )
|
|
{
|
|
// submit reclaim of payment
|
|
printf("bob reclaims bobpayment\n");
|
|
swap->I.statebits |= (0x40000 | 0x80000);
|
|
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobreclaim,0,0) == 0 )
|
|
printf("Bob error reclaiming own payment after alice timed out\n");
|
|
else
|
|
{
|
|
printf("Bob reclaimed own payment\n");
|
|
while ( 0 && (swap->I.statebits & 0x100000) == 0 ) // why wait for own tx?
|
|
{
|
|
if ( basilisk_numconfirms(myinfo,swap,&swap->bobreclaim) >= 1 )
|
|
{
|
|
printf("bobreclaim confirmed\n");
|
|
swap->I.statebits |= 0x100000;
|
|
printf("Bob confirms reclain of payment\n");
|
|
break;
|
|
}
|
|
}
|
|
retval = 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//printf("ALICE\n");
|
|
// [BLOCKING: depfound] Alice waits for deposit to confirm and sends altpayment
|
|
if ( (swap->I.statebits & 0x200) == 0 )
|
|
{
|
|
printf("checkfor deposit\n");
|
|
if ( basilisk_swapget(myinfo,swap,0x200,data,maxlen,basilisk_verify_bobdeposit) == 0 )
|
|
{
|
|
// verify deposit and submit, set confirmed height
|
|
printf("got bobdeposit\n");
|
|
swap->I.statebits |= 0x200;
|
|
} else printf("no valid deposit\n");
|
|
}
|
|
else if ( (swap->I.statebits & 0x400) == 0 )
|
|
{
|
|
if ( basilisk_istrustedbob(myinfo,swap) != 0 || (swap->I.bobconfirms == 0 && swap->depositunconf != 0) || basilisk_numconfirms(myinfo,swap,&swap->bobdeposit) >= swap->I.bobconfirms )
|
|
{
|
|
printf("bobdeposit confirmed\n");
|
|
swap->I.statebits |= 0x400;
|
|
}
|
|
}
|
|
else if ( (swap->I.statebits & 0x800) == 0 )
|
|
{
|
|
printf("send alicepayment\n");
|
|
swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x1000,data,maxlen,&swap->alicepayment,0x800,0);
|
|
}
|
|
// [BLOCKING: payfound] make sure payment is confrmed and send in spend or see bob's reclaim and claim
|
|
else if ( (swap->I.statebits & 0x8000) == 0 )
|
|
{
|
|
if ( basilisk_swapget(myinfo,swap,0x8000,data,maxlen,basilisk_verify_bobpaid) == 0 )
|
|
{
|
|
printf("got bobpayment\n");
|
|
tradebot_swap_balancingtrade(myinfo,swap,0);
|
|
// verify payment and submit, set confirmed height
|
|
swap->I.statebits |= 0x8000;
|
|
}
|
|
}
|
|
else if ( (swap->I.statebits & 0x10000) == 0 )
|
|
{
|
|
if ( basilisk_istrustedbob(myinfo,swap) != 0 || (swap->I.bobconfirms == 0 && swap->paymentunconf != 0) || basilisk_numconfirms(myinfo,swap,&swap->bobpayment) >= swap->I.bobconfirms )
|
|
{
|
|
printf("bobpayment confirmed\n");
|
|
swap->I.statebits |= 0x10000;
|
|
}
|
|
}
|
|
else if ( (swap->I.statebits & 0x20000) == 0 )
|
|
{
|
|
printf("alicespend bobpayment\n");
|
|
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicespend,0x20000,0) != 0 )//&& (swap->aliceunconf != 0 || basilisk_numconfirms(myinfo,swap,&swap->alicespend) > 0) )
|
|
{
|
|
swap->I.statebits |= 0x20000;
|
|
}
|
|
}
|
|
else if ( (swap->I.statebits & 0x40000) == 0 )
|
|
{
|
|
int32_t numconfs;
|
|
if ( (numconfs= basilisk_numconfirms(myinfo,swap,&swap->alicespend)) >= swap->I.bobconfirms )
|
|
{
|
|
for (j=datalen=0; j<32; j++)
|
|
data[datalen++] = swap->I.privAm.bytes[j];
|
|
printf("send privAm %x\n",swap->I.statebits);
|
|
swap->I.statebits |= basilisk_swapsend(myinfo,swap,0x40000,data,datalen,0x20000,swap->I.crcs_mypriv);
|
|
printf("Alice confirms spend of Bob's payment\n");
|
|
retval = 1;
|
|
} else printf("alicespend numconfs.%d < %d\n",numconfs,swap->I.bobconfirms);
|
|
}
|
|
if ( swap->bobdeposit.I.locktime != 0 && time(NULL) > swap->bobdeposit.I.locktime )
|
|
{
|
|
printf("Alice claims deposit\n");
|
|
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->aliceclaim,0,0) == 0 )
|
|
printf("Alice couldnt claim deposit\n");
|
|
else
|
|
{
|
|
printf("Alice claimed deposit\n");
|
|
retval = 1;
|
|
}
|
|
}
|
|
else if ( swap->aborted != 0 || basilisk_privBn_extract(myinfo,swap,data,maxlen) == 0 )
|
|
{
|
|
printf("Alice reclaims her payment\n");
|
|
swap->I.statebits |= 0x40000000;
|
|
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->alicereclaim,0x40000000,0) == 0 )
|
|
printf("Alice error sending alicereclaim\n");
|
|
else
|
|
{
|
|
printf("Alice reclaimed her payment\n");
|
|
retval = 1;
|
|
}
|
|
}
|
|
}
|
|
if ( (rand() % 30) == 0 )
|
|
printf("finished swapstate.%x other.%x\n",swap->I.statebits,swap->I.otherstatebits);
|
|
if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits )
|
|
sleep(DEX_SLEEP + (swap->I.iambob == 0)*1);
|
|
savestatebits = swap->I.statebits;
|
|
saveotherbits = swap->I.otherstatebits;
|
|
basilisk_sendstate(myinfo,swap,data,maxlen);
|
|
basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
|
|
}
|
|
return(retval);
|
|
}
|
|
|
|
int32_t swapcompleted(struct supernet_info *myinfo,struct basilisk_swap *swap)
|
|
{
|
|
if ( swap->I.iambob != 0 )
|
|
return(swap->I.bobspent);
|
|
else return(swap->I.alicespent);
|
|
}
|
|
|
|
cJSON *swapjson(struct supernet_info *myinfo,struct basilisk_swap *swap)
|
|
{
|
|
cJSON *retjson = cJSON_CreateObject();
|
|
return(retjson);
|
|
}
|
|
|
|
void basilisk_psockinit(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t amlp)
|
|
{
|
|
char keystr[64],databuf[1024],*retstr,*retstr2,*datastr,*pushaddr=0,*subaddr=0; cJSON *retjson,*addrjson; uint8_t data[512]; int32_t datalen,timeout,pushsock = -1,subsock = -1;
|
|
if ( swap->connected == 1 )
|
|
return;
|
|
if ( swap->pushsock < 0 && swap->subsock < 0 && (pushsock= nn_socket(AF_SP,NN_PUSH)) >= 0 && (subsock= nn_socket(AF_SP,NN_SUB)) >= 0 )
|
|
{
|
|
timeout = 1000;
|
|
nn_setsockopt(pushsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout));
|
|
timeout = 1;
|
|
nn_setsockopt(subsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout));
|
|
nn_setsockopt(subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0);
|
|
swap->pushsock = pushsock;
|
|
swap->subsock = subsock;
|
|
}
|
|
if ( swap->subsock < 0 || swap->pushsock < 0 )
|
|
{
|
|
printf("error getting nn_sockets\n");
|
|
return;
|
|
}
|
|
sprintf(keystr,"%08x-%08x",swap->I.req.requestid,swap->I.req.quoteid);
|
|
if ( swap->connected == 0 && (retstr= _dex_kvsearch(myinfo,"KV",keystr)) != 0 )
|
|
{
|
|
if ( (retjson= cJSON_Parse(retstr)) != 0 )
|
|
{
|
|
if ( (datastr= jstr(retjson,"value")) != 0 )
|
|
{
|
|
datalen = (int32_t)strlen(datastr) >> 1;
|
|
decode_hex((uint8_t *)databuf,datalen,datastr);
|
|
if ( (addrjson= cJSON_Parse(databuf)) != 0 )
|
|
{
|
|
pushaddr = jstr(addrjson,"push");
|
|
subaddr = jstr(addrjson,"sub");
|
|
if ( pushaddr != 0 && subaddr != 0 )
|
|
{
|
|
printf("KV decoded (%s and %s) %d %d\n",pushaddr,subaddr,swap->pushsock,swap->subsock);
|
|
if ( nn_connect(swap->pushsock,pushaddr) >= 0 && nn_connect(swap->subsock,subaddr) >= 0 )
|
|
swap->connected = 1;
|
|
}
|
|
free_json(addrjson);
|
|
}
|
|
}
|
|
free_json(retjson);
|
|
}
|
|
printf("KVsearch.(%s) connected.%d socks.(%d %d)\n",retstr,swap->connected,swap->pushsock,swap->subsock);
|
|
free(retstr);
|
|
}
|
|
if ( swap->connected <= 0 && amlp != 0 )
|
|
{
|
|
if ( (retstr= _dex_psock(myinfo,"{}")) != 0 )
|
|
{
|
|
// {"result":"success","pushaddr":"tcp://5.9.102.210:30002","subaddr":"tcp://5.9.102.210:30003","randipbits":3606291758,"coin":"KMD","tag":"6952562460568228137"}
|
|
if ( (retjson= cJSON_Parse(retstr)) != 0 )
|
|
{
|
|
pushaddr = jstr(retjson,"pushaddr");
|
|
subaddr = jstr(retjson,"subaddr");
|
|
if ( pushaddr != 0 && subaddr != 0 )
|
|
{
|
|
if ( nn_connect(pushsock,pushaddr) >= 0 && nn_connect(subsock,subaddr) >= 0 )
|
|
{
|
|
swap->connected = 1;
|
|
sprintf((char *)data,"{\"push\":\"%s\",\"sub\":\"%s\",\"trade\":[\"%s\", %.8f, \"%s\", %.8f]}",pushaddr,subaddr,swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount));
|
|
datalen = (int32_t)strlen((char *)data) + 1;
|
|
printf("datalen.%d (%s)\n",datalen,(char *)data);
|
|
init_hexbytes_noT(databuf,data,datalen);
|
|
printf("%s -> %s\n",keystr,databuf);
|
|
if ( (retstr2= _dex_kvupdate(myinfo,"KV",keystr,databuf,1)) != 0 )
|
|
{
|
|
printf("KVupdate.(%s)\n",retstr2);
|
|
free(retstr2);
|
|
}
|
|
}
|
|
}
|
|
free_json(retjson);
|
|
}
|
|
free(retstr);
|
|
}
|
|
}
|
|
}
|
|
|
|
int32_t basilisk_alicetxs(struct supernet_info *myinfo,struct basilisk_swap *swap,uint8_t *data,int32_t maxlen)
|
|
{
|
|
int32_t i,retval = -1;
|
|
for (i=0; i<3; i++)
|
|
{
|
|
basilisk_alicepayment(myinfo,swap,swap->alicepayment.coin,&swap->alicepayment,swap->I.pubAm,swap->I.pubBn);
|
|
if ( swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.spendlen == 0 )
|
|
{
|
|
printf("error alice generating payment.%d\n",swap->alicepayment.I.spendlen);
|
|
sleep(20);
|
|
}
|
|
else
|
|
{
|
|
retval = 0;
|
|
for (i=0; i<swap->alicepayment.I.datalen; i++)
|
|
printf("%02x",swap->alicepayment.txbytes[i]);
|
|
printf(" ALICE PAYMENT created\n");
|
|
iguana_unspents_mark(myinfo,swap->alicecoin,swap->alicepayment.vins);
|
|
basilisk_txlog(myinfo,swap,&swap->alicepayment,-1);
|
|
break;
|
|
}
|
|
}
|
|
printf("generate fee\n");
|
|
if ( basilisk_rawtx_gen("myfee",myinfo,swap->I.started,swap->persistent_pubkey33,swap->I.iambob,1,&swap->myfee,0,swap->myfee.spendscript,swap->myfee.I.spendlen,swap->myfee.coin->chain->txfee,1,0) == 0 )
|
|
{
|
|
swap->I.statebits |= basilisk_swapdata_rawtxsend(myinfo,swap,0x80,data,maxlen,&swap->myfee,0x40,0);
|
|
iguana_unspents_mark(myinfo,swap->I.iambob!=0?swap->bobcoin:swap->alicecoin,swap->myfee.vins);
|
|
basilisk_txlog(myinfo,swap,&swap->myfee,-1);
|
|
for (i=0; i<swap->myfee.I.spendlen; i++)
|
|
printf("%02x",swap->myfee.txbytes[i]);
|
|
printf(" fee %p %x\n",swap->myfee.txbytes,swap->I.statebits);
|
|
swap->I.statebits |= 0x40;
|
|
if ( swap->alicepayment.I.datalen != 0 && swap->alicepayment.I.spendlen > 0 )
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
printf("error creating myfee\n");
|
|
return(-2);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
void basilisk_swaploop(void *_swap)
|
|
{
|
|
uint8_t *data; uint32_t expiration,savestatebits=0,saveotherbits=0; uint32_t channel; int32_t iters,retval=0,j,datalen,maxlen; struct supernet_info *myinfo; struct basilisk_swap *swap = _swap;
|
|
myinfo = swap->myinfoptr;
|
|
fprintf(stderr,"start swap\n");
|
|
maxlen = 1024*1024 + sizeof(*swap);
|
|
data = malloc(maxlen);
|
|
expiration = (uint32_t)time(NULL) + 600;
|
|
myinfo->DEXactive = expiration;
|
|
channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16);
|
|
while ( swap->aborted == 0 && (swap->I.statebits & (0x08|0x02)) != (0x08|0x02) && time(NULL) < expiration )
|
|
{
|
|
dex_channelsend(myinfo,swap->I.req.srchash,swap->I.req.desthash,channel,0x4000000,(void *)&swap->I.req.requestid,sizeof(swap->I.req.requestid)); //,60);
|
|
if ( swap->connected == 0 )
|
|
basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
|
|
if ( swap->connected > 0 )
|
|
{
|
|
printf("A r%u/q%u swapstate.%x\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits);
|
|
basilisk_sendstate(myinfo,swap,data,maxlen);
|
|
basilisk_sendpubkeys(myinfo,swap,data,maxlen); // send pubkeys
|
|
if ( basilisk_checkdeck(myinfo,swap,data,maxlen) == 0) // check for other deck 0x02
|
|
basilisk_sendchoosei(myinfo,swap,data,maxlen);
|
|
basilisk_waitchoosei(myinfo,swap,data,maxlen); // wait for choosei 0x08
|
|
if ( (swap->I.statebits & (0x08|0x02)) == (0x08|0x02) )
|
|
break;
|
|
}
|
|
if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits )
|
|
sleep(DEX_SLEEP + (swap->I.iambob == 0)*1);
|
|
savestatebits = swap->I.statebits;
|
|
saveotherbits = swap->I.otherstatebits;
|
|
}
|
|
if ( swap->connected == 0 )
|
|
{
|
|
printf("couldnt establish connection\n");
|
|
retval = -1;
|
|
}
|
|
while ( swap->aborted == 0 && retval == 0 && (swap->I.statebits & 0x20) == 0 && time(NULL) < expiration )
|
|
{
|
|
if ( swap->connected == 0 )
|
|
basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
|
|
printf("B r%u/q%u swapstate.%x\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits);
|
|
basilisk_sendstate(myinfo,swap,data,maxlen);
|
|
basilisk_sendchoosei(myinfo,swap,data,maxlen);
|
|
basilisk_sendmostprivs(myinfo,swap,data,maxlen);
|
|
if ( basilisk_swapget(myinfo,swap,0x20,data,maxlen,basilisk_verify_privkeys) == 0 )
|
|
{
|
|
swap->I.statebits |= 0x20;
|
|
break;
|
|
}
|
|
if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits )
|
|
sleep(DEX_SLEEP + (swap->I.iambob == 0)*1);
|
|
savestatebits = swap->I.statebits;
|
|
saveotherbits = swap->I.otherstatebits;
|
|
}
|
|
myinfo->DEXactive = swap->I.expiration;
|
|
if ( time(NULL) >= expiration )
|
|
{
|
|
retval = -1;
|
|
myinfo->DEXactive = 0;
|
|
}
|
|
if ( swap->aborted != 0 )
|
|
{
|
|
printf("swap aborted before tx sent\n");
|
|
retval = -1;
|
|
}
|
|
printf("C r%u/q%u swapstate.%x retval.%d\n",swap->I.req.requestid,swap->I.req.quoteid,swap->I.statebits,retval);
|
|
iters = 0;
|
|
while ( swap->aborted == 0 && retval == 0 && (swap->I.statebits & 0x40) == 0 && iters++ < 10 ) // send fee
|
|
{
|
|
if ( swap->connected == 0 )
|
|
basilisk_psockinit(myinfo,swap,swap->I.iambob != 0);
|
|
//printf("sendstate.%x\n",swap->I.statebits);
|
|
basilisk_sendstate(myinfo,swap,data,maxlen);
|
|
//printf("swapget\n");
|
|
basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
|
|
//printf("after swapget\n");
|
|
if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen == 0 )
|
|
{
|
|
printf("bobscripts set\n");
|
|
if ( basilisk_bobscripts_set(myinfo,swap,1,1) < 0 )
|
|
{
|
|
sleep(DEX_SLEEP);
|
|
printf("bobscripts set error\n");
|
|
continue;
|
|
}
|
|
}
|
|
if ( swap->I.iambob == 0 && swap->myfee.I.datalen == 0 )
|
|
{
|
|
/*for (i=0; i<20; i++)
|
|
printf("%02x",swap->secretAm[i]);
|
|
printf(" <- secretAm\n");
|
|
for (i=0; i<32; i++)
|
|
printf("%02x",swap->secretAm256[i]);
|
|
printf(" <- secretAm256\n");
|
|
for (i=0; i<32; i++)
|
|
printf("%02x",swap->pubAm.bytes[i]);
|
|
printf(" <- pubAm\n");
|
|
for (i=0; i<20; i++)
|
|
printf("%02x",swap->secretBn[i]);
|
|
printf(" <- secretBn\n");
|
|
for (i=0; i<32; i++)
|
|
printf("%02x",swap->secretBn256[i]);
|
|
printf(" <- secretBn256\n");
|
|
for (i=0; i<32; i++)
|
|
printf("%02x",swap->pubBn.bytes[i]);
|
|
printf(" <- pubBn\n");
|
|
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");*/
|
|
if ( (retval= basilisk_alicetxs(myinfo,swap,data,maxlen)) != 0 )
|
|
{
|
|
printf("basilisk_alicetxs error\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( swap->I.iambob == 0 && (swap->I.statebits & 0x40) == 0 )
|
|
{
|
|
printf("couldnt send fee\n");
|
|
retval = -8;
|
|
}
|
|
if ( retval == 0 )
|
|
{
|
|
if ( swap->I.iambob == 0 && (swap->myfee.I.datalen == 0 || swap->alicepayment.I.datalen == 0 || swap->alicepayment.I.datalen == 0) )
|
|
{
|
|
printf("ALICE's error %d %d %d\n",swap->myfee.I.datalen,swap->alicepayment.I.datalen,swap->alicepayment.I.datalen);
|
|
retval = -7;
|
|
}
|
|
else if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen == 0 ) //swap->bobpayment.I.datalen == 0
|
|
{
|
|
printf("BOB's error %d %d %d\n",swap->myfee.I.datalen,swap->bobpayment.I.datalen,swap->bobdeposit.I.datalen);
|
|
retval = -7;
|
|
}
|
|
}
|
|
while ( swap->aborted == 0 && retval == 0 && basilisk_swapiteration(myinfo,swap,data,maxlen) == 0 )
|
|
{
|
|
if ( swap->I.statebits == savestatebits && swap->I.otherstatebits == saveotherbits )
|
|
sleep(DEX_SLEEP + (swap->I.iambob == 0)*1);
|
|
savestatebits = swap->I.statebits;
|
|
saveotherbits = swap->I.otherstatebits;
|
|
basilisk_sendstate(myinfo,swap,data,maxlen);
|
|
basilisk_swapget(myinfo,swap,0x80000000,data,maxlen,basilisk_verify_otherstatebits);
|
|
basilisk_swap_saveupdate(myinfo,swap);
|
|
if ( time(NULL) > swap->I.expiration )
|
|
break;
|
|
}
|
|
if ( swap->I.iambob != 0 && swap->bobdeposit.I.datalen != 0 && bits256_nonz(swap->bobdeposit.I.actualtxid) != 0 )
|
|
{
|
|
printf("BOB waiting for confirm state.%x\n",swap->I.statebits);
|
|
sleep(60); // wait for confirm/propagation of msig
|
|
printf("BOB reclaims refund\n");
|
|
basilisk_bobdeposit_refund(myinfo,swap,0);
|
|
if ( basilisk_swapdata_rawtxsend(myinfo,swap,0,data,maxlen,&swap->bobrefund,0x40000000,0) == 0 ) // use secretBn
|
|
{
|
|
printf("Bob submit error getting refund of deposit\n");
|
|
}
|
|
else
|
|
{
|
|
// maybe wait for bobrefund to be confirmed
|
|
for (j=datalen=0; j<32; j++)
|
|
data[datalen++] = swap->I.privBn.bytes[j];
|
|
basilisk_swapsend(myinfo,swap,0x40000000,data,datalen,0x40000000,swap->I.crcs_mypriv);
|
|
}
|
|
basilisk_swap_saveupdate(myinfo,swap);
|
|
}
|
|
if ( retval != 0 )
|
|
basilisk_swap_sendabort(myinfo,swap);
|
|
printf("end of atomic swap\n");
|
|
if ( swapcompleted(myinfo,swap) > 0 ) // only if swap completed
|
|
{
|
|
if ( swap->I.iambob != 0 )
|
|
tradebot_pendingadd(myinfo,swapjson(myinfo,swap),swap->I.req.src,dstr(swap->I.req.srcamount),swap->I.req.dest,dstr(swap->I.req.destamount));
|
|
else tradebot_pendingadd(myinfo,swapjson(myinfo,swap),swap->I.req.dest,dstr(swap->I.req.destamount),swap->I.req.src,dstr(swap->I.req.srcamount));
|
|
}
|
|
printf("%s swap finished statebits %x\n",swap->I.iambob!=0?"BOB":"ALICE",swap->I.statebits);
|
|
basilisk_swap_purge(myinfo,swap);
|
|
free(data);
|
|
}
|
|
|
|
cJSON *basilisk_swapjson(struct supernet_info *myinfo,struct basilisk_swap *swap)
|
|
{
|
|
cJSON *item = cJSON_CreateObject();
|
|
jaddnum(item,"requestid",swap->I.req.requestid);
|
|
jaddnum(item,"quoteid",swap->I.req.quoteid);
|
|
jaddnum(item,"state",swap->I.statebits);
|
|
jaddnum(item,"otherstate",swap->I.otherstatebits);
|
|
jadd(item,"request",basilisk_requestjson(&swap->I.req));
|
|
return(item);
|
|
}
|
|
|
|
struct basilisk_swap *basilisk_thread_start(struct supernet_info *myinfo,bits256 privkey,struct basilisk_request *rp,uint32_t statebits,int32_t optionduration,int32_t reinit)
|
|
{
|
|
int32_t i,m,n; uint8_t pubkey33[33]; bits256 pubkey25519; uint32_t channel,starttime; cJSON *retarray,*item,*msgobj; struct iguana_info *coin; struct basilisk_swap *swap = 0;
|
|
// statebits 1 -> client, 0 -> LP
|
|
if ( statebits == 0 && myinfo->numswaps > 0 )
|
|
{
|
|
if ( (coin= iguana_coinfind(rp->src)) == 0 || coin->FULLNODE >= 0 )
|
|
{
|
|
printf("dont have SRC coin.%s or not native and already swap pending\n",rp->src);
|
|
return(0);
|
|
}
|
|
if ( (coin= iguana_coinfind(rp->dest)) == 0 || coin->FULLNODE >= 0 )
|
|
{
|
|
printf("dont have DEST coin.%s or not native and already swap pending\n",rp->dest);
|
|
return(0);
|
|
}
|
|
}
|
|
portable_mutex_lock(&myinfo->DEX_swapmutex);
|
|
for (i=0; i<myinfo->numswaps; i++)
|
|
if ( myinfo->swaps[i]->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->subsock = swap->pushsock = -1;
|
|
vcalc_sha256(0,swap->I.orderhash.bytes,(uint8_t *)rp,sizeof(*rp));
|
|
swap->I.req = *rp;
|
|
swap->myinfoptr = myinfo;
|
|
printf("basilisk_thread_start request.%u statebits.%d (%s/%s) reinit.%d\n",rp->requestid,statebits,rp->src,rp->dest,reinit);
|
|
bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey);
|
|
pubkey25519 = curve25519(privkey,curve25519_basepoint9());
|
|
swap->persistent_pubkey = pubkey25519;
|
|
swap->persistent_privkey = privkey;
|
|
memcpy(swap->persistent_pubkey33,pubkey33,33);
|
|
m = n = 0;
|
|
if ( bitcoin_swapinit(myinfo,privkey,pubkey33,pubkey25519,swap,optionduration,statebits,reinit) != 0 )
|
|
{
|
|
basilisk_psockinit(myinfo,swap,statebits == 0);
|
|
if ( reinit != 0 )
|
|
{
|
|
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)basilisk_swaploop,(void *)swap) != 0 )
|
|
{
|
|
|
|
}
|
|
myinfo->swaps[myinfo->numswaps++] = swap;
|
|
}
|
|
else
|
|
{
|
|
starttime = (uint32_t)time(NULL);
|
|
printf("statebits.%x m.%d n.%d\n",statebits,m,n);
|
|
while ( statebits == 0 && m <= n/2 && time(NULL) < starttime+2*BASILISK_MSGDURATION )
|
|
{
|
|
m = n = 0;
|
|
sleep(DEX_SLEEP);
|
|
printf("waiting for offer to be accepted\n");
|
|
channel = 'D' + ((uint32_t)'E' << 8) + ((uint32_t)'X' << 16);
|
|
if ( (retarray= basilisk_channelget(myinfo,rp->srchash,rp->desthash,channel,0x4000000,30)) != 0 )
|
|
{
|
|
if ( is_cJSON_Array(retarray) != 0 && (n= cJSON_GetArraySize(retarray)) > 0 )
|
|
{
|
|
for (i=0; i<n; i++)
|
|
{
|
|
item = jitem(retarray,i);
|
|
if ( (msgobj= jarray(&n,item,"messages")) != 0 && n > 0 )
|
|
{
|
|
item = jitem(msgobj,0);
|
|
if ( jobj(item,"data") != 0 && jobj(item,"key") != 0 )
|
|
m++;
|
|
else printf("(%s)\n",jprint(item,0));
|
|
} //else printf("msgobj.%p m.%d n.%d\n",msgobj,m,n);
|
|
}
|
|
}
|
|
} else printf("no retarray\n");
|
|
}
|
|
printf("LAUNCH check.%d m.%d\n",statebits,m);
|
|
if ( statebits != 0 || m > 0 )//n/2 )
|
|
{
|
|
//for (i=0; i<sizeof(swap->I.req); i++)
|
|
// fprintf(stderr,"%02x",((uint8_t *)&swap->I.req)[i]);
|
|
fprintf(stderr," M.%d N.%d launch.%d %d %p reinit.%d\n",m,n,myinfo->numswaps,(int32_t)(sizeof(myinfo->swaps)/sizeof(*myinfo->swaps)),&swap->I.req,reinit);
|
|
if ( (swap->fp= basilisk_swap_save(myinfo,swap,privkey,rp,statebits,optionduration,reinit)) != 0 )
|
|
{
|
|
}
|
|
if ( reinit == 0 )
|
|
{
|
|
if ( myinfo->swapsfp == 0 )
|
|
{
|
|
char fname[512];
|
|
sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname);
|
|
if ( (myinfo->swapsfp= fopen(fname,"rb+")) == 0 )
|
|
myinfo->swapsfp = fopen(fname,"wb+");
|
|
else fseek(myinfo->swapsfp,0,SEEK_END);
|
|
printf("LIST fp.%p\n",myinfo->swapsfp);
|
|
}
|
|
if ( myinfo->swapsfp != 0 )
|
|
{
|
|
fwrite(&rp->requestid,1,sizeof(rp->requestid),myinfo->swapsfp);
|
|
fwrite(&rp->quoteid,1,sizeof(rp->quoteid),myinfo->swapsfp);
|
|
fflush(myinfo->swapsfp);
|
|
}
|
|
}
|
|
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)basilisk_swaploop,(void *)swap) != 0 )
|
|
{
|
|
|
|
}
|
|
myinfo->swaps[myinfo->numswaps++] = swap;
|
|
} else printf("%u/%u offer wasnt accepted statebits.%d m.%d n.%d\n",rp->requestid,rp->quoteid,statebits,m,n);
|
|
}
|
|
}
|
|
}
|
|
portable_mutex_unlock(&myinfo->DEX_swapmutex);
|
|
return(swap);
|
|
}
|
|
|
|
/////////////// remember functions
|
|
|
|
cJSON *basilisk_nullretjson(cJSON *retjson)
|
|
{
|
|
char *outstr;
|
|
if ( retjson != 0 )
|
|
{
|
|
outstr = jprint(retjson,0);
|
|
if ( strcmp(outstr,"{}") == 0 )
|
|
{
|
|
free_json(retjson);
|
|
retjson = 0;
|
|
}
|
|
free(outstr);
|
|
}
|
|
return(retjson);
|
|
}
|
|
|
|
cJSON *basilisk_swapgettxout(struct supernet_info *myinfo,char *symbol,bits256 trigger,int32_t vout)
|
|
{
|
|
char *retstr; cJSON *retjson=0; struct iguana_info *coin;
|
|
if ( ((coin= iguana_coinfind(symbol)) == 0 || coin->FULLNODE == 0) && iguana_isnotarychain(symbol) >= 0 )
|
|
{
|
|
if ( (retstr= dex_gettxout(myinfo,0,0,0,trigger,symbol,vout)) != 0 )
|
|
{
|
|
//printf("dexgettxout.(%s)\n",retstr);
|
|
retjson = cJSON_Parse(retstr);
|
|
free(retstr);
|
|
}
|
|
if ( 0 && strcmp("BTC",symbol) == 0 )
|
|
printf("%s gettxout.(%s)\n",symbol,jprint(retjson,0));
|
|
}
|
|
else
|
|
{
|
|
retjson = dpow_gettxout(myinfo,coin,trigger,vout);
|
|
printf("need to verify passthru has this info\n");
|
|
printf("dpowgettxout.(%s)\n",jprint(retjson,0));
|
|
}
|
|
return(basilisk_nullretjson(retjson));
|
|
}
|
|
|
|
cJSON *basilisk_swapgettx(struct supernet_info *myinfo,char *symbol,bits256 txid)
|
|
{
|
|
char *retstr; cJSON *retjson=0; struct iguana_info *coin;
|
|
if ( ((coin= iguana_coinfind(symbol)) == 0 || coin->FULLNODE == 0) && iguana_isnotarychain(symbol) >= 0 )
|
|
{
|
|
if ( (retstr= dex_gettransaction(myinfo,0,0,0,txid,symbol)) != 0 )
|
|
{
|
|
retjson = cJSON_Parse(retstr);
|
|
free(retstr);
|
|
}
|
|
//if ( strcmp("BTC",symbol) == 0 )
|
|
// printf("%s gettx.(%s)\n",symbol,jprint(retjson,0));
|
|
} else retjson = dpow_gettransaction(myinfo,coin,txid);
|
|
return(basilisk_nullretjson(retjson));
|
|
}
|
|
|
|
int32_t basilisk_swap_txdestaddr(char *destaddr,bits256 txid,int32_t vout,cJSON *txobj)
|
|
{
|
|
int32_t n,m,retval = -1; cJSON *vouts,*item,*addresses,*skey; char *addr;
|
|
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n )
|
|
{
|
|
item = jitem(vouts,vout);
|
|
if ( (skey= jobj(item,"scriptPubKey")) != 0 && (addresses= jarray(&m,skey,"addresses")) != 0 )
|
|
{
|
|
item = jitem(addresses,0);
|
|
if ( (addr= jstr(item,0)) != 0 )
|
|
{
|
|
safecopy(destaddr,addr,64);
|
|
retval = 0;
|
|
}
|
|
//printf("item.(%s) -> dest.(%s)\n",jprint(item,0),destaddr);
|
|
}
|
|
}
|
|
return(retval);
|
|
}
|
|
|
|
int32_t basilisk_swap_getcoinaddr(struct supernet_info *myinfo,char *symbol,char *coinaddr,bits256 txid,int32_t vout)
|
|
{
|
|
cJSON *retjson;
|
|
coinaddr[0] = 0;
|
|
if ( (retjson= basilisk_swapgettx(myinfo,symbol,txid)) != 0 )
|
|
{
|
|
basilisk_swap_txdestaddr(coinaddr,txid,vout,retjson);
|
|
free_json(retjson);
|
|
}
|
|
return(coinaddr[0] != 0);
|
|
}
|
|
|
|
int32_t basilisk_swap_getsigscript(struct supernet_info *myinfo,char *symbol,uint8_t *script,int32_t maxlen,bits256 txid,int32_t vini)
|
|
{
|
|
cJSON *retjson,*vins,*item,*skey; int32_t n,scriptlen = 0; char *hexstr;
|
|
if ( (retjson= basilisk_swapgettx(myinfo,symbol,txid)) != 0 )
|
|
{
|
|
if ( (vins= jarray(&n,retjson,"vin")) != 0 && vini < n )
|
|
{
|
|
item = jitem(vins,vini);
|
|
if ( (skey= jobj(item,"scriptSig")) != 0 && (hexstr= jstr(skey,"hex")) != 0 && (scriptlen= (int32_t)strlen(hexstr)) < maxlen*2 )
|
|
{
|
|
scriptlen >>= 1;
|
|
decode_hex(script,scriptlen,hexstr);
|
|
//char str[65]; printf("%s/v%d sigscript.(%s)\n",bits256_str(str,txid),vini,hexstr);
|
|
}
|
|
}
|
|
free_json(retjson);
|
|
}
|
|
return(scriptlen);
|
|
}
|
|
|
|
bits256 basilisk_swap_spendtxid(struct supernet_info *myinfo,char *symbol,char *destaddr,bits256 utxotxid,int32_t vout)
|
|
{
|
|
bits256 spendtxid,txid; char *retstr,*addr; cJSON *array,*array2,*item; int32_t i,n,m; char coinaddr[64]; struct iguana_info *coin = iguana_coinfind(symbol);
|
|
// listtransactions or listspents
|
|
destaddr[0] = 0;
|
|
memset(&spendtxid,0,sizeof(spendtxid));
|
|
//char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid));
|
|
if ( (coin == 0 || coin->FULLNODE >= 0) && iguana_isnotarychain(symbol) >= 0 )
|
|
{
|
|
//[{"type":"sent","confirmations":379,"height":275311,"timestamp":1492084664,"txid":"8703c5517bc57db38134058370a14e99b8e662b99ccefa2061dea311bbd02b8b","vout":0,"amount":117.50945263,"spendtxid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","vin":0,"paid":{"type":"paid","txid":"cf2509e076fbb9b22514923df916b7aacb1391dce9c7e1460b74947077b12510","height":275663,"timestamp":1492106024,"vouts":[{"RUDpN6PEBsE7ZFbGjUxk1W3QVsxnjBLYw6":117.50935263}]}}]
|
|
basilisk_swap_getcoinaddr(myinfo,symbol,coinaddr,utxotxid,vout);
|
|
//printf("spendtxid %s dest.(%s)\n",symbol,coinaddr);
|
|
if ( coinaddr[0] != 0 && (retstr= dex_listtransactions(myinfo,0,0,0,symbol,coinaddr,100,0)) != 0 )
|
|
{
|
|
//printf("listtransactions.(%s)\n",retstr);
|
|
if ( (array= cJSON_Parse(retstr)) != 0 )
|
|
{
|
|
if ( (n= cJSON_GetArraySize(array)) > 0 )
|
|
{
|
|
for (i=0; i<n; i++)
|
|
{
|
|
if ( (item= jitem(array,i)) == 0 )
|
|
continue;
|
|
txid = jbits256(item,"txid");
|
|
if ( bits256_nonz(txid) == 0 )
|
|
{
|
|
spendtxid = jbits256(item,"hash");
|
|
if ( (array2= jarray(&m,item,"inputs")) != 0 && m == 1 )
|
|
{
|
|
//printf("found inputs with %s\n",bits256_str(str,spendtxid));
|
|
txid = jbits256(jitem(array2,0),"output_hash");
|
|
if ( bits256_cmp(txid,utxotxid) == 0 )
|
|
{
|
|
//printf("matched %s\n",bits256_str(str,txid));
|
|
if ( (array2= jarray(&m,item,"outputs")) != 0 && m == 1 && (addr= jstr(jitem(array2,0),"address")) != 0 )
|
|
{
|
|
strcpy(destaddr,addr);
|
|
//printf("set addr.(%s)\n",addr);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( bits256_cmp(txid,utxotxid) == 0 )
|
|
{
|
|
spendtxid = jbits256(item,"spendtxid");
|
|
if ( bits256_nonz(spendtxid) != 0 )
|
|
{
|
|
basilisk_swap_getcoinaddr(myinfo,symbol,destaddr,spendtxid,0);
|
|
//char str[65]; printf("found spendtxid.(%s) -> %s\n",bits256_str(str,spendtxid),destaddr);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(retstr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("need to find spendtxid the hard way\n");
|
|
}
|
|
return(spendtxid);
|
|
}
|
|
|
|
bits256 basilisk_swap_sendrawtransaction(struct supernet_info *myinfo,char *txname,char *symbol,char *txbytes)
|
|
{
|
|
char *retstr; bits256 txid; int32_t i,sentflag = 0;
|
|
memset(&txid,0,sizeof(txid));
|
|
for (i=0; i<3; i++)
|
|
{
|
|
if ( (retstr= _dex_sendrawtransaction(myinfo,symbol,txbytes)) != 0 )
|
|
{
|
|
if ( is_hexstr(retstr,0) == 64 )
|
|
{
|
|
decode_hex(txid.bytes,32,retstr);
|
|
sentflag = 1;
|
|
}
|
|
char str[65]; printf("[%s] %s RETSTR.(%s) %s.%s\n",txname,txbytes,retstr,symbol,bits256_str(str,txid));
|
|
free(retstr);
|
|
}
|
|
if ( sentflag != 0 )
|
|
break;
|
|
}
|
|
return(txid);
|
|
}
|
|
|
|
char *basilisk_swap_bobtxspend(char *name,struct supernet_info *myinfo,char *symbol,bits256 privkey,bits256 *privkey2p,uint8_t *redeemscript,int32_t redeemlen,uint8_t *userdata,int32_t userdatalen,bits256 utxotxid,int32_t vout,uint8_t *pubkey33,int32_t finalseqid)
|
|
{
|
|
char *rawtxbytes=0,*signedtx=0,str[65],hexstr[999],wifstr[128],destaddr[64]; uint8_t spendscript[512],addrtype,rmd160[20]; cJSON *utxoobj,*txobj,*vins,*item,*sobj,*privkeys; int32_t height,completed,spendlen,ignore_cltverr=1,suppress_pubkeys=1; struct vin_info *V; uint32_t timestamp,locktime = (uint32_t)time(NULL) - 777,sequenceid = finalseqid * 0xffffffff; struct iguana_info *coin; bits256 txid,signedtxid; uint64_t destamount;
|
|
//printf("bobtxspend.%s redeem.[%d]\n",symbol,redeemlen);
|
|
if ( redeemlen < 0 || (coin= iguana_coinfind(symbol)) == 0 )
|
|
return(0);
|
|
if ( (utxoobj= basilisk_swapgettxout(myinfo,symbol,utxotxid,vout)) == 0 )
|
|
{
|
|
printf("basilisk_swap_bobtxspend.%s utxo already spent or doesnt exist\n",name);
|
|
return(0);
|
|
}
|
|
if ( strcmp(symbol,"KMD") != 0 )
|
|
locktime = 0;
|
|
if ( (destamount= jdouble(utxoobj,"amount")*SATOSHIDEN) == 0 && (destamount= jdouble(utxoobj,"value")*SATOSHIDEN) == 0 )
|
|
{
|
|
printf("%s %s basilisk_swap_bobtxspend.%s strange utxo.(%s)\n",symbol,bits256_str(str,utxotxid),name,jprint(utxoobj,0));
|
|
free_json(utxoobj);
|
|
return(0);
|
|
} else free_json(utxoobj);
|
|
if ( destamount > 10000 )
|
|
destamount -= 10000;
|
|
if ( strcmp(symbol,"BTC") == 0 )
|
|
{
|
|
if ( destamount > 40000 )
|
|
destamount -= 40000;
|
|
}
|
|
height = coin->longestchain;
|
|
timestamp = (uint32_t)time(NULL);
|
|
V = calloc(256,sizeof(*V));
|
|
privkeys = cJSON_CreateArray();
|
|
if ( privkey2p != 0 )
|
|
{
|
|
V[0].signers[1].privkey = *privkey2p;
|
|
bitcoin_pubkey33(myinfo->ctx,V[0].signers[1].pubkey,*privkey2p);
|
|
bitcoin_priv2wif(wifstr,*privkey2p,coin->chain->wiftype);
|
|
jaddistr(privkeys,wifstr);
|
|
V[0].N = V[0].M = 2;
|
|
} else V[0].N = V[0].M = 1;
|
|
V[0].signers[0].privkey = privkey;
|
|
bitcoin_pubkey33(myinfo->ctx,V[0].signers[0].pubkey,privkey);
|
|
bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype);
|
|
jaddistr(privkeys,wifstr);
|
|
V[0].suppress_pubkeys = suppress_pubkeys;
|
|
V[0].ignore_cltverr = ignore_cltverr;
|
|
if ( redeemlen != 0 )
|
|
memcpy(V[0].p2shscript,redeemscript,redeemlen), V[0].p2shlen = redeemlen;
|
|
txobj = bitcoin_txcreate(coin->symbol,coin->chain->isPoS,locktime,1,timestamp);
|
|
vins = cJSON_CreateArray();
|
|
item = cJSON_CreateObject();
|
|
if ( userdata != 0 && userdatalen > 0 )
|
|
{
|
|
memcpy(V[0].userdata,userdata,userdatalen);
|
|
V[0].userdatalen = userdatalen;
|
|
init_hexbytes_noT(hexstr,userdata,userdatalen);
|
|
jaddstr(item,"userdata",hexstr);
|
|
}
|
|
jaddbits256(item,"txid",utxotxid);
|
|
jaddnum(item,"vout",vout);
|
|
sobj = cJSON_CreateObject();
|
|
bitcoin_address(destaddr,coin->chain->pubtype,pubkey33,33);
|
|
bitcoin_addr2rmd160(&addrtype,rmd160,destaddr);
|
|
/*int32_t i;
|
|
for (i=0; i<33; i++)
|
|
printf("%02x",pubkey33[i]);
|
|
printf(" pubkey33 ->\n");
|
|
for (i=0; i<20; i++)
|
|
printf("%02x",rmd160[i]);
|
|
printf(" destaddr.(%s)\n",destaddr);
|
|
calc_rmd160_sha256(rmd160,pubkey33,33);
|
|
for (i=0; i<20; i++)
|
|
printf("%02x",rmd160[i]);
|
|
printf(" <- vs direct calc\n");*/
|
|
spendlen = bitcoin_standardspend(spendscript,0,rmd160);
|
|
init_hexbytes_noT(hexstr,spendscript,spendlen);
|
|
jaddstr(sobj,"hex",hexstr);
|
|
jadd(item,"scriptPubKey",sobj);
|
|
jaddnum(item,"suppress",suppress_pubkeys);
|
|
jaddnum(item,"sequence",sequenceid);
|
|
if ( redeemlen != 0 )
|
|
{
|
|
init_hexbytes_noT(hexstr,redeemscript,redeemlen);
|
|
jaddstr(item,"redeemScript",hexstr);
|
|
}
|
|
jaddi(vins,item);
|
|
jdelete(txobj,"vin");
|
|
jadd(txobj,"vin",vins);
|
|
txobj = bitcoin_txoutput(txobj,spendscript,spendlen,destamount);
|
|
if ( (rawtxbytes= bitcoin_json2hex(myinfo,coin,&txid,txobj,V)) != 0 )
|
|
{
|
|
//printf("locktime.%u sequenceid.%x rawtx.(%s) vins.(%s)\n",locktime,sequenceid,rawtxbytes,jprint(vins,0));
|
|
if ( (signedtx= iguana_signrawtx(myinfo,coin,height,&signedtxid,&completed,vins,rawtxbytes,privkeys,V)) == 0 )
|
|
printf("couldnt sign transaction\n");
|
|
else if ( completed == 0 )
|
|
printf("incomplete signing\n");
|
|
else printf("%s -> %s\n",name,bits256_str(str,signedtxid));
|
|
free(rawtxbytes);
|
|
} else printf("error making rawtx\n");
|
|
free_json(privkeys);
|
|
free_json(txobj);
|
|
free(V);
|
|
return(signedtx);
|
|
}
|
|
|
|
char *basilisk_swap_Aspend(char *name,struct supernet_info *myinfo,char *symbol,bits256 privAm,bits256 privBn,bits256 utxotxid,int32_t vout,uint8_t pubkey33[33])
|
|
{
|
|
char msigaddr[64],*signedtx = 0; int32_t spendlen,redeemlen; uint8_t tmp33[33],redeemscript[512],spendscript[128]; bits256 pubAm,pubBn; struct iguana_info *coin = iguana_coinfind(symbol);
|
|
if ( coin != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
|
|
{
|
|
pubAm = bitcoin_pubkey33(myinfo->ctx,tmp33,privAm);
|
|
pubBn = bitcoin_pubkey33(myinfo->ctx,tmp33,privBn);
|
|
//char str[65];
|
|
//printf("pubAm.(%s)\n",bits256_str(str,pubAm));
|
|
//printf("pubBn.(%s)\n",bits256_str(str,pubBn));
|
|
spendlen = basilisk_alicescript(redeemscript,&redeemlen,spendscript,0,msigaddr,coin->chain->p2shtype,pubAm,pubBn);
|
|
//char str[65]; printf("%s utxo.(%s) redeemlen.%d spendlen.%d\n",msigaddr,bits256_str(str,utxotxid),redeemlen,spendlen);
|
|
/*rev = privAm;
|
|
for (i=0; i<32; i++)
|
|
privAm.bytes[i] = rev.bytes[31 - i];
|
|
rev = privBn;
|
|
for (i=0; i<32; i++)
|
|
privBn.bytes[i] = rev.bytes[31 - i];*/
|
|
signedtx = basilisk_swap_bobtxspend(name,myinfo,symbol,privAm,&privBn,redeemscript,redeemlen,0,0,utxotxid,vout,pubkey33,1);
|
|
}
|
|
return(signedtx);
|
|
}
|
|
|
|
bits256 basilisk_swap_privbob_extract(struct supernet_info *myinfo,char *symbol,bits256 spendtxid,int32_t vini,int32_t revflag)
|
|
{
|
|
bits256 privkey; int32_t i,scriptlen,siglen; uint8_t script[1024]; // from Bob refund of Bob deposit
|
|
memset(&privkey,0,sizeof(privkey));
|
|
if ( (scriptlen= basilisk_swap_getsigscript(myinfo,symbol,script,(int32_t)sizeof(script),spendtxid,vini)) > 0 )
|
|
{
|
|
siglen = script[0];
|
|
for (i=0; i<32; i++)
|
|
{
|
|
if ( revflag != 0 )
|
|
privkey.bytes[31 - i] = script[siglen+2+i];
|
|
else privkey.bytes[i] = script[siglen+2+i];
|
|
}
|
|
char str[65]; printf("extracted privbob.(%s)\n",bits256_str(str,privkey));
|
|
}
|
|
return(privkey);
|
|
}
|
|
|
|
bits256 basilisk_swap_privBn_extract(struct supernet_info *myinfo,bits256 *bobrefundp,char *bobcoin,bits256 bobdeposit,bits256 privBn)
|
|
{
|
|
char destaddr[64];
|
|
if ( bits256_nonz(privBn) == 0 )
|
|
{
|
|
if ( bits256_nonz(bobdeposit) != 0 )
|
|
*bobrefundp = basilisk_swap_spendtxid(myinfo,bobcoin,destaddr,bobdeposit,0);
|
|
if ( bits256_nonz(*bobrefundp) != 0 )
|
|
privBn = basilisk_swap_privbob_extract(myinfo,bobcoin,*bobrefundp,0,0);
|
|
}
|
|
return(privBn);
|
|
}
|
|
|
|
bits256 basilisk_swap_spendupdate(struct supernet_info *myinfo,char *symbol,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr)
|
|
{
|
|
bits256 spendtxid,txid; char destaddr[64];
|
|
txid = txids[utxoind];
|
|
memset(&spendtxid,0,sizeof(spendtxid));
|
|
/*if ( aliceaddr != 0 )
|
|
printf("aliceaddr.(%s)\n",aliceaddr);
|
|
if ( bobaddr != 0 )
|
|
printf("bobaddr.(%s)\n",bobaddr);*/
|
|
if ( bits256_nonz(txid) != 0 )
|
|
{
|
|
//char str[65];
|
|
spendtxid = basilisk_swap_spendtxid(myinfo,symbol,destaddr,txid,vout);
|
|
if ( bits256_nonz(spendtxid) != 0 )
|
|
{
|
|
sentflags[utxoind] = 1;
|
|
if ( aliceaddr != 0 && strcmp(destaddr,aliceaddr) == 0 )
|
|
{
|
|
//printf("ALICE spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
|
|
sentflags[alicespent] = 1;
|
|
txids[alicespent] = spendtxid;
|
|
}
|
|
else if ( bobaddr != 0 && strcmp(destaddr,bobaddr) == 0 )
|
|
{
|
|
//printf("BOB spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
|
|
sentflags[bobspent] = 1;
|
|
txids[bobspent] = spendtxid;
|
|
}
|
|
else
|
|
{
|
|
//printf("OTHER dest spent.(%s) -> %s\n",bits256_str(str,txid),destaddr);
|
|
if ( aliceaddr != 0 )
|
|
{
|
|
sentflags[bobspent] = 1;
|
|
txids[bobspent] = spendtxid;
|
|
}
|
|
else if ( bobaddr != 0 )
|
|
{
|
|
sentflags[alicespent] = 1;
|
|
txids[alicespent] = spendtxid;
|
|
}
|
|
}
|
|
}
|
|
} else printf("utxoind.%d null txid\n",utxoind);
|
|
return(spendtxid);
|
|
}
|
|
|
|
#define BASILISK_ALICESPEND 0
|
|
#define BASILISK_BOBSPEND 1
|
|
#define BASILISK_BOBPAYMENT 2
|
|
#define BASILISK_ALICEPAYMENT 3
|
|
#define BASILISK_BOBDEPOSIT 4
|
|
#define BASILISK_OTHERFEE 5
|
|
#define BASILISK_MYFEE 6
|
|
#define BASILISK_BOBREFUND 7
|
|
#define BASILISK_BOBRECLAIM 8
|
|
#define BASILISK_ALICERECLAIM 9
|
|
#define BASILISK_ALICECLAIM 10
|
|
//0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0
|
|
char *txnames[] = { "alicespend", "bobspend", "bobpayment", "alicepayment", "bobdeposit", "otherfee", "myfee", "bobrefund", "bobreclaim", "alicereclaim", "aliceclaim" };
|
|
|
|
// add blocktrail presence requirement for BTC
|
|
|
|
cJSON *basilisk_remember(struct supernet_info *myinfo,int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid)
|
|
{
|
|
FILE *fp; struct iguana_info *coin; int32_t sentflags[sizeof(txnames)/sizeof(*txnames)],i,j,len,needflag,secretstart,redeemlen,addflag,origfinishedflag = 0,finishedflag = 0,iambob = -1; int64_t srcamount,destamount=0,value,values[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],pubkey33[33],redeemscript[512],userdata[512]; uint32_t plocktime,dlocktime,expiration=0,r,q,state,otherstate; char *secretstr,*srcstr,*deststr,str[65],src[64],dest[64],fname[512],*fstr,*dest33,*symbol,*Adest,*Bdest,*AAdest,*ABdest,destaddr[64],Adestaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; long fsize; cJSON *txobj,*item,*sentobj,*array; bits256 checktxid,txid,pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,zero,privkey,rev,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)];
|
|
sprintf(fname,"%s/SWAPS/%u-%u.finished",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname);
|
|
if ( (fp= fopen(fname,"rb")) != 0 )
|
|
{
|
|
origfinishedflag = finishedflag = 1;
|
|
fclose(fp);
|
|
}
|
|
memset(values,0,sizeof(values));
|
|
memset(txids,0,sizeof(txids));
|
|
memset(secretAm,0,sizeof(secretAm));
|
|
memset(secretAm256,0,sizeof(secretAm256));
|
|
memset(secretBn,0,sizeof(secretBn));
|
|
memset(secretBn256,0,sizeof(secretBn256));
|
|
memset(pubkey33,0,sizeof(pubkey33));
|
|
memset(txbytes,0,sizeof(txbytes));
|
|
memset(sentflags,0,sizeof(sentflags));
|
|
memset(myprivs,0,sizeof(myprivs));
|
|
Apaymentspent = paymentspent = depositspent = rev = zero = pubA0 = pubB0 = pubB1 = privAm = privBn = myprivs[0];
|
|
plocktime = dlocktime = 0;
|
|
src[0] = dest[0] = bobcoin[0] = alicecoin[0] = 0;
|
|
sprintf(fname,"%s/SWAPS/%u-%u",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname);
|
|
if ( (fstr= OS_filestr(&fsize,fname)) != 0 )
|
|
{
|
|
if ( (item= cJSON_Parse(fstr)) != 0 )
|
|
{
|
|
iambob = jint(item,"iambob");
|
|
if ( (secretstr= jstr(item,"secretAm")) != 0 && strlen(secretstr) == 40 )
|
|
decode_hex(secretAm,20,secretstr);
|
|
if ( (secretstr= jstr(item,"secretAm256")) != 0 && strlen(secretstr) == 64 )
|
|
decode_hex(secretAm256,32,secretstr);
|
|
if ( (secretstr= jstr(item,"secretBn")) != 0 && strlen(secretstr) == 40 )
|
|
decode_hex(secretBn,20,secretstr);
|
|
if ( (secretstr= jstr(item,"secretBn256")) != 0 && strlen(secretstr) == 64 )
|
|
decode_hex(secretBn256,32,secretstr);
|
|
if ( (srcstr= jstr(item,"src")) != 0 )
|
|
safecopy(src,srcstr,sizeof(src));
|
|
if ( (deststr= jstr(item,"dest")) != 0 )
|
|
safecopy(dest,deststr,sizeof(dest));
|
|
if ( (dest33= jstr(item,"dest33")) != 0 && strlen(dest33) == 66 )
|
|
{
|
|
decode_hex(pubkey33,33,dest33);
|
|
//for (i=0; i<33; i++)
|
|
// printf("%02x",pubkey33[i]);
|
|
//printf(" <- %s dest33\n",dest33);
|
|
}
|
|
plocktime = juint(item,"plocktime");
|
|
dlocktime = juint(item,"dlocktime");
|
|
r = juint(item,"requestid");
|
|
q = juint(item,"quoteid");
|
|
pubA0 = jbits256(item,"pubA0");
|
|
pubB0 = jbits256(item,"pubB0");
|
|
pubB1 = jbits256(item,"pubB1");
|
|
privkey = jbits256(item,"myprivs0");
|
|
if ( bits256_nonz(privkey) != 0 )
|
|
myprivs[0] = privkey;
|
|
privkey = jbits256(item,"myprivs1");
|
|
if ( bits256_nonz(privkey) != 0 )
|
|
myprivs[1] = privkey;
|
|
privkey = jbits256(item,"privAm");
|
|
if ( bits256_nonz(privkey) != 0 )
|
|
{
|
|
privAm = privkey;
|
|
//printf("set privAm <- %s\n",bits256_str(str,privAm));
|
|
}
|
|
privkey = jbits256(item,"privBn");
|
|
if ( bits256_nonz(privkey) != 0 )
|
|
{
|
|
privBn = privkey;
|
|
//printf("set privBn <- %s\n",bits256_str(str,privBn));
|
|
}
|
|
expiration = juint(item,"expiration");
|
|
state = jint(item,"state");
|
|
otherstate = jint(item,"otherstate");
|
|
srcamount = SATOSHIDEN * jdouble(item,"srcamount");
|
|
destamount = SATOSHIDEN * jdouble(item,"destamount");
|
|
txids[BASILISK_BOBDEPOSIT] = jbits256(item,"Bdeposit");
|
|
txids[BASILISK_BOBREFUND] = jbits256(item,"Brefund");
|
|
txids[BASILISK_ALICECLAIM] = jbits256(item,"Aclaim");
|
|
txids[BASILISK_BOBPAYMENT] = jbits256(item,"Bpayment");
|
|
txids[BASILISK_ALICESPEND] = jbits256(item,"Aspend");
|
|
txids[BASILISK_BOBRECLAIM] = jbits256(item,"Breclaim");
|
|
txids[BASILISK_ALICEPAYMENT] = jbits256(item,"Apayment");
|
|
txids[BASILISK_BOBSPEND] = jbits256(item,"Bspend");
|
|
txids[BASILISK_ALICERECLAIM] = jbits256(item,"Areclaim");
|
|
txids[BASILISK_MYFEE] = jbits256(item,"myfee");
|
|
txids[BASILISK_OTHERFEE] = jbits256(item,"otherfee");
|
|
free_json(item);
|
|
}
|
|
free(fstr);
|
|
}
|
|
if ( iambob < 0 )
|
|
return(0);
|
|
item = cJSON_CreateObject();
|
|
array = cJSON_CreateArray();
|
|
//printf("R.%u Q.%u\n",requestid,quoteid);
|
|
for (i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
|
|
{
|
|
needflag = addflag = 0;
|
|
sprintf(fname,"%s/SWAPS/%u-%u.%s",GLOBAL_DBDIR,requestid,quoteid,txnames[i]), OS_compatible_path(fname);
|
|
if ( (fstr= OS_filestr(&fsize,fname)) != 0 )
|
|
{
|
|
//printf("%s -> (%s)\n",fname,fstr);
|
|
if ( (txobj= cJSON_Parse(fstr)) != 0 )
|
|
{
|
|
//printf("TXOBJ.(%s)\n",jprint(txobj,0));
|
|
iambob = jint(txobj,"iambob");
|
|
txid = jbits256(txobj,"txid");
|
|
if ( bits256_nonz(txid) == 0 )
|
|
continue;
|
|
txids[i] = txid;
|
|
if ( jobj(txobj,"tx") != 0 )
|
|
{
|
|
txbytes[i] = clonestr(jstr(txobj,"tx"));
|
|
//printf("[%s] TX.(%s)\n",txnames[i],txbytes[i]);
|
|
}
|
|
if ( (symbol= jstr(txobj,"coin")) != 0 )
|
|
{
|
|
if ( i == BASILISK_ALICESPEND || i == BASILISK_BOBPAYMENT || i == BASILISK_BOBDEPOSIT || i == BASILISK_BOBREFUND || i == BASILISK_BOBRECLAIM || i == BASILISK_ALICECLAIM )
|
|
safecopy(bobcoin,symbol,sizeof(bobcoin));
|
|
else if ( i == BASILISK_BOBSPEND || i == BASILISK_ALICEPAYMENT || i == BASILISK_ALICERECLAIM )
|
|
safecopy(alicecoin,symbol,sizeof(alicecoin));
|
|
if ( (sentobj= basilisk_swapgettx(myinfo,symbol,txid)) == 0 )
|
|
{
|
|
//printf("%s %s ready to broadcast\n",symbol,bits256_str(str2,txid));
|
|
}
|
|
else
|
|
{
|
|
checktxid = jbits256(sentobj,"txid");
|
|
if ( bits256_nonz(checktxid) == 0 )
|
|
checktxid = jbits256(sentobj,"hash");
|
|
if ( bits256_cmp(checktxid,txid) == 0 )
|
|
{
|
|
//printf(">>>>>> %s txid %s\n",jprint(sentobj,0),bits256_str(str,txid));
|
|
sentflags[i] = 1;
|
|
}
|
|
free_json(sentobj);
|
|
}
|
|
values[i] = value = jdouble(txobj,"amount") * SATOSHIDEN;
|
|
//printf("%s %.8f\n",txnames[i],dstr(value));
|
|
//if ( sentflags[i] == 0 || addflag != 0 )
|
|
// jaddi(array,txobj);
|
|
}
|
|
} //else printf("no symbol\n");
|
|
free(fstr);
|
|
}
|
|
}
|
|
//printf("iambob.%d src.%s dest.%s bob.%s alice.%s pubA0.(%s)\n",iambob,src,dest,bobcoin,alicecoin,bits256_str(str,pubA0));
|
|
//strcpy(bobcoin,"KMD");
|
|
//strcpy(alicecoin,"BTC");
|
|
Adestaddr[0] = destaddr[0] = 0;
|
|
Adest = Bdest = AAdest = ABdest = 0;
|
|
if ( iambob == 0 )
|
|
{
|
|
if ( (coin= iguana_coinfind(alicecoin)) != 0 )
|
|
{
|
|
bitcoin_address(Adestaddr,coin->chain->pubtype,pubkey33,33);
|
|
AAdest = Adestaddr;
|
|
}
|
|
if ( (coin= iguana_coinfind(bobcoin)) != 0 )
|
|
{
|
|
bitcoin_address(destaddr,coin->chain->pubtype,pubkey33,33);
|
|
Adest = destaddr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( (coin= iguana_coinfind(bobcoin)) != 0 )
|
|
{
|
|
bitcoin_address(destaddr,coin->chain->pubtype,pubkey33,33);
|
|
Bdest = destaddr;
|
|
}
|
|
if ( (coin= iguana_coinfind(alicecoin)) != 0 )
|
|
{
|
|
bitcoin_address(Adestaddr,coin->chain->pubtype,pubkey33,33);
|
|
ABdest = Adestaddr;
|
|
}
|
|
}
|
|
//printf("privAm.(%s) %p/%p\n",bits256_str(str,privAm),Adest,AAdest);
|
|
//printf("privBn.(%s) %p/%p\n",bits256_str(str,privBn),Bdest,ABdest);
|
|
if ( bobcoin[0] != 0 && alicecoin[0] != 0 )
|
|
{
|
|
if ( sentflags[BASILISK_ALICEPAYMENT] == 0 && bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 )
|
|
{
|
|
printf("txbytes.%p Apayment.%s\n",txbytes[BASILISK_ALICEPAYMENT],bits256_str(str,txids[BASILISK_ALICEPAYMENT]));
|
|
if ( txbytes[BASILISK_ALICEPAYMENT] != 0 )
|
|
sentflags[BASILISK_ALICEPAYMENT] = 1;
|
|
else if ( (sentobj= basilisk_swapgettx(myinfo,alicecoin,txids[BASILISK_ALICEPAYMENT])) != 0 )
|
|
{
|
|
sentflags[BASILISK_ALICEPAYMENT] = 1;
|
|
free_json(sentobj);
|
|
}
|
|
}
|
|
paymentspent = basilisk_swap_spendupdate(myinfo,bobcoin,sentflags,txids,BASILISK_BOBPAYMENT,BASILISK_ALICESPEND,BASILISK_BOBRECLAIM,0,Adest,Bdest);
|
|
Apaymentspent = basilisk_swap_spendupdate(myinfo,alicecoin,sentflags,txids,BASILISK_ALICEPAYMENT,BASILISK_ALICERECLAIM,BASILISK_BOBSPEND,0,AAdest,ABdest);
|
|
depositspent = basilisk_swap_spendupdate(myinfo,bobcoin,sentflags,txids,BASILISK_BOBDEPOSIT,BASILISK_ALICECLAIM,BASILISK_BOBREFUND,0,Adest,Bdest);
|
|
if ( bits256_nonz(paymentspent) != 0 && bits256_nonz(Apaymentspent) != 0 && bits256_nonz(depositspent) != 0 )
|
|
{
|
|
finishedflag = 1;
|
|
}
|
|
if ( finishedflag == 0 && iambob == 0 )
|
|
{
|
|
if ( sentflags[BASILISK_ALICESPEND] == 0 )
|
|
{
|
|
if ( sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(paymentspent) == 0 )
|
|
{
|
|
//if ( txbytes[BASILISK_ALICESPEND] == 0 )
|
|
{
|
|
if ( bits256_nonz(txids[BASILISK_BOBPAYMENT]) != 0 )
|
|
{
|
|
// alicespend
|
|
for (j=0; j<32; j++)
|
|
rev.bytes[j] = privAm.bytes[31 - j];
|
|
revcalc_rmd160_sha256(secretAm,rev);//privAm);
|
|
vcalc_sha256(0,secretAm256,rev.bytes,sizeof(rev));
|
|
redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,rev,privBn,secretAm,secretAm256,secretBn,secretBn256);
|
|
len = basilisk_swapuserdata(userdata,rev,0,myprivs[0],redeemscript,redeemlen);
|
|
if ( (txbytes[BASILISK_ALICESPEND]= basilisk_swap_bobtxspend("alicespend",myinfo,bobcoin,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,pubkey33,1)) != 0 )
|
|
printf("alicespend.(%s)\n",txbytes[BASILISK_ALICESPEND]);
|
|
}
|
|
}
|
|
if ( txbytes[BASILISK_ALICESPEND] != 0 )
|
|
{
|
|
txids[BASILISK_ALICESPEND] = basilisk_swap_sendrawtransaction(myinfo,"alicespend",bobcoin,txbytes[BASILISK_ALICESPEND]);
|
|
if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 ) // tested
|
|
{
|
|
sentflags[BASILISK_ALICESPEND] = 1;
|
|
paymentspent = txids[BASILISK_ALICESPEND];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( sentflags[BASILISK_ALICECLAIM] == 0 && sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(depositspent) == 0 )
|
|
{
|
|
if ( time(NULL) > expiration )
|
|
{
|
|
//if ( txbytes[BASILISK_ALICECLAIM] == 0 )
|
|
{
|
|
redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256);
|
|
if ( redeemlen > 0 )
|
|
{
|
|
len = basilisk_swapuserdata(userdata,zero,1,myprivs[0],redeemscript,redeemlen);
|
|
if ( (txbytes[BASILISK_ALICECLAIM]= basilisk_swap_bobtxspend("aliceclaim",myinfo,bobcoin,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,pubkey33,0)) != 0 )
|
|
printf("privBn.(%s) aliceclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICECLAIM]);
|
|
}
|
|
}
|
|
if ( txbytes[BASILISK_ALICECLAIM] != 0 )
|
|
{
|
|
txids[BASILISK_ALICECLAIM] = basilisk_swap_sendrawtransaction(myinfo,"aliceclaim",bobcoin,txbytes[BASILISK_ALICECLAIM]);
|
|
if ( bits256_nonz(txids[BASILISK_ALICECLAIM]) != 0 ) // tested
|
|
{
|
|
sentflags[BASILISK_ALICECLAIM] = 1;
|
|
depositspent = txids[BASILISK_ALICECLAIM];
|
|
}
|
|
}
|
|
} else printf("now %u before expiration %u\n",(uint32_t)time(NULL),expiration);
|
|
}
|
|
if ( sentflags[BASILISK_ALICEPAYMENT] != 0 && bits256_nonz(Apaymentspent) == 0 && sentflags[BASILISK_ALICECLAIM] == 0 )
|
|
{
|
|
//if ( txbytes[BASILISK_ALICERECLAIM] == 0 )
|
|
{
|
|
privBn = basilisk_swap_privBn_extract(myinfo,&txids[BASILISK_BOBREFUND],bobcoin,txids[BASILISK_BOBDEPOSIT],privBn);
|
|
if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) != 0 && bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
|
|
{
|
|
if ( (txbytes[BASILISK_ALICERECLAIM]= basilisk_swap_Aspend("alicereclaim",myinfo,alicecoin,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33)) != 0 )
|
|
printf("privBn.(%s) alicereclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_ALICERECLAIM]);
|
|
}
|
|
}
|
|
if ( txbytes[BASILISK_ALICERECLAIM] != 0 )
|
|
{
|
|
txids[BASILISK_ALICERECLAIM] = basilisk_swap_sendrawtransaction(myinfo,"alicereclaim",alicecoin,txbytes[BASILISK_ALICERECLAIM]);
|
|
if ( bits256_nonz(txids[BASILISK_ALICERECLAIM]) != 0 ) // tested
|
|
{
|
|
sentflags[BASILISK_ALICERECLAIM] = 1;
|
|
Apaymentspent = txids[BASILISK_ALICERECLAIM];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ( finishedflag == 0 && iambob == 1 )
|
|
{
|
|
if ( sentflags[BASILISK_BOBSPEND] == 0 && bits256_nonz(Apaymentspent) == 0 )
|
|
{
|
|
if ( bits256_nonz(txids[BASILISK_ALICESPEND]) != 0 || bits256_nonz(privAm) != 0 )
|
|
{
|
|
//if ( txbytes[BASILISK_BOBSPEND] == 0 )
|
|
{
|
|
if ( bits256_nonz(privAm) == 0 )
|
|
{
|
|
privAm = basilisk_swap_privbob_extract(myinfo,bobcoin,txids[BASILISK_ALICESPEND],0,1);
|
|
}
|
|
if ( bits256_nonz(privAm) != 0 && bits256_nonz(privBn) != 0 )
|
|
{
|
|
if ( (txbytes[BASILISK_BOBSPEND]= basilisk_swap_Aspend("bobspend",myinfo,alicecoin,privAm,privBn,txids[BASILISK_ALICEPAYMENT],0,pubkey33)) != 0 )
|
|
printf("bobspend.(%s)\n",txbytes[BASILISK_BOBSPEND]);
|
|
}
|
|
}
|
|
if ( txbytes[BASILISK_BOBSPEND] != 0 )
|
|
{
|
|
txids[BASILISK_BOBSPEND] = basilisk_swap_sendrawtransaction(myinfo,"bobspend",alicecoin,txbytes[BASILISK_BOBSPEND]);
|
|
if ( bits256_nonz(txids[BASILISK_BOBSPEND]) != 0 ) // tested
|
|
{
|
|
sentflags[BASILISK_BOBSPEND] = 1;
|
|
Apaymentspent = txids[BASILISK_BOBSPEND];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( sentflags[BASILISK_BOBRECLAIM] == 0 && sentflags[BASILISK_BOBPAYMENT] != 0 && bits256_nonz(txids[BASILISK_BOBPAYMENT]) != 0 && time(NULL) > expiration && bits256_nonz(paymentspent) == 0 )
|
|
{
|
|
//if ( txbytes[BASILISK_BOBRECLAIM] == 0 )
|
|
{
|
|
// bobreclaim
|
|
redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,plocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256);
|
|
if ( redeemlen > 0 )
|
|
{
|
|
len = basilisk_swapuserdata(userdata,zero,1,myprivs[1],redeemscript,redeemlen);
|
|
if ( (txbytes[BASILISK_BOBRECLAIM]= basilisk_swap_bobtxspend("bobrefund",myinfo,bobcoin,myprivs[1],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBPAYMENT],0,pubkey33,0)) != 0 )
|
|
printf("privBn.(%s) bobreclaim.(%s)\n",bits256_str(str,privBn),txbytes[BASILISK_BOBRECLAIM]);
|
|
}
|
|
}
|
|
if ( txbytes[BASILISK_BOBRECLAIM] != 0 )
|
|
{
|
|
txids[BASILISK_BOBRECLAIM] = basilisk_swap_sendrawtransaction(myinfo,"bobreclaim",bobcoin,txbytes[BASILISK_BOBRECLAIM]);
|
|
if ( bits256_nonz(txids[BASILISK_BOBRECLAIM]) != 0 ) // tested
|
|
{
|
|
sentflags[BASILISK_BOBRECLAIM] = 1;
|
|
paymentspent = txids[BASILISK_BOBRECLAIM];
|
|
}
|
|
}
|
|
}
|
|
if ( sentflags[BASILISK_BOBREFUND] == 0 && sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(depositspent) == 0 )
|
|
{
|
|
if ( bits256_nonz(paymentspent) != 0 )
|
|
{
|
|
//if ( txbytes[BASILISK_BOBREFUND] == 0 )
|
|
{
|
|
revcalc_rmd160_sha256(secretBn,privBn);
|
|
vcalc_sha256(0,secretBn256,privBn.bytes,sizeof(privBn));
|
|
redeemlen = basilisk_swap_bobredeemscript(1,&secretstart,redeemscript,dlocktime,pubA0,pubB0,pubB1,privAm,privBn,secretAm,secretAm256,secretBn,secretBn256);
|
|
len = basilisk_swapuserdata(userdata,privBn,0,myprivs[0],redeemscript,redeemlen);
|
|
if ( (txbytes[BASILISK_BOBREFUND]= basilisk_swap_bobtxspend("bobrefund",myinfo,bobcoin,myprivs[0],0,redeemscript,redeemlen,userdata,len,txids[BASILISK_BOBDEPOSIT],0,pubkey33,1)) != 0 )
|
|
printf("pubB1.(%s) bobrefund.(%s)\n",bits256_str(str,pubB1),txbytes[BASILISK_BOBREFUND]);
|
|
}
|
|
if ( txbytes[BASILISK_BOBREFUND] != 0 )
|
|
{
|
|
txids[BASILISK_BOBREFUND] = basilisk_swap_sendrawtransaction(myinfo,"bobrefund",bobcoin,txbytes[BASILISK_BOBREFUND]);
|
|
if ( bits256_nonz(txids[BASILISK_BOBREFUND]) != 0 ) // tested
|
|
{
|
|
sentflags[BASILISK_BOBREFUND] = 1;
|
|
depositspent = txids[BASILISK_BOBREFUND];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( sentflags[BASILISK_ALICESPEND] != 0 || sentflags[BASILISK_BOBRECLAIM] != 0 )
|
|
sentflags[BASILISK_BOBPAYMENT] = 1;
|
|
if ( sentflags[BASILISK_ALICERECLAIM] != 0 || sentflags[BASILISK_BOBSPEND] != 0 )
|
|
sentflags[BASILISK_ALICEPAYMENT] = 1;
|
|
if ( sentflags[BASILISK_ALICECLAIM] != 0 || sentflags[BASILISK_BOBREFUND] != 0 )
|
|
sentflags[BASILISK_BOBDEPOSIT] = 1;
|
|
printf("iambob.%d Apaymentspent.(%s) alice.%d bob.%d %s %.8f\n",iambob,bits256_str(str,Apaymentspent),sentflags[BASILISK_ALICERECLAIM],sentflags[BASILISK_BOBSPEND],alicecoin,dstr(values[BASILISK_ALICEPAYMENT]));
|
|
printf("paymentspent.(%s) alice.%d bob.%d %s %.8f\n",bits256_str(str,paymentspent),sentflags[BASILISK_ALICESPEND],sentflags[BASILISK_BOBRECLAIM],bobcoin,dstr(values[BASILISK_BOBPAYMENT]));
|
|
printf("depositspent.(%s) alice.%d bob.%d %s %.8f\n",bits256_str(str,depositspent),sentflags[BASILISK_ALICECLAIM],sentflags[BASILISK_BOBREFUND],bobcoin,dstr(values[BASILISK_BOBDEPOSIT]));
|
|
values[BASILISK_OTHERFEE] = 0;
|
|
if ( iambob == 0 )
|
|
{
|
|
if ( strcmp(alicecoin,"BTC") == 0 )
|
|
{
|
|
BTCtotals[BASILISK_ALICEPAYMENT] -= values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICEPAYMENT];
|
|
BTCtotals[BASILISK_ALICERECLAIM] += values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICERECLAIM];
|
|
BTCtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE];
|
|
}
|
|
else if ( strcmp(alicecoin,"KMD") == 0 )
|
|
{
|
|
KMDtotals[BASILISK_ALICEPAYMENT] -= values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICEPAYMENT];
|
|
KMDtotals[BASILISK_ALICERECLAIM] += values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_ALICERECLAIM];
|
|
KMDtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE];
|
|
}
|
|
if ( strcmp(bobcoin,"KMD") == 0 )
|
|
{
|
|
KMDtotals[BASILISK_ALICESPEND] += values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_ALICESPEND];
|
|
KMDtotals[BASILISK_ALICECLAIM] += values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_ALICECLAIM];
|
|
}
|
|
else if ( strcmp(bobcoin,"BTC") == 0 )
|
|
{
|
|
BTCtotals[BASILISK_ALICESPEND] += values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_ALICESPEND];
|
|
BTCtotals[BASILISK_ALICECLAIM] += values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_ALICECLAIM];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( strcmp(bobcoin,"BTC") == 0 )
|
|
{
|
|
BTCtotals[BASILISK_BOBPAYMENT] -= values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_BOBPAYMENT];
|
|
BTCtotals[BASILISK_BOBDEPOSIT] -= values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_BOBDEPOSIT];
|
|
BTCtotals[BASILISK_BOBREFUND] += values[BASILISK_BOBREFUND] * sentflags[BASILISK_BOBREFUND];
|
|
BTCtotals[BASILISK_BOBRECLAIM] += values[BASILISK_BOBRECLAIM] * sentflags[BASILISK_BOBRECLAIM];
|
|
BTCtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE];
|
|
}
|
|
else if ( strcmp(bobcoin,"KMD") == 0 )
|
|
{
|
|
KMDtotals[BASILISK_BOBPAYMENT] -= values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_BOBPAYMENT];
|
|
KMDtotals[BASILISK_BOBDEPOSIT] -= values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_BOBDEPOSIT];
|
|
KMDtotals[BASILISK_BOBREFUND] += values[BASILISK_BOBDEPOSIT] * sentflags[BASILISK_BOBREFUND];
|
|
KMDtotals[BASILISK_BOBRECLAIM] += values[BASILISK_BOBPAYMENT] * sentflags[BASILISK_BOBRECLAIM];
|
|
KMDtotals[BASILISK_MYFEE] -= values[BASILISK_MYFEE] * sentflags[BASILISK_MYFEE];
|
|
}
|
|
if ( strcmp(alicecoin,"KMD") == 0 )
|
|
{
|
|
KMDtotals[BASILISK_BOBSPEND] += values[BASILISK_BOBSPEND] * sentflags[BASILISK_BOBSPEND];
|
|
}
|
|
else if ( strcmp(alicecoin,"BTC") == 0 )
|
|
{
|
|
BTCtotals[BASILISK_BOBSPEND] += values[BASILISK_ALICEPAYMENT] * sentflags[BASILISK_BOBSPEND];
|
|
}
|
|
}
|
|
if ( bits256_nonz(paymentspent) != 0 && bits256_nonz(Apaymentspent) != 0 && bits256_nonz(depositspent) != 0 )
|
|
{
|
|
finishedflag = 1;
|
|
}
|
|
jaddnum(item,"requestid",requestid);
|
|
jaddnum(item,"quoteid",quoteid);
|
|
jadd(item,"txs",array);
|
|
array = cJSON_CreateArray();
|
|
for (i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
|
|
{
|
|
if ( sentflags[i] != 0 )
|
|
jaddistr(array,txnames[i]);
|
|
if ( txbytes[i] != 0 )
|
|
free(txbytes[i]);
|
|
}
|
|
jadd(item,"sentflags",array);
|
|
jaddstr(item,"result","success");
|
|
if ( finishedflag != 0 )
|
|
jaddstr(item,"status","finished");
|
|
else jaddstr(item,"status","pending");
|
|
bits256_str(str,paymentspent), jaddbits256(item,"paymentspent",paymentspent);
|
|
bits256_str(str,Apaymentspent), jaddbits256(item,"Apaymentspent",Apaymentspent);
|
|
bits256_str(str,depositspent), jaddbits256(item,"depositspent",depositspent);
|
|
if ( origfinishedflag == 0 && finishedflag != 0 )
|
|
{
|
|
//printf("SWAP %u-%u finished!\n",requestid,quoteid);
|
|
sprintf(fname,"%s/SWAPS/%u-%u.finished",GLOBAL_DBDIR,requestid,quoteid), OS_compatible_path(fname);
|
|
if ( (fp= fopen(fname,"wb")) != 0 )
|
|
{
|
|
char *itemstr;
|
|
itemstr = jprint(item,0);
|
|
fprintf(fp,"%s\n",itemstr);
|
|
free(itemstr);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
return(item);
|
|
}
|
|
|
|
char *basilisk_swaplist(struct supernet_info *myinfo)
|
|
{
|
|
char fname[512],*status; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t quoteid,requestid; int64_t KMDtotals[16],BTCtotals[16],Btotal,Ktotal; int32_t i;
|
|
memset(KMDtotals,0,sizeof(KMDtotals));
|
|
memset(BTCtotals,0,sizeof(BTCtotals));
|
|
//,statebits; int32_t optionduration; struct basilisk_request R; bits256 privkey;
|
|
retjson = cJSON_CreateObject();
|
|
array = cJSON_CreateArray();
|
|
sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname);
|
|
if ( (fp= fopen(fname,"rb")) != 0 )
|
|
{
|
|
struct basilisk_swap *swap; int32_t flag = 0;
|
|
while ( fread(&requestid,1,sizeof(requestid),fp) == sizeof(requestid) && fread("eid,1,sizeof(quoteid),fp) == sizeof(quoteid) )
|
|
{
|
|
flag = 0;
|
|
for (i=0; i<myinfo->numswaps; i++)
|
|
if ( (swap= myinfo->swaps[i]) != 0 && swap->I.req.requestid == requestid && swap->I.req.quoteid == quoteid )
|
|
{
|
|
jaddi(array,basilisk_swapjson(myinfo,swap));
|
|
flag = 1;
|
|
break;
|
|
}
|
|
if ( flag == 0 )
|
|
{
|
|
if ( (item= basilisk_remember(myinfo,KMDtotals,BTCtotals,requestid,quoteid)) != 0 )
|
|
{
|
|
jaddi(array,item);
|
|
if ( (status= jstr(item,"status")) != 0 && strcmp(status,"pending") == 0 )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
fclose(fp);
|
|
}
|
|
jaddstr(retjson,"result","success");
|
|
jadd(retjson,"swaps",array);
|
|
if ( cJSON_GetArraySize(array) > 0 )
|
|
{
|
|
totalsobj = cJSON_CreateObject();
|
|
for (Btotal=i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
|
|
if ( BTCtotals[i] != 0 )
|
|
jaddnum(totalsobj,txnames[i],dstr(BTCtotals[i])), Btotal += BTCtotals[i];
|
|
jadd(retjson,"BTCtotals",totalsobj);
|
|
totalsobj = cJSON_CreateObject();
|
|
for (Ktotal=i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
|
|
if ( KMDtotals[i] != 0 )
|
|
jaddnum(totalsobj,txnames[i],dstr(KMDtotals[i])), Ktotal += KMDtotals[i];
|
|
jadd(retjson,"KMDtotals",totalsobj);
|
|
jaddnum(retjson,"KMDtotal",dstr(Ktotal));
|
|
jaddnum(retjson,"BTCtotal",dstr(Btotal));
|
|
if ( Ktotal > 0 && Btotal < 0 )
|
|
jaddnum(retjson,"avebuy",(double)-Btotal/Ktotal);
|
|
else if ( Ktotal < 0 && Btotal > 0 )
|
|
jaddnum(retjson,"avesell",(double)-Btotal/Ktotal);
|
|
}
|
|
array = cJSON_CreateArray();
|
|
for (i=0; i<sizeof(myinfo->linfos)/sizeof(*myinfo->linfos); i++)
|
|
{
|
|
if ( myinfo->linfos[i].base[0] != 0 && myinfo->linfos[i].rel[0] != 0 )
|
|
jaddi(array,linfo_json(&myinfo->linfos[i]));
|
|
}
|
|
jadd(retjson,"quotes",array);
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
|
|
|