Skip to content
Snippets Groups Projects
dap_chain_node_cli_cmd.c 55.6 KiB
Newer Older
            return -1;
        }

        // send request
        size_t l_data_size_out = 0;
        // Get last timestamp in log
        time_t l_timestamp_start = dap_db_log_get_last_timestamp();
        size_t l_data_send_len = 0;
        uint8_t *l_data_send = dap_stream_ch_chain_net_make_packet(l_cur_node_addr, node_info->hdr.address.uint64,
                l_timestamp_start, NULL, 0, &l_data_send_len);
        uint8_t l_ch_id = dap_stream_ch_chain_net_get_id(); // Channel id for global_db sync
        res = dap_chain_node_client_send_chain_net_request(client, l_ch_id,
        STREAM_CH_CHAIN_NET_PKT_TYPE_GLOBAL_DB_REQUEST_SYNC, l_data_send, l_data_send_len); //, NULL);
        DAP_DELETE(l_data_send);
        if(res != 1) {
            set_reply_text(str_reply, "no request sent");
            // clean client struct
            dap_chain_node_client_close(client);
            DAP_DELETE(node_info);
            return -1;
        }

        // wait for finishing of request
        timeout_ms = 120000; // 2 min = 120 sec = 120 000 ms
        // TODO add progress info to console
        res = chain_node_client_wait(client, NODE_CLIENT_STATE_END, timeout_ms);
        DAP_DELETE(node_info);
        dap_client_disconnect(client->client);
        dap_chain_node_client_close(client);
        switch (res) {
        case 0:
            set_reply_text(str_reply, "timeout");
            return -1;
        case 1:
            set_reply_text(str_reply, "nodes sync completed");
            return 0;
        default:
            set_reply_text(str_reply, "error");
            return -1;
        }
        // make handshake
    case CMD_HANDSHAKE: {
        // get address from alias if addr not defined
        if(alias_str && !address.uint64) {
            dap_chain_node_addr_t *address_tmp = get_name_by_alias(alias_str);
            if(address_tmp) {
                memcpy(&address, address_tmp, sizeof(address_tmp));
                DAP_DELETE(address_tmp);
            }
            else {
                set_reply_text(str_reply, "no address found by alias");
                return -1;
            }
        }
        if(!address.uint64) {
            set_reply_text(str_reply, "addr not found");
            return -1;
        }

        dap_chain_node_info_t *node_info = dap_chain_node_info_read(&address, str_reply);
            return -1;
        int timeout_ms = 10000; //10 sec = 10000 ms
        // start handshake
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
        dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info);
        if(!client) {
            set_reply_text(str_reply, "can't connect");
            DAP_DELETE(node_info);
            return -1;
        }
        // wait handshake
        int res = chain_node_client_wait(client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
        if(res != 1) {
            set_reply_text(str_reply, "no response from node");
            // clean client struct
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
            dap_chain_node_client_close(client);
            DAP_DELETE(node_info);
            return -1;
        }
        DAP_DELETE(node_info);
        //Add new established connection in the list
        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");
    return 0;
}

/**
 * Traceroute command
 *
 * return 0 OK, -1 Err
 */
int com_traceroute(int argc, const char** argv, char **str_reply)
{
    const char *addr = NULL;
    int hops = 0, time_usec = 0;
    if(argc > 1)
        addr = argv[1];
    iputils_set_verbose();
    int res = (addr) ? traceroute_util(addr, &hops, &time_usec) : -EADDRNOTAVAIL;
    if(res >= 0) {
        set_reply_text(str_reply, "traceroute %s hops=%d time=%.1lf ms", addr, hops, time_usec * 1. / 1000);
    }
    else {
        if(str_reply) {
            switch (-res)
            {
            case EADDRNOTAVAIL:
                set_reply_text(str_reply, "traceroute %s error: %s", (addr) ? addr : "",
                        (addr) ? "Name or service not known" : "Host not defined");
                break;
            case 2:
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "Unknown traceroute module");
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "first hop out of range");
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "max hops cannot be more than 255");
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "no more than 10 probes per hop");
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "bad wait specifications");
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "too big packetlen ");
                set_reply_text(str_reply, "traceroute %s error: %s", addr,
                        "IP version mismatch in addresses specified");
                break;
            case 9:
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "bad sendtime");
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "init_ip_options");
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "calloc");
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "parse cmdline");
                set_reply_text(str_reply, "traceroute %s error: %s", addr, "trace method's init failed");
                set_reply_text(str_reply, "traceroute %s error(%d) %s", addr, res, "trace not found");
            }
        }
    }
    return res;
}

