Newer
Older
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);
// 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_BLISS };
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_addr_from_str(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);
dap_string_append_printf(l_string_ret, "wallet: %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:\u00a00");
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, " %.3Lf (%llu) %s\n", l_balance_coins,
dap_string_append_printf(l_string_ret, "\t\u00a0%.3Lf (%llu) %s", l_balance_coins,
if(i < l_addr_tokens_size - 1)
dap_string_append_printf(l_string_ret, "\n");
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;
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
}
/**
* @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;
const char * l_chain_emission_str = NULL;
dap_chain_t * l_chain_emission = NULL;
const char * l_chain_base_tx_str = NULL;
dap_chain_t * l_chain_base_tx = NULL;
const char * l_net_str = NULL;
dap_chain_net_t * l_net = NULL;
// Wallet address that recieves the emission
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-certs", &l_certs_str);
// Wallet address that recieves the emission
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-addr", &l_addr_str);
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-token", &l_ticker);
if(dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-emission_value", &str_tmp)) {
l_emission_value = strtoull(str_tmp, NULL, 10);
}
if(!l_emission_value) {
dap_chain_node_cli_set_reply_text(str_reply, "token_emit requires parameter '-emission_value'");
return -1;
}
if(!l_addr_str) {
dap_chain_node_cli_set_reply_text(str_reply, "token_emit requires parameter '-addr'");
return -2;
}
if(!l_ticker) {
dap_chain_node_cli_set_reply_text(str_reply, "token_emit requires parameter '-token'");
dap_chain_node_cli_set_reply_text(str_reply, "token_emit requires parameter '-certs'");
dap_chain_cert_parse_str_list(l_certs_str, &l_certs, &l_certs_size);
"token_emit command requres at least one valid certificate to sign the basic transaction of emission");
dap_chain_addr_t * l_addr = dap_chain_addr_from_str(l_addr_str);
dap_chain_node_cli_set_reply_text(str_reply, "address \"%s\" is invalid", l_addr_str);
// Net addr
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-net", &l_net_str);
// Select chain network
if(!l_net_str) {
dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'net'");
return -42;
} else {
if((l_net = dap_chain_net_by_name(l_net_str)) == NULL) { // Can't find such network
dap_chain_node_cli_set_reply_text(str_reply,
"token_create requires parameter '-net' to be valid chain network name");
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-chain_emission", &l_chain_emission_str);
dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-chain_base_tx", &l_chain_base_tx_str);
// Select chain emission
if(!l_chain_emission_str) {
dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter '-chain_emission'");
} else {
if((l_chain_emission = dap_chain_net_get_chain_by_name(l_net, l_chain_emission_str)) == NULL) { // Can't find such chain
dap_chain_node_cli_set_reply_text(str_reply,
"token_create requires parameter 'chain_emission' to be valid chain name in chain net %s",
l_net_str);
// Select chain emission
if(!l_chain_base_tx_str) {
dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'chain_base_tx'");
return -46;
} else {
if((l_chain_base_tx = dap_chain_net_get_chain_by_name(l_net, l_chain_base_tx_str)) == NULL) { // Can't find such chain
dap_chain_node_cli_set_reply_text(str_reply,
"token_create requires parameter 'chain_emission' to be valid chain name in chain net %s",
l_net_str);
char * l_gdb_group_mempool_emission = dap_chain_net_get_gdb_group_mempool(l_chain_emission);
char * l_gdb_group_mempool_base_tx = dap_chain_net_get_gdb_group_mempool(l_chain_base_tx);
dap_chain_datum_token_emission_t * l_token_emission;
size_t l_token_emission_size = sizeof (l_token_emission->hdr) +
sizeof (l_token_emission->data.type_auth.signs_count);
l_token_emission = DAP_NEW_Z_SIZE(dap_chain_datum_token_emission_t, l_token_emission_size);
strncpy(l_token_emission->hdr.ticker, l_ticker, sizeof(l_token_emission->hdr.ticker));
l_token_emission->hdr.value = l_emission_value;
l_token_emission->hdr.type = DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH;
memcpy(&l_token_emission->hdr.address, l_addr, sizeof (l_token_emission->hdr.address));
// Then add signs
size_t l_offset=0;
for (size_t i =0; i < l_certs_size; i++ ){
dap_chain_sign_t * l_sign = dap_chain_cert_sign(l_certs[i],&l_token_emission->hdr, sizeof(l_token_emission->hdr),0 );
size_t l_sign_size = dap_chain_sign_get_size(l_sign);
l_token_emission_size += l_sign_size;
l_token_emission= DAP_REALLOC(l_token_emission, l_token_emission_size);
memcpy(l_token_emission->data.type_auth.signs+l_offset,l_sign,l_sign_size);
l_offset+= l_sign_size;
DAP_DELETE(l_sign);
}
// Produce datum
dap_chain_datum_t * l_datum_emission = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_EMISSION,
size_t l_datum_emission_size = sizeof(l_datum_emission->header) + l_datum_emission->header.data_size;
// Calc datum's hash
dap_chain_hash_fast_t l_datum_emission_hash;