diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index 0a2672e1bc1490a4461fbdd84b15e66d814100fc..ca07ba8f0eecc901e705c1a5a86d064fc1aa045e 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -4918,17 +4918,17 @@ uint64_t dap_ledger_count_from_to(dap_ledger_t * a_ledger, dap_time_t a_ts_from, pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock); if ( a_ts_from && a_ts_to) { HASH_ITER(hh, l_ledger_pvt->ledger_items , l_iter_current, l_item_tmp){ - if ( l_iter_current->cache_data.ts_created >= a_ts_from && l_iter_current->cache_data.ts_created <= a_ts_to ) + if ( l_iter_current->tx->header.ts_created >= a_ts_from && l_iter_current->cache_data.ts_created <= a_ts_to ) l_ret++; } } else if ( a_ts_to ){ HASH_ITER(hh, l_ledger_pvt->ledger_items , l_iter_current, l_item_tmp){ - if ( l_iter_current->cache_data.ts_created <= a_ts_to ) + if ( l_iter_current->tx->header.ts_created <= a_ts_to ) l_ret++; } } else if ( a_ts_from ){ HASH_ITER(hh, l_ledger_pvt->ledger_items , l_iter_current, l_item_tmp){ - if ( l_iter_current->cache_data.ts_created >= a_ts_from ) + if ( l_iter_current->tx->header.ts_created >= a_ts_from ) l_ret++; } }else { diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index a94d103d59843f26f74775989e60fc39606a23c6..36f9f2d91381b7cb3cd945a40796966dbc5cf834 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -119,6 +119,7 @@ #include "dap_chain_node_net_ban_list.h" #include "dap_chain_cs_esbocs.h" #include "dap_chain_net_voting.h" +#include "dap_stream_cluster.h" #include <stdio.h> #include <sys/types.h> @@ -296,7 +297,7 @@ int dap_chain_net_init() "\tDelete certificate from list of authority cetificates in GDB group by it's hash\n" "net -net <chain net name> ledger reload\n" "\tPurge the cache of chain net ledger and recalculate it from chain file\n" - "net -net <chain net name> poa_cets list\n" + "net -net <chain net name> poa_certs list\n" "\tPrint list of PoA cerificates for this network\n"); s_debug_more = dap_config_get_item_bool_default(g_config,"chain_net","debug_more",false); @@ -1343,6 +1344,56 @@ dap_string_t* dap_cli_list_net() return l_string_ret; } +json_object* s_set_reply_text_node_status_json(dap_chain_net_t *a_net) { + json_object *l_jobj_ret = json_object_new_object(); + json_object *l_jobj_net_name = json_object_new_string(a_net->pub.name); + if (!l_jobj_ret || !l_jobj_net_name) { + json_object_put(l_jobj_ret); + json_object_put(l_jobj_net_name); + dap_json_rpc_allocation_error; + return NULL; + } + json_object_object_add(l_jobj_ret, "net", l_jobj_net_name); + dap_chain_node_addr_t l_cur_node_addr = { 0 }; + l_cur_node_addr.uint64 = dap_chain_net_get_cur_addr_int(a_net); + json_object *l_jobj_cur_node_addr; + if(!l_cur_node_addr.uint64) { + l_jobj_cur_node_addr = json_object_new_string("not defined"); + } else { + char *l_cur_node_addr_str = dap_strdup_printf(NODE_ADDR_FP_STR,NODE_ADDR_FP_ARGS_S(l_cur_node_addr)); + l_jobj_cur_node_addr = json_object_new_string(l_cur_node_addr_str); + DAP_DELETE(l_cur_node_addr_str); + } + if (!l_jobj_cur_node_addr) { + json_object_put(l_jobj_ret); + return NULL; + } + json_object_object_add(l_jobj_ret, "current_addr", l_jobj_cur_node_addr); + if (PVT(a_net)->state != NET_STATE_OFFLINE) { + json_object *l_jobj_links = json_object_new_object(); + json_object *l_jobj_active_links = json_object_new_uint64(s_net_get_active_links_count(a_net)); + json_object *l_jobj_total_links = json_object_new_uint64(HASH_COUNT(PVT(a_net)->net_links)); + if (!l_jobj_links || !l_jobj_active_links || !l_jobj_total_links) { + json_object_put(l_jobj_ret); + json_object_put(l_jobj_links); + json_object_put(l_jobj_active_links); + json_object_put(l_jobj_total_links); + dap_json_rpc_allocation_error; + return NULL; + } + json_object_object_add(l_jobj_links, "active", l_jobj_active_links); + json_object_object_add(l_jobj_links, "total", l_jobj_total_links); + json_object_object_add(l_jobj_ret, "links", l_jobj_links); + } + json_object *l_jobj_states = json_object_new_object(); + json_object *l_jobj_current_states = json_object_new_string(c_net_states[PVT(a_net)->state]); + json_object *l_jobj_target_states = json_object_new_string(c_net_states[PVT(a_net)->state_target]); + json_object_object_add(l_jobj_states, "current", l_jobj_current_states); + json_object_object_add(l_jobj_states, "target", l_jobj_target_states); + json_object_object_add(l_jobj_ret, "states", l_jobj_states); + return l_jobj_ret; +} + void s_set_reply_text_node_status(void **a_str_reply, dap_chain_net_t * a_net){ char* l_node_address_text_block = NULL; dap_chain_node_addr_t l_cur_node_addr = { 0 }; @@ -1492,8 +1543,13 @@ static const char *s_chain_type_convert_to_string(dap_chain_type_t a_type) * @param str_reply * @return */ -static int s_cli_net(int argc, char **argv, void **a_str_reply) +static int s_cli_net(int argc, char **argv, void **reply) { + json_object *l_jobj_return = json_object_new_object(); + if (!l_jobj_return) { + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } int arg_index = 1; dap_chain_net_t * l_net = NULL; @@ -1502,85 +1558,150 @@ static int s_cli_net(int argc, char **argv, void **a_str_reply) if(!l_hash_out_type) l_hash_out_type = "hex"; if(dap_strcmp(l_hash_out_type,"hex") && dap_strcmp(l_hash_out_type,"base58")) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "invalid parameter -H, valid values: -H <hex | base58>"); - return -1; + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_INVALID_PARAMETER_HASH, "invalid parameter -H, valid values: -H <hex | base58>"); + return DAP_CHAIN_NET_JSON_RPC_INVALID_PARAMETER_HASH; + } // command 'list' const char * l_list_cmd = NULL; if(dap_cli_server_cmd_find_option_val(argv, arg_index, dap_min(argc, arg_index + 1), "list", &l_list_cmd) != 0 ) { - dap_string_t *l_string_ret = dap_string_new(""); if (dap_strcmp(l_list_cmd,"chains")==0){ const char * l_net_str = NULL; dap_chain_net_t* l_net = NULL; if (dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-net", &l_net_str) && !l_net_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Parameter '-net' require <net name>"); - return -1; + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_CAN_NOT_PARAMETER_NET_REQUIRE, "Parameter '-net' require <net name>"); + return DAP_CHAIN_NET_JSON_RPC_CAN_NOT_PARAMETER_NET_REQUIRE; } l_net = dap_chain_net_by_name(l_net_str); if (l_net_str && !l_net) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Wrong <net name>, use 'net list' " - "command to display a list of available networks"); - return -1; + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_WRONG_NET, "Wrong <net name>, use 'net list' " + "command to display a list of available networks"); + return DAP_CHAIN_NET_JSON_RPC_WRONG_NET; } if (l_net){ - dap_string_append(l_string_ret,"Chains:\n"); + json_object *l_jobj_net_name = json_object_new_string(l_net->pub.name); + json_object *l_jobj_chains = json_object_new_array(); + if (!l_jobj_net_name || !l_jobj_chains) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_net_name); + json_object_put(l_jobj_chains); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } dap_chain_t * l_chain = l_net->pub.chains; while (l_chain) { - dap_string_append_printf(l_string_ret, "\t%s:\n", l_chain->name ); + json_object *l_jobj_chain_name = json_object_new_string(l_chain->name); + if (!l_jobj_chain_name) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_net_name); + json_object_put(l_jobj_chains); + json_object_put(l_jobj_chain_name); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_array_add(l_jobj_chains, l_jobj_chain_name); l_chain = l_chain->next; } + json_object_object_add(l_jobj_return, "net", l_jobj_net_name); + json_object_object_add(l_jobj_return, "chains", l_jobj_chains); }else{ dap_chain_net_item_t * l_net_item, *l_net_item_tmp; - int l_net_i = 0; - dap_string_append(l_string_ret,"Networks:\n"); + json_object *l_jobj_networks = json_object_new_array(); HASH_ITER(hh, s_net_items, l_net_item, l_net_item_tmp){ + json_object *l_jobj_network = json_object_new_object(); + json_object *l_jobj_chains = json_object_new_array(); l_net = l_net_item->chain_net; - dap_string_append_printf(l_string_ret, "\t%s:\n", l_net_item->name); - l_net_i++; + json_object *l_jobj_network_name = json_object_new_string(l_net_item->name); + if (!l_jobj_network || !l_jobj_chains || !l_jobj_network_name) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_network); + json_object_put(l_jobj_chains); + json_object_put(l_jobj_network_name); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_network, "name", l_jobj_network_name); dap_chain_t * l_chain = l_net->pub.chains; while (l_chain) { - dap_string_append_printf(l_string_ret, "\t\t%s:\n", l_chain->name ); - if (l_chain->default_datum_types_count) - { - dap_string_append_printf(l_string_ret, "\t\t"); - for (uint16_t i = 0; i < l_chain->default_datum_types_count; i++) - dap_string_append_printf(l_string_ret, "| %s ", s_chain_type_convert_to_string(l_chain->default_datum_types[i]) ); - dap_string_append_printf(l_string_ret, "|\n"); + json_object *l_jobj_chain = json_object_new_object(); + json_object *l_jobj_chain_name = json_object_new_string(l_chain->name); + if (!l_jobj_chain || !l_jobj_chain_name) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_network); + json_object_put(l_jobj_chains); + json_object_put(l_jobj_chain); + json_object_put(l_jobj_chain_name); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_chain, "name", l_jobj_chain_name); + if (l_chain->default_datum_types_count) { + json_object *l_jobj_default_types = json_object_new_array(); + if (!l_jobj_default_types) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_chain); + json_object_put(l_jobj_chains); + json_object_put(l_jobj_network); + json_object_put(l_jobj_networks); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + for (uint16_t i = 0; i < l_chain->default_datum_types_count; i++) { + json_object *l_jobj_type_str = json_object_new_string(s_chain_type_convert_to_string( + l_chain->default_datum_types[i])); + if (!l_jobj_type_str) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_default_types); + json_object_put(l_jobj_chain); + json_object_put(l_jobj_chains); + json_object_put(l_jobj_network); + json_object_put(l_jobj_networks); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_array_add(l_jobj_default_types, l_jobj_type_str); + } + json_object_object_add(l_jobj_chain, "default_types", l_jobj_default_types); } + json_object_array_add(l_jobj_chains, l_jobj_chain); l_chain = l_chain->next; } + json_object_object_add(l_jobj_network, "chain", l_jobj_chains); + json_object_array_add(l_jobj_networks, l_jobj_network); } + json_object_object_add(l_jobj_return, "networks", l_jobj_networks); } - }else{ // plug for wrong command arguments if (argc > 2) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "To many arguments for 'net list' command see help"); - return -1; + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_MANY_ARGUMENT_FOR_COMMAND_NET_LIST, + "To many arguments for 'net list' command see help"); + return DAP_CHAIN_NET_JSON_RPC_MANY_ARGUMENT_FOR_COMMAND_NET_LIST; } - dap_string_append(l_string_ret,"Networks:\n"); + json_object *l_jobj_networks = json_object_new_array(); // show list of nets dap_chain_net_item_t * l_net_item, *l_net_item_tmp; - int l_net_i = 0; HASH_ITER(hh, s_net_items, l_net_item, l_net_item_tmp){ - dap_string_append_printf(l_string_ret, "\t%s\n", l_net_item->name); - l_net_i++; + json_object *l_jobj_network_name = json_object_new_string(l_net_item->name); + json_object_array_add(l_jobj_networks, l_jobj_network_name); } - dap_string_append(l_string_ret, "\n"); + json_object_object_add(l_jobj_return, "networks", l_jobj_networks); } - - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_string_ret->str); - dap_string_free(l_string_ret, true); + json_object_array_add(*reply, l_jobj_return); return 0; } - int l_ret = dap_chain_node_cli_cmd_values_parse_net_chain( &arg_index, argc, argv, a_str_reply, NULL, &l_net ); + int l_ret = dap_chain_node_cli_cmd_values_parse_net_chain_for_json(&arg_index, argc, argv, NULL, &l_net); if ( l_net ) { const char *l_sync_str = NULL; @@ -1611,11 +1732,11 @@ static int s_cli_net(int argc, char **argv, void **a_str_reply) if (strcmp(l_stats_str,"tx") == 0) { const char *l_to_str = NULL; const char *l_from_str = NULL; - const char *l_prev_sec_str = NULL; + const char *l_prev_day_str = NULL; // Read from/to time dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-from", &l_from_str); dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-to", &l_to_str); - dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-prev_sec", &l_prev_sec_str); + dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-prev_day", &l_prev_day_str); time_t l_ts_now = time(NULL); if (l_from_str) { strptime( (char *)l_from_str, c_time_fmt, &l_from_tm ); @@ -1624,11 +1745,14 @@ static int s_cli_net(int argc, char **argv, void **a_str_reply) } else { // If not set '-to' - we set up current time localtime_r(&l_ts_now, &l_to_tm); } - } else if (l_prev_sec_str) { - l_ts_now -= strtol( l_prev_sec_str, NULL,10 ); + } else if (l_prev_day_str) { + localtime_r(&l_ts_now, &l_to_tm); + double l_days = strtod(l_prev_day_str, NULL); + l_ts_now -= (time_t)(l_days * 86400); localtime_r(&l_ts_now, &l_from_tm ); } else if ( l_from_str == NULL ) { // If not set '-from' we set up current time minus 60 seconds - l_ts_now -= 60; + localtime_r(&l_ts_now, &l_to_tm); + l_ts_now -= 86400; localtime_r(&l_ts_now, &l_from_tm ); } // Form timestamps from/to @@ -1639,69 +1763,180 @@ static int s_cli_net(int argc, char **argv, void **a_str_reply) char l_to_str_new[50]; strftime(l_from_str_new, sizeof(l_from_str_new), c_time_fmt,&l_from_tm ); strftime(l_to_str_new, sizeof(l_to_str_new), c_time_fmt,&l_to_tm ); - dap_string_t * l_ret_str = dap_string_new("Transactions statistics:\n"); - dap_string_append_printf( l_ret_str, "\tFrom: %s\tTo: %s\n", l_from_str_new, l_to_str_new); + json_object *l_jobj_stats = json_object_new_object(); + if (!l_jobj_stats) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + if (l_from_str) { + json_object *l_jobj_from = json_object_new_string(l_from_str); + if (!l_jobj_from) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_stats); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_stats, "from", l_jobj_from); + } + if (l_to_str) { + json_object *l_jobj_to = json_object_new_string(l_to_str); + if (!l_jobj_to) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_stats); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_stats, "to", l_jobj_to); + } log_it(L_INFO, "Calc TPS from %s to %s", l_from_str_new, l_to_str_new); uint64_t l_tx_count = dap_ledger_count_from_to ( l_net->pub.ledger, l_from_ts, l_to_ts); - long double l_tps = l_to_ts == l_from_ts ? 0 : - (long double) l_tx_count / (long double) ( l_to_ts - l_from_ts ); - dap_string_append_printf( l_ret_str, "\tSpeed: %.3Lf TPS\n", l_tps ); - dap_string_append_printf( l_ret_str, "\tTotal: %"DAP_UINT64_FORMAT_U"\n", l_tx_count ); - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_ret_str->str); - dap_string_free(l_ret_str, true); - } else if (strcmp(l_stats_str, "tps") == 0) { + long double l_tpd = l_to_ts == l_from_ts ? 0 : + (long double) l_tx_count / (long double) ((long double)(l_to_ts - l_from_ts) / 86400); + char *l_tpd_str = dap_strdup_printf("%.3Lf", l_tpd); + json_object *l_jobj_tpd = json_object_new_string(l_tpd_str); + DAP_DELETE(l_tpd_str); + json_object *l_jobj_total = json_object_new_uint64(l_tx_count); + if (!l_jobj_tpd || !l_jobj_total) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_stats); + json_object_put(l_jobj_tpd); + json_object_put(l_jobj_total); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_stats, "transaction_per_day", l_jobj_tpd); + json_object_object_add(l_jobj_stats, "total", l_jobj_total); + json_object_object_add(l_jobj_return, "transaction_statistics", l_jobj_stats); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; + } +#ifdef DAP_TPS_TEST + else if (strcmp(l_stats_str, "tps") == 0) { struct timespec l_from_time_acc = {}, l_to_time_acc = {}; - dap_string_t * l_ret_str = dap_string_new("Transactions per second peak values:\n"); + json_object *l_jobj_values = json_object_new_object(); + if (!l_jobj_values) { + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } size_t l_tx_num = dap_ledger_count_tps(l_net->pub.ledger, &l_from_time_acc, &l_to_time_acc); if (l_tx_num) { localtime_r(&l_from_time_acc.tv_sec, &l_from_tm); strftime(l_from_str_new, sizeof(l_from_str_new), c_time_fmt, &l_from_tm); localtime_r(&l_to_time_acc.tv_sec, &l_to_tm); strftime(l_to_str_new, sizeof(l_to_str_new), c_time_fmt, &l_to_tm); - dap_string_append_printf(l_ret_str, "\tFrom: %s\tTo: %s\n", l_from_str_new, l_to_str_new); + json_object *l_jobj_from = json_object_new_string(l_from_str_new); + json_object *l_jobj_to = json_object_new_string(l_to_str_new); uint64_t l_diff_ns = (l_to_time_acc.tv_sec - l_from_time_acc.tv_sec) * 1000000000 + l_to_time_acc.tv_nsec - l_from_time_acc.tv_nsec; long double l_tps = (long double)(l_tx_num * 1000000000) / (long double)(l_diff_ns); - dap_string_append_printf(l_ret_str, "\tSpeed: %.3Lf TPS\n", l_tps); + char *l_tps_str = dap_strdup_printf("%.3Lf", l_tps); + json_object *l_jobj_tps = json_object_new_string(l_tps_str); + DAP_DELETE(l_tps_str); + if (!l_jobj_from || !l_jobj_to || !l_jobj_tps) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_values); + json_object_put(l_jobj_from); + json_object_put(l_jobj_to); + json_object_put(l_jobj_tps); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_values, "from", l_jobj_from); + json_object_object_add(l_jobj_values, "to", l_jobj_to); + json_object_object_add(l_jobj_values, "tps", l_jobj_tps); } - dap_string_append_printf(l_ret_str, "\tTotal: %zu\n", l_tx_num); - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_ret_str->str); - dap_string_free(l_ret_str, true); - } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Subcommand 'stats' requires one of parameter: tx, tps\n"); + json_object *l_jobj_total = json_object_new_uint64(l_tx_num); + if (!l_jobj_total) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_values); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_values, "total", l_jobj_total); + json_object_object_add(l_jobj_return, "transactions_per_second_peak", l_jobj_values); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; + } +#endif + else { + json_object_put(l_jobj_return); +#ifdef DAP_TPS_TEST + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_STATS, "Subcommand 'stats' requires one of parameter: tx, tps"); +#else + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_STATS, "Subcommand 'stats' requires one of parameter: tx"); +#endif + l_ret = DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_STATS; } } else if ( l_go_str){ + json_object *l_jobj_net = json_object_new_string(l_net->pub.name); + json_object *l_jobj_current_status = json_object_new_string(c_net_states[PVT(l_net)->state]); + if (!l_jobj_net || !l_jobj_current_status) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_net); + json_object_put(l_jobj_current_status); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "net", l_jobj_net); + json_object_object_add(l_jobj_return, "current", l_jobj_current_status); if ( strcmp(l_go_str,"online") == 0 ) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network \"%s\" going from state %s to %s", - l_net->pub.name,c_net_states[PVT(l_net)->state], - c_net_states[NET_STATE_ONLINE]); - + json_object *l_jobj_to = json_object_new_string(c_net_states[NET_STATE_ONLINE]); + if (!l_jobj_to) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "to", l_jobj_to); dap_chain_net_balancer_prepare_list_links(l_net->pub.name,true); dap_chain_net_state_go_to(l_net, NET_STATE_ONLINE); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if ( strcmp(l_go_str,"offline") == 0 ) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network \"%s\" going from state %s to %s", - l_net->pub.name,c_net_states[PVT(l_net)->state], - c_net_states[NET_STATE_OFFLINE]); + json_object *l_jobj_to = json_object_new_string(c_net_states[NET_STATE_OFFLINE]); + if (!l_jobj_to) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "to", l_jobj_to); dap_chain_net_state_go_to(l_net, NET_STATE_OFFLINE); - + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if (strcmp(l_go_str, "sync") == 0) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Network \"%s\" resynchronizing", - l_net->pub.name); + json_object *l_jobj_to = json_object_new_string("resynchronizing"); + if (!l_jobj_to) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "start", l_jobj_to); if (PVT(l_net)->state_target == NET_STATE_ONLINE) dap_chain_net_state_go_to(l_net, NET_STATE_ONLINE); else dap_chain_net_state_go_to(l_net, NET_STATE_SYNC_CHAINS); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Subcommand 'go' requires one of parameters: online, offline, sync\n"); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_GO, + "Subcommand 'go' requires one of parameters: online, offline, sync\n"); + l_ret = DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_GO; } } else if ( l_get_str){ if ( strcmp(l_get_str,"status") == 0 ) { - s_set_reply_text_node_status(a_str_reply, l_net); - l_ret = 0; + json_object *l_jobj = s_set_reply_text_node_status_json(l_net); + if (!l_jobj) { + json_object_put(l_jobj_return); + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "status", l_jobj); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if ( strcmp(l_get_str, "fee") == 0) { - dap_string_t *l_str = dap_string_new("\0"); + json_object *l_jobj_fees = json_object_new_object(); + json_object *l_jobj_network_name = json_object_new_string(l_net->pub.name); + if (!l_jobj_fees || !l_jobj_network_name) { + json_object_put(l_jobj_return); + json_object_put(l_jobj_fees); + json_object_put(l_jobj_network_name); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_fees, "network", l_jobj_network_name); // Network fee uint256_t l_network_fee = {}; dap_chain_addr_t l_network_fee_addr = {}; @@ -1709,106 +1944,168 @@ static int s_cli_net(int argc, char **argv, void **a_str_reply) char *l_network_fee_balance_str = dap_chain_balance_print(l_network_fee); char *l_network_fee_coins_str = dap_chain_balance_to_coins(l_network_fee); char *l_network_fee_addr_str = dap_chain_addr_to_str(&l_network_fee_addr); - dap_string_append_printf(l_str, "Fees on %s network:\n" - "\t Network: %s (%s) %s Addr: %s\n", - l_net->pub.name, l_network_fee_coins_str, l_network_fee_balance_str, - l_net->pub.native_ticker, l_network_fee_addr_str); + json_object *l_jobj_network = json_object_new_object(); + json_object *l_jobj_fee_coins = json_object_new_string(l_network_fee_coins_str); + json_object *l_jobj_fee_balance = json_object_new_string(l_network_fee_balance_str); + json_object *l_jobj_native_ticker = json_object_new_string(l_net->pub.native_ticker); + json_object *l_jobj_fee_addr = json_object_new_string(l_network_fee_addr_str); + if (!l_jobj_network || !l_jobj_fee_coins || !l_jobj_fee_balance || !l_jobj_native_ticker || !l_jobj_fee_addr) { + json_object_put(l_jobj_fees); + json_object_put(l_jobj_network); + json_object_put(l_jobj_fee_coins); + json_object_put(l_jobj_fee_balance); + json_object_put(l_jobj_native_ticker); + json_object_put(l_jobj_fee_addr); + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_network, "coins", l_jobj_fee_coins); + json_object_object_add(l_jobj_network, "balance", l_jobj_fee_balance); + json_object_object_add(l_jobj_network, "ticker", l_jobj_native_ticker); + json_object_object_add(l_jobj_network, "addr", l_jobj_fee_addr); + json_object_object_add(l_jobj_fees, "network", l_jobj_network); DAP_DELETE(l_network_fee_coins_str); DAP_DELETE(l_network_fee_balance_str); DAP_DELETE(l_network_fee_addr_str); - //Get validators fee - dap_chain_net_srv_stake_get_fee_validators_str(l_net, l_str); + json_object *l_jobj_validators = dap_chain_net_srv_stake_get_fee_validators_json(l_net); + if (!l_jobj_validators) { + json_object_put(l_jobj_fees); + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } //Get services fee - dap_string_append_printf(l_str, "Services fee: \n"); - dap_chain_net_srv_xchange_print_fee(l_net, l_str); //Xchaneg fee - - *a_str_reply = dap_string_free(l_str, false); - l_ret = 0; + json_object *l_jobj_xchange = dap_chain_net_srv_xchange_print_fee_json(l_net); //Xchaneg fee + if (!l_jobj_xchange) { + json_object_put(l_jobj_validators); + json_object_put(l_jobj_fees); + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_fees, "validators", l_jobj_validators); + json_object_object_add(l_jobj_fees, "xchange", l_jobj_xchange); + json_object_object_add(l_jobj_return, "fees", l_jobj_fees); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if (strcmp(l_get_str,"id") == 0 ){ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Net %s has id 0x%016"DAP_UINT64_FORMAT_X, - l_net->pub.name, l_net->pub.id.uint64); - l_ret = 0; + json_object *l_jobj_net_name = json_object_new_string(l_net->pub.name); + char *l_id_str = dap_strdup_printf("0x%016"DAP_UINT64_FORMAT_X, l_net->pub.id.uint64); + json_object *l_jobj_id = json_object_new_string(l_id_str); + DAP_DELETE(l_id_str); + if (!l_jobj_net_name || !l_jobj_id) { + json_object_put(l_jobj_net_name); + json_object_put(l_jobj_id); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "network", l_jobj_net_name); + json_object_object_add(l_jobj_return, "id", l_jobj_id); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } } else if ( l_links_str ){ if ( strcmp(l_links_str,"list") == 0 ) { - size_t i =0; - dap_chain_net_pvt_t * l_net_pvt = PVT(l_net); - pthread_mutex_lock(&l_net_pvt->uplinks_mutex); - size_t l_links_count = HASH_COUNT(l_net_pvt->net_links); - dap_string_t *l_reply = dap_string_new(""); - dap_string_append_printf(l_reply,"Links %zu:\n", l_links_count); - struct net_link *l_link, *l_link_tmp; - HASH_ITER(hh, l_net_pvt->net_links, l_link, l_link_tmp) { - dap_chain_node_client_t *l_node_client = l_link->link; - if(l_node_client){ - dap_chain_node_info_t * l_info = l_node_client->info; - char l_ext_addr_v4[INET_ADDRSTRLEN]={}; - char l_ext_addr_v6[INET6_ADDRSTRLEN]={}; - inet_ntop(AF_INET,&l_info->hdr.ext_addr_v4,l_ext_addr_v4,sizeof (l_info->hdr.ext_addr_v4)); - inet_ntop(AF_INET6,&l_info->hdr.ext_addr_v6,l_ext_addr_v6,sizeof (l_info->hdr.ext_addr_v6)); - - dap_string_append_printf(l_reply, - "\t"NODE_ADDR_FP_STR":\n" - "\t\talias: %s\n" - "\t\tcell_id: 0x%016"DAP_UINT64_FORMAT_X"\n" - "\t\text_ipv4: %s\n" - "\t\text_ipv6: %s\n" - "\t\text_port: %u\n" - "\t\tstate: %s\n", - NODE_ADDR_FP_ARGS_S(l_info->hdr.address), l_info->alias, l_info->hdr.cell_id.uint64, - l_ext_addr_v4, l_ext_addr_v6, l_info->hdr.ext_port, - dap_chain_node_client_state_to_str(l_node_client->state) ); - } - i++; + dap_cluster_t *l_net_cluster = dap_cluster_by_mnemonim(l_net->pub.name); + if (!l_net_cluster) { + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_CAN_NOT_GET_CLUSTER, "Failed to obtain a cluster for " + "the specified network."); + return DAP_CHAIN_NET_JSON_RPC_CAN_NOT_GET_CLUSTER; } - pthread_mutex_unlock(&l_net_pvt->uplinks_mutex); - dap_cli_server_cmd_set_reply_text(a_str_reply,"%s",l_reply->str); - dap_string_free(l_reply,true); - + json_object *l_jobj_links = dap_cluster_get_links_info_json(l_net_cluster); + if (!l_jobj_links) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "links", l_jobj_links); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if ( strcmp(l_links_str,"add") == 0 ) { - dap_cli_server_cmd_set_reply_text(a_str_reply,"Not implemented\n"); + json_object *l_jobj_not_implemented = json_object_new_string("Not implemented"); + if (!l_jobj_not_implemented) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "add", l_jobj_not_implemented); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if ( strcmp(l_links_str,"del") == 0 ) { - dap_cli_server_cmd_set_reply_text(a_str_reply,"Not implemented\n"); - + json_object *l_jobj_not_implemented = json_object_new_string("Not implemented"); + if (!l_jobj_not_implemented) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "del", l_jobj_not_implemented); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if ( strcmp(l_links_str,"info") == 0 ) { - dap_cli_server_cmd_set_reply_text(a_str_reply,"Not implemented\n"); - + json_object *l_jobj_not_implemented = json_object_new_string("Not implemented"); + if (!l_jobj_not_implemented) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "info", l_jobj_not_implemented); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if ( strcmp (l_links_str,"disconnect_all") == 0 ){ - l_ret = 0; dap_chain_net_stop(l_net); - dap_cli_server_cmd_set_reply_text(a_str_reply,"Stopped network\n"); + json_object *l_jobj_ret = json_object_new_string("Stopped network"); + if (!l_jobj_ret) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "message", l_jobj_ret); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; }else { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Subcommand 'link' requires one of parameters: list, add, del, info, disconnect_all\n"); - l_ret = -3; + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_LINK, + "Subcommand 'link' requires one of parameters: list, add, del, info, disconnect_all"); + l_ret = DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_LINK; } } else if( l_sync_str) { + json_object *l_jobj_state_machine = json_object_new_object(); + json_object *l_jobj_requested; + json_object *l_jobj_current = json_object_new_string(c_net_states[PVT(l_net)->state]); + if (!l_jobj_state_machine || !l_jobj_current) { + json_object_put(l_jobj_state_machine); + json_object_put(l_jobj_current); + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } if ( strcmp(l_sync_str,"all") == 0 ) { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "SYNC_ALL state requested to state machine. Current state: %s\n", - c_net_states[ PVT(l_net)->state] ); + l_jobj_requested = json_object_new_string("SYNC_ALL"); dap_chain_net_sync_all(l_net); } else if ( strcmp(l_sync_str,"gdb") == 0) { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "SYNC_GDB state requested to state machine. Current state: %s\n", - c_net_states[ PVT(l_net)->state] ); + l_jobj_requested = json_object_new_string("SYNC_GDB"); dap_chain_net_sync_gdb(l_net); - } else if ( strcmp(l_sync_str,"chains") == 0) { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "SYNC_CHAINS state requested to state machine. Current state: %s\n", - c_net_states[ PVT(l_net)->state] ); + l_jobj_requested = json_object_new_string("SYNC_CHAINS"); // TODO set PVT flag to exclude GDB sync dap_chain_net_sync_chains(l_net); } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Subcommand 'sync' requires one of parameters: all, gdb, chains\n"); - l_ret = -2; + json_object_put(l_jobj_return); + json_object_put(l_jobj_state_machine); + json_object_put(l_jobj_current); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_SYNC, + "Subcommand 'sync' requires one of parameters: all, gdb, chains"); + l_ret = DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_SYNC; + } + if (!l_jobj_requested) { + json_object_put(l_jobj_state_machine); + json_object_put(l_jobj_current); + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; } + json_object_object_add(l_jobj_state_machine, "current", l_jobj_current); + json_object_object_add(l_jobj_state_machine, "requested", l_jobj_requested); + json_object_object_add(l_jobj_return, "state_machine", l_jobj_state_machine); + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if (l_ca_str) { if (strcmp(l_ca_str, "add") == 0 ) { const char *l_cert_string = NULL, *l_hash_string = NULL; @@ -1819,11 +2116,12 @@ static int s_cli_net(int argc, char **argv, void **a_str_reply) dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-hash", &l_hash_string); if (!l_cert_string && !l_hash_string) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "One of -cert or -hash parameters is mandatory"); - return -6; + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_CA_ADD, + "One of -cert or -hash parameters is mandatory"); + return DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_CA_ADD; } char *l_hash_hex_str = NULL; - //char *l_hash_base58_str; // hash may be in hex or base58 format if(!dap_strncmp(l_hash_string, "0x", 2) || !dap_strncmp(l_hash_string, "0X", 2)) { l_hash_hex_str = dap_strdup(l_hash_string); @@ -1837,22 +2135,28 @@ static int s_cli_net(int argc, char **argv, void **a_str_reply) if (l_cert_string) { dap_cert_t * l_cert = dap_cert_find_by_name(l_cert_string); if (l_cert == NULL) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find \"%s\" certificate", l_cert_string); - DAP_DEL_Z(l_hash_hex_str); - return -7; + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_CAN_NOT_FIND_CERT_CA_ADD, + "Can't find \"%s\" certificate", l_cert_string); + DAP_DELETE(l_hash_hex_str); + return DAP_CHAIN_NET_JSON_RPC_CAN_NOT_FIND_CERT_CA_ADD; } if (l_cert->enc_key == NULL) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "No key found in \"%s\" certificate", l_cert_string ); + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_CAN_NOT_KEY_IN_CERT_CA_ADD, + "No key found in \"%s\" certificate", l_cert_string); DAP_DEL_Z(l_hash_hex_str); - return -8; + return DAP_CHAIN_NET_JSON_RPC_CAN_NOT_KEY_IN_CERT_CA_ADD; } // Get publivc key hash size_t l_pub_key_size = 0; uint8_t *l_pub_key = dap_enc_key_serialize_pub_key(l_cert->enc_key, &l_pub_key_size);; if (l_pub_key == NULL) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't serialize public key of certificate \"%s\"", l_cert_string); + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_CAN_SERIALIZE_PUBLIC_KEY_CERT_CA_ADD, + "Can't serialize public key of certificate \"%s\"", l_cert_string); DAP_DEL_Z(l_hash_hex_str); - return -9; + return DAP_CHAIN_NET_JSON_RPC_CAN_SERIALIZE_PUBLIC_KEY_CERT_CA_ADD; } dap_chain_hash_fast_t l_pkey_hash; dap_hash_fast(l_pub_key, l_pub_key_size, &l_pkey_hash); @@ -1863,65 +2167,105 @@ static int s_cli_net(int argc, char **argv, void **a_str_reply) const char c = '1'; char *l_gdb_group_str = dap_chain_net_get_gdb_group_acl(l_net); if (!l_gdb_group_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Database ACL group not defined for this network"); - return -11; + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_ADD, + "Database ACL group not defined for this network"); + return DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_ADD; } if( l_hash_hex_str ){ l_ret = dap_global_db_set_sync(l_gdb_group_str, l_hash_hex_str, &c, sizeof(c), false ); DAP_DELETE(l_gdb_group_str); if (l_ret) { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Can't save public key hash %s in database", l_hash_hex_str); + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_CAN_NOT_SAVE_PUBLIC_KEY_IN_DATABASE, + "Can't save public key hash %s in database", l_hash_hex_str); DAP_DELETE(l_hash_hex_str); - return -10; + return DAP_CHAIN_NET_JSON_RPC_CAN_NOT_SAVE_PUBLIC_KEY_IN_DATABASE; } DAP_DELETE(l_hash_hex_str); } else{ - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't save NULL public key hash in database"); - return -10; + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_CAN_NOT_SAVE_PUBLIC_KEY_IN_DATABASE, + "Can't save NULL public key hash in database"); + return DAP_CHAIN_NET_JSON_RPC_CAN_NOT_SAVE_PUBLIC_KEY_IN_DATABASE; } - return 0; + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if (strcmp(l_ca_str, "list") == 0 ) { char *l_gdb_group_str = dap_chain_net_get_gdb_group_acl(l_net); if (!l_gdb_group_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Database ACL group not defined for this network"); - return -11; + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_LIST, + "Database ACL group not defined for this network"); + return DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_LIST; } size_t l_objs_count; dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_gdb_group_str, &l_objs_count); DAP_DELETE(l_gdb_group_str); - dap_string_t *l_reply = dap_string_new(""); + json_object *l_jobj_list_ca = json_object_new_array(); + if (!l_jobj_list_ca) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } for (size_t i = 0; i < l_objs_count; i++) { - dap_string_append(l_reply, l_objs[i].key); - dap_string_append(l_reply, "\n"); + json_object *l_jobj_key = json_object_new_string(l_objs[i].key); + if (!l_jobj_key) { + json_object_put(l_jobj_list_ca); + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } } dap_global_db_objs_delete(l_objs, l_objs_count); - *a_str_reply = l_reply->len ? l_reply->str : dap_strdup("No entries found"); - dap_string_free(l_reply, false); - return 0; + if (json_object_array_length(l_jobj_list_ca) > 0) { + json_object_object_add(l_jobj_return, "ca_list", l_jobj_list_ca); + } else { + json_object_put(l_jobj_list_ca); + json_object *l_jobj_str_ret = json_object_new_string("No entries found"); + if (!l_jobj_list_ca) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_return, "ca_list", l_jobj_str_ret); + } + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else if (strcmp(l_ca_str, "del") == 0 ) { const char *l_hash_string = NULL; dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-hash", &l_hash_string); if (!l_hash_string) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Format should be 'net ca del -hash <hash string>"); - return -6; + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNKNOWN_HASH_CA_DEL, + "Format should be 'net ca del -hash <hash string>"); + return DAP_CHAIN_NET_JSON_RPC_UNKNOWN_HASH_CA_DEL; } char *l_gdb_group_str = dap_chain_net_get_gdb_group_acl(l_net); if (!l_gdb_group_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Database ACL group not defined for this network"); - return -11; + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_DEL, + "Database ACL group not defined for this network"); + return DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_DEL; + } + char *l_ret_msg_str = dap_strdup_printf("Certificate %s has been deleted.", l_hash_string); + json_object *l_jobj_ret = json_object_new_string(l_ret_msg_str); + DAP_DELETE(l_ret_msg_str); + if (l_jobj_ret) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; } l_ret = dap_global_db_del_sync(l_gdb_group_str, l_hash_string); DAP_DELETE(l_gdb_group_str); if (l_ret) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Cant't find certificate public key hash in database"); - return -10; + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_CAN_NOT_FIND_CERT_CA_DEL, + "Can't find certificate public key hash in database"); + return DAP_CHAIN_NET_JSON_RPC_CAN_NOT_FIND_CERT_CA_DEL; } - return 0; + json_object_put(l_jobj_return); + json_object_array_add(*reply, l_jobj_ret); + return DAP_CHAIN_NET_JSON_RPC_OK; } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Subcommand 'ca' requires one of parameter: add, list, del\n"); - l_ret = -5; + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_INVALID_PARAMETER_COMMAND_CA, + "Subcommand 'ca' requires one of parameter: add, list, del"); + return DAP_CHAIN_NET_JSON_RPC_INVALID_PARAMETER_COMMAND_CA; } } else if (l_ledger_str && !strcmp(l_ledger_str, "reload")) { int l_return_state = dap_chain_net_stop(l_net); @@ -1931,27 +2275,52 @@ static int s_cli_net(int argc, char **argv, void **a_str_reply) dap_chain_net_start(l_net); } else if (l_list_str && !strcmp(l_list_str, "list")) { if (!l_net->pub.keys) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "No PoA certs found for this network"); - return -11; + json_object_put(l_jobj_return); + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_NO_POA_CERTS_FOUND_POA_CERTS, + "No PoA certs found for this network"); + return DAP_CHAIN_NET_JSON_RPC_NO_POA_CERTS_FOUND_POA_CERTS; + } + json_object *l_jobj_pkeys = json_object_new_array(); + if (!l_jobj_pkeys) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; } - dap_string_t *l_str_out = dap_string_new("List of network PoA certificates:\n"); - int i = 0; for (dap_list_t *it = l_net->pub.keys; it; it = it->next) { dap_hash_fast_t l_pkey_hash; char l_pkey_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; dap_pkey_get_hash(it->data, &l_pkey_hash); dap_chain_hash_fast_to_str(&l_pkey_hash, l_pkey_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE); - dap_string_append_printf(l_str_out, "%d) %s\n", i++, l_pkey_hash_str); + json_object *l_jobj_hash_key = json_object_new_string(l_pkey_hash_str); + if (!l_jobj_hash_key) { + json_object_put(l_jobj_pkeys); + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_array_add(l_jobj_pkeys, l_jobj_hash_key); } - *a_str_reply = l_str_out->str; - dap_string_free(l_str_out, false); - + if (json_object_array_length(l_jobj_pkeys) > 0) { + json_object_object_add(l_jobj_return, "poa_certs", l_jobj_pkeys); + } else { + json_object_put(l_jobj_pkeys); + json_object *l_jobj_info = json_object_new_string("empty"); + if (!l_jobj_info) { + json_object_put(l_jobj_return); + dap_json_rpc_allocation_error; + return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; + } + json_object_object_add(l_jobj_pkeys, "poa_certs", l_jobj_info); + } + l_ret = DAP_CHAIN_NET_JSON_RPC_OK; } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, - "Command 'net' requires one of subcomands: sync, link, go, get, stats, ca, ledger"); - l_ret = -1; + dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_UNKNOWN_SUBCOMMANDS, + "Command 'net' requires one of subcomands: sync, link, go, get, stats, ca, ledger"); + l_ret = DAP_CHAIN_NET_JSON_RPC_UNKNOWN_SUBCOMMANDS; } - + } + if (l_jobj_return) { + json_object_array_add(*reply, l_jobj_return); } return l_ret; } diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index 719c635e49ed4bd79a448e4f4bc7ee5721f9ef2b..71abb1e26f0e5d934aecf3f955375b0868b3b584 100644 --- a/modules/net/include/dap_chain_net.h +++ b/modules/net/include/dap_chain_net.h @@ -43,6 +43,7 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic #include "dap_chain_datum_anchor.h" #include "dap_chain_datum_tx.h" #include "uthash.h" +#include "dap_json_rpc.h" #define DAP_CHAIN_NET_NAME_MAX 32 #define DAP_CHAIN_NET_MEMPOOL_TTL 48 // Hours @@ -212,3 +213,31 @@ int dap_chain_datum_add(dap_chain_t * a_chain, dap_chain_datum_t *a_datum, size_ bool dap_chain_net_get_load_mode(dap_chain_net_t * a_net); void dap_chain_net_announce_addrs(); char *dap_chain_net_links_dump(dap_chain_net_t*); + +enum dap_chain_net_json_rpc_error_list{ + DAP_CHAIN_NET_JSON_RPC_OK, + DAP_CHAIN_NET_JSON_RPC_INVALID_PARAMETER_HASH = DAP_JSON_RPC_ERR_CODE_METHOD_ERR_START, + DAP_CHAIN_NET_JSON_RPC_CAN_NOT_PARAMETER_NET_REQUIRE, + DAP_CHAIN_NET_JSON_RPC_WRONG_NET, + DAP_CHAIN_NET_JSON_RPC_MANY_ARGUMENT_FOR_COMMAND_NET_LIST, + DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_STATS, + DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_COMMAND_GO, + DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETER_ADDR_COMMAND_INFO, + DAP_CHAIN_NET_JSON_RPC_CANT_CALCULATE_HASH_FOR_ADDR, + DAP_CHAIN_NET_JSON_RPC_CAN_NOT_GET_CLUSTER, + DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_LINK, + DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_COMMAND_SYNC, + DAP_CHAIN_NET_JSON_RPC_UNDEFINED_PARAMETERS_CA_ADD, + DAP_CHAIN_NET_JSON_RPC_CAN_NOT_FIND_CERT_CA_ADD, + DAP_CHAIN_NET_JSON_RPC_CAN_NOT_KEY_IN_CERT_CA_ADD, + DAP_CHAIN_NET_JSON_RPC_CAN_SERIALIZE_PUBLIC_KEY_CERT_CA_ADD, + DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_ADD, + DAP_CHAIN_NET_JSON_RPC_CAN_NOT_SAVE_PUBLIC_KEY_IN_DATABASE, + DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_LIST, + DAP_CHAIN_NET_JSON_RPC_UNKNOWN_HASH_CA_DEL, + DAP_CHAIN_NET_JSON_RPC_DATABASE_ACL_GROUP_NOT_DEFINED_FOR_THIS_NETWORK_CA_DEL, + DAP_CHAIN_NET_JSON_RPC_CAN_NOT_FIND_CERT_CA_DEL, + DAP_CHAIN_NET_JSON_RPC_INVALID_PARAMETER_COMMAND_CA, + DAP_CHAIN_NET_JSON_RPC_NO_POA_CERTS_FOUND_POA_CERTS, + DAP_CHAIN_NET_JSON_RPC_UNKNOWN_SUBCOMMANDS +}; diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c index d2b6a4d9eb6c8bda712272e59b6f850cfeca3e20..3d226a3a562ea6bd068d57fb710d165961c2b60b 100644 --- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c +++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c @@ -38,6 +38,7 @@ #include "dap_chain_node_client.h" #include "dap_stream_ch_chain_net_pkt.h" #include "dap_chain_node_cli_cmd.h" +#include "json_object.h" #define LOG_TAG "dap_chain_net_srv_stake_pos_delegate" @@ -2728,6 +2729,77 @@ void dap_chain_net_srv_stake_get_fee_validators_str(dap_chain_net_t *a_net, dap_ DAP_DELETE(l_median_coins); } +json_object *dap_chain_net_srv_stake_get_fee_validators_json(dap_chain_net_t *a_net) { + if (!a_net) + return NULL; + uint256_t l_min = uint256_0, l_max = uint256_0, l_average = uint256_0, l_median = uint256_0; + dap_chain_net_srv_stake_get_fee_validators(a_net, &l_max, &l_average, &l_min, &l_median); + const char *l_native_token = a_net->pub.native_ticker; + char *l_min_balance = dap_chain_balance_print(l_min), + *l_min_coins = dap_chain_balance_to_coins(l_min), + *l_max_balance = dap_chain_balance_print(l_max), + *l_max_coins = dap_chain_balance_to_coins(l_max), + *l_average_balance = dap_chain_balance_print(l_average), + *l_average_coins = dap_chain_balance_to_coins(l_average), + *l_median_balance = dap_chain_balance_print(l_median), + *l_median_coins = dap_chain_balance_to_coins(l_median); + json_object *l_jobj_ret = json_object_new_object(); + json_object *l_jobj_min = json_object_new_object(); + json_object *l_jobj_min_coins = json_object_new_string(l_min_coins); + json_object *l_jobj_min_balance = json_object_new_string(l_min_balance); + json_object *l_jobj_max = json_object_new_object(); + json_object *l_jobj_max_coins = json_object_new_string(l_max_coins); + json_object *l_jobj_max_balance = json_object_new_string(l_max_balance); + json_object *l_jobj_average = json_object_new_object(); + json_object *l_jobj_average_coins = json_object_new_string(l_average_coins); + json_object *l_jobj_average_balance = json_object_new_string(l_average_balance); + json_object *l_jobj_median = json_object_new_object(); + json_object *l_jobj_median_coins = json_object_new_string(l_median_coins); + json_object *l_jobj_median_balance = json_object_new_string(l_median_balance); + json_object *l_jobj_ticker = json_object_new_string(l_native_token); + if (!l_jobj_ret || !l_jobj_min || !l_jobj_min_coins || !l_jobj_min_balance || !l_jobj_max || !l_jobj_max_coins || + !l_jobj_max_balance || !l_jobj_average || !l_jobj_average_coins || !l_jobj_average_balance || !l_jobj_median || + !l_jobj_median_coins || !l_jobj_median_balance || !l_jobj_ticker) { + json_object_put(l_jobj_ret); + json_object_put(l_jobj_min); + json_object_put(l_jobj_min_coins); + json_object_put(l_jobj_min_balance); + json_object_put(l_jobj_max); + json_object_put(l_jobj_max_coins); + json_object_put(l_jobj_max_balance); + json_object_put(l_jobj_average); + json_object_put(l_jobj_average_coins); + json_object_put(l_jobj_average_balance); + json_object_put(l_jobj_median); + json_object_put(l_jobj_median_coins); + json_object_put(l_jobj_median_balance); + json_object_put(l_jobj_ticker); + return NULL; + } + json_object_object_add(l_jobj_min, "coin", l_jobj_min_coins); + json_object_object_add(l_jobj_min, "balance", l_jobj_min_balance); + json_object_object_add(l_jobj_max, "coin", l_jobj_max_coins); + json_object_object_add(l_jobj_max, "balance", l_jobj_max_balance); + json_object_object_add(l_jobj_average, "coin", l_jobj_average_coins); + json_object_object_add(l_jobj_average, "balance", l_jobj_average_balance); + json_object_object_add(l_jobj_median, "coin", l_jobj_median_coins); + json_object_object_add(l_jobj_median, "balance", l_jobj_median_balance); + json_object_object_add(l_jobj_ret, "min", l_jobj_min); + json_object_object_add(l_jobj_ret, "max", l_jobj_max); + json_object_object_add(l_jobj_ret, "average", l_jobj_average); + json_object_object_add(l_jobj_ret, "median", l_jobj_median); + json_object_object_add(l_jobj_ret, "token", l_jobj_ticker); + DAP_DELETE(l_min_balance); + DAP_DELETE(l_min_coins); + DAP_DELETE(l_max_balance); + DAP_DELETE(l_max_coins); + DAP_DELETE(l_average_balance); + DAP_DELETE(l_average_coins); + DAP_DELETE(l_median_balance); + DAP_DELETE(l_median_coins); + return l_jobj_ret; +} + static void s_cache_data(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_addr_t *a_signing_addr) { if (!dap_ledger_cache_enabled(a_ledger)) diff --git a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h index ff69a780555530f66e2115885afc85fe3d3bf932..b9ed7aaed047cde7711036dd9179ff89817c84b2 100644 --- a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h +++ b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h @@ -81,6 +81,7 @@ bool dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net, uint256_t *a_max_fee, uint256_t *a_average_fee, uint256_t *a_min_fee, uint256_t *a_median_fee); void dap_chain_net_srv_stake_get_fee_validators_str(dap_chain_net_t *a_net, dap_string_t *a_string); +json_object *dap_chain_net_srv_stake_get_fee_validators_json(dap_chain_net_t *a_net); int dap_chain_net_srv_stake_load_cache(dap_chain_net_t *a_net); void dap_chain_net_srv_stake_purge(dap_chain_net_t *a_net); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 0564972caa758eef27182b2290cfcc613b3872b9..d73c2eadd34e96e6d3c94f04717c277f0c92f8ec 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -2364,6 +2364,41 @@ static int s_callback_receipt_next_success(dap_chain_net_srv_t *a_srv, uint32_t return 0; } +json_object *dap_chain_net_srv_xchange_print_fee_json(dap_chain_net_t *a_net) { + if (!a_net) + return NULL; + uint256_t l_fee = {0}; + dap_chain_addr_t l_addr = {0}; + uint16_t l_type = 0; + if (s_srv_xchange_get_fee(a_net->pub.id, &l_fee, &l_addr, &l_type)) { + char *l_fee_balance = dap_chain_balance_print(l_fee); + char *l_fee_coins = dap_chain_balance_to_coins(l_fee); + char *l_addr_str = dap_chain_addr_to_str(&l_addr); + const char *l_type_str = dap_chain_net_srv_fee_type_to_str((dap_chain_net_srv_fee_type_t)l_type); + json_object *l_jobj_xchange = json_object_new_object(); + json_object *l_jobj_balance = json_object_new_string(l_fee_balance); + json_object *l_jobj_coins = json_object_new_string(l_fee_coins); + json_object *l_jobj_addr = json_object_new_string(l_addr_str); + json_object *l_jobj_type = json_object_new_string(l_type_str); + if (!l_jobj_xchange || !l_jobj_balance || !l_jobj_coins || !l_jobj_addr || !l_jobj_type) { + json_object_put(l_jobj_xchange); + json_object_put(l_jobj_balance); + json_object_put(l_jobj_coins); + json_object_put(l_jobj_addr); + json_object_put(l_jobj_type); + return NULL; + } + json_object_object_add(l_jobj_xchange, "coin", l_jobj_coins); + json_object_object_add(l_jobj_xchange, "balance", l_jobj_balance); + json_object_object_add(l_jobj_xchange, "addr", l_jobj_addr); + json_object_object_add(l_jobj_xchange, "type", l_jobj_type); + return l_jobj_xchange; + } else { + json_object *l_jobj_str = json_object_new_string("service has not announced a commission fee"); + return l_jobj_str; + } +} + void dap_chain_net_srv_xchange_print_fee(dap_chain_net_t *a_net, dap_string_t *a_string_ret){ if (!a_net || !a_string_ret) return; diff --git a/modules/service/xchange/include/dap_chain_net_srv_xchange.h b/modules/service/xchange/include/dap_chain_net_srv_xchange.h index 94544ab8dfce325280d1559fd64fa1a7c36bcbc2..1d8ac20c694eb2f847b2ec197c8b25d8eedb3369 100644 --- a/modules/service/xchange/include/dap_chain_net_srv_xchange.h +++ b/modules/service/xchange/include/dap_chain_net_srv_xchange.h @@ -60,4 +60,5 @@ extern const dap_chain_net_srv_uid_t c_dap_chain_net_srv_xchange_uid; int dap_chain_net_srv_xchange_init(); void dap_chain_net_srv_xchange_deinit(); +json_object *dap_chain_net_srv_xchange_print_fee_json(dap_chain_net_t *a_net); void dap_chain_net_srv_xchange_print_fee(dap_chain_net_t *a_net, dap_string_t *a_string_ret);