Browse Source

test

release/v0.1
jl777 9 years ago
parent
commit
d8aa7a42ad
  1. 11
      crypto777/iguana_utils.c
  2. 59
      iguana/SuperNET.c
  3. 17
      iguana/SuperNET.h
  4. 12
      iguana/SuperNET_category.c
  5. 8
      iguana/SuperNET_hexmsg.c
  6. 2
      iguana/SuperNET_keys.c
  7. 162
      iguana/exchanges/bitcoin.c
  8. 6
      iguana/exchanges/bitcoin.h
  9. 19
      iguana/exchanges777.h
  10. 2
      iguana/iguana777.c
  11. 12
      iguana/iguana777.h
  12. 4
      iguana/iguana_blocks.c
  13. 160
      iguana/iguana_exchanges.c
  14. 232
      iguana/iguana_instantdex.c
  15. 10
      iguana/iguana_recv.c
  16. 111
      iguana/iguana_tx.c
  17. 60
      iguana/main.c
  18. 12
      iguana/pangea_api.c
  19. 12
      iguana/pnacl/Release/iguana.nmf
  20. BIN
      iguana/pnacl/Release/iguana.pexe
  21. 827
      iguana/swaps/iguana_BTCswap.c
  22. 6
      includes/iguana_apideclares.h

11
crypto777/iguana_utils.c

@ -133,9 +133,9 @@ int32_t bitweight(uint64_t x)
return(wt);
}
void calc_OP_HASH160(char hexstr[41],uint8_t hash160[20],char *pubkey)
void calc_OP_HASH160(char hexstr[41],uint8_t rmd160[20],char *pubkey)
{
uint8_t sha256[32],buf[4096]; int32_t len;
uint8_t buf[4096]; int32_t len;
len = (int32_t)strlen(pubkey)/2;
if ( len > sizeof(buf) )
{
@ -143,17 +143,16 @@ void calc_OP_HASH160(char hexstr[41],uint8_t hash160[20],char *pubkey)
return;
}
decode_hex(buf,len,pubkey);
vcalc_sha256(0,sha256,buf,len);
calc_rmd160(0,hash160,sha256,sizeof(sha256));
calc_rmd160_sha256(rmd160,buf,len);
if ( 0 )
{
int i;
for (i=0; i<20; i++)
printf("%02x",hash160[i]);
printf("%02x",rmd160[i]);
printf("<- (%s)\n",pubkey);
}
if ( hexstr != 0 )
init_hexbytes_noT(hexstr,hash160,20);
init_hexbytes_noT(hexstr,rmd160,20);
}
double _dxblend(double *destp,double val,double decay)

59
iguana/SuperNET.c

