From d0c2d3967e63df16f9374a8b7b41af42d41d8fa9 Mon Sep 17 00:00:00 2001
From: "roman.khlopkov" <roman.khlopkov@demlabs.net>
Date: Wed, 25 Sep 2024 17:58:21 +0300
Subject: [PATCH] [*] Conditional tx chains/wasting history correction

---
 dap-sdk                                       |   2 +-
 modules/chain/dap_chain_ch.c                  |   2 +-
 modules/common/dap_chain_datum.c              | 330 +-----------------
 modules/common/include/dap_chain_datum.h      |   7 -
 .../consensus/dag-poa/dap_chain_cs_dag_poa.c  |   4 +-
 modules/net/dap_chain_node_cli_cmd.c          |   2 +-
 modules/net/dap_chain_node_cli_cmd_tx.c       |  94 +++--
 .../dap_chain_net_srv_stake_pos_delegate.c    |   2 +-
 .../xchange/dap_chain_net_srv_xchange.c       |   1 -
 modules/type/blocks/dap_chain_cs_blocks.c     |  10 +-
 10 files changed, 71 insertions(+), 383 deletions(-)

diff --git a/dap-sdk b/dap-sdk
index 16bc981375..a2431fb2ba 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit 16bc9813751b728c9b0ad67402198a5749a1ce86
+Subproject commit a2431fb2bac221b9a5393292d02bede1f237a99f
diff --git a/modules/chain/dap_chain_ch.c b/modules/chain/dap_chain_ch.c
index 98eef65ffe..fa7d51339f 100644
--- a/modules/chain/dap_chain_ch.c
+++ b/modules/chain/dap_chain_ch.c
@@ -618,7 +618,7 @@ static bool s_sync_in_chains_callback(void *a_arg)
         DAP_DELETE(l_args);
         return false;
     }
-    char *l_atom_hash_str = NULL;
+    const char *l_atom_hash_str = NULL;
     dap_hash_fast_t l_atom_hash = { }; 
     dap_hash_fast(l_atom, l_atom_size, &l_atom_hash); 
     if (s_debug_more)
diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c
index 8394a83ea5..6031d8db86 100644
--- a/modules/common/dap_chain_datum.c
+++ b/modules/common/dap_chain_datum.c
@@ -198,313 +198,6 @@ void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datu
     }
 }
 
