Newer
Older
else {
dap_chain_node_cli_set_reply_text(str_reply, "no address found by alias");
}
if(!address.uint64) {
dap_chain_node_cli_set_reply_text(str_reply, "addr not found");
return -1;
}
dap_chain_node_info_t *node_info = dap_chain_node_info_read_and_reply(&address, str_reply);
if(!node_info)
return -1;
int timeout_ms = 10000; //10 sec = 10000 ms
// start handshake
dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info);
if(!client) {
dap_chain_node_cli_set_reply_text(str_reply, "can't connect");
return -1;
}
// wait handshake
int res = dap_chain_node_client_wait(client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
if(res != 1) {
dap_chain_node_cli_set_reply_text(str_reply, "no response from node");
// clean client struct
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 = dap_chain_node_client_list_add(&address, client);
switch (ret)
{
case -1:
dap_chain_node_client_close(client);
dap_chain_node_cli_set_reply_text(str_reply, "connection established, but not saved");
return -1;
case -2:
dap_chain_node_client_close(client);
dap_chain_node_cli_set_reply_text(str_reply, "connection already present");
return -1;
}
dap_chain_node_cli_set_reply_text(str_reply, "connection established");
}
break;
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) {
dap_chain_node_cli_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:
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", (addr) ? addr : "",
(addr) ? "Name or service not known" : "Host not defined");
break;
case 2:
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr,
"Unknown traceroute module");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr, "first hop out of range");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr,
"max hops cannot be more than 255");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr,
"no more than 10 probes per hop");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr,
"bad wait specifications");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr, "too big packetlen ");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr,
"IP version mismatch in addresses specified");
break;
case 9:
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr, "bad sendtime");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr, "init_ip_options");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr, "calloc");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr, "parse cmdline");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error: %s", addr,
"trace method's init failed");
dap_chain_node_cli_set_reply_text(str_reply, "traceroute %s error(%d) %s", addr, res,
"trace not found");
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
}
}
}
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)
dap_chain_node_cli_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:
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", (addr) ? addr : "",
(addr) ? "Name or service not known" : "Host not defined");
break;
case ESOCKTNOSUPPORT:
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't create socket");
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", addr,
"Can't setsockopt IPV6_MTU_DISCOVER");
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", addr,
"Can't setsockopt IPV6_RECVERR");
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", addr,
"Can't setsockopt IPV6_HOPLIMIT");
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", addr,
"Can't setsockopt IP_MTU_DISCOVER");
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", addr,
"Can't setsockopt IP_RECVERR");
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", addr,
"Can't setsockopt IP_RECVTTL");
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", addr, "malloc");
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", addr,
"Can't setsockopt IPV6_UNICAST_HOPS");
dap_chain_node_cli_set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_TTL");
dap_chain_node_cli_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;
dap_chain_node_cli_set_reply_text(str_reply, "host not specified");
int argc_host = 1;
int argc_start = 1;
argc_start = dap_chain_node_cli_find_option_val(argv, argc_start, argc, "-n", &n_str);
if(argc_start) {
argc_host = argc_start + 1;
argc_start = dap_chain_node_cli_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)
dap_chain_node_cli_set_reply_text(str_reply, "ping %s time=%.1lf ms", addr, res * 1. / 1000);
}
else {
if(str_reply) {
switch (-res)
{
case EDESTADDRREQ:
dap_chain_node_cli_set_reply_text(str_reply, "ping %s error: %s", addr, "Destination address required");
dap_chain_node_cli_set_reply_text(str_reply, "ping %s error: %s", (addr) ? addr : "",
(addr) ? "Host not found" : "Host not defined");
break;
case EPFNOSUPPORT:
dap_chain_node_cli_set_reply_text(str_reply, "ping %s error: %s", addr, "Unknown protocol family");
dap_chain_node_cli_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)
log_it(L_DEBUG, "Help for command %s", argv[1]);
dap_chain_node_cmd_item_t *l_cmd = dap_chain_node_cli_cmd_find(argv[1]);
dap_chain_node_cli_set_reply_text(str_reply, "%s:\n%s", l_cmd->doc, l_cmd->doc_ex);
dap_chain_node_cli_set_reply_text(str_reply, "command \"%s\" not recognized", argv[1]);
return -1;
// TODO Read list of commands & return it
log_it(L_DEBUG, "General help requested");
dap_string_t * l_help_list_str = dap_string_new(NULL);
dap_chain_node_cmd_item_t *l_cmd = dap_chain_node_cli_cmd_get_first();
dap_string_printf(l_help_list_str, "");
while(l_cmd) {
dap_string_append_printf(l_help_list_str, "%s:\t\t\t%s\n",
l_cmd->name, l_cmd->doc ? l_cmd->doc : "(undocumented command)");
l_cmd = (dap_chain_node_cmd_item_t*) l_cmd->hh.next;
}
dap_chain_node_cli_set_reply_text(str_reply,
"Available commands:\n\n%s\n",
l_help_list_str->len ? l_help_list_str->str : "NO ANY COMMAND WERE DEFINED");
}
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 = dap_config_get_item_str(g_config, "general", "wallets_path");
// Get address of wallet
enum {
CMD_NONE, CMD_WALLET_NEW, 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(dap_chain_node_cli_find_option_val(argv, arg_index, min(argc, arg_index + 1), "new", NULL)) {
cmd_num = CMD_WALLET_NEW;
}
else if(dap_chain_node_cli_find_option_val(argv, arg_index, min(argc, arg_index + 1), "list", NULL)) {
cmd_num = CMD_WALLET_LIST;
}
else if(dap_chain_node_cli_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) {
"format of command: wallet [new -w <wallet_name> | list | info -addr <addr> -w <wallet_name> -net <net_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, *l_net_name = NULL;
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-addr", &addr_str);
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-w", &wallet_name);
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-net", &l_net_name); // for
dap_string_t *l_string_ret = dap_string_new(NULL);
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
// new wallet
case CMD_WALLET_NEW: {
if(!wallet_name) {
dap_chain_node_cli_set_reply_text(str_reply,
"wallet name option <-w> not defined");
return -1;
}
dap_chain_sign_type_t l_sign_type = { SIG_TYPE_TESLA };
dap_chain_net_id_t l_net_id = { 0x1 };
// Creates new wallet
dap_chain_wallet_t *l_wallet = dap_chain_wallet_create(wallet_name, c_wallets_path, l_net_id, l_sign_type);
dap_chain_addr_t *l_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet);
if(!l_wallet || !l_addr) {
dap_chain_node_cli_set_reply_text(str_reply, "wallet is not created");
return -1;
}
char *l_addr_str = dap_chain_addr_to_str(l_addr);
dap_string_append_printf(l_string_ret, "wallet '%s' successfully created\n", l_wallet->name);
dap_string_append_printf(l_string_ret, "new address %s", l_addr_str);
DAP_DELETE(l_addr_str);
dap_chain_wallet_close(l_wallet);
}
break;
// wallet list
while((l_dir_entry = readdir(l_dir)) != NULL) {
const char *l_file_name = l_dir_entry->d_name;
size_t l_file_name_len = (l_file_name) ? strlen(l_file_name) : 0;
if((l_file_name_len > 8) && (strcmp(l_file_name + l_file_name_len - 8, ".dwallet") == 0)) {
char *l_file_path_tmp = dap_strdup_printf("%s/%s", c_wallets_path, l_file_name);
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_wallet_get_addr(l_wallet);
char *l_addr_str = dap_chain_addr_to_str(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);
}
}
}
break;
// wallet info
case CMD_WALLET_INFO: {
dap_chain_wallet_t *l_wallet = NULL;
dap_chain_addr_t *l_addr = NULL;
if(wallet_name) {
l_wallet = dap_chain_wallet_open(wallet_name, c_wallets_path);
l_addr = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet);
}
if(!l_addr && addr_str)
l_addr = dap_chain_str_to_addr(addr_str);
dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name((const char *) l_net_name);
if(!l_net_name) {
dap_chain_node_cli_set_reply_text(str_reply, "wallet info requires parameter 'net'");
return -1;
}
else {
if((l_ledger = dap_chain_ledger_by_net_name(l_net_name)) == NULL) {
dap_chain_node_cli_set_reply_text(str_reply, "not found net by name '%s'", l_net_name);
return -1;
}
}
char *l_addr_str = dap_chain_addr_to_str((dap_chain_addr_t*) l_addr);
if(l_wallet)
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 : "-");
size_t l_addr_tokens_size = 0;
char **l_addr_tokens = NULL;
dap_chain_ledger_addr_get_token_ticker_all(l_ledger, l_addr, &l_addr_tokens, &l_addr_tokens_size);
dap_string_append_printf(l_string_ret, "balance:\n");
else
dap_string_append_printf(l_string_ret, "balance: 0\n");
for(size_t i = 0; i < l_addr_tokens_size; i++) {
if(l_addr_tokens[i]) {
uint64_t l_balance = dap_chain_ledger_calc_balance(l_ledger, l_addr, l_addr_tokens[i]);
long double l_balance_coins = (long double) l_balance / 1000000000000.0L;
dap_string_append_printf(l_string_ret, " %Lf %s\n", l_balance_coins, l_addr_tokens[i]);
if(l_wallet)
dap_chain_wallet_close(l_wallet);
if(l_wallet)
dap_chain_wallet_close(l_wallet);
dap_string_free(l_string_ret, true);
dap_chain_node_cli_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);
dap_chain_node_cli_set_reply_text(str_reply, str_ret);
/**
* @brief s_values_parse_net_chain
* @param argc
* @param argv
* @param str_reply
* @param l_chain
* @param l_net
* @return
*/
int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int argc, const char ** argv, char ** a_str_reply,
dap_chain_t ** a_chain, dap_chain_net_t ** a_net)
{
const char * l_chain_str = NULL;
const char * l_net_str = NULL;
// Net name
dap_chain_node_cli_find_option_val(argv, *a_arg_index, argc, "-net", &l_net_str);
else
dap_chain_node_cli_set_reply_text(a_str_reply, "%s requires parameter 'net'", argv[0]);
if((*a_net = dap_chain_net_by_name(l_net_str)) == NULL) { // Can't find such network
dap_chain_node_cli_set_reply_text(a_str_reply, "%s cand find network \"%s\"", argv[0], l_net_str);
dap_chain_node_cli_find_option_val(argv, *a_arg_index, argc, "-chain", &l_chain_str);
// Select chain
if(l_chain_str) {
if((*a_chain = dap_chain_net_get_chain_by_name(*a_net, l_chain_str)) == NULL) { // Can't find such chain
dap_chain_node_cli_set_reply_text(a_str_reply,
"%s requires parameter 'chain' to be valid chain name in chain net %s",
argv[0], l_net_str);
}
/**
* @brief com_token_decl_sign
* @param argc
* @param argv
* @param str_reply
* @return
*/
int com_token_decl_sign(int argc, const char ** argv, char ** a_str_reply)
{
int arg_index = 1;
const char * l_datum_hash_str = NULL;
// Chain name
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "datum", &l_datum_hash_str);
const char * l_certs_str = NULL;
dap_chain_cert_t ** l_certs = NULL;
size_t l_certs_size = 0;
dap_chain_t * l_chain;
dap_chain_net_t * l_net = NULL;
if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, a_str_reply, &l_chain, &l_net) < 0)
size_t l_signs_size = dap_chain_cert_parse_str_list(l_certs_str, &l_certs, &l_certs_size);
if(!l_certs_size) {
dap_chain_node_cli_set_reply_text(a_str_reply,
"token_create command requres at least one valid certificate to sign the basic transaction of emission");
return -7;
}
size_t l_certs_count = l_certs_size / sizeof(dap_chain_cert_t *);
char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
log_it(L_DEBUG, "Requested to sign token declaration %s in gdb://%s with certs %s",
l_gdb_group_mempool, l_datum_hash_str, l_certs_str);
dap_chain_datum_t * l_datum = NULL;
size_t l_datum_size = 0;
if((l_datum = (dap_chain_datum_t*) dap_chain_global_db_gr_get(
l_datum_hash_str, &l_datum_size, l_gdb_group_mempool)) != NULL) {
if(l_datum->header.type_id == DAP_CHAIN_DATUM_TOKEN_DECL) {
dap_chain_datum_token_t * l_datum_token = (dap_chain_datum_token_t *) l_datum->data;
size_t l_datum_token_size = l_datum->header.data_size;
size_t l_signs_size = l_datum_token_size - sizeof(l_datum_token->header);
// Check for signatures, are they all in set and are good enought?
size_t l_signs_count = 0;
for(size_t l_offset = 0; l_offset < l_signs_size; l_signs_count++) {
dap_chain_sign_t * l_sign = (dap_chain_sign_t *) l_datum_token->signs + l_offset;
l_offset += dap_chain_sign_get_size(l_sign);
if(dap_chain_sign_verify(l_sign, &l_datum_token->header, sizeof(l_datum_token->header)) != 1) {
log_it(L_WARNING, "Wrong signature for datum_token with key %s in mempool!", l_datum_hash_str);
dap_chain_node_cli_set_reply_text(a_str_reply,
"Datum %s with datum token has wrong signature %u, break process and exit",
l_datum_hash_str, l_signs_count + 1);
DAP_DELETE(l_datum);
DAP_DELETE(l_datum_token);
DAP_DELETE(l_gdb_group_mempool);
return -666;
}
}
log_it(L_DEBUG, "Datum % with token declaration: %u signatures are verified well", l_signs_count);
if(l_signs_count == l_datum_token->header.signs_total) {
dap_chain_node_cli_set_reply_text(a_str_reply,
"Datum %s with datum token has all signs on board. Can't add anything in it");
DAP_DELETE(l_datum);
DAP_DELETE(l_datum_token);
DAP_DELETE(l_gdb_group_mempool);
return -7;
} // Check if more signs that could be (corrupted datum)
else if(l_signs_count > l_datum_token->header.signs_total) {
dap_chain_node_cli_set_reply_text(a_str_reply,
"Warning! Datum %s with datum token has more signs on board (%u) than its possible to have (%u)!",
l_signs_count, l_datum_token->header.signs_total);
DAP_DELETE(l_datum);
DAP_DELETE(l_datum_token);
DAP_DELETE(l_gdb_group_mempool);
return -8;
} // Check if we have enough place to sign the datum token declaration
else if(l_datum_token->header.signs_total - l_signs_count < l_certs_count) {
l_datum = DAP_REALLOC(l_datum, l_datum_size + l_signs_size); // add place for new signatures
size_t l_offset = 0;
for(size_t i = 0; i < l_certs_count; i++) {
dap_chain_sign_t * l_sign = dap_chain_sign_create(l_certs[i]->enc_key,
&l_datum_token->header,
sizeof(l_datum_token->header), 0);
size_t l_sign_size = dap_chain_sign_get_size(l_sign);
if(l_offset + l_sign_size <= l_signs_size) {
memcpy(l_datum_token->signs + l_datum_token_size - sizeof(l_datum_token->header) + l_offset,
l_sign, l_sign_size);
log_it(L_DEBUG, "Added datum token declaration sign with cert %s", l_certs[i]->name);
break;
}
}
l_datum_size += l_signs_size;
// Recalc hash, string and place new datum
// Calc datum's hash
dap_chain_hash_fast_t l_key_hash;
dap_hash_fast(l_datum, l_datum_size, &l_key_hash);
char * l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
// Add datum to mempool with datum_token hash as a key
if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum, l_datum_size, l_gdb_group_mempool)) {
if(dap_chain_global_db_gr_del(l_datum_hash_str, l_gdb_group_mempool)) {
dap_chain_node_cli_set_reply_text(a_str_reply,
"datum %s produced from %s is replacing the %s in datum pool",
l_key_str, l_datum_hash_str, l_datum_hash_str);
DAP_DELETE(l_datum);
DAP_DELETE(l_datum_token);
DAP_DELETE(l_gdb_group_mempool);
dap_chain_node_cli_set_reply_text(a_str_reply,
"Warning! Can't remove old datum %s ( new datum %s added normaly in datum pool)",
l_datum_hash_str, l_key_str);
DAP_DELETE(l_datum);
DAP_DELETE(l_datum_token);
DAP_DELETE(l_gdb_group_mempool);
return 1;
}
}
else {
dap_chain_node_cli_set_reply_text(a_str_reply,
"Error! datum %s produced from %s can't be placed in mempool",
l_key_str, l_datum_hash_str);
DAP_DELETE(l_datum);
DAP_DELETE(l_datum_token);
DAP_DELETE(l_gdb_group_mempool);
return -2;
}
} else {
dap_chain_node_cli_set_reply_text(a_str_reply,
"Error! Not enought place for new signature (%u is left when we need %u signatures)",
l_datum_token->header.signs_total - l_signs_count, l_certs_count);
dap_chain_node_cli_set_reply_text(a_str_reply,
"Error! Wrong datum type. token_decl_sign sign only token declarations datum");
} else {
dap_chain_node_cli_set_reply_text(a_str_reply,
"token_decl_sign can't find datum with %s hash in the mempool of %s:%s", l_net->pub.name,
l_chain->name);
dap_chain_node_cli_set_reply_text(a_str_reply, "token_decl_sign need datum <datum hash> argument");
return -2;
}
}
/**
* @brief com_token_decl_list
* @param argc
* @param argv
* @param str_reply
* @return
*/
int com_mempool_list(int argc, const char ** argv, char ** a_str_reply)
if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, a_str_reply, &l_chain, &l_net) != 0) {
char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
dap_string_t * l_str_tmp = dap_string_new(NULL);
size_t l_objs_size = 0;
dap_global_db_obj_t ** l_objs = dap_chain_global_db_gr_load(l_gdb_group_mempool, &l_objs_size);
dap_string_append_printf(l_str_tmp, "%s.%s: Found %u records :\n", l_net->pub.name, l_chain->name, l_objs_size);
for(size_t i = 0; i < l_objs_size; i++) {
dap_chain_datum_t * l_datum = (dap_chain_datum_t*) l_objs[i]->value;
char buf[50];
time_t l_ts_create = (time_t) l_datum->header.ts_create;
dap_string_append_printf(l_str_tmp, "%s: type_id=%s data_size=%u ts_create=%s",
l_objs[i]->key, c_datum_type_str[l_datum->header.type_id],
l_datum->header.data_size, ctime_r(&l_ts_create, buf));
}
// Clean up
dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
dap_chain_global_db_objs_delete(l_objs);
return 0;
} else {
dap_chain_node_cli_set_reply_text(a_str_reply,
"Error! Need both -net <network name> and -chain <chain name> params\n");
return -2;
}
}
/**
* @brief com_mempool_delete
* @param argc
* @param argv
* @param a_str_reply
* @return
*/
int com_mempool_delete(int argc, const char ** argv, char ** a_str_reply)
{
int arg_index = 1;
dap_chain_t * l_chain = NULL;
dap_chain_net_t * l_net = NULL;
if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, a_str_reply, &l_chain, &l_net) != 0) {
dap_chain_node_cli_set_reply_text(a_str_reply,
"Error! Need both -net <network name> and -chain <chain name> params\n");
const char * l_datum_hash_str = NULL;
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-datum", &l_datum_hash_str);
char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
if(dap_chain_global_db_gr_del(l_datum_hash_str, l_gdb_group_mempool)) {
dap_chain_node_cli_set_reply_text(a_str_reply, "Datum %s deleted", l_datum_hash_str);
return 0;
} else {
dap_chain_node_cli_set_reply_text(a_str_reply, "Error! Can't find datum %s", l_datum_hash_str);
return -4;
} else {
dap_chain_node_cli_set_reply_text(a_str_reply, "Error! %s requires -datum <datum hash> option", argv[0]);
} else {
dap_chain_node_cli_set_reply_text(a_str_reply,
"Error! Need both -net <network name> and -chain <chain name> params\n");
}
/**
* @brief com_mempool_proc
* @param argc
* @param argv
* @param a_str_reply
* @return
*/
int com_mempool_proc(int argc, const char ** argv, char ** a_str_reply)
{
int arg_index = 1;
dap_chain_t * l_chain;
dap_chain_net_t * l_net = NULL;
if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, a_str_reply, &l_chain, &l_net) < 0)
return -1;
char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
size_t l_objs_size = 0;
dap_global_db_obj_t ** l_objs = dap_chain_global_db_gr_load(l_gdb_group_mempool, &l_objs_size);
dap_string_t * l_str_tmp = dap_string_new(NULL);
if(l_objs_size) {
dap_string_append_printf(l_str_tmp, "%s.%s: Found %u records :\n", l_net->pub.name, l_chain->name);
size_t l_datums_size = l_objs_size;
dap_chain_datum_t ** l_datums = DAP_NEW_Z_SIZE(dap_chain_datum_t*, sizeof(dap_chain_datum_t*) * l_datums_size);
for(size_t i = 0; i < l_objs_size; i++) {
dap_chain_datum_t * l_datum = (dap_chain_datum_t*) l_objs[i]->value;
l_datums[i] = l_datum;
char buf[50];
time_t l_ts_create = (time_t) l_datum->header.ts_create;
dap_string_append_printf(l_str_tmp, "0x%s: type_id=%s ts_create=%s data_size=%u\n",
l_objs[i]->key, c_datum_type_str[l_datum->header.type_id],
ctime_r(&l_ts_create, buf), l_datum->header.data_size);
}
size_t l_objs_processed = l_chain->callback_datums_pool_proc(l_chain, l_datums, l_datums_size);
// Delete processed objects
for(size_t i = 0; i < l_objs_processed; i++) {
dap_chain_global_db_gr_del(l_objs[i]->key, l_gdb_group_mempool);
dap_string_append_printf(l_str_tmp, "New event created, removed datum 0x%s from mempool \n",
l_objs[i]->key);
}
dap_chain_global_db_objs_delete(l_objs);
dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
dap_string_free(l_str_tmp, false);
} else {
dap_chain_node_cli_set_reply_text(a_str_reply, "%s.^s: No records in mempool", l_net->pub.name, l_chain->name);
}
return 0;
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
}
/**
* @brief com_token_decl
* @param argc
* @param argv
* @param str_reply
* @return
*/
int com_token_decl(int argc, const char ** argv, char ** str_reply)
{
int arg_index = 1;
const char *str_tmp = NULL;
char *str_reply_tmp = NULL;
const char * l_ticker = NULL;
const char * l_total_supply_str = NULL;
uint64_t l_total_supply = 0;
const char * l_signs_emission_str = NULL;
uint16_t l_signs_emission = 0;
const char * l_signs_total_str = NULL;
uint16_t l_signs_total = 0;
const char * l_certs_str = NULL;
dap_chain_cert_t ** l_certs = NULL;
size_t l_certs_size = 0;
dap_chain_t * l_chain;
dap_chain_net_t * l_net = NULL;
if(dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, str_reply, &l_chain, &l_net) < 0)
return -1;
// Total supply value
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "total_supply", &l_total_supply_str);
// Token ticker
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "token", &l_ticker);
// Certificates thats will be used to sign currend datum token
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "certs", &l_certs_str);
// Signs number thats own emissioncan't find
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "signs_total", &l_signs_total_str);
// Signs minimum number thats need to authorize the emission
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "signs_emission", &l_signs_emission_str);
if(!l_total_supply_str) {
dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'total_supply'");
return -11;
if((l_total_supply = strtoull(l_total_supply_str, &l_tmp, 10)) == 0) {
dap_chain_node_cli_set_reply_text(str_reply,
"token_create requires parameter 'total_supply' to be unsigned integer value that fits in 8 bytes");
return -2;
}
}
// Signs emission
if(!l_signs_emission_str) {
dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'signs_emission'");
return -3;
if((l_signs_emission = (uint16_t) strtol(l_signs_emission_str, &l_tmp, 10)) == 0) {
dap_chain_node_cli_set_reply_text(str_reply,
"token_create requires parameter 'signs_emission' to be unsigned integer value that fits in 2 bytes");
return -4;
}
}
// Signs total
if(!l_signs_total_str) {
dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'signs_total'");
return -31;
if((l_signs_total = (uint16_t) strtol(l_signs_total_str, &l_tmp, 10)) == 0) {
dap_chain_node_cli_set_reply_text(str_reply,
"token_create requires parameter 'signs_total' to be unsigned integer value that fits in 2 bytes");
return -41;
}
}
// Check for ticker
if(!l_ticker) {
dap_chain_node_cli_set_reply_text(str_reply, "token_emit requires parameter 'token'");
return -5;
}
// Check certs list
if(!l_certs_str) {
dap_chain_node_cli_set_reply_text(str_reply, "token_emit requires parameter 'certs'");
return -6;
}
// Load certs lists
size_t l_certs_count = dap_chain_cert_parse_str_list(l_certs_str, &l_certs, &l_certs_size);
if(!l_certs_size) {
dap_chain_node_cli_set_reply_text(str_reply,
"token_create command requres at least one valid certificate to sign the basic transaction of emission");
return -7;
}
// If we have more certs than we need signs - use only first part of the list
l_certs_size = l_signs_total;
// Create new datum token
dap_chain_datum_token_t * l_datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, sizeof(l_datum_token->header));
l_datum_token->header.version = 1; // Current version
snprintf(l_datum_token->header.ticker, sizeof(l_datum_token->header.ticker), "%s", l_ticker);
l_datum_token->header.total_supply = l_total_supply;
l_datum_token->header.signs_total = l_signs_total;
l_datum_token->header.signs_valid = l_signs_emission;
size_t l_signs_offset = 0;
// Sign header with all certificates in the list and add signs to the end of ticker declaration
// Important:
for(size_t i = 0; i < l_certs_size; i++) {
dap_chain_sign_t * l_sign = dap_chain_cert_sign(l_certs[i],
l_datum_token,
sizeof(l_datum_token->header),
0);
size_t l_sign_size = dap_chain_sign_get_size(l_sign);
l_datum_token=DAP_REALLOC(l_datum_token,sizeof (l_datum_token->header)+l_signs_offset +l_sign_size);
memcpy(l_datum_token->signs + l_signs_offset, l_sign, l_sign_size);
dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_DECL, l_datum_token,
size_t l_datum_size = dap_chain_datum_size(l_datum);
// Calc datum's hash
dap_chain_hash_fast_t l_key_hash;
dap_hash_fast(l_datum, l_datum_size, &l_key_hash);
char * l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
// Add datum to mempool with datum_token hash as a key
char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum, l_datum_size, l_gdb_group_mempool)) {
dap_chain_node_cli_set_reply_text(str_reply, "%s\ndatum %s with token %s is placed in datum pool ",
str_reply_tmp, l_key_str, l_ticker);
DAP_DELETE(l_datum);
DAP_DELETE(l_datum_token);
DAP_DELETE(l_gdb_group_mempool);
else {
dap_chain_node_cli_set_reply_text(str_reply, "%s\ndatum tx %s is not placed in datum pool ", str_reply_tmp,
l_key_str);
DAP_DELETE(l_datum);
DAP_DELETE(l_datum_token);
DAP_DELETE(l_gdb_group_mempool);
return -2;
}
}
/**
* @brief com_token_emit
* @param argc
* @param argv
* @param str_reply
* @return
*/
int com_token_emit(int argc, const char ** argv, char ** str_reply)
{
int arg_index = 1;
const char *str_tmp = NULL;
uint64_t l_emission_value = 0;
const char * l_ticker = NULL;
const char * l_addr_str = NULL;
const char * l_certs_str = NULL;
dap_chain_cert_t ** l_certs = NULL;