Browse Source

Electrum tx cache

beta
jl777 7 years ago
parent
commit
760a31b337
  1. 8
      iguana/exchanges/LP_include.h
  2. 4
      iguana/exchanges/LP_prices.c
  3. 161
      iguana/exchanges/LP_rpc.c
  4. 77
      iguana/exchanges/LP_socket.c
  5. 8
      iguana/exchanges/LP_utxo.c

8
iguana/exchanges/LP_include.h

@ -172,7 +172,8 @@ struct LP_outpoint { bits256 spendtxid; uint64_t value,interest; int32_t spendvi
struct LP_transaction
{
UT_hash_handle hh;
bits256 txid; int32_t height,numvouts,numvins; //uint32_t timestamp;
bits256 txid; int32_t height,numvouts,numvins,len; //uint32_t timestamp;
uint8_t *serialized;
struct LP_outpoint outpoints[];
};
@ -303,6 +304,8 @@ struct LP_address *_LP_addressfind(struct iguana_info *coin,char *coinaddr);
struct LP_address *_LP_addressadd(struct iguana_info *coin,char *coinaddr);
int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,struct iguana_msgtx *msgtx,char **signedtxp,bits256 *signedtxidp,struct vin_info *V,int32_t numinputs,char *rawtx,cJSON *vins,cJSON *privkeysjson);
//void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo);
struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout);
int32_t LP_destaddr(char *destaddr,cJSON *item);
int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration);
struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid);
cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJSON *txobj);
@ -310,10 +313,11 @@ int32_t LP_mempoolscan(char *symbol,bits256 searchtxid);
int32_t LP_txheight(struct iguana_info *coin,bits256 txid);
int32_t LP_address_utxoadd(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight);
cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrumret);
cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout);
cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout);
void LP_postutxos(char *symbol,char *coinaddr);
int32_t LP_listunspent_both(char *symbol,char *coinaddr);
uint16_t LP_randpeer(char *destip);
cJSON *bitcoin_data2json(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *txidp,struct iguana_msgtx *msgtx,uint8_t *extraspace,int32_t extralen,uint8_t *serialized,int32_t len,cJSON *vins,int32_t suppress_pubkeys);
//int32_t LP_butxo_findeither(bits256 txid,int32_t vout);
cJSON *LP_listunspent(char *symbol,char *coinaddr);
int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid);

4
iguana/exchanges/LP_prices.c

@ -394,10 +394,10 @@ double LP_pricecache(struct LP_quoteinfo *qp,char *base,char *rel,bits256 txid,i
ptr->price = 0.;
printf("LP_pricecache: set %s/%s ptr->price %.8f\n",base,rel,ptr->price);
}
printf("found %s/%s %.8f\n",base,rel,ptr->price);
printf(">>>>>>>>>> found %s/%s %.8f\n",base,rel,ptr->price);
return(ptr->price);
}
char str[65]; printf("cachemiss %s/%s %s/v%d\n",base,rel,bits256_str(str,txid),vout);
//char str[65]; printf("cachemiss %s/%s %s/v%d\n",base,rel,bits256_str(str,txid),vout);
return(0.);
}

161
iguana/exchanges/LP_rpc.c

