Browse Source

Fix tx history crash for BTC/LTC. Disable support for QTUM, BTX, CRW.

blackjok3r
Artem Pikulin 6 years ago
parent
commit
abc79a5acb
  1. 104
      iguana/exchanges/LP_socket.c

104
iguana/exchanges/LP_socket.c

@ -1229,9 +1229,57 @@ int history_item_cmp(struct LP_tx_history_item *item1, struct LP_tx_history_item
return(item1->time < item2->time);
}
void LP_electrum_get_tx_until_success(struct iguana_info *coin, char *tx_hash, cJSON **res) {
cJSON *params = cJSON_CreateArray();
jaddistr(params, tx_hash);
jaddi(params, cJSON_CreateBool(cJSON_True));
while(1) {
electrum_jsonarg(coin->symbol, coin->electrum, res, "blockchain.transaction.get", params,
ELECTRUM_TIMEOUT);
if (jobj(*res, "error") != NULL) {
printf("Error getting electrum tx %s %s %s\n", coin->symbol, jstri(params, 0), jprint(*res, 1));
*res = cJSON_CreateObject();
sleep(5);
continue;
} else {
break;
}
}
free_json(params);
}
char *LP_get_address_from_tx_out(cJSON *tx_out) {
cJSON *script_pub_key = jobj(tx_out, "scriptPubKey");
if (script_pub_key == 0) {
printf("No scriptPubKey on tx_out: %s\n", jprint(tx_out, 0));
return 0;
}
struct cJSON *addresses = jobj(script_pub_key, "addresses");
if (addresses == 0) {
printf("No addresses on tx_out: %s\n", jprint(tx_out, 0));
return NULL;
}
if (!is_cJSON_Array(addresses)) {
printf("Addresses are not array on tx out: %s\n", jprint(tx_out, 0));
return NULL;
}
if (cJSON_GetArraySize(addresses) > 1) {
printf("Addresses array size is > 1 on tx out: %s\n", jprint(tx_out, 0));
return NULL;
}
return jstri(addresses, 0);
}
void LP_electrum_txhistory_loop(void *_coin)
{
struct iguana_info *coin = _coin;
if (strcmp(coin->symbol, "QTUM") == 0 || strcmp(coin->symbol, "CRW") == 0 || strcmp(coin->symbol, "BTX") == 0) {
printf("Tx history loop doesn't support QTUM, CRW and BTX! yet\n");
return;
}
while (coin != NULL && coin->electrum != NULL && coin->inactive == 0) {
cJSON *history = cJSON_CreateObject();
if (strcmp(coin->symbol, "BCH") == 0) {
@ -1242,7 +1290,7 @@ void LP_electrum_txhistory_loop(void *_coin)
ELECTRUM_TIMEOUT);
}
if (jobj(history, "error") != NULL) {
printf("Error getting electrum history %s\n", jprint(history, 1));
printf("Error getting electrum history of coin %s %s\n", coin->symbol, jprint(history, 1));
sleep(10);
continue;
}
@ -1251,6 +1299,7 @@ void LP_electrum_txhistory_loop(void *_coin)
cJSON *history_item = jitem(history, i);
cJSON *tx_item = cJSON_CreateObject();
char *tx_hash = jstr(history_item, "tx_hash");
LP_electrum_get_tx_until_success(coin, tx_hash, &tx_item);
struct LP_tx_history_item *iter;
int found = 0;
int confirmed = 0;
@ -1277,42 +1326,47 @@ void LP_electrum_txhistory_loop(void *_coin)
continue;
}
cJSON *params = cJSON_CreateArray();
jaddistr(params, tx_hash);
jaddi(params, cJSON_CreateBool(cJSON_True));
while(1) {
electrum_jsonarg(coin->symbol, coin->electrum, &tx_item, "blockchain.transaction.get", params,
ELECTRUM_TIMEOUT);
if (jobj(tx_item, "error") != NULL) {
printf("Error getting electrum tx %s %s\n", jstri(params, 0), jprint(tx_item, 1));
tx_item = cJSON_CreateObject();
sleep(5);
continue;
} else {
break;
}
}
free_json(params);
if (!found) {
strcpy(item->txid, jstr(tx_item, "txid"));
// receive by default, but if at least 1 vin contains our address the category is send
strcpy(item->category, "receive");
cJSON *vin = jobj(tx_item, "vin");
cJSON *prev_tx_item = NULL;
for (int j = 0; j < cJSON_GetArraySize(vin); j++) {
cJSON *vin_item = jitem(vin, j);
if (strcmp(coin->smartaddr, jstr(vin_item, "address")) == 0) {
strcpy(item->category, "send");
break;
char *address = jstr(vin_item, "address");
if (address != NULL) {
if (strcmp(coin->smartaddr, jstr(vin_item, "address")) == 0) {
strcpy(item->category, "send");
break;
}
} else {
// At least BTC and LTC doesn't have an address field for Vins.
// Need to get previous tx and check the output
cJSON *params = cJSON_CreateArray();
// some transactions use few vouts of one prev tx so we can reuse it
if (prev_tx_item == 0 || strcmp(jstr(prev_tx_item, "txid"), jstr(vin_item, "txid")) != 0) {
if (prev_tx_item != 0) {
free_json(prev_tx_item);
prev_tx_item = NULL;
}
LP_electrum_get_tx_until_success(coin, jstr(vin_item, "txid"), &prev_tx_item);
}
char *vout_address = LP_get_address_from_tx_out(jitem(jobj(prev_tx_item, "vout"), jint(vin_item, "vout")));
if (strcmp(coin->smartaddr, vout_address) == 0) {
strcpy(item->category, "send");
break;
}
free_json(params);
}
}
int size = 0;
cJSON *vout = jarray(&size, tx_item, "vout");
for (int k = 0; k < size; k++) {
cJSON *vout_item = jitem(vout, k);
int addresses_size = 0;
cJSON *addresses = jarray(&addresses_size, jobj(vout_item, "scriptPubKey"), "addresses");
for (int z = 0; z < addresses_size; z++) {
if (strcmp(coin->smartaddr, jstri(addresses, z)) == 0) {
char *vout_address = LP_get_address_from_tx_out(vout_item);
if (vout_address != 0) {
if (strcmp(coin->smartaddr, vout_address) == 0) {
if (strcmp(item->category, "receive") == 0) {
item->amount += jdouble(vout_item, "value");
}
@ -1327,7 +1381,7 @@ void LP_electrum_txhistory_loop(void *_coin)
if (juint(history_item, "height") > 0) {
item->time = juint(tx_item, "time");
strcpy(item->blockhash, jstr(tx_item, "blockhash"));
item->blockindex = juint(tx_item, "height");
item->blockindex = juint(history_item, "height");
item->blocktime = juint(tx_item, "blocktime");
} else {
// set current time temporary until confirmed

Loading…
Cancel
Save