-/**
- * @brief _dap_chain_datum_tx_out_data
- *
- * @param a_datum
- * @param a_ledger
- * @param a_str_out
- * @param a_hash_out_type
- * @param save_processed_tx
- * @param a_tx_hash_processed
- * @param l_tx_num
- */
-bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
-                             const char *a_ticker,
-                             dap_string_t *a_str_out,
-                             const char *a_hash_out_type,
-                             dap_hash_fast_t *a_tx_hash,
-                             dap_chain_net_id_t a_net_id)
-{
-    bool l_is_first = false;
-    dap_chain_tx_in_t *l_in_item = (dap_chain_tx_in_t *)dap_chain_datum_tx_item_get(a_datum, NULL, NULL, TX_ITEM_TYPE_IN, NULL);
-    if (l_in_item && dap_hash_fast_is_blank(&l_in_item->header.tx_prev_hash))
-        l_is_first = true;
-    char l_tmp_buf[DAP_TIME_STR_SIZE];
-    const char *l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-            ? dap_enc_base58_encode_hash_to_str_static(a_tx_hash)
-            : dap_chain_hash_fast_to_str_static(a_tx_hash);
-    dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, a_datum->header.ts_created);
-    dap_string_append_printf(a_str_out, "transaction:%s hash %s\n TS Created: %s%s%s\n Items:\n",
-                             l_is_first ? " (emit)" : "", l_hash_str, l_tmp_buf,
-                             a_ticker ? " Token ticker: " : "", a_ticker ? a_ticker : "");
-    dap_hash_fast_t l_hash_tmp = { };
-    byte_t *item; size_t l_size;
-    TX_ITEM_ITER_TX(item, l_size, a_datum) {
-        switch (*item) {
-        case TX_ITEM_TYPE_IN:
-            l_hash_tmp = ((dap_chain_tx_in_t*)item)->header.tx_prev_hash;
-            l_hash_str = !dap_hash_fast_is_blank(&l_hash_tmp) 
-                ? dap_strcmp(a_hash_out_type, "hex") ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) : dap_chain_hash_fast_to_str_static(&l_hash_tmp)
-                : "BLANK";
-            dap_string_append_printf(a_str_out, "\t IN:\nTx_prev_hash: %s\n"
-                                                "\t\t Tx_out_prev_idx: %u\n",
-                                        l_hash_str,
-                                        ((dap_chain_tx_in_t*)item)->header.tx_out_prev_idx);
-            break;
-        case TX_ITEM_TYPE_OUT_OLD: {
-            const char *l_value_str = dap_uint256_to_char(
-                dap_chain_uint256_from(((dap_chain_tx_out_old_t*)item)->header.value), NULL );
-            dap_string_append_printf(a_str_out, "\t OUT OLD (64):\n"
-                                                "\t\t Value: %s (%"DAP_UINT64_FORMAT_U")\n"
-                                                "\t\t Address: %s\n",
-                                        l_value_str,
-                                        ((dap_chain_tx_out_old_t*)item)->header.value,
-                                        dap_chain_addr_to_str_static(&((dap_chain_tx_out_old_t*)item)->addr));
-        } break;
-        case TX_ITEM_TYPE_OUT: { // 256
-            const char *l_coins_str,
-                    *l_value_str = dap_uint256_to_char(((dap_chain_tx_out_t*)item)->header.value, &l_coins_str),
-                    *l_addr_str = dap_chain_addr_to_str_static(&((dap_chain_tx_out_t*)item)->addr);
-            dap_string_append_printf(a_str_out, "\t OUT:\n"
-                                                "\t\t Value: %s (%s)\n"
-                                                "\t\t Address: %s\n",
-                                        l_coins_str,
-                                        l_value_str,
-                                        l_addr_str);
-        } break;
-        case TX_ITEM_TYPE_IN_EMS: {
-            l_hash_tmp = ((dap_chain_tx_in_ems_t*)item)->header.token_emission_hash;
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
-                    : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-            dap_string_append_printf(a_str_out, "\t IN_EMS:\n"
-                                                "\t\t ticker: %s \n"
-                                                "\t\t token_emission_hash: %s\n"
-                                                "\t\t token_emission_chain_id: 0x%016"DAP_UINT64_FORMAT_x"\n",
-                                                ((dap_chain_tx_in_ems_t*)item)->header.ticker,
-                                                l_hash_str,
-                                                ((dap_chain_tx_in_ems_t*)item)->header.token_emission_chain_id.uint64);
-        } break;
-            /*
-        case TX_ITEM_TYPE_IN_EMS_EXT: {
-            l_hash_tmp = &((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_hash;
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str(l_hash_tmp)
-                    : dap_chain_hash_fast_to_str_new(l_hash_tmp);
-            dap_string_append_printf(a_str_out, "\t IN_EMS EXT:\n"
-                                         "\t\t Version: %u\n"
-                                         "\t\t Ticker: %s\n"
-                                         "\t\t Ext chain id: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                         "\t\t Ext net id: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                         "\t\t Ext tx hash: %s\n"
-                                         "\t\t Ext tx out idx: %u\n",
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.version,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ticker,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_chain_id.uint64,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_net_id.uint64,
-                                     l_hash_str,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_out_idx);
-            DAP_DELETE(l_hash_str);
-        } break; */
-
-        case TX_ITEM_TYPE_IN_REWARD: {
-            l_hash_tmp = ((dap_chain_tx_in_reward_t *)item)->block_hash;
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
-                    : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-            dap_string_append_printf(a_str_out, "\t IN_REWARD:\n"
-                                                "\t\t block_hash: %s\n",
-                                                l_hash_str);
-        } break;
-
-        case TX_ITEM_TYPE_SIG: {
-            dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t*)item);
-            dap_sign_get_information(l_sign, a_str_out, a_hash_out_type);
-            dap_chain_addr_t l_sender_addr;
-            dap_chain_addr_fill_from_sign(&l_sender_addr, l_sign, a_net_id);
-            dap_string_append_printf(a_str_out, "\tSender addr: %s\n", dap_chain_addr_to_str_static(&l_sender_addr));
-        } break;
-        case TX_ITEM_TYPE_RECEIPT: {
-            const char *l_coins_str, *l_value_str = dap_uint256_to_char(((dap_chain_datum_tx_receipt_t*)item)->receipt_info.value_datoshi, &l_coins_str);
-            dap_string_append_printf(a_str_out, "\t Receipt:\n"
-                                                "\t\t size: %"DAP_UINT64_FORMAT_U"\n"
-                                                "\t\t ext size: %"DAP_UINT64_FORMAT_U"\n"
-                                                "\t\t Info:"
-                                                "\t\t\t units: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                                "\t\t\t uid: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                                "\t\t\t units type: %s \n"
-                                                "\t\t\t value: %s (%s)\n",
-                                     ((dap_chain_datum_tx_receipt_t*)item)->size,
-                                     ((dap_chain_datum_tx_receipt_t*)item)->exts_size,
-                                     ((dap_chain_datum_tx_receipt_t*)item)->receipt_info.units,
-                                     ((dap_chain_datum_tx_receipt_t*)item)->receipt_info.srv_uid.uint64,
-                                     dap_chain_srv_unit_enum_to_str(((dap_chain_datum_tx_receipt_t*)item)->receipt_info.units_type.enm),
-                                     l_coins_str,
-                                     l_value_str);
-            dap_string_append_printf(a_str_out, "Exts:\n");                         
-            switch ( ((dap_chain_datum_tx_receipt_t*)item)->exts_size ) {
-            case (sizeof(dap_sign_t) * 2): {
-                dap_sign_t *l_client = DAP_CAST_PTR( dap_sign_t, ((dap_chain_datum_tx_receipt_t*)item)->exts_n_signs + sizeof(dap_sign_t) );
-                dap_string_append_printf(a_str_out, "   Client:\n");
-                dap_sign_get_information(l_client, a_str_out, a_hash_out_type);
-            }
-            case (sizeof(dap_sign_t)): {
-                dap_sign_t *l_provider = DAP_CAST_PTR( dap_sign_t, ((dap_chain_datum_tx_receipt_t*)item)->exts_n_signs );
-                dap_string_append_printf(a_str_out, "   Provider:\n");
-                dap_sign_get_information(l_provider, a_str_out, a_hash_out_type);
-                break;
-            }
-            }
-        } break;
-        case TX_ITEM_TYPE_PKEY: {
-            dap_pkey_t *l_pkey = (dap_pkey_t*)((dap_chain_tx_pkey_t*)item)->pkey;
-            dap_chain_hash_fast_t l_pkey_hash;
-            dap_hash_fast(l_pkey->pkey, l_pkey->header.size, &l_pkey_hash);
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str_static(&l_pkey_hash)
-                    : dap_chain_hash_fast_to_str_static(&l_pkey_hash);
-            dap_string_append_printf(a_str_out, "\t PKey: \n"
-                                                "\t\t SIG type: %s\n"
-                                                "\t\t SIG size: %u\n"
-                                                "\t\t Sequence number: %u \n"
-                                                "\t\t Key: \n"
-                                                "\t\t\t Type: %s\n"
-                                                "\t\t\t Size: %u\n"
-                                                "\t\t\t Hash: %s\n",
-                                     dap_sign_type_to_str(((dap_chain_tx_pkey_t*)item)->header.sig_type),
-                                     ((dap_chain_tx_pkey_t*)item)->header.sig_size,
-                                     ((dap_chain_tx_pkey_t*)item)->seq_no,
-                                     dap_pkey_type_to_str(l_pkey->header.type),
-                                     l_pkey->header.size,
-                                     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;
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
-                    : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-            dap_string_append_printf(a_str_out, "\t IN COND:\n\t\tReceipt_idx: %u\n"
-                                                "\t\t Tx_prev_hash: %s\n"
-                                                "\t\t Tx_out_prev_idx: %u\n",
-                                     ((dap_chain_tx_in_cond_t*)item)->header.receipt_idx,
-                                     l_hash_str,
-                                     ((dap_chain_tx_in_cond_t*)item)->header.tx_out_prev_idx);
-            break;
-        case TX_ITEM_TYPE_OUT_COND: {
-            const char *l_coins_str, *l_value_str = dap_uint256_to_char(((dap_chain_tx_out_cond_t*)item)->header.value, &l_coins_str);
-            dap_time_t l_ts_exp = ((dap_chain_tx_out_cond_t*)item)->header.ts_expires;
-            dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_ts_exp);
-            dap_string_append_printf(a_str_out, "\t OUT COND:\n"
-                                                "\t Header:\n"
-                                                "\t\t ts_expires: %s"
-                                                "\t\t value: %s (%s)\n"
-                                                "\t\t subtype: %s\n"
-                                                "\t\t uid: 0x%016"DAP_UINT64_FORMAT_x"\n",
-                                     l_ts_exp ? l_tmp_buf : "never\n", l_coins_str, l_value_str,
-                                     dap_chain_tx_out_cond_subtype_to_str(((dap_chain_tx_out_cond_t*)item)->header.subtype),
-                                     ((dap_chain_tx_out_cond_t*)item)->header.srv_uid.uint64);
-            switch (((dap_chain_tx_out_cond_t*)item)->header.subtype) {
-                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: {
-                    const char *l_coins_str, *l_value_str =
-                        dap_uint256_to_char( ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit_price_max_datoshi, &l_coins_str );
-                    l_hash_tmp = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.pkey_hash;
-                    l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                            ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
-                            : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-                    dap_string_append_printf(a_str_out, "\t\t\t unit: 0x%08x\n"
-                                                        "\t\t\t pkey: %s\n"
-                                                        "\t\t\t max price: %s (%s)\n",
-                                             ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit.uint32,
-                                             l_hash_str,
-                                             l_coins_str,
-                                             l_value_str);
-                } break;
-                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: {
-                    dap_chain_node_addr_t *l_signer_node_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signer_node_addr;
-                    dap_chain_addr_t *l_signing_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signing_addr;
-                    l_hash_tmp = l_signing_addr->data.hash_fast;
-                    l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                            ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
-                            : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-                    dap_string_append_printf(a_str_out, "\t\t\t signing_addr: %s\n"
-                                                        "\t\t\t with pkey hash %s\n"
-                                                        "\t\t\t signer_node_addr: "NODE_ADDR_FP_STR"\n",
-                                                        dap_chain_addr_to_str_static(l_signing_addr),
-                                                        l_hash_str,
-                                                        NODE_ADDR_FP_ARGS(l_signer_node_addr));
-                } break;
-                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: {
-                    const char *l_rate_str, *l_tmp_str =
-                        dap_uint256_to_char( (((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.rate), &l_rate_str );
-                    dap_string_append_printf(a_str_out, "\t\t\t net id: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                                        "\t\t\t buy_token: %s\n"
-                                                        "\t\t\t rate: %s\n",
-                                             ((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_net_id.uint64,
-                                             ((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_token,
-                                             l_rate_str);
-                } break;
-                case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: {
-                    dap_time_t l_ts_unlock = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_lock.time_unlock;
-                    dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_ts_unlock);
-                    dap_string_append_printf(a_str_out, "\t\t\t time_unlock %s\n", l_tmp_buf);
-                } break;
-                default: break;
-            }
-        } break;
-        case TX_ITEM_TYPE_OUT_EXT: {
-            const char *l_coins_str, *l_value_str = dap_uint256_to_char( ((dap_chain_tx_out_ext_t*)item)->header.value, &l_coins_str);
-            dap_string_append_printf(a_str_out, "\t OUT EXT:\n"
-                                                "\t\t Addr: %s\n"
-                                                "\t\t Token: %s\n"
-                                                "\t\t Value: %s (%s)\n",
-                                     dap_chain_addr_to_str_static(&((dap_chain_tx_out_ext_t*)item)->addr),
-                                     ((dap_chain_tx_out_ext_t*)item)->token,
-                                     l_coins_str,
-                                     l_value_str);
-        } break;
-        case TX_ITEM_TYPE_VOTING:{
-            size_t l_tsd_size = 0;
-            dap_chain_tx_tsd_t *l_item = (dap_chain_tx_tsd_t *)dap_chain_datum_tx_item_get(a_datum, NULL, (byte_t*)item + l_size, TX_ITEM_TYPE_TSD, &l_tsd_size);
-            if (!l_item || !l_tsd_size)
-                    break;
-            dap_chain_datum_tx_voting_params_t *l_voting_params = dap_chain_voting_parse_tsd(a_datum);
-            dap_string_append_printf(a_str_out, "\t VOTING:\n\tVoting question: %s\n\t Answer options:\n", l_voting_params->voting_question);
-            dap_list_t *l_temp = l_voting_params->answers_list;
-            uint8_t l_index = 0;
-            while (l_temp){
-                    dap_string_append_printf(a_str_out, "\t\t %i) %s\n", l_index, (char*)l_temp->data);
-                    l_index++;
-                    l_temp = l_temp->next;
-            }
-
-            if (l_voting_params->voting_expire) {
-                dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_voting_params->voting_expire);
-                dap_string_append_printf(a_str_out, "\t Voting expire: %s\n", l_tmp_buf);
-            }
-            if (l_voting_params->votes_max_count)
-                    dap_string_append_printf(a_str_out, "\t Votes max count: %"DAP_UINT64_FORMAT_U"\n", l_voting_params->votes_max_count);
-            dap_string_append_printf(a_str_out, "\t Changing vote is %s available.\n", l_voting_params->vote_changing_allowed ? "" : "not");
-            dap_string_append_printf(a_str_out, "\t A delegated key is%s required to participate in voting. \n",
-                                     l_voting_params->delegate_key_required ? "" : " not");
-
-            dap_list_free_full(l_voting_params->answers_list, NULL);
-            DAP_DELETE(l_voting_params->voting_question);
-            DAP_DELETE(l_voting_params);
-        } break;
-        case TX_ITEM_TYPE_VOTE:{
-            dap_chain_tx_vote_t *l_vote_item = (dap_chain_tx_vote_t *)item;
-            const char *l_hash_str = dap_chain_hash_fast_to_str_static(&l_vote_item->voting_hash);
-            dap_string_append_printf(a_str_out, "\t VOTE: \n"
-                                                "\t Voting hash: %s\n"
-                                                "\t Vote answer idx: %"DAP_UINT64_FORMAT_U"\n", l_hash_str, l_vote_item->answer_idx);
-        } break;
-        default:
-            dap_string_append_printf(a_str_out, " This transaction have unknown item type \n");
-            break;
-        }
-    }
-    dap_string_append_printf(a_str_out, "\n");
-    return true;
-}
-
 /**
  * @brief _dap_chain_datum_tx_out_data
  *
@@ -583,27 +276,6 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum,
             sprintf(l_tmp_buff,"0x%016"DAP_UINT64_FORMAT_x"",((dap_chain_tx_in_ems_t*)item)->header.token_emission_chain_id.uint64);
             json_object_object_add(json_obj_item,"token_emission_chain_id", json_object_new_string(l_tmp_buff));
         } break;
-            /*
-        case TX_ITEM_TYPE_IN_EMS_EXT: {
-            l_hash_tmp = &((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_hash;
-            l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-                    ? dap_enc_base58_encode_hash_to_str(l_hash_tmp)
-                    : dap_chain_hash_fast_to_str_new(l_hash_tmp);
-            dap_string_append_printf(a_str_out, "\t IN_EMS EXT:\n"
-                                         "\t\t Version: %u\n"
-                                         "\t\t Ticker: %s\n"
-                                         "\t\t Ext chain id: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                         "\t\t Ext net id: 0x%016"DAP_UINT64_FORMAT_x"\n"
-                                         "\t\t Ext tx hash: %s\n"
-                                         "\t\t Ext tx out idx: %u\n",
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.version,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ticker,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_chain_id.uint64,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_net_id.uint64,
-                                     l_hash_str,
-                                     ((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_out_idx);
-            DAP_DELETE(l_hash_str);
-        } break; */
 
         case TX_ITEM_TYPE_IN_REWARD: {
             l_hash_tmp = ((dap_chain_tx_in_reward_t *)item)->block_hash;
@@ -678,7 +350,7 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum,
             l_hash_str = dap_strcmp(a_hash_out_type, "hex")
                     ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp)
                     : dap_chain_hash_fast_to_str_static(&l_hash_tmp);
-            json_object_object_add(json_obj_item,"Receipt_idx", json_object_new_uint64(((dap_chain_tx_in_cond_t*)item)->header.receipt_idx));
+            json_object_object_add(json_obj_item,"Receipt_idx", json_object_new_int(((dap_chain_tx_in_cond_t*)item)->header.receipt_idx));
             json_object_object_add(json_obj_item,"Tx_prev_hash", json_object_new_string(l_hash_str));
             json_object_object_add(json_obj_item,"Tx_out_prev_idx", json_object_new_uint64(((dap_chain_tx_in_cond_t*)item)->header.tx_out_prev_idx));
             break;
diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h
index 8227287524..a384070e65 100644
--- a/modules/common/include/dap_chain_datum.h
+++ b/modules/common/include/dap_chain_datum.h
@@ -159,13 +159,6 @@ DAP_STATIC_INLINE const char *dap_chain_datum_type_id_to_str(uint16_t a_type_id)
 }
 
 void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datum_token_t *a_token, size_t a_token_size, const char *a_hash_out_type);