/**
 * Tracepath command
 *
 * return 0 OK, -1 Err
 */
int com_tracepath(int argc, const char** argv, char **str_reply)
{
    const char *addr = NULL;
    int hops = 0, time_usec = 0;
    if(argc > 1)
        addr = argv[1];
    iputils_set_verbose();
    int res = (addr) ? tracepath_util(addr, &hops, &time_usec) : -EADDRNOTAVAIL;
    if(res >= 0) {
        if(str_reply)
            set_reply_text(str_reply, "tracepath %s hops=%d time=%.1lf ms", addr, hops, time_usec * 1. / 1000);
    }
    else {
        if(str_reply) {
            switch (-res)
            {
            case EADDRNOTAVAIL:
                set_reply_text(str_reply, "tracepath %s error: %s", (addr) ? addr : "",
                        (addr) ? "Name or service not known" : "Host not defined");
                break;
            case ESOCKTNOSUPPORT:
                set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't create socket");
                set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_MTU_DISCOVER");
                set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_RECVERR");
                set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_HOPLIMIT");
                set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_MTU_DISCOVER");
                set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_RECVERR");
                set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_RECVTTL");
                set_reply_text(str_reply, "tracepath %s error: %s", addr, "malloc");
                set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_UNICAST_HOPS");
                set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_TTL");
                set_reply_text(str_reply, "tracepath %s error(%d) %s", addr, res, "trace not found");
            }
        }
    }
    return res;
}

/**
 * Ping command
 *
 * return 0 OK, -1 Err
 */
int com_ping(int argc, const char** argv, char **str_reply)
{
    int n = 4;
    if(argc < 2) {
        set_reply_text(str_reply, "host not specified");
        return -1;
    }
    const char *n_str = NULL;
    int argc_host = 1;
    int argc_start = 1;
    argc_start = find_option_val(argv, argc_start, argc, "-n", &n_str);
    if(argc_start) {
        argc_host = argc_start + 1;
        n = (n_str) ? atoi(n_str) : 4;
    }
    else {
        argc_start = find_option_val(argv, argc_start, argc, "-c", &n_str);
        if(argc_start) {
            argc_host = argc_start + 1;
            n = (n_str) ? atoi(n_str) : 4;
        }
    }
    const char *addr = argv[argc_host];
    iputils_set_verbose();
    int res = (addr) ? ping_util(addr, n) : -EADDRNOTAVAIL;
    if(res >= 0) {
        if(str_reply)
            set_reply_text(str_reply, "ping %s time=%.1lf ms", addr, res * 1. / 1000);
    }
    else {
        if(str_reply) {
            switch (-res)
            {
            case EDESTADDRREQ:
                set_reply_text(str_reply, "ping %s error: %s", addr, "Destination address required");
                break;
            case EADDRNOTAVAIL:
                set_reply_text(str_reply, "ping %s error: %s", (addr) ? addr : "",
                        (addr) ? "Host not found" : "Host not defined");
                break;
            case EPFNOSUPPORT:
                set_reply_text(str_reply, "ping %s error: %s", addr, "Unknown protocol family");
                set_reply_text(str_reply, "ping %s error(%d)", addr, -res);
            }
        }
    }
    return res;
}

/**
 * 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;
}

/**
 * com_tx_create command
 *
 * Wallet info
 */
