From bbb2163bd97b6f74058f325623cc815bae7e8cd2 Mon Sep 17 00:00:00 2001 From: Roman Khlopkov <roman.khlopkov@demlabs.net> Date: Mon, 25 May 2020 10:20:44 +0300 Subject: [PATCH] [+] Per chain mempool autoprocessing --- modules/chain/dap_chain.c | 27 ++++-- modules/chain/dap_chain_ledger.c | 2 +- modules/chain/include/dap_chain.h | 6 +- modules/net/dap_chain_node.c | 35 +++++-- modules/net/include/dap_chain_node.h | 2 +- .../xchange/dap_chain_net_srv_xchange.c | 95 +++++++++++++++---- .../include/dap_chain_net_srv_xchange.h | 1 + 7 files changed, 125 insertions(+), 43 deletions(-) diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index 27542ad8db..a3d888bfa7 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -188,6 +188,20 @@ dap_chain_t * dap_chain_find_by_id(dap_chain_net_id_t a_chain_net_id,dap_chain_i return NULL; } +dap_chain_type_t dap_chain_type_from_str(const char *a_type_str) +{ + if(!dap_strcmp(a_type_str, "token")) { + return CHAIN_TYPE_TOKEN; + } + if(!dap_strcmp(a_type_str, "emission")) { + return CHAIN_TYPE_EMISSION; + } + if(!dap_strcmp(a_type_str, "transaction")) { + return CHAIN_TYPE_TX; + } + return CHAIN_TYPE_UNKNOWN; +} + /** * @brief dap_chain_load_from_cfg * @param a_chain_net_name @@ -277,16 +291,9 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha l_chain->datum_types = DAP_NEW_SIZE(dap_chain_type_t, l_datum_types_count * sizeof(dap_chain_type_t)); uint16_t l_count_recognized = 0; for(uint16_t i = 0; i < l_datum_types_count; i++) { - if(!dap_strcmp(l_datum_types[i], "token")) { - l_chain->datum_types[l_count_recognized] = CHAIN_TYPE_TOKEN; - l_count_recognized++; - } - else if(!dap_strcmp(l_datum_types[i], "emission")) { - l_chain->datum_types[l_count_recognized] = CHAIN_TYPE_EMISSION; - l_count_recognized++; - } - else if(!dap_strcmp(l_datum_types[i], "transaction")) { - l_chain->datum_types[l_count_recognized] = CHAIN_TYPE_TX; + dap_chain_type_t l_chain_type = dap_chain_type_from_str(l_datum_types[i]); + if (l_chain_type != CHAIN_TYPE_UNKNOWN) { + l_chain->datum_types[l_count_recognized] = l_chain_type; l_count_recognized++; } } diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index ae594fca2e..b8b62b87a1 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -1340,7 +1340,7 @@ uint64_t dap_chain_ledger_calc_balance(dap_ledger_t *a_ledger, const dap_chain_a const char *a_token_ticker) { uint64_t l_ret = 0; - dap_ledger_wallet_balance_t *l_balance_item = NULL ,* l_balance_item_tmp = NULL; + dap_ledger_wallet_balance_t *l_balance_item = NULL;// ,* l_balance_item_tmp = NULL; char *l_addr = dap_chain_addr_to_str(a_addr); char *l_wallet_balance_key = dap_strjoin(" ", l_addr, a_token_ticker, (char*)NULL); diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 8634ef4e11..4de3f01818 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -84,7 +84,8 @@ typedef enum dap_chain_type CHAIN_TYPE_TOKEN, CHAIN_TYPE_EMISSION, CHAIN_TYPE_TX, - CHAIN_TYPE_LAST + CHAIN_TYPE_LAST, + CHAIN_TYPE_UNKNOWN } dap_chain_type_t; typedef struct dap_chain{ @@ -164,5 +165,4 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger,const char * a_chai void dap_chain_delete(dap_chain_t * a_chain); void dap_chain_add_callback_notify(dap_chain_t * a_chain, dap_chain_callback_notify_t a_callback, void * a_arg); - - +dap_chain_type_t dap_chain_type_from_str(const char *a_type_str); diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c index 38cf9d1933..4e49bcd854 100644 --- a/modules/net/dap_chain_node.c +++ b/modules/net/dap_chain_node.c @@ -239,7 +239,7 @@ dap_chain_node_info_t* dap_chain_node_info_read( dap_chain_net_t * a_net,dap_cha return node_info; }*/ -int dap_chain_node_mempool_process(dap_chain_t *a_chain) +int dap_chain_node_mempool_process(dap_chain_t *a_chain, char **a_datum_types, uint16_t a_datum_types_count) { char *l_gdb_group_mempool = NULL; if (!a_chain) { @@ -251,10 +251,27 @@ int dap_chain_node_mempool_process(dap_chain_t *a_chain) if (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; - if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX && - l_datum->header.type_id != DAP_CHAIN_DATUM_TOKEN_EMISSION && - l_datum->header.type_id != DAP_CHAIN_DATUM_TOKEN_DECL) { + bool b_need_process = false; + for (uint16_t j = 0; j < a_datum_types_count; j++) { + if (l_datum->header.type_id == dap_chain_type_from_str(a_datum_types[j]) || + !strcmp(a_datum_types[j], "all")) { + b_need_process = true; + break; + } + } + if (!b_need_process) continue; + if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) { + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data; + dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)dap_chain_datum_tx_item_get(l_tx, NULL, TX_ITEM_TYPE_IN, NULL); + // Is it a base transaction? + if (dap_hash_fast_is_blank(&l_tx_in->header.tx_prev_hash)) { + dap_chain_tx_token_t *l_tx_token = (dap_chain_tx_token_t *)dap_chain_datum_tx_item_get(l_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL); + if (l_tx_token && !dap_chain_ledger_token_emission_find(a_chain->ledger, l_tx_token->header.ticker, + &l_tx_token->header.token_emission_hash)) { + continue; + } + } } if (a_chain->callback_datums_pool_proc(a_chain, &l_datum, 1) != 1) { continue; @@ -292,10 +309,12 @@ void dap_chain_node_mempool_periodic(void *a_param) if (l_mempool_auto) { dap_chain_t *l_chain; DL_FOREACH(l_net_list[i]->pub.chains, l_chain) { - for (uint16_t i = 0; i < l_chain->datum_types_count; i++) { - if (l_chain->datum_types[i] == CHAIN_TYPE_TX) { - dap_chain_node_mempool_process(l_chain); - } + // Read chain datum types + char** l_datum_types = NULL; + uint16_t l_datum_types_count = 0; + l_datum_types = dap_config_get_array_str(g_config, "chain", "mempool_auto_types", &l_datum_types_count); + if (l_datum_types_count) { + dap_chain_node_mempool_process(l_chain, l_datum_types, l_datum_types_count); } } } diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h index 1e5f0b6d7f..aa5db7f462 100644 --- a/modules/net/include/dap_chain_node.h +++ b/modules/net/include/dap_chain_node.h @@ -141,6 +141,6 @@ inline static char* dap_chain_node_addr_to_hash_str(dap_chain_node_addr_t *addre return a_key; } -int dap_chain_node_mempool_process(dap_chain_t *a_chain); +int dap_chain_node_mempool_process(dap_chain_t *a_chain, char **a_datum_types, uint16_t a_datum_types_count); int dap_chain_node_mempool_init(); void dap_chain_node_mempool_deinit(); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 3bf646077c..6214ec8693 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -121,7 +121,20 @@ static bool dap_chain_net_srv_xchange_verificator(dap_chain_tx_out_cond_t *a_con return true; } -static dap_chain_datum_tx_t *s_xchange_create_tx_request(dap_chain_net_srv_xchange_price_t *a_price) +static dap_chain_datum_tx_receipt_t *s_xchage_receipt_create(dap_chain_net_srv_xchange_price_t *a_price) +{ + uint32_t l_ext_size = sizeof(uint64_t) + DAP_CHAIN_TICKER_SIZE_MAX; + uint8_t *l_ext = DAP_NEW_SIZE(uint8_t, l_ext_size); + dap_lendian_put64(l_ext, a_price->datoshi_sell); + strcpy((char *)&l_ext[sizeof(uint64_t)], a_price->token_sell); + dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; + dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; + dap_chain_datum_tx_receipt_t *l_receipt = dap_chain_datum_tx_receipt_create(l_uid, l_unit, 0, a_price->datoshi_buy, + l_ext, l_ext_size); + return l_receipt; +} + +static dap_chain_datum_tx_t *s_xchange_tx_create_request(dap_chain_net_srv_xchange_price_t *a_price) { if (!a_price || !a_price->net_sell || !a_price->net_buy || !*a_price->token_sell || !*a_price->token_buy || !a_price->wallet) { return NULL; @@ -141,7 +154,8 @@ static dap_chain_datum_tx_t *s_xchange_create_tx_request(dap_chain_net_srv_xchan dap_chain_datum_tx_delete(l_tx); log_it(L_WARNING, "Nothing to change (not enough funds)"); return NULL; - } + } + // add 'in' items to sell uint64_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); dap_list_free_full(l_list_used_out, free); @@ -185,7 +199,7 @@ static dap_chain_datum_tx_t *s_xchange_create_tx_request(dap_chain_net_srv_xchan return l_tx; } -static dap_chain_datum_tx_t *s_xchange_create_tx_exchange(dap_chain_net_srv_xchange_price_t *a_price, dap_chain_hash_fast_t *a_tx_cond_hash) +static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xchange_price_t *a_price, dap_chain_hash_fast_t *a_tx_cond_hash) { if (!a_price || !a_price->net_sell || !a_price->net_buy || !*a_price->token_sell || !*a_price->token_buy || !a_price->wallet) { return NULL; @@ -208,14 +222,7 @@ static dap_chain_datum_tx_t *s_xchange_create_tx_exchange(dap_chain_net_srv_xcha } // create and add reciept - uint32_t l_ext_size = sizeof(uint64_t) + DAP_CHAIN_TICKER_SIZE_MAX; - uint8_t *l_ext = DAP_NEW_SIZE(uint8_t, l_ext_size); - dap_lendian_put64(l_ext, a_price->datoshi_sell); - strcpy((char *)&l_ext[sizeof(uint64_t)], a_price->token_sell); - dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; - dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; - dap_chain_datum_tx_receipt_t *l_receipt = dap_chain_datum_tx_receipt_create(l_uid, l_unit, 0, a_price->datoshi_buy, - l_ext, l_ext_size); + dap_chain_datum_tx_receipt_t *l_receipt = s_xchage_receipt_create(a_price); dap_chain_datum_tx_add_item(&l_tx, (byte_t *)l_receipt); DAP_DELETE(l_receipt); // add 'in' items to sell @@ -237,7 +244,6 @@ static dap_chain_datum_tx_t *s_xchange_create_tx_exchange(dap_chain_net_srv_xcha { // transfer selling coins const dap_chain_addr_t *l_buyer_addr = (dap_chain_addr_t *)l_tx_out_cond->params; - uint64_t l_buying_value = l_tx_out_cond->header.value; dap_chain_tx_out_t *l_tx_out = dap_chain_datum_tx_item_out_create(l_buyer_addr, a_price->datoshi_sell, a_price->token_sell); if (l_tx_out) { dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_tx_out); @@ -267,6 +273,7 @@ static dap_chain_datum_tx_t *s_xchange_create_tx_exchange(dap_chain_net_srv_xcha return NULL; } //transfer unbuying coins (partial exchange) + uint64_t l_buying_value = l_tx_out_cond->header.value; l_value_back = l_buying_value - a_price->datoshi_buy; if (l_value_back) { //if (dap_chain_datum_tx_add_out_item(&l_tx, l_buyer_addr, l_value_back) != 1) { @@ -316,6 +323,50 @@ static bool s_xchange_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_net_t *a_net) return true; } +static bool s_xchage_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price) +{ + // create empty transaction + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); + + dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(a_price->net_sell->pub.name); + const dap_chain_addr_t *l_seller_addr = (const dap_chain_addr_t *) dap_chain_wallet_get_addr(a_price->wallet, a_price->net_sell->pub.id); + dap_enc_key_t *l_seller_key = dap_chain_wallet_get_key(a_price->wallet, 0); + + // create and add reciept + dap_chain_datum_tx_receipt_t *l_receipt = s_xchage_receipt_create(a_price); + dap_chain_datum_tx_add_item(&l_tx, (byte_t *)l_receipt); + DAP_DELETE(l_receipt); + + // add 'in' item to buy from conditional transaction + int l_prev_cond_idx = 0; + dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, &a_price->tx_hash); + dap_chain_tx_out_cond_t *l_tx_out_cond = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get( + l_cond_tx, &l_prev_cond_idx, TX_ITEM_TYPE_OUT_COND, NULL); + dap_chain_datum_tx_add_in_cond_item(&l_tx, &a_price->tx_hash, l_prev_cond_idx, 0); + + // add 'out' item +#ifndef NDEBUG + const dap_chain_addr_t *l_buyer_addr = (dap_chain_addr_t *)l_tx_out_cond->params; + assert(l_buyer_addr == l_seller_addr); +#endif + if (dap_chain_datum_tx_add_out_item(&l_tx, l_seller_addr, l_tx_out_cond->header.value)) { + dap_chain_datum_tx_delete(l_tx); + log_it(L_ERROR, "Cant add returning coins output"); + return false; + } + + // add 'sign' items + if(dap_chain_datum_tx_add_sign_item(&l_tx, l_seller_key) != 1) { + dap_chain_datum_tx_delete(l_tx); + log_it( L_ERROR, "Can't add sign output"); + return false; + } + if (!s_xchange_tx_put(l_tx, a_price->net_sell)) { + return false; + } + return true; +} + static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, char **a_str_reply) { enum { @@ -445,7 +496,7 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c l_price->datoshi_sell = l_datoshi_sell; l_price->datoshi_buy = l_datoshi_buy; // Create conditional transaction - dap_chain_datum_tx_t *l_tx = s_xchange_create_tx_request(l_price); + dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_request(l_price); if (!l_tx) { DAP_DELETE(l_price); break; @@ -460,7 +511,7 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c dap_chain_node_addr_t *l_node_addr = dap_chain_net_get_cur_addr(l_price->net_sell); dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; - //TODO add l_net_buy to the order + //TODO add l_net_sell to the order char *l_order_hash_str = dap_chain_net_srv_order_create(l_net_buy, SERV_DIR_SELL, l_uid, *l_node_addr, l_tx_hash, l_datoshi_sell, l_unit, l_price->token_sell, 0, l_ext, l_ext_size, NULL, 0); @@ -473,6 +524,7 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c DAP_DELETE(l_order_hash_str); break; } + memcpy(&l_price->tx_hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t)); dap_chain_node_cli_set_reply_text(a_str_reply, "Successfully created order %s", l_order_hash_str); DAP_DELETE(l_order_hash_str); // Add active price to pricelist @@ -488,15 +540,18 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c HASH_FIND_STR(s_srv_xchange->pricelist, l_strkey, l_price); if (l_price) { if (l_cmd_num == CMD_REMOVE) { + if (!s_xchage_tx_invalidate(l_price)) { + char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_price->tx_hash); + dap_chain_node_cli_set_reply_text(a_str_reply, "Can't invalidate transaction %s", l_tx_hash_str); + DAP_DELETE(l_tx_hash_str); + break; + } + //TODO delete order (l_price->order); HASH_DEL(s_srv_xchange->pricelist, l_price); DAP_DELETE(l_price->key_ptr); - dap_chain_wallet_close(l_price->wallet); - - //TODO invalidate transaction - - //TODO delete order (l_price->order); DAP_DELETE(l_price); + dap_chain_node_cli_set_reply_text(a_str_reply, "Price successfully removed"); } else { // CMD_UPDATE const char *l_val_sell_str = NULL, *l_val_buy_str = NULL, *l_wallet_str = NULL; uint64_t l_datoshi_sell = 0, l_datoshi_buy = 0; @@ -634,7 +689,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void *a_arg_func, char * l_price->datoshi_sell = dap_lendian_get64(l_order->ext); l_price->wallet = l_wallet; // Create conditional transaction - dap_chain_datum_tx_t *l_tx = s_xchange_create_tx_exchange(l_price, &l_order->tx_cond_hash); + dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_exchange(l_price, &l_order->tx_cond_hash); if (l_tx) { s_xchange_tx_put(l_tx, l_net); } diff --git a/modules/service/xchange/include/dap_chain_net_srv_xchange.h b/modules/service/xchange/include/dap_chain_net_srv_xchange.h index 9dc7335842..4592b4491d 100644 --- a/modules/service/xchange/include/dap_chain_net_srv_xchange.h +++ b/modules/service/xchange/include/dap_chain_net_srv_xchange.h @@ -37,6 +37,7 @@ typedef struct dap_chain_net_srv_xchange_price { dap_chain_net_t *net_buy; char token_buy[DAP_CHAIN_TICKER_SIZE_MAX]; uint64_t datoshi_buy; + dap_chain_hash_fast_t tx_hash; dap_chain_hash_fast_t order_hash; char *key_ptr; UT_hash_handle hh; -- GitLab