diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c index 7240e64b6c64e7ca89568132c3ab978830ba167d..4b9a26fdd7c761114cd5e0d7dbb1a028b0b85bb0 100644 --- a/modules/common/dap_chain_datum.c +++ b/modules/common/dap_chain_datum.c @@ -381,6 +381,13 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, l_hash_str); DAP_DELETE(l_hash_str); } break; + case TX_ITEM_TYPE_TSD: { + dap_string_append_printf(a_str_out, "\t TSD data: \n" + "\t\t type: %d\n" + "\t\t size: %lu\n", + ((dap_chain_tx_tsd_t*)item)->header.type, + ((dap_chain_tx_tsd_t*)item)->header.size); + } break; case TX_ITEM_TYPE_IN_COND: l_hash_tmp = &((dap_chain_tx_in_cond_t*)item)->header.tx_prev_hash; if (!dap_strcmp(a_hash_out_type, "hex")) diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c index 765b25da21f9ff1655f9778db5bf5a3570d23dc2..9966faaac70549dd80697be96c023b17882252f7 100644 --- a/modules/common/dap_chain_datum_tx_items.c +++ b/modules/common/dap_chain_datum_tx_items.c @@ -105,6 +105,11 @@ static size_t dap_chain_datum_tx_receipt_get_size(const dap_chain_datum_tx_recei return size; } +static size_t dap_chain_tx_tsd_get_size(const dap_chain_tx_tsd_t *a_item) +{ + return sizeof(dap_chain_tx_tsd_t) + a_item->header.size; +} + /** * Get item type by item name * @@ -118,19 +123,21 @@ dap_chain_tx_item_type_t dap_chain_datum_tx_item_str_to_type(const char *a_datum else if(!dap_strcmp(a_datum_name, "out")) return TX_ITEM_TYPE_OUT; else if(!dap_strcmp(a_datum_name, "out_ext")) - return TX_ITEM_TYPE_OUT_EXT; + return TX_ITEM_TYPE_OUT_EXT; else if(!dap_strcmp(a_datum_name, "pkey")) - return TX_ITEM_TYPE_PKEY; + return TX_ITEM_TYPE_PKEY; else if(!dap_strcmp(a_datum_name, "sign")) - return TX_ITEM_TYPE_SIG; + return TX_ITEM_TYPE_SIG; else if(!dap_strcmp(a_datum_name, "token")) - return TX_ITEM_TYPE_TOKEN; + return TX_ITEM_TYPE_TOKEN; else if(!dap_strcmp(a_datum_name, "in_cond")) - return TX_ITEM_TYPE_IN_COND; + return TX_ITEM_TYPE_IN_COND; else if(!dap_strcmp(a_datum_name, "out_cond")) - return TX_ITEM_TYPE_OUT_COND; + return TX_ITEM_TYPE_OUT_COND; else if(!dap_strcmp(a_datum_name, "receipt")) - return TX_ITEM_TYPE_RECEIPT; + return TX_ITEM_TYPE_RECEIPT; + else if(!dap_strcmp(a_datum_name, "data")) + return TX_ITEM_TYPE_TSD; return TX_ITEM_TYPE_UNKNOWN; } @@ -209,6 +216,9 @@ size_t dap_chain_datum_item_tx_get_size(const void *a_item) case TX_ITEM_TYPE_TOKEN: // token item size = dap_chain_tx_token_get_size((const dap_chain_tx_token_t*) a_item); break; + case TX_ITEM_TYPE_TSD: + size = dap_chain_tx_tsd_get_size((const dap_chain_tx_tsd_t*)a_item); + break; default: return 0; } @@ -248,6 +258,24 @@ dap_chain_tx_in_t* dap_chain_datum_tx_item_in_create(dap_chain_hash_fast_t *a_tx return l_item; } +/** + * Create tsd section + */ +dap_chain_tx_tsd_t *dap_chain_datum_tx_item_tsd_create(void *a_data, int a_type, size_t a_size) { + if (!a_data || !a_size) { + return NULL; + } + dap_tsd_t *l_tsd = dap_tsd_create(a_type, a_data, a_size); + size_t l_tsd_sz = dap_tsd_size(l_tsd); + dap_chain_tx_tsd_t *l_item = DAP_NEW_Z_SIZE(dap_chain_tx_tsd_t, + sizeof(dap_chain_tx_tsd_t) + l_tsd_sz); + memcpy(l_item->tsd, l_tsd, l_tsd_sz); + DAP_DELETE(l_tsd); + l_item->header.type = TX_ITEM_TYPE_TSD; + l_item->header.size = l_tsd_sz; + return l_item; +} + /** * @brief dap_chain_datum_tx_item_in_cond_create * @param a_pkey_serialized @@ -422,6 +450,22 @@ dap_sign_t* dap_chain_datum_tx_item_sign_get_sig(dap_chain_tx_sig_t *a_tx_sig) return (dap_sign_t*) a_tx_sig->sig; } +/** + * Get data from tsd section + * @param a_tx_tsd + * @param a_type + * @param a_size + * @return + */ +byte_t *dap_chain_datum_tx_item_get_data(dap_chain_tx_tsd_t *a_tx_tsd, int *a_type, size_t *a_size) { + if (!a_tx_tsd || !a_type || !a_size) + return NULL; + + *a_size = a_tx_tsd->header.size; + *a_type = ((dap_tsd_t*)(a_tx_tsd->tsd))->type; + return ((dap_tsd_t*)(a_tx_tsd->tsd))->data; +} + /** * Get item from transaction * diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h index 41f82afb33bda2959d91e39eaa3b543bd8b66fbd..e038862770f87f2d4ba1b0ccdedf25c98a73a01b 100644 --- a/modules/common/include/dap_chain_common.h +++ b/modules/common/include/dap_chain_common.h @@ -214,6 +214,8 @@ enum dap_chain_tx_item_type { TX_ITEM_TYPE_RECEIPT = 0x70, + TX_ITEM_TYPE_TSD = 0x80, + TX_ITEM_TYPE_IN_ALL = 0xfd, TX_ITEM_TYPE_OUT_ALL = 0xfe, TX_ITEM_TYPE_ANY = 0xff diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h index afb2bae94cb72143c602341b56769d3c0876348d..74299c607e06c7b0dd91cac5d8171e7da3332a4d 100644 --- a/modules/common/include/dap_chain_datum_tx_items.h +++ b/modules/common/include/dap_chain_datum_tx_items.h @@ -41,6 +41,7 @@ #include "dap_chain_datum_tx_pkey.h" #include "dap_chain_datum_tx_token.h" #include "dap_chain_datum_tx_receipt.h" +#include "dap_chain_datum_tx_tsd.h" /** * Get item type @@ -74,6 +75,7 @@ DAP_STATIC_INLINE const char * dap_chain_datum_tx_item_type_to_str(dap_chain_tx_ case TX_ITEM_TYPE_IN_COND: return "TX_ITEM_TYPE_IN_COND"; case TX_ITEM_TYPE_OUT_COND: return "TX_ITEM_TYPE_OUT_COND"; // 256 case TX_ITEM_TYPE_RECEIPT: return "TX_ITEM_TYPE_RECEIPT"; + case TX_ITEM_TYPE_TSD: return "TX_ITEM_TYPE_TSD"; case TX_ITEM_TYPE_OUT_ALL: return "TX_ITEM_TYPE_OUT_OLDALL"; case TX_ITEM_TYPE_ANY: return "TX_ITEM_TYPE_ANY"; default: return "UNDEFINED"; @@ -115,6 +117,8 @@ dap_chain_tx_token_t *dap_chain_datum_tx_item_token_create(dap_chain_id_t a_id, */ dap_chain_tx_in_t* dap_chain_datum_tx_item_in_create(dap_chain_hash_fast_t *a_tx_prev_hash, uint32_t a_tx_out_prev_idx); +dap_chain_tx_tsd_t *dap_chain_datum_tx_item_tsd_create(void *a_data, int a_type, size_t a_size); + dap_chain_tx_in_cond_t* dap_chain_datum_tx_item_in_cond_create(dap_chain_hash_fast_t *a_tx_prev_hash, uint32_t a_tx_out_prev_idx, uint32_t a_receipt_idx); @@ -186,6 +190,8 @@ dap_chain_tx_sig_t *dap_chain_datum_tx_item_sign_create(dap_enc_key_t *a_key, co */ dap_sign_t *dap_chain_datum_tx_item_sign_get_sig(dap_chain_tx_sig_t *a_tx_sig); +byte_t *dap_chain_datum_tx_item_get_data(dap_chain_tx_tsd_t *a_tx_tsd, int *a_type, size_t *a_size); + /** * Get item from transaction * diff --git a/modules/common/include/dap_chain_datum_tx_tsd.h b/modules/common/include/dap_chain_datum_tx_tsd.h new file mode 100644 index 0000000000000000000000000000000000000000..825ce2b953047774404d15560364205d1b66699b --- /dev/null +++ b/modules/common/include/dap_chain_datum_tx_tsd.h @@ -0,0 +1,15 @@ +#pragma once + +#include "dap_common.h" +#include "dap_chain_common.h" +#include "dap_chain_datum_tx.h" +#include "dap_tsd.h" + +typedef struct dap_chain_tx_tsd { + struct { + dap_chain_tx_item_type_t type; + size_t size; + } header; + byte_t tsd[]; +} DAP_ALIGN_PACKED dap_chain_tx_tsd_t; + diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c index e03870d6e6d40b8a0bc81450dbf215849b939d0c..2eaae0e0ae358fcfa479613339c36b03df54c704 100644 --- a/modules/mempool/dap_chain_mempool.c +++ b/modules/mempool/dap_chain_mempool.c @@ -577,7 +577,8 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t * char * l_key_str = dap_chain_hash_fast_to_str_new( l_key_hash ); - char * l_gdb_group = dap_chain_net_get_gdb_group_mempool_by_chain_type(a_net, CHAIN_TYPE_TX); + dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_TX); + char *l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(l_chain); if( dap_global_db_set(l_gdb_group, l_key_str, l_datum, dap_chain_datum_size(l_datum), true, NULL, NULL ) == 0 ) { log_it(L_NOTICE, "Transaction %s placed in mempool", l_key_str); diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 3d0b23899956f9a6f8468280872aa800276e7ff2..d443ceafe5114545e11e662be55af2e9b4933b21 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -2493,7 +2493,7 @@ int com_token_decl_sign(int argc, char ** argv, char ** a_str_reply) // Calc datum's hash l_datum_size = dap_chain_datum_size(l_datum); dap_chain_hash_fast_t l_key_hash={}; - dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_key_hash); + dap_hash_fast(l_datum->data, l_token_size, &l_key_hash); char * l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash); char * l_key_str_base58 = dap_enc_base58_encode_hash_to_str(&l_key_hash); const char * l_key_out_str; @@ -2503,7 +2503,7 @@ int com_token_decl_sign(int argc, char ** argv, char ** a_str_reply) l_key_out_str = l_key_str_base58; // Add datum to mempool with datum_token hash as a key - if( dap_global_db_set_sync(l_gdb_group_mempool, l_key_str, l_datum, l_datum_size, true) == 0) { + if( dap_global_db_set_sync(l_gdb_group_mempool, l_key_str, l_datum, dap_chain_datum_size(l_datum), true) == 0) { char* l_hash_str = l_datum_hash_hex_str; // Remove old datum from pool @@ -2751,6 +2751,24 @@ int com_mempool_delete(int argc, char ** argv, char ** a_str_reply) } } +/** + * @brief s_com_mempool_check_datum_in_chain + * @param a_chain + * @param a_datum_hash_str + * @return boolean + */ +bool s_com_mempool_check_datum_in_chain(dap_chain_t *a_chain, const char *a_datum_hash_str){ + char *l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(a_chain); + uint8_t *l_data_tmp = dap_global_db_get_sync(l_gdb_group_mempool, a_datum_hash_str, NULL, NULL, NULL); + DAP_DELETE(l_gdb_group_mempool); + if (l_data_tmp){ + DAP_DELETE(l_data_tmp); + return true; + } else { + return false; + } +} + /** * @brief com_mempool_check * @param argc @@ -2765,32 +2783,57 @@ int com_mempool_check(int argc, char ** argv, char ** a_str_reply) 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)) + if (dap_chain_node_cli_cmd_values_parse_net_chain(&arg_index, argc, argv, a_str_reply, NULL, &l_net)) return -1; - const char * l_datum_hash_str = NULL; - dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-datum", &l_datum_hash_str); - if(l_datum_hash_str) { - char *l_datum_hash_hex_str = NULL; - // datum hash may be in hex or base58 format - if(dap_strncmp(l_datum_hash_str, "0x", 2) && dap_strncmp(l_datum_hash_str, "0X", 2)) - l_datum_hash_hex_str = dap_enc_base58_to_hex_str_from_str(l_datum_hash_str); - char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); - uint8_t *l_data_tmp = dap_global_db_get_sync(l_gdb_group_mempool, l_datum_hash_hex_str ? l_datum_hash_hex_str : l_datum_hash_str, - NULL, NULL, NULL); - if (l_data_tmp) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s is present in mempool", l_datum_hash_str); - return 0; - } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find datum %s", l_datum_hash_str); + const char *l_chain_str = NULL; + dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-chain", &l_chain_str); + if (l_chain_str) { + l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str); + if (!l_chain) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter '-chain' to be valid chain name in chain net %s. Current chain %s is not valid", + argv[0], l_net->pub.name, l_chain_str); return -4; } - DAP_DELETE(l_gdb_group_mempool); - DAP_DELETE(l_data_tmp); - DAP_DEL_Z(l_datum_hash_hex_str); + } + + if (l_net) { + const char *l_datum_hash_str = NULL; + dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-datum", &l_datum_hash_str); + if (l_datum_hash_str) { + char *l_datum_hash_hex_str = NULL; + // datum hash may be in hex or base58 format + if (dap_strncmp(l_datum_hash_str, "0x", 2) && dap_strncmp(l_datum_hash_str, "0X", 2)) + l_datum_hash_hex_str = dap_enc_base58_to_hex_str_from_str(l_datum_hash_str); + if (l_chain) { + if (s_com_mempool_check_datum_in_chain(l_chain, l_datum_hash_hex_str ? l_datum_hash_hex_str : l_datum_hash_str)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s is present in mempool", l_datum_hash_str); + DAP_DEL_Z(l_datum_hash_hex_str); + return 0; + } else { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find datum %s in %s.%s", l_datum_hash_str, l_net->pub.name, l_chain->name); + DAP_DEL_Z(l_datum_hash_hex_str); + return -4; + } + } else { + DL_FOREACH(l_net->pub.chains, l_chain) + if (s_com_mempool_check_datum_in_chain(l_chain, l_datum_hash_hex_str ? l_datum_hash_hex_str : l_datum_hash_str)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s is present in mempool", l_datum_hash_str); + DAP_DEL_Z(l_datum_hash_hex_str); + return 0; + } + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find datum %s in net %s", l_datum_hash_str, l_net->pub.name); + DAP_DEL_Z(l_datum_hash_hex_str); + return -4; + } + } else { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! %s requires -datum <datum hash> option", argv[0]); + return -3; + } } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Error! %s requires -datum <datum hash> option", argv[0]); - return -3; + dap_cli_server_cmd_set_reply_text(a_str_reply, + "Error! Need both -net <network name> param\n"); + return -2; } } @@ -4707,6 +4750,19 @@ int com_tx_create_json(int a_argc, char ** a_argv, char **a_str_reply) size_t l_params_size = dap_strlen(l_params_str); dap_chain_datum_tx_receipt_t *l_receipt = dap_chain_datum_tx_receipt_create(l_srv_uid, l_price_unit, l_units, l_value, l_params_str, l_params_size); l_item = (const uint8_t*) l_receipt; + } + break; + case TX_ITEM_TYPE_TSD: { + int64_t l_tsd_type; + if(!s_json_get_int64(l_json_item_obj, "type_tsd", &l_tsd_type)) { + break; + } + const char *l_tsd_data = s_json_get_text(l_json_item_obj, "data"); + if (!l_tsd_data) { + break; + } + size_t l_data_size = dap_strlen(l_tsd_data); + l_item = (const uint8_t*)dap_chain_datum_tx_item_tsd_create((void*)l_tsd_data, (int)l_tsd_type, l_data_size); } break; //case TX_ITEM_TYPE_PKEY: @@ -4777,15 +4833,16 @@ int com_tx_create_json(int a_argc, char ** a_argv, char **a_str_reply) char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(l_datum_tx_hash); bool l_placed = dap_global_db_set(l_gdb_group_mempool_base_tx,l_tx_hash_str, l_datum_tx, l_datum_tx_size, true, NULL,NULL ); - DAP_DELETE(l_tx_hash_str); DAP_DELETE(l_datum_tx); DAP_DELETE(l_gdb_group_mempool_base_tx); if(!l_placed) { + DAP_DELETE(l_tx_hash_str); dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't add transaction to mempool"); return -90; } // Completed successfully - dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction with %d items created and added to mempool successfully", l_items_ready); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Transaction %s with %d items created and added to mempool successfully", l_tx_hash_str, l_items_ready); + DAP_DELETE(l_tx_hash_str); return l_err_code; }