int com_tx_wallet(int argc, const char ** argv, char **str_reply)
{
    const char *c_wallets_path = "/opt/kelvin-node/etc";
    // Get address of wallet
    enum {
        CMD_NONE, CMD_WALLET_LIST, CMD_WALLET_INFO
    };
    int arg_index = 1;
    int cmd_num = CMD_NONE;
    const char *cmd_str = NULL;
    // find  add parameter ('alias' or 'handshake')
    if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "list", NULL)) {
        cmd_num = CMD_WALLET_LIST;
    }
    else if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "info", NULL)) {
        cmd_num = CMD_WALLET_INFO;
    }
    arg_index++;
    if(cmd_num == CMD_NONE) {
        set_reply_text(str_reply, "format of command: wallet [list | info -addr <addr> -w <wallet_name>]");
        return -1;
    }

    dap_chain_node_addr_t address;
    memset(&address, 0, sizeof(dap_chain_node_addr_t));
    const char *addr_str = NULL, *wallet_name = NULL;
    // find wallet addr
    find_option_val(argv, arg_index, argc, "-addr", &addr_str);
    find_option_val(argv, arg_index, argc, "-w", &wallet_name);

    dap_string_t *l_string_ret = dap_string_new(NULL);
    switch (cmd_num) {
    // wallet list
    case CMD_WALLET_LIST: {
        GDir *l_dir = g_dir_open(c_wallets_path, 0, NULL);
        if(l_dir) {
            const char *l_file = NULL;
            do {
                l_file = g_dir_read_name(l_dir);
                int l_file_len = (l_file) ? strlen(l_file) : 0;
                if(l_file_len > 8 && !g_strcmp0(l_file + l_file_len - 8, ".dwallet")) {
                    char *l_file_path_tmp = dap_strdup_printf("%s/%s", c_wallets_path, l_file);
                    dap_chain_wallet_t *l_wallet = dap_chain_wallet_open_file(l_file_path_tmp);
                    if(l_wallet) {
                        dap_chain_addr_t *l_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet);
                        char *l_addr_str = dap_chain_addr_to_str((dap_chain_addr_t*) l_addr);
                        dap_string_append_printf(l_string_ret, "\nwallet: %s\n", l_wallet->name);
                        dap_string_append_printf(l_string_ret, "addr: %s\n", (l_addr_str) ? l_addr_str : "-");
                        DAP_DELETE(l_addr_str);
                        dap_chain_wallet_close(l_wallet);
                    }
                    DAP_DELETE(l_file_path_tmp);
                }
            }
            while(l_file);
            g_dir_close(l_dir);
        }
    }
        break;

        // wallet info
    case CMD_WALLET_INFO: {
        dap_chain_wallet_t *l_wallet = NULL;
        if(wallet_name)
            l_wallet = dap_chain_wallet_open(wallet_name, c_wallets_path);
        if(l_wallet) {
            dap_chain_addr_t *l_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet);
            char *l_addr_str = dap_chain_addr_to_str((dap_chain_addr_t*) l_addr);
            uint64_t balance = dap_chain_datum_tx_cache_calc_balance(l_addr);
            dap_string_append_printf(l_string_ret, "\nwallet: %s\n", l_wallet->name);
            dap_string_append_printf(l_string_ret, "addr: %s\n", (l_addr_str) ? l_addr_str : "-");
            dap_string_append_printf(l_string_ret, "balance: %lld\n", balance);
            DAP_DELETE(l_addr_str);
            dap_chain_wallet_close(l_wallet);
        }
        else {
            dap_string_free(l_string_ret, true);
            set_reply_text(str_reply, "wallet not found");
            return -1;
        }
    }
        break;
    }

    char *l_str_ret_tmp = dap_string_free(l_string_ret, false);
    char *str_ret = dap_strdup(l_str_ret_tmp);
    set_reply_text(str_reply, str_ret);
    DAP_DELETE(l_str_ret_tmp);
    return 0;
}

/**
 * com_tx_create command
 *
 * Create transaction
 */