@ -564,9 +564,10 @@ char *SuperNET_DHTsend(struct supernet_info *myinfo,uint64_t destipbits,bits256
jaddbits256(json,"subhash",subhash);
if ( SuperNET_hexmsgfind(myinfo,categoryhash,subhash,hexmsg,1) >= 0 )
{
//char str[65]; printf("duplicate hex.(%s) for %s\n",hexmsg,bits256_str(str,categoryhash));
char str[65]; printf("duplicate hex.(%s) for %s\n",hexmsg,bits256_str(str,categoryhash));
return(clonestr("{\"error\":\"duplicate packet rejected\"}"));
}
else SuperNET_hexmsgadd(myinfo,categoryhash,subhash,hexmsg,tai_now(),0);
jsonstr = jprint(json,1);
if ( broadcastflag != 0 || destipbits == 0 )
{
@ -919,6 +920,18 @@ cJSON *SuperNET_rosettajson(bits256 privkey,int32_t showprivs)
#include "../includes/iguana_apidefs.h"
STRING_ARG(SuperNET,addr2rmd160,address)
{
uint8_t addrtype,rmd160[20]; char rmdstr[41]; cJSON *retjson;
bitcoin_addr2rmd160(&addrtype,rmd160,address);
init_hexbytes_noT(rmdstr,rmd160,sizeof(rmd160));
retjson = cJSON_CreateObject();
jaddstr(retjson,"result",rmdstr);
jaddnum(retjson,"addrtype",addrtype);
jaddstr(retjson,"address",address);
return(jprint(retjson,1));
}
HASH_AND_INT(SuperNET,priv2pub,privkey,addrtype)
{
cJSON *retjson; bits256 pub; uint8_t pubkey[33]; char coinaddr[64];
@ -1221,7 +1234,7 @@ THREE_STRINGS(SuperNET,announce,category,subcategory,message)
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
categoryhash = calc_categoryhashes(&subhash,category,subcategory);
return(SuperNET_categorymulticast(myinfo,0,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext")));
return(SuperNET_categorymulticast(myinfo,0,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext"),json,remoteaddr));
}
THREE_STRINGS(SuperNET,survey,category,subcategory,message)
@ -1230,7 +1243,7 @@ THREE_STRINGS(SuperNET,survey,category,subcategory,message)
if ( remoteaddr != 0 )
return(clonestr("{\"error\":\"no remote\"}"));
categoryhash = calc_categoryhashes(&subhash,category,subcategory);
return(SuperNET_categorymulticast(myinfo,1,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext")));
return(SuperNET_categorymulticast(myinfo,1,categoryhash,subhash,message,juint(json,"maxdelay"),juint(json,"broadcast"),juint(json,"plaintext"),json,remoteaddr));
}
STRING_ARG(SuperNET,wif2priv,wif)
@ -1299,9 +1312,49 @@ ZERO_ARGS(SuperNET,activehandle)
retjson = SuperNET_rosettajson(myinfo->persistent_priv,0);
jaddstr(retjson,"result","success");
jaddstr(retjson,"handle",myinfo->handle);
SuperNET_MYINFOadd(myinfo);
return(jprint(retjson,1));
}
struct supernet_info *SuperNET_accountfind(cJSON *json)
{
int32_t num; char *decryptstr; struct supernet_info M,*myinfo; struct iguana_info *coin = 0;
char *password,*permanentfile,*passphrase,*remoteaddr,*perspriv;
myinfo = 0;
if ( (password= jstr(json,"password")) == 0 )
password = "";
if ( (permanentfile= jstr(json,"permanentfile")) == 0 )
permanentfile = "";
if ( (passphrase= jstr(json,"passphrase")) == 0 )
passphrase = "";
remoteaddr = jstr(json,"remoteaddr");
if ( (passphrase == 0 || passphrase[0] == 0) && (decryptstr= SuperNET_decryptjson(IGUANA_CALLARGS,password,permanentfile)) != 0 )
{
if ( (json= cJSON_Parse(decryptstr)) != 0 )
{
memset(&M,0,sizeof(M));
if ( (perspriv= jstr(json,"persistent_priv")) != 0 && strlen(perspriv) == sizeof(bits256)*2 )
{
M.persistent_priv = bits256_conv(perspriv);
SuperNET_setkeys(&M,0,0,0);
myinfo = SuperNET_MYINFOfind(&num,M.myaddr.persistent);
printf("found account.(%s) %s %llu\n",myinfo!=0?myinfo->handle:"",M.myaddr.NXTADDR,(long long)M.myaddr.nxt64bits);
return(myinfo);
}
else if ( (passphrase= jstr(json,"result")) != 0 || (passphrase= jstr(json,"passphrase")) != 0 )
{
SuperNET_setkeys(&M,passphrase,(int32_t)strlen(passphrase),1);
myinfo = SuperNET_MYINFOfind(&num,M.myaddr.persistent);
printf("found account.(%s) %s %llu\n",myinfo!=0?myinfo->handle:"",M.myaddr.NXTADDR,(long long)M.myaddr.nxt64bits);
return(myinfo);
} else printf("no passphrase in (%s)\n",jprint(json,0));
free_json(json);
} else printf("cant parse.(%s)\n",decryptstr);
free(decryptstr);
}
return(SuperNET_MYINFO(0));
}
FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase)
{
char *str,*decryptstr = 0; cJSON *argjson;

17
iguana/SuperNET.h

@ -122,6 +122,15 @@ struct category_msg { struct queueitem DL; struct tai t; uint64_t remoteipbits;
struct exchange_quote { uint64_t satoshis,orderid,offerNXT,exchangebits; double price,volume; uint32_t timestamp,val; };
struct bitcoin_unspent { bits256 txid,privkeys[16]; uint64_t value; int32_t vout; };
struct bitcoin_spend
{
char changeaddr[64];
int32_t numinputs;
int64_t txfee,input_satoshis,satoshis,change,netamount;
struct bitcoin_unspent inputs[];
};
void expand_epbits(char *endpoint,struct endpoint epbits);
struct endpoint calc_epbits(char *transport,uint32_t ipbits,uint16_t port,int32_t type);
@ -143,7 +152,7 @@ cJSON *SuperNET_argjson(cJSON *json);
void *category_info(bits256 categoryhash,bits256 subhash);
void *category_infoset(bits256 categoryhash,bits256 subhash,void *info);
struct category_info *category_find(bits256 categoryhash,bits256 subhash);
void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *json,char *hexmsg,char *remoteaddr);
void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *retjson,cJSON *json,char *hexmsg,char *remoteaddr);
struct category_info *category_processfunc(bits256 categoryhash,char *(*process_func)(struct supernet_info *myinfo,void *data,int32_t datalen,char *remoteaddr));
char *pangea_hexmsg(struct supernet_info *myinfo,void *data,int32_t len,char *remoteaddr);
void pangea_queues(struct supernet_info *myinfo);
@ -157,7 +166,7 @@ void *category_subscribe(struct supernet_info *myinfo,bits256 category,bits256 s
struct category_msg *category_gethexmsg(struct supernet_info *myinfo,bits256 categoryhash,bits256 subhash);
char *SuperNET_htmlstr(char *fname,char *htmlstr,int32_t maxsize,char *agentstr);
char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag,bits256 categoryhash,bits256 subcategory,char *message,int32_t maxdelay,int32_t broadcastflag,int32_t plaintext);
char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag,bits256 categoryhash,bits256 subhash,char *message,int32_t maxdelay,int32_t broadcastflag,int32_t plaintext,cJSON *argjson,char *remoteaddr);
bits256 calc_categoryhashes(bits256 *subhashp,char *category,char *subcategory);
struct category_chain *category_chain_functions(struct supernet_info *myinfo,bits256 categoryhash,bits256 subhash,int32_t hashlen,int32_t addrlen,void *hash_func,void *stake_func,void *hit_func,void *default_func);
#define category_default_latest() (*cchain->default_func)(cchain,'L',0,0,0,0,zero)
@ -172,6 +181,10 @@ char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey,int32_t le
uint8_t *cards777_recover(uint8_t *shares[],uint8_t *sharenrs,int32_t M,int32_t numcards,int32_t N);
int32_t cards777_calcmofn(uint8_t *allshares,uint8_t *myshares[],uint8_t *sharenrs,int32_t M,bits256 *xoverz,int32_t numcards,int32_t N);
int32_t init_sharenrs(unsigned char sharenrs[255],unsigned char *orig,int32_t m,int32_t n);
struct supernet_info *SuperNET_MYINFOfind(int32_t *nump,bits256 pubkey);
void SuperNET_MYINFOadd(struct supernet_info *myinfo);
struct supernet_info *SuperNET_accountfind(cJSON *argjson);
int32_t SuperNET_MYINFOS(struct supernet_info **myinfos,int32_t max);
#endif

12
iguana/SuperNET_category.c

@ -311,9 +311,9 @@ int32_t category_broadcastflag(struct supernet_info *myinfo,bits256 category,bit
return(broadcastflag);
}
char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag,bits256 categoryhash,bits256 subhash,char *message,int32_t maxdelay,int32_t broadcastflag,int32_t plaintext)
char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag,bits256 categoryhash,bits256 subhash,char *message,int32_t maxdelay,int32_t broadcastflag,int32_t plaintext,cJSON *argjson,char *remoteaddr)
{
char *hexmsg,*retstr; int32_t len;
char *hexmsg,*retstr; int32_t len; cJSON *retjson = cJSON_CreateObject();
len = (int32_t)strlen(message);
//char str[65]; printf("multicast.(%s)\n",bits256_str(str,categoryhash));
if ( is_hexstr(message,len) == 0 )
@ -325,8 +325,16 @@ char *SuperNET_categorymulticast(struct supernet_info *myinfo,int32_t surveyflag
broadcastflag = category_broadcastflag(myinfo,categoryhash,subhash,broadcastflag);
maxdelay = category_maxdelay(myinfo,categoryhash,subhash,maxdelay);
retstr = SuperNET_DHTsend(myinfo,0,categoryhash,subhash,hexmsg,maxdelay,broadcastflag,plaintext);
if ( 0 && argjson != 0 )
SuperNET_hexmsgprocess(myinfo,retjson,argjson,hexmsg,remoteaddr);
if ( hexmsg != message)
free(hexmsg);
if ( retjson != 0 )
{
if ( retstr != 0 )
jaddstr(retjson,"result",retstr);
retstr = jprint(retjson,1);
}
return(retstr);
}

8
iguana/SuperNET_hexmsg.c

@ -73,7 +73,7 @@ void SuperNET_hexmsgadd(struct supernet_info *myinfo,bits256 categoryhash,bits25
//printf("HEXMSG.(%s).%llx -> %s\n",hexmsg,(long long)subhash.txid,str);
}
void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *json,char *hexmsg,char *remoteaddr)
void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *retjson,cJSON *json,char *hexmsg,char *remoteaddr)
{
int32_t len,flag=0; char *str; uint8_t _buf[8192],*buf = _buf; bits256 categoryhash; struct category_info *cat;
if ( hexmsg != 0 )
@ -91,7 +91,11 @@ void SuperNET_hexmsgprocess(struct supernet_info *myinfo,cJSON *json,char *hexms
if ( cat->processfunc != 0 )
{
if ( (str= (*cat->processfunc)(myinfo,buf,len,remoteaddr)) != 0 )
free(str);
{
if ( retjson != 0 )
jaddstr(retjson,"processfunc",str);
else free(str);
}
flag = 1;
//printf("PROCESSFUNC\n");
}

2
iguana/SuperNET_keys.c

@ -190,7 +190,7 @@ cJSON *SuperNET_decryptedjson(char *passphrase,int32_t passsize,bits256 walletha
wallet2shared = SuperNET_wallet2shared(wallethash,wallet2priv);
wallet2pub = curve25519(wallet2shared,curve25519_basepoint9());
sprintf(fname,"confs/%s",bits256_str(str,wallet2pub));
printf("fname.(%s) wallet2shared.%s\n",fname,bits256_str(str,wallet2pub));
//printf("fname.(%s) wallet2shared.%s\n",fname,bits256_str(str,wallet2pub));
if ( (confstr= OS_filestr(&allocsize,fname)) != 0 )
{
if ( (filejson= cJSON_Parse(confstr)) != 0 )

162
iguana/exchanges/bitcoin.c

@ -183,14 +183,19 @@ int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr
return(0);
}
void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen)
{
bits256 hash;
vcalc_sha256(0,hash.bytes,data,datalen);
calc_rmd160(0,rmd160,hash.bytes,sizeof(hash));
}
char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey,int32_t len)
{
int32_t i; uint8_t data[25]; bits256 hash; char checkaddr[65];
if ( len != 20 )
{
vcalc_sha256(0,hash.bytes,pubkey,len);
calc_rmd160(0,data+1,hash.bytes,sizeof(hash));
} else memcpy(data+1,pubkey,20);
calc_rmd160_sha256(data+1,pubkey,len);
else memcpy(data+1,pubkey,20);
btc_convrmd160(checkaddr,addrtype,data+1);
//for (i=0; i<20; i++)
// printf("%02x",data[i+1]);
@ -399,7 +404,7 @@ int32_t bitcoin_checklocktimeverify(uint8_t *script,int32_t n,uint32_t locktime)
int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp)
{
uint8_t sha256[32]; int32_t i,plen;
int32_t i,plen;
script[n++] = 0x50 + vp->M;
for (i=0; i<vp->N; i++)
{
@ -411,8 +416,7 @@ int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t
}
script[n++] = 0x50 + vp->N;
script[n++] = SCRIPT_OP_CHECKMULTISIG;
vcalc_sha256(0,sha256,script,n);
calc_rmd160(0,p2sh_rmd160,sha256,sizeof(sha256));
calc_rmd160_sha256(p2sh_rmd160,script,n);
return(n);
}
@ -484,7 +488,7 @@ int32_t bitcoin_cltvscript(uint8_t p2shtype,char *ps2h_coinaddr,uint8_t p2sh_rmd
// OP_ELSE
// OP_HASH160 secret160 OP_EQUALVERIFY OP_DUP OP_HASH160 <hash160> OP_EQUALVERIFY OP_CHECKSIG // standard spend
// OP_ENDIF
uint8_t sha256[32],rmd160A[20],rmd160B[20],addrtypeA,addrtypeB;
uint8_t rmd160A[20],rmd160B[20],addrtypeA,addrtypeB;
bitcoin_addr2rmd160(&addrtypeA,rmd160A,senderaddr);
bitcoin_addr2rmd160(&addrtypeB,rmd160B,otheraddr);
script[n++] = SCRIPT_OP_IF;
@ -494,8 +498,7 @@ int32_t bitcoin_cltvscript(uint8_t p2shtype,char *ps2h_coinaddr,uint8_t p2sh_rmd
n = bitcoin_revealsecret160(script,n,secret160);
n = bitcoin_standardspend(script,n,rmd160B);
script[n++] = SCRIPT_OP_ENDIF;
vcalc_sha256(0,sha256,script,n);
calc_rmd160(0,p2sh_rmd160,sha256,sizeof(sha256));
calc_rmd160_sha256(p2sh_rmd160,script,n);
bitcoin_address(ps2h_coinaddr,p2shtype,p2sh_rmd160,20);
return(n);
}
@ -584,8 +587,9 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp)
{
if ( zero_rmd160[0] == 0 )
{
vcalc_sha256(0,sha256,vp->spendscript,vp->spendlen); // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
calc_rmd160(0,zero_rmd160,sha256,sizeof(sha256)); // b472a266d0bd89c13706a4132ccfb16f7c3b9fcb
calc_rmd160_sha256(zero_rmd160,vp->spendscript,vp->spendlen);
//vcalc_sha256(0,sha256,vp->spendscript,vp->spendlen); // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
//calc_rmd160(0,zero_rmd160,sha256,sizeof(sha256)); // b472a266d0bd89c13706a4132ccfb16f7c3b9fcb
init_hexbytes_noT(hexstr,zero_rmd160,20);
char str[65]; printf("iguana_calcrmd160 zero len %s -> %s\n",bits256_str(str,*(bits256 *)sha256),hexstr);
}
@ -613,8 +617,7 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp)
else if ( vp->spendscript[0] > 0 && vp->spendscript[0] < 76 && vp->spendscript[vp->spendlen-1] == SCRIPT_OP_CHECKSIG && vp->spendscript[0] == vp->spendlen-2 )
{
memcpy(vp->signers[0].pubkey,&vp->spendscript[1],vp->spendscript[0]);
vcalc_sha256(0,sha256,vp->signers[0].pubkey,vp->spendscript[0]);
calc_rmd160(0,vp->rmd160,sha256,sizeof(sha256));
calc_rmd160_sha256(vp->rmd160,vp->signers[0].pubkey,vp->spendscript[0]);
return(IGUANA_SCRIPT_76AC);
}
else if ( vp->spendscript[0] == SCRIPT_OP_HASH160 && vp->spendscript[1] == 0x14 && vp->spendlen == 23 && vp->spendscript[22] == SCRIPT_OP_EQUAL )
@ -635,8 +638,7 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp)
return(-1);
}
memcpy(vp->signers[i].pubkey,script,plen);
vcalc_sha256(0,sha256,vp->signers[i].pubkey,plen);
calc_rmd160(0,vp->signers[i].rmd160,sha256,sizeof(sha256));
calc_rmd160_sha256(vp->signers[i].rmd160,vp->signers[i].pubkey,plen);
bitcoin_address(vp->signers[i].coinaddr,coin->chain->pubtype,vp->signers[i].pubkey,plen);
}
if ( (int32_t)((long)script - (long)vp->spendscript) == vp->spendlen-2 )
@ -645,8 +647,7 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp)
vp->M = m;
//printf("M.%d N.%d\n",m,n);
}
vcalc_sha256(0,sha256,vp->spendscript,vp->spendlen);
calc_rmd160(0,vp->rmd160,sha256,sizeof(sha256));
calc_rmd160_sha256(vp->rmd160,vp->spendscript,vp->spendlen);
if ( n == 3 )
{
if ( m == 3 )
@ -685,8 +686,7 @@ int32_t _iguana_calcrmd160(struct iguana_info *coin,struct vin_info *vp)
fprintf(fp,"%s\n",hexstr), fflush(fp);
} else sprintf(hexstr,"pkscript overflowed %ld\n",(long)sizeof(hexstr));
}
vcalc_sha256(0,sha256,vp->spendscript,vp->spendlen);
calc_rmd160(0,vp->rmd160,sha256,sizeof(sha256));
calc_rmd160_sha256(vp->rmd160,vp->spendscript,vp->spendlen);
return(type);
}
@ -1040,21 +1040,9 @@ char *iguana_rawtxbytes(struct iguana_info *coin,cJSON *json,struct iguana_msgtx
return(txbytes);
}
/*
struct vin_signer { bits256 privkey; uint8_t siglen,sig[80],rmd160[20],pubkey[66]; };
struct vin_info
{
struct iguana_msgvin vin;
int32_t M,N,validmask,spendlen,p2shflag;
struct vin_signer signers[16];
uint8_t rmd160[20],spendscript[IGUANA_MAXSCRIPTSIZE];
};
*/
int32_t bitcoin_scriptget(struct iguana_info *coin,int32_t *hashtypep,struct vin_info *vp,uint8_t *scriptsig,int32_t len,int32_t type)
{
char asmstr[IGUANA_MAXSCRIPTSIZE*3]; int32_t j,n,siglen,plen; uint8_t sha256[32];
char asmstr[IGUANA_MAXSCRIPTSIZE*3]; int32_t j,n,siglen,plen;
j = n = 0;
*hashtypep = SIGHASH_ALL;
while ( (siglen= scriptsig[n]) >= 70 && siglen <= 73 && n+siglen+1 < len && j < 16 )
@ -1073,8 +1061,7 @@ int32_t bitcoin_scriptget(struct iguana_info *coin,int32_t *hashtypep,struct vin
while ( ((plen= scriptsig[n]) == 33 || plen == 65 ) && j < 16 )
{
memcpy(vp->signers[j].pubkey,&scriptsig[n+1],plen);
vcalc_sha256(0,sha256,vp->signers[j].pubkey,plen);
calc_rmd160(0,vp->signers[j].rmd160,sha256,sizeof(sha256));
calc_rmd160_sha256(vp->signers[j].rmd160,vp->signers[j].pubkey,plen);
if ( j == 0 )
memcpy(vp->rmd160,vp->signers[j].rmd160,20);
n += (plen + 1);
@ -1248,6 +1235,30 @@ char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson)
return(txbytes);
}
cJSON *bitcoin_hex2json(struct iguana_info *coin,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes)
{
int32_t n,len; char vpnstr[64]; struct iguana_msgtx M; uint8_t *serialized; cJSON *txobj;
txobj = cJSON_CreateObject();
if ( msgtx == 0 )
{
msgtx = &M;
memset(msgtx,0,sizeof(M));
}
len = (int32_t)strlen(txbytes) >> 1;
serialized = malloc(len);
decode_hex(serialized,len,txbytes);
vpnstr[0] = 0;
memset(txidp,0,sizeof(*txidp));
//char str[65]; printf("%d of %d: %s\n",i,msg.txn_count,bits256_str(str,tx.txid));
if ( (n= iguana_rwmsgtx(coin,0,txobj,serialized,len,msgtx,txidp,vpnstr)) <= 0 )
{
free_json(txobj);
txobj = 0;
}
free(serialized);
return(txobj);
}
cJSON *bitcoin_createtx(struct iguana_info *coin,int32_t locktime)
{
cJSON *json = cJSON_CreateObject();
@ -1447,9 +1458,10 @@ static char *BASERELS[][2] = { {"btcd","btc"}, {"nxt","btc"}, {"asset","btc"} };
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert)
{
cJSON *retjson,*bids,*asks; double hbla;
struct supernet_info *myinfo = SuperNET_accountfind(argjson);
bids = cJSON_CreateArray();
asks = cJSON_CreateArray();
instantdex_acceptablefind(exchange,bids,asks,0,base,rel);
instantdex_acceptablefind(myinfo,exchange,bids,asks,0,base,rel);
retjson = cJSON_CreateObject();
cJSON_AddItemToObject(retjson,"bids",bids);
cJSON_AddItemToObject(retjson,"asks",asks);
@ -1460,11 +1472,13 @@ double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchang
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
//struct supernet_info *myinfo = SuperNET_accountfind(argjson);
return(clonestr("{\"error\":\"bitcoin is not yet\"}"));
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
//struct supernet_info *myinfo = SuperNET_accountfind(argjson);
return(cJSON_Parse("{\"error\":\"bitcoin is not yet\"}"));
}
@ -1481,9 +1495,11 @@ int32_t is_valid_BTCother(char *other)
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
struct instantdex_accept *ap; char *str,coinaddr[64]; uint64_t txid = 0; cJSON *json;
char *str,coinaddr[64]; uint64_t txid = 0; cJSON *tmp,*json=0;
struct supernet_info *myinfo; uint8_t pubkey[33]; struct iguana_info *other; int32_t hops = 3;
myinfo = SuperNET_MYINFO(0);
myinfo = SuperNET_accountfind(argjson);
if ( retstrp != 0 )
*retstrp = 0;
if ( strcmp(base,"BTC") == 0 || strcmp(base,"btc") == 0 )
{
base = rel;
@ -1494,54 +1510,49 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha
}
if ( is_valid_BTCother(base) != 0 && (strcmp(rel,"BTC") == 0 || strcmp(rel,"btc") == 0) )
{
ap = 0;//instantdex_acceptable(exchange,base,rel,"BTC",dir,price,volume);
if ( dotrade == 0 )
{
if ( retstrp != 0 )
{
if ( ap != 0 )
*retstrp = jprint(instantdex_acceptjson(ap),1);
else *retstrp = clonestr("{\"result\":\"would issue new trade\"}");
}
*retstrp = clonestr("{\"result\":\"would issue new trade\"}");
}
else
{
if ( ap != 0 )
if ( (other= iguana_coinfind(base)) != 0 )
{
// issue matching response
bitcoin_pubkey33(pubkey,myinfo->persistent_priv);
bitcoin_address(coinaddr,other->chain->pubtype,pubkey,sizeof(pubkey));
jaddstr(argjson,base,coinaddr);
}
else if ( dir < 0 )
else if ( strcmp(base,"NXT") == 0 || (is_decimalstr(base) > 0 && strlen(base) > 13) )
{
printf("bitcoin sell is not yet\n");
printf("NXT is not yet\n");
return(0);
}
else
else return(0);
json = cJSON_CreateObject();
jaddstr(json,"base",base);
jaddstr(json,"rel","BTC");
jaddnum(json,dir > 0 ? "maxprice" : "minprice",price);
jaddnum(json,"volume",volume);
jaddstr(json,"BTC",myinfo->myaddr.BTC);
//printf("trade dir.%d (%s/%s) %.6f vol %.8f\n",dir,base,"BTC",price,volume);
if ( (str= instantdex_sendcmd(myinfo,json,"BTCoffer",myinfo->ipaddr,hops)) != 0 )
{
json = cJSON_CreateObject();
jaddstr(json,"base",base);
jaddstr(json,"rel","BTC");
jaddnum(json,"maxprice",price);
jaddnum(json,"volume",volume);
if ( (other= iguana_coinfind(base)) != 0 )
{
bitcoin_pubkey33(pubkey,myinfo->persistent_priv);
bitcoin_address(coinaddr,other->chain->pubtype,pubkey,sizeof(pubkey));
jaddstr(argjson,base,coinaddr);
}
jaddstr(json,"BTC",myinfo->myaddr.BTC);
if ( (str= instantdex_sendcmd(myinfo,json,"BTCoffer",myinfo->ipaddr,hops)) != 0 )
free(str);
free_json(json);
if ( (str= instantdex_queueaccept(exchange,base,"BTC",price,volume,-1,"BTC",INSTANTDEX_OFFERDURATION)) != 0 )
jaddstr(json,"BTCoffer",str);
}
if ( (str= instantdex_queueaccept(myinfo,exchange,base,"BTC",price,volume,-dir,dir > 0 ? "BTC" : base,INSTANTDEX_OFFERDURATION)) != 0 )
{
jaddstr(json,"queue",str);
if ( (tmp= cJSON_Parse(str)) != 0 )
{
if ( (json= cJSON_Parse(str)) != 0 )
{
txid = j64bits(json,"orderid");
free_json(json);
}
free(str);
txid = j64bits(json,"orderid");
free_json(tmp);
}
}
if ( retstrp != 0 )
*retstrp = jprint(json,1);
else free_json(json);
}
}
return(txid);
@ -1550,7 +1561,8 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson)
{
struct instantdex_accept *ap; cJSON *retjson;
if ( (ap= instantdex_acceptablefind(exchange,0,0,orderid,"*","*")) != 0 )
struct supernet_info *myinfo = SuperNET_accountfind(argjson);
if ( (ap= instantdex_acceptablefind(myinfo,exchange,0,0,orderid,"*","*")) != 0 )
{
retjson = cJSON_CreateObject();
jadd(retjson,"result",instantdex_acceptjson(ap));
@ -1561,7 +1573,8 @@ char *ORDERSTATUS(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson
char *CANCELORDER(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson)
{
struct instantdex_accept *ap; cJSON *retjson;
if ( (ap= instantdex_acceptablefind(exchange,0,0,orderid,"*","*")) != 0 )
struct supernet_info *myinfo = SuperNET_accountfind(argjson);
if ( (ap= instantdex_acceptablefind(myinfo,exchange,0,0,orderid,"*","*")) != 0 )
{
ap->dead = (uint32_t)time(NULL);
retjson = cJSON_CreateObject();
@ -1574,9 +1587,10 @@ char *CANCELORDER(struct exchange_info *exchange,uint64_t orderid,cJSON *argjson
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
cJSON *retjson,*bids,*asks;
struct supernet_info *myinfo = SuperNET_accountfind(argjson);
bids = cJSON_CreateArray();
asks = cJSON_CreateArray();
instantdex_acceptablefind(exchange,bids,asks,0,"*","*");
instantdex_acceptablefind(myinfo,exchange,bids,asks,0,"*","*");
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jadd(retjson,"bids",bids);
@ -1586,11 +1600,13 @@ char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
//struct supernet_info *myinfo = SuperNET_accountfind(argjson);
return(clonestr("{\"error\":\"bitcoin is not yet\"}"));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
//struct supernet_info *myinfo = SuperNET_accountfind(argjson);
return(clonestr("{\"error\":\"bitcoin is not yet\"}"));
}

6
iguana/exchanges/bitcoin.h

@ -50,12 +50,6 @@ int32_t bitcoin_cltvscript(uint8_t p2shtype,char *ps2h_coinaddr,uint8_t p2sh_rmd
int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr);
char *bitcoin_cltvtx(struct iguana_info *coin,char *changeaddr,char *senderaddr,char *senders_otheraddr,char *otheraddr,uint32_t locktime,uint64_t satoshis,bits256 txid,int32_t vout,uint64_t inputsatoshis,bits256 privkey);
int32_t bitcoin_MofNspendscript(uint8_t p2sh_rmd160[20],uint8_t *script,int32_t n,const struct vin_info *vp);
cJSON *bitcoin_createtx(struct iguana_info *coin,int32_t locktime);
cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis);
int32_t bitcoin_changescript(struct iguana_info *coin,uint8_t *changescript,int32_t n,uint64_t *changep,char *changeaddr,uint64_t inputsatoshis,uint64_t satoshis,uint64_t txfee);
cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequence);
int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V);
char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson);
int32_t bitcoin_pubkeyspend(uint8_t *script,int32_t n,uint8_t pubkey[66]);
int32_t bitcoin_p2shspend(uint8_t *script,int32_t n,uint8_t rmd160[20]);

19
iguana/exchanges777.h

@ -20,6 +20,7 @@
#include <curl/curl.h>
#include <curl/easy.h>
#define INSTANTDEX_OFFERDURATION 300
#define INSTANTDEX_LOCKTIME 3600
#define EXCHANGES777_MINPOLLGAP 3
#define EXCHANGES777_MAXDEPTH 200
@ -89,21 +90,12 @@ struct exchange_request
struct exchange_quote bidasks[];
};
struct bitcoin_unspent { bits256 txid,privkey; uint64_t value; int32_t vout; };
struct bitcoin_spend
{
char changeaddr[64];
int32_t numinputs;
int64_t txfee,input_satoshis,satoshis,change,netamount;
struct bitcoin_unspent inputs[];
};
struct instantdex_entry { char base[24],rel[24]; uint64_t price64,basevolume64,offer64; uint32_t expiration,nonce; char myside,acceptdir; };
struct instantdex_accept { struct queueitem DL; cJSON *statusjson; uint64_t pendingvolume64,orderid; uint32_t dead; struct instantdex_entry A; };
struct instantdex_accept { struct queueitem DL; void *info; uint64_t pendingvolume64,orderid; uint32_t dead; struct instantdex_entry A; };
struct instantdex_accept *instantdex_acceptablefind(struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel);
struct instantdex_accept *instantdex_acceptablefind(struct supernet_info *myinfo,struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel);
cJSON *instantdex_acceptjson(struct instantdex_accept *ap);
struct instantdex_accept *instantdex_acceptable(struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits);
struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits);
void *curl_post(void **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3);
char *instantdex_sendcmd(struct supernet_info *myinfo,cJSON *argjson,char *cmdstr,char *ipaddr,int32_t hops);
@ -121,6 +113,7 @@ double truefx_price(struct exchange_info *exchange,char *base,char *rel,struct e
double fxcm_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert);
double instaforex_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert);
char *instantdex_queueaccept(struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *myside,int32_t duration);
char *instantdex_queueaccept(struct supernet_info *myinfo,struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *mysidestr,int32_t duration);
void instantdex_update(struct supernet_info *myinfo);
#endif

2
iguana/iguana777.c

@ -421,7 +421,7 @@ void iguana_coinloop(void *arg)
}
}
if ( flag == 0 )
usleep(coin->polltimeout * 1000);
usleep(coin->polltimeout * 10000);
}
}

12
iguana/iguana777.h

