diff --git a/dap_chain_global_db.h b/dap_chain_global_db.h index 9eeb6c44254780264fa7a28ec87699a0a2dea9b1..c8d8feb6ea2b0d6e27557eb28ea4d28b551299d9 100755 --- a/dap_chain_global_db.h +++ b/dap_chain_global_db.h @@ -103,7 +103,9 @@ char* dap_chain_global_db_hash_fast(const uint8_t *data, size_t data_size); uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out); // Get data according the history log -char* dap_db_history_filter(dap_chain_addr_t * a_addr, const char *a_group_mempool, size_t *a_data_size_out); +char* dap_db_history_tx(dap_chain_hash_fast_t * a_tx_hash, const char *a_group_mempool); +char* dap_db_history_addr(dap_chain_addr_t * a_addr, const char *a_group_mempool); +char* dap_db_history_filter(dap_chain_addr_t * a_addr, const char *a_group_mempool); // Parse data from dap_db_log_pack() void* dap_db_log_unpack(const void *a_data, size_t a_data_size, size_t *a_store_obj_count); diff --git a/dap_chain_global_db_hist.c b/dap_chain_global_db_hist.c index a9dd2402be3f6ed02bebbf05ef225be9d244acef..1455cd59bf5db1d3d7dbc26719b92e76a61e96ef 100755 --- a/dap_chain_global_db_hist.c +++ b/dap_chain_global_db_hist.c @@ -17,6 +17,7 @@ // for dap_db_history_filter() typedef struct dap_tx_data{ dap_chain_hash_fast_t tx_hash; + char tx_hash_str[70]; char token_ticker[10]; size_t obj_num; size_t pos_num; @@ -154,7 +155,566 @@ static dap_store_obj_t* get_prev_tx(dap_global_db_obj_t *a_objs, dap_tx_data_t * * * return history string */ -char* dap_db_history_filter(dap_chain_addr_t * a_addr, const char *a_group_mempool, size_t *a_data_size_out) +char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, const char *a_group_mempool) +{ + dap_string_t *l_str_out = dap_string_new(NULL); + // load history + size_t l_data_size_out = 0; + dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, &l_data_size_out); + size_t i, j; + bool l_tx_hash_found = false; + dap_tx_data_t *l_tx_data_hash = NULL; + for(i = 0; i < l_data_size_out; i++) { + dap_global_db_obj_t *l_obj_cur = l_objs + i; + + // parse global_db records in a history record + dap_global_db_hist_t l_rec; + if(dap_db_history_unpack_hist((char*) l_obj_cur->value, &l_rec) == -1) + continue; + // use only groups with datums + if(dap_strcmp(a_group_mempool, l_rec.group)) + continue; + + char **l_keys = dap_strsplit(l_rec.keys, GLOBAL_DB_HIST_KEY_SEPARATOR, -1); + size_t l_count = dap_str_countv(l_keys); + dap_store_obj_t *l_obj = NULL; + // all objs in one history records + for(j = 0; j < l_count; j++) { + + if(l_rec.type != 'a') + continue; + l_obj = (dap_store_obj_t*) dap_chain_global_db_obj_get(l_keys[j], l_rec.group); + if(!l_obj) + continue; + // datum + dap_chain_datum_t *l_datum = (dap_chain_datum_t*) l_obj->value; + if(!l_datum && l_datum->header.type_id != DAP_CHAIN_DATUM_TX) + continue; + + dap_tx_data_t *l_tx_data = NULL; + + // transaction + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data; + + // find Token items - present in emit transaction + dap_list_t *l_list_tx_token = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_TOKEN, NULL); + + // find OUT items + dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, NULL); + dap_list_t *l_list_tmp = l_list_out_items; + while(l_list_tmp) { + const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data; + // save OUT item l_tx_out + if(!l_tx_data) + { + // save tx hash + l_tx_data = DAP_NEW_Z(dap_tx_data_t); + dap_chain_hash_fast_t l_tx_hash; + dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); + memcpy(&l_tx_data->tx_hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t)); + memcpy(&l_tx_data->addr, &l_tx_out->addr, sizeof(dap_chain_addr_t)); + dap_chain_hash_fast_to_str(&l_tx_data->tx_hash, l_tx_data->tx_hash_str, + sizeof(l_tx_data->tx_hash_str)); + l_tx_data->obj_num = i; + l_tx_data->pos_num = j; + // save token name + if(l_list_tx_token) { + dap_chain_tx_token_t *tk = l_list_tx_token->data; + int d = sizeof(l_tx_data->token_ticker); + memcpy(l_tx_data->token_ticker, tk->header.ticker, sizeof(l_tx_data->token_ticker)); + } + // take token from prev out item + else { + + // find IN items + dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN, NULL); + dap_list_t *l_list_tmp_in = l_list_in_items; + // find token_ticker in prev OUT items + while(l_list_tmp_in) { + const dap_chain_tx_in_t *l_tx_in = + (const dap_chain_tx_in_t*) l_list_tmp_in->data; + dap_chain_hash_fast_t tx_prev_hash = l_tx_in->header.tx_prev_hash; + + //find prev OUT item + dap_tx_data_t *l_tx_data_prev = NULL; + HASH_FIND(hh, l_tx_data_hash, &tx_prev_hash, sizeof(dap_chain_hash_fast_t), + l_tx_data_prev); + if(l_tx_data_prev != NULL) { + // fill token in l_tx_data from prev transaction + if(l_tx_data) { + // get token from prev tx + memcpy(l_tx_data->token_ticker, l_tx_data_prev->token_ticker, + sizeof(l_tx_data->token_ticker)); + break; + } + l_list_tmp_in = dap_list_next(l_list_tmp_in); + } + } + if(l_list_in_items) + dap_list_free(l_list_in_items); + } + HASH_ADD(hh, l_tx_data_hash, tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_data); + } + l_list_tmp = dap_list_next(l_list_tmp); + } + if(l_list_out_items) + dap_list_free(l_list_out_items); + + // calc hash + dap_chain_hash_fast_t l_tx_hash; + dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); + // search tx with a_tx_hash + if(!dap_hash_fast_compare(a_tx_hash, &l_tx_hash)) + continue; + // found a_tx_hash now + + // transaction time + char *l_time_str = NULL; + if(l_tx->header.ts_created > 0) { + time_t rawtime = (time_t) l_tx->header.ts_created; + struct tm * timeinfo; + timeinfo = localtime(&rawtime); + if(timeinfo) { + dap_string_append_printf(l_str_out, " %s", asctime(timeinfo)); + } + } + + // find all OUT items in transaction + l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, NULL); + l_list_tmp = l_list_out_items; + while(l_list_tmp) { + const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data; + dap_tx_data_t *l_tx_data_prev = NULL; + + const char *l_token_str = NULL; + if(l_tx_data) + l_token_str = l_tx_data->token_ticker; + char *l_dst_to_str = + (l_tx_out) ? dap_chain_addr_to_str(&l_tx_out->addr) : + NULL; + dap_string_append_printf(l_str_out, " OUT item %lld %s to %s\n", + l_tx_out->header.value, + dap_strlen(l_token_str) > 0 ? l_token_str : "?", + l_dst_to_str ? l_dst_to_str : "?" + ); + DAP_DELETE(l_dst_to_str); + l_list_tmp = dap_list_next(l_list_tmp); + } + // find all IN items in transaction + dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN, NULL); + l_list_tmp = l_list_in_items; + // find cur addr in prev OUT items + while(l_list_tmp) { + const dap_chain_tx_in_t *l_tx_in = (const dap_chain_tx_in_t*) l_list_tmp->data; + dap_chain_hash_fast_t tx_prev_hash = l_tx_in->header.tx_prev_hash; + char l_tx_hash_str[70]; + if(!dap_hash_fast_is_blank(&tx_prev_hash)) + dap_chain_hash_fast_to_str(&tx_prev_hash, l_tx_hash_str, sizeof(l_tx_hash_str)); + else + strcpy(l_tx_hash_str,"Null"); + dap_string_append_printf(l_str_out, " IN item \n prev tx_hash %s\n", l_tx_hash_str); + + //find prev OUT item + dap_tx_data_t *l_tx_data_prev = NULL; + HASH_FIND(hh, l_tx_data_hash, &tx_prev_hash, sizeof(dap_chain_hash_fast_t), l_tx_data_prev); + if(l_tx_data_prev != NULL) { + + dap_store_obj_t *l_obj_prev = get_prev_tx(l_objs, l_tx_data_prev); + dap_chain_datum_t *l_datum_prev = + l_obj_prev ? (dap_chain_datum_t*) l_obj_prev->value : NULL; + dap_chain_datum_tx_t *l_tx_prev = + l_datum_prev ? (dap_chain_datum_tx_t*) l_datum_prev->data : NULL; + + // find OUT items in prev datum + dap_list_t *l_list_out_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, + TX_ITEM_TYPE_OUT, NULL); + // find OUT item for IN item; + dap_list_t *l_list_out_prev_item = dap_list_nth(l_list_out_prev_items, + l_tx_in->header.tx_out_prev_idx); + dap_chain_tx_out_t *l_tx_prev_out = + l_list_out_prev_item ? + (dap_chain_tx_out_t*) l_list_out_prev_item->data : + NULL; + // print value from prev out item + dap_string_append_printf(l_str_out, " prev OUT item value=%lld", + l_tx_prev_out->header.value + ); + } + dap_string_append_printf(l_str_out, "\n"); + l_list_tmp = dap_list_next(l_list_tmp); + } + + if(l_list_tx_token) + dap_list_free(l_list_tx_token); + if(l_list_out_items) + dap_list_free(l_list_out_items); + if(l_list_in_items) + dap_list_free(l_list_in_items); + l_tx_hash_found = true; + break; + } + dap_list_t *l_records_out = NULL; + + DAP_DELETE(l_obj); + dap_strfreev(l_keys); + // transaction was found -> exit + if(l_tx_hash_found) + break; + } + dap_chain_global_db_objs_delete(l_objs, l_data_size_out); + // if no history + if(!l_str_out->len) + dap_string_append(l_str_out, "empty"); + char *l_ret_str = l_str_out ? dap_string_free(l_str_out, false) : NULL; + return l_ret_str; +} + +/** + * Get data according the history log + * + * return history string + */ +char* dap_db_history_addr(dap_chain_addr_t * a_addr, const char *a_group_mempool) +{ + dap_string_t *l_str_out = dap_string_new(NULL); + // load history + size_t l_data_size_out = 0; + dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, &l_data_size_out); + size_t i, j; + dap_tx_data_t *l_tx_data_hash = NULL; + for(i = 0; i < l_data_size_out; i++) { + dap_global_db_obj_t *l_obj_cur = l_objs + i; + // parse global_db records in a history record + dap_global_db_hist_t l_rec; + if(dap_db_history_unpack_hist((char*) l_obj_cur->value, &l_rec) == -1) + continue; + // use only groups with datums + if(dap_strcmp(a_group_mempool, l_rec.group)) + continue; + + char **l_keys = dap_strsplit(l_rec.keys, GLOBAL_DB_HIST_KEY_SEPARATOR, -1); + size_t l_count = dap_str_countv(l_keys); + dap_store_obj_t *l_obj = NULL; + // all objs in one history records + for(j = 0; j < l_count; j++) { + if(l_rec.type != 'a') + continue; + l_obj = (dap_store_obj_t*) dap_chain_global_db_obj_get(l_keys[j], l_rec.group); + if(!l_obj) + continue; + // datum + dap_chain_datum_t *l_datum = (dap_chain_datum_t*) l_obj->value; + if(!l_datum && l_datum->header.type_id != DAP_CHAIN_DATUM_TX) + continue; + + // transaction + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data; + dap_list_t *l_records_out = NULL; + // transaction time + char *l_time_str = NULL; + { + if(l_tx->header.ts_created > 0) { + time_t rawtime = (time_t) l_tx->header.ts_created; + struct tm * timeinfo; + timeinfo = localtime(&rawtime); + if(timeinfo) + l_time_str = dap_strdup(asctime(timeinfo)); + } + else + l_time_str = dap_strdup(" "); + } + + // transaction + dap_tx_data_t *l_tx_data = NULL; + + // find Token items - present in emit transaction + dap_list_t *l_list_tx_token = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_TOKEN, NULL); + + // find OUT items + dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, NULL); + dap_list_t *l_list_tmp = l_list_out_items; + while(l_list_tmp) { + const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data; + // save OUT item l_tx_out + { + // save tx hash + l_tx_data = DAP_NEW_Z(dap_tx_data_t); + dap_chain_hash_fast_t l_tx_hash; + dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); + memcpy(&l_tx_data->tx_hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t)); + memcpy(&l_tx_data->addr, &l_tx_out->addr, sizeof(dap_chain_addr_t)); + dap_chain_hash_fast_to_str(&l_tx_data->tx_hash, l_tx_data->tx_hash_str, + sizeof(l_tx_data->tx_hash_str)); + l_tx_data->obj_num = i; + l_tx_data->pos_num = j; + // save token name + if(l_tx_data && l_list_tx_token) { + dap_chain_tx_token_t *tk = l_list_tx_token->data; + int d = sizeof(l_tx_data->token_ticker); + memcpy(l_tx_data->token_ticker, tk->header.ticker, sizeof(l_tx_data->token_ticker)); + } + HASH_ADD(hh, l_tx_data_hash, tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_data); + + // save OUT items to list + { + l_records_out = dap_list_append(l_records_out, (void*) l_tx_out); + } + } + l_list_tmp = dap_list_next(l_list_tmp); + } + + // find IN items + l_count = 0; + dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN, NULL); + l_list_tmp = l_list_in_items; + // find cur addr in prev OUT items + bool l_is_use_all_cur_out = false; + { + while(l_list_tmp) { + const dap_chain_tx_in_t *l_tx_in = (const dap_chain_tx_in_t*) l_list_tmp->data; + dap_chain_hash_fast_t tx_prev_hash = l_tx_in->header.tx_prev_hash; + + //find prev OUT item + dap_tx_data_t *l_tx_data_prev = NULL; + HASH_FIND(hh, l_tx_data_hash, &tx_prev_hash, sizeof(dap_chain_hash_fast_t), l_tx_data_prev); + if(l_tx_data_prev != NULL) { + // fill token in l_tx_data from prev transaction + if(l_tx_data) { + // get token from prev tx + memcpy(l_tx_data->token_ticker, l_tx_data_prev->token_ticker, + sizeof(l_tx_data->token_ticker)); + dap_store_obj_t *l_obj_prev = get_prev_tx(l_objs, l_tx_data_prev); + dap_chain_datum_t *l_datum_prev = + l_obj_prev ? (dap_chain_datum_t*) l_obj_prev->value : NULL; + dap_chain_datum_tx_t *l_tx_prev = + l_datum_prev ? (dap_chain_datum_tx_t*) l_datum_prev->data : NULL; + + // find OUT items in prev datum + dap_list_t *l_list_out_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, + TX_ITEM_TYPE_OUT, NULL); + // find OUT item for IN item; + dap_list_t *l_list_out_prev_item = dap_list_nth(l_list_out_prev_items, + l_tx_in->header.tx_out_prev_idx); + dap_chain_tx_out_t *l_tx_prev_out = + l_list_out_prev_item ? + (dap_chain_tx_out_t*) l_list_out_prev_item->data : + NULL; + if(l_tx_prev_out && !memcmp(&l_tx_prev_out->addr, a_addr, sizeof(dap_chain_addr_t))) + l_is_use_all_cur_out = true; + + } + } + + // find prev OUT items for IN items + l_list_tmp = l_list_in_items; + while(l_list_tmp) { + const dap_chain_tx_in_t *l_tx_in = (const dap_chain_tx_in_t*) l_list_tmp->data; + dap_chain_hash_fast_t tx_prev_hash = l_tx_in->header.tx_prev_hash; + // if first transaction - empty prev OUT item + if(dap_hash_fast_is_blank(&tx_prev_hash)) { + // add emit info to ret string + if(!memcmp(&l_tx_data->addr, a_addr, sizeof(dap_chain_addr_t))) + { + dap_list_t *l_records_tmp = l_records_out; + while(l_records_tmp) { + + const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_records_tmp->data; + dap_string_append_printf(l_str_out, "tx hash %s \n emit %lld %s\n", + l_tx_data->tx_hash_str, + l_tx_out->header.value, + l_tx_data->token_ticker); + l_records_tmp = dap_list_next(l_records_tmp); + } + } + dap_list_free(l_records_out); + } + // in other transactions except first one + else { + //find prev OUT item + dap_tx_data_t *l_tx_data_prev = NULL; + HASH_FIND(hh, l_tx_data_hash, &tx_prev_hash, sizeof(dap_chain_hash_fast_t), l_tx_data_prev); + if(l_tx_data_prev != NULL) { + char *l_src_str = NULL; + bool l_src_str_is_cur = false; + if(l_tx_data) { + // get token from prev tx + memcpy(l_tx_data->token_ticker, l_tx_data_prev->token_ticker, + sizeof(l_tx_data->token_ticker)); + + dap_store_obj_t *l_obj_prev = get_prev_tx(l_objs, l_tx_data_prev); + dap_chain_datum_t *l_datum_prev = + l_obj_prev ? (dap_chain_datum_t*) l_obj_prev->value : NULL; + dap_chain_datum_tx_t *l_tx_prev = + l_datum_prev ? (dap_chain_datum_tx_t*) l_datum_prev->data : NULL; + + // find OUT items in prev datum + dap_list_t *l_list_out_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, + TX_ITEM_TYPE_OUT, NULL); + // find OUT item for IN item; + dap_list_t *l_list_out_prev_item = dap_list_nth(l_list_out_prev_items, + l_tx_in->header.tx_out_prev_idx); + dap_chain_tx_out_t *l_tx_prev_out = + l_list_out_prev_item ? + (dap_chain_tx_out_t*) l_list_out_prev_item->data : + NULL; + // if use src addr + bool l_is_use_src_addr = false; + // find source addrs + dap_string_t *l_src_addr = dap_string_new(NULL); + { + // find IN items in prev datum - for get destination addr + dap_list_t *l_list_in_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, + TX_ITEM_TYPE_IN, NULL); + dap_list_t *l_list_tmp = l_list_in_prev_items; + while(l_list_tmp) { + dap_chain_tx_in_t *l_tx_prev_in = l_list_tmp->data; + dap_chain_hash_fast_t l_tx_prev_prev_hash = + l_tx_prev_in->header.tx_prev_hash; + //find prev OUT item + dap_tx_data_t *l_tx_data_prev_prev = NULL; + HASH_FIND(hh, l_tx_data_hash, &l_tx_prev_prev_hash, + sizeof(dap_chain_hash_fast_t), l_tx_data_prev_prev); + if(l_tx_data_prev_prev) { + // if use src addr + if(!memcmp(&l_tx_data_prev_prev->addr, a_addr, + sizeof(dap_chain_addr_t))) + l_is_use_src_addr = true; + char *l_str = dap_chain_addr_to_str(&l_tx_data_prev_prev->addr); + if(l_src_addr->len > 0) + dap_string_append_printf(l_src_addr, "\n %s", l_str); + else + dap_string_append_printf(l_src_addr, "%s", l_str); // first record + DAP_DELETE(l_str); + } + l_list_tmp = dap_list_next(l_list_tmp); + } + } + + char *l_dst_to_str = + (l_tx_prev_out) ? dap_chain_addr_to_str(&l_tx_prev_out->addr) : + NULL; + // if use dst addr + bool l_is_use_dst_addr = false; + if(!memcmp(&l_tx_prev_out->addr, a_addr, sizeof(dap_chain_addr_t))) + l_is_use_dst_addr = true; + + l_src_str_is_cur = l_is_use_src_addr; + if(l_src_addr->len <= 1) { + l_src_str = + (l_tx_data) ? dap_chain_addr_to_str(&l_tx_data->addr) : + NULL; + if(!memcmp(&l_tx_prev_out->addr, a_addr, sizeof(dap_chain_addr_t))) + l_src_str_is_cur = true; + dap_string_free(l_src_addr, true); + } + else + l_src_str = dap_string_free(l_src_addr, false); + if(l_is_use_src_addr && !l_is_use_dst_addr) { + dap_string_append_printf(l_str_out, + "tx hash %s \n %s in send %lld %s from %s\n to %s\n", + l_tx_data->tx_hash_str, + l_time_str ? l_time_str : "", + l_tx_prev_out->header.value, + l_tx_data->token_ticker, + l_src_str ? l_src_str : "", + l_dst_to_str); + } else if(l_is_use_dst_addr && !l_is_use_src_addr) { + if(!l_src_str_is_cur) + dap_string_append_printf(l_str_out, + "tx hash %s \n %s in recv %lld %s from %s\n", + l_tx_data->tx_hash_str, + l_time_str ? l_time_str : "", + l_tx_prev_out->header.value, + l_tx_data->token_ticker, + l_src_str ? l_src_str : ""); + } + + DAP_DELETE(l_dst_to_str); + dap_list_free(l_list_out_prev_items); + DAP_DELETE(l_obj_prev); + } + + // OUT items + dap_list_t *l_records_tmp = l_records_out; + while(l_records_tmp) { + + const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_records_tmp->data; + + if(l_is_use_all_cur_out + || !memcmp(&l_tx_out->addr, a_addr, sizeof(dap_chain_addr_t))) { + + char *l_addr_str = (l_tx_out) ? dap_chain_addr_to_str(&l_tx_out->addr) : NULL; + + if(!memcmp(&l_tx_out->addr, a_addr, sizeof(dap_chain_addr_t))) { + if(!l_src_str_is_cur) + dap_string_append_printf(l_str_out, "tx hash %s \n %s recv %lld %s from %s\n", + l_tx_data->tx_hash_str, + l_time_str ? l_time_str : "", + l_tx_out->header.value, + l_tx_data_prev->token_ticker, + l_src_str ? l_src_str : "?"); + } + else { + dap_string_append_printf(l_str_out, "tx hash %s \n %s send %lld %s to %sd\n", + l_tx_data->tx_hash_str, + l_time_str ? l_time_str : "", + l_tx_out->header.value, + l_tx_data_prev->token_ticker, + l_addr_str ? l_addr_str : ""); + } + DAP_DELETE(l_addr_str); + } + l_records_tmp = dap_list_next(l_records_tmp); + } + dap_list_free(l_records_out); + DAP_DELETE(l_src_str); + + } + } + l_list_tmp = dap_list_next(l_list_tmp); + } + l_list_tmp = dap_list_next(l_list_tmp); + } + } + + + + if(l_list_tx_token) + dap_list_free(l_list_tx_token); + if(l_list_out_items) + dap_list_free(l_list_out_items); + if(l_list_in_items) + dap_list_free(l_list_in_items); + + DAP_DELETE(l_time_str); + } + DAP_DELETE(l_obj); + dap_strfreev(l_keys); + + } + // delete hashes + dap_tx_data_t *l_iter_current, *l_item_tmp; + HASH_ITER(hh, l_tx_data_hash , l_iter_current, l_item_tmp) + { + // delete struct + DAP_DELETE(l_iter_current); + HASH_DEL(l_tx_data_hash, l_iter_current); + } + dap_chain_global_db_objs_delete(l_objs, l_data_size_out); + // if no history + if(!l_str_out->len) + dap_string_append(l_str_out, " empty"); + char *l_ret_str = l_str_out ? dap_string_free(l_str_out, false) : NULL; + return l_ret_str; +} + + +/** + * Get data according the history log + * + * return history string + */ +char* dap_db_history_filter(dap_chain_addr_t * a_addr, const char *a_group_mempool) { dap_string_t *l_str_out = dap_string_new(NULL); // load history @@ -217,7 +777,7 @@ char* dap_db_history_filter(dap_chain_addr_t * a_addr, const char *a_group_mempo dap_tx_data_t *l_tx_data = NULL; // find Token items - present in emit transaction l_count = 0; - dap_list_t *l_tx_token = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_TOKEN, &l_count); + dap_list_t *l_list_tx_token = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_TOKEN, &l_count); // find OUT items dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, &l_count); @@ -235,8 +795,8 @@ char* dap_db_history_filter(dap_chain_addr_t * a_addr, const char *a_group_mempo l_tx_data->obj_num = i; l_tx_data->pos_num = j; // save token name - if(l_tx_data && l_tx_token) { - dap_chain_tx_token_t *tk = l_tx_token->data; + if(l_tx_data && l_list_tx_token) { + dap_chain_tx_token_t *tk = l_list_tx_token->data; int d = sizeof(l_tx_data->token_ticker); memcpy(l_tx_data->token_ticker, tk->header.ticker, sizeof(l_tx_data->token_ticker)); } @@ -458,6 +1018,8 @@ char* dap_db_history_filter(dap_chain_addr_t * a_addr, const char *a_group_mempo } l_list_tmp = dap_list_next(l_list_tmp); } + if(l_list_tx_token) + dap_list_free(l_list_tx_token); if(l_list_out_items) dap_list_free(l_list_out_items); if(l_list_in_items) @@ -486,9 +1048,6 @@ char* dap_db_history_filter(dap_chain_addr_t * a_addr, const char *a_group_mempo DAP_DELETE(l_iter_current); HASH_DEL(l_tx_data_hash, l_iter_current); } - - if(a_data_size_out) - *a_data_size_out = l_data_size_out; dap_chain_global_db_objs_delete(l_objs, l_data_size_out); // if no history if(!l_str_out->len)