diff --git a/CMakeLists.txt b/CMakeLists.txt index fb253140c30cc55ba369661e9bb0b5b218e1e36d..81f707bea95be8b29830ae3cce3b3780767ed916 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ project(cellframe-sdk C) cmake_minimum_required(VERSION 2.8) set(CMAKE_C_STANDARD 11) -set(CELLFRAME_SDK_NATIVE_VERSION "2.6-56") +set(CELLFRAME_SDK_NATIVE_VERSION "2.6-61") add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"") set(DAPSDK_MODULES "") diff --git a/dap-sdk/core/src/dap_list.c b/dap-sdk/core/src/dap_list.c index 4c6ee31c2be86bd2c6f0c460445b6eeced7cf4e5..d5d1cb033fa8717c64d4271937e65a167fcdba9a 100755 --- a/dap-sdk/core/src/dap_list.c +++ b/dap-sdk/core/src/dap_list.c @@ -351,7 +351,6 @@ dap_list_t *dap_list_remove(dap_list_t *list, const void * data) { list = _dap_list_remove_link(list, tmp); dap_list_free1(tmp); - break; } } @@ -717,7 +716,7 @@ dap_list_t * dap_list_last(dap_list_t *list) { if(list) { - while(list->next) + while(list && list->next) list = list->next; } diff --git a/dap-sdk/core/src/rpmalloc/rpmalloc.c b/dap-sdk/core/src/rpmalloc/rpmalloc.c index 8b1bbcdfa549ed4552d0b487f47db5b00652fab8..cab7ed149d76e532c4321870af18b12b705f741c 100644 --- a/dap-sdk/core/src/rpmalloc/rpmalloc.c +++ b/dap-sdk/core/src/rpmalloc/rpmalloc.c @@ -2230,7 +2230,8 @@ rpaligned_alloc(size_t alignment, size_t size) { ptr = (void*)(((uintptr_t)ptr & ~(uintptr_t)align_mask) + alignment); //Mark as having aligned blocks span_t* span = (span_t*)((uintptr_t)ptr & _memory_span_mask); - span->flags |= SPAN_FLAG_ALIGNED_BLOCKS; + if (span) + span->flags |= SPAN_FLAG_ALIGNED_BLOCKS; return ptr; } diff --git a/dap-sdk/core/src/unix/linux/dap_network_monitor.c b/dap-sdk/core/src/unix/linux/dap_network_monitor.c index 3341ad089f80ec0b0d9df86938c5ade3e8ef0a40..27b2aa373e4dc7ce01da8a4d170051aa174b1307 100755 --- a/dap-sdk/core/src/unix/linux/dap_network_monitor.c +++ b/dap-sdk/core/src/unix/linux/dap_network_monitor.c @@ -189,7 +189,7 @@ static void _link_msg_handler(struct nlmsghdr *nlh, static void clear_results(dap_network_notification_t* cb_result) { - bzero(cb_result, sizeof (dap_network_notification_t)); + memset(cb_result, 0,sizeof (dap_network_notification_t)); cb_result->route.destination_address = (uint64_t) -1; cb_result->route.gateway_address = (uint64_t) -1; } diff --git a/dap-sdk/crypto/src/dap_enc_base58.c b/dap-sdk/crypto/src/dap_enc_base58.c index fba7d9a63399290516220f17d4bf207fed7242bc..84282f26f97c1b9da2101a7b8274f93091f89f06 100755 --- a/dap-sdk/crypto/src/dap_enc_base58.c +++ b/dap-sdk/crypto/src/dap_enc_base58.c @@ -98,6 +98,7 @@ size_t dap_enc_base58_decode(const char * a_in, void * a_out) } unsigned char l_out_u80[l_out_size_max]; + memset(l_out_u80,0,l_out_size_max); unsigned char *l_out_u8 = l_out_u80; j = 0; switch (bytesleft) { diff --git a/dap-sdk/crypto/src/dap_enc_bliss.c b/dap-sdk/crypto/src/dap_enc_bliss.c index ce87eabdc2c342f6a65c622a2f02baa317c020ed..e75d0f8d8d46d6947e779c473b8b07b8cd8f218c 100755 --- a/dap-sdk/crypto/src/dap_enc_bliss.c +++ b/dap-sdk/crypto/src/dap_enc_bliss.c @@ -199,7 +199,7 @@ bliss_signature_t* dap_enc_sig_bliss_read_signature(const uint8_t *a_buf, size_t l_sign->kind = kind; l_sign->z1 = DAP_NEW_SIZE(int32_t, p.n * sizeof(int32_t)); l_sign->z2 = DAP_NEW_SIZE(int32_t, p.n * sizeof(int32_t)); - l_sign->c = DAP_NEW_SIZE(uint32_t, p.kappa * sizeof(int32_t)); + l_sign->c = DAP_NEW_SIZE(unsigned int, p.kappa * sizeof(unsigned int)); size_t l_shift_mem = sizeof(size_t) + sizeof(bliss_kind_t); memcpy(l_sign->z1, a_buf + l_shift_mem, p.n * sizeof(int32_t)); l_shift_mem += p.n * sizeof(int32_t); diff --git a/dap-sdk/crypto/src/dap_enc_key.c b/dap-sdk/crypto/src/dap_enc_key.c index 4c82fd3a69b8859e84ef66efc27a3e37b3f5778e..a04f827079a692449a16d1f796f1117295b0905e 100755 --- a/dap-sdk/crypto/src/dap_enc_key.c +++ b/dap-sdk/crypto/src/dap_enc_key.c @@ -709,7 +709,8 @@ dap_enc_key_t *dap_enc_key_new(dap_enc_key_type_t a_key_type) s_callbacks[a_key_type].new_callback(ret); } } - ret->type = a_key_type; + if(ret) + ret->type = a_key_type; return ret; } diff --git a/dap-sdk/crypto/src/dap_sign.c b/dap-sdk/crypto/src/dap_sign.c index 4b390b5258004767fce2a537e3d91017b82a6615..fd3c76f9900204bbbeae0f188ea38c019501eaa7 100755 --- a/dap-sdk/crypto/src/dap_sign.c +++ b/dap-sdk/crypto/src/dap_sign.c @@ -500,27 +500,32 @@ dap_multi_sign_t *dap_multi_sign_deserialize(dap_sign_type_enum_t a_type, uint8_ l_mem_shift++; memcpy(&l_sign->sign_count, &a_sign[l_mem_shift], 1); l_mem_shift++; - l_sign->key_seq = DAP_NEW_Z_SIZE(dap_multi_sign_keys_t, l_sign->sign_count * sizeof(dap_multi_sign_keys_t)); + if(l_sign->sign_count) + l_sign->key_seq = DAP_NEW_Z_SIZE(dap_multi_sign_keys_t, l_sign->sign_count * sizeof(dap_multi_sign_keys_t)); for (int i = 0; i < l_sign->sign_count; i++) { memcpy(&l_sign->key_seq[i].num, &a_sign[l_mem_shift], 1); l_mem_shift++; memcpy(&l_sign->key_seq[i].type, &a_sign[l_mem_shift], sizeof(dap_sign_type_t)); l_mem_shift += sizeof(dap_sign_type_t); } - l_sign->meta = DAP_NEW_Z_SIZE(dap_multi_sign_meta_t, l_sign->sign_count * sizeof(dap_multi_sign_meta_t)); size_t l_pkeys_size = 0, l_signes_size = 0; - for (int i = 0; i < l_sign->sign_count; i++) { - memcpy(&l_sign->meta[i].pkey_size, &a_sign[l_mem_shift], sizeof(uint32_t)); - l_mem_shift += sizeof(uint32_t); - l_pkeys_size += l_sign->meta[i].pkey_size; - memcpy(&l_sign->meta[i].sign_size, &a_sign[l_mem_shift], sizeof(uint32_t)); - l_mem_shift += sizeof(uint32_t); - l_signes_size += l_sign->meta[i].sign_size; + if(l_sign->sign_count){ + l_sign->meta = DAP_NEW_Z_SIZE(dap_multi_sign_meta_t, l_sign->sign_count * sizeof(dap_multi_sign_meta_t)); + for (int i = 0; i < l_sign->sign_count; i++) { + memcpy(&l_sign->meta[i].pkey_size, &a_sign[l_mem_shift], sizeof(uint32_t)); + l_mem_shift += sizeof(uint32_t); + l_pkeys_size += l_sign->meta[i].pkey_size; + memcpy(&l_sign->meta[i].sign_size, &a_sign[l_mem_shift], sizeof(uint32_t)); + l_mem_shift += sizeof(uint32_t); + l_signes_size += l_sign->meta[i].sign_size; + } } - l_sign->key_hashes = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, l_sign->total_count * sizeof(dap_chain_hash_fast_t)); - for (int i = 0; i < l_sign->total_count; i++) { - memcpy(&l_sign->key_hashes[i], &a_sign[l_mem_shift], sizeof(dap_chain_hash_fast_t)); - l_mem_shift += sizeof(dap_chain_hash_fast_t); + if(l_sign->total_count){ + l_sign->key_hashes = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, l_sign->total_count * sizeof(dap_chain_hash_fast_t)); + for (int i = 0; i < l_sign->total_count; i++) { + memcpy(&l_sign->key_hashes[i], &a_sign[l_mem_shift], sizeof(dap_chain_hash_fast_t)); + l_mem_shift += sizeof(dap_chain_hash_fast_t); + } } uint32_t l_data_shift = 0, l_data_size = 0; l_sign->pub_keys = DAP_NEW_Z_SIZE(uint8_t, l_pkeys_size); diff --git a/dap-sdk/net/client/dap_client.c b/dap-sdk/net/client/dap_client.c index f70f5132dc6cc88ab9aaa2a4c8f60eeed972f25a..aa42b899ad6f2a7825a52282bbd7b491f867ba51 100644 --- a/dap-sdk/net/client/dap_client.c +++ b/dap-sdk/net/client/dap_client.c @@ -294,7 +294,7 @@ static void s_go_stage_on_client_worker_unsafe(dap_worker_t * a_worker,void * a_ } l_client_pvt->refs_count--; if ( l_client_pvt->is_to_delete ) - dap_client_delete_unsafe(l_client_pvt->client); + dap_client_delete_unsafe(l_client); } /** diff --git a/dap-sdk/net/client/dap_client_pvt.c b/dap-sdk/net/client/dap_client_pvt.c index 8cad69894eaa7bc5dc850187cbca3ed7025c86f3..77f47f987301ec0bd3638b64f460abccd700eab1 100644 --- a/dap-sdk/net/client/dap_client_pvt.c +++ b/dap-sdk/net/client/dap_client_pvt.c @@ -721,47 +721,52 @@ static void s_request_error(int a_err_code, void * a_obj) */ static void s_request_response(void * a_response, size_t a_response_size, void * a_obj) { - dap_client_pvt_t * a_client_internal = (dap_client_pvt_t *) a_obj; - if(!a_client_internal || !a_client_internal->client){ - if( !a_client_internal ) + dap_client_pvt_t * l_client_pvt = (dap_client_pvt_t *) a_obj; + if (! l_client_pvt || !dap_client_pvt_check(l_client_pvt) ){ + // Response received after client_pvt was deleted + return; + } + + if(!l_client_pvt || !l_client_pvt->client){ + if( !l_client_pvt ) log_it(L_ERROR,"Client internal is NULL for s_request_response"); else log_it(L_ERROR,"Client is NULL for s_request_response"); return; } - a_client_internal->refs_count--; + l_client_pvt->refs_count--; - if (a_client_internal->is_to_delete){ - if(a_client_internal->refs_count==0) // Was requested to delete until we was working with request - dap_client_delete_unsafe(a_client_internal->client); // Init delete + if (l_client_pvt->is_to_delete){ + if(l_client_pvt->refs_count==0) // Was requested to delete until we was working with request + dap_client_delete_unsafe(l_client_pvt->client); // Init delete return; } //int l_ref = dap_client_pvt_get_ref(a_client_internal); - if(a_client_internal->is_encrypted) { + if(l_client_pvt->is_encrypted) { size_t l_response_dec_size_max = a_response_size ? a_response_size * 2 + 16 : 0; char * l_response_dec = a_response_size ? DAP_NEW_Z_SIZE(char, l_response_dec_size_max) : NULL; size_t l_response_dec_size = 0; if(a_response_size) - l_response_dec_size = dap_enc_decode(a_client_internal->session_key, + l_response_dec_size = dap_enc_decode(l_client_pvt->session_key, a_response, a_response_size, l_response_dec, l_response_dec_size_max, DAP_ENC_DATA_TYPE_RAW); - if ( a_client_internal->request_response_callback ) - a_client_internal->request_response_callback(a_client_internal->client, l_response_dec, l_response_dec_size); + if ( l_client_pvt->request_response_callback ) + l_client_pvt->request_response_callback(l_client_pvt->client, l_response_dec, l_response_dec_size); else - log_it(L_ERROR, "NULL request_response_callback for encrypted client %p", a_client_internal->client ); + log_it(L_ERROR, "NULL request_response_callback for encrypted client %p", l_client_pvt->client ); if(l_response_dec) DAP_DELETE(l_response_dec); } else { - if ( a_client_internal->request_response_callback ) - a_client_internal->request_response_callback(a_client_internal->client, a_response, a_response_size); + if ( l_client_pvt->request_response_callback ) + l_client_pvt->request_response_callback(l_client_pvt->client, a_response, a_response_size); else - log_it(L_ERROR, "NULL request_response_callback for unencrypted client %p", a_client_internal->client ); + log_it(L_ERROR, "NULL request_response_callback for unencrypted client %p", l_client_pvt->client ); } //int l_ref2 = dap_client_pvt_get_ref(a_client_internal); @@ -779,7 +784,7 @@ static void s_request_response(void * a_response, size_t a_response_size, void * static void s_enc_init_response(dap_client_t * a_client, void * a_response, size_t a_response_size) { dap_client_pvt_t * l_client_pvt = a_client ? DAP_CLIENT_PVT(a_client) : NULL; - if (!dap_client_pvt_check(l_client_pvt) ){ + if (! l_client_pvt || !dap_client_pvt_check(l_client_pvt) ){ // Response received after client_pvt was deleted return; } @@ -885,6 +890,10 @@ static void s_enc_init_response(dap_client_t * a_client, void * a_response, size static void s_enc_init_error(dap_client_t * a_client, int a_err_code) { dap_client_pvt_t * l_client_pvt = DAP_CLIENT_PVT(a_client); + if (! l_client_pvt || !dap_client_pvt_check(l_client_pvt) ){ + // Response received after client_pvt was deleted + return; + } //dap_client_internal_t * l_client_internal = dap_CLIENT_INTERNAL(a_client); log_it(L_ERROR, "ENC: Can't init ecnryption session, err code %d", a_err_code); @@ -996,6 +1005,10 @@ static void s_stream_ctl_error(dap_client_t * a_client, int a_error) log_it(L_WARNING, "STREAM_CTL error %d", a_error); dap_client_pvt_t * l_client_pvt = DAP_CLIENT_PVT(a_client); + if (! l_client_pvt || !dap_client_pvt_check(l_client_pvt) ){ + // Response received after client_pvt was deleted + return; + } if (a_error == ETIMEDOUT) { l_client_pvt->last_error = ERROR_NETWORK_CONNECTION_TIMEOUT; diff --git a/dap-sdk/net/core/dap_events_socket.c b/dap-sdk/net/core/dap_events_socket.c index 3e40b1524b52d2eb3d5b90701a7cda702640eb49..d9e9d8022c27638e2019f94b81438794b6b49115 100644 --- a/dap-sdk/net/core/dap_events_socket.c +++ b/dap-sdk/net/core/dap_events_socket.c @@ -361,6 +361,10 @@ dap_events_socket_t * dap_events_socket_queue_ptr_create_input(dap_events_socket dap_events_socket_t * s_create_type_queue_ptr(dap_worker_t * a_w, dap_events_socket_callback_queue_ptr_t a_callback) { dap_events_socket_t * l_es = DAP_NEW_Z(dap_events_socket_t); + if(!l_es){ + log_it(L_ERROR,"Can't allocate esocket!"); + return NULL; + } l_es->type = DESCRIPTOR_TYPE_QUEUE; l_es->flags = DAP_SOCK_QUEUE_PTR; if (a_w){ @@ -429,6 +433,7 @@ dap_events_socket_t * s_create_type_queue_ptr(dap_worker_t * a_w, dap_events_soc DAP_DELETE(l_es); l_es = NULL; log_it(L_CRITICAL,"Can't create mqueue descriptor %s: \"%s\" code %d",l_mq_name, l_errbuf, l_errno); + return NULL; }else{ l_es->mqd_id = l_mq_last_number; l_mq_last_number++; diff --git a/dap-sdk/net/core/dap_proc_queue.c b/dap-sdk/net/core/dap_proc_queue.c index 91502bfc2537be0f90aad6bd04d49f53c567cab7..ec98b6881c79a663ba4e06386c371159f42ea3bc 100644 --- a/dap-sdk/net/core/dap_proc_queue.c +++ b/dap-sdk/net/core/dap_proc_queue.c @@ -75,14 +75,16 @@ static void s_queue_esocket_callback( dap_events_socket_t * a_es, void * a_msg) dap_proc_queue_item_t * l_item = DAP_NEW_Z(dap_proc_queue_item_t); l_item->callback = l_msg->callback; l_item->callback_arg = l_msg->callback_arg; - l_item->next=l_queue->items_last ; - if ( l_queue->items_last) - l_queue->items_last->prev = l_item; - l_queue->items_last = l_item->next; + if ( l_queue->item_last) + l_queue->item_last->prev = l_item; - if( !l_queue->items_fisrt) - l_queue->items_fisrt = l_item; + l_item->next=l_queue->item_last ; + + l_queue->item_last = l_item; + + if( !l_queue->item_first) + l_queue->item_first = l_item; // Add on top so after call this callback will be executed first diff --git a/dap-sdk/net/core/dap_proc_thread.c b/dap-sdk/net/core/dap_proc_thread.c index 4015d0f0d13e3c26b9454650559b7139181dabc0..461a34413b1862b697038a528272f9828552837c 100644 --- a/dap-sdk/net/core/dap_proc_thread.c +++ b/dap-sdk/net/core/dap_proc_thread.c @@ -124,26 +124,28 @@ static void s_proc_event_callback(dap_events_socket_t * a_esocket, uint64_t a_va (void) a_value; //log_it(L_DEBUG, "Proc event callback"); dap_proc_thread_t * l_thread = (dap_proc_thread_t *) a_esocket->_inheritor; - dap_proc_queue_item_t * l_item = l_thread->proc_queue->items_fisrt; + dap_proc_queue_item_t * l_item = l_thread->proc_queue->item_first; dap_proc_queue_item_t * l_item_old = NULL; bool l_is_anybody_for_repeat=false; while(l_item){ bool l_is_finished = l_item->callback(l_thread, l_item->callback_arg); if (l_is_finished){ if(l_item_old){ - if ( ! l_item->prev ) - l_thread->proc_queue->items_last = l_item_old; - if ( ! l_item->next ) - l_thread->proc_queue->items_fisrt = l_item->prev; - - l_item_old->prev = l_item->prev; - + if ( ! l_item->next ){ // We deleted tail + l_thread->proc_queue->item_last = l_item_old; + } + l_item_old->prev = l_item->next; DAP_DELETE(l_item); l_item = l_item_old->prev; }else{ - l_thread->proc_queue->items_fisrt = l_item->prev; + l_thread->proc_queue->item_first = l_item->next; + if (l_thread->proc_queue->item_first) + l_thread->proc_queue->item_first->prev = NULL; // Prev if it was - now its NULL + else + l_thread->proc_queue->item_last = NULL; // NULL last item + DAP_DELETE(l_item); - l_item = l_thread->proc_queue->items_fisrt; + l_item = l_thread->proc_queue->item_first; } }else{ diff --git a/dap-sdk/net/core/dap_timerfd.c b/dap-sdk/net/core/dap_timerfd.c index 95d8146c391654eb92ec3edbdd1ee20be511483a..e259e889803c16cc89031ae46411717b55c18131 100644 --- a/dap-sdk/net/core/dap_timerfd.c +++ b/dap-sdk/net/core/dap_timerfd.c @@ -195,7 +195,7 @@ static void s_es_callback_timer(struct dap_events_socket *a_event_sock) #if defined DAP_OS_WINDOWS CloseHandle(l_timerfd->th); #endif - dap_events_socket_remove_and_delete_unsafe(l_timerfd->events_socket, false); + l_timerfd->events_socket->flags |= DAP_SOCK_SIGNAL_CLOSE; } } diff --git a/dap-sdk/net/core/include/dap_proc_queue.h b/dap-sdk/net/core/include/dap_proc_queue.h index b204d3692d9d8cd594bd16eb389d288cd1ac3aa9..278a0685e1a1e1c019012e65625ff11145cd2c19 100644 --- a/dap-sdk/net/core/include/dap_proc_queue.h +++ b/dap-sdk/net/core/include/dap_proc_queue.h @@ -37,8 +37,8 @@ typedef struct dap_proc_queue_item{ typedef struct dap_proc_queue{ dap_proc_thread_t * proc_thread; dap_events_socket_t *esocket; - dap_proc_queue_item_t * items_last; - dap_proc_queue_item_t * items_fisrt; + dap_proc_queue_item_t * item_last; + dap_proc_queue_item_t * item_first; } dap_proc_queue_t; dap_proc_queue_t * dap_proc_queue_create(dap_proc_thread_t * a_thread); diff --git a/modules/app-cli/dap_app_cli_net.c b/modules/app-cli/dap_app_cli_net.c index a472241c029a3b5d19c2547def93fd2cb00a5dac..161aa4008ed006d01fdea1f0b43dcfa024488080 100644 --- a/modules/app-cli/dap_app_cli_net.c +++ b/modules/app-cli/dap_app_cli_net.c @@ -95,6 +95,16 @@ static void dap_app_cli_http_read(dap_app_cli_connect_param_t *socket, dap_app_c size_t l_head_size = l_str_ptr - l_cmd->cmd_res; memmove(l_cmd->cmd_res, l_str_ptr, l_cmd->cmd_res_cur - l_head_size); l_cmd->cmd_res_cur -= l_head_size; + // read rest of data + if(l_cmd->cmd_res_cur < l_cmd->cmd_res_len) { + l_cmd->cmd_res = DAP_REALLOC(l_cmd->cmd_res, l_cmd->cmd_res_len + 1); + while((l_cmd->cmd_res_len - l_cmd->cmd_res_cur) > 0) { + ssize_t l_recv_len = recv(*socket, &l_cmd->cmd_res[l_cmd->cmd_res_cur], l_cmd->cmd_res_len - l_cmd->cmd_res_cur, 0); + if(l_recv_len <= 0) + break; + l_cmd->cmd_res_cur += l_recv_len; + } + } s_status++; } else { break; diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index 79748f4a8e887ad8fdd3cc155003bb2836b5b64f..4d68717b698a12978760201db76551b8cabacb80 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -93,8 +93,35 @@ void dap_chain_deinit(void) dap_chain_item_t * l_item = NULL, *l_tmp = NULL; pthread_rwlock_wrlock(&s_chain_items_rwlock); HASH_ITER(hh, s_chain_items, l_item, l_tmp) { - dap_chain_delete(s_chain_items->chain); - } + dap_chain_delete(l_item->chain); + } + pthread_rwlock_unlock(&s_chain_items_rwlock); +} + + +/** + * @brief dap_chain_deinit + * note: require dap_chain_enum_unlock() after + */ +dap_chain_t* dap_chain_enum(void** a_item) +{ + // if a_item == 0x1 then first item + dap_chain_item_t *l_item_start = (*a_item == 0x1) ? s_chain_items : (dap_chain_item_t*) *a_item; + dap_chain_item_t *l_item = NULL; + dap_chain_item_t *l_item_tmp = NULL; + pthread_rwlock_wrlock(&s_chain_items_rwlock); + HASH_ITER(hh, l_item_start, l_item, l_item_tmp) { + *a_item = l_item_tmp; + return l_item->chain; + } + return NULL ; +} + +/** + * @brief dap_chain_enum_unlock + */ +void dap_chain_enum_unlock(void) +{ pthread_rwlock_unlock(&s_chain_items_rwlock); } diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index a30da0cabcb2f09cefccf3337ae01af9c789b888..4e89caa2e3e3f413492c1f145319fb479fa332d2 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -192,6 +192,7 @@ static dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger, static void s_treshold_emissions_proc( dap_ledger_t * a_ledger); static void s_treshold_txs_proc( dap_ledger_t * a_ledger); +static void s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_item_t *a_token_item , dap_chain_datum_token_t * a_token, size_t a_token_size); static size_t s_treshold_emissions_max = 1000; static size_t s_treshold_txs_max = 10000; @@ -333,10 +334,7 @@ int dap_chain_ledger_token_add(dap_ledger_t * a_ledger, dap_chain_datum_token_t break; case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: log_it( L_NOTICE, "Private token %s type=DAP_CHAIN_DATUM_TOKEN_PRIVATE_DECL )", a_token->ticker); - l_token_item->total_supply = a_token->header_private.total_supply; - l_token_item->auth_signs= dap_chain_datum_token_signs_parse(a_token,a_token_size, - &l_token_item->auth_signs_total, - &l_token_item->auth_signs_valid ); + s_token_tsd_parse(a_ledger,l_token_item, a_token, a_token_size); break; default: log_it(L_WARNING,"Unknown token declaration type 0x%04X", a_token->type ); @@ -350,6 +348,152 @@ int dap_chain_ledger_token_add(dap_ledger_t * a_ledger, dap_chain_datum_token_t return 0; } +/** + * @brief s_token_tsd_parse + * @param a_ledger + * @param a_token + * @param a_token_size + */ +static void s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_item_t *a_token_item , dap_chain_datum_token_t * a_token, size_t a_token_size) +{ + dap_chain_datum_token_tsd_t * l_tsd= dap_chain_datum_token_tsd_get(a_token,a_token_size); + size_t l_tsd_size=0; + size_t l_tsd_total_size =a_token_size- (((byte_t*)l_tsd)- (byte_t*) a_token ); + + for( size_t l_offset=0; l_tsd && l_offset < l_tsd_total_size; l_offset += l_tsd_size ){ + l_tsd = (dap_chain_datum_token_tsd_t *) (((byte_t*)l_tsd ) +l_offset); + l_tsd_size = l_tsd? dap_chain_datum_token_tsd_size(l_tsd): 0; + if( l_tsd_size==0 ){ + log_it(L_ERROR,"Wrong zero TSD size, exiting TSD parse"); + break; + }else if (l_tsd_size + l_offset > l_tsd_total_size ){ + log_it(L_ERROR,"Wrong %zd TSD size, exiting TSD parse", l_tsd_size); + break; + } + switch (l_tsd->type) { + // set flags + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS:{ + a_token_item->flags |= dap_chain_datum_token_tsd_get_scalar(l_tsd,uint16_t); + }break; + + // unset flags + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS:{ + a_token_item->flags ^= dap_chain_datum_token_tsd_get_scalar(l_tsd,uint16_t); + }break; + + // set total supply + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY:{ + a_token_item->total_supply = dap_chain_datum_token_tsd_get_scalar(l_tsd,uint64_t); + }break; + + // Set total signs count value to set to be valid + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID:{ + a_token_item->auth_signs_valid = dap_chain_datum_token_tsd_get_scalar(l_tsd,uint16_t); + }break; + + // Remove owner signature by pkey fingerprint + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_REMOVE:{ + dap_hash_fast_t l_hash = dap_chain_datum_token_tsd_get_scalar(l_tsd,dap_hash_fast_t); + for( size_t i=0; i<a_token_item->auth_signs_total; i++){ + if (dap_hash_fast_compare(&l_hash, &a_token_item->auth_signs_pkey_hash[i] )){ + if (i+1 != a_token_item->auth_signs_total){ + memmove(a_token_item->auth_signs+i,a_token_item->auth_signs+i+1, + (a_token_item->auth_signs_total-i-1)*sizeof (void*)); + memmove(a_token_item->auth_signs_pkey_hash+i,a_token_item->auth_signs_pkey_hash+i+1, + (a_token_item->auth_signs_total-i-1)*sizeof (void*)); + } + a_token_item->auth_signs_total--; + a_token_item->auth_signs = DAP_REALLOC(a_token_item->auth_signs,a_token_item->auth_signs_total*sizeof (void*) ); + a_token_item->auth_signs_pkey_hash = DAP_REALLOC(a_token_item->auth_signs_pkey_hash,a_token_item->auth_signs_total*sizeof (void*) ); + break; + } + } + }break; + + // Add owner signature's pkey fingerprint + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_ADD:{ + if(l_tsd->size == sizeof (dap_hash_fast_t) ){ + a_token_item->auth_signs_total++; + a_token_item->auth_signs = DAP_REALLOC(a_token_item->auth_signs,a_token_item->auth_signs_total*sizeof (void*) ); + a_token_item->auth_signs_pkey_hash = DAP_REALLOC(a_token_item->auth_signs_pkey_hash,a_token_item->auth_signs_total*sizeof (void*) ); + a_token_item->auth_signs[a_token_item->auth_signs_total-1] = NULL; + memcpy( &a_token_item->auth_signs_pkey_hash[a_token_item->auth_signs_total-1], l_tsd->data, l_tsd->size ) ; + }else{ + log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_ADD expected to have %zd bytes data length, not %zd", + sizeof (dap_hash_fast_t), l_tsd_size ); + } + }break; + + /// ------- Permissions list flags, grouped by update-remove-clear operations -------- + // Blocked datum types list add, remove or clear + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_CLEAR:{ + }break; + + + + // Allowed datum types list add, remove or clear + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_CLEAR:{ + }break; + + //Allowed tx receiver addres list add, remove or clear + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_CLEAR:{ + }break; + + + //Blocked tx receiver addres list add, remove or clear + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_CLEAR:{ + }break; + + //Allowed tx sender addres list add, remove or clear + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_CLEAR:{ + }break; + + + //Blocked tx sender addres list add, remove or clear + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE:{ + }break; + + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_CLEAR:{ + }break; + default:{} + } + } + +} + int dap_chain_ledger_token_load(dap_ledger_t *a_ledger, dap_chain_datum_token_t *a_token, size_t a_token_size) { if (PVT(a_ledger)->last_ticker.found) { diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index cf6c1492664526add0905720fd802b14a08355b1..63b32a066797caf11e8403c144c2519acd674e1f 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -159,6 +159,9 @@ typedef struct dap_chain{ int dap_chain_init(void); void dap_chain_deinit(void); +dap_chain_t* dap_chain_enum(void** a_item); +void dap_chain_enum_unlock(void); + dap_chain_t * dap_chain_create(dap_ledger_t* a_ledger,const char * a_chain_net_name, const char * a_chain_name, dap_chain_net_id_t a_chain_net_id, dap_chain_id_t a_chain_id ); diff --git a/modules/global-db/dap_chain_global_db.c b/modules/global-db/dap_chain_global_db.c index ffdd19273dcf74056ce73b2f1542e08268142140..7ccaa5f4c337e837575895051682fd9a6e89c926 100644 --- a/modules/global-db/dap_chain_global_db.c +++ b/modules/global-db/dap_chain_global_db.c @@ -859,8 +859,11 @@ char* dap_chain_global_db_hash(const uint8_t *data, size_t data_size) void* dap_db_log_unpack(const void *a_data, size_t a_data_size, size_t *a_store_obj_count) { const dap_store_obj_pkt_t *l_pkt = (const dap_store_obj_pkt_t*) a_data; - if(!l_pkt || l_pkt->data_size != ((size_t) a_data_size - sizeof(dap_store_obj_pkt_t))) + if (! l_pkt) return NULL; + if( (l_pkt->data_size+ sizeof(dap_store_obj_pkt_t)) != ((size_t) a_data_size )) + return NULL; + size_t l_store_obj_count = 0; dap_store_obj_t *l_obj = dap_store_unpacket_multiple(l_pkt, &l_store_obj_count); if(a_store_obj_count) diff --git a/modules/global-db/dap_chain_global_db_hist.c b/modules/global-db/dap_chain_global_db_hist.c index 4ac96d14723d9dba34e479c32cba8cfc776cce10..57204af9dbbbcc9a7ea2dc1d04db140760d6ae87 100644 --- a/modules/global-db/dap_chain_global_db_hist.c +++ b/modules/global-db/dap_chain_global_db_hist.c @@ -12,7 +12,7 @@ #include "dap_chain_global_db_hist.h" #include "uthash.h" -// for dap_db_history_filter() +// for dap_db_history() typedef struct dap_tx_data{ dap_chain_hash_fast_t tx_hash; char tx_hash_str[70]; @@ -138,7 +138,7 @@ dap_list_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out) } -// for dap_db_history_filter() +// for dap_db_history() static dap_store_obj_t* get_prev_tx(dap_global_db_obj_t *a_objs, dap_tx_data_t *a_tx_data) { if(!a_objs || !a_tx_data) @@ -727,7 +727,7 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, const char *a_group_mempool * * return history string */ -char* dap_db_history_filter(dap_chain_addr_t * a_addr, const char *a_group_mempool) +char* dap_db_history(dap_chain_addr_t * a_addr, const char *a_group_mempool) { dap_string_t *l_str_out = dap_string_new(NULL); // load history diff --git a/modules/global-db/include/dap_chain_global_db.h b/modules/global-db/include/dap_chain_global_db.h index 76ae0627161424824ce8d44a65eb493be464bcf3..4dc540b2b1c5c25cab95439ab7ee88e11090ec9c 100644 --- a/modules/global-db/include/dap_chain_global_db.h +++ b/modules/global-db/include/dap_chain_global_db.h @@ -124,7 +124,7 @@ dap_list_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_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); +//char* dap_db_history(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/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c index 14c3284b028de289f7b2236e27b3dfe518cf4db0..24ffdaf0c7db7b27ed7c5d286083fe741a065568 100644 --- a/modules/mempool/dap_chain_mempool.c +++ b/modules/mempool/dap_chain_mempool.c @@ -106,7 +106,7 @@ int dap_chain_mempool_datum_add(dap_chain_datum_t * a_datum, dap_chain_t * a_cha * * return 0 Ok, -2 not enough funds to transfer, -1 other Error */ -int dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_t *a_key_from, +dap_hash_fast_t* dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_t *a_key_from, const dap_chain_addr_t* a_addr_from, const dap_chain_addr_t* a_addr_to, const dap_chain_addr_t* a_addr_fee, const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], @@ -116,7 +116,7 @@ int dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_t *a_key_from if(!a_chain | !a_key_from || ! a_addr_from || !a_key_from->priv_key_data || !a_key_from->priv_key_data_size || !dap_chain_addr_check_sum(a_addr_from) || !dap_chain_addr_check_sum(a_addr_to) || (a_addr_fee && !dap_chain_addr_check_sum(a_addr_fee)) || !a_value) - return -1; + return NULL; // find the transactions from which to take away coins uint64_t l_value_transfer = 0; // how many coins to transfer @@ -125,7 +125,7 @@ int dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_t *a_key_from a_addr_from, l_value_need, &l_value_transfer); if (!l_list_used_out) { log_it(L_WARNING,"Not enough funds to transfer"); - return -2; + return NULL; } // create empty transaction dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); @@ -151,7 +151,7 @@ int dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_t *a_key_from if(l_value_back) { if(dap_chain_datum_tx_add_out_item(&l_tx, a_addr_from, l_value_back) != 1) { dap_chain_datum_tx_delete(l_tx); - return -1; + return NULL; } } } @@ -164,12 +164,15 @@ int dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_t *a_key_from size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, l_tx_size); + dap_hash_fast_t * l_ret = DAP_NEW_Z(dap_hash_fast_t); + dap_hash_fast(l_tx, l_tx_size, l_ret); DAP_DELETE(l_tx); if(dap_chain_mempool_datum_add (l_datum, a_chain) == 0){ - return 0; + return l_ret; }else{ DAP_DELETE( l_datum ); - return -4; + DAP_DELETE(l_ret); + return NULL; } } diff --git a/modules/mempool/include/dap_chain_mempool.h b/modules/mempool/include/dap_chain_mempool.h index e4db94b8be5e956217b404eddddd4f07fa9f5e33..5fbf3e3d259370754770503aad85bb88f7d64513 100644 --- a/modules/mempool/include/dap_chain_mempool.h +++ b/modules/mempool/include/dap_chain_mempool.h @@ -44,7 +44,7 @@ void dap_datum_mempool_free(dap_datum_mempool_t *datum); void dap_chain_mempool_add_proc(dap_http_t * a_http_server, const char * a_url); int dap_chain_mempool_datum_add(dap_chain_datum_t *a_datum, dap_chain_t *a_chain); -int dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_t *a_key_from, +dap_hash_fast_t* dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_t *a_key_from, const dap_chain_addr_t* a_addr_from, const dap_chain_addr_t* a_addr_to, const dap_chain_addr_t* a_addr_fee, const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX], diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 940b411ceb809fc9e4e1466bfcd6a09f3ead25fa..2bcb8c44e484dc147e353bf4c3a2f28d20ef8380 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -526,10 +526,11 @@ static int s_net_states_proc(dap_chain_net_t *a_net) } dap_stream_worker_t *l_worker = dap_client_get_stream_worker(l_node_client->client); dap_stream_ch_chain_sync_request_t l_sync_gdb = {}; - // Get last timestamp in log - l_sync_gdb.id_start = (uint64_t) dap_db_get_last_id_remote(l_node_client->remote_node_addr.uint64); + // Get last timestamp in log if wasn't SYNC_FROM_ZERO flag + if (! (l_pvt_net->flags & F_DAP_CHAIN_NET_SYNC_FROM_ZERO) ) + l_sync_gdb.id_start = (uint64_t) dap_db_get_last_id_remote(l_node_client->remote_node_addr.uint64); l_sync_gdb.node_addr.uint64 = dap_chain_net_get_cur_addr_int(a_net); - log_it(L_DEBUG, "Prepared request to gdb sync from %llu to %llu", l_sync_gdb.id_start, l_sync_gdb.id_end); + log_it(L_DEBUG, "Prepared request to gdb sync from %llu to %llu", l_sync_gdb.id_start, l_sync_gdb.id_end?l_sync_gdb.id_end:-1 ); // find dap_chain_id_t dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(a_net, "gdb"); dap_chain_id_t l_chain_id = l_chain ? l_chain->id : (dap_chain_id_t ) {}; @@ -555,7 +556,7 @@ static int s_net_states_proc(dap_chain_net_t *a_net) default: log_it(L_INFO, "Node sync error %d",l_res); } - /* + dap_chain_node_client_reset(l_node_client); l_res = dap_stream_ch_chain_pkt_write_mt(l_worker, l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB_RVRS, a_net->pub.id, l_chain_id, a_net->pub.cell_id, &l_sync_gdb, sizeof(l_sync_gdb)); @@ -570,7 +571,7 @@ static int s_net_states_proc(dap_chain_net_t *a_net) default: log_it(L_INFO, "Node reverse sync error %d",l_res); } - */ + l_tmp = dap_list_next(l_tmp); } if (!l_pvt_net->links) { @@ -578,7 +579,9 @@ static int s_net_states_proc(dap_chain_net_t *a_net) } else if (l_pvt_net->state_target >= NET_STATE_SYNC_CHAINS) { l_pvt_net->state = NET_STATE_SYNC_CHAINS; } else { // Synchronization done, go offline - log_it(L_INFO, "Synchronization done"); + log_it(L_INFO, "Synchronization done, go offline"); + l_pvt_net->flags ^= F_DAP_CHAIN_NET_GO_SYNC; + l_pvt_net->flags ^= F_DAP_CHAIN_NET_SYNC_FROM_ZERO; l_pvt_net->state = l_pvt_net->state_target = NET_STATE_OFFLINE; } } @@ -601,7 +604,13 @@ static int s_net_states_proc(dap_chain_net_t *a_net) DL_FOREACH (a_net->pub.chains, l_chain) { dap_chain_node_client_reset(l_node_client); dap_stream_ch_chain_sync_request_t l_request = {0}; - dap_chain_get_atom_last_hash(l_chain,&l_request.hash_from); + + // TODO: Uncomment next block when finish with partial updates + /* + if (! (l_pvt_net->flags & F_DAP_CHAIN_NET_SYNC_FROM_ZERO) ) + dap_chain_get_atom_last_hash(l_chain,&l_request.hash_from); + */ + if ( !dap_hash_fast_is_blank(&l_request.hash_from) ){ if(dap_log_level_get() <= L_DEBUG){ char l_hash_str[128]={[0]='\0'}; @@ -666,12 +675,14 @@ static int s_net_states_proc(dap_chain_net_t *a_net) log_it( L_INFO,"Return back to state LINKS_PREPARE "); l_pvt_net->state = NET_STATE_LINKS_PREPARE; } else { - log_it(L_INFO, "Synchronization done"); if (l_pvt_net->state_target == NET_STATE_ONLINE) { - l_pvt_net->flags &= ~F_DAP_CHAIN_NET_GO_SYNC; + l_pvt_net->flags ^= F_DAP_CHAIN_NET_GO_SYNC; + l_pvt_net->flags ^= F_DAP_CHAIN_NET_SYNC_FROM_ZERO; l_pvt_net->state = NET_STATE_ONLINE; + log_it(L_INFO, "Synchronization done, status online"); } else { // Synchronization done, go offline l_pvt_net->state = l_pvt_net->state_target = NET_STATE_OFFLINE; + log_it(L_INFO, "Synchronization done, go offline"); } } } @@ -849,14 +860,16 @@ void dap_chain_net_delete( dap_chain_net_t * a_net ) int dap_chain_net_init() { dap_chain_node_cli_cmd_item_create ("net", s_cli_net, NULL, "Network commands", - "net -net <chain net name> go < online | offline >\n" - "\tFind and establish links and stay online\n" + "net -net <chain net name> [-mode update|all] go < online | offline >\n" + "\tFind and establish links and stay online. \n" + "\tMode \"update\" is by default when only new chains and gdb are updated. Mode \"all\" updates everything from zero\n" "net -net <chain net name> get status\n" "\tLook at current status\n" "net -net <chain net name> stats tx [-from <From time>] [-to <To time>] [-prev_sec <Seconds>] \n" "\tTransactions statistics. Time format is <Year>-<Month>-<Day>_<Hours>:<Minutes>:<Seconds> or just <Seconds> \n" - "net -net <chain net name> sync < all | gdb | chains >\n" + "net -net <chain net name> [-mode update|all] sync < all | gdb | chains >\n" "\tSyncronyze gdb, chains or everything\n" + "\tMode \"update\" is by default when only new chains and gdb are updated. Mode \"all\" updates everything from zero\n" "net -net <chain net name> link < list | add | del | info | establish >\n" "\tList, add, del, dump or establish links\n" "net -net <chain net name> ca add {-cert <cert name> | -hash <cert hash>}\n" @@ -1016,6 +1029,11 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) dap_chain_node_cli_find_option_val(argv, arg_index, argc, "ca", &l_ca_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "ledger", &l_ledger_str); + const char * l_sync_mode_str = "updates"; + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-mode", &l_sync_mode_str); + if ( !dap_strcmp(l_sync_mode_str,"all") ) + dap_chain_net_get_flag_sync_from_zero(l_net); + if ( l_stats_str ){ if ( strcmp(l_stats_str,"tx") == 0 ) { const char *l_to_str = NULL; @@ -1126,11 +1144,6 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) } else if( l_sync_str) { - const char * l_sync_mode_str = "updates"; - dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-mode", &l_sync_mode_str); - if ( !dap_strcmp(l_sync_mode_str,"all") ) - dap_chain_net_get_flag_sync_from_zero(l_net); - if ( strcmp(l_sync_str,"all") == 0 ) { dap_chain_node_cli_set_reply_text(a_str_reply, "SYNC_ALL state requested to state machine. Current state: %s\n", @@ -1790,13 +1803,16 @@ void dap_chain_net_deinit() dap_chain_net_t **dap_chain_net_list(uint16_t *a_size) { *a_size = HASH_COUNT(s_net_items); - dap_chain_net_t **l_net_list = DAP_NEW_SIZE(dap_chain_net_t *, (*a_size) * sizeof(dap_chain_net_t *)); - dap_chain_net_item_t *l_current_item, *l_tmp; - int i = 0; - HASH_ITER(hh, s_net_items, l_current_item, l_tmp) { - l_net_list[i++] = l_current_item->chain_net; - } - return l_net_list; + if(*a_size){ + dap_chain_net_t **l_net_list = DAP_NEW_SIZE(dap_chain_net_t *, (*a_size) * sizeof(dap_chain_net_t *)); + dap_chain_net_item_t *l_current_item, *l_tmp; + int i = 0; + HASH_ITER(hh, s_net_items, l_current_item, l_tmp) { + l_net_list[i++] = l_current_item->chain_net; + } + return l_net_list; + }else + return NULL; } /** @@ -2600,11 +2616,12 @@ static uint8_t *dap_chain_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash) { uint16_t l_net_count; dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count); - if (l_net_count) { + if (l_net_count && l_net_list) { uint8_t *l_ret = DAP_NEW_SIZE(uint8_t, l_net_count); for (uint16_t i = 0; i < l_net_count; i++) { l_ret[i] = s_net_check_acl(l_net_list[i], a_pkey_hash); } + DAP_DELETE(l_net_list); return l_ret; } return NULL; diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c index ff8712aab3b8221f0d37574ddc7e72053d40c89f..5c4f91cf18c62d5bfee855d97d71c73d10af5395 100644 --- a/modules/net/dap_chain_node_cli.c +++ b/modules/net/dap_chain_node_cli.c @@ -63,6 +63,7 @@ #include "dap_list.h" #include "dap_chain_node_cli_cmd.h" #include "dap_chain_node_client.h" +#include "dap_chain_node_cli_cmd_tx.h" #include "dap_chain_node_cli.h" //#include "dap_chain_node_cli.h" @@ -341,7 +342,16 @@ static void* thread_one_client_func(void *args) "Content-Length: %d\r\n\r\n" "%s", strlen(reply_body), reply_body); - /*int ret = */ send(newsockfd, reply_str, strlen(reply_str) ,0); + size_t l_reply_step = 32768; + size_t l_reply_len = strlen(reply_str); + size_t l_reply_rest = l_reply_len; + while(l_reply_rest) { + size_t l_send_bytes = min(l_reply_step, l_reply_rest); + int ret = send(newsockfd, reply_str + l_reply_len - l_reply_rest, l_send_bytes, 0); + if(ret<=0) + break; + l_reply_rest-=l_send_bytes; + }; DAP_DELETE(str_reply); DAP_DELETE(reply_str); DAP_DELETE(reply_body); @@ -989,6 +999,18 @@ int dap_chain_node_cli_init(dap_config_t * g_config) dap_chain_node_cli_cmd_item_create("tx_history", com_tx_history, NULL, "Transaction history (for address or by hash)", "tx_history [-addr <addr> | -w <wallet name> | -tx <tx_hash>] -net <net name> -chain <chain name>\n"); + // Ledger info + dap_chain_node_cli_cmd_item_create("ledger", com_ledger, NULL, "Ledger info", + "ledger list coins -net <network name>\n" + "ledger list coins_cond -net <network name>\n" + "ledger list addrs -net <network name>\n" + "ledger tx [all | -addr <addr> | -w <wallet name> | -tx <tx_hash>] [-chain <chain name>] -net <network name>\n"); + + // Token info + dap_chain_node_cli_cmd_item_create("token", com_token, NULL, "Token info", + "token list -net <network name>\n" + "token tx all name <token name> -net <network name> [-page_start <page>] [-page <page>]\n"); + // Log dap_chain_node_cli_cmd_item_create ("print_log", com_print_log, NULL, "Print log info", "print_log [ts_after <timestamp >] [limit <line numbers>]\n" ); diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 01fb9ae72fd94106692d31f986ae43147a15c01c..af0c9397eaee5a5184b3d375a2c3bb8be12031bd 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -3743,18 +3743,29 @@ int com_tx_create(int argc, char ** argv, void *arg_func, char **str_reply) dap_string_t *string_ret = dap_string_new(NULL); //g_string_printf(string_ret, "from=%s\nto=%s\nval=%lld\nfee=%s\nval_fee=%lld\n\n", // addr_base58_from, addr_base58_to, value, addr_base58_fee, value_fee); - - int res = - l_tx_num ? - dap_chain_mempool_tx_create_massive(l_chain, dap_chain_wallet_get_key(l_wallet, 0), addr_from, + int res = 0; + if(l_tx_num){ + res = dap_chain_mempool_tx_create_massive(l_chain, dap_chain_wallet_get_key(l_wallet, 0), addr_from, addr_to, addr_fee, - l_token_ticker, value, value_fee, l_tx_num) - : - dap_chain_mempool_tx_create(l_chain, dap_chain_wallet_get_key(l_wallet, 0), addr_from, addr_to, - addr_fee, - l_token_ticker, value, value_fee); - dap_string_append_printf(string_ret, "transfer=%s\n", - (res == 0) ? "Ok" : (res == -2) ? "False, not enough funds for transfer" : "False"); + l_token_ticker, value, value_fee, l_tx_num); + + dap_string_append_printf(string_ret, "transfer=%s\n", + (res == 0) ? "Ok" : (res == -2) ? "False, not enough funds for transfer" : "False"); + }else{ + dap_hash_fast_t * l_tx_hash = dap_chain_mempool_tx_create(l_chain, dap_chain_wallet_get_key(l_wallet, 0), addr_from, addr_to, + addr_fee, + l_token_ticker, value, value_fee); + if (l_tx_hash){ + char l_tx_hash_str[80]={[0]='\0'}; + dap_chain_hash_fast_to_str(l_tx_hash,l_tx_hash_str,sizeof (l_tx_hash_str)-1); + dap_string_append_printf(string_ret, "transfer=Ok\ntx_hash=%s\n",l_tx_hash_str); + DAP_DELETE(l_tx_hash); + }else{ + dap_string_append_printf(string_ret, "transfer=False\n"); + res = -1; + } + + } dap_chain_node_cli_set_reply_text(str_reply, string_ret->str); dap_string_free(string_ret, false); diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c index 67cc3f80663625ed6ce8a5c3fb227ba05430c2e9..4882751ee5de8ae28b4a16426ca26a0adbb0dc8f 100644 --- a/modules/net/dap_chain_node_cli_cmd_tx.c +++ b/modules/net/dap_chain_node_cli_cmd_tx.c @@ -26,15 +26,18 @@ #include <stddef.h> #include <pthread.h> -#include <dap_common.h> -#include <dap_enc_base58.h> -#include <dap_strfuncs.h> -#include <dap_string.h> -#include <dap_list.h> -#include <dap_hash.h> +#include "dap_common.h" +#include "dap_enc_base58.h" +#include "dap_strfuncs.h" +#include "dap_string.h" +#include "dap_list.h" +#include "dap_hash.h" +#include "dap_chain_wallet.h" +#include "dap_chain_datum.h" +#include "dap_chain_datum_token.h" #include "dap_chain_datum_tx_items.h" - +#include "dap_chain_node_cli.h" #include "dap_chain_node_cli_cmd_tx.h" #define LOG_TAG "chain_node_cli_cmd_tx" @@ -683,3 +686,918 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, cons char *l_ret_str = l_str_out ? dap_string_free(l_str_out, false) : NULL; return l_ret_str; } + +static char* dap_db_history_token_list(dap_chain_t * a_chain, const char *a_token_name, const char *a_hash_out_type, size_t *a_token_num) +{ + dap_string_t *l_str_out = dap_string_new(NULL); + *a_token_num = 0; + bool l_tx_hash_found = false; + // list all transactions + dap_tx_data_t *l_tx_data_hash = NULL; + // load transactions + size_t l_atom_size = 0; + dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain); + dap_chain_atom_ptr_t *l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = (a_chain->callback_atom_get_datums && l_atom && l_atom_size) ? + a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count) : NULL; + if(!l_datums) { + log_it(L_WARNING, "Not defined callback_atom_get_datums for chain \"%s\"", a_chain->name); + return NULL ; + } + for(size_t l_datum_n = 0; l_datum_n < l_datums_count; l_datum_n++) { + + dap_chain_datum_t *l_datum = l_datums[l_datum_n]; + if(!l_datum ) {// || l_datum->header.type_id != DAP_CHAIN_DATUM_TX) { + // go to next atom + //l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); + continue; + } + /* + // transaction + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data; + dap_list_t *l_records_out = NULL; + + + dap_chain_datum_t *l_datum = + a_chain->callback_atom_get_datum ? + a_chain->callback_atom_get_datum(l_atom) : (dap_chain_datum_t*) l_atom; + if(!l_datum) { + // go to next transaction + l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter); + l_atom_size = a_chain->callback_atom_get_size(l_atom); + log_it(L_ERROR, "datum=NULL for atom=0x%x", l_atom); + continue; + } +*/ + char l_time_str[70]; + // get time of create datum + if(dap_time_to_str_rfc822(l_time_str, 71, l_datum->header.ts_create) < 1) + l_time_str[0] = '\0'; + if(l_datum->header.type_id==DAP_CHAIN_DATUM_TOKEN_DECL) { + dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data; + if(!a_token_name || !dap_strcmp(l_token->ticker, a_token_name)) { + dap_string_append_printf(l_str_out, "token %s, created: %s\n", l_token->ticker, l_time_str); + switch (l_token->type) { + // Simple private token decl + case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: + dap_string_append_printf(l_str_out, " total_supply: %.0llf(%llu), signs: valid/total %02d/%02d \n", + l_token->header_private.total_supply / DATOSHI_LD, + l_token->header_private.total_supply, + l_token->header_private.signs_valid, l_token->header_private.signs_total); + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: + dap_string_append_printf(l_str_out, " tsd_total_size: %llu, flags: 0x%x \n", + l_token->header_private_decl.tsd_total_size, + l_token->header_private_decl.flags); + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: + dap_string_append_printf(l_str_out, " tsd_total_size: %llu, padding: 0x%x \n", + l_token->header_private_update.tsd_total_size, + l_token->header_private_update.padding); + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC: { + char *l_addr = dap_chain_addr_to_str(&l_token->header_public.premine_address); + dap_string_append_printf(l_str_out, + " total_supply: %.0llf(%llu), flags: 0x%x\n, premine_supply: %llu, premine_address '%s'\n", + l_token->header_public.total_supply / DATOSHI_LD, + l_token->header_public.total_supply, + l_token->header_public.flags, + l_token->header_public.premine_supply, + l_addr ? l_addr : "-"); + DAP_DELETE(l_addr); + } + break; + default: + dap_string_append_printf(l_str_out, "unknown token type: 0x%x\n", l_token->type); + break; + + } + dap_string_append_printf(l_str_out, "\n"); + (*a_token_num)++; + } + } + + // go to next transaction + //l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter); + //l_atom_size = a_chain->callback_atom_get_size(l_atom); + } + + a_chain->callback_atom_iter_delete(l_atom_iter); + 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 + */ +static char* dap_db_history_filter(dap_chain_t * a_chain, const char *a_filter_token_name, const char *a_filtr_addr_base58, const char *a_hash_out_type, long a_datum_start, long a_datum_end, long *a_total_datums) +{ + dap_string_t *l_str_out = dap_string_new(NULL); + + bool l_tx_hash_found = false; + // list all transactions + dap_tx_data_t *l_tx_data_hash = NULL; + // load transactions + size_t l_atom_size = 0; + dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain); + dap_chain_atom_ptr_t *l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); + size_t l_datum_num = 0, l_token_num = 0, l_emission_num = 0, l_tx_num = 0; + size_t l_datum_num_global = a_total_datums ? *a_total_datums : 0; + while(l_atom && l_atom_size) { + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = + (a_chain->callback_atom_get_datums && l_atom && l_atom_size) ? + a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count) : NULL; + if(!l_datums) { + log_it(L_WARNING, "Not defined callback_atom_get_datums for chain \"%s\"", a_chain->name); + return NULL ; + } + for(size_t l_datum_n = 0; l_datum_n < l_datums_count; l_datum_n++) { + + dap_chain_datum_t *l_datum = l_datums[l_datum_n]; + if(!l_datum) { // || l_datum->header.type_id != DAP_CHAIN_DATUM_TX) { + // go to next atom + //l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); + continue; + } + + /*dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain); + dap_chain_atom_ptr_t *l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter); + size_t l_atom_size = a_chain->callback_atom_get_size(l_atom); + size_t l_datum_num = 0, l_token_num = 0, l_emission_num = 0, l_tx_num = 0; + while(l_atom && l_atom_size) { + dap_chain_datum_t *l_datum = + a_chain->callback_atom_get_datum ? + a_chain->callback_atom_get_datum(l_atom) : (dap_chain_datum_t*) l_atom; + if(!l_datum) { + // go to next transaction + l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter); + l_atom_size = a_chain->callback_atom_get_size(l_atom); + log_it(L_ERROR, "datum=NULL for atom=0x%x", l_atom); + continue; + }*/ + char l_time_str[70]; + // get time of create datum + if(dap_time_to_str_rfc822(l_time_str, 71, l_datum->header.ts_create) < 1) + l_time_str[0] = '\0'; + switch (l_datum->header.type_id) { + + // token + case DAP_CHAIN_DATUM_TOKEN_DECL: { + + // no token necessary for addr + if(a_filtr_addr_base58) { + break; + } + + dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data; + //if(a_datum_start < 0 || (l_datum_num >= a_datum_start && l_datum_num < a_datum_end)) + // datum out of page + if(a_datum_start >= 0 && (l_datum_num+l_datum_num_global < a_datum_start || l_datum_num+l_datum_num_global >= a_datum_end)){ + l_token_num++; + break; + } + if(!a_filter_token_name || !dap_strcmp(l_token->ticker, a_filter_token_name)) { + dap_string_append_printf(l_str_out, "token %s, created: %s\n", l_token->ticker, l_time_str); + switch (l_token->type) { + // Simple private token decl + case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: + dap_string_append_printf(l_str_out, " total_supply: %.0llf(%llu), signs: valid/total %02d/%02d \n", + l_token->header_private.total_supply / DATOSHI_LD, + l_token->header_private.total_supply, + l_token->header_private.signs_valid, l_token->header_private.signs_total); + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: + dap_string_append_printf(l_str_out, " tsd_total_size: %llu, flags: 0x%x \n", + l_token->header_private_decl.tsd_total_size, + l_token->header_private_decl.flags); + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: + dap_string_append_printf(l_str_out, " tsd_total_size: %llu, padding: 0x%x \n", + l_token->header_private_update.tsd_total_size, + l_token->header_private_update.padding); + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC: { + char *l_addr = dap_chain_addr_to_str(&l_token->header_public.premine_address); + dap_string_append_printf(l_str_out, + " total_supply: %.0llf(%llu), flags: 0x%x\n, premine_supply: %llu, premine_address '%s'\n", + l_token->header_public.total_supply / DATOSHI_LD, + l_token->header_public.total_supply, + l_token->header_public.flags, + l_token->header_public.premine_supply, + l_addr ? l_addr : "-"); + DAP_DELETE(l_addr); + } + break; + default: + dap_string_append_printf(l_str_out, "unknown token type: 0x%x\n", l_token->type); + break; + + } + dap_string_append_printf(l_str_out, "\n"); + l_token_num++; + } + } + break; + + // emission + case DAP_CHAIN_DATUM_TOKEN_EMISSION: { + // datum out of page + if(a_datum_start >= 0 && (l_datum_num+l_datum_num_global < a_datum_start || l_datum_num+l_datum_num_global >= a_datum_end)) { + l_token_num++; + break; + } + dap_chain_datum_token_emission_t *l_token_em = (dap_chain_datum_token_emission_t*) l_datum->data; + if(!a_filter_token_name || !dap_strcmp(l_token_em->hdr.ticker, a_filter_token_name)) { + char * l_token_emission_address_str = dap_chain_addr_to_str(&(l_token_em->hdr.address)); + // filter for addr + if(dap_strcmp(a_filtr_addr_base58,l_token_emission_address_str)) { + break; + } + + dap_string_append_printf(l_str_out, "emission: %.0llf(%llu) %s, type: %s, version: %d\n", + l_token_em->hdr.value / DATOSHI_LD, l_token_em->hdr.value, l_token_em->hdr.ticker, + c_dap_chain_datum_token_emission_type_str[l_token_em->hdr.type], + l_token_em->hdr.version); + dap_string_append_printf(l_str_out, " to addr: %s\n", l_token_emission_address_str); + + DAP_DELETE(l_token_emission_address_str); + switch (l_token_em->hdr.type) { + case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_UNDEFINED: + break; + case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH: + dap_string_append_printf(l_str_out, " signs_count: %d\n", l_token_em->data.type_auth.signs_count); + break; + case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ALGO: + dap_string_append_printf(l_str_out, " codename: %s\n", l_token_em->data.type_algo.codename); + break; + case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER: + dap_string_append_printf(l_str_out, " value_start: %.0llf(%llu), codename: %s\n", + l_token_em->data.type_atom_owner.value_start / DATOSHI_LD, + l_token_em->data.type_atom_owner.value_start, + l_token_em->data.type_atom_owner.value_change_algo_codename); + break; + case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT: { + char *l_addr = dap_chain_addr_to_str(&l_token_em->data.type_presale.addr); + // get time of create datum + if(dap_time_to_str_rfc822(l_time_str, 71, l_token_em->data.type_presale.lock_time) < 1) + l_time_str[0] = '\0'; + dap_string_append_printf(l_str_out, " flags: 0x%x, lock_time: %s\n", l_token_em->data.type_presale.flags, l_time_str); + dap_string_append_printf(l_str_out, " addr: %s\n", l_addr); + DAP_DELETE(l_addr); + } + break; + } + dap_string_append_printf(l_str_out, "\n"); + l_emission_num++; + } + } + break; + + // transaction + case DAP_CHAIN_DATUM_TX:{ + + // datum out of page + if(a_datum_start >= 0 && (l_datum_num+l_datum_num_global < a_datum_start || l_datum_num+l_datum_num_global >= a_datum_end)) { + l_tx_num++; + break; + } + 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_tx_data_t *l_tx_data = NULL; + + // calc tx 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); + char *tx_hash_str; + char l_tx_hash_str[70]; + dap_chain_hash_fast_to_str(&l_tx_hash, l_tx_hash_str, 70); + if(!dap_strcmp(a_hash_out_type, "hex")) + tx_hash_str = dap_strdup(l_tx_hash_str); + else + tx_hash_str = dap_enc_base58_from_hex_str_to_str(l_tx_hash_str); + + dap_string_append_printf(l_str_out, "transaction: %s hash: %s\n", l_list_tx_token ? "(emit)" : "", tx_hash_str); + DAP_DELETE(tx_hash_str); + + 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 - only for first OUT item + 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->datum = DAP_NEW_SIZE(dap_chain_datum_t, l_atom_size); + memcpy(l_tx_data->datum, l_datum, l_atom_size); + // save token name + if(l_list_tx_token) { + dap_chain_tx_token_t *tk = l_list_tx_token->data; + 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); + + // found a_tx_hash now + // transaction time + if(l_tx->header.ts_created > 0) { + time_t rawtime = (time_t) l_tx->header.ts_created; + struct tm l_timeinfo = { 0 }; + localtime_r(&rawtime, &l_timeinfo); + dap_string_append_printf(l_str_out, " %s", asctime(&l_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]; + char *tx_hash_base58_str = NULL; + if(!dap_hash_fast_is_blank(&tx_prev_hash)) { + tx_hash_base58_str = dap_enc_base58_from_hex_str_to_str(l_tx_data->tx_hash_str); + 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"); + tx_hash_base58_str = dap_strdup("Null"); + } + if(!dap_strcmp(a_hash_out_type, "hex")) + dap_string_append_printf(l_str_out, " IN item \n prev tx_hash %s\n", l_tx_hash_str); + else + dap_string_append_printf(l_str_out, " IN item \n prev tx_hash %s\n", tx_hash_base58_str); + DAP_DELETE(tx_hash_base58_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_chain_datum_t *l_datum_prev = get_prev_tx(l_tx_data_prev); + 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 ? l_tx_prev_out->header.value : 0); + } + 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; + l_tx_num++; + } + break; + default: + dap_string_append_printf(l_str_out, "unknown datum type=%d %lld %s to %s\n", l_datum->header.type_id); + break; + } + l_datum_num++; + } + // go to next transaction + l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); + //l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter); + //l_atom_size = a_chain->callback_atom_get_size(l_atom); + } + a_chain->callback_atom_iter_delete(l_atom_iter); + //total + dap_string_append_printf(l_str_out, + "---------------\ntokens: %u\nemissions: %u\ntransactions: %u\ntotal datums: %u", l_token_num, + l_emission_num, l_tx_num, l_datum_num); + + // return total datums + if(a_total_datums) + *a_total_datums = l_datum_num; + // 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) + { + HASH_DEL(l_tx_data_hash, l_iter_current); + // delete datum + DAP_DELETE(l_iter_current->datum); + // delete struct + DAP_DELETE(l_iter_current); + } + + // 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; +} + + + + +/** + * ledger command + * + */ +int com_ledger(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply) +{ + enum { CMD_NONE, CMD_LIST, CMD_TX_HISTORY }; + int arg_index = 1; + const char *l_addr_base58 = NULL; + const char *l_wallet_name = NULL; + const char *l_net_str = NULL; + const char *l_chain_str = NULL; + const char *l_tx_hash_str = NULL; + + dap_chain_t * l_chain = NULL; + dap_chain_net_t * l_net = NULL; + + const char * l_hash_out_type = NULL; + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-H", &l_hash_out_type); + if(!l_hash_out_type) + l_hash_out_type = "base58"; + if(dap_strcmp(l_hash_out_type,"hex") && dap_strcmp(l_hash_out_type,"base58")) { + dap_chain_node_cli_set_reply_text(a_str_reply, "invalid parameter -H, valid values: -H <hex | base58>"); + return -1; + } + + int l_cmd = CMD_NONE; + if (dap_chain_node_cli_find_option_val(a_argv, 1, 2, "list", NULL)) + l_cmd = CMD_LIST; + else if (dap_chain_node_cli_find_option_val(a_argv, 1, 2, "tx", NULL)) + l_cmd = CMD_TX_HISTORY; + // command tx_history + if(l_cmd == CMD_TX_HISTORY) { + bool l_is_all = dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-all", NULL); + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-addr", &l_addr_base58); + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-w", &l_wallet_name); + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-net", &l_net_str); + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-chain", &l_chain_str); + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-tx", &l_tx_hash_str); + + if(!l_is_all && !l_addr_base58 && !l_wallet_name && !l_tx_hash_str) { + dap_chain_node_cli_set_reply_text(a_str_reply, "command requires parameter '-all' or '-addr' or '-w'"); + return -1; + } + + // Select chain network + if(!l_net_str) { + dap_chain_node_cli_set_reply_text(a_str_reply, "command requires parameter '-net'"); + return -2; + } else { + if((l_net = dap_chain_net_by_name(l_net_str)) == NULL) { // Can't find such network + dap_chain_node_cli_set_reply_text(a_str_reply, + "command requires parameter '-net' to be valid chain network name"); + return -3; + } + } + //Select chain emission + if(!l_chain_str) { // chain may be null -> then all chain use + //dap_chain_node_cli_set_reply_text(a_str_reply, "command requires parameter '-chain'"); + //return -4; + } else { + if((l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str)) == NULL) { // Can't find such chain + dap_chain_node_cli_set_reply_text(a_str_reply, + "command requires parameter '-chain' to be valid chain name in chain net %s", + l_net_str); + return -5; + } + } + //char *l_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain); + //const char *l_chain_group = dap_chain_gdb_get_group(l_chain); + + dap_chain_hash_fast_t l_tx_hash; + if(l_tx_hash_str) { + if(dap_chain_hash_fast_from_str(l_tx_hash_str, &l_tx_hash) < 0) { + l_tx_hash_str = NULL; + dap_chain_node_cli_set_reply_text(a_str_reply, "tx hash not recognized"); + return -1; + } +// char hash_str[99]; +// dap_chain_hash_fast_to_str(&l_tx_hash, hash_str,99); +// int gsdgsd=523; + } + dap_chain_addr_t *l_addr = NULL; + // if need addr + if(l_wallet_name || l_addr_base58) { + if(l_wallet_name) { + const char *c_wallets_path = dap_chain_wallet_get_path(g_config); + dap_chain_wallet_t * l_wallet = dap_chain_wallet_open(l_wallet_name, c_wallets_path); + if(l_wallet) { + dap_chain_addr_t *l_addr_tmp = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet, + l_net->pub.id); + l_addr = DAP_NEW_SIZE(dap_chain_addr_t, sizeof(dap_chain_addr_t)); + memcpy(l_addr, l_addr_tmp, sizeof(dap_chain_addr_t)); + dap_chain_wallet_close(l_wallet); + } + } + if(!l_addr && l_addr_base58) { + l_addr = dap_chain_addr_from_str(l_addr_base58); + } + if(!l_addr && !l_tx_hash_str) { + dap_chain_node_cli_set_reply_text(a_str_reply, "wallet address not recognized"); + return -1; + } + } + + dap_string_t *l_str_ret = dap_string_new(NULL); //char *l_str_ret = NULL; + dap_chain_t *l_chain_cur; + void *l_chain_tmp = (void*)0x1; + int l_num = 0; + // only one chain + if(l_chain) + l_chain_cur = l_chain; + // all chain + else + l_chain_cur = dap_chain_enum(&l_chain_tmp); + while(l_chain_cur) { + // only selected net + if(l_net->pub.id.uint64 == l_chain_cur->net_id.uint64) { + // separator between chains + if(l_num>0 && !l_chain) + dap_string_append(l_str_ret, "---------------\n"); + + char *l_str_out = NULL; + dap_string_append_printf(l_str_ret, "chain: %s\n", l_chain_cur->name); + if(l_is_all) { + // without filters + l_str_out = dap_db_history_filter(l_chain_cur, NULL, NULL, l_hash_out_type, -1, 0, NULL); + dap_string_append_printf(l_str_ret, "all history:\n%s\n", l_str_out ? l_str_out : " empty"); + } + else { + l_str_out = l_tx_hash_str ? + dap_db_history_tx(&l_tx_hash, l_chain_cur, l_hash_out_type) : + dap_db_history_addr(l_addr, l_chain_cur, l_hash_out_type); + + if(l_tx_hash_str) { + dap_string_append_printf(l_str_ret, "history for tx hash %s:\n%s\n", l_tx_hash_str, + l_str_out ? l_str_out : " empty"); + } + else if(l_addr) { + char *l_addr_str = dap_chain_addr_to_str(l_addr); + dap_string_append_printf(l_str_ret, "history for addr %s:\n%s\n", l_addr_str, + l_str_out ? l_str_out : " empty"); + DAP_DELETE(l_addr_str); + } + } + DAP_DELETE(l_str_out); + l_num++; + } + // only one chain use + if(l_chain) + break; + dap_chain_enum_unlock(); + l_chain_cur = dap_chain_enum(&l_chain_tmp); + } + // all chain + if(!l_chain) + dap_chain_enum_unlock(); + dap_chain_node_cli_set_reply_text(a_str_reply, l_str_ret->str); + dap_string_free(l_str_ret, true); + return 0; + } + else{ + dap_chain_node_cli_set_reply_text(a_str_reply, "command requires parameter 'list' or 'tx' or 'info'"); + return -1; + } +} + +/** + * token command + * + */ +int com_token(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply) +{ + enum { CMD_NONE, CMD_LIST, CMD_INFO, CMD_TX }; + int arg_index = 1; + //const char *l_addr_base58 = NULL; + //const char *l_wallet_name = NULL; + const char *l_net_str = NULL; + const char *l_chain_str = NULL; + + dap_chain_t * l_chain = NULL; + dap_chain_net_t * l_net = NULL; + + const char * l_hash_out_type = NULL; + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-H", &l_hash_out_type); + if(!l_hash_out_type) + l_hash_out_type = "base58"; + if(dap_strcmp(l_hash_out_type,"hex") && dap_strcmp(l_hash_out_type,"base58")) { + dap_chain_node_cli_set_reply_text(a_str_reply, "invalid parameter -H, valid values: -H <hex | base58>"); + return -1; + } + + //bool l_is_all = dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-all", NULL); + //dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-addr", &l_addr_base58); + //dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-w", &l_wallet_name); + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-net", &l_net_str); + //dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-chain", &l_chain_str); + //dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-tx", &l_tx_hash_str); + + // Select chain network + if(!l_net_str) { + dap_chain_node_cli_set_reply_text(a_str_reply, "command requires parameter '-net'"); + return -2; + } else { + if((l_net = dap_chain_net_by_name(l_net_str)) == NULL) { // Can't find such network + dap_chain_node_cli_set_reply_text(a_str_reply, + "command requires parameter '-net' to be valid chain network name"); + return -3; + } + } + + int l_cmd = CMD_NONE; + if (dap_chain_node_cli_find_option_val(a_argv, 1, 2, "list", NULL)) + l_cmd = CMD_LIST; + else if (dap_chain_node_cli_find_option_val(a_argv, 1, 2, "info", NULL)) + l_cmd = CMD_INFO; + else if (dap_chain_node_cli_find_option_val(a_argv, 1, 2, "tx", NULL)) + l_cmd = CMD_TX; + // token list + if(l_cmd == CMD_LIST) { + dap_string_t *l_str_out = dap_string_new(NULL); + size_t l_token_num_total = 0; + // get first chain + void *l_chain_tmp = (void*)0x1; + dap_chain_t *l_chain_cur = dap_chain_enum(&l_chain_tmp); + while(l_chain_cur) { + // only selected net + if(l_net->pub.id.uint64 == l_chain_cur->net_id.uint64) { + size_t l_token_num = 0; + char *token_list_str = dap_db_history_token_list(l_chain_cur, NULL, l_hash_out_type, &l_token_num); + if(token_list_str) + dap_string_append(l_str_out, token_list_str); + l_token_num_total += l_token_num; + } + // next chain + dap_chain_enum_unlock(); + l_chain_cur = dap_chain_enum(&l_chain_tmp); + } + dap_chain_enum_unlock(); + //total + dap_string_append_printf(l_str_out, "---------------\ntokens: %u\n", l_token_num_total); + dap_chain_node_cli_set_reply_text(a_str_reply, l_str_out->str); + dap_string_free(l_str_out, true); + return 0; + + } + // token info + else if(l_cmd == CMD_INFO) { + const char *l_token_name_str = NULL; + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-name", &l_token_name_str); + if(!l_token_name_str) { + dap_chain_node_cli_set_reply_text(a_str_reply, "command requires parameter '-name' <token name>"); + return -4; + } + + dap_string_t *l_str_out = dap_string_new(NULL); + size_t l_token_num_total = 0; + // get first chain + void *l_chain_tmp = (void*)0x1; + dap_chain_t *l_chain_cur = dap_chain_enum(&l_chain_tmp); + while(l_chain_cur) { + // only selected net + if(l_net->pub.id.uint64 == l_chain_cur->net_id.uint64) { + size_t l_token_num = 0; + // filter - token name + char *token_list_str = dap_db_history_token_list(l_chain_cur, l_token_name_str, l_hash_out_type, &l_token_num); + if(token_list_str) + dap_string_append(l_str_out, token_list_str); + l_token_num_total += l_token_num; + } + // next chain + dap_chain_enum_unlock(); + l_chain_cur = dap_chain_enum(&l_chain_tmp); + } + dap_chain_enum_unlock(); + if(!l_token_num_total) + dap_string_append_printf(l_str_out, "token '%s' not found\n", l_token_name_str); + dap_chain_node_cli_set_reply_text(a_str_reply, l_str_out->str); + dap_string_free(l_str_out, true); + return 0; + + } + // command tx history + else if(l_cmd == CMD_TX) { + + enum { SUBCMD_TX_NONE, SUBCMD_TX_ALL, SUBCMD_TX_ADDR }; + // find subcommand + int l_subcmd = CMD_NONE; + const char *l_addr_base58_str = NULL; + const char *l_wallet_name = NULL; + if(dap_chain_node_cli_find_option_val(a_argv, 2, a_argc, "-all", NULL)) + l_subcmd = SUBCMD_TX_ALL; + else if(dap_chain_node_cli_find_option_val(a_argv, 2, a_argc, "-addr", &l_addr_base58_str)) + l_subcmd = SUBCMD_TX_ADDR; + else if(dap_chain_node_cli_find_option_val(a_argv, 2, a_argc, "-wallet", &l_wallet_name)) + l_subcmd = SUBCMD_TX_ADDR; + + const char *l_token_name_str = NULL; + const char *l_page_start_str = NULL; + const char *l_page_size_str = NULL; + const char *l_page_str = NULL; + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-name", &l_token_name_str); + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-page_start", &l_page_start_str); + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-page_size", &l_page_size_str); + dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-page", &l_page_str); + if(!l_token_name_str) { + dap_chain_node_cli_set_reply_text(a_str_reply, "command requires parameter '-name' <token name>"); + return -4; + } + long l_page_start = -1;// not used if =-1 + long l_page_size = 10; + long l_page = 2; + long l_cur_datum = 0; + if(l_page_start_str) + l_page_start = strtol(l_page_start_str, NULL, 10); + if(l_page_size_str) { + l_page_size = strtol(l_page_size_str, NULL, 10); + if(l_page_size < 1) + l_page_size = 1; + } + if(l_page_str) { + l_page = strtol(l_page_str, NULL, 10); + if(l_page < 1) + l_page = 1; + } + + + // tx all + if(l_subcmd == SUBCMD_TX_ALL) { + dap_string_t *l_str_out = dap_string_new(NULL); + // get first chain + void *l_chain_tmp = (void*) 0x1; + dap_chain_t *l_chain_cur = dap_chain_enum(&l_chain_tmp); + while(l_chain_cur) { + // only selected net + if(l_net->pub.id.uint64 == l_chain_cur->net_id.uint64) { + long l_chain_datum = l_cur_datum; + char *l_datum_list_str = dap_db_history_filter(l_chain_cur, l_token_name_str, NULL, + l_hash_out_type, l_page_start * l_page_size, (l_page_start+l_page)*l_page_size, &l_chain_datum); + if(l_datum_list_str) { + l_cur_datum += l_chain_datum; + dap_string_append_printf(l_str_out, "Chain: %s\n", l_chain_cur->name); + dap_string_append_printf(l_str_out, "%s\n\n", l_datum_list_str); + DAP_DELETE(l_datum_list_str); + } + } + // next chain + dap_chain_enum_unlock(); + l_chain_cur = dap_chain_enum(&l_chain_tmp); + } + dap_chain_enum_unlock(); + dap_chain_node_cli_set_reply_text(a_str_reply, l_str_out->str); + dap_string_free(l_str_out, true); + return 0; + } + // tx -addr or tx -wallet + else if(l_subcmd == SUBCMD_TX_ADDR) { + // parse addr from -addr <addr> or -wallet <wallet> + dap_chain_addr_t *l_addr_base58 = NULL; + if(l_addr_base58_str) { + //l_addr_base58 = dap_strdup(l_addr_base58_str); + l_addr_base58 = dap_chain_addr_from_str(l_addr_base58_str); + } + else if(l_wallet_name) { + const char *c_wallets_path = dap_chain_wallet_get_path(g_config); + dap_chain_wallet_t * l_wallet = dap_chain_wallet_open(l_wallet_name, c_wallets_path); + if(l_wallet) { + dap_chain_addr_t *l_addr_tmp = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet, + l_net->pub.id); + l_addr_base58 = DAP_NEW_SIZE(dap_chain_addr_t, sizeof(dap_chain_addr_t)); + memcpy(l_addr_base58, l_addr_tmp, sizeof(dap_chain_addr_t)); + dap_chain_wallet_close(l_wallet); + char *ffl_addr_base58 = dap_chain_addr_to_str(l_addr_base58); + ffl_addr_base58 = 0; + } + else { + dap_chain_node_cli_set_reply_text(a_str_reply, "wallet '%s' not found", l_wallet_name); + return -2; + } + } + if(!l_addr_base58) { + dap_chain_node_cli_set_reply_text(a_str_reply, "address not recognized"); + return -3; + } + + dap_string_t *l_str_out = dap_string_new(NULL); + // get first chain + void *l_chain_tmp = (void*) 0x1; + dap_chain_t *l_chain_cur = dap_chain_enum(&l_chain_tmp); + while(l_chain_cur) { + // only selected net + if(l_net->pub.id.uint64 == l_chain_cur->net_id.uint64) { + long l_chain_datum = l_cur_datum; + char *l_datum_list_str = dap_db_history_addr(l_addr_base58, l_chain_cur, l_hash_out_type); + if(l_datum_list_str) { + l_cur_datum += l_chain_datum; + dap_string_append_printf(l_str_out, "Chain: %s\n", l_chain_cur->name); + dap_string_append_printf(l_str_out, "%s\n\n", l_datum_list_str); + DAP_DELETE(l_datum_list_str); + } + } + // next chain + dap_chain_enum_unlock(); + l_chain_cur = dap_chain_enum(&l_chain_tmp); + } + dap_chain_enum_unlock(); + dap_chain_node_cli_set_reply_text(a_str_reply, l_str_out->str); + dap_string_free(l_str_out, true); + DAP_DELETE(l_addr_base58); + return 0; + + } + else{ + dap_chain_node_cli_set_reply_text(a_str_reply, "not found parameter '-all', '-wallet' or '-addr'"); + return -1; + } + return 0; + } + + dap_chain_node_cli_set_reply_text(a_str_reply, "unknown command code %d", l_cmd); + return -5; +} + + diff --git a/modules/net/include/dap_chain_node_cli_cmd_tx.h b/modules/net/include/dap_chain_node_cli_cmd_tx.h index 64fb1fbc0c12fe905efac4c8185075945b73a13d..a7a1a4a317cd9bd34e74e437e3d28771e03c0499 100644 --- a/modules/net/include/dap_chain_node_cli_cmd_tx.h +++ b/modules/net/include/dap_chain_node_cli_cmd_tx.h @@ -31,3 +31,16 @@ */ char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * a_chain, const char *a_hash_out_type); char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, const char *a_hash_out_type); + +/** + * ledger command + * + */ +int com_ledger(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply); + +/** + * token command + * + */ +int com_token(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply); +