@ -743,6 +743,18 @@ cJSON *iguana_blockjson(struct iguana_info *coin,struct iguana_block *block,int3
//int32_t iguana_sig(uint8_t *sig,int32_t maxsize,uint8_t *data,int32_t datalen,bits256 privkey);
//int32_t iguana_ver(uint8_t *sig,int32_t siglen,uint8_t *data,int32_t datalen,bits256 pubkey);
//int32_t iguana_ver(uint8_t *sig,int32_t siglen,uint8_t *data,int32_t datalen,uint8_t *pubkey);
void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen);
int32_t bitcoin_checklocktimeverify(uint8_t *script,int32_t n,uint32_t locktime);
struct bitcoin_spend *iguana_spendset(struct supernet_info *myinfo,struct iguana_info *coin,int64_t satoshis,int64_t insurance);
cJSON *bitcoin_hex2json(struct iguana_info *coin,bits256 *txidp,struct iguana_msgtx *msgtx,char *txbytes);
cJSON *iguana_signtx(struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj);
cJSON *bitcoin_createtx(struct iguana_info *coin,int32_t locktime);
cJSON *bitcoin_addoutput(struct iguana_info *coin,cJSON *txobj,uint8_t *paymentscript,int32_t len,uint64_t satoshis);
int32_t bitcoin_changescript(struct iguana_info *coin,uint8_t *changescript,int32_t n,uint64_t *changep,char *changeaddr,uint64_t inputsatoshis,uint64_t satoshis,uint64_t txfee);
cJSON *bitcoin_addinput(struct iguana_info *coin,cJSON *txobj,bits256 txid,int32_t vout,uint32_t sequence);
int32_t bitcoin_verifytx(struct iguana_info *coin,bits256 *signedtxidp,char **signedtx,char *rawtxstr,struct vin_info *V);
char *bitcoin_json2hex(struct iguana_info *coin,bits256 *txidp,cJSON *txjson);
int32_t bitcoin_addr2rmd160(uint8_t *addrtypep,uint8_t rmd160[20],char *coinaddr);
extern queue_t bundlesQ;

4
iguana/iguana_blocks.c

@ -347,9 +347,9 @@ struct iguana_block *_iguana_chainlink(struct iguana_info *coin,struct iguana_bl
}
if ( coin->started != 0 && (block->height % coin->chain->bundlesize) == 10 )
{
printf("savehdrs\n");
//printf("savehdrs\n");
iguana_savehdrs(coin);
printf("done savehdrs\n");
//printf("done savehdrs\n");
}
}
}

160
iguana/iguana_exchanges.c