@ -243,7 +243,7 @@ cJSON *LP_paxprice(char *fiat)
cJSON *LP_gettx(char *symbol,bits256 txid)
{
char buf[128],str[65],*hexstr; int32_t len; bits256 checktxid; cJSON *retjson; struct iguana_info *coin; struct iguana_msgtx msgtx; uint8_t *extraspace,*serialized;
struct iguana_info *coin; char buf[512],str[65]; cJSON *retjson;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
@ -258,49 +258,38 @@ cJSON *LP_gettx(char *symbol,bits256 txid)
}
else
{
sprintf(buf,"[\"%s\"]",bits256_str(str,txid));
if ( (retjson= electrum_transaction(symbol,coin->electrum,&retjson,txid)) != 0 )
{
hexstr = jprint(retjson,1);
if ( strlen(hexstr) > 20000 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("rawtransaction too big %d\n",(int32_t)strlen(hexstr));
free(hexstr);
return(cJSON_Parse("{\"error\":\"transaction too big\"}"));
}
if ( hexstr[0] == '"' && hexstr[strlen(hexstr)-1] == '"' )
hexstr[strlen(hexstr)-1] = 0;
if ( (len= is_hexstr(hexstr+1,0)) > 2 )
{
memset(&msgtx,0,sizeof(msgtx));
len = (int32_t)strlen(hexstr+1) >> 1;
serialized = malloc(len);
decode_hex(serialized,len,hexstr+1);
free(hexstr);
//printf("DATA.(%s)\n",hexstr+1);
extraspace = calloc(1,1000000);
retjson = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,1000000,serialized,len,0,0);
free(serialized);
free(extraspace);
//printf("TX.(%s) match.%d\n",jprint(retjson,0),bits256_cmp(txid,checktxid));
return(retjson);
} else printf("non-hex tx.(%s)\n",hexstr);
free(hexstr);
return(cJSON_Parse("{\"error\":\"non hex transaction\"}"));
} else printf("failed blockchain.transaction.get %s %s\n",coin->symbol,buf);
return(retjson);
else printf("failed blockchain.transaction.get %s %s\n",coin->symbol,buf);
return(cJSON_Parse("{\"error\":\"no transaction bytes\"}"));
}
}
cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout)
cJSON *LP_gettxout_json(bits256 txid,int32_t vout,int32_t height,char *coinaddr,uint64_t value)
{
cJSON *retjson,*addresses,*sobj;
retjson = cJSON_CreateObject();
jaddnum(retjson,"value",dstr(value));
jaddnum(retjson,"height",height);
jaddbits256(retjson,"txid",txid);
jaddnum(retjson,"vout",vout);
addresses = cJSON_CreateArray();
jaddistr(addresses,coinaddr);
sobj = cJSON_CreateObject();
jaddnum(sobj,"reqSigs",1);
jaddstr(sobj,"type","pubkey");
jadd(sobj,"addresses",addresses);
jadd(retjson,"scriptPubKey",sobj);
printf("GETTXOUT.(%s)\n",jprint(retjson,0));
return(retjson);
}
cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout)
{
char buf[128],str[65],coinaddr[64],*hexstr; uint64_t value; uint8_t *serialized; cJSON *sobj,*addresses,*item,*array,*hexobj,*retjson=0; int32_t i,n,v,len; bits256 t; struct iguana_info *coin;
char buf[128],str[65]; cJSON *item,*array,*vouts,*txobj,*retjson=0; int32_t i,v,n; bits256 t; struct iguana_info *coin; struct LP_transaction *tx; struct LP_address_utxo *up;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 )
if ( (coin= LP_coinfind(symbol)) == 0 )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( bits256_nonz(txid) == 0 )
return(cJSON_Parse("{\"error\":\"null txid\"}"));
@ -311,84 +300,52 @@ cJSON *LP_gettxout(char *symbol,bits256 txid,int32_t vout)
}
else
{
printf("gettxout v%d\n",vout);
sprintf(buf,"[\"%s\"]",bits256_str(str,txid));
if ( (hexobj= electrum_transaction(symbol,coin->electrum,&hexobj,txid)) != 0 )
if ( (tx= LP_transactionfind(coin,txid)) != 0 && vout < tx->numvouts )
{
if ( tx->outpoints[vout].spendheight > 0 )
return(0);
return(LP_gettxout_json(txid,vout,tx->height,tx->outpoints[vout].coinaddr,tx->outpoints[vout].value));
}
if ( coinaddr[0] == 0 )
{
if ( (txobj= electrum_transaction(symbol,coin->electrum,&txobj,txid)) != 0 )
{
if ( (vouts= jarray(&n,txobj,"vout")) != 0 && n > 0 )
LP_destaddr(coinaddr,jitem(vouts,vout));
free_json(txobj);
}
}
if ( coinaddr[0] != 0 )
{
hexstr = jprint(hexobj,1);
if ( strlen(hexstr) > 20000 )
if ( (up= LP_address_utxofind(coin,coinaddr,txid,vout)) != 0 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("rawtransaction too big %d\n",(int32_t)strlen(hexstr));
free(hexstr);
return(cJSON_Parse("{\"error\":\"transaction too big\"}"));
if ( up->spendheight > 0 )
return(0);
return(LP_gettxout_json(txid,vout,up->U.height,coinaddr,up->U.value));
}
if ( hexstr[0] == '"' && hexstr[strlen(hexstr)-1] == '"' )
hexstr[strlen(hexstr)-1] = 0;
if ( (len= is_hexstr(hexstr+1,0)) > 2 )
if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr)) != 0 )
{
len = (int32_t)strlen(hexstr+1) >> 1;
serialized = malloc(len);
decode_hex(serialized,len,hexstr+1);
LP_swap_coinaddr(coin,coinaddr,&value,serialized,len,vout);
//printf("HEX.(%s) len.%d %s %.8f\n",hexstr+1,len,coinaddr,dstr(value));
free(hexstr);
if ( (array= electrum_address_listunspent(coin->symbol,0,&array,coinaddr)) != 0 )
//printf("array.(%s)\n",jprint(array,0));
if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
//printf("array.(%s)\n",jprint(array,0));
if ( array != 0 && (n= cJSON_GetArraySize(array)) > 0 )
for (i=0; i<n; i++)
{
for (i=0; i<n; i++)
item = jitem(array,i);
t = jbits256(item,"tx_hash");
v = jint(item,"tx_pos");
if ( v == vout && bits256_cmp(t,txid) == 0 )
{
item = jitem(array,i);
t = jbits256(item,"tx_hash");
v = jint(item,"tx_pos");
if ( v == vout && bits256_cmp(t,txid) == 0 )
{
retjson = cJSON_CreateObject();
/*{
"bestblock": "002f7bbe3973b735f535d472501962e86ce8dbc76c73ac5a310a905931b907fa",
"confirmations": 7,
"value": 2013.10431750,
"scriptPubKey": {
"asm": "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828 OP_CHECKSIG",
"hex": "2103b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828ac",
"reqSigs": 1,
"type": "pubkey",
"addresses": [
"RNJmgYaFF5DbnrNUX6pMYz9rcnDKC2tuAc"
]
},
"version": 1,
"coinbase": false
}*/
if ( value != j64bits(item,"value") )
printf("LP_gettxout: value %llu != %llu\n",(long long)value,(long long)j64bits(item,"value"));
jaddnum(retjson,"value",dstr(value));
jaddbits256(retjson,"txid",t);
jaddnum(retjson,"vout",v);
addresses = cJSON_CreateArray();
jaddistr(addresses,coinaddr);
sobj = cJSON_CreateObject();
jaddnum(sobj,"reqSigs",1);
jaddstr(sobj,"type","pubkey");
jadd(sobj,"addresses",addresses);
jadd(retjson,"scriptPubKey",sobj);
printf("GETTXOUT.(%s)\n",jprint(retjson,0));
break;
}
retjson = LP_gettxout_json(txid,vout,jint(item,"height"),coinaddr,j64bits(item,"value"));
break;
}
}
free_json(array);
}
} else free(hexstr);
if ( retjson == 0 )
{
free_json(array);
if ( retjson != 0 )
return(retjson);
}
return(retjson);
}
printf("couldnt find %s/v%d\n",bits256_str(str,txid),vout);
return(cJSON_Parse("{\"error\":\"couldnt get tx\"}"));
}
}

