Newer
Older
DAP_DELETE(node_info);
return -1;
}
// wait handshake
int res = 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;
}
//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");
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
}
}
}
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]);
if(l_cmd){
dap_chain_node_cli_set_reply_text(str_reply, "%s:\n%s", l_cmd->doc, l_cmd->doc_ex);
return 0;
}else {
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_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), "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) {
dap_chain_node_cli_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
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_string_t *l_string_ret = dap_string_new(NULL);
switch (cmd_num) {
// wallet list
case CMD_WALLET_LIST: {
DIR * l_dir = opendir(c_wallets_path);
if( l_dir ) {
struct dirent * l_dir_entry;
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);
if(l_addr) {
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_utxo_addr_get_token_ticker_all(l_addr, &l_addr_tokens, &l_addr_tokens_size);
if(l_addr_tokens_size>0)
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 balance = dap_chain_utxo_calc_balance(l_addr, l_addr_tokens[i]);
dap_string_append_printf(l_string_ret, " %llu %s\n", balance, 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 s_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);
dap_chain_node_cli_find_option_val(argv, *a_arg_index, argc, "-chain", &l_chain_str);
// Select chain network
if(!l_net_str) {
dap_chain_node_cli_set_reply_text(a_str_reply, "%s requires parameter 'net'",argv[0]);
return -42;
}else {
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);
return -43;
}
}
// Select chain
if(!l_chain_str) {
dap_chain_node_cli_set_reply_text(a_str_reply, "%s requires parameter 'chain'",argv[0]);
return -44;
}else {
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);
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
return -45;
}
}
return 0;
}
/**
* @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);
if ( 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 ( s_values_parse_net_chain(&arg_index,argc,argv,a_str_reply,&l_chain, &l_net) < 0 )
return -1;
// Load certs lists
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 ) {
// Check if its token declaration
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);
// Check if all signs are present
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);
}
DAP_DELETE( l_sign);
l_offset += l_sign_size;
if (l_offset > l_signs_size ){
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 )) {
// Remove old datum from pool
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);
return 0;
} else {
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 );
return -6;
}
} else {
dap_chain_node_cli_set_reply_text(a_str_reply, "Error! Wrong datum type. token_decl_sign sign only token declarations datum");
return -61;
}
}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);
return -5;
}
}else {
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)
{
int arg_index = 1;
dap_chain_t * l_chain;
dap_chain_net_t * l_net = NULL;
if (s_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);
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
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);
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,"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 );
}
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);
return 0;
}
/**
* @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 (s_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;
1671
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
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
}
/**
* @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 (s_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;
}else {
char * l_tmp = NULL;
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;
}else {
char * l_tmp = NULL;
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;
}else {
char * l_tmp = NULL;
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_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(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
if (l_certs_size > l_signs_total )
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_signs_size);
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);
memcpy(l_datum_token->signs+l_signs_offset,l_sign,l_sign_size);
DAP_DELETE(l_sign);
}
dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_DECL,l_datum_token,
sizeof (l_datum_token->header)+ l_signs_size);
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);
return 0;
}
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;
size_t l_certs_size = 0;
const char * l_chain_str = NULL;
dap_chain_t * l_chain;
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'");
// Load 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_str_to_addr(l_addr_str);
dap_chain_node_cli_set_reply_text(str_reply, "address \"%s\" is invalid", l_addr_str);
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
// 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");
return -43;
}
}
// Select chain
if(!l_chain_str) {
dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'chain'");
return -44;
}else {
if ( ( l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str ) ) == NULL ){ // Can't find such chain
dap_chain_node_cli_set_reply_text(str_reply, "token_create requires parameter 'chain' to be valid chain name in chain net %s",l_net_str);
return -45;
}
}
// Get mempool group for this chain
char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
// Create emission datum
dap_chain_datum_token_emission_t * l_token_emission;
dap_chain_hash_fast_t l_token_emission_hash;
l_token_emission = DAP_NEW_Z(dap_chain_datum_token_emission_t);
strncpy(l_token_emission->ticker, l_ticker, sizeof(l_token_emission->ticker));
l_token_emission->value = l_emission_value;
dap_hash_fast(l_token_emission, sizeof(dap_chain_datum_token_emission_t), &l_token_emission_hash);
dap_chain_datum_t * l_datum_emission = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_EMISSION,
l_token_emission,
sizeof(dap_chain_datum_token_emission_t));
size_t l_datum_emission_size = sizeof(l_datum_emission->header) + l_datum_emission->header.data_size;
dap_hash_fast(l_datum_emission, l_datum_emission_size, &l_key_hash);
char * l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
// Add to mempool emission token
if(dap_chain_global_db_gr_set(l_key_str, (uint8_t *) l_datum_emission, l_datum_emission_size
str_reply_tmp = dap_strdup_printf("datum emission %s is placed in datum pool ", l_key_str);
dap_chain_node_cli_set_reply_text(str_reply, "datum emission %s is not placed in datum pool ", l_key_str);
return -1;
}
DAP_DELETE(l_key_str);
// create first transaction (with tx_token)
dap_chain_datum_tx_t *l_tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, sizeof(dap_chain_datum_tx_t));
dap_chain_hash_fast_t l_tx_prev_hash = { 0 };
dap_chain_hash_fast_t l_datum_token_hash = { 0 };
// create items
dap_chain_tx_token_t *l_tx_token = dap_chain_datum_tx_item_token_create(&l_token_emission_hash, l_ticker);
dap_chain_tx_in_t *l_in = dap_chain_datum_tx_item_in_create(&l_tx_prev_hash, 0);
dap_chain_tx_out_t *l_out = dap_chain_datum_tx_item_out_create(l_addr, l_emission_value);
// pack items to transaction
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_tx_token);
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_in);
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_out);
// Sign all that we have with certs
for(size_t i = 0; i < l_certs_size; i++)
dap_chain_datum_tx_add_sign_item(&l_tx, l_certs[i]->enc_key);
DAP_DELETE(l_certs);
DAP_DELETE(l_tx_token);
DAP_DELETE(l_in);
DAP_DELETE(l_out);
size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx);
// Pack transaction into the datum
dap_chain_datum_t * l_datum_tx = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, l_tx_size);
size_t l_datum_tx_size = dap_chain_datum_size(l_datum_tx);