-void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, const char *a_hash_out_type, dap_chain_net_id_t a_net_id);
-bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
-                             const char *a_ticker,
-                             dap_string_t *a_str_out,
-                             const char *a_hash_out_type,
-                             dap_hash_fast_t *a_tx_hash,
-                             dap_chain_net_id_t a_net_id);
 bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum,
                              const char *a_ticker,
                              json_object* json_obj_out,
diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
index c8523c0bd1..4661961f05 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -798,8 +798,8 @@ static int s_callback_event_round_sync(dap_chain_cs_dag_t * a_dag, const char a_
     if (!l_event)
         return log_it(L_CRITICAL, "Memory allocation failed"), -1;
 
-    if ( dap_chain_cs_dag_event_sign_exists(l_event, l_event_size, l_poa_pvt->events_sign_cert->enc_key)
-        || dap_chain_cs_dag_event_round_sign_exists(l_round_item, l_poa_pvt->events_sign_cert->enc_key)
+    if ( (dap_chain_cs_dag_event_sign_exists(l_event, l_event_size, l_poa_pvt->events_sign_cert->enc_key)
+        || dap_chain_cs_dag_event_round_sign_exists(l_round_item, l_poa_pvt->events_sign_cert->enc_key))
         && l_poa_pvt->auto_round_complete
         && s_round_event_ready_minimum_check(a_dag, l_event, l_event_size, (char*)a_key) )
     {
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index ecd031bae9..db540b5e5d 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -8262,7 +8262,7 @@ static int s_signer_cmd(int a_arg_index, int a_argc, char **a_argv, void **a_str
     dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_SIGNER, l_sign->pkey_n_sign, l_sign->header.sign_size);
     if (!l_datum)
         return dap_cli_server_cmd_set_reply_text(a_str_reply, "not created datum"), -1;
-    dap_cli_server_cmd_set_reply_text(a_str_reply, "hash: %s", dap_get_data_hash_str(l_datum->data, l_datum->header.data_size));
+    dap_cli_server_cmd_set_reply_text(a_str_reply, "hash: %s", dap_get_data_hash_str(l_datum->data, l_datum->header.data_size).s);
     return DAP_DELETE(l_datum), l_chain->callback_add_datums(l_chain, &l_datum, 1);
 }
 
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index 2475ddd5d2..63287032b1 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -343,9 +343,6 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
 
     dap_chain_addr_t  l_net_fee_addr = {};
     bool l_net_fee_used = dap_chain_net_tx_get_fee(l_net->pub.id, NULL, &l_net_fee_addr);
-    bool l_is_need_correction = false;
-    bool l_continue = false;
-    uint256_t l_corr_value = {}, l_unstake_value = {};    
     bool look_for_unknown_service = (a_srv && strcmp(a_srv,"unknown") == 0);
     size_t l_arr_start = 0;
     size_t l_arr_end = 0;
@@ -372,12 +369,15 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
     {
         if (i_tmp >= l_arr_end)
             break;
-        json_object *l_corr_object = NULL;
         if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX)
             // go to next datum
             continue;        
         // it's a transaction        
-        bool l_is_unstake = false;
+        bool l_is_need_correction = false;
+        bool l_continue = false;
+        uint256_t l_corr_value = {}, l_cond_value = {};
+        bool l_recv_from_cond = false, l_send_to_same_cond = false;
+        json_object *l_corr_object = NULL, *l_cond_recv_object = NULL, *l_cond_send_object = NULL;
         dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data;
         dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN_ALL, NULL);
         if (!l_list_in_items) // a bad tx
@@ -441,10 +441,8 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
                     if (l_cond_prev->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE)
                         l_noaddr_token = l_native_ticker;
                     else {
-                        if (l_cond_prev->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK) {
-                            l_is_unstake = true;
-                            l_unstake_value = l_cond_prev->header.value;
-                        }
+                        l_recv_from_cond = true;
+                        l_cond_value = l_cond_prev->header.value;
                         l_noaddr_token = l_src_token;
                     }
                 } break;