77
iguana/exchanges/LP_socket.c

@ -310,7 +310,7 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep
v = jint(item,"vout");
value = LP_value_extract(item,0);
ht = LP_txheight(coin,txid);
if ( (retjson= LP_gettxout(coin->symbol,txid,v)) != 0 )
if ( (retjson= LP_gettxout(coin->symbol,coinaddr,txid,v)) != 0 )
free_json(retjson);
else
{
@ -527,12 +527,79 @@ cJSON *electrum_estimatefee(char *symbol,struct electrum_info *ep,cJSON **retjso
cJSON *electrum_getheader(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t n) { return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_header",n,ELECTRUM_TIMEOUT)); }
cJSON *electrum_getchunk(char *symbol,struct electrum_info *ep,cJSON **retjsonp,int32_t n) { return(electrum_intarg(symbol,ep,retjsonp,"blockchain.block.get_chunk",n,ELECTRUM_TIMEOUT)); }
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,1000000);
memset(&msgtx,0,sizeof(msgtx));
txobj = bitcoin_data2json(coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->height,&checktxid,&msgtx,extraspace,1000000,serialized,len,0,0);
//printf("TX.(%s) match.%d\n",jprint(retjson,0),bits256_cmp(txid,checktxid));
free(extraspace);
if ( bits256_cmp(txid,checktxid) != 0 )
{
printf("LP_transaction_fromdata mismatched txid %s vs %s\n",bits256_str(str,txid),bits256_str(str2,checktxid));
free_json(txobj);
txobj = 0;
}
return(txobj);
}
cJSON *electrum_transaction(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid)
{
char str[65]; printf("%s add cache here -> TRANSACTION.(%s)\n",symbol,bits256_str(str,txid));
if ( bits256_nonz(txid) != 0 )
return(electrum_hasharg(symbol,ep,retjsonp,"blockchain.transaction.get",txid,ELECTRUM_TIMEOUT));
else return(cJSON_Parse("{\"error\":\"null txid\"}"));
char *hexstr,str[65]; int32_t len; cJSON *hexjson,*txobj=0; struct iguana_info *coin; uint8_t *serialized; struct LP_transaction *tx;
if ( bits256_nonz(txid) != 0 && (coin= LP_coinfind(symbol)) != 0 )
{
if ( (tx= LP_transactionfind(coin,txid)) != 0 && tx->serialized != 0 )
{
char str[65]; printf("%s cache hit -> TRANSACTION.(%s)\n",symbol,bits256_str(str,txid));
if ( (txobj= LP_transaction_fromdata(coin,txid,tx->serialized,tx->len)) != 0 )
{
*retjsonp = txobj;
return(txobj);
}
}
hexjson = electrum_hasharg(symbol,ep,&hexjson,"blockchain.transaction.get",txid,ELECTRUM_TIMEOUT);
hexstr = jprint(hexjson,1);
if ( strlen(hexstr) > 60000 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("rawtransaction too big %d\n",(int32_t)strlen(hexstr));
free(hexstr);
*retjsonp = cJSON_Parse("{\"error\":\"transaction too big\"}");
return(*retjsonp);
}
if ( hexstr[0] == '"' && hexstr[strlen(hexstr)-1] == '"' )
hexstr[strlen(hexstr)-1] = 0;
if ( (len= is_hexstr(hexstr+1,0)) > 2 )
{
len = (int32_t)strlen(hexstr+1) >> 1;
serialized = malloc(len);
decode_hex(serialized,len,hexstr+1);
free(hexstr);
//printf("DATA.(%s)\n",hexstr+1);
if ( (tx= LP_transactionfind(coin,txid)) == 0 || tx->serialized == 0 )
{
txobj = LP_transactioninit(coin,txid,0,0);
LP_transactioninit(coin,txid,1,txobj);
if ( (tx= LP_transactionfind(coin,txid)) != 0 )
{
tx->serialized = serialized;
tx->len = len;
}
else
{
printf("unexpected couldnt find tx %s %s\n",coin->symbol,bits256_str(str,txid));
free(serialized);
}
}
*retjsonp = txobj;
return(*retjsonp);
} else printf("non-hex tx.(%s)\n",hexstr);
free(hexstr);
}
*retjsonp = cJSON_Parse("{\"error\":\"null txid\"}");
return(*retjsonp);
}
cJSON *electrum_getmerkle(char *symbol,struct electrum_info *ep,cJSON **retjsonp,bits256 txid,int32_t height)

8
iguana/exchanges/LP_utxo.c

@ -332,7 +332,7 @@ int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array)
val = j64bits(item,"value");
//if ( strcmp(coin->symbol,"LBC") == 0 )
// printf("(%s)\n",jprint(item,0));
if ( coin->electrum == 0 && (txobj= LP_gettxout(coin->symbol,txid,v)) != 0 )
if ( coin->electrum == 0 && (txobj= LP_gettxout(coin->symbol,coinaddr,txid,v)) != 0 )
{
value = LP_value_extract(txobj,0);
if ( value != 0 && value != val )
@ -475,7 +475,7 @@ uint64_t LP_txinterestvalue(uint64_t *interestp,char *destaddr,struct iguana_inf
uint64_t interest,value = 0; cJSON *txobj;
*interestp = 0;
destaddr[0] = 0;
if ( (txobj= LP_gettxout(coin->symbol,txid,vout)) != 0 )
if ( (txobj= LP_gettxout(coin->symbol,destaddr,txid,vout)) != 0 )
{
if ( (value= LP_value_extract(txobj,0)) == 0 )
{
@ -591,7 +591,7 @@ int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int
if ( coin->electrum == 0 )
{
numconfirms = -1;
if ( (txobj= LP_gettxout(symbol,txid,vout)) != 0 )
if ( (txobj= LP_gettxout(symbol,coinaddr,txid,vout)) != 0 )
{
numconfirms = jint(txobj,"confirmations");
free_json(txobj);
@ -663,7 +663,7 @@ uint64_t LP_txvalue(char *coinaddr,char *symbol,bits256 txid,int32_t vout)
}
else
{
if ( (txobj= LP_gettxout(coin->symbol,txid,vout)) != 0 )
if ( (txobj= LP_gettxout(coin->symbol,coinaddr,txid,vout)) != 0 )
{
value = LP_value_extract(txobj,0);//SATOSHIDEN * (jdouble(txobj,"value") + jdouble(txobj,"interest"));
if ( coinaddr == 0 )

Loading…
Cancel
Save