jl777
7 years ago
committed by
GitHub
35 changed files with 2561 additions and 1209 deletions
@ -0,0 +1,339 @@ |
|||
|
|||
/******************************************************************************
|
|||
* Copyright © 2014-2017 The SuperNET Developers. * |
|||
* * |
|||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * |
|||
* the top-level directory of this distribution for the individual copyright * |
|||
* holder information and the developer policies on copyright and licensing. * |
|||
* * |
|||
* Unless otherwise agreed in a custom licensing agreement, no part of the * |
|||
* SuperNET software, including this file may be copied, modified, propagated * |
|||
* or distributed except according to the terms contained in the LICENSE file * |
|||
* * |
|||
* Removal or modification of this copyright notice is prohibited. * |
|||
* * |
|||
******************************************************************************/ |
|||
//
|
|||
// LP_cache.c
|
|||
// marketmaker
|
|||
//
|
|||
|
|||
cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len) |
|||
{ |
|||
uint8_t *extraspace; cJSON *txobj; char str[65],str2[65]; struct iguana_msgtx msgtx; bits256 checktxid; |
|||
extraspace = calloc(1,4000000); |
|||
memset(&msgtx,0,sizeof(msgtx)); |
|||
txobj = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,4000000,serialized,len,0,0,coin->zcash); |
|||
//printf("TX.(%s) match.%d\n",jprint(txobj,0),bits256_cmp(txid,checktxid));
|
|||
free(extraspace); |
|||
if ( bits256_cmp(txid,checktxid) != 0 ) |
|||
{ |
|||
printf("%s LP_transaction_fromdata mismatched txid %s vs %s\n",coin->symbol,bits256_str(str,txid),bits256_str(str2,checktxid)); |
|||
free_json(txobj); |
|||
txobj = 0; |
|||
} |
|||
return(txobj); |
|||
} |
|||
|
|||
struct LP_transaction *LP_create_transaction(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len,int32_t height,long fpos) |
|||
{ |
|||
cJSON *txobj; bits256 spenttxid; int32_t i,spentvout,numvins,numvouts; cJSON *vout,*vin,*vins,*vouts; struct LP_transaction *tx; char str[65]; |
|||
if ( (tx= LP_transactionfind(coin,txid)) != 0 ) |
|||
return(tx); |
|||
if ( (txobj= LP_transaction_fromdata(coin,txid,serialized,len)) != 0 ) |
|||
{ |
|||
vins = jarray(&numvins,txobj,"vin"); |
|||
vouts = jarray(&numvouts,txobj,"vout"); |
|||
tx = LP_transactionadd(coin,txid,height,numvouts,numvins); |
|||
tx->serialized = serialized; |
|||
//free(serialized);
|
|||
tx->fpos = fpos; |
|||
tx->len = tx->len; |
|||
tx->SPV = tx->height = height; |
|||
//printf("tx.%s numvins.%d numvouts.%d\n",bits256_str(str,txid),numvins,numvouts);
|
|||
for (i=0; i<numvouts; i++) |
|||
{ |
|||
vout = jitem(vouts,i); |
|||
tx->outpoints[i].value = LP_value_extract(vout,0); |
|||
tx->outpoints[i].interest = SATOSHIDEN * jdouble(vout,"interest"); |
|||
LP_destaddr(tx->outpoints[i].coinaddr,vout); |
|||
//printf("from transaction init %s %s %s/v%d <- %.8f\n",coin->symbol,tx->outpoints[i].coinaddr,bits256_str(str,txid),i,dstr(tx->outpoints[i].value));
|
|||
LP_address_utxoadd("LP_create_transaction",coin,tx->outpoints[i].coinaddr,txid,i,tx->outpoints[i].value,height,-1); |
|||
} |
|||
for (i=0; i<numvins; i++) |
|||
{ |
|||
vin = jitem(vins,i); |
|||
spenttxid = jbits256(vin,"txid"); |
|||
spentvout = jint(vin,"vout"); |
|||
if ( i == 0 && bits256_nonz(spenttxid) == 0 ) |
|||
continue; |
|||
if ( (tx= LP_transactionfind(coin,spenttxid)) != 0 ) |
|||
{ |
|||
if ( spentvout < tx->numvouts ) |
|||
{ |
|||
if ( tx->outpoints[spentvout].spendheight <= 0 ) |
|||
{ |
|||
tx->outpoints[spentvout].spendtxid = txid; |
|||
tx->outpoints[spentvout].spendvini = i; |
|||
tx->outpoints[spentvout].spendheight = height > 0 ? height : 1; |
|||
LP_address_utxoadd("LP_transactioninit iter1",coin,tx->outpoints[spentvout].coinaddr,spenttxid,spentvout,tx->outpoints[spentvout].value,-1,height>0?height:1); |
|||
if ( 0 && strcmp(coin->symbol,"REVS") == 0 ) |
|||
printf("spend %s %s/v%d at ht.%d\n",coin->symbol,bits256_str(str,tx->txid),spentvout,height); |
|||
} |
|||
} else printf("LP_transactioninit: %s spentvout.%d < numvouts.%d spendheight.%d\n",bits256_str(str,spenttxid),spentvout,tx->numvouts,tx->outpoints[spentvout].spendheight); |
|||
} //else printf("LP_transactioninit: couldnt find (%s) ht.%d %s\n",bits256_str(str,spenttxid),height,jprint(vin,0));
|
|||
if ( bits256_cmp(spenttxid,txid) == 0 ) |
|||
printf("spending same tx's %p vout ht.%d %s.[%d] s%d\n",tx,height,bits256_str(str,txid),tx!=0?tx->numvouts:0,spentvout); |
|||
} |
|||
free_json(txobj); |
|||
} |
|||
return(tx); |
|||
} |
|||
|
|||
void LP_SPV_store(struct iguana_info *coin,bits256 txid,int32_t height) |
|||
{ |
|||
FILE *fp; char fname[512]; struct LP_transaction *tx = 0; |
|||
if ( (tx= LP_transactionfind(coin,txid)) != 0 && tx->serialized != 0 && tx->len > 0 && tx->fpos == 0 ) |
|||
{ |
|||
sprintf(fname,"%s/UNSPENTS/%s.SPV",GLOBAL_DBDIR,coin->symbol), OS_portable_path(fname); |
|||
if ( (fp= OS_appendfile(fname)) != 0 ) |
|||
{ |
|||
fwrite(&tx->txid,1,sizeof(tx->txid),fp); |
|||
fwrite(&tx->len,1,sizeof(tx->len),fp); |
|||
fwrite(&tx->height,1,sizeof(tx->height),fp); |
|||
tx->fpos = ftell(fp); |
|||
fwrite(tx->serialized,1,tx->len,fp); |
|||
fclose(fp); |
|||
} |
|||
} //else printf("cant store %s %s tx.%p [%d] fpos.%ld SPV.%d\n",coin->symbol,bits256_str(str,txid),tx,tx!=0?tx->len:-1,tx!=0?tx->fpos:-1,tx!=0?tx->SPV:-1);
|
|||
} |
|||
|
|||
int32_t LP_cacheitem(struct iguana_info *coin,FILE *fp) |
|||
{ |
|||
bits256 txid,hash; long fpos; int32_t offset,retval,height,len; uint8_t *serialized; char str[65],str2[65]; |
|||
fpos = ftell(fp); |
|||
if ( fread(&txid,1,sizeof(txid),fp) == sizeof(txid) && fread(&len,1,sizeof(len),fp) == sizeof(len) && fread(&height,1,sizeof(height),fp) == sizeof(height) && len < 100000 ) |
|||
{ |
|||
offset = (int32_t)(sizeof(txid) + sizeof(len) + sizeof(height)); |
|||
serialized = malloc(len); |
|||
if ( (retval= (int32_t)fread(serialized,1,len,fp)) == len ) |
|||
{ |
|||
hash = bits256_doublesha256(0,serialized,len); |
|||
if ( bits256_cmp(hash,txid) == 0 ) |
|||
{ |
|||
//printf("%s validated in cache\n",bits256_str(str,hash));
|
|||
LP_create_transaction(coin,txid,serialized,len,height,fpos+offset); |
|||
return((int32_t)(ftell(fp) - fpos)); |
|||
} |
|||
printf("%s vs %s did not validated in cache\n",bits256_str(str,hash),bits256_str(str2,txid)); |
|||
} else printf("retval.%d vs len.%d\n",retval,len); |
|||
} else printf("fread error\n"); |
|||
return(-1); |
|||
} |
|||
|
|||
void LP_cacheptrs_init(struct iguana_info *coin) |
|||
{ |
|||
char fname[1024]; FILE *fp; int32_t count,tflag=0; long n,fsize=0,len = 0; |
|||
sprintf(fname,"%s/UNSPENTS/%s.SPV",GLOBAL_DBDIR,coin->symbol), OS_portable_path(fname); |
|||
fp = fopen(fname,"rb"); |
|||
count = 0; |
|||
if ( fp != 0 ) |
|||
{ |
|||
fseek(fp,0,SEEK_END); |
|||
fsize = ftell(fp); |
|||
rewind(fp); |
|||
while ( len < fsize ) |
|||
{ |
|||
if ( (n= LP_cacheitem(coin,fp)) < 0 ) |
|||
{ |
|||
printf("cacheitem error at %s offset.%ld when fsize.%ld\n",coin->symbol,len,fsize); |
|||
tflag = 1; |
|||
break; |
|||
} |
|||
count++; |
|||
len += n; |
|||
} |
|||
printf("loaded %s %d entries total len.%ld\n",fname,count,len); |
|||
fclose(fp); |
|||
} //else printf("couldnt find.(%s)\n",fname);
|
|||
if ( tflag != 0 ) |
|||
OS_truncate(fname,len); |
|||
} |
|||
|
|||
bits256 iguana_merkle(bits256 *tree,int32_t txn_count) |
|||
{ |
|||
int32_t i,n=0,prev; uint8_t serialized[sizeof(bits256) * 2]; |
|||
if ( txn_count == 1 ) |
|||
return(tree[0]); |
|||
prev = 0; |
|||
while ( txn_count > 1 ) |
|||
{ |
|||
if ( (txn_count & 1) != 0 ) |
|||
tree[prev + txn_count] = tree[prev + txn_count-1], txn_count++; |
|||
n += txn_count; |
|||
for (i=0; i<txn_count; i+=2) |
|||
{ |
|||
iguana_rwbignum(1,serialized,sizeof(*tree),tree[prev + i].bytes); |
|||
iguana_rwbignum(1,&serialized[sizeof(*tree)],sizeof(*tree),tree[prev + i + 1].bytes); |
|||
tree[n + (i >> 1)] = bits256_doublesha256(0,serialized,sizeof(serialized)); |
|||
} |
|||
prev = n; |
|||
txn_count >>= 1; |
|||
} |
|||
return(tree[n]); |
|||
} |
|||
|
|||
bits256 validate_merkle(int32_t pos,bits256 txid,cJSON *proofarray,int32_t proofsize) |
|||
{ |
|||
int32_t i; uint8_t serialized[sizeof(bits256) * 2]; bits256 hash,proof; |
|||
hash = txid; |
|||
for (i=0; i<proofsize; i++) |
|||
{ |
|||
proof = jbits256i(proofarray,i); |
|||
if ( (pos & 1) == 0 ) |
|||
{ |
|||
iguana_rwbignum(1,&serialized[0],sizeof(hash),hash.bytes); |
|||
iguana_rwbignum(1,&serialized[sizeof(hash)],sizeof(proof),proof.bytes); |
|||
} |
|||
else |
|||
{ |
|||
iguana_rwbignum(1,&serialized[0],sizeof(proof),proof.bytes); |
|||
iguana_rwbignum(1,&serialized[sizeof(hash)],sizeof(hash),hash.bytes); |
|||
} |
|||
hash = bits256_doublesha256(0,serialized,sizeof(serialized)); |
|||
pos >>= 1; |
|||
} |
|||
return(hash); |
|||
} |
|||
|
|||
bits256 LP_merkleroot(struct iguana_info *coin,struct electrum_info *ep,int32_t height) |
|||
{ |
|||
cJSON *hdrobj; bits256 merkleroot; |
|||
memset(merkleroot.bytes,0,sizeof(merkleroot)); |
|||
if ( coin->cachedmerkleheight == height ) |
|||
return(coin->cachedmerkle); |
|||
if ( (hdrobj= electrum_getheader(coin->symbol,ep,&hdrobj,height)) != 0 ) |
|||
{ |
|||
if ( jobj(hdrobj,"merkle_root") != 0 ) |
|||
{ |
|||
merkleroot = jbits256(hdrobj,"merkle_root"); |
|||
if ( bits256_nonz(merkleroot) != 0 ) |
|||
{ |
|||
coin->cachedmerkle = merkleroot; |
|||
coin->cachedmerkleheight = height; |
|||
} |
|||
} |
|||
free_json(hdrobj); |
|||
} else printf("couldnt get header for ht.%d\n",height); |
|||
return(merkleroot); |
|||
} |
|||
|
|||
int32_t LP_merkleproof(struct iguana_info *coin,char *coinaddr,struct electrum_info *ep,bits256 txid,int32_t height) |
|||
{ |
|||
struct LP_transaction *tx=0; cJSON *merkobj,*merkles,*retjson; bits256 roothash,merkleroot; int32_t m,SPV = 0; |
|||
if ( height <= 0 ) |
|||
return(0); |
|||
if ( (tx= LP_transactionfind(coin,txid)) == 0 && strcmp(coinaddr,coin->smartaddr) == 0 ) |
|||
{ |
|||
if ( (retjson= electrum_transaction(coin->symbol,ep,&retjson,txid)) != 0 ) |
|||
free_json(retjson); |
|||
} |
|||
if ( tx != 0 ) |
|||
{ |
|||
tx->height = height; |
|||
if ( tx->SPV > 0 ) |
|||
return(tx->SPV); |
|||
} |
|||
if ( (merkobj= electrum_getmerkle(coin->symbol,ep,&merkobj,txid,height)) != 0 ) |
|||
{ |
|||
char str[65],str2[65],str3[65]; |
|||
SPV = -1; |
|||
memset(roothash.bytes,0,sizeof(roothash)); |
|||
if ( (merkles= jarray(&m,merkobj,"merkle")) != 0 ) |
|||
{ |
|||
roothash = validate_merkle(jint(merkobj,"pos"),txid,merkles,m); |
|||
merkleroot = LP_merkleroot(coin,ep,height); |
|||
if ( bits256_nonz(merkleroot) != 0 ) |
|||
{ |
|||
if ( bits256_cmp(merkleroot,roothash) == 0 ) |
|||
{ |
|||
SPV = height; |
|||
LP_SPV_store(coin,txid,height); |
|||
if ( tx != 0 ) |
|||
{ |
|||
tx->SPV = height; |
|||
if ( tx->serialized != 0 ) |
|||
{ |
|||
free(tx->serialized); |
|||
tx->serialized = 0; |
|||
tx->len = 0; |
|||
} |
|||
} |
|||
//printf("validated MERK %s ht.%d -> %s root.(%s)\n",bits256_str(str,txid),height,jprint(merkobj,0),bits256_str(str2,roothash));
|
|||
} |
|||
else printf("ERROR MERK %s ht.%d -> %s root.(%s) vs %s\n",bits256_str(str,txid),height,jprint(merkobj,0),bits256_str(str2,roothash),bits256_str(str3,merkleroot)); |
|||
} else SPV = 0; |
|||
} |
|||
if ( SPV < 0 ) |
|||
{ |
|||
printf("MERKLE DIDNT VERIFY.%s %s ht.%d (%s)\n",coin->symbol,bits256_str(str,txid),height,jprint(merkobj,0)); |
|||
if ( jobj(merkobj,"error") != 0 ) |
|||
SPV = 0; // try again later
|
|||
} |
|||
free_json(merkobj); |
|||
} |
|||
return(SPV); |
|||
} |
|||
|
|||
char *LP_unspents_filestr(char *symbol,char *addr) |
|||
{ |
|||
char fname[1024]; long fsize; |
|||
sprintf(fname,"%s/UNSPENTS/%s_%s",GLOBAL_DBDIR,symbol,addr), OS_portable_path(fname); |
|||
return(OS_filestr(&fsize,fname)); |
|||
} |
|||
|
|||
void LP_unspents_cache(char *symbol,char *addr,char *arraystr,int32_t updatedflag) |
|||
{ |
|||
char fname[1024]; FILE *fp=0; |
|||
sprintf(fname,"%s/UNSPENTS/%s_%s",GLOBAL_DBDIR,symbol,addr), OS_portable_path(fname); |
|||
//printf("unspents cache.(%s) for %s %s, updated.%d\n",fname,symbol,addr,updatedflag);
|
|||
if ( updatedflag == 0 && (fp= fopen(fname,"rb")) == 0 ) |
|||
updatedflag = 1; |
|||
else if ( fp != 0 ) |
|||
fclose(fp); |
|||
if ( updatedflag != 0 && (fp= fopen(fname,"wb")) != 0 ) |
|||
{ |
|||
fwrite(arraystr,1,strlen(arraystr),fp); |
|||
fclose(fp); |
|||
} |
|||
} |
|||
|
|||
uint64_t LP_unspents_load(char *symbol,char *addr) |
|||
{ |
|||
char *arraystr; uint64_t balance = 0; int32_t i,n; cJSON *retjson,*item; struct iguana_info *coin; |
|||
if ( (coin= LP_coinfind(symbol)) != 0 ) |
|||
{ |
|||
if ( (arraystr= LP_unspents_filestr(symbol,addr)) != 0 ) |
|||
{ |
|||
if ( (retjson= cJSON_Parse(arraystr)) != 0 ) |
|||
{ |
|||
//printf("PROCESS UNSPENTS %s\n",arraystr);
|
|||
if ( (n= cJSON_GetArraySize(retjson)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = jitem(retjson,i); |
|||
balance += j64bits(item,"value"); |
|||
} |
|||
} |
|||
electrum_process_array(coin,coin->electrum,coin->smartaddr,retjson,1); |
|||
free_json(retjson); |
|||
} |
|||
free(arraystr); |
|||
} |
|||
} |
|||
return(balance); |
|||
} |
|||
|
|||
|
|||
|
@ -1,3 +1,3 @@ |
|||
#!/bin/bash |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"bot_settings\",\"botid\":$1,\"newprice\":$1,\"newvolume\":$2}" |
|||
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"bot_settings\",\"botid\":$1,\"newprice\":$2,\"newvolume\":$3}" |
|||
|
@ -0,0 +1,3 @@ |
|||
#!/bin/bash |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"bot_statuslist\"}" |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,3 @@ |
|||
ls -l /proc/$1/fd |
|||
echo sockstat |
|||
cat /proc/$1/net/sockstat |
@ -1,3 +1,3 @@ |
|||
#!/bin/bash |
|||
source userpass |
|||
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"KMD\",\"rel\":\"BTC\",\"basevolume\":10.0\",price\":0.0005}" |
|||
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"KMD\",\"rel\":\"BTC\",\"basevolume\":10.0\",\"price\":0.0005}" |
|||
|
Loading…
Reference in new issue