@@ -535,26 +533,20 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
                 SUM_256_256(l_fee_sum, l_value, &l_fee_sum);
             
             //tag
-            char *service_name = NULL;
+            const char *l_service_name = NULL;
             dap_chain_tx_tag_action_type_t l_action;
             bool srv_found = l_datum_iter->uid.uint64 ? true : false;
             l_action = l_datum_iter->action;
-            service_name = dap_ledger_tx_action_str(l_action);
+            l_service_name = dap_ledger_tx_action_str(l_action);
             if (!(l_action & a_action))
                 continue;
-            if (a_srv)
-            {
-              
+            if (a_srv) {
                 //skip if looking for UNKNOWN + it is known
-                if (look_for_unknown_service && srv_found) {
-                    continue;
-                }
-                            
+                if (look_for_unknown_service && srv_found)
+                    continue;                    
                 //skip if search condition provided, it not UNKNOWN and found name not match
-                if (!look_for_unknown_service && (!srv_found || strcmp(service_name, a_srv) != 0))
-                {
+                if (!look_for_unknown_service && (!srv_found || strcmp(l_service_name, a_srv) != 0))
                     continue;
-                }
             }
 
             if (l_dst_addr && dap_chain_addr_compare(l_dst_addr, a_addr)) {  
@@ -578,8 +570,8 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
                     l_src_str = dap_chain_addr_to_str_static(l_src_addr);
                 else
                     l_src_str = dap_chain_tx_out_cond_subtype_to_str(l_src_subtype);
-                if (l_is_unstake)
-                    l_value = l_unstake_value;
+                if (l_recv_from_cond)
+                    l_value = l_cond_value;
                 else if (!dap_strcmp(l_native_ticker, l_noaddr_token)) {
                     l_is_need_correction = true;
                     l_corr_value = l_value;
@@ -599,10 +591,12 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
                 json_object_object_add(j_obj_data, "token", l_dst_token ? json_object_new_string(l_dst_token)
                                                                             : json_object_new_string("UNKNOWN"));
                 json_object_object_add(j_obj_data, "source_address", json_object_new_string(l_src_str));
-                if (l_is_need_correction)
-                    l_corr_object = j_obj_data;
+                if (l_recv_from_cond && !l_cond_recv_object)
+                    l_cond_recv_object = j_obj_data;
                 else
                     json_object_array_add(j_arr_data, j_obj_data);
+                if (l_is_need_correction)
+                    l_corr_object = j_obj_data;
                 
             } else if (!l_src_addr || dap_chain_addr_compare(l_src_addr, a_addr)) {
                 if (!l_dst_addr && ((dap_chain_tx_out_cond_t *)it->data)->header.subtype == l_src_subtype && l_src_subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE)
@@ -623,9 +617,15 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
                     l_src_token ? l_tx_ledger_accepted++ : l_tx_ledger_rejected++;
                 }
 
-                const char *l_dst_addr_str = l_dst_addr ? dap_chain_addr_to_str_static(l_dst_addr)
-                                                        : dap_chain_tx_out_cond_subtype_to_str(
-                                                              ((dap_chain_tx_out_cond_t *)it->data)->header.subtype);
+                const char *l_dst_addr_str = NULL;
+                if (l_dst_addr)
+                    l_dst_addr_str = dap_chain_addr_to_str_static(l_dst_addr);
+                else {
+                    dap_chain_tx_out_cond_subtype_t l_dst_subtype = ((dap_chain_tx_out_cond_t *)it->data)->header.subtype;
+                    l_dst_addr_str = dap_chain_tx_out_cond_subtype_to_str(l_dst_subtype);
+                    if (l_recv_from_cond && l_dst_subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE && l_dst_subtype == l_src_subtype)
+                        l_send_to_same_cond = true;
+                }
                 const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_value, &l_coins_str);
                                 
                 json_object * j_obj_data = json_object_new_object();
@@ -641,22 +641,46 @@ json_object* dap_db_history_addr(dap_chain_addr_t *a_addr, dap_chain_t *a_chain,
                 json_object_object_add(j_obj_data, "token", l_dst_token ? json_object_new_string(l_dst_token)
                                                                         : json_object_new_string("UNKNOWN"));
                 json_object_object_add(j_obj_data, "destination_address", json_object_new_string(l_dst_addr_str));
-                json_object_array_add(j_arr_data, j_obj_data);                
+                if (l_send_to_same_cond && !l_cond_send_object)
+                    l_cond_send_object = j_obj_data;
+                else
+                    json_object_array_add(j_arr_data, j_obj_data);
             }
         }  
