diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c004d8990799addb100c55defdfca7735539d57..9f39fae0270e87948077680944c78f7bbf23fa2a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,7 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS find_package(PkgConfig REQUIRED) pkg_search_module(GLIB REQUIRED glib-2.0) -target_link_libraries(dap_chain_net dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_mempool dap_chain_global_db -lresolv ${GLIB_LDFLAGS}) +target_link_libraries(dap_chain_net dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_wallet dap_chain_mempool dap_chain_global_db -lresolv ${GLIB_LDFLAGS}) target_include_directories(dap_chain_net INTERFACE . PUBLIC ${GLIB_INCLUDE_DIRS} ${IPUTILS_INCLUDE_DIRS}) set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE) diff --git a/dap_chain_net.c b/dap_chain_net.c index 5f2f6c9131fc24e790ea987fd149fd607e5adb2a..b359346e9ce5b4e2ba1ba34728bd33afa63779fd 100644 --- a/dap_chain_net.c +++ b/dap_chain_net.c @@ -221,7 +221,8 @@ int dap_chain_net_init() // Create chain object dap_chain_t * l_chain = dap_chain_load_from_cfg(l_net->pub.name,l_entry_name); - DL_APPEND( l_net->pub.chains, l_chain); + if(l_chain) + DL_APPEND( l_net->pub.chains, l_chain); free(l_entry_name); } } diff --git a/dap_chain_node_cli.c b/dap_chain_node_cli.c index 6f267f06a62ca13448b1ad759d7b16d605352848..bb446f11c43028f685375fe8e81f26f69c3aa6ae 100644 --- a/dap_chain_node_cli.c +++ b/dap_chain_node_cli.c @@ -58,16 +58,30 @@ typedef int SOCKET; static SOCKET server_sockfd = -1; -static const COMMAND commands[] = { - { "global_db", com_global_db, "Work with database" }, - { "node", com_node, "Work with node" }, - { "ping", com_ping, "Ping utility" }, - { "traceroute", com_traceroute, "Traceroute utility" }, - { "tracepath", com_tracepath, "Tracepath utility" }, - { "help", com_help, "Display this text" }, - { "?", com_help, "Synonym for `help'" }, - { (char *) NULL, (cmdfunc_t *) NULL, (char *) NULL } -}; +static const COMMAND commands[] = + { + { "global_db", com_global_db, "Work with global database", + "global_db node add -addr {<node address> | -alias <node alias>} -shard <shard id> {-ipv4 <ipv4 external address> | -ipv6 <ipv6 external address>}\n" + "global_db node del -addr <node address> | -alias <node alias>\n" + "global_db node link {add|del} {-addr <node address> | -alias <node alias>} -link <node address>\n" + "global_db node dump -addr <node address> | -alias <node alias>" }, + { "node", com_node, "Work with node", + "node alias {<node address> | -alias <node alias>}\n" + "node handshake {<node address> | -alias <node alias>}" }, + { "ping", com_ping, "Send ICMP ECHO_REQUEST to network hosts", + "ping [-c <count>] host" }, + { "traceroute", com_traceroute, "Print the hops and time of packets trace to network host", + "traceroute host" }, + { "tracepath", com_tracepath, "Traces path to a network host along this path", + "tracepath host" }, + { "help", com_help, "Description of command parameters", "" }, + { "?", com_help, "Synonym for 'help'", "" }, + { "tx_create", com_tx_create, "Signing transaction", + "tx_create -wallet <wallet name> [-path <wallet path>]" }, + { "tx_verify", com_tx_verify, "Verifing transaction", + "tx_verify -wallet <wallet name> [-path <wallet path>]" }, + { (char *) NULL, (cmdfunc_t *) NULL, (char *) NULL } + }; /** * Look up NAME as the name of a command, and return a pointer to that @@ -296,6 +310,8 @@ static void* thread_one_client_func(void *args) // execute command char *str_cmd = g_strdup_printf("%s", cmd_name); const COMMAND *command = find_command(cmd_name); + int res = -1; + char *str_reply = NULL; if(command) { while(list) { @@ -304,26 +320,27 @@ static void* thread_one_client_func(void *args) } log_it(L_INFO, "execute command=%s", str_cmd); // exec command - int res = 0; + char **argv = g_strsplit(str_cmd, ";", -1); - char *str_reply = NULL; // Call the command function if(command && command->func) res = (*(command->func))(argc, (const char **) argv, &str_reply); g_strfreev(argv); - gchar *reply_body = g_strdup_printf("%d\r\n%s\r\n", res, (str_reply) ? str_reply : ""); - // return the result of the command function - gchar *reply_str = g_strdup_printf("HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", - strlen(reply_body), reply_body); - int ret = send(newsockfd, reply_str, strlen(reply_str), 1000); - g_free(str_reply); - g_free(reply_str); - g_free(reply_body); } else { - log_it(L_ERROR, "can't recognize command=%s", str_cmd); + str_reply = g_strdup_printf("can't recognize command=%s", str_cmd); + log_it(L_ERROR, str_reply); } + gchar *reply_body = g_strdup_printf("%d\r\n%s\r\n", res, (str_reply) ? str_reply : ""); + // return the result of the command function + gchar *reply_str = g_strdup_printf("HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", + strlen(reply_body), reply_body); + int ret = send(newsockfd, reply_str, strlen(reply_str), 1000); + g_free(str_reply); + g_free(reply_str); + g_free(reply_body); + g_free(str_cmd); } g_list_free_full(cmd_param_list, free); diff --git a/dap_chain_node_cli.h b/dap_chain_node_cli.h index a449082ab5334abe11773d0d54fc90fdd4e7d287..37875ba60ed56c1bcceb49681808f64b17b0a6ac 100644 --- a/dap_chain_node_cli.h +++ b/dap_chain_node_cli.h @@ -34,6 +34,7 @@ typedef struct { char *name; /* User printable name of the function. */ cmdfunc_t *func; /* Function to call to do the job. */ char *doc; /* Documentation for this function. */ + char *doc_ex; /* Full documentation for this function. */ } COMMAND; /** diff --git a/dap_chain_node_cli_cmd.c b/dap_chain_node_cli_cmd.c index eddac8d1615a4626ce208a8e4a1c483d24c6a998..457c25e4935dda64f11a3fd03f705f44823d31c4 100644 --- a/dap_chain_node_cli_cmd.c +++ b/dap_chain_node_cli_cmd.c @@ -26,17 +26,28 @@ #include <errno.h> #include <assert.h> #include <glib.h> +#include <time.h> #include <arpa/inet.h> #include <netinet/in.h> #include "iputils/iputils.h" //#include "dap_common.h" +#include "dap_hash.h" +#include "dap_chain_common.h" +#include "dap_chain_wallet.h" #include "dap_chain_node.h" #include "dap_chain_global_db.h" #include "dap_chain_node_client.h" #include "dap_chain_node_remote.h" #include "dap_chain_node_cli_cmd.h" +#include "dap_chain_datum.h" +#include "dap_chain_datum_tx_in.h" +#include "dap_chain_datum_tx_out.h" +#include "dap_chain_datum_tx_pkey.h" +#include "dap_chain_datum_tx_sig.h" +#include "dap_chain_datum_tx_cache.h" + // Max and min macros #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) @@ -124,7 +135,7 @@ static bool del_alias(const char *alias) * * return addr, NULL if not found */ -static dap_chain_node_addr_t* get_name_by_alias(const char *alias) +dap_chain_node_addr_t* get_name_by_alias(const char *alias) { dap_chain_node_addr_t *addr = NULL; if(!alias) @@ -638,7 +649,7 @@ int com_global_db(int argc, const char ** argv, char **str_reply) return com_global_db_link(&node_info, "del", alias_str, &link, str_reply); else { set_reply_text(str_reply, "command not recognize, supported format:\n" - "global_db node link [add|del] [-addr <node address> | -alias <node alias>] -link <node address>"); + "global_db node link <add|del] [-addr <node address> | -alias <node alias>] -link <node address>"); return -1; } break; @@ -733,7 +744,7 @@ int com_node(int argc, const char ** argv, char **str_reply) if(!node_info) { return -1; } - int timeout_ms = 100000; //100 sec. + int timeout_ms = 10000; //10 sec. // start handshake dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info); if(!client) { @@ -753,8 +764,18 @@ int com_node(int argc, const char ** argv, char **str_reply) DAP_DELETE(node_info); //Add new established connection in the list - chain_node_client_list_add(client); - + int ret = chain_node_client_list_add(&address, client); + switch (ret) + { + case -1: + dap_chain_node_client_close(client); + set_reply_text(str_reply, "connection established, but not saved"); + return -1; + case -2: + dap_chain_node_client_close(client); + set_reply_text(str_reply, "connection already present"); + return -1; + } set_reply_text(str_reply, "connection established"); break; } @@ -943,6 +964,147 @@ int com_ping(int argc, const char** argv, char **str_reply) * Help command */ int com_help(int argc, const char ** argv, char **str_reply) +{ + if(argc > 1) { + const COMMAND *cmd = find_command(argv[1]); + if(cmd) + { + set_reply_text(str_reply, "%s:\n%s", cmd->doc, cmd->doc_ex); + return 1; + } + set_reply_text(str_reply, "command \"%s\" not recognized", argv[1]); + return -1; + } + else { + // TODO Read list of commands & return it + } + if(str_reply) + set_reply_text(str_reply, "command not defined, enter \"help <cmd name>\""); + return -1; +} + +dap_chain_datum_tx_t* create_tx(const char *net_name) +{ + dap_chain_tx_in_t tx_in; + dap_chain_tx_in_t tx_out; + + tx_in.header.type = TX_ITEM_TYPE_IN; + //tx_in.header.sig_size = 0; + //tx_in + + dap_chain_datum_tx_t *tx = DAP_NEW_Z(dap_chain_datum_tx_t); + tx->header.lock_time = time(NULL); + int res = dap_chain_datum_tx_add_item(&tx, (const uint8_t*) &tx_in); + //dap_chain_tx_in_t + + //dap_chain_hash_t a_hash_fast; + //dap_hash((char*) tx, sizeof(tx), a_hash_fast.raw, sizeof(a_hash_fast.raw), DAP_HASH_TYPE_KECCAK); + + /* + // create file with dap_chain_t + dap_chain_id_t a_chain_id = {0x1}; + dap_chain_net_id_t a_chain_net_id = {0x2}; + dap_chain_shard_id_t a_shard_id = {0x3}; + + dap_chain_t *a_chain = dap_chain_create(a_chain_net_id, a_chain_id, a_shard_id); + const char * a_chain_net_name = "0x1"; + const char * a_chain_cfg_name = "chain-0"; + dap_chain_t *ch2 = dap_chain_load_from_cfg(a_chain_net_name, a_chain_cfg_name); + + //dap_chain_net_t *l_net = dap_chain_net_by_name(net_name); + //dap_chain_id_t *chain = l_net->pub.chains; + */ + return tx; +} + +/** + * com_tx_create command + * + * Signing transaction + */ +int com_tx_create(int argc, const char ** argv, char **str_reply) +{ + // create wallet + const char *a_wallets_path = "/opt/kelvin-node/etc"; + const char *a_wallet_name = "w1"; + dap_chain_net_id_t a_net_id = { 0x1 }; + dap_chain_sign_type_t a_sig_type = { SIG_TYPE_TESLA }; + //dap_chain_sign_type_t a_sig_type = { SIG_TYPE_PICNIC }; + //dap_chain_sign_type_t a_sig_type = { SIG_TYPE_BLISS }; + dap_chain_wallet_t *wallet = dap_chain_wallet_create(a_wallet_name, a_wallets_path, a_net_id, a_sig_type); + dap_chain_wallet_t *wallet2 = dap_chain_wallet_open(a_wallet_name, a_wallets_path); + //wallet = dap_chain_wallet_open(a_wallet_name, a_wallets_path); + //dap_chain_wallet_save(wallet2); + dap_chain_datum_tx_t *tx = create_tx("0x123"); + + static bool l_first_start = true; + if(l_first_start) + { + const char *l_token_name = "KLVN"; + dap_enc_key_t *l_key = dap_chain_wallet_get_key(wallet, 0); + const dap_chain_addr_t *l_addr = dap_chain_wallet_get_addr(wallet); + dap_chain_node_datum_tx_cache_init(l_key, l_token_name, (dap_chain_addr_t*)l_addr, 1000); + l_first_start = false; + } + + const dap_chain_addr_t *addr = dap_chain_wallet_get_addr(wallet); + + char *addr_str = dap_chain_addr_to_str((dap_chain_addr_t*)addr); + const dap_chain_addr_t *addr2 = dap_chain_str_to_addr(addr_str); + char *addr_str2 = dap_chain_addr_to_str(addr2); + free(addr_str); + + // debug - check signing + { + int a_data_size = 50; + char *a_data = "DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify"; + + + dap_enc_key_t *a_key0 = dap_enc_key_new_generate(DAP_ENC_KEY_TYPE_SIG_BLISS, NULL, 0, NULL, 0, 0); + + dap_enc_key_t *a_key1 = dap_chain_wallet_get_key(wallet, 0); + dap_enc_key_t *a_key2 = dap_chain_wallet_get_key(wallet2, 0); + dap_chain_sign_t *a_chain_sign0 = dap_chain_sign_create(a_key0, a_data, a_data_size, 0); + dap_chain_sign_t *a_chain_sign1 = dap_chain_sign_create(a_key1, a_data, a_data_size, 0); + dap_chain_sign_t *a_chain_sign2 = dap_chain_sign_create(a_key2, a_data, a_data_size, 0); + size_t a_chain_sign_size = dap_chain_sign_get_size(a_chain_sign1); + int verify0 = dap_chain_sign_verify(a_chain_sign0, a_data, a_data_size); + int verify1 = dap_chain_sign_verify(a_chain_sign1, a_data, a_data_size); + int verify2 = dap_chain_sign_verify(a_chain_sign2, a_data, a_data_size); + printf("a_chain_sign=%d verify=%d %d %d\n", a_chain_sign_size, verify0, verify1, verify2); + free(a_chain_sign2); + free(a_chain_sign1); + free(a_chain_sign0); + //dap_enc_key_delete(a_key2); + dap_enc_key_delete(a_key0); + //dap_enc_key_delete(a_key1); + } + + if(wallet) { + if(dap_chain_wallet_get_certs_number(wallet) > 0) { + dap_chain_pkey_t *pk0 = dap_chain_wallet_get_pkey(wallet, 0); + dap_enc_key_t *a_key = dap_chain_wallet_get_key(wallet, 0); + //dap_enc_key_t *a_key1 = dap_chain_wallet_get_key(wallet, 0); + //dap_enc_key_t *a_key2 = dap_chain_wallet_get_key(wallet2, 0); + int res = dap_chain_datum_tx_add_sign(&tx, a_key); + int res1 = dap_chain_datum_tx_add_sign(&tx, a_key); + int res2 = dap_chain_datum_tx_add_sign(&tx, a_key); + int res3 = dap_chain_datum_tx_verify_sign(tx); + res3 = 0; + } + dap_chain_wallet_close(wallet); + DAP_DELETE(tx); + } + set_reply_text(str_reply, "com_tx_create ok"); + return 0; +} + +/** + * tx_verify command + * + * Verifing transaction + */ +int com_tx_verify(int argc, const char ** argv, char **str_reply) { if(argc > 1) { const COMMAND *cmd = find_command(argv[1]); @@ -959,4 +1121,3 @@ int com_help(int argc, const char ** argv, char **str_reply) set_reply_text(str_reply, "command not defined, enter \"help <cmd name>\""); return -1; } - diff --git a/dap_chain_node_cli_cmd.h b/dap_chain_node_cli_cmd.h index c27e7ec822ac0cfbc3a6af0ef9f727196720f735..61f9e4484e0700b846c583238b64ac625a994e09 100644 --- a/dap_chain_node_cli_cmd.h +++ b/dap_chain_node_cli_cmd.h @@ -21,8 +21,16 @@ #pragma once +#include "dap_chain_node.h" #include "dap_chain_node_cli.h" +/** + * Find in base addr by alias + * + * return addr, NULL if not found + */ +dap_chain_node_addr_t* get_name_by_alias(const char *alias); + /** * Look up NAME as the name of a command, and return a pointer to that * command. Return a NULL pointer if NAME isn't a command name. @@ -64,3 +72,17 @@ int com_ping(int argc, const char** argv, char **str_reply); * Help command */ int com_help(int argc, const char ** argv, char **str_reply); + +/** + * com_tx_create command + * + * Signing transaction + */ +int com_tx_create(int argc, const char ** argv, char **str_reply); + +/** + * tx_verify command + * + * Verifing transaction + */ +int com_tx_verify(int argc, const char ** argv, char **str_reply); diff --git a/dap_chain_node_remote.c b/dap_chain_node_remote.c index 9ba16a39893c26a2a7afe4174b629d8830041f95..4c923e3a4f9db93cd355cf75ed11747ff9bb8cdb 100644 --- a/dap_chain_node_remote.c +++ b/dap_chain_node_remote.c @@ -22,69 +22,117 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> -#include <glib.h> #include <pthread.h> +#include "uthash.h" +#include "dap_common.h" #include "dap_chain_node_remote.h" +typedef struct list_linked_item { + dap_chain_node_addr_t address; + dap_chain_node_client_t *client; + UT_hash_handle hh; +} list_linked_item_t; // List of connections -static GList *connect_list = NULL; +static list_linked_item_t *conn_list = NULL; // for separate access to connect_list static pthread_mutex_t connect_list_mutex = PTHREAD_MUTEX_INITIALIZER; + /** - * Add new established connection in the list + * Add new established connection to the list + * + * return 0 OK, -1 error, -2 already present */ -bool chain_node_client_list_add(dap_chain_node_client_t *client) +int chain_node_client_list_add(dap_chain_node_addr_t *a_address, dap_chain_node_client_t *a_client) { - if(!client) - return false; + int l_ret = 0; + if(!a_address || !a_client) + return -1; + list_linked_item_t *item_tmp = NULL; pthread_mutex_lock(&connect_list_mutex); - connect_list = g_list_append(connect_list, client); + HASH_FIND(hh, conn_list, a_address, sizeof(dap_chain_node_addr_t), item_tmp); // address already in the hash? + if(item_tmp == NULL) { + item_tmp = DAP_NEW(list_linked_item_t); + item_tmp->address.uint64 = a_address->uint64; + item_tmp->client = a_client; + HASH_ADD(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp); // address: name of key field + l_ret = 0; + } + // connection already present + else + l_ret = -2; + //connect_list = g_list_append(connect_list, client); pthread_mutex_unlock(&connect_list_mutex); - return true; + return l_ret; } /** * Delete established connection from the list + * + * return 0 OK, -1 error, -2 address not found */ -bool chain_node_client_list_del(dap_chain_node_client_t *client) +int chain_node_client_list_del(dap_chain_node_addr_t *address) { + int ret = -1; + if(!address) + return -1; + list_linked_item_t *item_tmp; pthread_mutex_lock(&connect_list_mutex); - GList *list = g_list_find(connect_list, client); - // found - if(list) - connect_list = g_list_remove(connect_list, client); + HASH_FIND(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp); + if(item_tmp != NULL) { + HASH_DEL(conn_list, item_tmp); + ret = 0; + } + else + // address not found in the hash + ret = -2; pthread_mutex_unlock(&connect_list_mutex); - if(list) - return true; - return false; + if(!ret) { + // close connection + dap_chain_node_client_close(item_tmp->client); + // del struct for hash + DAP_DELETE(item_tmp); + } + return ret; } /** - * Get one established connection - * - * n - the position of the established connection, counting from 0 - * - * return client, or NULL if the position is off the end of the list + * Delete all established connection from the list */ -dap_chain_node_client_t* chain_node_client_list_get_item(int n) +void chain_node_client_list_del_all(void) { + int ret = -1; + list_linked_item_t *iter_current, *item_tmp; pthread_mutex_lock(&connect_list_mutex); - dap_chain_node_client_t *client = g_list_nth_data(connect_list, (guint) n); + HASH_ITER(hh, conn_list , iter_current, item_tmp) { + // close connection + dap_chain_node_client_close(iter_current->client); + // del struct for hash + HASH_DEL(conn_list, iter_current); + } pthread_mutex_unlock(&connect_list_mutex); - return client; } + /** - * Get the number of established connections + * Get present established connection by address + * + * return client, or NULL if the connection not found in the list */ -int chain_node_client_list_count(void) +const dap_chain_node_client_t* chain_node_client_find(dap_chain_node_addr_t *address) { + int ret = 0; + if(!address) + return NULL; + dap_chain_node_client_t *client_ret = NULL; + list_linked_item_t *item_tmp; pthread_mutex_lock(&connect_list_mutex); - int len = g_list_length(connect_list); + HASH_FIND(hh, conn_list, address, sizeof(dap_chain_node_addr_t), item_tmp); // address already in the hash? + if(item_tmp != NULL) { + client_ret = item_tmp->client; + } pthread_mutex_unlock(&connect_list_mutex); - return len; + return client_ret; } - diff --git a/dap_chain_node_remote.h b/dap_chain_node_remote.h index 0ce1cfdb528e863fb0f0ede875d996af0629b215..ca175db0d008490f1c57dc5d5487c3039f6ce72a 100644 --- a/dap_chain_node_remote.h +++ b/dap_chain_node_remote.h @@ -23,28 +23,31 @@ #include <stdbool.h> +#include "dap_chain_node.h" #include "dap_chain_node_client.h" /** - * Add new established connection in the list + * Add new established connection to the list + * + * return 0 OK, -1 error, -2 already present */ -bool chain_node_client_list_add(dap_chain_node_client_t *client); +int chain_node_client_list_add(dap_chain_node_addr_t *address, dap_chain_node_client_t *client); /** * Delete established connection from the list + * + * return 0 OK, -1 error, -2 address not found */ -bool chain_node_client_list_del(dap_chain_node_client_t *client); +int chain_node_client_list_del(dap_chain_node_addr_t *address); /** - * Get one established connection - * - * n - the position of the established connection, counting from 0 - * - * return client, or NULL if the position is off the end of the list + * Delete all established connection from the list */ -dap_chain_node_client_t* chain_node_client_list_get_item(int n); +void chain_node_client_list_del_all(void); /** - * Get the number of established connections + * Get present established connection by address + * + * return client, or NULL if the connection not found in the list */ -int chain_node_client_list_count(void); +const dap_chain_node_client_t* chain_node_client_find(dap_chain_node_addr_t *address);