int com_tx_create(int argc, const char ** argv, char **str_reply)
{
    int arg_index = 1;
    int cmd_num = 1;
    const char *value_str = NULL;
    const char *addr_base58_from = NULL;
    const char *addr_base58_to = NULL;
    const char *addr_base58_fee = NULL;
    const char *str_tmp = NULL;
    uint64_t value = 0;
    uint64_t value_fee = 0;
    find_option_val(argv, arg_index, argc, "from", &addr_base58_from);
    find_option_val(argv, arg_index, argc, "to", &addr_base58_to);
    if(find_option_val(argv, arg_index, argc, "fee", &addr_base58_fee)) {
        if(find_option_val(argv, arg_index, argc, "value_fee", &str_tmp)) {
            value_fee = strtoll(str_tmp, NULL, 10);
        }
    }
    if(find_option_val(argv, arg_index, argc, "value", &str_tmp)) {
        value = strtoll(str_tmp, NULL, 10);
    }
    if(!addr_base58_from) {
        set_reply_text(str_reply, "tx_create requires parameter 'from'");
        return -1;
    }
    if(!addr_base58_to) {
        set_reply_text(str_reply, "tx_create requires parameter 'to'");
        return -1;
    }
    if(!value) {
        set_reply_text(str_reply, "tx_create requires parameter 'value'");
        return -1;
    }
    if(addr_base58_fee && !value_fee) {
        set_reply_text(str_reply, "tx_create requires parameter 'value_fee' if 'fee' is specified");
        return -1;
    }

    const char *c_wallets_path = "/opt/kelvin-node/etc";
    const char *a_wallet_name_bliss = "w_bliss";
    const char *a_wallet_name_bliss2 = "w_bliss2";
    const char *a_wallet_name_picnic = "w_picnic";
    const char *a_wallet_name_tesla = "w_tesla";

    dap_chain_wallet_t *wallet_bliss = dap_chain_wallet_open(a_wallet_name_bliss, c_wallets_path);
    dap_chain_wallet_t *wallet_bliss2 = dap_chain_wallet_open(a_wallet_name_bliss2, c_wallets_path);
    dap_chain_wallet_t *wallet_picnic = dap_chain_wallet_open(a_wallet_name_picnic, c_wallets_path);
    dap_chain_wallet_t *wallet_tesla = dap_chain_wallet_open(a_wallet_name_tesla, c_wallets_path);
    dap_enc_key_t *l_key_bliss = dap_chain_wallet_get_key(wallet_bliss, 0);
    dap_enc_key_t *l_key_bliss2 = dap_chain_wallet_get_key(wallet_bliss2, 0);
    dap_enc_key_t *l_key_picnic = dap_chain_wallet_get_key(wallet_picnic, 0);
    dap_enc_key_t *l_key_tesla = dap_chain_wallet_get_key(wallet_tesla, 0);
            //"EXh66KVCxChbKHQcTWKYJXhua6HVZecpxuTTmWGuqm1V4vy5mVq52wD8rMQvfUnmJHsL4MuoJ7YVSFqn2RrdoN19mqHP1aQXSQPnXDR6oP9vsBPwYC9PhSvAxFystX";
            "EXh66KVCxChbKHQcSCRnMTByuFRDU2UsZUViPz2BoUAEYYWPfu8WhHhqX9HSyL3U3Q54JvJoKRZhRtumsAVNV6j8pzgtZDkkwzLgHBCAQHcG2FaSwCxESjkCYkgHUo";
            //"EXh66KVCxChbKHQcTeGf8TT7KhcCiiQ9TrPn6rcbNoNKuhAyJ4T9zr5yMfMCXGLVHmxVKZ6J4E9Zc7pNmAa4yrKNb3DkS34jxD6Q4MCXbHJMAPFEVtMoDdFMtCysE2";
            "EXh66KVCxChbKHQcSx27VwwbUnT2rRGNDBJm6zdC3DQw8XWtHqHrpoc9NEVd6Ub5rdFosQiXgWc5VhiNoySB6T4E49LMhMnLhr9sMSVqRr7Mix4bPrPEZXsYnNLzeX";
            //"EXh66KVCxChbKJLxZbyNJLxfF8CfGZmdenQWuqtr8MnXavhJaLo6vckjpYgpcevBo3zB65sAGQJT3ctYVwQnASc6sYyaawFHnacsrcP47PB4XfLYiEDZvwog4AVdbC";
            "EXh66KVCxChbKJLxXTwipYMooUpoGvpwpkcjpmGLbubwzqR2vVsH9HEgT2LcU2hDs2BTFkaNC8itE8nuCWxskVtRJG4iaubBDcRWAt2awtCVHAULffQGrwe8ocRCzS";
    char *addr_w_tesla =
            "EXh66KVCxChbTZ9umzb4Y6nJcMti8DPUdrsE1V4adjoKyPG3VvyrzHh6wrP6wGERLq9Qj5qK4hMEjd6uidcbsSSpzKQuADC2g1DzYkCCcitAs2Nsxk4dhespDdximc";

    dap_chain_wallet_t *l_wallet;
    dap_enc_key_t *l_key;
    if(!strcmp(addr_base58_from, addr_w_bliss)) {
        l_wallet = wallet_bliss;
        l_key = l_key_bliss;
    }
    else if(!strcmp(addr_base58_from, addr_w_bliss2)) {
        l_wallet = wallet_bliss2;
        l_key = l_key_bliss2;
    }
    else if(!strcmp(addr_base58_from, addr_w_picnic)) {
        l_wallet = wallet_picnic;
        l_key = l_key_picnic;
    }
    if(!l_wallet || !l_key) {
        set_reply_text(str_reply, "wallet for address 'from' does not exist");
        return -1;
    }

    dap_chain_addr_t *addr_from = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet);
    dap_chain_addr_t *addr_to = dap_chain_str_to_addr(addr_base58_to);
    dap_chain_addr_t *addr_fee = dap_chain_str_to_addr(addr_base58_fee);

    if(!addr_from) {
        set_reply_text(str_reply, "source address is invalid");
        return -1;
    }
    if(!addr_to) {
        set_reply_text(str_reply, "destination address is invalid");
        return -1;
    }
    if(addr_base58_fee && !addr_fee) {
        set_reply_text(str_reply, "fee address is invalid");
        return -1;
    }
    /*    dap_chain_addr_t *addr_b2 = (dap_chain_addr_t *) dap_chain_wallet_get_addr(wallet_bliss2);
     dap_chain_addr_t *addr_p = (dap_chain_addr_t *) dap_chain_wallet_get_addr(wallet_picnic);
     dap_chain_addr_t *addr_t = (dap_chain_addr_t *) dap_chain_wallet_get_addr(wallet_tesla);

     char *addr_str_b2 = dap_chain_addr_to_str((dap_chain_addr_t*) addr_b2);
     char *addr_str_p = dap_chain_addr_to_str((dap_chain_addr_t*) addr_p);
     char *addr_str_t = dap_chain_addr_to_str((dap_chain_addr_t*) addr_t);

     char *addr_str = dap_chain_addr_to_str((dap_chain_addr_t*) addr_from);
     const dap_chain_addr_t *addr2 = dap_chain_str_to_addr(addr_str);
     char *addr_str2 = dap_chain_addr_to_str(addr2);
     int a1 = strcmp(addr_str, addr_str2);
     int a2 = strcmp(addr_str, addr_w_bliss);
     int a3 = strcmp(addr_str, addr_w_bliss2);*/

    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_bliss, 0);
        const dap_chain_addr_t *l_addr = dap_chain_wallet_get_addr(wallet_bliss);
        dap_chain_node_datum_tx_cache_init(l_key, l_token_name, (dap_chain_addr_t*) l_addr, 1000);
        l_first_start = false;
    }
    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);

    uint64_t balance2 = dap_chain_datum_tx_cache_calc_balance(addr_to);
    uint64_t balance3 = dap_chain_datum_tx_cache_calc_balance(addr_fee);
    uint64_t balance1 = dap_chain_datum_tx_cache_calc_balance(addr_from);
    dap_string_append_printf(string_ret, "transactions in cache=%d balance w_from=%lld w_to=%lld w_feee=%lld\n",
            dap_chain_node_datum_tx_cache_count(),
            balance1, balance2, balance3);

    int res = dap_chain_datum_tx_ctrl_create_transfer(l_key, addr_from, addr_to, addr_fee, value, value_fee);
    dap_string_append_printf(string_ret, "transfer=%s\n", (res == 1) ? "Ok" : "False");

    if(1) {
        uint64_t balance1 = dap_chain_datum_tx_cache_calc_balance(addr_from);
        uint64_t balance2 = dap_chain_datum_tx_cache_calc_balance(addr_to);
        uint64_t balance3 = dap_chain_datum_tx_cache_calc_balance(addr_fee);
        dap_string_append_printf(string_ret, "transactions in cache=%d balance w_from=%lld w_to=%lld w_feee=%lld\n",
                dap_chain_node_datum_tx_cache_count(),
    char *str_ret_tmp = dap_string_free(string_ret, false);
    char *str_ret = strdup(str_ret_tmp);
    set_reply_text(str_reply, str_ret);
    DAP_DELETE(str_ret_tmp);
    DAP_DELETE(addr_to);
    DAP_DELETE(addr_fee);
    dap_chain_wallet_close(wallet_bliss);
    dap_chain_wallet_close(wallet_bliss2);
    dap_chain_wallet_close(wallet_picnic);
    dap_chain_wallet_close(wallet_tesla);
/**
 * 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]);
        if(cmd)
        {
            if(str_reply)
                *str_reply = dap_strdup(cmd->doc);
            return 1;
        }
        if(str_reply)
            set_reply_text(str_reply, "command \"%s\" not recognized", argv[1]);
        set_reply_text(str_reply, "command not defined, enter \"help <cmd name>\"");