-        if (l_continue){
-            l_continue = false;
+        if (l_continue)
             continue;
-        }
 
-        if (l_is_need_correction && l_corr_object) {
+        if (l_is_need_correction) {
             SUM_256_256(l_corr_value, l_fee_sum, &l_corr_value);
             const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_corr_value, &l_coins_str);
             json_object_object_add(l_corr_object, "recv_coins", json_object_new_string(l_coins_str));
             json_object_object_add(l_corr_object, "recv_datoshi", json_object_new_string(l_value_str));
-            json_object_array_add(j_arr_data, l_corr_object);
-            l_is_need_correction = false;
         }
+        if (l_send_to_same_cond) {
+            json_object *l_cond_recv_value_obj = json_object_object_get(l_cond_recv_object, "recv_datoshi");
+            const char *l_cond_recv_value_str = json_object_get_string(l_cond_recv_value_obj);
+            uint256_t l_cond_recv_value = dap_uint256_scan_uninteger(l_cond_recv_value_str);
+            json_object *l_cond_send_value_obj = json_object_object_get(l_cond_send_object, "send_datoshi");
+            const char *l_cond_send_value_str = json_object_get_string(l_cond_send_value_obj);
+            uint256_t l_cond_send_value = dap_uint256_scan_uninteger(l_cond_send_value_str);
+            assert(!IS_ZERO_256(l_cond_recv_value) && !IS_ZERO_256(l_cond_send_value));
+            int l_direction = compare256(l_cond_recv_value, l_cond_send_value);
+            if (l_direction > 0) {
+                SUBTRACT_256_256(l_cond_recv_value, l_cond_send_value, &l_cond_recv_value);
+                const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_cond_recv_value, &l_coins_str);
+                json_object_object_add(l_cond_recv_object, "recv_coins", json_object_new_string(l_coins_str));
+                json_object_object_add(l_cond_recv_object, "recv_datoshi", json_object_new_string(l_value_str));
+                json_object_array_add(j_arr_data, l_cond_recv_object);
+            } else if (l_direction < 0) {
+                SUBTRACT_256_256(l_cond_send_value, l_cond_recv_value, &l_cond_send_value);
+                const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_cond_send_value, &l_coins_str);
+                json_object_object_add(l_cond_send_object, "send_coins", json_object_new_string(l_coins_str));
+                json_object_object_add(l_cond_send_object, "send_datoshi", json_object_new_string(l_value_str));
+                json_object_array_add(j_arr_data, l_cond_send_object);
+            }
+        } else if (l_recv_from_cond)
+            json_object_array_add(j_arr_data, l_cond_recv_object);
+
         if (json_object_array_length(j_arr_data) > 0) {
             json_object_object_add(j_obj_tx, "data", j_arr_data);
             json_object_array_add(json_obj_datum, j_obj_tx);
diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
index 6ae42e529b..a416bab7dd 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
@@ -464,10 +464,10 @@ void dap_chain_net_srv_stake_key_update(dap_chain_addr_t *a_signing_addr, uint25
     if (!l_stake)
         return; // It's update for non delegated key, it's OK
     HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake);
+    char *l_old_value_str = dap_chain_balance_to_coins(l_stake->locked_value);
     l_stake->locked_value = l_stake->value = a_new_value;
     l_stake->tx_hash = *a_new_tx_hash;
     HASH_ADD(ht, l_srv_stake->tx_itemlist, tx_hash, sizeof(dap_hash_fast_t), l_stake);
-    char *l_old_value_str = dap_chain_balance_to_coins(l_stake->locked_value);
     const char *l_new_value_str; dap_uint256_to_char(a_new_value, &l_new_value_str);
     log_it(L_NOTICE, "Updated key with fingerprint %s and locked value %s to new locked value %s for node " NODE_ADDR_FP_STR,
                             dap_chain_hash_fast_to_str_static(&a_signing_addr->data.hash_fast), l_old_value_str,
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index 7e8c19c190..c0a630dc67 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -1773,7 +1773,6 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str,
                                          tx_opt_status_t a_filter_by_status,
                                          bool a_print_prev_hash, bool a_print_status, bool a_print_ts)
 {
-    enum{TX_TYPE_NONE, TX_TYPE_ORDER, TX_TYPE_EXCHANGE, TX_TYPE_INVALIDATE};
     size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx);
 
     dap_hash_fast_t l_tx_hash = {0};
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index fe85e5a88e..8bd80468bb 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -476,7 +476,7 @@ static void s_cli_meta_hex_print(json_object* a_json_obj_out, const char * a_met
 {
     int l_len = a_meta->hdr.data_size * 2 + 5;
     char *l_str = DAP_NEW_STACK_SIZE(char, l_len);
-    snprintf(l_str, 2, "0x");
+    strcpy(l_str, "0x");
     dap_bin2hex(l_str + 2, a_meta->data, a_meta->hdr.data_size);
     json_object_object_add(a_json_obj_out, a_meta_title, json_object_new_string(l_str));
 }
@@ -759,7 +759,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                     json_object_object_add(json_obj_meta, "# -", json_object_new_string(l_hexbuf));
                     int l_len = l_meta->hdr.data_size * 2 + 5;
                     char *l_data_hex = DAP_NEW_STACK_SIZE(char, l_len);
-                    snprintf(l_data_hex, 2, "0x");
+                    strcpy(l_data_hex, "0x");
                     dap_bin2hex(l_data_hex + 2, l_meta->data, l_meta->hdr.data_size);
                     json_object_object_add(json_obj_meta, "Data hex - ", json_object_new_string(l_data_hex)); }
                 }
@@ -1185,9 +1185,9 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply)
                 : dap_chain_mempool_tx_reward_create(l_blocks, l_cert->enc_key, l_addr, l_block_list, l_fee_value, l_hash_out_type);
             if (l_hash_tx) {
                 json_object* json_obj_out = json_object_new_object();
-                char *l_val = dap_strdup_printf(l_val, "TX for %s collection created successfully, hash = %s\n", l_subcmd_str, l_hash_tx);
-                json_object_object_add(json_obj_out, "status", json_object_new_string(l_val));
-                DAP_DELETE(l_val);
+                char *l_val = dap_strdup_printf("TX for %s collection created successfully, hash = %s\n", l_subcmd_str, l_hash_tx);
+                json_object_object_add(json_obj_out, "status", json_object_new_string(l_val ? l_val : "(null)"));
+                DAP_DEL_Z(l_val);
                 json_object_array_add(*json_arr_reply, json_obj_out);
                 DAP_DELETE(l_hash_tx);
             } else {
-- 
GitLab