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

1174 lines
50 KiB

9 years ago
/******************************************************************************
8 years ago
* Copyright © 2014-2017 The SuperNET Developers. *
9 years ago
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
8 years ago
/*struct bitcoin_rawtxdependents
9 years ago
{
int64_t spentsatoshis,outputsum,cost,change;
int32_t numptrs,numresults;
char **results,*coinaddrs;
struct basilisk_item *ptrs[];
8 years ago
};*/
9 years ago
9 years ago
#ifdef bitcoincancalculatebalances
char *bitcoin_balance(struct iguana_info *coin,char *coinaddr,int32_t lastheight,int32_t minconf)
{
int32_t i,n,height,maxconf=1<<30; int64_t balance = 0; char params[512],*curlstr; cJSON *array,*retjson,*curljson;
retjson = cJSON_CreateObject();
if ( (curlstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getinfo",params)) != 0 )
{
if ( (curljson= cJSON_Parse(curlstr)) != 0 )
{
if ( (height= juint(curljson,"blocks")) > lastheight )
maxconf = height - lastheight;
free_json(curljson);
}
free(curlstr);
}
sprintf(params,"%d, %d, [\"%s\"]",minconf,maxconf,coinaddr);
if ( (curlstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listunspent",params)) != 0 )
{
if ( (array= cJSON_Parse(curlstr)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
9 years ago
balance += SATOSHIDEN * jdouble(jitem(array,i),"satoshis");
9 years ago
}
free_json(array);
}
free(curlstr);
}
jaddnum(retjson,"balance",dstr(balance));
return(jprint(retjson,1));
}
8 years ago
int64_t bitcoin_value(struct iguana_info *coin,bits256 txid,int16_t vout,char *coinaddr)
{
char params[512],str[65]; char *curlstr; cJSON *txobj,*vouts,*item,*sobj,*addrs; int32_t j,m,n; int64_t value = 0;
sprintf(params,"[\"%s\", 1]",bits256_str(str,txid));
if ( (curlstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getrawtransaction",params)) != 0 )
{
if ( (txobj= cJSON_Parse(curlstr)) != 0 )
{
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && vout < n )
{
item = jitem(vouts,vout);
if ( (sobj= jobj(item,"scriptPubKey")) != 0 && (addrs= jarray(&m,sobj,"addresses")) != 0 )
{
for (j=0; j<m; j++)
{
if ( strcmp(jstri(addrs,j),coinaddr) == 0 )
{
value = SATOSHIDEN * jdouble(item,"satoshis");
break;
}
}
}
}
free_json(txobj);
}
free(curlstr);
}
return(value);
}
9 years ago
char *basilisk_bitcoinblockhashstr(char *coinstr,char *serverport,char *userpass,int32_t height)
9 years ago
{
9 years ago
char numstr[128],*blockhashstr=0; bits256 hash2; struct iguana_info *coin;
9 years ago
sprintf(numstr,"%d",height);
9 years ago
if ( (blockhashstr= bitcoind_passthru(coinstr,serverport,userpass,"getblockhash",numstr)) == 0 )
return(0);
9 years ago
hash2 = bits256_conv(blockhashstr);
if ( blockhashstr == 0 || blockhashstr[0] == 0 || bits256_nonz(hash2) == 0 )
9 years ago
{
9 years ago
printf("couldnt get blockhash for %u, probably curl is disabled\n",height);
9 years ago
if ( blockhashstr != 0 )
free(blockhashstr);
9 years ago
if ( height == 0 )
{
if ( (coin= iguana_coinfind(coinstr)) != 0 )
{
bits256_str(numstr,*(bits256 *)coin->chain->genesis_hashdata);
return(clonestr(numstr));
}
}
9 years ago
return(0);
}
return(blockhashstr);
}
9 years ago
int32_t basilisk_blockhashes(struct iguana_info *coin,int32_t height,int32_t n)
{
9 years ago
char *blockhashstr; struct iguana_block *block,*checkblock; struct iguana_bundle *bp=0; int32_t bundlei,checki,h,i,num = 0; bits256 zero,hash2;
9 years ago
h = height;
for (i=0; i<n; i++,h++)
{
hash2 = iguana_blockhash(coin,h);
9 years ago
if ( 0 && (block= iguana_blockfind("basilisk",coin,hash2)) != 0 && block->height == h && block->mainchain != 0 )
9 years ago
continue;
9 years ago
if ( (blockhashstr= basilisk_bitcoinblockhashstr(coin->symbol,coin->chain->serverport,coin->chain->userpass,h)) != 0 && bits256_nonz(hash2) != 0 )
9 years ago
{
hash2 = bits256_conv(blockhashstr);
memset(zero.bytes,0,sizeof(zero));
block = iguana_blockhashset("remote",coin,h,hash2,1);
9 years ago
if ( (bundlei= (h % coin->chain->bundlesize)) == 0 )
bp = iguana_bundlecreate(coin,&checki,h,hash2,zero,1);
9 years ago
iguana_bundlehash2add(coin,&checkblock,bp,bundlei,hash2);
9 years ago
if ( block != checkblock )
printf("bp.%p block mismatch %p %p at ht.%d bundlei.%d\n",bp,block,checkblock,h,bundlei);
9 years ago
else
{
block->mainchain = 1;
9 years ago
char str[65]; printf("%s ht.%d\n",bits256_str(str,hash2),h);
9 years ago
num++;
}
9 years ago
free(blockhashstr);
}
}
return(num);
}
9 years ago
int32_t basilisk_blockheight(struct iguana_info *coin,bits256 hash2)
9 years ago
{
9 years ago
char buf[128],str[65],*blocktxt; cJSON *blockjson; int32_t height=-1;
sprintf(buf,"\"%s\"",bits256_str(str,hash2));
if ( (blocktxt= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getblock",buf)) != 0 )
{
if ( (blockjson= cJSON_Parse(blocktxt)) != 0 )
{
height = jint(blockjson,"height");
free_json(blockjson);
}
free(blocktxt);
}
return(height);
}
9 years ago
cJSON *bitcoin_blockjson(int32_t *heightp,char *coinstr,char *serverport,char *userpass,char *blockhashstr,int32_t height)
{
cJSON *json = 0; int32_t flag = 0; char buf[1024],*blocktxt = 0;
if ( blockhashstr == 0 )
9 years ago
blockhashstr = basilisk_bitcoinblockhashstr(coinstr,serverport,userpass,height), flag = 1;
9 years ago
if ( blockhashstr != 0 )
{
sprintf(buf,"\"%s\"",blockhashstr);
blocktxt = bitcoind_passthru(coinstr,serverport,userpass,"getblock",buf);
//printf("get_blockjson.(%d %s) %s\n",height,blockhashstr,blocktxt);
if ( blocktxt != 0 && blocktxt[0] != 0 && (json= cJSON_Parse(blocktxt)) != 0 && heightp != 0 )
if ( (*heightp= juint(json,"height")) != height )
*heightp = -1;
if ( flag != 0 && blockhashstr != 0 )
free(blockhashstr);
if ( blocktxt != 0 )
free(blocktxt);
}
return(json);
}
int32_t basilisk_bitcoinscan(struct iguana_info *coin,uint8_t origblockspace[IGUANA_MAXPACKETSIZE],struct OS_memspace *rawmem)
{
9 years ago
struct iguana_txblock txdata; struct iguana_block B; int32_t len,starti,h,num=0,loadheight,hexlen,datalen,n,i,numtxids,flag=0,j,height=-1; cJSON *curljson,*blockjson,*txids; char *bitstr,*curlstr,params[128],str[65]; struct iguana_msghdr H; struct iguana_msgblock *msg; uint8_t *blockspace,revbits[4],bitsbuf[4]; bits256 hash2,checkhash2;
9 years ago
strcpy(params,"[]");
if ( (curlstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getinfo",params)) != 0 )
{
if ( (curljson= cJSON_Parse(curlstr)) != 0 )
{
height = juint(curljson,"blocks");
free_json(curljson);
}
free(curlstr);
}
loadheight = coin->blocks.hwmchain.height;
9 years ago
basilisk_blockhashes(coin,loadheight,coin->chain->bundlesize);
9 years ago
for (j=0; j<coin->chain->bundlesize; j++)
9 years ago
{
9 years ago
if ( loadheight == 0 )
{
loadheight++;
continue;
}
basilisk_blockhashes(coin,loadheight,1);
9 years ago
flag = 0;
if ( (blockjson= bitcoin_blockjson(&h,coin->symbol,coin->chain->serverport,coin->chain->userpass,0,loadheight)) != 0 )
{
blockspace = origblockspace;
9 years ago
memset(&B,0,sizeof(B));
B.RO.version = juint(blockjson,"version");
B.RO.prev_block = jbits256(blockjson,"previousblockhash");
B.RO.merkle_root = jbits256(blockjson,"merkleroot");
B.RO.timestamp = juint(blockjson,"time");
if ( (bitstr= jstr(blockjson,"nBits")) != 0 )
9 years ago
{
9 years ago
decode_hex(revbits,sizeof(uint32_t),bitstr);
9 years ago
for (i=0; i<4; i++)
bitsbuf[i] = revbits[3 - i];
9 years ago
memcpy(&B.RO.bits,bitsbuf,sizeof(B.RO.bits));
9 years ago
}
printf("need to handle zcash/auxpow\n");
9 years ago
B.RO.nonce = juint(blockjson,"nonce");
//char str[65],str2[65];
//printf("v.%d t.%u bits.%08x nonce.%x %s %s\n",B.RO.version,B.RO.timestamp,B.RO.bits,B.RO.nonce,bits256_str(str,B.RO.prev_block),bits256_str(str2,B.RO.merkle_root));
iguana_serialize_block(coin->chain,&checkhash2,blockspace,&B);
msg = (void *)blockspace;
9 years ago
//printf("(%s)\n",jprint(blockjson,0));
9 years ago
checkhash2 = iguana_calcblockhash(coin->symbol,coin->chain->hashalgo,blockspace,sizeof(*msg)-4);
9 years ago
if ( jstr(blockjson,"hash") != 0 )
hash2 = bits256_conv(jstr(blockjson,"hash"));
else memset(hash2.bytes,0,sizeof(hash2));
//printf("%s vs %s %ld\n",bits256_str(str,hash2),bits256_str(str2,checkhash2),sizeof(*msg)-4);
9 years ago
datalen = 80;
if ( (txids= jarray(&numtxids,blockjson,"tx")) != 0 )
{
msg->txn_count = numtxids;
if ( numtxids < 0xfd )
blockspace[datalen++] = numtxids;
else
{
blockspace[datalen++] = 0xfd;
blockspace[datalen++] = numtxids & 0xff;
blockspace[datalen++] = numtxids >> 8;
}
starti = datalen;
for (i=0; i<numtxids; i++)
{
sprintf(params,"[\"%s\"]",bits256_str(str,jbits256(jitem(txids,i),0)));
if ( (curlstr= bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getrawtransaction",params)) != 0 )
{
//printf("%s txid.%d\n",curlstr,i);
if ( (hexlen= is_hexstr(curlstr,0)) > 1 )
{
hexlen >>= 1;
decode_hex(&blockspace[datalen],hexlen,curlstr);
datalen += hexlen;
}
free(curlstr);
}
}
num++;
coin->blocks.pending++;
if ( rawmem->ptr == 0 )
iguana_meminit(rawmem,"basilisk",0,IGUANA_MAXPACKETSIZE*3,0);
else iguana_memreset(rawmem);
memset(&txdata,0,sizeof(txdata));
memset(&H,0,sizeof(H));
8 years ago
if ( (n= iguana_gentxarray(coin,rawmem,&txdata,&len,blockspace,datalen)) == datalen || n == datalen-1 )
9 years ago
{
len = n;
8 years ago
iguana_gotblockM(coin,0,&txdata,rawmem->ptr,&H,blockspace,datalen,0);
9 years ago
flag = 1;
//if ( (rand() % 1000) == 0 )
9 years ago
printf("%s h.%-7d len.%-6d | HWM.%d\n",coin->symbol,h,datalen,coin->blocks.hwmchain.height);
9 years ago
}
else
{
printf(" parse error block.%d txn_count.%d, n.%d len.%d vs datalen.%d\n",loadheight,txdata.block.RO.txn_count,n,len,datalen);
}
}
free_json(blockjson);
}
9 years ago
loadheight++;
9 years ago
if ( flag == 0 )
break;
}
if ( coin->blocks.pending > 0 )
coin->blocks.pending--;
return(num);
}
#endif
int32_t basilisk_bitcoinavail(struct iguana_info *coin)
{
if ( coin->VALIDATENODE > 0 || coin->FULLNODE > 0 )
9 years ago
return(1);
//else if ( coin->chain->serverport[0] != 0 )
// return(1);
else return(0);
}
9 years ago
void *basilisk_bitcoinbalances(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *vals)
9 years ago
{
int64_t balance,total = 0; int32_t i,j,n,hist; char *str; cJSON *spends,*unspents,*retjson,*item,*addresses,*array = cJSON_CreateArray();
8 years ago
spends = unspents = 0;
8 years ago
if ( (hist= juint(vals,"history")) != 0 )
8 years ago
{
if ( (hist & 1) != 0 )
unspents = cJSON_CreateArray();
if ( (hist & 2) != 0 )
spends = cJSON_CreateArray();
}
8 years ago
//printf("hist.%d (%s) %p %p\n",hist,jprint(vals,0),unspents,spends);
8 years ago
if ( (addresses= jarray(&n,vals,"addresses")) != 0 )
{
for (i=0; i<n; i++)
{
8 years ago
if ( (str= jstri(addresses,i)) != 0 )
{
for (j=0; j<n; j++)
if ( jstri(addresses,j) != 0 && strcmp(jstri(addresses,j),str) == 0 )
break;
if ( j == n )
continue;
balance = iguana_addressreceived(myinfo,coin,vals,remoteaddr,0,0,unspents,spends,str,juint(vals,"minconf"),0);//juint(vals,"firstheight"));
8 years ago
item = cJSON_CreateObject();
jaddnum(item,str,dstr(balance));
jaddstr(item,"address",str);
8 years ago
jaddi(array,item);
total += balance;
}
8 years ago
//printf("%.8f ",dstr(balance));
8 years ago
}
}
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
8 years ago
jaddstr(retjson,"ipaddr",myinfo->ipaddr);
8 years ago
jaddnum(retjson,"total",dstr(total));
8 years ago
jaddnum(retjson,"balance",dstr(total));
8 years ago
jadd(retjson,"addresses",array);
8 years ago
if ( unspents != 0 )
jadd(retjson,"unspents",unspents);
8 years ago
if ( spends != 0 )
jadd(retjson,"spends",spends);
8 years ago
jaddnum(retjson,"RTheight",coin->RTheight);
jaddnum(retjson,"longest",coin->longestchain);
jaddnum(retjson,"lag",coin->longestchain- coin->RTheight);
8 years ago
//printf("BAL.(%s)\n",jprint(retjson,0));
8 years ago
Lptr->retstr = jprint(retjson,1);
return(Lptr);
9 years ago
}
9 years ago
char *basilisk_valuestr(struct iguana_info *coin,char *coinaddr,uint64_t value,int32_t height,bits256 txid,int16_t vout)
9 years ago
{
9 years ago
cJSON *retjson = cJSON_CreateObject();
8 years ago
jaddstr(retjson,"result","success");
9 years ago
jaddstr(retjson,"address",coinaddr);
9 years ago
jadd64bits(retjson,"satoshis",value);
8 years ago
jaddnum(retjson,"amount",dstr(value));
8 years ago
jaddnum(retjson,"value",dstr(value));
9 years ago
jaddnum(retjson,"height",height);
8 years ago
jaddnum(retjson,"numconfirms",coin->blocks.hwmchain.height - height + 1);
9 years ago
jaddbits256(retjson,"txid",txid);
jaddnum(retjson,"vout",vout);
9 years ago
jaddstr(retjson,"coin",coin->symbol);
9 years ago
return(jprint(retjson,1));
}
9 years ago
double basilisk_bitcoin_valuemetric(struct supernet_info *myinfo,struct basilisk_item *ptr,char *resultstr)
{
struct basilisk_value *v; cJSON *resultarg; int32_t ind;
if ( (ind= myinfo->basilisks.numvalues) >= sizeof(myinfo->basilisks.values)/sizeof(*myinfo->basilisks.values) )
ind = (rand() % (sizeof(myinfo->basilisks.values)/sizeof(*myinfo->basilisks.values)));
else myinfo->basilisks.numvalues++;
v = &myinfo->basilisks.values[ind];
if ( (resultarg= cJSON_Parse(resultstr)) != 0 )
{
safecopy(v->coinaddr,jstr(resultarg,"address"),sizeof(v->coinaddr));
9 years ago
v->value = j64bits(resultarg,"satoshis");
9 years ago
v->txid = jbits256(resultarg,"txid");
v->vout = jint(resultarg,"vout");
v->height = jint(resultarg,"height");
}
return(ind + 1);
}
void *basilisk_bitcoinvalue(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj)
9 years ago
{
8 years ago
int32_t i,j,height,vout,numsent; cJSON *retjson; struct basilisk_item *ptr; char coinaddr[64],str[65]; struct basilisk_value *v; uint64_t value = 0; bits256 txid; struct iguana_outpoint outpt;
8 years ago
if ( valsobj == 0 )
return(clonestr("{\"error\":\"null valsobj\"}"));
8 years ago
if ( myinfo->IAMNOTARY != 0 && myinfo->NOTARY.RELAYID >= 0 )
8 years ago
return(0);
9 years ago
txid = jbits256(valsobj,"txid");
vout = jint(valsobj,"vout");
9 years ago
if ( coin != 0 && basilisk_bitcoinavail(coin) != 0 )
9 years ago
{
if ( (coin->VALIDATENODE > 0 || coin->FULLNODE > 0) )//&& coinaddr != 0 && coinaddr[0] != 0 )
9 years ago
{
8 years ago
if ( iguana_RTunspentindfind(myinfo,coin,&outpt,coinaddr,0,0,&value,&height,txid,vout,coin->bundlescount,0) == 0 )
9 years ago
{
8 years ago
//printf("bitcoinvalue found iguana\n");
9 years ago
Lptr->retstr = basilisk_valuestr(coin,coinaddr,value,height,txid,vout);
return(Lptr);
8 years ago
} else printf("unspentind cant find %s vout.%d\n",bits256_str(str,txid),vout);
9 years ago
} //else return(bitcoin_value(coin,txid,vout,coinaddr));
9 years ago
Lptr->retstr = clonestr("{\"error\":\"basilisk value missing address\"}");
9 years ago
return(Lptr);
9 years ago
}
9 years ago
//printf("Scan basilisks values\n");
9 years ago
if ( (v= myinfo->basilisks.values) != 0 )
9 years ago
{
9 years ago
for (i=0; i<myinfo->basilisks.numvalues; i++,v++)
9 years ago
{
9 years ago
if ( v->vout == vout && bits256_cmp(txid,v->txid) == 0 && strcmp(v->coinaddr,coinaddr) == 0 )
9 years ago
{
9 years ago
printf("bitcoinvalue local ht.%d %s %.8f\n",v->height,v->coinaddr,dstr(v->value));
8 years ago
ptr = basilisk_issueremote(myinfo,0,&numsent,"VAL",coin->symbol,1,valsobj,juint(valsobj,"fanout"),juint(valsobj,"numrequired"),basilisktag,timeoutmillis,0,basilisk_valuestr(coin,v->coinaddr,v->value,v->height,txid,vout),0,0,BASILISK_DEFAULTDIFF); // this completes immediate
8 years ago
//queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
8 years ago
if ( ptr->numresults > 0 )
{
retjson = cJSON_CreateArray();
for (j=0; j<ptr->numresults; j++)
jaddi(retjson,ptr->results[j]), ptr->results[j] = 0;
ptr->retstr = jprint(retjson,1);
//printf("numresults.%d (%p)\n",ptr->numresults,ptr);
}
8 years ago
return(ptr);
9 years ago
}
}
9 years ago
}
8 years ago
printf("bitcoinvalue issue remote tag.%u\n",basilisktag);
8 years ago
ptr = basilisk_issueremote(myinfo,0,&numsent,"VAL",coin->symbol,1,valsobj,juint(valsobj,"fanout"),juint(valsobj,"numrequired"),basilisktag,timeoutmillis,0,0,0,0,BASILISK_DEFAULTDIFF);
8 years ago
if ( ptr->numresults > 0 )
{
retjson = cJSON_CreateArray();
for (j=0; j<ptr->numresults; j++)
jaddi(retjson,ptr->results[j]), ptr->results[j] = 0;
ptr->retstr = jprint(retjson,1);
//printf("numresults.%d (%p)\n",ptr->numresults,ptr);
}
8 years ago
//queue_enqueue("submitQ",&myinfo->basilisks.submitQ,&ptr->DL,0);
8 years ago
return(ptr);
9 years ago
}
8 years ago
void *basilisk_getinfo(struct basilisk_item *Lptr,struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj)
{
8 years ago
struct basilisk_item *ptr; cJSON *infojson,*retjson; int32_t j,numsent,fanout,numrequired;
8 years ago
if ( valsobj == 0 )
return(clonestr("{\"error\":\"null valsobj\"}"));
8 years ago
if ( (myinfo->IAMNOTARY != 0 || myinfo->NOTARY.RELAYID >= 0) && strcmp(coin->symbol,"RELAY") != 0 )
8 years ago
return(0);
8 years ago
if ( coin->VALIDATENODE > 0 || coin->FULLNODE > 0 || coin->notarychain >= 0 )
8 years ago
{
infojson = iguana_getinfo(myinfo,coin);
Lptr->retstr = jprint(infojson,1);
return(Lptr);
}
8 years ago
if ( (fanout= juint(valsobj,"fanout")) < 8 )
fanout = 8;
8 years ago
if ( (numrequired= juint(valsobj,"numrequired")) < fanout )
{
jaddnum(valsobj,"numrequired",fanout);
8 years ago
numrequired = 1;
8 years ago
}
ptr = basilisk_issueremote(myinfo,0,&numsent,"INF",coin->symbol,1,valsobj,fanout,numrequired,basilisktag,timeoutmillis,0,0,0,0,BASILISK_DEFAULTDIFF);
8 years ago
if ( ptr->numresults > 0 )
{
retjson = cJSON_CreateArray();
for (j=0; j<ptr->numresults; j++)
jaddi(retjson,ptr->results[j]), ptr->results[j] = 0;
ptr->retstr = jprint(retjson,1);
//printf("numresults.%d (%p)\n",ptr->numresults,ptr);
}
8 years ago
return(ptr);
}
int64_t iguana_getestimatedfee(struct supernet_info *myinfo,struct iguana_info *coin)
{
char *retstr; cJSON *retjson; double x; int64_t txfeeperbyte = 200;
if ( (retstr= _dex_getinfo(myinfo,coin->symbol)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (x= jdouble(retjson,"estimatefee")) > SMALLVAL )
txfeeperbyte = 1 + (x * SATOSHIDEN) / 1024;
printf("SET txfeeperbyte %lld (%s)\n",(long long)txfeeperbyte,retstr);
free(retjson);
}
free(retstr);
}
return(txfeeperbyte);
}
8 years ago
int32_t basilisk_voutvin_validate(struct iguana_info *coin,char *rawtx,uint64_t inputsum,uint64_t amount,uint64_t txfee)
{
8 years ago
//static int counter;
//if ( counter++ < 10 )
// printf("validate.(%s) vout's vin\n",rawtx);
8 years ago
if ( rawtx != 0 )
{
return(0); // convert rawtx, add up outputs, verify totals
}
return(-1);
}
8 years ago
int32_t basilisk_vins_validate(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *retjson,uint64_t amount,uint64_t txfee)
8 years ago
{
8 years ago
cJSON *vins,*item,*argjson,*valuearray; uint64_t value,inputsum=0; int32_t j,i=-1,vout,retval=-1,numvins=0; bits256 txid; char *valstr;
8 years ago
if ( retjson != 0 )
8 years ago
{
if ( (vins= jarray(&numvins,retjson,"vins")) != 0 )
{
for (i=0; i<numvins; i++)
{
item = jitem(vins,i);
txid = jbits256(item,"txid");
vout = jint(item,"vout");
argjson = cJSON_CreateObject();
jaddbits256(argjson,"txid",txid);
jaddnum(argjson,"vout",vout);
8 years ago
jaddstr(argjson,"coin",coin->symbol);
8 years ago
retval = -1;
8 years ago
if ( (valstr= basilisk_value(myinfo,coin,0,0,myinfo->myaddr.persistent,argjson,0)) != 0 )
{
8 years ago
//printf("valstr.(%d) %s\n",i,valstr);
8 years ago
if ( (valuearray= cJSON_Parse(valstr)) != 0 )
8 years ago
{
8 years ago
if ( is_cJSON_Array(valuearray) != 0 )
8 years ago
{
8 years ago
for (j=0; j<cJSON_GetArraySize(valuearray); j++)
{
item = jitem(valuearray,j);
if ( jobj(item,"error") == 0 && (value= j64bits(item,"satoshis")) != 0 )
{
inputsum += value;
retval = 0;
break;
}
}
}
else
{
if ( jobj(valuearray,"error") == 0 && (value= j64bits(valuearray,"satoshis")) != 0 )
8 years ago
{
inputsum += value;
retval = 0;
}
}
8 years ago
free_json(valuearray);
8 years ago
}
free(valstr);
}
8 years ago
if ( retval < 0 )
break;
8 years ago
}
}
if ( i != numvins || basilisk_voutvin_validate(coin,jstr(retjson,"rawtx"),inputsum,amount,txfee) < 0 )
retval = -1;
8 years ago
else retval = 0;
8 years ago
}
return(retval);
}
int64_t iguana_esttxfee(struct supernet_info *myinfo,struct iguana_info *coin,char *rawtx,char *signedtx,int32_t numvins)
{
int64_t txfee = 0;
if ( coin->estimatedfee == 0 )
coin->estimatedfee = iguana_getestimatedfee(myinfo,coin);
if ( signedtx != 0 )
{
8 years ago
txfee = coin->estimatedfee * (strlen(signedtx)/2 + numvins);
free(signedtx);
}
else if ( rawtx != 0 )
{
8 years ago
txfee = coin->estimatedfee * (strlen(rawtx)/2 + numvins * 110);
free(rawtx);
}
return(txfee);
}
char *iguana_utxoduplicates(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *pubkey33,uint64_t satoshis,int32_t duplicates,int32_t *completedp,bits256 *signedtxidp,int32_t sendflag,cJSON *addresses)
8 years ago
{
uint8_t script[35]; int64_t txfee; int32_t i,spendlen; cJSON *txobj=0,*vins=0; char *rawtx=0,*signedtx=0,changeaddr[64];
8 years ago
*completedp = 0;
if ( signedtxidp != 0 )
memset(signedtxidp,0,sizeof(*signedtxidp));
bitcoin_address(changeaddr,coin->chain->pubtype,myinfo->persistent_pubkey33,33);
txfee = 10 * (coin->txfee + duplicates*coin->txfee/5);
if ( (txobj= bitcoin_txcreate(coin->symbol,coin->chain->isPoS,0,1,0)) != 0 )
8 years ago
{
if ( duplicates <= 0 )
duplicates = 1;
spendlen = bitcoin_pubkeyspend(script,0,pubkey33);
for (i=0; i<duplicates; i++)
bitcoin_txoutput(txobj,script,spendlen,satoshis);
rawtx = iguana_calcrawtx(myinfo,coin,&vins,txobj,satoshis * duplicates,changeaddr,txfee,addresses,0,0,0,0,"127.0.0.1",0,1);
if ( cJSON_GetArraySize(vins) > duplicates/4 )
{
free(rawtx);
rawtx = 0;
fprintf(stderr,"No point to recycle utxo when trying to create utxo duplicates, numvins.%d vs duplicates.%d\n",cJSON_GetArraySize(vins),duplicates);
free_json(vins);
return(rawtx);
}
8 years ago
//printf("duplicatesTX.(%s)\n",rawtx);
8 years ago
if ( signedtxidp != 0 )
{
if ( (signedtx= iguana_signrawtx(myinfo,coin,0,signedtxidp,completedp,vins,rawtx,0,0)) != 0 )
{
if ( *completedp != 0 )
8 years ago
{
8 years ago
printf("splitfunds signedtx.(%s)\n",signedtx);
if ( sendflag != 0 )
iguana_sendrawtransaction(myinfo,coin,signedtx);
free(rawtx);
rawtx = signedtx, signedtx = 0;
8 years ago
}
} else printf("error signing raw utxoduplicates tx\n");
}
}
if ( vins != 0 )
free_json(vins);
if ( txobj != 0 )
free_json(txobj);
return(rawtx);
}
8 years ago
int64_t iguana_verifytimelock(struct supernet_info *myinfo,struct iguana_info *coin,uint32_t timelocked,char *destaddr,bits256 txid,int32_t vout)
8 years ago
{
8 years ago
uint8_t script[35],script2[35],p2shscript[128],rmd160[20],addrtype; char *retstr,*spendscriptstr; int32_t p2shlen,spendlen; cJSON *sobj,*txout=0; int64_t value = 0;
bitcoin_addr2rmd160(&addrtype,rmd160,destaddr);
if ( addrtype != coin->chain->pubtype )
return(-1);
p2shlen = bitcoin_timelockspend(p2shscript,0,rmd160,timelocked);
calc_rmd160(0,rmd160,p2shscript,p2shlen);
spendlen = bitcoin_p2shspend(script,0,rmd160);
if ( coin->FULLNODE != 0 )
txout = dpow_gettxout(myinfo,coin,txid,vout);
else if ( (retstr= _dex_gettxout(myinfo,coin->symbol,txid,vout)) != 0 )
{
txout = cJSON_Parse(retstr);
free(retstr);
}
if ( txout != 0 )
{
if ( (sobj= jobj(txout,"scriptPubKey")) != 0 && (spendscriptstr= jstr(sobj,"hex")) == 0 )
{
if ( strlen(spendscriptstr) == spendlen*2 )
{
decode_hex(script2,spendlen,spendscriptstr);
if ( memcmp(script,script2,spendlen) != 0 )
return(-2);
value = SATOSHIDEN * jdouble(txout,"value");
} else return(-4);
}
free_json(txout);
return(value);
} return(-2);
}
char *iguana_utxorawtx(struct supernet_info *myinfo,struct iguana_info *coin,int32_t timelock,char *destaddr,char *changeaddr,uint64_t satoshis,uint64_t txfee,int32_t *completedp,int32_t sendflag,cJSON *utxos)
{
uint8_t script[35],p2shscript[128],rmd160[20],addrtype; bits256 txid; int32_t p2shlen,iter,spendlen; cJSON *retjson,*txcopy,*txobj=0,*vins=0; char *rawtx=0,*signedtx=0; uint32_t timelocked = 0;
8 years ago
*completedp = 0;
if ( iguana_addressvalidate(coin,&addrtype,destaddr) < 0 || iguana_addressvalidate(coin,&addrtype,changeaddr) < 0 )
return(clonestr("{\"error\":\"invalid coin address\"}"));
bitcoin_addr2rmd160(&addrtype,rmd160,changeaddr);
if ( addrtype != coin->chain->pubtype )
8 years ago
return(clonestr("{\"error\":\"invalid changeaddr type\"}"));
8 years ago
bitcoin_addr2rmd160(&addrtype,rmd160,destaddr);
if ( addrtype != coin->chain->pubtype )
return(clonestr("{\"error\":\"invalid dest address type\"}"));
if ( txfee == 0 && strcmp(coin->symbol,"BTC") != 0 && (txfee= coin->txfee) == 0 )
txfee = coin->chain->txfee;
8 years ago
retjson = cJSON_CreateObject();
if ( (txobj= bitcoin_txcreate(coin->symbol,coin->chain->isPoS,0,1,0)) != 0 )
{
8 years ago
if ( timelock == 0 )
spendlen = bitcoin_standardspend(script,0,rmd160);
else
{
timelocked = (uint32_t)(time(NULL)+timelock);
8 years ago
if ( (timelocked % 3600) != 0 )
timelocked += (3600 - (timelocked % 3600));
8 years ago
p2shlen = bitcoin_timelockspend(p2shscript,0,rmd160,timelocked);
calc_rmd160(0,rmd160,p2shscript,p2shlen);
spendlen = bitcoin_p2shspend(script,0,rmd160);
printf("timelock.%d spend timelocked %u\n",timelock,timelocked);
}
8 years ago
bitcoin_txoutput(txobj,script,spendlen,satoshis);
for (iter=0; iter<2; iter++)
8 years ago
{
txcopy = jduplicate(txobj);
if ( (rawtx= iguana_calcutxorawtx(myinfo,coin,&vins,txobj,satoshis,changeaddr,txfee,utxos,"",0,0)) != 0 )
8 years ago
{
if ( iter == 1 || txfee != 0 )
jaddstr(retjson,"rawtx",rawtx);
if ( (signedtx= iguana_signrawtx(myinfo,coin,0,&txid,completedp,vins,rawtx,0,0)) != 0 )
8 years ago
{
if ( (iter == 1 || txfee != 0) && *completedp != 0 )
8 years ago
{
jaddbits256(retjson,"txid",txid);
jaddstr(retjson,"signedtx",signedtx);
if ( sendflag != 0 )
{
//printf("send signedtx.(%s)\n",signedtx);
txid = iguana_sendrawtransaction(myinfo,coin,signedtx);
jaddbits256(retjson,"sent",txid);
}
8 years ago
}
} else printf("error signing raw utxorawtx tx\n");
} else printf("null rawtx from calcutxorawtx\n");
if ( txfee != 0 )
{
free_json(txcopy);
break;
}
else // must be BTC and txfee == 0
{
txfee = iguana_esttxfee(myinfo,coin,rawtx,signedtx,cJSON_GetArraySize(vins));
free_json(vins);
rawtx = signedtx = 0;
vins = 0;
*completedp = 0;
txobj = txcopy;
}
8 years ago
}
}
8 years ago
if ( timelock != 0 )
{
jaddnum(retjson,"timelock",timelock);
jaddnum(retjson,"timelocked",timelocked);
}
8 years ago
jaddstr(retjson,"result","success");
if ( *completedp != 0 )
jadd(retjson,"completed",jtrue());
else jadd(retjson,"completed",jfalse());
if ( vins != 0 )
free_json(vins);
if ( txobj != 0 )
free_json(txobj);
if ( rawtx != 0 )
free(rawtx);
if ( signedtx != 0 )
free(signedtx);
return(jprint(retjson,1));
}
8 years ago
char *basilisk_bitcoinrawtx(struct supernet_info *myinfo,struct iguana_info *coin,char *remoteaddr,uint32_t basilisktag,int32_t timeoutmillis,cJSON *valsobj,struct vin_info *V)
9 years ago
{
8 years ago
uint8_t buf[4096]; int32_t oplen,offset,minconf,spendlen; cJSON *vins,*addresses,*txobj = 0; uint32_t locktime; char *opreturn,*spendscriptstr,*changeaddr,*rawtx = 0; int64_t amount,txfee,burnamount;
8 years ago
if ( valsobj == 0 )
return(clonestr("{\"error\":\"null valsobj\"}"));
8 years ago
//if ( myinfo->IAMNOTARY != 0 || myinfo->NOTARY.RELAYID >= 0 )
// return(clonestr("{\"error\":\"special relays only do OUT and MSG\"}"));
9 years ago
vins = 0;
9 years ago
changeaddr = jstr(valsobj,"changeaddr");
8 years ago
if ( (amount= j64bits(valsobj,"satoshis")) == 0 )
amount = jdouble(valsobj,"value") * SATOSHIDEN;
9 years ago
if ( (txfee= j64bits(valsobj,"txfee")) == 0 )
txfee = coin->chain->txfee;
9 years ago
if ( txfee == 0 )
txfee = 10000;
8 years ago
spendscriptstr = jstr(valsobj,"spendscript");
9 years ago
minconf = juint(valsobj,"minconf");
8 years ago
locktime = jint(valsobj,"locktime");
8 years ago
if ( (addresses= jobj(valsobj,"addresses")) == 0 )
8 years ago
{
8 years ago
addresses = iguana_getaddressesbyaccount(myinfo,coin,"*");
8 years ago
jadd(valsobj,"addresses",addresses);
}
8 years ago
printf("use addresses.(%s)\n",jprint(addresses,0));
8 years ago
//printf("(%s) vals.(%s) change.(%s) spend.%s\n",coin->symbol,jprint(valsobj,0),changeaddr,spendscriptstr);
8 years ago
if ( changeaddr == 0 || changeaddr[0] == 0 || spendscriptstr == 0 || spendscriptstr[0] == 0 )
return(clonestr("{\"error\":\"invalid changeaddr or spendscript or addresses\"}"));
8 years ago
if ( coin != 0 )
9 years ago
{
if ( (txobj= bitcoin_txcreate(coin->symbol,coin->chain->isPoS,locktime,locktime==0?coin->chain->normal_txversion:coin->chain->locktime_txversion,juint(valsobj,"timestamp"))) != 0 )
9 years ago
{
8 years ago
spendlen = (int32_t)strlen(spendscriptstr) >> 1;
decode_hex(buf,spendlen,spendscriptstr);
bitcoin_txoutput(txobj,buf,spendlen,amount);
burnamount = offset = oplen = 0;
if ( (opreturn= jstr(valsobj,"opreturn")) != 0 && (oplen= is_hexstr(opreturn,0)) > 0 )
9 years ago
{
8 years ago
oplen >>= 1;
8 years ago
if ( (strcmp("BTC",coin->symbol) == 0 && oplen < 76) || coin->chain->do_opreturn == 0 )
8 years ago
{
8 years ago
decode_hex(&buf[sizeof(buf) - oplen],oplen,opreturn);
spendlen = datachain_datascript(coin,buf,&buf[sizeof(buf) - oplen],oplen);
if ( (burnamount= SATOSHIDEN * jdouble(valsobj,"burn")) < 10000 )
{
//burnamount = 10000;
printf("low burnamount %.8f\n",dstr(burnamount));
}
8 years ago
bitcoin_txoutput(txobj,buf,spendlen,burnamount);
oplen = 0;
} else oplen = datachain_opreturnscript(coin,buf,opreturn,oplen);
9 years ago
}
8 years ago
rawtx = iguana_calcrawtx(myinfo,coin,&vins,txobj,amount,changeaddr,txfee,addresses,minconf,oplen!=0?buf:0,oplen+offset,burnamount,remoteaddr,V,0);
8 years ago
if ( txfee == 0 )
{
txfee = iguana_esttxfee(myinfo,coin,rawtx,0,vins != 0 ? cJSON_GetArraySize(vins): 0);
rawtx = iguana_calcrawtx(myinfo,coin,&vins,txobj,amount,changeaddr,txfee,addresses,minconf,oplen!=0?buf:0,oplen+offset,burnamount,remoteaddr,V,0);
printf("new txfee %.8f\n",dstr(txfee));
}
printf("generated.(%s) vins.(%s)\n",rawtx!=0?rawtx:"",vins!=0?jprint(vins,0):"");
8 years ago
}
9 years ago
if ( rawtx != 0 )
{
9 years ago
if ( vins != 0 )
9 years ago
{
free_json(txobj);
9 years ago
valsobj = cJSON_CreateObject();
jadd(valsobj,"vins",vins);
9 years ago
jaddstr(valsobj,"rawtx",rawtx);
9 years ago
jaddstr(valsobj,"coin",coin->symbol);
9 years ago
free(rawtx);
8 years ago
return(jprint(valsobj,1));
9 years ago
} else free(rawtx);
9 years ago
}
if ( txobj != 0 )
free_json(txobj);
if ( vins != 0 )
free_json(vins);
8 years ago
return(clonestr("{\"error\":\"couldnt create rawtx\"}"));
9 years ago
}
8 years ago
return(clonestr("{\"error\":\"dont have coin to create rawtx\"}"));
9 years ago
}
9 years ago
8 years ago
/*
both fees are standard payments: OP_DUP OP_HASH160 FEE_RMD160 OP_EQUALVERIFY OP_CHECKSIG
Alice altpayment: OP_2 <alice_pubM> <bob_pubN> OP_2 OP_CHECKMULTISIG
Bob deposit:
OP_IF
<now + INSTANTDEX_LOCKTIME*2> OP_CLTV OP_DROP <alice_pubA0> OP_CHECKSIG
OP_ELSE
OP_HASH160 <hash(bob_privN)> OP_EQUALVERIFY <bob_pubB0> OP_CHECKSIG
OP_ENDIF
Bob paytx:
OP_IF
<now + INSTANTDEX_LOCKTIME> OP_CLTV OP_DROP <bob_pubB1> OP_CHECKSIG
OP_ELSE
OP_HASH160 <hash(alice_privM)> OP_EQUALVERIFY <alice_pubA0> OP_CHECKSIG
OP_ENDIF
Naming convention are pubAi are alice's pubkeys (seems only pubA0 and not pubA1)
pubBi are Bob's pubkeys
privN is Bob's privkey from the cut and choose deck as selected by Alice
privM is Alice's counterpart
pubN and pubM are the corresponding pubkeys for these chosen privkeys
Alice timeout event is triggered if INSTANTDEX_LOCKTIME elapses from the start of a FSM instance. Bob timeout event is triggered after INSTANTDEX_LOCKTIME*2
*/
8 years ago
8 years ago
#ifdef oldway
8 years ago
8 years ago
int32_t instantdex_feetxverify(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_swap *swap,cJSON *argjson)
{
cJSON *txobj; bits256 txid; uint32_t n; int32_t i,retval = -1,extralen=65536; int64_t insurance; uint64_t r;
struct iguana_msgtx msgtx; uint8_t script[512],serialized[8192],*extraspace=0; char coinaddr[64];
if ( swap->otherfee != 0 )
{
extraspace = calloc(1,extralen);
if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->otherfee->txbytes,extraspace,extralen,serialized)) != 0 )
{
r = swap->other.orderid;
if ( strcmp(coin->symbol,"BTC") == 0 )
insurance = swap->insurance + swap->bobcoin->chain->txfee;
else insurance = swap->altinsurance + swap->alicecoin->chain->txfee;
n = instantdex_outputinsurance(coinaddr,coin->chain->pubtype,script,insurance,r,r * (strcmp("BTC",coin->symbol) == 0));
if ( n == msgtx.vouts[0].pk_scriptlen )
{
if ( memcmp(script,msgtx.vouts[0].pk_script,n) == 0 )
{
printf("feetx script verified.(%s)\n",swap->otherfee->txbytes);
retval = 0;
}
else
{
for (i=0; i<n; i++)
printf("%02x",script[i]);
printf(" fee script\n");
for (i=0; i<n; i++)
printf("%02x",msgtx.vouts[0].pk_script[i]);
printf(" feetx mismatched\n");
printf("FEETX.(%s)\n",jprint(txobj,0));
}
} else printf("pk_scriptlen %d mismatch %d\n",msgtx.vouts[0].pk_scriptlen,n);
free_json(txobj);
} else printf("error converting (%s) txobj\n",swap->otherfee->txbytes);
} else printf("no feetx to verify\n");
if ( extraspace != 0 )
free(extraspace);
return(retval);
}
struct bitcoin_statetx *instantdex_bobtx(struct supernet_info *myinfo,struct basilisk_swap *swap,struct iguana_info *coin,int64_t amount,int32_t depositflag)
{
int32_t n,secretstart; struct bitcoin_statetx *ptr = 0; uint8_t script[1024]; uint32_t locktime; int64_t satoshis; char scriptstr[512];
if ( coin == 0 )
return(0);
satoshis = amount + depositflag*swap->insurance*100 + swap->bobcoin->chain->txfee;
n = instantdex_bobscript(script,0,&locktime,&secretstart,swap,depositflag);
if ( n < 0 )
{
printf("instantdex_bobtx couldnt generate bobscript deposit.%d\n",depositflag);
return(0);
}
printf("locktime.%u amount %.8f satoshis %.8f\n",locktime,dstr(amount),dstr(satoshis));
init_hexbytes_noT(scriptstr,script,n);
if ( (ptr= instantdex_signtx(depositflag != 0 ? "deposit" : "payment",myinfo,coin,locktime,scriptstr,satoshis,coin->txfee,swap->mine.minconfirms,swap->mine.offer.myside)) != 0 )
{
bitcoin_address(ptr->destaddr,coin->chain->p2shtype,script,n);
printf("BOBTX.%d (%s) -> %s\n",depositflag,ptr->txbytes,ptr->destaddr);
} else printf("sign error for bottx\n");
return(ptr);
}
int32_t instantdex_paymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_swap *swap,cJSON *argjson,int32_t depositflag)
{
cJSON *txobj; bits256 txid; uint32_t n,locktime; int32_t i,secretstart,retval = -1,extralen=65536; uint64_t x;
struct iguana_msgtx msgtx; uint8_t script[512],serialized[8192],*extraspace=0; int64_t amount;
if ( coin != 0 && swap->deposit != 0 )
{
amount = swap->BTCsatoshis + depositflag*swap->insurance*100 + swap->bobcoin->chain->txfee;
if ( (n= instantdex_bobscript(script,0,&locktime,&secretstart,swap,depositflag)) <= 0 )
return(retval);
extraspace = calloc(1,extralen);
if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->deposit->txbytes,extraspace,extralen,serialized)) != 0 )
{
memcpy(&script[secretstart],&msgtx.vouts[0].pk_script[secretstart],20);
printf("locktime.%u amount %.8f satoshis %.8f\n",locktime,dstr(amount),dstr(amount));
if ( msgtx.lock_time == locktime && msgtx.vouts[0].value == amount && n == msgtx.vouts[0].pk_scriptlen )
{
if ( memcmp(script,msgtx.vouts[0].pk_script,n) == 0 )
{
iguana_rwnum(0,&script[secretstart],sizeof(x),&x);
printf("deposit script verified\n");
if ( x == swap->otherdeck[swap->choosei][0] )
retval = 0;
else printf("deposit script verified but secret mismatch x.%llx vs otherdeck %llx\n",(long long)x,(long long)swap->otherdeck[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);
}
}
if ( extraspace != 0 )
free(extraspace);
return(retval);
}
int32_t instantdex_altpaymentverify(struct supernet_info *myinfo,struct iguana_info *coin,struct basilisk_swap *swap,cJSON *argjson)
{
cJSON *txobj; bits256 txid; uint32_t n; int32_t i,retval = -1,extralen = 65536;
struct iguana_msgtx msgtx; uint8_t script[512],serialized[8192],*extraspace=0; char *altmsigaddr=0,msigaddr[64];
if ( swap->altpayment != 0 && (altmsigaddr= jstr(argjson,"altmsigaddr")) != 0 )
{
extraspace = calloc(1,extralen);
if ( (txobj= bitcoin_hex2json(coin,&txid,&msgtx,swap->altpayment->txbytes,extraspace,extralen,serialized)) != 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("altpayment script verified\n");
retval = 0;
}
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");
}
} else printf("msig mismatch.(%s %s) or n.%d != %d\n",msigaddr,altmsigaddr,n,msgtx.vouts[0].pk_scriptlen);
free_json(txobj);
} else printf("bitcoin_hex2json error\n");
} else printf("no altpayment.%p or no altmsig.%s\n",swap->altpayment,altmsigaddr!=0?altmsigaddr:"");
if ( extraspace != 0 )
free(extraspace);
return(retval);
}
struct bitcoin_statetx *instantdex_alicetx(struct supernet_info *myinfo,struct iguana_info *alicecoin,char *msigaddr,bits256 pubAm,bits256 pubBn,int64_t amount,struct basilisk_swap *swap)
{
int32_t n; uint8_t script[1024]; char scriptstr[2048]; struct bitcoin_statetx *ptr = 0;
if ( alicecoin != 0 )
{
if ( bits256_nonz(pubAm) == 0 || bits256_nonz(pubBn) == 0 )
{
printf("instantdex_bobtx null pubAm.%llx or pubBn.%llx\n",(long long)pubAm.txid,(long long)pubBn.txid);
return(0);
}
n = instantdex_alicescript(script,0,msigaddr,alicecoin->chain->p2shtype,pubAm,pubBn);
init_hexbytes_noT(scriptstr,script,n);
if ( (ptr= instantdex_signtx("altpayment",myinfo,alicecoin,0,scriptstr,amount,alicecoin->txfee,swap->mine.minconfirms,swap->mine.offer.myside)) != 0 )
{
strcpy(ptr->destaddr,msigaddr);
printf("ALICETX (%s) -> %s\n",ptr->txbytes,ptr->destaddr);
}
}
return(ptr);
}
cJSON *BTC_makeclaimfunc(struct supernet_info *myinfo,struct exchange_info *exchange,struct basilisk_swap *swap,cJSON *argjson,cJSON *newjson,uint8_t **serdatap,int32_t *serdatalenp)
{
int32_t got_payment=1,bob_reclaimed=0;
*serdatap = 0, *serdatalenp = 0;
if ( instantdex_isbob(swap) == 0 )
{
// [BLOCKING: payfound] now Alice's turn to make sure payment is confrmed and send in claim or see bob's reclaim and reclaim
if ( got_payment != 0 )
{
//swap->privAm = swap->privkeys[swap->otherchoosei];
// sign if/else payment
}
else if ( bob_reclaimed != 0 )
{
}
}
else
{
// [BLOCKING: privM] Bob waits for privM either from Alice or alt blockchain
if ( bits256_nonz(swap->privAm) != 0 )
{
// a multisig tx for alicecoin
}
}
return(newjson);
}
#endif
8 years ago
8 years ago
int32_t basilisk_unspentfind(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *txidp,int32_t *voutp,uint8_t *spendscript,struct iguana_outpoint outpt,int64_t value)
8 years ago
{
8 years ago
struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2;
8 years ago
memset(txidp,0,sizeof(*txidp));
*voutp = -1;
portable_mutex_lock(&myinfo->bu_mutex);
HASH_ITER(hh,myinfo->wallet,wacct,tmp)
{
HASH_ITER(hh,wacct->waddr,waddr,tmp2)
{
8 years ago
printf("need to port basilisk_unspentfind\n");
8 years ago
}
}
portable_mutex_unlock(&myinfo->bu_mutex);
return(-1);
}
cJSON *basilisk_jsonmerge(char *symbol,cJSON *array)
{
int32_t i,j,n,m; cJSON *jobj,*iobj,*dest = cJSON_CreateArray();
if ( dest != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
m = cJSON_GetArraySize(dest);
iobj = jitem(array,i);
for (j=0; j<m; j++)
{
jobj = jitem(dest,j);
if ( bits256_cmp(jbits256(jobj,"txid"),jbits256(iobj,"txid")) == 0 && jint(jobj,"vout") == jint(iobj,"vout") )
{
//printf("(%s) == (%s)\n",jprint(iobj,0),jprint(jobj,0));
break;
}
}
if ( j == m )
{
jaddi(dest,jduplicate(iobj));
//printf("add.(%s) ",jprint(iobj,0));
} //else printf("j.%d != m.%d\n",j,m);
}
}
return(dest);
}
8 years ago
void basilisk_unspent_update(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json)
8 years ago
{
cJSON *unspents,*spends,*item; int32_t n; char *address; //struct iguana_waccount *wacct; struct iguana_waddress *waddr=0;
if ( (spends= jarray(&n,json,"spends")) != 0 && n > 0 )
8 years ago
{
8 years ago
item = jitem(spends,0);
if ( (address= jstr(item,"address")) != 0 )//&& (waddr= iguana_waddresssearch(myinfo,&wacct,address)) != 0 )
8 years ago
{
8 years ago
if ( myinfo->Cspends == 0 )
myinfo->Cspends = cJSON_CreateObject();
if ( jobj(myinfo->Cspends,coin->symbol) != 0 )
jdelete(myinfo->Cspends,coin->symbol);
jadd(myinfo->Cspends,coin->symbol,basilisk_jsonmerge(coin->symbol,spends));
8 years ago
//printf("S.(%s)\n",jprint(waddr->Cspends,0));
8 years ago
}
//printf("merge spends.(%s)\n",jprint(spends,0));
8 years ago
}
if ( (unspents= jarray(&n,json,"unspents")) != 0 && n > 0 )
8 years ago
{
8 years ago
item = jitem(unspents,0);
if ( (address= jstr(item,"address")) != 0 )//&& (waddr= iguana_waddresssearch(myinfo,&wacct,address)) != 0 )
8 years ago
{
8 years ago
if ( myinfo->Cunspents == 0 )
myinfo->Cunspents = cJSON_CreateObject();
if ( jobj(myinfo->Cunspents,coin->symbol) != 0 )
jdelete(myinfo->Cunspents,coin->symbol);
jadd(myinfo->Cunspents,coin->symbol,basilisk_jsonmerge(coin->symbol,unspents));
//printf("U.(%s)\n",jprint(myinfo->Cunspents,0));
8 years ago
}
//printf("merge unspents.(%s)\n",jprint(unspents,0));
8 years ago
}
}
void basilisk_unspents_process(struct supernet_info *myinfo,struct iguana_info *coin,char *retstr)
{
cJSON *retarray; int32_t i,n;
portable_mutex_lock(&myinfo->bu_mutex);
if ( myinfo->Cspends != 0 )
free_json(myinfo->Cspends), myinfo->Cspends = 0;
if ( myinfo->Cunspents != 0 )
free_json(myinfo->Cunspents), myinfo->Cunspents = 0;
if ( (retarray= cJSON_Parse(retstr)) != 0 )
{
if ( is_cJSON_Array(retarray) != 0 )
{
n = cJSON_GetArraySize(retarray);
for (i=0; i<n; i++)
basilisk_unspent_update(myinfo,coin,jitem(retarray,i));
} else basilisk_unspent_update(myinfo,coin,retarray);
free_json(retarray);
}
portable_mutex_unlock(&myinfo->bu_mutex);
}
8 years ago
cJSON *basilisk_balance_valsobj(struct supernet_info *myinfo,struct iguana_info *coin)
8 years ago
{
8 years ago
int32_t oldest,i,RTheight; cJSON *vals;
8 years ago
for (i=oldest=0; i<BASILISK_MAXRELAYS; i++)
if ( (RTheight= coin->relay_RTheights[i]) != 0 && (oldest == 0 || RTheight < oldest) )
oldest = RTheight;
8 years ago
vals = cJSON_CreateObject();
8 years ago
jaddnum(vals,"firstheight",oldest);
jaddnum(vals,"history",3);
jaddstr(vals,"coin",coin->symbol);
8 years ago
return(vals);
}
void basilisk_unspents_update(struct supernet_info *myinfo,struct iguana_info *coin)
{
char *retstr; cJSON *vals;
if ( (vals= basilisk_balance_valsobj(myinfo,coin)) != 0 && (retstr= basilisk_balances(myinfo,coin,0,0,GENESIS_PUBKEY,vals,"")) != 0 )
8 years ago
{
basilisk_unspents_process(myinfo,coin,retstr);
8 years ago
free(retstr);
8 years ago
}
8 years ago
free_json(vals);
8 years ago
}