@ -58,8 +58,8 @@ cJSON *exchanges777_quotejson(struct exchange_quote *quote,int32_t allflag,doubl
jaddstr(json,"time",utc_str(str,quote->timestamp));
if ( quote->orderid > 0 )
jadd64bits(json,"orderid",quote->orderid);
if ( quote->offerNXT > 0 )
jadd64bits(json,"offerNXT",quote->offerNXT);
//if ( quote->offerNXT != 0 )
jadd64bits(json,"offerer",quote->offerNXT);
return(json);
} else return(cJSON_CreateNumber(quote->price));
}
@ -245,6 +245,7 @@ void exchanges777_json_quotes(struct exchange_info *exchange,double commission,c
volume = jdouble(item,"volume");
timestamp = juint(item,"timestamp");
orderid = j64bits(item,"orderid");
offerNXT = j64bits(item,"offerer");
}
if ( price == 0. || volume == 0. )
continue;
@ -533,11 +534,13 @@ char *exchanges777_process(struct exchange_info *exchange,int32_t *retvalp,struc
orderid = (*exchange->issue.trade)(req->dotrade,&retstr,exchange,base,rel,polarity * req->dir,price,volume,req->argjson);
if ( retstr == 0 )
{
retjson = cJSON_CreateObject();
req->orderid = orderid;
retstr = (*exchange->issue.orderstatus)(exchange,req->orderid,req->argjson);
/*retjson = cJSON_CreateObject();
if ( orderid != 0 )
jadd64bits(retjson,"result",orderid);
else jaddstr(retjson,"error","no return value from trade call");
retstr = jprint(retjson,1);
retstr = jprint(retjson,1);*/
}
}
break;
@ -907,7 +910,7 @@ struct exchange_info *exchange_create(char *exchangestr,cJSON *argjson)
struct exchange_info *exchanges777_info(char *exchangestr,int32_t sleepflag,cJSON *json,char *remoteaddr)
{
struct exchange_info *exchange;
if ( remoteaddr != 0 )
if ( remoteaddr != 0 || exchangestr == 0 )
return(0);
if ( (exchange= exchanges777_find(exchangestr)) == 0 )
{
@ -956,116 +959,153 @@ void exchanges777_init(struct supernet_info *myinfo,cJSON *exchanges,int32_t sle
THREE_STRINGS_AND_THREE_INTS(InstantDEX,orderbook,exchange,base,rel,depth,allfields,ignore)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qprices(ptr,base,rel,juint(json,"maxseconds"),allfields,depth,json,0,ptr->commission));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( remoteaddr == 0 )
{
instantdex_update(myinfo);
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qprices(ptr,base,rel,juint(json,"maxseconds"),allfields,depth,json,0,ptr->commission));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,buy,exchange,base,rel,price,volume,dotrade)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qtrade(ptr,base,rel,juint(json,"maxseconds"),dotrade,1,price,volume,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( remoteaddr == 0 )
{
instantdex_update(myinfo);
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qtrade(ptr,base,rel,juint(json,"maxseconds"),dotrade,1,price,volume,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,sell,exchange,base,rel,price,volume,dotrade)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qtrade(ptr,base,rel,juint(json,"maxseconds"),dotrade,-1,price,volume,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( remoteaddr == 0 )
{
instantdex_update(myinfo);
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qtrade(ptr,base,rel,juint(json,"maxseconds"),dotrade,-1,price,volume,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
THREE_STRINGS_AND_DOUBLE(InstantDEX,withdraw,exchange,base,destaddr,amount)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'W',base,0,juint(json,"maxseconds"),0,destaddr,amount,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
THREE_STRINGS(InstantDEX,supports,exchange,base,rel)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'S',base,rel,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( remoteaddr == 0 )
{
instantdex_update(myinfo);
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'W',base,0,juint(json,"maxseconds"),0,destaddr,amount,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
TWO_STRINGS(InstantDEX,balance,exchange,base)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'B',base,0,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( remoteaddr == 0 )
{
instantdex_update(myinfo);
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'B',base,0,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
TWO_STRINGS(InstantDEX,orderstatus,exchange,orderid)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'P',0,0,juint(json,"maxseconds"),calc_nxt64bits(orderid),0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( remoteaddr == 0 )
{
instantdex_update(myinfo);
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'P',0,0,juint(json,"maxseconds"),calc_nxt64bits(orderid),0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
TWO_STRINGS(InstantDEX,cancelorder,exchange,orderid)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'C',0,0,juint(json,"maxseconds"),calc_nxt64bits(orderid),0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( remoteaddr == 0 )
{
instantdex_update(myinfo);
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'C',0,0,juint(json,"maxseconds"),calc_nxt64bits(orderid),0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
STRING_ARG(InstantDEX,openorders,exchange)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'O',0,0,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( remoteaddr == 0 )
{
instantdex_update(myinfo);
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'O',0,0,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
STRING_ARG(InstantDEX,tradehistory,exchange)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'H',0,0,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( remoteaddr == 0 )
{
instantdex_update(myinfo);
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'H',0,0,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
THREE_STRINGS(InstantDEX,apikeypair,exchange,apikey,apisecret)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
if ( remoteaddr == 0 )
{
if ( apikey != 0 && apikey[0] != 0 && apisecret != 0 && apisecret[0] != 0 )
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
{
safecopy(ptr->apikey,apikey,sizeof(ptr->apikey));
safecopy(ptr->apisecret,apisecret,sizeof(ptr->apisecret));
return(clonestr("{\"result\":\"set apikey and apisecret\"}"));
} else return(clonestr("{\"error\":\"need both userid and password\"}"));
} else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( apikey != 0 && apikey[0] != 0 && apisecret != 0 && apisecret[0] != 0 )
{
safecopy(ptr->apikey,apikey,sizeof(ptr->apikey));
safecopy(ptr->apisecret,apisecret,sizeof(ptr->apisecret));
return(clonestr("{\"result\":\"set apikey and apisecret\"}"));
} else return(clonestr("{\"error\":\"need both userid and password\"}"));
} else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
THREE_STRINGS(InstantDEX,setuserid,exchange,userid,tradepassword)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
if ( remoteaddr == 0 )
{
safecopy(ptr->userid,userid,sizeof(ptr->userid));
safecopy(ptr->tradepassword,tradepassword,sizeof(ptr->tradepassword));
return(clonestr("{\"result\":\"set userid and/or tradepassword\"}"));
} else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
{
safecopy(ptr->userid,userid,sizeof(ptr->userid));
safecopy(ptr->tradepassword,tradepassword,sizeof(ptr->tradepassword));
return(clonestr("{\"result\":\"set userid and/or tradepassword\"}"));
} else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
STRING_AND_INT(InstantDEX,pollgap,exchange,pollgap)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
if ( remoteaddr == 0 )
{
ptr->pollgap = pollgap;
return(clonestr("{\"result\":\"set pollgap\"}"));
} else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
{
ptr->pollgap = pollgap;
return(clonestr("{\"result\":\"set pollgap\"}"));
} else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
} else return(clonestr("{\"error\":\"no remote for this API\"}"));
}
ZERO_ARGS(InstantDEX,allexchanges)
@ -1078,6 +1118,14 @@ ZERO_ARGS(InstantDEX,allexchanges)
return(jprint(retjson,1));
}
THREE_STRINGS(InstantDEX,supports,exchange,base,rel)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json,remoteaddr)) != 0 )
return(exchanges777_Qrequest(ptr,'S',base,rel,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
STRING_ARG(InstantDEX,allpairs,exchange)
{
struct exchange_info *ptr;

232
iguana/iguana_instantdex.c

@ -82,37 +82,43 @@ struct instantdex_msghdr *instantdex_msgcreate(struct supernet_info *myinfo,stru
char *instantdex_sendcmd(struct supernet_info *myinfo,cJSON *argjson,char *cmdstr,char *ipaddr,int32_t hops)
{
char *reqstr,hexstr[8192]; uint8_t _msg[4096]; uint64_t nxt64bits; int32_t i,datalen;
char *reqstr,*hexstr,*retstr; uint64_t nxt64bits; int32_t i,datalen;
bits256 instantdexhash; struct instantdex_msghdr *msg;
msg = (struct instantdex_msghdr *)_msg;
memset(msg,0,sizeof(*msg));
instantdexhash = calc_categoryhashes(0,"InstantDEX",0);
category_subscribe(myinfo,instantdexhash,GENESIS_PUBKEY);
//if ( ipaddr == 0 || ipaddr[0] == 0 || strncmp(ipaddr,"127.0.0.1",strlen("127.0.0.1")) == 0 )
// return(clonestr("{\"error\":\"no ipaddr, need to send your ipaddr for now\"}"));
jaddstr(argjson,"cmd",cmdstr);
for (i=0; i<sizeof(msg->cmd); i++)
if ( (msg->cmd[i]= cmdstr[i]) == 0 )
break;
jaddstr(argjson,"agent","SuperNET");
jaddstr(argjson,"method","DHT");
jaddstr(argjson,"traderip",ipaddr);
jaddstr(argjson,"handle",myinfo->handle);
jaddbits256(argjson,"categoryhash",instantdexhash);
jaddbits256(argjson,"traderpub",myinfo->myaddr.persistent);
nxt64bits = acct777_nxt64bits(myinfo->myaddr.persistent);
reqstr = jprint(argjson,1);
reqstr = jprint(argjson,0);
datalen = (int32_t)(strlen(reqstr) + 1);
msg = calloc(1,sizeof(*msg) + datalen);
for (i=0; i<sizeof(msg->cmd); i++)
if ( (msg->cmd[i]= cmdstr[i]) == 0 )
break;
memcpy(msg->serialized,reqstr,datalen);
free(reqstr);
if ( (datalen+sizeof(*msg))*2+1 < sizeof(hexstr) && instantdex_msgcreate(myinfo,msg,datalen) != 0 )
if ( instantdex_msgcreate(myinfo,msg,datalen) != 0 )
{
printf("instantdex send.(%s)\n",cmdstr);
//printf("instantdex send.(%s)\n",jprint(argjson,0));
hexstr = malloc(msg->sig.allocsize*2 + 1);
init_hexbytes_noT(hexstr,(uint8_t *)msg,msg->sig.allocsize);
return(SuperNET_categorymulticast(myinfo,0,instantdexhash,GENESIS_PUBKEY,hexstr,0,hops,1));
retstr = SuperNET_categorymulticast(myinfo,0,instantdexhash,GENESIS_PUBKEY,hexstr,0,hops,1,argjson,0);
free_json(argjson);
free(hexstr);
free(msg);
return(retstr);
}
else
{
printf("cant msgcreate\n");
free_json(argjson);
free(msg);
printf("cant msgcreate datalen.%d\n",datalen);
return(clonestr("{\"error\":\"couldnt create instantdex message\"}"));
}
}
@ -242,7 +248,7 @@ cJSON *instantdex_acceptjson(struct instantdex_accept *ap)
return(item);
}
struct instantdex_accept *instantdex_acceptablefind(struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel)
struct instantdex_accept *instantdex_acceptablefind(struct supernet_info *myinfo,struct exchange_info *exchange,cJSON *bids,cJSON *asks,uint64_t orderid,char *base,char *rel)
{
struct instantdex_accept PAD,*ap,*retap = 0; uint32_t now; cJSON *item; char *type;
now = (uint32_t)time(NULL);
@ -252,13 +258,15 @@ struct instantdex_accept *instantdex_acceptablefind(struct exchange_info *exchan
{
if ( now < ap->A.expiration && ap->dead == 0 )
{
printf("find cmps %d %d %d %d %d %d\n",strcmp(base,"*") == 0,strcmp(base,ap->A.base) == 0,strcmp(rel,"*") == 0,strcmp(rel,ap->A.rel) == 0,orderid == 0,orderid == ap->orderid);
if ( (strcmp(base,"*") == 0 || strcmp(base,ap->A.base) == 0) && (strcmp(rel,"*") == 0 || strcmp(rel,ap->A.rel) == 0) && (orderid == 0 || orderid == ap->orderid) )
{
printf("found match\n");
retap = ap;
}
if ( (item= instantdex_acceptjson(ap)) != 0 )
{
//printf("item.(%s)\n",jprint(item,0));
printf("item.(%s)\n",jprint(item,0));
if ( (type= jstr(item,"type")) != 0 )
{
if ( strcmp(type,"bid") == 0 && bids != 0 )
@ -273,7 +281,7 @@ struct instantdex_accept *instantdex_acceptablefind(struct exchange_info *exchan
return(retap);
}
struct instantdex_accept *instantdex_acceptable(struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits)
struct instantdex_accept *instantdex_acceptable(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,uint64_t offerbits)
{
struct instantdex_accept PAD,*ap,*retap = 0; uint64_t bestprice64 = 0;
uint32_t now; int32_t offerdir;
@ -283,12 +291,15 @@ struct instantdex_accept *instantdex_acceptable(struct exchange_info *exchange,s
offerdir = instantdex_bidaskdir(A);
while ( (ap= queue_dequeue(&exchange->acceptableQ,0)) != 0 && ap != &PAD )
{
if ( now < ap->A.expiration && ap->dead == 0 )
if ( now < ap->A.expiration && ap->dead == 0 && (offerbits == 0 || offerbits != ap->A.offer64) )
{
if ( (offerbits == 0 || offerbits != A->A.offer64) && A->A.basevolume64 > 0. && (strcmp(A->A.base,"*") == 0 || strcmp(A->A.base,ap->A.base) == 0) && (strcmp(A->A.rel,"*") == 0 || strcmp(A->A.rel,ap->A.rel) == 0) && A->A.basevolume64 <= (ap->A.basevolume64 - ap->pendingvolume64) && offerdir*instantdex_bidaskdir(ap) < 0 )
printf("check offerbits.%llu vs %llu: %d %d %d %d %d %d %d %d\n",(long long)offerbits,(long long)ap->A.offer64,A->A.basevolume64 > 0.,strcmp(A->A.base,"*") == 0 ,strcmp(A->A.base,ap->A.base) == 0, strcmp(A->A.rel,"*") == 0 ,strcmp(A->A.rel,ap->A.rel) == 0,A->A.basevolume64 <= (ap->A.basevolume64 - ap->pendingvolume64),offerdir,instantdex_bidaskdir(ap));
if ( A->A.basevolume64 > 0. && (strcmp(A->A.base,"*") == 0 || strcmp(A->A.base,ap->A.base) == 0) && (strcmp(A->A.rel,"*") == 0 || strcmp(A->A.rel,ap->A.rel) == 0) && A->A.basevolume64 <= (ap->A.basevolume64 - ap->pendingvolume64) && offerdir*instantdex_bidaskdir(ap) < 0 )
{
if ( offerdir == 0 || A->A.price64 == 0 || ((offerdir > 0 && ap->A.price64 > A->A.price64) || (offerdir < 0 && ap->A.price64 < A->A.price64)) )
printf("passed first cmp: %d %d %d %d\n",offerdir == 0,A->A.price64 == 0,(offerdir > 0 && ap->A.price64 >= A->A.price64),(offerdir < 0 && ap->A.price64 <= A->A.price64));
if ( offerdir == 0 || A->A.price64 == 0 || ((offerdir > 0 && ap->A.price64 >= A->A.price64) || (offerdir < 0 && ap->A.price64 <= A->A.price64)) )
{
printf("passed second cmp: offerdir.%d best %.8f ap %.8f\n",offerdir,dstr(bestprice64),dstr(ap->A.price64));
if ( bestprice64 == 0 || (offerdir < 0 && ap->A.price64 < bestprice64) || (offerdir > 0 && ap->A.price64 > bestprice64) )
{
printf("found better price %f vs %f\n",dstr(ap->A.price64),dstr(bestprice64));
@ -315,42 +326,16 @@ struct instantdex_accept *instantdex_acceptable(struct exchange_info *exchange,s
// NXT node verifies bitcoin txbytes has proper payment and cashes in with onetimepubkey
// BTC* node approves phased tx with onetimepubkey
int32_t instantdex_acceptextract(struct instantdex_accept *ap,cJSON *argjson)
{
char *base,*rel; bits256 hash;
memset(ap,0,sizeof(*ap));
if ( (base= jstr(argjson,"b")) != 0 )
safecopy(ap->A.base,base,sizeof(ap->A.base));
if ( (rel= jstr(argjson,"r")) != 0 )
safecopy(ap->A.rel,rel,sizeof(ap->A.rel));
ap->A.nonce = juint(argjson,"n");
ap->A.expiration = juint(argjson,"e");
ap->A.myside = juint(argjson,"s");
ap->A.acceptdir = jint(argjson,"d");
ap->A.offer64 = j64bits(argjson,"o");
ap->A.price64 = j64bits(argjson,"p");
ap->A.basevolume64 = j64bits(argjson,"v");
vcalc_sha256(0,hash.bytes,(void *)&ap->A,sizeof(ap->A));
ap->orderid = j64bits(argjson,"i");
if ( hash.txid != ap->orderid )
{
int32_t i;
for (i=0; i<sizeof(*ap); i++)
printf("%02x ",((uint8_t *)ap)[i]);
printf("instantdex_acceptset warning %llu != %llu\n",(long long)hash.txid,(long long)ap->orderid);
return(-1);
}
return(0);
}
bits256 instantdex_acceptset(struct instantdex_accept *ap,char *base,char *rel,int32_t duration,int32_t myside,int32_t acceptdir,double price,double volume,uint64_t offerbits)
{
bits256 hash;
memset(ap,0,sizeof(*ap));
safecopy(ap->A.base,base,sizeof(ap->A.base));
safecopy(ap->A.rel,base,sizeof(ap->A.rel));
safecopy(ap->A.rel,rel,sizeof(ap->A.rel));
OS_randombytes((uint8_t *)&ap->A.nonce,sizeof(ap->A.nonce));
ap->A.expiration = (uint32_t)time(NULL) + duration;
if ( duration < 1000000000 )
ap->A.expiration = (uint32_t)time(NULL) + duration;
else ap->A.expiration = duration;
ap->A.offer64 = offerbits;
ap->A.myside = myside;
ap->A.acceptdir = acceptdir;
@ -358,9 +343,67 @@ bits256 instantdex_acceptset(struct instantdex_accept *ap,char *base,char *rel,i
ap->A.basevolume64 = volume * SATOSHIDEN;
vcalc_sha256(0,hash.bytes,(void *)&ap->A,sizeof(ap->A));
ap->orderid = hash.txid;
//printf("(%s/%s) acceptdir.%d myside.%d\n",base,rel,acceptdir,myside);
return(hash);
}
int32_t instantdex_acceptextract(struct instantdex_accept *ap,cJSON *argjson)
{
char *base,*rel; bits256 hash,traderpub; double price,volume; int32_t baserel,acceptdir,num;
struct supernet_info *myinfo;
memset(ap,0,sizeof(*ap));
if ( (base= jstr(argjson,"base")) != 0 )
{
volume = jdouble(argjson,"volume");
if ( (rel= jstr(argjson,"rel")) != 0 )
safecopy(ap->A.rel,rel,sizeof(ap->A.rel));
if ( (price= jdouble(argjson,"maxprice")) > SMALLVAL )
{
baserel = 1;
acceptdir = -1;
}
else if ( (price= jdouble(argjson,"minprice")) > SMALLVAL )
{
baserel = 0;
acceptdir = 1;
} else return(-1);
//printf("price %f vol %f baserel.%d acceptdir.%d\n",price,volume,baserel,acceptdir);
traderpub = jbits256(argjson,"traderpub");
if ( (myinfo= SuperNET_MYINFOfind(&num,traderpub)) != 0 )
hash = instantdex_acceptset(ap,base,rel,INSTANTDEX_LOCKTIME*2,baserel,acceptdir,price,volume,myinfo->myaddr.nxt64bits);
else
{
char str[65]; printf("cant find account for (%s)\n",bits256_str(str,traderpub));
return(-1);
}
}
else
{
if ( (base= jstr(argjson,"b")) != 0 )
safecopy(ap->A.base,base,sizeof(ap->A.base));
if ( (rel= jstr(argjson,"r")) != 0 )
safecopy(ap->A.rel,rel,sizeof(ap->A.rel));
ap->A.nonce = juint(argjson,"n");
ap->A.expiration = juint(argjson,"e");
ap->A.myside = juint(argjson,"s");
ap->A.acceptdir = jint(argjson,"d");
ap->A.offer64 = j64bits(argjson,"o");
ap->A.price64 = j64bits(argjson,"p");
ap->A.basevolume64 = j64bits(argjson,"v");
vcalc_sha256(0,hash.bytes,(void *)&ap->A,sizeof(ap->A));
ap->orderid = j64bits(argjson,"id");
}
if ( hash.txid != ap->orderid )
{
int32_t i;
for (i=0; i<sizeof(*ap); i++)
printf("%02x ",((uint8_t *)ap)[i]);
printf("instantdex_acceptextract warning %llu != %llu\n",(long long)hash.txid,(long long)ap->orderid);
return(-1);
}
return(0);
}
cJSON *instantdex_acceptsendjson(struct instantdex_accept *ap)
{
cJSON *json = cJSON_CreateObject();
@ -373,7 +416,7 @@ cJSON *instantdex_acceptsendjson(struct instantdex_accept *ap)
jadd64bits(json,"p",ap->A.price64);
jadd64bits(json,"v",ap->A.basevolume64);
jadd64bits(json,"o",ap->A.offer64);
jadd64bits(json,"i",ap->orderid);
jadd64bits(json,"id",ap->orderid);
return(json);
}
@ -391,9 +434,9 @@ char *instantdex_parse(struct supernet_info *myinfo,struct instantdex_msghdr *ms
if ( argjson != 0 )
{
memset(&A,0,sizeof(A));
if ( (traderip= jstr(argjson,"traderip")) != 0 && strcmp(traderip,myinfo->ipaddr) == 0 )
if ( (remoteaddr != 0 && strcmp(remoteaddr,myinfo->ipaddr) == 0) || ((traderip= jstr(argjson,"traderip")) != 0 && strcmp(traderip,myinfo->ipaddr) == 0) )
{
printf("got my own request\n");
printf("got my own request.(%s)\n",jprint(argjson,0));
if ( instantdex_acceptextract(&A,argjson) < 0 )
return(clonestr("{\"error\":\"hash txid mismatches orderid\"}"));
return(clonestr("{\"result\":\"got my own request\"}"));
@ -401,10 +444,15 @@ char *instantdex_parse(struct supernet_info *myinfo,struct instantdex_msghdr *ms
if ( (orderidstr= jstr(argjson,"id")) != 0 )
{
orderid = calc_nxt64bits(orderidstr);
if ( (ap= instantdex_acceptablefind(exchange,0,0,orderid,"*","*")) != 0 )
printf("orderid.%llu\n",(long long)orderid);
if ( (ap= instantdex_acceptablefind(myinfo,exchange,0,0,orderid,"*","*")) != 0 )
{
printf("found existing\n");
A = *ap;
}
} else if ( instantdex_acceptextract(&A,argjson) < 0 )
return(clonestr("{\"error\":\"hash txid mismatches orderid\"}"));
printf("call (%s/%s) swap baserel.%d acceptdir.%d\n",A.A.base,A.A.rel,A.A.myside,A.A.acceptdir);
if ( strncmp(cmdstr,"BTC",3) == 0 )
retstr = instantdex_BTCswap(myinfo,exchange,&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,data,datalen);
else if ( strncmp(cmdstr,"NXT",3) == 0 )
@ -413,20 +461,23 @@ char *instantdex_parse(struct supernet_info *myinfo,struct instantdex_msghdr *ms
retstr = instantdex_ALTswap(myinfo,exchange,&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,data,datalen);
else if ( strncmp(cmdstr,"PAX",3) == 0 )
retstr = instantdex_PAXswap(myinfo,exchanges777_find("PAX"),&A,cmdstr+3,msg,argjson,remoteaddr,signerbits,data,datalen);
else return(clonestr("{\"error\":\"unrecognized atomic swap family\"}"));
if ( ap != 0 )
{
ap->statusjson = A.statusjson;
ap->info = A.info;
ap->pendingvolume64 = A.pendingvolume64;
}
else return(clonestr("{\"error\":\"unrecognized atomic swap family\"}"));
printf("after swap ap.%p (%s)\n",ap,retstr);
return(retstr);
}
return(clonestr("{\"error\":\"request needs argjson\"}"));
}
char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char *remoteaddr)
{
struct instantdex_msghdr *msg = ptr; cJSON *argjson; int32_t n,datalen,newlen,flag = 0;
uint64_t signerbits; uint8_t *data; uint8_t tmp[sizeof(msg->sig)]; char *retstr = 0;
struct instantdex_msghdr *msg = ptr; cJSON *argjson; int32_t i,num,n,datalen,newlen,flag = 0;
uint8_t *data; struct supernet_info *myinfos[64];
uint64_t signerbits; uint8_t tmp[sizeof(msg->sig)]; char *retstr = 0; cJSON *retjson,*item;
acct777_rwsig(0,(void *)&msg->sig,(void *)tmp);
memcpy(&msg->sig,tmp,sizeof(msg->sig));
datalen = len - (int32_t)sizeof(msg->sig);
@ -443,9 +494,11 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char
else if ( (signerbits= acct777_validate(&msg->sig,acct777_msgprivkey(data,datalen),msg->sig.pubkey)) != 0 )
{
flag++;
printf("InstantDEX_hexmsg <<<<<<<<<<<<< sigsize.%ld VALIDATED [%ld] len.%d t%u allocsize.%d (%s) [%d]\n",sizeof(msg->sig),(long)data-(long)msg,datalen,msg->sig.timestamp,msg->sig.allocsize,(char *)msg->serialized,data[datalen-1]);
//printf("InstantDEX_hexmsg <<<<<<<<<<<<< sigsize.%ld VALIDATED [%ld] len.%d t%u allocsize.%d (%s) [%d]\n",sizeof(msg->sig),(long)data-(long)msg,datalen,msg->sig.timestamp,msg->sig.allocsize,(char *)msg->serialized,data[datalen-1]);
if ( data[datalen-1] == 0 && (argjson= cJSON_Parse((char *)msg->serialized)) != 0 )
retstr = instantdex_parse(myinfo,msg,argjson,remoteaddr,signerbits,data,datalen);
{
}
else
{
newlen = (int32_t)(msg->sig.allocsize - sizeof(*msg));
@ -461,8 +514,31 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char
else data = 0;
}
}
if ( data != 0 )
retstr = instantdex_parse(myinfo,msg,argjson,remoteaddr,signerbits,data,newlen);
}
if ( data != 0 || argjson != 0 )
{
printf("CALL instantdex_parse.(%s)\n",argjson!=0?jprint(argjson,0):"");
retjson = cJSON_CreateArray();
if ( (num= SuperNET_MYINFOS(myinfos,sizeof(myinfos)/sizeof(*myinfos))) == 0 )
{
myinfos[0] = myinfo;
num = 1;
}
for (i=0; i<num; i++)
{
myinfo = myinfos[i];
//char str[65]; printf("i.%d of %d: %s\n",i,num,bits256_str(str,myinfo->myaddr.persistent));
if ( (retstr= instantdex_parse(myinfo,msg,argjson,remoteaddr,signerbits,data,newlen)) != 0 )
{
item = cJSON_CreateObject();
jaddstr(item,"result",retstr);
if ( myinfo->handle[0] != 0 )
jaddstr(item,"handle",myinfo->handle);
jaddbits256(item,"traderpub",myinfo->myaddr.persistent);
jaddi(retjson,item);
}
}
retstr = jprint(retjson,1);
}
}
if ( argjson != 0 )
@ -470,9 +546,9 @@ char *InstantDEX_hexmsg(struct supernet_info *myinfo,void *ptr,int32_t len,char
return(retstr);
}
char *instantdex_queueaccept(struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *mysidestr,int32_t duration)
char *instantdex_queueaccept(struct supernet_info *myinfo,struct exchange_info *exchange,char *base,char *rel,double price,double basevolume,int32_t acceptdir,char *mysidestr,int32_t duration)
{
struct instantdex_accept *ap; int32_t myside; struct supernet_info *myinfo = SuperNET_MYINFO(0);
struct instantdex_accept *ap; int32_t myside;
if ( exchange != 0 )
{
ap = calloc(1,sizeof(*ap));
@ -480,7 +556,11 @@ char *instantdex_queueaccept(struct exchange_info *exchange,char *base,char *rel
myside = 0;
else if ( strcmp(mysidestr,rel) == 0 )
myside = 1;
else myside = -1;
else
{
myside = -1;
printf("myside.(%s) != base.%s or rel.%s\n",mysidestr,base,rel);
}
instantdex_acceptset(ap,base,rel,duration,myside,acceptdir,price,basevolume,myinfo->myaddr.nxt64bits);
queue_enqueue("acceptableQ",&exchange->acceptableQ,&ap->DL,0);
return(jprint(instantdex_acceptjson(ap),1));
@ -488,23 +568,41 @@ char *instantdex_queueaccept(struct exchange_info *exchange,char *base,char *rel
else return(clonestr("{\"error\":\"invalid exchange\"}"));
}
void instantdex_update(struct supernet_info *myinfo)
{
struct instantdex_msghdr *pm; struct category_msg *m; bits256 instantdexhash; char *str,remote[64];
instantdexhash = calc_categoryhashes(0,"InstantDEX",0);
while ( (m= category_gethexmsg(myinfo,instantdexhash,GENESIS_PUBKEY)) != 0 )
{
pm = (struct instantdex_msghdr *)m->msg;
if ( m->remoteipbits != 0 )
expand_ipbits(remote,m->remoteipbits);
else remote[0] = 0;
if ( (str= InstantDEX_hexmsg(myinfo,pm,m->len,remote)) != 0 )
free(str);
free(m);
}
}
#include "../includes/iguana_apidefs.h"
TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,maxaccept,base,rel,maxprice,basevolume)
{
myinfo = SuperNET_accountfind(json);
if ( remoteaddr == 0 )
return(instantdex_queueaccept(exchanges777_find("bitcoin"),base,rel,maxprice,basevolume,-1,rel,INSTANTDEX_OFFERDURATION));
return(instantdex_queueaccept(myinfo,exchanges777_find("bitcoin"),base,rel,maxprice,basevolume,-1,rel,INSTANTDEX_OFFERDURATION));
else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}"));
}
TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,minaccept,base,rel,minprice,basevolume)
{
myinfo = SuperNET_accountfind(json);
if ( remoteaddr == 0 )
return(instantdex_queueaccept(exchanges777_find("bitcoin"),base,rel,minprice,basevolume,1,base,INSTANTDEX_OFFERDURATION));
return(instantdex_queueaccept(myinfo,exchanges777_find("bitcoin"),base,rel,minprice,basevolume,1,base,INSTANTDEX_OFFERDURATION));
else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}"));
}
TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,BTCoffer,othercoin,otherassetid,maxprice,othervolume)
/*TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,BTCoffer,othercoin,otherassetid,maxprice,othervolume)
{
if ( remoteaddr == 0 )
return(instantdex_btcoffer(myinfo,exchanges777_find("bitcoin"),othercoin[0] != 0 ? othercoin : otherassetid,othervolume,maxprice));
@ -549,6 +647,6 @@ STRING_AND_TWO_DOUBLES(InstantDEX,NXToffer,assetid,minprice,basevolume)
return(instantdex_sendcmd(myinfo,argjson,"NXToffer",myinfo->ipaddr,hops));
} else return(clonestr("{\"error\":\"InstantDEX API request only local usage!\"}"));
}
*/
#include "../includes/iguana_apiundefs.h"

10
iguana/iguana_recv.c

@ -326,7 +326,7 @@ void iguana_bundlespeculate(struct iguana_info *coin,struct iguana_bundle *bp,in
if ( bp->numhashes < bp->n && bundlei == 0 && bp->speculative == 0 && bp->bundleheight < coin->longestchain-coin->chain->bundlesize )
{
char str[65]; bits256_str(str,bp->hashes[0]);
printf("Afound block -> %d %d hdr.%s\n",bp->bundleheight,coin->longestchain-coin->chain->bundlesize,str);
//printf("Afound block -> %d %d hdr.%s\n",bp->bundleheight,coin->longestchain-coin->chain->bundlesize,str);
queue_enqueue("hdrsQ",&coin->hdrsQ,queueitem(str),1);
}
else if ( bp->speculative != 0 && bundlei < bp->numspec && memcmp(hash2.bytes,bp->speculative[bundlei].bytes,sizeof(hash2)) == 0 )
@ -371,7 +371,7 @@ int32_t iguana_bundleiters(struct iguana_info *coin,struct iguana_bundle *bp,int
if ( pend >= coin->MAXPENDING*coin->MAXPEERS )
{
sleep(10000);
printf("SKIP pend.%d vs %d: ITERATE bundle.%d n.%d r.%d s.%d finished.%d timelimit.%d\n",pend,coin->MAXPENDING*coin->MAXPEERS,bp->bundleheight,bp->n,bp->numrecv,bp->numsaved,bp->emitfinish,timelimit);
//printf("SKIP pend.%d vs %d: ITERATE bundle.%d n.%d r.%d s.%d finished.%d timelimit.%d\n",pend,coin->MAXPENDING*coin->MAXPEERS,bp->bundleheight,bp->n,bp->numrecv,bp->numsaved,bp->emitfinish,timelimit);
iguana_bundleQ(coin,bp,counter == 0 ? bp->n*5 : bp->n*2);
return(0);
}
@ -404,7 +404,7 @@ int32_t iguana_bundleiters(struct iguana_info *coin,struct iguana_bundle *bp,int
break;
usleep(10000);
}
//if ( 0 && counter > 0 )
if ( 0 && counter > 0 )
printf("ITERATE bundle.%d h.%d n.%d r.%d s.%d finished.%d issued.%d\n",bp->bundleheight,bp->numhashes,bp->n,bp->numrecv,bp->numsaved,bp->emitfinish,counter);
if ( bp->emitfinish == 0 )
{
@ -508,14 +508,14 @@ struct iguana_bundlereq *iguana_recvblockhdrs(struct iguana_info *coin,struct ig
firstbp = bp;
if ( bundlei == i+1 && bp == firstbp )
match++;
else printf("recvhdr: ht.%d[%d] vs i.%d\n",bp->bundleheight,bundlei,i);
//else printf("recvhdr: ht.%d[%d] vs i.%d\n",bp->bundleheight,bundlei,i);
}
}
if ( firstbp != 0 && match == coin->chain->bundlesize-1 && n == firstbp->n )
{
if ( firstbp->queued == 0 )
{
printf("firstbp blockQ %d\n",firstbp->bundleheight);
//printf("firstbp blockQ %d\n",firstbp->bundleheight);
iguana_bundleQ(coin,firstbp,1000 + 10*(rand() % (int32_t)(1+sqrt(firstbp->bundleheight))));
}
} else printf("match.%d vs n.%d bp->n.%d ht.%d\n",match,n,firstbp->n,firstbp->bundleheight);

111
iguana/iguana_tx.c

@ -336,4 +336,115 @@ cJSON *iguana_blockjson(struct iguana_info *coin,struct iguana_block *block,int3
return(jprint(retitem,1));
}*/
struct bitcoin_unspent *iguana_bestfit(struct iguana_info *coin,struct bitcoin_unspent *unspents,int32_t numunspents,uint64_t value,int32_t mode)
{
int32_t i; uint64_t above,below,gap,atx_value; struct bitcoin_unspent *vin,*abovevin,*belowvin;
abovevin = belowvin = 0;
for (above=below=i=0; i<numunspents; i++)
{
vin = &unspents[i];
atx_value = vin->value;
//printf("(%.8f vs %.8f)\n",dstr(atx_value),dstr(value));
if ( atx_value == value )
return(vin);
else if ( atx_value > value )
{
gap = (atx_value - value);
if ( above == 0 || gap < above )
{
above = gap;
abovevin = vin;
}
}
else if ( mode == 0 )
{
gap = (value - atx_value);
if ( below == 0 || gap < below )
{
below = gap;
belowvin = vin;
}
}
}
if ( (vin= (abovevin != 0) ? abovevin : belowvin) == 0 && mode == 1 )
vin = unspents;
return(vin);
}
struct bitcoin_unspent *iguana_unspentsget(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *numunspentsp)
{
struct bitcoin_unspent *ups = calloc(1,sizeof(*ups)); //uint8_t addrtype;
// struct bitcoin_unspent { bits256 txid,privkey; uint64_t value; int32_t vout; };
*numunspentsp = 0;
return(ups);
}
struct bitcoin_spend *iguana_spendset(struct supernet_info *myinfo,struct iguana_info *coin,int64_t amount,int64_t txfee)
{
int32_t i,mode,numunspents,maxinputs = 1024; int64_t remains; struct bitcoin_unspent *ptr,*up;
struct bitcoin_unspent *ups; struct bitcoin_spend *spend;
if ( (ups= iguana_unspentsget(myinfo,coin,&numunspents)) == 0 )
return(0);
spend = calloc(1,sizeof(*spend) + sizeof(*spend->inputs) * maxinputs);
spend->txfee = txfee;
remains = txfee + amount;
spend->satoshis = remains;
ptr = spend->inputs;
for (i=0; i<maxinputs; i++,ptr++)
{
for (mode=1; mode>=0; mode--)
if ( (up= iguana_bestfit(coin,ups,numunspents,remains,mode)) != 0 )
break;
if ( up != 0 )
{
spend->input_satoshis += up->value;
spend->inputs[spend->numinputs++] = *up;
if ( spend->input_satoshis >= spend->satoshis )
{
spend->netamount = (spend->input_satoshis - spend->satoshis);
spend->change = (spend->input_satoshis - spend->netamount);
printf("numinputs %d sum %.8f vs amount %.8f change %.8f -> txfee %.8f\n",spend->numinputs,dstr(spend->input_satoshis),dstr(amount),dstr(spend->change),dstr(spend->input_satoshis - spend->change - spend->netamount));
break;
}
remains -= up->value;
} else break;
}
if ( spend->input_satoshis >= spend->satoshis )
{
spend = realloc(spend,sizeof(*spend) + sizeof(*spend->inputs) * spend->numinputs);
return(spend);
}
else
{
free(spend);
return(0);
}
}
cJSON *iguana_signtx(struct iguana_info *coin,bits256 *txidp,char **signedtxp,struct bitcoin_spend *spend,cJSON *txobj)
{
int32_t i,j; char *rawtxstr; struct vin_info V; bits256 txid;
for (i=0; i<spend->numinputs; i++)
bitcoin_addinput(coin,txobj,spend->inputs[i].txid,spend->inputs[i].vout,0xffffffff);
for (i=0; i<spend->numinputs; i++) // N times less efficient, but for small number of inputs ok
{
if ( *signedtxp != 0 )
{
free_json(txobj);
txobj = bitcoin_hex2json(coin,&txid,0,*signedtxp);
free(*signedtxp);
}
if ( (rawtxstr= bitcoin_json2hex(coin,&txid,txobj)) != 0 )
{
memset(&V,0,sizeof(V));
for (j=0; j<sizeof(spend->inputs[i].privkeys)/sizeof(*spend->inputs[i].privkeys); j++)
if ( bits256_nonz(spend->inputs[i].privkeys[j]) > 0 )
V.signers[j].privkey = spend->inputs[i].privkeys[j];
bitcoin_verifytx(coin,txidp,signedtxp,rawtxstr,&V);
free(rawtxstr);
} else break;
}
if ( *signedtxp != 0 && i != spend->numinputs )
free(*signedtxp), *signedtxp = 0;
return(txobj);
}

60
iguana/main.c

@ -38,7 +38,7 @@ struct iguana_info *Coins[IGUANA_MAXCOINS];
int32_t USE_JAY,FIRST_EXTERNAL,IGUANA_disableNXT,Debuglevel;
uint32_t prices777_NXTBLOCK,MAX_DEPTH = 100;
queue_t helperQ,jsonQ,finishedQ,bundlesQ;
struct supernet_info MYINFO;
struct supernet_info MYINFO,**MYINFOS;
static int32_t initflag;
cJSON *API_json;
#ifdef __linux__
@ -107,6 +107,45 @@ struct supernet_info *SuperNET_MYINFO(char *passphrase)
return(0);
}
struct supernet_info *SuperNET_MYINFOfind(int32_t *nump,bits256 pubkey)
{
int32_t i;
*nump = 0;
if ( MYINFOS != 0 )
{
for (i=0; MYINFOS[i]!=0; i++)
{
*nump = i;
if ( bits256_cmp(pubkey,MYINFOS[i]->myaddr.persistent) == 0 )
return(MYINFOS[i]);
}
*nump = i;
}
return(0);
}
int32_t SuperNET_MYINFOS(struct supernet_info **myinfos,int32_t max)
{
int32_t i;
for (i=0; i<max; i++)
if ( (myinfos[i]= MYINFOS[i]) == 0 )
break;
return(i);
}
void SuperNET_MYINFOadd(struct supernet_info *myinfo)
{
int32_t num;
if ( SuperNET_MYINFOfind(&num,myinfo->myaddr.persistent) == 0 )
{
MYINFOS = realloc(MYINFOS,(num + 2) * sizeof(*MYINFOS));
char str[65]; printf("MYNFOadd[%d] <- %s\n",num,bits256_str(str,myinfo->myaddr.persistent));
MYINFOS[num] = calloc(1,sizeof(*myinfo));
*MYINFOS[num] = *myinfo;
MYINFOS[++num] = 0;
}
}
char *iguana_JSON(char *jsonstr)
{
char *retstr=0; cJSON *json;
@ -205,7 +244,7 @@ char *SuperNET_processJSON(struct supernet_info *myinfo,cJSON *json,char *remote
timeout = IGUANA_JSONTIMEOUT;
if ( (method= jstr(json,"method")) != 0 && strcmp(method,"DHT") == 0 && remoteaddr != 0 )
{
SuperNET_hexmsgprocess(myinfo,json,jstr(json,"hexmsg"),remoteaddr);
SuperNET_hexmsgprocess(myinfo,0,json,jstr(json,"hexmsg"),remoteaddr);
return(clonestr("{\"result\":\"processed remote DHT\"}"));
}
jsonstr = jprint(json,0);
@ -1102,16 +1141,21 @@ void iguana_main(void *arg)
char *str;
strcpy(MYINFO.rpcsymbol,"BTCD");
iguana_launchcoin(MYINFO.rpcsymbol,cJSON_Parse("{}"));
if ( 1 && (str= SuperNET_JSON(&MYINFO,cJSON_Parse("{\"wallet\":\"password\",\"agent\":\"iguana\",\"method\":\"addcoin\",\"services\":128,\"maxpeers\":3,\"newcoin\":\"BTCD\",\"active\":0}"),0)) != 0 )
if ( 1 && (str= SuperNET_JSON(&MYINFO,cJSON_Parse("{\"agent\":\"iguana\",\"method\":\"addcoin\",\"services\":128,\"maxpeers\":3,\"newcoin\":\"BTCD\",\"active\":0}"),0)) != 0 )
{
printf("got.(%s)\n",str);
free(str);
if ( (str= SuperNET_JSON(&MYINFO,cJSON_Parse("{\"agent\":\"iguana\",\"method\":\"addcoin\",\"services\":128,\"maxpeers\":3,\"newcoin\":\"BTC\",\"active\":0}"),0)) != 0 )
{
free(str);
if ( 0 && (str= SuperNET_JSON(&MYINFO,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"alice\",\"password\":\"alice\",\"passphrase\":\"alice\"}"),0)) != 0 )
{
free(str);
if ( (str= SuperNET_JSON(&MYINFO,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"bob\",\"password\":\"bob\",\"passphrase\":\"bob\"}"),0)) != 0 )
free(str);
}
}
}
sleep(1);
static bits256 txid;
bitcoin_txtest(iguana_coinfind(MYINFO.rpcsymbol),"000",txid);
//getchar();
#endif
}
if ( arg != 0 )

12
iguana/pangea_api.c

@ -263,7 +263,7 @@ char *pangea_jsondatacmd(struct supernet_info *myinfo,bits256 tablehash,struct p
{
printf("pangea send.(%s)\n",cmdstr);
init_hexbytes_noT(hexstr,(uint8_t *)pm,pm->sig.allocsize);
return(SuperNET_categorymulticast(myinfo,0,pangeahash,tablehash,hexstr,0,2,1));
return(SuperNET_categorymulticast(myinfo,0,pangeahash,tablehash,hexstr,0,2,1,argjson,0));
}
else
{
@ -291,7 +291,7 @@ void pangea_sendcmd(struct supernet_info *myinfo,struct table_info *tp,char *cmd
loopback = 1;
if ( destplayer < 0 )
{
if ( (str= SuperNET_categorymulticast(myinfo,0,tp->G.gamehash,tp->G.tablehash,hexstr,0,2,plaintext)) != 0 )
if ( (str= SuperNET_categorymulticast(myinfo,0,tp->G.gamehash,tp->G.tablehash,hexstr,0,2,plaintext,0,0)) != 0 )
free(str);
loopback = 1;
}
@ -541,16 +541,16 @@ char *pangea_hexmsg(struct supernet_info *myinfo,void *data,int32_t len,char *re
void pangea_update(struct supernet_info *myinfo)
{
struct pangea_msghdr *pm; struct category_msg *m; bits256 pangeahash; char remoteaddr[64];
struct pangea_msghdr *pm; struct category_msg *m; bits256 pangeahash; char remoteaddr[64],*str;
pangeahash = calc_categoryhashes(0,"pangea",0);
while ( (m= category_gethexmsg(myinfo,pangeahash,GENESIS_PUBKEY)) != 0 )
{
pm = (struct pangea_msghdr *)m->msg;
if ( m->remoteipbits != 0 )
expand_ipbits(remoteaddr,m->remoteipbits);
if ( pangea_hexmsg(myinfo,pm,m->len,remoteaddr) > 0 )
{
}
else remoteaddr[0] = 0;
if ( (str= pangea_hexmsg(myinfo,pm,m->len,remoteaddr)) != 0 )
free(str);
free(m);
}
}

12
iguana/pnacl/Release/iguana.nmf

@ -0,0 +1,12 @@
{
"program": {
"portable": {
"pnacl-translate": {
"url": "iguana.pexe"
},
"pnacl-debug": {
"url": "iguana_unstripped.bc"
}
}
}
}

BIN
iguana/pnacl/Release/iguana.pexe

Binary file not shown.

827
iguana/swaps/iguana_BTCswap.c

@ -14,23 +14,117 @@
******************************************************************************/
#include "../exchanges/bitcoin.h"
/* https://bitcointalk.org/index.php?topic=1340621.msg13828271#msg13828271
Tier Nolan's approach is followed with the following changes:
a) instead of cutting 1000 keypairs, only 777 are a
b) instead of sending the entire 256 bits, it is truncated to 64 bits. With odds of collision being so low, it is dwarfed by the ~0.1% insurance factor.
c) D is set to 100x the insurance rate of 1/777 12.87% + BTC amount
d) insurance is added to Bob's payment, which is after the deposit and bailin
e) BEFORE Bob broadcasts deposit, Alice broadcasts BTC denominated fee in cltv so if trade isnt done fee is reclaimed
*/
#define INSTANTDEX_INSURANCERATE (1. / 777.)
#define INSTANTDEX_PUBEY "03bc2c7ba671bae4a6fc835244c9762b41647b9827d4780a89a949b984a8ddcc06"
#define INSTANTDEX_RMD160 "ca1e04745e8ca0c60d8c5881531d51bec470743f"
#define TIERNOLAN_RMD160 "daedddd8dbe7a2439841ced40ba9c3d375f98146"
#define INSTANTDEX_BTC "1KRhTPvoxyJmVALwHFXZdeeWFbcJSbkFPu"
#define INSTANTDEX_BTCD "RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf"
struct bitcoin_swapinfo
{
bits256 privkeys[777],mypubs[2],otherpubs[2],pubBn,pubAm,dtxid,ptxid,aptxid,astxid,stxid,ftxid;
uint64_t otherscut[777][2];
int32_t isbob,choosei,otherschoosei,state,cutverified,otherverifiedcut;
char altmsigaddr[64],*deposit,*payment,*altpayment,*altspend,*spendtx,*feetx;
};
int32_t instantdex_outputinsurance(struct iguana_info *coin,cJSON *txobj,int64_t insurance,uint64_t nonce)
{
uint8_t rmd160[20],script[128]; int32_t n;
decode_hex(rmd160,sizeof(rmd160),(nonce % 10) == 0 ? TIERNOLAN_RMD160 : INSTANTDEX_RMD160);
n = bitcoin_standardspend(script,0,rmd160);
bitcoin_addoutput(coin,txobj,script,n,insurance);
return(n);
}
/*
bitcoin_pubkey33(pubkey,myinfo->persistent_priv);
bitcoin_address(coinaddr,other->chain->pubtype,pubkey,sizeof(pubkey));
bitcoin_addr2rmd160(&addrtype,secret160,coinaddr);
scriptlen = bitcoin_cltvscript(coinbtc->chain->p2shtype,p2sh_coinaddr,p2sh_rmd160,script,0,senderaddr,otheraddr,secret160,locktime);
if ( jobj(argjson,"p2sh") != 0 )
Alice fee:
OP_IF
<now + 1 days> OP_CLTV OP_DROP INSTANTDEX OP_CHECKSIG
OP_ELSE
<now + 2 days> OP_CLTV OP_DROP OP_HASH160 <hash(alice_priv_m)> OP_EQUALVERIFY <alice_pub_key_1001> OP_CHECKSIG
OP_ENDIF
Bob deposit:
instantdex_bobscript(script,0,(uint32_t)(time(NULL)+INSTANTDEX_LOCKTIME*2),pubA0,privBn,pubB0);
OP_IF
<now + 2 days> OP_CLTV OP_DROP <alice_pub_1001> OP_CHECKSIG
OP_ELSE
OP_HASH160 <hash(bob_priv_n)> OP_EQUALVERIFY <bob_pub_1001> OP_CHECKSIG
OP_ENDIF
Bobpays:
instantdex_bobscript(script,0,(uint32_t)(time(NULL)+INSTANTDEX_LOCKTIME),pubB1,privAm,pubA0);
OP_IF
<now + 1 day> OP_CLTV OP_DROP <bob_pub_1002> OP_CHECKSIG
OP_ELSE
OP_HASH160 <hash(alice_priv_m)> OP_EQUALVERIFY <alice_pub_key_1001> OP_CHECKSIG
OP_ENDIF
*/
int32_t instantdex_bobscript(uint8_t *script,int32_t n,int32_t *secretstartp,uint32_t locktime,bits256 cltvpub,uint8_t secret160[20],bits256 destpub)
{
if ( strcmp(jstr(argjson,"p2sh"),p2sh_coinaddr) != 0 )
uint8_t pubkeyA[33],pubkeyB[33];
memcpy(pubkeyA+1,cltvpub.bytes,sizeof(cltvpub)), pubkeyA[0] = 0x02;
memcpy(pubkeyB+1,destpub.bytes,sizeof(destpub)), pubkeyB[0] = 0x03;
script[n++] = SCRIPT_OP_IF;
n = bitcoin_checklocktimeverify(script,n,locktime);
n = bitcoin_pubkeyspend(script,n,pubkeyA);
script[n++] = SCRIPT_OP_ELSE;
if ( secretstartp != 0 )
*secretstartp = n + 2;
n = bitcoin_revealsecret160(script,n,secret160);
n = bitcoin_pubkeyspend(script,n,pubkeyB);
script[n++] = SCRIPT_OP_ENDIF;
return(n);
}
// OP_2 <alice_pub_m> <bob_pub_n> OP_2 OP_CHECKMULTISIG
int32_t instantdex_alicescript(uint8_t *script,int32_t n,char *msigaddr,uint8_t altps2h,bits256 pubAm,bits256 pubBn)
{
uint8_t p2sh160[20]; struct vin_info V;
memset(&V,0,sizeof(V));
memcpy(&V.signers[0].pubkey[1],pubAm.bytes,sizeof(pubAm)), V.signers[0].pubkey[0] = 0x02;
memcpy(&V.signers[1].pubkey[1],pubBn.bytes,sizeof(pubBn)), V.signers[1].pubkey[0] = 0x03;
V.M = V.N = 2;
n = bitcoin_MofNspendscript(p2sh160,script,n,&V);
bitcoin_address(msigaddr,altps2h,p2sh160,sizeof(p2sh160));
return(n);
}
char *instantdex_bobtx(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,bits256 pubA0,bits256 pubB0,bits256 privBn,uint32_t reftime,int64_t amount,int32_t depositflag)
{
cJSON *txobj; int32_t n,secretstart; char *signedtx = 0;
uint8_t script[1024],secret[20]; struct bitcoin_spend *spend; int64_t insurance; uint32_t locktime;
locktime = (uint32_t)(reftime + INSTANTDEX_LOCKTIME * (1 + depositflag));
txobj = bitcoin_createtx(coin,locktime);
insurance = (amount * INSTANTDEX_INSURANCERATE + coin->chain->txfee); // txfee prevents dust attack
if ( (spend= iguana_spendset(myinfo,coin,amount + insurance,coin->chain->txfee)) != 0 )
{
printf("mismatched p2sh.(%s) vs (%s)\n",jstr(argjson,"p2sh"),p2sh_coinaddr);
return(clonestr("{\"error\":\"instantdex_BTCswap base or rel mismatch\"}"));
calc_rmd160_sha256(secret,privBn.bytes,sizeof(privBn));
n = instantdex_bobscript(script,0,&secretstart,locktime,pubA0,secret,pubB0);
bitcoin_addoutput(coin,txobj,script,n,amount + depositflag*insurance*100);
if ( depositflag == 0 )
instantdex_outputinsurance(coin,txobj,insurance,pubB0.txid);
txobj = iguana_signtx(coin,txidp,&signedtx,spend,txobj);
if ( signedtx != 0 )
printf("bob deposit.%s\n",signedtx);
else printf("error signing bobdeposit numinputs.%d\n",spend->numinputs);
free(spend);
}
free_json(txobj);
return(signedtx);
}
*/
#define INSTANTDEX_DONATION 2000
// https://github.com/TierNolan/bips/blob/bip4x/bip-atom.mediawiki
uint64_t instantdex_relsatoshis(uint64_t price,uint64_t volume)
{
@ -39,143 +133,580 @@ uint64_t instantdex_relsatoshis(uint64_t price,uint64_t volume)
else return(dstr(price) * volume);
}
int32_t instantdex_paymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,struct instantdex_accept *A,cJSON *argjson,int32_t depositflag)
{
cJSON *txobj; bits256 txid; uint32_t n,locktime; int32_t i,secretstart,retval = -1; uint64_t x;
struct iguana_msgtx msgtx; uint8_t script[512],rmd160[20]; int64_t insurance,relsatoshis,amount;
if ( jstr(argjson,depositflag != 0 ? "deposit" : "payment") != 0 )
{
relsatoshis = instantdex_relsatoshis(A->A.price64,A->A.basevolume64);
insurance = (relsatoshis * INSTANTDEX_INSURANCERATE + coin->chain->txfee); // txfee prevents dust attack
if ( depositflag != 0 )
{
swap->deposit = clonestr(jstr(argjson,"deposit"));
swap->dtxid = jbits256(argjson,"dtxid");
swap->pubBn = jbits256(argjson,"pubBn");
insurance *= 100;
}
amount = relsatoshis + insurance;
if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->deposit)) != 0 )
{
locktime = A->A.expiration;
if ( depositflag == 0 )
memset(rmd160,0,sizeof(rmd160));
else calc_rmd160_sha256(rmd160,swap->privkeys[0].bytes,sizeof(rmd160));
n = instantdex_bobscript(script,0,&secretstart,locktime,swap->mypubs[0],rmd160,swap->otherpubs[0]);
if ( msgtx.lock_time == locktime && msgtx.vouts[0].value == amount && n == msgtx.vouts[0].pk_scriptlen )
{
memcpy(&script[secretstart],&msgtx.vouts[0].pk_script[secretstart],20);
if ( memcmp(script,msgtx.vouts[0].pk_script,n) == 0 )
{
iguana_rwnum(0,&script[secretstart],sizeof(x),&x);
printf("deposit script verified x.%llx vs otherscut %llx\n",(long long)x,(long long)swap->otherscut[swap->choosei][0]);
if ( x == swap->otherscut[swap->choosei][0] )
{
if ( depositflag == 0 )
{
decode_hex(rmd160,sizeof(rmd160),(swap->otherpubs[0].txid % 10) == 0 ? TIERNOLAN_RMD160 : INSTANTDEX_RMD160);
n = bitcoin_standardspend(script,0,rmd160);
if ( msgtx.vouts[1].value == insurance && n == msgtx.vouts[1].pk_scriptlen && memcmp(script,msgtx.vouts[1].pk_script,n) == 0 )
retval = 0;
} else retval = 0;
}
else printf("deposit script verified but secret mismatch x.%llx vs otherscut %llx\n",(long long)x,(long long)swap->otherscut[swap->choosei][0]);
}
else
{
for (i=0; i<n; i++)
printf("%02x ",script[i]);
printf("script\n");
for (i=0; i<n; i++)
printf("%02x ",msgtx.vouts[0].pk_script[i]);
printf("deposit\n");
}
}
free_json(txobj);
}
}
return(retval);
}
char *instantdex_alicetx(struct supernet_info *myinfo,struct iguana_info *altcoin,char *msigaddr,bits256 *txidp,bits256 pubAm,bits256 pubBn,int64_t amount)
{
cJSON *txobj; int32_t n; char *signedtx = 0;
uint8_t script[1024]; struct bitcoin_spend *spend; int64_t insurance;
txobj = bitcoin_createtx(altcoin,0);
insurance = (amount * INSTANTDEX_INSURANCERATE + altcoin->chain->txfee); // txfee prevents dust attack
if ( (spend= iguana_spendset(myinfo,altcoin,amount + insurance,altcoin->chain->txfee)) != 0 )
{
//instantdex_outputinsurance(altcoin,txobj,insurance);
n = instantdex_alicescript(script,0,msigaddr,altcoin->chain->p2shtype,pubAm,pubBn);
bitcoin_addoutput(altcoin,txobj,script,n,amount);
txobj = iguana_signtx(altcoin,txidp,&signedtx,spend,txobj);
if ( signedtx != 0 )
printf("alice payment.%s\n",signedtx);
else printf("error signing alicetx numinputs.%d\n",spend->numinputs);
free(spend);
}
free_json(txobj);
return(signedtx);
}
int32_t instantdex_altpaymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct bitcoin_swapinfo *swap,struct instantdex_accept *A,cJSON *argjson)
{
cJSON *txobj; bits256 txid; uint32_t n; int32_t i,retval = -1;
struct iguana_msgtx msgtx; uint8_t script[512]; char *altmsigaddr,msigaddr[64];
if ( jstr(argjson,"altpayment") != 0 && (altmsigaddr= jstr(argjson,"altmsigaddr")) != 0 )
{
swap->altpayment = clonestr(jstr(argjson,"altpayment"));
swap->aptxid = jbits256(argjson,"aptxid");
swap->pubAm = jbits256(argjson,"pubAm");
if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->altpayment)) != 0 )
{
n = instantdex_alicescript(script,0,msigaddr,coin->chain->p2shtype,swap->pubAm,swap->pubBn);
if ( strcmp(msigaddr,altmsigaddr) == 0 && n == msgtx.vouts[0].pk_scriptlen )
{
if ( memcmp(script,msgtx.vouts[0].pk_script,n) == 0 )
{
printf("deposit script verified\n");
}
else
{
for (i=0; i<n; i++)
printf("%02x ",script[i]);
printf("altscript\n");
for (i=0; i<n; i++)
printf("%02x ",msgtx.vouts[0].pk_script[i]);
printf("altpayment\n");
}
}
free_json(txobj);
}
}
return(retval);
}
void instantdex_pendingnotice(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,struct instantdex_accept *A)
{
printf("need to start monitoring thread\n");
ap->pendingvolume64 -= A->A.basevolume64;
}
bits256 instantdex_sharedpub256(bits256 *sharedprivp,uint8_t pubkey[33],bits256 privkey,bits256 hash,int32_t n)
{
bits256 shared,iters; int32_t i;
bits256 shared,iters;
iters = shared = curve25519_shared(privkey,hash);
for (i=0; i<n; i++)
iters = curve25519(iters,curve25519(iters,curve25519_basepoint9()));
iters = curve25519(iters,curve25519(iters,curve25519_basepoint9()));
vcalc_sha256cat(sharedprivp->bytes,shared.bytes,sizeof(shared),iters.bytes,sizeof(iters));
return(bitcoin_pubkey33(pubkey,*sharedprivp));
}
int32_t instantdex_pubkeyargs(bits256 *sharedprivs,cJSON *argjson,int32_t numpubs,bits256 privkey,bits256 hash,int32_t firstbyte)
int32_t instantdex_pubkeyargs(bits256 *sharedprivs,cJSON *newjson,int32_t numpubs,bits256 privkey,bits256 hash,int32_t firstbyte)
{
char buf[3]; int32_t i,n; bits256 tmp; uint8_t pubkey[33];
char buf[3],*hexstr=0; int32_t i,n,len=0; bits256 pubi; uint64_t txid; uint8_t secret160[20],pubkey[33],*hex=0;
if ( numpubs > 2 )
{
if ( (hexstr= malloc(777 * sizeof(uint64_t) * 2 * 2 + 1)) == 0 )
return(-1);
if ( (hex= malloc(777 * sizeof(uint64_t) * 2)) == 0 )
return(-1);
}
sprintf(buf,"%c0",'A' - 0x02 + firstbyte);
for (i=n=0; i<numpubs*100&&n<numpubs; i++)
for (i=n=0; i<numpubs*100 && n<numpubs; i++)
{
tmp = instantdex_sharedpub256(&sharedprivs[n],pubkey,privkey,hash,i+1);
pubi = instantdex_sharedpub256(&sharedprivs[n],pubkey,privkey,hash,i+1);
privkey = sharedprivs[n];
//printf("i.%d n.%d numpubs.%d %02x vs %02x\n",i,n,numpubs,pubkey[0],firstbyte);
if ( pubkey[0] != firstbyte )
continue;
buf[1] = '0' + n++;
jaddbits256(argjson,buf,tmp);
if ( n < 2 && numpubs > 2 )
{
sprintf(buf+1,"%d",n);
jaddbits256(newjson,buf,pubi);
}
else
{
calc_rmd160_sha256(secret160,sharedprivs[n].bytes,sizeof(sharedprivs[n]));
memcpy(&txid,secret160,sizeof(txid));
len += iguana_rwnum(1,&hex[len],sizeof(txid),&txid);
len += iguana_rwnum(1,&hex[len],sizeof(pubi.txid),&pubi.txid);
}
n++;
}
if ( n > 2 && newjson != 0 && len > 0 )
{
init_hexbytes_noT(hexstr,hex,len);
jaddstr(newjson,"cut",hexstr);
}
if ( hex != 0 )
free(hex);
if ( hexstr != 0 )
free(hexstr);
return(n);
}
int32_t bitcoin_2of2spendscript(int32_t *paymentlenp,uint8_t *paymentscript,uint8_t *msigscript,bits256 pub0,bits256 pub1)
char *instantdex_choosei(struct bitcoin_swapinfo *swap,cJSON *newjson,cJSON *argjson)
{
struct vin_info V; uint8_t p2sh_rmd160[20]; int32_t p2shlen;
memset(&V,0,sizeof(V));
V.M = V.N = 2;
memcpy(V.signers[0].pubkey+1,pub0.bytes,sizeof(pub0)), V.signers[0].pubkey[0] = 0x02;
memcpy(V.signers[1].pubkey+1,pub1.bytes,sizeof(pub1)), V.signers[1].pubkey[0] = 0x03;
p2shlen = bitcoin_MofNspendscript(p2sh_rmd160,msigscript,0,&V);
*paymentlenp = bitcoin_p2shspend(paymentscript,0,p2sh_rmd160);
return(p2shlen);
char *cutstr; int32_t i,j,max,len = 0; uint64_t x;
if ( swap->choosei < 0 && (cutstr= jstr(argjson,"cut")) != 0 )
{
max = (int32_t)(sizeof(swap->otherscut) / sizeof(*swap->otherscut));
if ( strlen(cutstr) == sizeof(swap->otherscut)*2 )
{
decode_hex((uint8_t *)swap->otherscut,sizeof(swap->otherscut),cutstr);
for (i=0; i<max; i++)
for (j=0; j<2; j++)
{
len += iguana_rwnum(1,(uint8_t *)&swap->otherscut[i][j],sizeof(x),&x);
swap->otherscut[i][j] = x;
}
} else return(clonestr("{\"error\":\"instantdex_BTCswap offer wrong cutsize\"}"));
OS_randombytes((uint8_t *)&swap->choosei,sizeof(swap->choosei));
swap->choosei %= max;
jaddnum(newjson,"mychoosei",swap->choosei);
return(0);
} else return(clonestr("{\"error\":\"instantdex_BTCswap offer no cut\"}"));
}
void instantdex_getpubs(struct bitcoin_swapinfo *swap,cJSON *argjson,cJSON *newjson)
{
char fields[2][2][3]; int32_t i,j,myind,otherind;
memset(fields,0,sizeof(fields));
fields[0][0][0] = fields[0][1][0] = 'A';
fields[1][0][0] = fields[1][1][0] = 'B';
for (i=0; i<2; i++)
for (j=0; j<2; j++)
fields[i][j][1] = '0' + j;
myind = swap->isbob;
otherind = (myind ^ 1);
for (j=0; j<2; j++)
{
if ( bits256_nonz(swap->mypubs[j]) == 0 && jobj(argjson,fields[myind][j]) != 0 )
swap->mypubs[j] = jbits256(newjson,fields[myind][j]);
if ( bits256_nonz(swap->otherpubs[j]) == 0 && jobj(argjson,fields[otherind][j]) != 0 )
swap->otherpubs[j] = jbits256(argjson,fields[otherind][j]);
}
}
struct bitcoin_unspent *instantdex_bestfit(struct iguana_info *coin,struct bitcoin_unspent *unspents,int32_t numunspents,uint64_t value,int32_t mode)
cJSON *instantdex_newjson(struct supernet_info *myinfo,struct bitcoin_swapinfo *swap,cJSON *argjson,bits256 hash,struct instantdex_accept *A,int32_t flag777,int32_t sendprivs)
{
int32_t i; uint64_t above,below,gap,atx_value; struct bitcoin_unspent *vin,*abovevin,*belowvin;
abovevin = belowvin = 0;
for (above=below=i=0; i<numunspents; i++)
{
vin = &unspents[i];
atx_value = vin->value;
//printf("(%.8f vs %.8f)\n",dstr(atx_value),dstr(value));
if ( atx_value == value )
return(vin);
else if ( atx_value > value )
cJSON *newjson; char serstr[sizeof(bits256)*2+1],*hexstr=0; int32_t i,wrongfirstbyte,errs;
bits256 hashpriv,pubi,otherpriv,*privs=0; uint8_t serialized[sizeof(bits256)],otherpubkey[33];
newjson = instantdex_acceptsendjson(A);
printf("acceptsend.(%s)\n",jprint(newjson,0));
if ( swap->otherschoosei < 0 && jobj(argjson,"mychoosei") != 0 )
{
printf("otherschoosei.%d\n",swap->otherschoosei);
if ( (swap->otherschoosei= juint(argjson,"mychoosei")) >= sizeof(swap->otherscut)/sizeof(*swap->otherscut) )
swap->otherschoosei = -1;
}
if ( juint(argjson,"verified") != 0 )
swap->otherverifiedcut = 1;
printf("otherverified.%d\n",swap->otherverifiedcut);
if ( jobj(argjson,"myprivs") != 0 && swap->cutverified == 0 )
{
printf("got privs\n");
if ( (privs= calloc(1,sizeof(*swap->privkeys))) == 0 )
printf("instantdex_newjson couldnt allocate hex\n");
else if ( (hexstr= jstr(argjson,"myprivs")) == 0 || strlen(hexstr) != sizeof(swap->privkeys)*2 )
printf("instantdex_newjson other's privkeys wrong size\n");
else
{
gap = (atx_value - value);
if ( above == 0 || gap < above )
for (i=wrongfirstbyte=errs=0; i<sizeof(swap->privkeys)/sizeof(*swap->privkeys); i++)
{
above = gap;
abovevin = vin;
memcpy(serstr,&hexstr[i * sizeof(bits256)],sizeof(bits256));
decode_hex(serialized,sizeof(bits256),serstr);
iguana_rwbignum(0,serialized,sizeof(otherpriv),otherpriv.bytes);
if ( i == swap->choosei )
{
if ( bits256_nonz(otherpriv) != 0 )
{
printf("got privkey in slot.%d my choosi??\n",i);
errs++;
}
continue;
}
pubi = bitcoin_pubkey33(otherpubkey,otherpriv);
vcalc_sha256(0,hashpriv.bytes,otherpriv.bytes,sizeof(otherpriv));
if ( otherpubkey[0] != (swap->isbob ^ 1) + 0x02 )
{
wrongfirstbyte++;
printf("wrongfirstbyte[%d] %02x\n",i,otherpubkey[0]);
}
else if ( swap->otherscut[i][0] != hashpriv.txid )
{
printf("otherscut[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherscut[i][0],(long long)hashpriv.txid);
errs++;
}
else if ( swap->otherscut[i][1] != pubi.txid )
{
printf("otherscut[%d] priv mismatch %llx != %llx\n",i,(long long)swap->otherscut[i][1],(long long)pubi.txid);
errs++;
}
}
if ( errs == 0 && wrongfirstbyte == 0 )
swap->cutverified = 1;
else printf("failed verification: wrong firstbyte.%d errs.%d\n",wrongfirstbyte,errs);
}
else if ( mode == 0 )
}
jaddnum(newjson,"verified",swap->otherverifiedcut);
printf("otherverified.%d\n",swap->otherverifiedcut);
if ( instantdex_pubkeyargs(swap->privkeys,newjson,2+flag777*777,myinfo->persistent_priv,hash,0x02 + swap->isbob) != 2+flag777*777 )
{
printf("error generating pubkeyargs\n");
return(0);
}
printf("call getpubs\n");
instantdex_getpubs(swap,argjson,newjson);
if ( sendprivs != 0 )
{
printf("sendprivs.%d\n",sendprivs);
if ( swap->otherschoosei < 0 )
printf("instantdex_newjson otherschoosei < 0 when sendprivs != 0\n");
else
{
gap = (value - atx_value);
if ( below == 0 || gap < below )
if ( privs == 0 && (privs= calloc(1,sizeof(*swap->privkeys))) == 0 )
printf("instantdex_newjson couldnt allocate hex\n");
else if ( hexstr == 0 && (hexstr= malloc(sizeof(*swap->privkeys) * 2 + 1)) == 0 )
printf("instantdex_newjson couldnt allocate hexstr\n");
else
{
below = gap;
belowvin = vin;
memcpy(privs,swap->privkeys,sizeof(*swap->privkeys));
memset(privs[swap->otherschoosei].bytes,0,sizeof(*privs));
for (i=0; i<sizeof(swap->privkeys)/sizeof(*swap->privkeys); i++)
{
iguana_rwbignum(1,serialized,sizeof(privs[i]),privs[i].bytes);
memcpy(privs[i].bytes,serialized,sizeof(privs[i]));
}
init_hexbytes_noT(hexstr,privs[0].bytes,sizeof(swap->privkeys));
jaddstr(newjson,"myprivs",hexstr);
}
}
}
if ( (vin= (abovevin != 0) ? abovevin : belowvin) == 0 && mode == 1 )
vin = unspents;
return(vin);
if ( privs != 0 )
free(privs);
if ( hexstr != 0 )
free(hexstr);
return(newjson);
}
struct bitcoin_unspent *iguana_unspentsget(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *numunspentsp)
char *instantdex_btcoffer(struct supernet_info *myinfo,struct exchange_info *exchange,char *othercoin,double othervolume,double price,int32_t dir) // Bob sending to network (Alice)
{
struct bitcoin_unspent *ups = calloc(1,sizeof(*ups)); //uint8_t addrtype;
// struct bitcoin_unspent { bits256 txid,privkey; uint64_t value; int32_t vout; };
*numunspentsp = 0;
return(ups);
char *str; struct iguana_info *other; int32_t isbob = 1; struct bitcoin_swapinfo *swap;
struct instantdex_accept checkA,A,*ap = 0; cJSON *newjson; bits256 hash;
if ( othercoin == 0 || (other= iguana_coinfind(othercoin)) == 0 )
return(clonestr("{\"error\":\"invalid othercoin\"}"));
hash = instantdex_acceptset(&A,othercoin,"BTC",INSTANTDEX_LOCKTIME*2,dir < 0 ? 1 : 0,-dir,price,othervolume,myinfo->myaddr.nxt64bits);
newjson = instantdex_acceptsendjson(&A);
if ( instantdex_acceptextract(&checkA,newjson) < 0 )
{
int32_t i;
for (i=0; i<sizeof(A); i++)
printf("%02x ",((uint8_t *)&A)[i]);
printf("instantdex_btcoffer checkA error\n");
}
swap = calloc(1,sizeof(struct bitcoin_swapinfo)), swap->isbob = dir > 0, swap->choosei = swap->otherschoosei = -1;
if ( instantdex_pubkeyargs(swap->privkeys,newjson,777+2,myinfo->persistent_priv,hash,0x02+isbob) != 4 )
return(clonestr("{\"error\":\"highly unlikely run of 02 pubkeys\"}"));
if ( price > SMALLVAL )
{
if ( dir > 0 && (str= InstantDEX_maxaccept(myinfo,0,newjson,0,othercoin,"BTC",price,othervolume)) != 0 )
free(str);
else if ( dir < 0 && (str= InstantDEX_minaccept(myinfo,0,newjson,0,othercoin,"BTC",price,othervolume)) != 0 )
free(str);
if ( (ap= instantdex_acceptablefind(myinfo,exchange,0,0,A.orderid,"*","*")) != 0 )
{
swap->state++;
ap->info = swap;
}
}
if ( ap == 0 )
{
printf("couldnt find accept??\n");
free(swap);
return(clonestr("{\"error\":\"couldnt find order just created\"}"));
} else return(instantdex_sendcmd(myinfo,newjson,"BTCoffer",myinfo->ipaddr,INSTANTDEX_HOPS));
}
struct bitcoin_spend *instantdex_spendset(struct supernet_info *myinfo,struct iguana_info *coin,uint64_t satoshis,uint64_t donation)
char *instantdex_BTCswap(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *A,char *cmdstr,struct instantdex_msghdr *msg,cJSON *argjson,char *remoteaddr,uint64_t signerbits,uint8_t *data,int32_t datalen) // receiving side
{
int32_t i,mode,numunspents,maxinputs = 1024; int64_t remains; struct bitcoin_unspent *ptr,*up;
struct bitcoin_unspent *ups; struct bitcoin_spend *spend;
if ( (ups= iguana_unspentsget(myinfo,coin,&numunspents)) == 0 )
return(0);
spend = calloc(1,sizeof(*spend) + sizeof(*spend->inputs) * maxinputs);
spend->satoshis = satoshis;
spend->txfee = coin->chain->txfee;
if ( strcmp(coin->symbol,"BTC") == 0 )
remains = spend->txfee + spend->satoshis + donation;
ptr = spend->inputs;
for (i=0; i<maxinputs; i++,ptr++)
{
for (mode=1; mode>=0; mode--)
if ( (up= instantdex_bestfit(coin,ups,numunspents,remains,mode)) != 0 )
break;
if ( up != 0 )
char *retstr=0; uint64_t satoshis[2]; int32_t reftime,offerdir = 0;
struct instantdex_accept *ap; struct bitcoin_swapinfo *swap = 0; bits256 hash;
struct iguana_info *coinbtc,*altcoin; cJSON *newjson=0; uint8_t pubkey[33];
if ( exchange == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap null exchange ptr\"}"));
offerdir = instantdex_bidaskdir(A);
coinbtc = iguana_coinfind("BTC");
if ( (altcoin= iguana_coinfind(A->A.base)) == 0 || coinbtc == 0 )
{
printf("other.%p coinbtc.%p (%s/%s)\n",altcoin,coinbtc,A->A.base,A->A.rel);
return(clonestr("{\"error\":\"instantdex_BTCswap cant find btc or other coin info\"}"));
}
reftime = (uint32_t)(A->A.expiration - INSTANTDEX_LOCKTIME*2);
if ( strcmp(A->A.rel,"BTC") != 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap offer non BTC rel\"}"));
vcalc_sha256(0,hash.bytes,(void *)&A->A,sizeof(ap->A));
if ( hash.txid != A->orderid )
return(clonestr("{\"error\":\"txid mismatches orderid\"}"));
satoshis[0] = A->A.basevolume64;
satoshis[1] = instantdex_relsatoshis(A->A.price64,A->A.basevolume64);
swap = A->info;
if ( swap == 0 && strcmp(cmdstr,"offer") != 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap no swap info after offer\"}"));
printf("got offer.(%s) offerside.%d offerdir.%d swap.%p\n",jprint(argjson,0),A->A.myside,A->A.acceptdir,A->info);
if ( strcmp(cmdstr,"offer") == 0 && A->info == 0 ) // sender is Bob, receiver is network (Alice)
{
if ( A->A.expiration < (time(NULL) + INSTANTDEX_DURATION) )
return(clonestr("{\"error\":\"instantdex_BTCswap offer too close to expiration\"}"));
if ( (ap= instantdex_acceptable(myinfo,exchange,A,myinfo->myaddr.nxt64bits)) != 0 )
{
spend->input_satoshis += up->value;
spend->inputs[spend->numinputs++] = *up;
if ( spend->input_satoshis >= satoshis )
printf("FOUND MATCH! %p (%s/%s)\n",A->info,A->A.base,A->A.rel);
if ( A->info == 0 )
{
spend->netamount = (spend->input_satoshis - spend->txfee - donation);
spend->change = (spend->input_satoshis - spend->netamount);
printf("numinputs %d sum %.8f vs satoshis %.8f change %.8f -> txfee %.8f\n",spend->numinputs,dstr(spend->input_satoshis),dstr(satoshis),dstr(spend->change),dstr(spend->input_satoshis - spend->change - spend->netamount));
break;
swap = calloc(1,sizeof(struct bitcoin_swapinfo));
swap->choosei = swap->otherschoosei = -1;
swap->state++;
}
remains -= up->value;
} else break;
if ( (A->info= swap) != 0 )
{
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,1,0)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap offer null newjson\"}"));
else
{
//printf("NEWJSON.(%s)\n",jprint(newjson,0));
instantdex_pendingnotice(myinfo,exchange,ap,A);
if ( (retstr= instantdex_choosei(swap,argjson,newjson)) != 0 )
{
printf("Choosei.%s\n",retstr);
return(retstr);
}
else return(instantdex_sendcmd(myinfo,newjson,"BTCstep1",myinfo->ipaddr,INSTANTDEX_HOPS));
}
}
}
else
{
printf("no matching trade.(%s) -> InstantDEX_minaccept\n",jprint(argjson,0));
retstr = instantdex_queueaccept(myinfo,exchange,A->A.base,A->A.rel,dstr(A->A.price64),dstr(A->A.basevolume64),A->A.acceptdir,A->A.myside == 0 ? A->A.base : A->A.rel,A->A.expiration);
}
}
else if ( strcmp(cmdstr,"step1") == 0 && swap->state == 1 ) // either
{
printf("got step1, should have other's choosei\n");
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,1)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap step1 null newjson\"}"));
else if ( swap->otherschoosei < 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap step1, no didnt choosei\"}"));
else
{
swap->state++;
if ( (retstr= instantdex_choosei(swap,argjson,newjson)) != 0 )
return(retstr);
if ( swap->isbob == 0 )
{
int64_t insurance = (satoshis[1] * INSTANTDEX_INSURANCERATE + coinbtc->chain->txfee); // txfee prevents dust attack
if ( (swap->feetx= instantdex_bobtx(myinfo,coinbtc,&swap->ftxid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->otherschoosei],reftime,insurance,1)) != 0 )
{
jaddstr(newjson,"feetx",swap->feetx);
jaddbits256(newjson,"ftxid",swap->ftxid);
// broadcast to network
}
}
return(instantdex_sendcmd(myinfo,newjson,swap->isbob != 0 ? "BTCstep1" : "BTCstep2",myinfo->ipaddr,INSTANTDEX_HOPS));
}
}
if ( spend->input_satoshis >= (satoshis + spend->txfee) )
else if ( strcmp(cmdstr,"step2") == 0 && swap->isbob != 0 && swap->state == 2 ) // Bob
{
spend = realloc(spend,sizeof(*spend) + sizeof(*spend->inputs) * spend->numinputs);
return(spend);
printf("got step2, should have other's privkeys\n");
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,0)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap step2 null newjson\"}"));
else if ( swap->cutverified == 0 || swap->otherverifiedcut == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap step2, both sides didnt validate\"}"));
else //if ( instantdex_feeverify() == 0 )
{
swap->state++;
//char *instantdex_bobtx(myinfo,coin,&paytxid,pubA0,pubB0,privAm,reftime,relsatoshis,0);
if ( (swap->deposit= instantdex_bobtx(myinfo,coinbtc,&swap->dtxid,swap->otherpubs[0],swap->mypubs[0],swap->privkeys[swap->otherschoosei],reftime,satoshis[swap->isbob],1)) != 0 )
{
jaddstr(newjson,"deposit",swap->deposit);
jaddbits256(newjson,"dtxid",swap->dtxid);
jaddbits256(newjson,"pubBn",bitcoin_pubkey33(pubkey,swap->privkeys[swap->otherschoosei]));
// broadcast to network
return(instantdex_sendcmd(myinfo,newjson,"BTCstep3",myinfo->ipaddr,INSTANTDEX_HOPS));
} else return(clonestr("{\"error\":\"instantdex_BTCswap Bob step2, cant create deposit\"}"));
} //else return(clonestr("{\"error\":\"instantdex_BTCswap step2 invalid fee\"}"));
}
else
else if ( strcmp(cmdstr,"step3") == 0 && swap->isbob == 0 && swap->state == 2 ) // Alice
{
free(spend);
return(0);
printf("Alice got step3 should have Bob's choosei\n");
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,0)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap Alice step3 null newjson\"}"));
else if ( swap->cutverified == 0 || swap->otherverifiedcut == 0 || bits256_nonz(swap->pubBn) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap step3, both sides didnt validate\"}"));
else if ( instantdex_paymentverify(myinfo,coinbtc,swap,A,argjson,1) == 0 )
{
swap->state++;
//char *instantdex_alicetx(myinfo,altcoin,&alicetxid,pubAm,pubBn,satoshis);
swap->pubAm = bitcoin_pubkey33(pubkey,swap->privkeys[swap->otherschoosei]);
if ( (swap->altpayment= instantdex_alicetx(myinfo,altcoin,swap->altmsigaddr,&swap->aptxid,swap->pubAm,swap->pubBn,satoshis[swap->isbob])) != 0 )
{
jaddstr(newjson,"altpayment",swap->altpayment);
jaddstr(newjson,"altmsigaddr",swap->altmsigaddr);
jaddbits256(newjson,"aptxid",swap->aptxid);
jaddbits256(newjson,"pubAm",swap->pubAm);
// broadcast to network
return(instantdex_sendcmd(myinfo,newjson,"BTCstep4",myinfo->ipaddr,INSTANTDEX_HOPS));
} else return(clonestr("{\"error\":\"instantdex_BTCswap Alice step3, error making altpay\"}"));
} else return(clonestr("{\"error\":\"instantdex_BTCswap Alice step3, invalid deposit\"}"));
}
else if ( strcmp(cmdstr,"step4") == 0 && swap->isbob != 0 && swap->state == 3 ) // Bob
{
printf("Bob got step4 should have Alice's altpayment\n");
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,0)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap Bob step4 null newjson\"}"));
else if ( bits256_nonz(swap->pubAm) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap step4, no pubAm\"}"));
else if ( instantdex_altpaymentverify(myinfo,altcoin,swap,A,argjson) == 0 )
{
swap->state++;
if ( (swap->deposit= instantdex_bobtx(myinfo,coinbtc,&swap->ptxid,swap->mypubs[1],swap->otherpubs[0],swap->privkeys[swap->otherschoosei],reftime,satoshis[swap->isbob],0)) != 0 )
{
jaddstr(newjson,"payment",swap->payment);
jaddbits256(newjson,"ptxid",swap->ptxid);
// broadcast to network
return(instantdex_sendcmd(myinfo,newjson,"BTCstep5",myinfo->ipaddr,INSTANTDEX_HOPS));
} else return(clonestr("{\"error\":\"instantdex_BTCswap Bob step4, cant create payment\"}"));
} else return(clonestr("{\"error\":\"instantdex_BTCswap Alice step3, invalid deposit\"}"));
}
else if ( strcmp(cmdstr,"step5") == 0 && swap->isbob == 0 && swap->state == 4 ) // Alice
{
printf("Alice got step5 should have Bob's payment\n");
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,0)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap Alice step5 null newjson\"}"));
else if ( instantdex_paymentverify(myinfo,coinbtc,swap,A,argjson,0) == 0 )
{
swap->state++;
/*if ( (swap->spendtx= instantdex_spendpayment(myinfo,coinbtc,&swap->stxid,swap,argjson,newjson)) != 0 )
{
// broadcast to network
return(instantdex_sendcmd(myinfo,newjson,"BTCstep6",myinfo->ipaddr,INSTANTDEX_HOPS));
} else return(clonestr("{\"error\":\"instantdex_BTCswap Alice step5, cant spend payment\"}"));*/
} else return(clonestr("{\"error\":\"instantdex_BTCswap Bob step6, invalid payment\"}"));
}
else if ( strcmp(cmdstr,"step6") == 0 ) // Bob
{
printf("Bob got step6 should have Alice's privkey\n");
if ( (newjson= instantdex_newjson(myinfo,swap,argjson,hash,A,0,0)) == 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap Bob step6 null newjson\"}"));
/*else if ( instantdex_spendverify(myinfo,coinbtc,swap,A,argjson,0) == 0 )
{
if ( (swap->altspend= instantdex_spendaltpayment(myinfo,altcoin,&swap->astxid,swap,argjson,newjson)) != 0 )
{
jaddstr(newjson,"altspend",swap->altspend);
jaddbits256(newjson,"astxid",swap->astxid);
// broadcast to network
return(clonestr("{\"result\":\"Bob finished atomic swap\"}"));
} else return(clonestr("{\"error\":\"instantdex_BTCswap Bob step6, cant spend altpayment\"}"));
} else return(clonestr("{\"error\":\"instantdex_BTCswap Bob step6, invalid spend\"}"));*/
}
else retstr = clonestr("{\"error\":\"BTC swap got unrecognized command\"}");
if ( retstr == 0 )
retstr = clonestr("{\"error\":\"BTC swap null retstr\"}");
if ( swap != 0 )
printf("BTCSWAP.(%s) isbob.%d state.%d verified.(%d %d)\n",retstr,swap->isbob,swap->state,swap->cutverified,swap->otherverifiedcut);
else printf("BTCSWAP.(%s)\n",retstr);
return(retstr);
}
#ifdef oldway
// https://github.com/TierNolan/bips/blob/bip4x/bip-atom.mediawiki
int32_t bitcoin_2of2spendscript(int32_t *paymentlenp,uint8_t *paymentscript,uint8_t *msigscript,bits256 pub0,bits256 pub1)
{
struct vin_info V; uint8_t p2sh_rmd160[20]; int32_t p2shlen;
memset(&V,0,sizeof(V));
V.M = V.N = 2;
memcpy(V.signers[0].pubkey+1,pub0.bytes,sizeof(pub0)), V.signers[0].pubkey[0] = 0x02;
memcpy(V.signers[1].pubkey+1,pub1.bytes,sizeof(pub1)), V.signers[1].pubkey[0] = 0x03;
p2shlen = bitcoin_MofNspendscript(p2sh_rmd160,msigscript,0,&V);
*paymentlenp = bitcoin_p2shspend(paymentscript,0,p2sh_rmd160);
return(p2shlen);
}
/*
Name: Bob.Bail.In
Name: Bob.Bail.In
Input value: B + 2*fb + change
Input source: (From Bob's coins, multiple inputs are allowed)
vout0 value: B, ScriptPubKey 0: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL
vout1 value: fb, ScriptPubKey 1: OP_HASH160 Hash160(x) OP_EQUALVERIFY pub-A1 OP_CHECKSIG
vout2 value: change, ScriptPubKey 2: <= 100 bytes
P2SH Redeem: OP_2 pub-A1 pub-B1 OP_2 OP_CHECKMULTISIG
Name: Alice.Bail.In
Name: Alice.Bail.In
vins: A + 2*fa + change, Input source: (From Alice's altcoins, multiple inputs are allowed)
vout0 value: A, ScriptPubKey 0: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL
vout1 value: fa, ScriptPubKey 1: OP_HASH160 Hash160(x) OP_EQUAL
vout2 value: change, ScriptPubKey 2: <= 100 bytes
*/
*/
char *instantdex_bailintx(struct iguana_info *coin,bits256 *txidp,struct bitcoin_spend *spend,bits256 A0,bits256 B0,uint8_t x[20],int32_t isbob)
{
uint64_t change; char *rawtxstr,*signedtx; struct vin_info *V; bits256 txid,signedtxid;
@ -211,12 +742,11 @@ char *instantdex_bailintx(struct iguana_info *coin,bits256 *txidp,struct bitcoin
cJSON *instantdex_bailinspend(struct iguana_info *coin,bits256 privkey,uint64_t amount)
{
bits256 hash; int32_t n; cJSON *txobj;
int32_t n; cJSON *txobj;
int32_t scriptv0len; uint8_t p2shscript[256],rmd160[20],scriptv0[128],pubkey[35];
bitcoin_pubkey33(pubkey,privkey);
n = bitcoin_pubkeyspend(p2shscript,0,pubkey);
vcalc_sha256(0,hash.bytes,p2shscript,n);
calc_rmd160(0,rmd160,hash.bytes,sizeof(hash.bytes));
calc_rmd160_sha256(rmd160,p2shscript,n);
scriptv0len = bitcoin_p2shspend(scriptv0,0,rmd160);
txobj = bitcoin_createtx(coin,0);
bitcoin_addoutput(coin,txobj,scriptv0,scriptv0len,amount);
@ -224,16 +754,16 @@ cJSON *instantdex_bailinspend(struct iguana_info *coin,bits256 privkey,uint64_t
}
/*
Name: Bob.Payout
vin0: A, Input source: Alice.Bail.In:0
vin1: fa, Input source: Alice.Bail.In:1
vout0: A, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-B2 OP_CHECKSIG
Name: Bob.Payout
vin0: A, Input source: Alice.Bail.In:0
vin1: fa, Input source: Alice.Bail.In:1
vout0: A, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-B2 OP_CHECKSIG
Name: Alice.Payout
vin0: B, Input source: Bob.Bail.In:0
vin1: fb, Input source: Bob.Bail.In:1
vout0: B, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-A2 OP_CHECKSIG
*/
vin0: B, Input source: Bob.Bail.In:0
vin1: fb, Input source: Bob.Bail.In:1
vout0: B, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-A2 OP_CHECKSIG
*/
char *instantdex_bailinsign(struct iguana_info *coin,bits256 bailinpriv,char *sigstr,int32_t *siglenp,bits256 *txidp,struct vin_info *V,cJSON *txobj,int32_t isbob)
{
@ -252,7 +782,6 @@ char *instantdex_bailinsign(struct iguana_info *coin,bits256 bailinpriv,char *si
return(signedtx);
}
char *instantdex_payouttx(struct iguana_info *coin,char *sigstr,int32_t *siglenp,bits256 *txidp,bits256 *sharedprivs,bits256 bailintxid,int64_t amount,int64_t txfee,int32_t isbob,char *othersigstr)
{
struct vin_info V; cJSON *txobj;
@ -270,16 +799,16 @@ char *instantdex_payouttx(struct iguana_info *coin,char *sigstr,int32_t *siglenp
}
/*
Name: Alice.Refund
vin0: A, Input source: Alice.Bail.In:0
vout0: A - fa, ScriptPubKey: OP_HASH160 Hash160(P2SH) OP_EQUAL; P2SH Redeem: pub-A3 OP_CHECKSIG
Locktime: current block height + ((T/2)/(altcoin block rate))
Name: Alice.Refund
vin0: A, Input source: Alice.Bail.In:0
vout0: A - fa, ScriptPubKey: OP_HASH160 Hash160(P2SH) OP_EQUAL; P2SH Redeem: pub-A3 OP_CHECKSIG
Locktime: current block height + ((T/2)/(altcoin block rate))
Name: Bob.Refund
vin0: B, Input source: Bob.Bail.In:0
vout0: B - fb, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-B3 OP_CHECKSIG
Locktime: (current block height) + (T / 10 minutes)
*/
Name: Bob.Refund
vin0: B, Input source: Bob.Bail.In:0
vout0: B - fb, ScriptPubKey: OP_HASH160 Hash160(P2SH Redeem) OP_EQUAL; P2SH Redeem: pub-B3 OP_CHECKSIG
Locktime: (current block height) + (T / 10 minutes)
*/
char *instantdex_refundtx(struct iguana_info *coin,bits256 *txidp,bits256 bailinpriv,bits256 priv2,bits256 bailintxid,int64_t amount,int64_t txfee,int32_t isbob)
{
char sigstr[256]; int32_t siglen; struct vin_info V; cJSON *txobj;
@ -290,70 +819,14 @@ char *instantdex_refundtx(struct iguana_info *coin,bits256 *txidp,bits256 bailin
int32_t instantdex_calcx20(char hexstr[41],uint8_t *p2shscript,uint8_t firstbyte,bits256 pub)
{
uint8_t pubkey[33],rmd160[20]; int32_t n; bits256 hash;
uint8_t pubkey[33],rmd160[20]; int32_t n;
memcpy(pubkey+1,pub.bytes,sizeof(pub)), pubkey[0] = firstbyte;
n = bitcoin_pubkeyspend(p2shscript,0,pubkey);
vcalc_sha256(0,hash.bytes,p2shscript,n);
calc_rmd160(0,rmd160,hash.bytes,sizeof(hash.bytes));
calc_rmd160_sha256(rmd160,p2shscript,n);
init_hexbytes_noT(hexstr,rmd160,sizeof(rmd160));
return(n);
}
char *instantdex_btcoffer(struct supernet_info *myinfo,struct exchange_info *exchange,char *othercoin,double othervolume,double maxprice) // Bob sending to network (Alice)
{
char *str,coinaddr[64],xstr[41]; uint8_t xscript[64]; struct iguana_info *other; int32_t isbob = 1;
struct instantdex_accept checkA,A; cJSON *newjson; bits256 hash,pub3,sharedprivs[4];
if ( othercoin == 0 || (other= iguana_coinfind(othercoin)) == 0 )
return(clonestr("{\"error\":\"invalid othercoin\"}"));
hash = instantdex_acceptset(&A,othercoin,"BTC",INSTANTDEX_OFFERDURATION,1,-1,maxprice,othervolume,myinfo->myaddr.nxt64bits);
newjson = instantdex_acceptsendjson(&A);
if ( instantdex_acceptextract(&checkA,newjson) < 0 )
{
int32_t i;
for (i=0; i<sizeof(A); i++)
printf("%02x ",((uint8_t *)&A)[i]);
printf("instantdex_btcoffer checkA error\n");
}
if ( instantdex_pubkeyargs(sharedprivs,newjson,4,myinfo->persistent_priv,hash,0x02+isbob) != 4 )
return(clonestr("{\"error\":\"highly unlikely run of 02 pubkeys\"}"));
pub3 = jbits256(newjson,"B3");
jdelete(newjson,"B3");
instantdex_calcx20(xstr,xscript,0x02+isbob,pub3);
jaddstr(newjson,"x",xstr);
if ( coinaddr[0] != 0 )
jaddstr(newjson,othercoin,coinaddr);
if ( maxprice > 0. )
{
if ( (str= InstantDEX_maxaccept(myinfo,0,newjson,0,othercoin,"BTC",maxprice,othervolume)) != 0 )
free(str);
}
return(instantdex_sendcmd(myinfo,newjson,"BTCoffer",myinfo->ipaddr,INSTANTDEX_HOPS));
}
void instantdex_pendingnotice(struct supernet_info *myinfo,struct exchange_info *exchange,struct instantdex_accept *ap,struct instantdex_accept *A)
{
printf("need to start monitoring thread\n");
ap->pendingvolume64 -= A->A.basevolume64;
}
cJSON *instantdex_newjson(struct supernet_info *myinfo,bits256 *A0p,bits256 *B0p,bits256 *sharedprivs,uint8_t secret160[20],int32_t isbob,cJSON *argjson,bits256 hash,struct instantdex_accept *A)
{
cJSON *newjson; char *xstr;
newjson = instantdex_acceptsendjson(A);
if ( instantdex_pubkeyargs(sharedprivs,newjson,3+isbob,myinfo->persistent_priv,hash,0x02+isbob) != 3 )
return(0);
if ( isbob == 0 )
*A0p = jbits256(newjson,"A0");
else *A0p = jbits256(argjson,"A0");
*B0p = jbits256(argjson,"B0");
if ( (xstr= jstr(argjson,"x")) != 0 )
{
decode_hex(secret160,20,xstr);
jaddstr(newjson,"x",xstr);
}
return(newjson);
}
char *instantdex_bailinrefund(struct supernet_info *myinfo,struct iguana_info *coin,struct exchange_info *exchange,struct instantdex_accept *A,char *nextcmd,uint8_t secret160[20],cJSON *newjson,int32_t isbob,bits256 A0,bits256 B0,bits256 *sharedprivs)
{
struct bitcoin_spend *spend; char *bailintx,*refundtx,field[64]; bits256 bailintxid,refundtxid;
@ -416,8 +889,11 @@ char *instantdex_BTCswap(struct supernet_info *myinfo,struct exchange_info *exch
return(clonestr("{\"error\":\"instantdex_BTCswap null exchange ptr\"}"));
offerdir = instantdex_bidaskdir(A);
if ( (other= iguana_coinfind(A->A.base)) == 0 || (coinbtc= iguana_coinfind("BTC")) == 0 )
{
printf("other.%p coinbtc.%p (%s/%s)\n",other,coinbtc,A->A.base,A->A.rel);
return(clonestr("{\"error\":\"instantdex_BTCswap cant find btc or other coin info\"}"));
locktime = (uint32_t)(A->A.expiration + INSTANTDEX_OFFERDURATION);
}
locktime = (uint32_t)(A->A.expiration + INSTANTDEX_LOCKTIME);
if ( strcmp(A->A.rel,"BTC") != 0 )
return(clonestr("{\"error\":\"instantdex_BTCswap offer non BTC rel\"}"));
vcalc_sha256(0,hash.bytes,(void *)&A->A,sizeof(ap->A));
@ -454,7 +930,7 @@ char *instantdex_BTCswap(struct supernet_info *myinfo,struct exchange_info *exch
isbob = 1;
newjson = instantdex_payout(myinfo,coinbtc,exchange,A,secret160,isbob,&A0,&B0,sharedprivs,hash,satoshis,argjson);
return(instantdex_bailinrefund(myinfo,coinbtc,exchange,A,"BTCaccept",secret160,newjson,isbob,A0,B0,sharedprivs));
}
}
else if ( strcmp(cmdstr,"accept") == 0 ) // sender is Bob, receiver is Alice
{
isbob = 0;
@ -489,3 +965,6 @@ char *instantdex_BTCswap(struct supernet_info *myinfo,struct exchange_info *exch
retstr = clonestr("{\"error\":\"BTC swap null retstr\"}");
return(retstr);
}
#endif

6
includes/iguana_apideclares.h

@ -17,11 +17,12 @@ STRING_ARG(SuperNET,bitcoinrpc,setcoin);
ZERO_ARGS(SuperNET,myipaddr);
STRING_ARG(SuperNET,setmyipaddr,ipaddr);
TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,BTCoffer,othercoin,otherassetid,maxprice,othervolume);
TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,minaccept,base,rel,minprice,basevolume);
TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,maxaccept,base,rel,maxprice,basevolume);
/*TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,BTCoffer,othercoin,otherassetid,maxprice,othervolume);
STRING_AND_TWO_DOUBLES(InstantDEX,ALToffer,basecoin,minprice,basevolume);
STRING_AND_TWO_DOUBLES(InstantDEX,NXToffer,assetid,minprice,basevolume);
STRING_AND_TWO_DOUBLES(InstantDEX,NXToffer,assetid,minprice,basevolume);*/
HASH_AND_STRING(ramchain,verifytx,txid,txbytes);
INT_ARG(ramchain,getblockhash,height);
@ -94,6 +95,7 @@ THREE_STRINGS(SuperNET,rosetta,passphrase,pin,showprivkey);
ZERO_ARGS(SuperNET,keypair);
HASH_AND_INT(SuperNET,priv2pub,privkey,addrtype);
STRING_ARG(SuperNET,wif2priv,wif);
STRING_ARG(SuperNET,addr2rmd160,address);
TWOHASHES_AND_STRING(SuperNET,cipher,privkey,destpubkey,message);
TWOHASHES_AND_STRING(SuperNET,decipher,privkey,srcpubkey,cipherstr);

Loading…
Cancel
Save