From 033d5fbecf00328ce0dd0db5f5edb1881b614d63 Mon Sep 17 00:00:00 2001
From: Pavel Uhanov <pavel.uhanov@demlabs.net>
Date: Wed, 26 Feb 2025 14:00:25 +0300
Subject: [PATCH 01/25] [*] error nums fix

---
 modules/chain/dap_chain_policy.c          |  2 ++
 modules/net/dap_chain_net.c               | 25 ++++++++++++++++-------
 modules/node-cli/dap_chain_node_cli_cmd.c | 11 +++++++---
 3 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/modules/chain/dap_chain_policy.c b/modules/chain/dap_chain_policy.c
index 5f68706931..df8b9f8bf3 100644
--- a/modules/chain/dap_chain_policy.c
+++ b/modules/chain/dap_chain_policy.c
@@ -147,6 +147,7 @@ int dap_chain_policy_add(dap_chain_policy_t *a_policy, uint64_t a_net_id)
  */
 int dap_chain_policy_add_to_exception_list(uint32_t a_policy_num, uint64_t a_net_id)
 {
+    dap_return_val_if_pass(!a_policy_num, -1);
     struct policy_net_list_item *l_net_item = s_net_find(a_net_id);
     if (!l_net_item) {
         log_it(L_ERROR, "Can't find net %"DAP_UINT64_FORMAT_X" in policy list", a_net_id);
@@ -212,6 +213,7 @@ bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id)
  */
 dap_chain_policy_t *dap_chain_policy_find(uint32_t a_policy_num, uint64_t a_net_id)
 {
+    dap_return_val_if_pass(!a_policy_num, NULL);
     struct policy_net_list_item *l_net_item = s_net_find(a_net_id);
     dap_return_val_if_pass(!l_net_item, NULL);
     if (l_net_item->last_num_policy < a_policy_num)
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index a32dfbcdbd..8cc8f09335 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -774,19 +774,30 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg)
         return NULL;
     }
     // activate policy
-    uint32_t l_policy_num = dap_config_get_item_uint32(a_cfg, "policy", "activate");
+    uint64_t l_policy_num = dap_config_get_item_uint64(a_cfg, "policy", "activate");
+    dap_chain_policy_t *l_new_policy = NULL;
     if (l_policy_num) {
-        dap_chain_policy_t *l_new_policy = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_policy_t, NULL, l_ret->pub.name, l_ret); 
-        l_new_policy->version = DAP_CHAIN_POLICY_VERSION;
-        l_new_policy->activate.num = l_policy_num;
-        l_new_policy->activate.flags = DAP_FLAG_ADD(l_new_policy->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG);
-        dap_chain_policy_add(l_new_policy, l_ret->pub.id.uint64);
+        if (l_policy_num > dap_maxuval(l_new_policy->activate.num)) {
+            log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U", maxval %u", l_policy_num, dap_maxuval(l_new_policy->activate.num));
+        } else {
+            dap_chain_policy_t *l_new_policy = NULL;
+            l_new_policy = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_policy_t, NULL, l_ret->pub.name, l_ret); 
+            l_new_policy->version = DAP_CHAIN_POLICY_VERSION;
+            l_new_policy->activate.num = l_policy_num;
+            l_new_policy->activate.flags = DAP_FLAG_ADD(l_new_policy->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG);
+            dap_chain_policy_add(l_new_policy, l_ret->pub.id.uint64);
+        }
     }
     // deactivate policy
     uint16_t l_policy_count = 0;
     const char **l_policy_str = dap_config_get_array_str(a_cfg, "policy", "deactivate", &l_policy_count);
     for (uint16_t i = 0; i < l_policy_count; ++i) {
-        dap_chain_policy_add_to_exception_list(strtoll(l_policy_str[i], NULL, 10), l_ret->pub.id.uint64);
+        l_policy_num = strtoull(l_policy_str[i], NULL, 10);
+        if (l_policy_num > dap_maxuval(l_new_policy->activate.num)) {
+            log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list, maxval %u", l_policy_num, dap_maxuval(l_new_policy->activate.num));
+        } else {
+            dap_chain_policy_add_to_exception_list(l_policy_num, l_ret->pub.id.uint64);
+        }
     }
     
     l_ret->pub.config = a_cfg;
diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index bd940670a7..b5d79746dd 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -5966,8 +5966,13 @@ int com_policy(int argc, char **argv, void **reply) {
     uint32_t l_last_num = dap_chain_policy_get_last_num(l_net->pub.id.uint64);
 
     if (l_cmd == CMD_FIND) {
-        uint32_t l_policy_num = strtoull(l_num_str, NULL, 10);
-        dap_chain_policy_t *l_policy = dap_chain_policy_find(l_policy_num, l_net->pub.id.uint64);
+        dap_chain_policy_t *l_policy = NULL;
+        uint64_t l_policy_num = strtoull(l_num_str, NULL, 10);
+        if (l_policy_num > dap_maxuval(l_policy->activate.num)) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -16, "Can't find policy CN-%"DAP_UINT64_FORMAT_U", maxval %u", l_policy_num, dap_maxuval(l_policy->activate.num));
+            return -16;
+        }
+        l_policy = dap_chain_policy_find(l_policy_num, l_net->pub.id.uint64);
         if (!l_policy) {
             if (l_last_num < l_policy_num) {
                 dap_json_rpc_error_add(*a_json_arr_reply, -15, "Can't find policy CN-%u in net %s", l_policy_num, l_net_str);
@@ -6025,7 +6030,7 @@ int com_policy(int argc, char **argv, void **reply) {
 
     l_policy->deactivate.count = l_deactivate_count;
     for (size_t i = 0; i < l_deactivate_count; ++i) {
-        l_policy->deactivate.nums[i] = strtoul(l_deactivate_array[i], NULL, 10);
+        l_policy->deactivate.nums[i] = strtoull(l_deactivate_array[i], NULL, 10);
     }
     dap_strfreev(l_deactivate_array);
 
-- 
GitLab


From 88b12f21b7466a733d26c2eb67e801a4ac42e1c4 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Thu, 27 Feb 2025 07:57:11 +0300
Subject: [PATCH 02/25] [*] use BIT macross

---
 modules/chain/include/dap_chain_policy.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/modules/chain/include/dap_chain_policy.h b/modules/chain/include/dap_chain_policy.h
index e526e42671..a4bdd86898 100644
--- a/modules/chain/include/dap_chain_policy.h
+++ b/modules/chain/include/dap_chain_policy.h
@@ -29,9 +29,9 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 
 #define DAP_CHAIN_POLICY_VERSION                1
 
-#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS            1
-#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM     (1 << 1)
-#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG        (1 << 2)
+#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS            BIT(0)
+#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM     BIT(1)
+#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG        BIT(2)
 
 #define DAP_CHAIN_POLICY_PUBLIC_KEY_HASH_SIGN_VALIDATORS    0x1
 #define DAP_CHAIN_POLICY_OUT_EXT_USE_ENSURE                 0x2
-- 
GitLab


From 0e114e802c046901ea6d0b112ffab05b488e9b98 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Thu, 27 Feb 2025 07:33:39 +0300
Subject: [PATCH 03/25] [+] add func dap_chain_policy_num_is_valid

---
 modules/chain/include/dap_chain_policy.h  | 11 ++++++++
 modules/net/dap_chain_net.c               |  4 +--
 modules/node-cli/dap_chain_node_cli_cmd.c | 32 ++++++++++++++---------
 3 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/modules/chain/include/dap_chain_policy.h b/modules/chain/include/dap_chain_policy.h
index a4bdd86898..2498bebe83 100644
--- a/modules/chain/include/dap_chain_policy.h
+++ b/modules/chain/include/dap_chain_policy.h
@@ -71,3 +71,14 @@ DAP_STATIC_INLINE size_t dap_chain_policy_get_size(dap_chain_policy_t *a_policy)
 {
     return a_policy ? a_policy->deactivate.count * sizeof(uint32_t) + sizeof(dap_chain_policy_t) : 0;
 }
+
+/**
+ * @brief check policy num
+ * @param a_num
+ * @return true if valid, fail if not
+ */
+DAP_STATIC_INLINE bool dap_chain_policy_num_is_valid(uint64_t a_num)
+{
+    uint32_t l_num = dap_maxval(l_num);
+    return (a_num && a_num <= l_num);
+}
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 8cc8f09335..fa8e25035f 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -777,7 +777,7 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg)
     uint64_t l_policy_num = dap_config_get_item_uint64(a_cfg, "policy", "activate");
     dap_chain_policy_t *l_new_policy = NULL;
     if (l_policy_num) {
-        if (l_policy_num > dap_maxuval(l_new_policy->activate.num)) {
+        if (!dap_chain_policy_num_is_valid(l_policy_num)) {
             log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U", maxval %u", l_policy_num, dap_maxuval(l_new_policy->activate.num));
         } else {
             dap_chain_policy_t *l_new_policy = NULL;
@@ -793,7 +793,7 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg)
     const char **l_policy_str = dap_config_get_array_str(a_cfg, "policy", "deactivate", &l_policy_count);
     for (uint16_t i = 0; i < l_policy_count; ++i) {
         l_policy_num = strtoull(l_policy_str[i], NULL, 10);
-        if (l_policy_num > dap_maxuval(l_new_policy->activate.num)) {
+        if (!dap_chain_policy_num_is_valid(l_policy_num)) {
             log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list, maxval %u", l_policy_num, dap_maxuval(l_new_policy->activate.num));
         } else {
             dap_chain_policy_add_to_exception_list(l_policy_num, l_ret->pub.id.uint64);
diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index b5d79746dd..54558c7ad9 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -5963,21 +5963,21 @@ int com_policy(int argc, char **argv, void **reply) {
         return -7;
     }
 
+    dap_chain_policy_t *l_policy = NULL;
+    uint64_t l_policy_num = strtoull(l_num_str, NULL, 10);
+    if (!dap_chain_policy_num_is_valid(l_policy_num)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy num sould be less or equal than %u and not equal 0", dap_maxval(l_policy->activate.num));
+    }
+
     uint32_t l_last_num = dap_chain_policy_get_last_num(l_net->pub.id.uint64);
 
     if (l_cmd == CMD_FIND) {
-        dap_chain_policy_t *l_policy = NULL;
-        uint64_t l_policy_num = strtoull(l_num_str, NULL, 10);
-        if (l_policy_num > dap_maxuval(l_policy->activate.num)) {
-            dap_json_rpc_error_add(*a_json_arr_reply, -16, "Can't find policy CN-%"DAP_UINT64_FORMAT_U", maxval %u", l_policy_num, dap_maxuval(l_policy->activate.num));
-            return -16;
+        if (l_last_num < l_policy_num) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -15, "Can't find policy CN-%u in net %s", l_policy_num, l_net_str);
+            return -15;
         }
         l_policy = dap_chain_policy_find(l_policy_num, l_net->pub.id.uint64);
         if (!l_policy) {
-            if (l_last_num < l_policy_num) {
-                dap_json_rpc_error_add(*a_json_arr_reply, -15, "Can't find policy CN-%u in net %s", l_policy_num, l_net_str);
-                return -15;
-            }
             dap_chain_policy_t l_to_print = {
                 .activate.num = l_policy_num
             };
@@ -6013,7 +6013,7 @@ int com_policy(int argc, char **argv, void **reply) {
         }
     }
 
-    if (strtoull(l_num_str, NULL, 10) == l_last_num) {
+    if (l_policy_num == l_last_num) {
         dap_json_rpc_error_add(*a_json_arr_reply, -15, "Specified policy num already existed");
         return -15;
     }
@@ -6023,14 +6023,20 @@ int com_policy(int argc, char **argv, void **reply) {
         l_deactivate_count = dap_str_symbol_count(l_deactivate_str, ',') + 1;
         l_deactivate_array = dap_strsplit(l_deactivate_str, ",", l_deactivate_count);
     }
-    dap_chain_policy_t *l_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + l_deactivate_count * sizeof(uint32_t), -5);
+    
+    l_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + l_deactivate_count * sizeof(uint32_t), -5);
     
     l_policy->version = DAP_CHAIN_POLICY_VERSION;
-    l_policy->activate.num = strtoull(l_num_str, NULL, 10);
+    l_policy->activate.num = l_policy_num;
 
     l_policy->deactivate.count = l_deactivate_count;
     for (size_t i = 0; i < l_deactivate_count; ++i) {
-        l_policy->deactivate.nums[i] = strtoull(l_deactivate_array[i], NULL, 10);
+        l_policy_num = strtoull(l_deactivate_array[i], NULL, 10);
+        if (!dap_chain_policy_num_is_valid(l_policy_num)) {
+            log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list, maxval %u", l_policy_num, dap_maxuval(l_policy->activate.num));
+            continue;
+        }
+        l_policy->deactivate.nums[i] = l_policy_num;
     }
     dap_strfreev(l_deactivate_array);
 
-- 
GitLab


From 3f65ed44085c91469f1e14ccdd5d4b63e3a3af31 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Thu, 27 Feb 2025 07:45:22 +0300
Subject: [PATCH 04/25] [*] fix deactivate num error

---
 modules/node-cli/dap_chain_node_cli_cmd.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index 54558c7ad9..36231da086 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -6034,6 +6034,7 @@ int com_policy(int argc, char **argv, void **reply) {
         l_policy_num = strtoull(l_deactivate_array[i], NULL, 10);
         if (!dap_chain_policy_num_is_valid(l_policy_num)) {
             log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list, maxval %u", l_policy_num, dap_maxuval(l_policy->activate.num));
+            --l_policy->deactivate.count;
             continue;
         }
         l_policy->deactivate.nums[i] = l_policy_num;
-- 
GitLab


From 7d3c53f6de9c4d7667618fb6ab18b540ea442ed6 Mon Sep 17 00:00:00 2001
From: Pavel Uhanov <pavel.uhanov@demlabs.net>
Date: Wed, 26 Feb 2025 07:54:04 +0000
Subject: [PATCH 05/25] [*] fix not native token

---
 .../dap_chain_net_srv_emit_delegate.c         | 72 ++++++++++++-------
 1 file changed, 45 insertions(+), 27 deletions(-)

diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index 465ebb9e37..b120d0b15a 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -308,33 +308,46 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o
 {
     dap_return_val_if_pass(!a_net || IS_ZERO_256(a_value) || IS_ZERO_256(a_fee), NULL);
     // create empty transaction
-    dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
-
     dap_ledger_t *l_ledger = a_net->pub.ledger;
     const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, a_tx_in_hash);
-    bool l_taking_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker);
-
-    uint256_t l_value = a_value, l_value_transfer = {}; // how many coins to refill
+    bool l_refill_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker);
+    uint256_t l_value = a_value, l_value_transfer = {}, l_fee_transfer = {}; // how many coins to transfer
     uint256_t l_net_fee, l_fee_total = a_fee;
     dap_chain_addr_t l_net_fee_addr;
+    // create empty transaction
+    dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
 
     bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr);
     if (l_net_fee_used && SUM_256_256(l_fee_total, l_net_fee, &l_fee_total))
         m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
-    if (SUM_256_256(l_value, l_fee_total, &l_value))
+    if (l_refill_native && SUM_256_256(l_value, l_fee_total, &l_value))
         m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
 
+    // list of transaction with 'out' items to sell
     dap_chain_addr_t l_owner_addr;
     dap_chain_addr_fill_from_key(&l_owner_addr, a_enc_key, a_net->pub.id);
-    dap_list_t *l_list_fee_out = dap_chain_wallet_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker,
-                            &l_owner_addr, l_value, &l_value_transfer);
-    if (!l_list_fee_out)
-        m_tx_fail(ERROR_FUNDS, "Nothing to pay for fee (not enough funds)");
-    // add 'in' items to pay fee
-    uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out);
-    dap_list_free_full(l_list_fee_out, NULL);
-    if (!EQUAL_256(l_value_fee_items, l_value_transfer))
-        m_tx_fail(ERROR_COMPOSE, "Can't compose the fee transaction input");
+    dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_tx_ticker,
+                                                                       &l_owner_addr, l_value, &l_value_transfer);
+    if (!l_list_used_out)
+        m_tx_fail(ERROR_FUNDS, "Nothing to pay for delegate (not enough funds)");
+
+    // add 'in' items to pay for delegate
+    uint256_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, NULL);
+    if (!EQUAL_256(l_value_to_items, l_value_transfer))
+        m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction input");
+
+    if (!l_refill_native) {
+        dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker,
+                                                                          &l_owner_addr, l_fee_total, &l_fee_transfer);
+        if (!l_list_fee_out)
+            m_tx_fail(ERROR_FUNDS, "Nothing to pay for fee (not enough funds)");
+        // add 'in' items to pay fee
+        uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out);
+        dap_list_free_full(l_list_fee_out, NULL);
+        if (!EQUAL_256(l_value_fee_items, l_fee_transfer))
+            m_tx_fail(ERROR_COMPOSE, "Can't compose the fee transaction input");
+    }
 
     dap_hash_fast_t l_final_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, a_tx_in_hash, false);
     if (dap_hash_fast_is_blank(&l_final_tx_hash))
@@ -357,7 +370,6 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o
         m_tx_fail(ERROR_COMPOSE, "Cant add conditionsl input");
     }
 
-    // coin back
     uint256_t l_value_back = {};
     if(SUM_256_256(l_cond_prev->header.value, a_value, &l_value_back)) {
         m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
@@ -388,24 +400,30 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o
         m_tx_fail(ERROR_COMPOSE, "Can't add custom TSD section item ");
     }
 
+// coin back
+    SUBTRACT_256_256(l_value_transfer, l_value, &l_value_back);
+    if (!IS_ZERO_256(l_value_back)) {
+        int rc = l_refill_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_value_back)
+                                   : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_value_back, l_tx_ticker);
+        if (rc != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add coin back output");
+    }
+
     // add fee items
     if (l_net_fee_used) {
-        int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_net_fee_addr, l_net_fee)
-        : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker);
+        int rc = l_refill_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_net_fee_addr, l_net_fee)
+                                   : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker);
         if (rc != 1)
-        m_tx_fail(ERROR_COMPOSE, "Cant add net fee output");
+            m_tx_fail(ERROR_COMPOSE, "Cant add net fee output");
     }
     if (!IS_ZERO_256(a_fee) && dap_chain_datum_tx_add_fee_item(&l_tx, a_fee) != 1)
         m_tx_fail(ERROR_COMPOSE, "Cant add validator fee output");
 
-    uint256_t l_fee_back = {};
-    // fee coin back
-    SUBTRACT_256_256(l_value_transfer, l_value, &l_fee_back);
-
-    if (!IS_ZERO_256(l_fee_back)) {
-        int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_fee_back)
-        : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker);
-        if (rc != 1)
+    if (!l_refill_native) {
+        uint256_t l_fee_back = {};
+        // fee coin back
+        SUBTRACT_256_256(l_fee_transfer, l_fee_total, &l_fee_back);
+        if (!IS_ZERO_256(l_fee_back) && dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker) != 1)
             m_tx_fail(ERROR_COMPOSE, "Cant add fee back output");
     }
 
-- 
GitLab


From 3f95cf77ce5767f3f7a9ebb6788dd6116ecd6c48 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Thu, 27 Feb 2025 08:04:41 +0300
Subject: [PATCH 06/25] [*] subs update

---
 dap-sdk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dap-sdk b/dap-sdk
index 0e5303fbfc..6184e49af5 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit 0e5303fbfc0a646d157117d451ac3e98e5a5752d
+Subproject commit 6184e49af5e0e2536696eab1a520ad3536e40cc7
-- 
GitLab


From d40a3adf7a8aebdad362c8b15948618c9901a452 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Tue, 25 Feb 2025 13:43:02 +0300
Subject: [PATCH 07/25] [*] fix signs check in refill

---
 .../service/emit-delegate/dap_chain_net_srv_emit_delegate.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index b120d0b15a..55eb367c68 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -160,9 +160,9 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_datum_t
         }
     }
 
-    if (l_signs_verified < a_cond->subtype.srv_emit_delegate.signers_minimum) {
-        log_it(L_WARNING, "Not enough valid signs (%u from %u) for delegated emission in tx %s",
-                                    l_signs_verified, a_cond->subtype.srv_emit_delegate.signers_minimum, dap_hash_fast_to_str_static(a_tx_in_hash));
+    if (l_change_type == DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF && l_signs_verified < a_cond->subtype.srv_emit_delegate.signers_minimum) {
+        log_it(L_WARNING, "Not enough valid signs (%u from %u) for delegated emission",
+                                    l_signs_verified, a_cond->subtype.srv_emit_delegate.signers_minimum);
         return DAP_CHAIN_CS_VERIFY_CODE_NOT_ENOUGH_SIGNS;
     }
     return 0;
-- 
GitLab


From a44a1873442a57a7fe7f6a2d2458eee274aa157c Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Tue, 25 Feb 2025 10:05:24 +0300
Subject: [PATCH 08/25] [*] pipe error fix

---
 .../service/emit-delegate/dap_chain_net_srv_emit_delegate.c   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index 55eb367c68..157ff3a848 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -326,7 +326,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o
     // list of transaction with 'out' items to sell
     dap_chain_addr_t l_owner_addr;
     dap_chain_addr_fill_from_key(&l_owner_addr, a_enc_key, a_net->pub.id);
-    dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_tx_ticker,
+    dap_list_t *l_list_used_out = dap_chain_wallet_get_list_tx_outs_with_val(l_ledger, l_tx_ticker,
                                                                        &l_owner_addr, l_value, &l_value_transfer);
     if (!l_list_used_out)
         m_tx_fail(ERROR_FUNDS, "Nothing to pay for delegate (not enough funds)");
@@ -338,7 +338,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o
         m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction input");
 
     if (!l_refill_native) {
-        dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker,
+        dap_list_t *l_list_fee_out = dap_chain_wallet_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker,
                                                                           &l_owner_addr, l_fee_total, &l_fee_transfer);
         if (!l_list_fee_out)
             m_tx_fail(ERROR_FUNDS, "Nothing to pay for fee (not enough funds)");
-- 
GitLab


From 3f83773d50e3983db12af9e2d6df33b32035a7b3 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Fri, 28 Feb 2025 09:04:53 +0300
Subject: [PATCH 09/25] [*] visual fixes

---
 .../dap_chain_net_srv_emit_delegate.c         | 20 ++++++++-----------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index 157ff3a848..12250a625c 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -285,20 +285,18 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply,
     }
 
     if (a_tag_str) {
-        dap_chain_tx_tsd_t *tsd_tag_item = dap_chain_datum_tx_item_tsd_create(a_tag_str, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_TAG, strlen(a_tag_str) + 1);
-        if (!tsd_tag_item)
+        dap_chain_tx_tsd_t *l_tsd_tag_item = dap_chain_datum_tx_item_tsd_create(a_tag_str, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_TAG, strlen(a_tag_str) + 1);
+        if (!l_tsd_tag_item)
             m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction tag");
-        if (dap_chain_datum_tx_add_item(&l_tx, tsd_tag_item) != 1) {
-            DAP_DELETE(tsd_tag_item);
+        if (dap_chain_datum_tx_add_item(&l_tx, l_tsd_tag_item) != 1) {
+            DAP_DELETE(l_tsd_tag_item);
             m_tx_fail(ERROR_COMPOSE, "Can't add the transaction tag");
         }
-        DAP_DELETE(tsd_tag_item);
+        DAP_DELETE(l_tsd_tag_item);
     }
     // add 'sign' item
     if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1)
         m_tx_fail(ERROR_COMPOSE, "Can't add sign output");
-
-
     return l_tx;
 }
 
@@ -307,7 +305,6 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o
     uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items)
 {
     dap_return_val_if_pass(!a_net || IS_ZERO_256(a_value) || IS_ZERO_256(a_fee), NULL);
-    // create empty transaction
     dap_ledger_t *l_ledger = a_net->pub.ledger;
     const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, a_tx_in_hash);
     bool l_refill_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker);
@@ -329,7 +326,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o
     dap_list_t *l_list_used_out = dap_chain_wallet_get_list_tx_outs_with_val(l_ledger, l_tx_ticker,
                                                                        &l_owner_addr, l_value, &l_value_transfer);
     if (!l_list_used_out)
-        m_tx_fail(ERROR_FUNDS, "Nothing to pay for delegate (not enough funds)");
+        m_tx_fail(ERROR_FUNDS, "Nothing to pay for refill (not enough funds)");
 
     // add 'in' items to pay for delegate
     uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out);
@@ -385,8 +382,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o
     }
     DAP_DELETE(l_out_cond);
 
-
-    // add track for takeoff from conditional value
+    // add track for refill from conditional value
     dap_chain_tx_tsd_t *l_refill_tsd = dap_chain_datum_tx_item_tsd_create(&a_value, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL, sizeof(uint256_t));
     if (dap_chain_datum_tx_add_item(&l_tx, l_refill_tsd) != 1) {
         DAP_DELETE(l_refill_tsd);
@@ -400,7 +396,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o
         m_tx_fail(ERROR_COMPOSE, "Can't add custom TSD section item ");
     }
 
-// coin back
+    // coin back
     SUBTRACT_256_256(l_value_transfer, l_value, &l_value_back);
     if (!IS_ZERO_256(l_value_back)) {
         int rc = l_refill_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_value_back)
-- 
GitLab


From 375b9263c4874568e620a3bc7491a518444ee3f2 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Fri, 28 Feb 2025 09:35:00 +0300
Subject: [PATCH 10/25] [*] wrn fix

---
 modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index 12250a625c..74542ad005 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -285,7 +285,7 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply,
     }
 
     if (a_tag_str) {
-        dap_chain_tx_tsd_t *l_tsd_tag_item = dap_chain_datum_tx_item_tsd_create(a_tag_str, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_TAG, strlen(a_tag_str) + 1);
+        dap_chain_tx_tsd_t *l_tsd_tag_item = dap_chain_datum_tx_item_tsd_create((void *)a_tag_str, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_TAG, strlen(a_tag_str) + 1);
         if (!l_tsd_tag_item)
             m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction tag");
         if (dap_chain_datum_tx_add_item(&l_tx, l_tsd_tag_item) != 1) {
-- 
GitLab


From 98c9f75321f4e79dceff874eee694c3a443b96f5 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Thu, 27 Feb 2025 12:28:05 +0300
Subject: [PATCH 11/25] [*] add return if cmd error

---
 modules/node-cli/dap_chain_node_cli_cmd.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index 36231da086..da26dd7bc7 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -5967,6 +5967,7 @@ int com_policy(int argc, char **argv, void **reply) {
     uint64_t l_policy_num = strtoull(l_num_str, NULL, 10);
     if (!dap_chain_policy_num_is_valid(l_policy_num)) {
         dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy num sould be less or equal than %u and not equal 0", dap_maxval(l_policy->activate.num));
+        return -16;
     }
 
     uint32_t l_last_num = dap_chain_policy_get_last_num(l_net->pub.id.uint64);
-- 
GitLab


From b9b2622b1dc2262ebeeff58b8135d93bb3fd9d6c Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Fri, 28 Feb 2025 08:32:07 +0300
Subject: [PATCH 12/25] [*] add cuurent time to draft

---
 modules/node-cli/dap_chain_node_cli.c     | 17 +++++++++--------
 modules/node-cli/dap_chain_node_cli_cmd.c |  5 ++++-
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/modules/node-cli/dap_chain_node_cli.c b/modules/node-cli/dap_chain_node_cli.c
index b4492e3f95..f6268aa2d6 100644
--- a/modules/node-cli/dap_chain_node_cli.c
+++ b/modules/node-cli/dap_chain_node_cli.c
@@ -381,21 +381,22 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                 "file clear_log\n"
                 "\t CAUTION !!! This command will clear the entire log file\n");
 
-    dap_cli_server_cmd_add ("policy", com_policy, "Policy commands", "policy [execute] - prepare or create policy execute decree\n"
-                "\t-net <net_name> - net name to policy apply\n"
-                "\t-num <policy_num> - policy num\n"
+    dap_cli_server_cmd_add ("policy", com_policy, "Policy commands", "policy - prepare or create policy execute decree\n"
+                "\t[execute] - used to create policy decree, otherwise show policy decree draft\n"
+                "\t-net <net_name>\n"
+                "\t-num <policy_num>\n"
                 "\t[-ts_start <dd/mm/yy-H:M:S>] - date to start policy\n"
                 "\t[-ts_stop <dd/mm/yy-H:M:S>] - date to stop policy\n"
                 "\t{\n\t\t[-block_start <block_num>] - block num to start policy\n"
                 "\t\t[-block_stop <block_num>] - block num to stop policy\n"
                 "\t\t-chain <chain_name> - chain name to check blocks num\n\t}\n"
-                "\t[-deactivate <deactivate_nums>] - list deactivated policy, example: 1,4,6\n"
-                "\t[-certs <certs_name>] - list signing certs, example: foobar.root.pvt.0,foobar.root.pvt.1\n"
+                "\t[-deactivate <num1[,num2,...,numN]>] - list deactivated policy\n"
+                "\t[-certs <cert1[,cert2,...,certN]>] - list signing certs\n"
                 "policy find - find info about policy in net\n"
-                "\t-net <net_name> - net name to policy search\n"
-                "\t-num <policy_num> - policy num\n"
+                "\t-net <net_name>\n"
+                "\t-num <policy_num>\n"
                 "policy list - show all policies from table in net\n"
-                "\t-net <net_name> - net name to policy search\n");
+                "\t-net <net_name>\n");
     // Exit - always last!
     dap_cli_server_cmd_add ("exit", com_exit, "Stop application and exit",
                 "exit\n" );
diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index da26dd7bc7..aa3b6f10ab 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -5928,7 +5928,7 @@ int com_policy(int argc, char **argv, void **reply) {
         l_certs_count = 0;
     dap_cert_t **l_certs = NULL;
 
-    enum { CMD_NONE=0, CMD_EXECUTE, CMD_FIND, CMD_LIST };  
+    enum { CMD_NONE = 0, CMD_EXECUTE, CMD_FIND, CMD_LIST };  
     int l_arg_index = 1;
 
     int l_cmd = CMD_NONE;
@@ -6104,6 +6104,9 @@ int com_policy(int argc, char **argv, void **reply) {
     // if cmd none - only print preaparing result
     if (l_cmd == CMD_NONE) {
         json_object *l_answer = dap_chain_policy_json_collect(l_policy);
+        char l_time[DAP_TIME_STR_SIZE] = {};
+        dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, dap_time_now());
+        json_object_object_add(l_answer, "current time", json_object_new_string(l_time));
         json_object_object_add(l_answer, "notification", json_object_new_string("It's policy draft, check and use 'execute' command to apply"));
         if (l_answer) {
             json_object_array_add(*a_json_arr_reply, l_answer);
-- 
GitLab


From f5722fba0308c801016cd5e5f63b567df98a2854 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Mon, 10 Mar 2025 12:41:36 +0300
Subject: [PATCH 13/25] [*] move tag to

---
 modules/datum/dap_chain_datum_tx_items.c       |  6 ++++--
 modules/datum/include/dap_chain_datum_token.h  |  1 -
 .../datum/include/dap_chain_datum_tx_items.h   |  3 ++-
 .../include/dap_chain_datum_tx_out_cond.h      |  2 ++
 .../dap_chain_net_srv_emit_delegate.c          | 18 ++++++------------
 5 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/modules/datum/dap_chain_datum_tx_items.c b/modules/datum/dap_chain_datum_tx_items.c
index 23ff6f240f..9b41c87123 100644
--- a/modules/datum/dap_chain_datum_tx_items.c
+++ b/modules/datum/dap_chain_datum_tx_items.c
@@ -376,11 +376,11 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake_lock(
 
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(dap_chain_srv_uid_t a_srv_uid, uint256_t a_value,
                                                                                    uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes,
-                                                                                   size_t a_pkey_hashes_count)
+                                                                                   size_t a_pkey_hashes_count, const char *a_tag_str)
 {
     if (IS_ZERO_256(a_value))
         return NULL;
-    size_t l_tsd_total_size = a_pkey_hashes_count * (sizeof(dap_hash_fast_t) + sizeof(dap_tsd_t));
+    size_t l_tsd_total_size = a_pkey_hashes_count * (sizeof(dap_hash_fast_t) + sizeof(dap_tsd_t)) + (a_tag_str ? sizeof(dap_tsd_t) + strlen(a_tag_str) + 1 : 0);
     dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + l_tsd_total_size, NULL);
     l_item->header.item_type = TX_ITEM_TYPE_OUT_COND;
     l_item->header.value = a_value;
@@ -391,6 +391,8 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delega
     byte_t *l_next_tsd_ptr = l_item->tsd;
     for (size_t i = 0; i < a_pkey_hashes_count; i++)
         l_next_tsd_ptr = dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_HASH, a_pkey_hashes + i, sizeof(dap_hash_fast_t));
+    if (a_tag_str)
+        l_next_tsd_ptr = dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_STR, (const void*)a_tag_str, strlen(a_tag_str) + 1);
     return l_item;
 }
 
diff --git a/modules/datum/include/dap_chain_datum_token.h b/modules/datum/include/dap_chain_datum_token.h
index 9c331e3844..a36b5ee5ac 100644
--- a/modules/datum/include/dap_chain_datum_token.h
+++ b/modules/datum/include/dap_chain_datum_token.h
@@ -341,7 +341,6 @@ typedef struct dap_chain_datum_token_emission {
 #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SIGNATURS         0x000E
 #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_UNIQUE_ID         0x000F
 #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_BASE_TX_HASH      0x0010
-#define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_TAG               0x0011
 
 // TSD sections with transfer additional params
 #define DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT         0x0013
diff --git a/modules/datum/include/dap_chain_datum_tx_items.h b/modules/datum/include/dap_chain_datum_tx_items.h
index 8b43e5aab5..85518a3df3 100644
--- a/modules/datum/include/dap_chain_datum_tx_items.h
+++ b/modules/datum/include/dap_chain_datum_tx_items.h
@@ -188,7 +188,8 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake_lock(
 
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(dap_chain_srv_uid_t a_srv_uid, uint256_t a_value,
                                                                                    uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes,
-                                                                                   size_t a_pkey_hashes_count);
+                                                                                   size_t a_pkey_hashes_count, const char *a_tag_str);
+
 /**
  * Create item dap_chain_tx_sig_t
  *
diff --git a/modules/datum/include/dap_chain_datum_tx_out_cond.h b/modules/datum/include/dap_chain_datum_tx_out_cond.h
index a15e582664..f98f1a472f 100644
--- a/modules/datum/include/dap_chain_datum_tx_out_cond.h
+++ b/modules/datum/include/dap_chain_datum_tx_out_cond.h
@@ -57,6 +57,8 @@ typedef byte_t dap_chain_tx_out_cond_subtype_t;
 #define DAP_CHAIN_TX_OUT_COND_TSD_ADDR                      0xf001
 // Chain hash
 #define DAP_CHAIN_TX_OUT_COND_TSD_HASH                      0xf002
+// Custom str
+#define DAP_CHAIN_TX_OUT_COND_TSD_STR                       0xf003
 
 /**
  * @struct dap_chain_tx_out
diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index 74542ad005..320fb9b283 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -250,7 +250,7 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply,
     // add 'out_cond' & 'out_ext' items
     dap_chain_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID };
     dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(
-                                                l_uid, a_value, a_signs_min, a_pkey_hashes, a_pkey_hashes_count);
+                                                l_uid, a_value, a_signs_min, a_pkey_hashes, a_pkey_hashes_count, a_tag_str);
     if (!l_tx_out)
         m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction conditional output");
     dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_tx_out);
@@ -283,17 +283,6 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply,
         if (!IS_ZERO_256(l_fee_back) && dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, l_native_ticker) != 1)
             m_tx_fail(ERROR_COMPOSE, "Cant add fee back output");
     }
-
-    if (a_tag_str) {
-        dap_chain_tx_tsd_t *l_tsd_tag_item = dap_chain_datum_tx_item_tsd_create((void *)a_tag_str, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_TAG, strlen(a_tag_str) + 1);
-        if (!l_tsd_tag_item)
-            m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction tag");
-        if (dap_chain_datum_tx_add_item(&l_tx, l_tsd_tag_item) != 1) {
-            DAP_DELETE(l_tsd_tag_item);
-            m_tx_fail(ERROR_COMPOSE, "Can't add the transaction tag");
-        }
-        DAP_DELETE(l_tsd_tag_item);
-    }
     // add 'sign' item
     if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1)
         m_tx_fail(ERROR_COMPOSE, "Can't add sign output");
@@ -1087,6 +1076,7 @@ static int s_cli_info(int a_argc, char **a_argv, int a_arg_index, json_object **
     json_object *l_jobj_token = json_object_new_object();
     json_object *l_jobj_take_verify = json_object_new_object();
     json_object *l_jobj_pkey_hashes = json_object_new_array();
+    json_object *l_jobj_tags = json_object_new_array();
     json_object *l_json_jobj_info = json_object_new_object();
 
     bool l_is_base_hash_type = dap_strcmp(a_hash_out_type, "hex");
@@ -1106,11 +1096,15 @@ static int s_cli_info(int a_argc, char **a_argv, int a_arg_index, json_object **
         if (l_tsd->type == DAP_CHAIN_TX_OUT_COND_TSD_HASH && l_tsd->size == sizeof(dap_hash_fast_t)) {
             json_object_array_add(l_jobj_pkey_hashes, json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data) : dap_hash_fast_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data)));
         }
+        if (l_tsd->type == DAP_CHAIN_TX_OUT_COND_TSD_STR) {
+            json_object_array_add(l_jobj_tags, json_object_new_string(l_tsd->data));
+        }
     }
     json_object_object_add(l_jobj_take_verify, "owner_hashes", l_jobj_pkey_hashes);
     // result block
     json_object_object_add(l_json_jobj_info, "tx_hash", json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static(&l_tx_hash) : dap_hash_fast_to_str_static(&l_tx_hash)));
     json_object_object_add(l_json_jobj_info, "tx_hash_final", json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static(&l_final_tx_hash) : dap_hash_fast_to_str_static(&l_final_tx_hash)));
+    json_object_object_add(l_json_jobj_info, "tags", l_jobj_tags);
     json_object_object_add(l_json_jobj_info, "balance", l_jobj_balance);
     json_object_object_add(l_json_jobj_info, "take_verify", l_jobj_take_verify);
     json_object_object_add(l_json_jobj_info, "token", l_jobj_token);
-- 
GitLab


From e62edaa9290dccbdd4cdb319c333e7e274b8baae Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Mon, 3 Mar 2025 15:51:11 +0300
Subject: [PATCH 14/25] [*] rebuild policy

---
 modules/chain/dap_chain_policy.c          | 166 +++++++++++--------
 modules/chain/include/dap_chain_policy.h  |  68 ++++++--
 modules/datum/dap_chain_datum_decree.c    |   2 +-
 modules/ledger/dap_chain_ledger_decree.c  |   7 +-
 modules/net/dap_chain_net.c               |  10 +-
 modules/node-cli/dap_chain_node_cli_cmd.c | 191 ++++++++++++----------
 6 files changed, 262 insertions(+), 182 deletions(-)

diff --git a/modules/chain/dap_chain_policy.c b/modules/chain/dap_chain_policy.c
index df8b9f8bf3..28f780d838 100644
--- a/modules/chain/dap_chain_policy.c
+++ b/modules/chain/dap_chain_policy.c
@@ -55,8 +55,15 @@ DAP_STATIC_INLINE struct policy_net_list_item *s_net_find(uint64_t a_net_id)
 
 DAP_STATIC_INLINE int s_policy_num_compare(dap_list_t  *a_list1, dap_list_t  *a_list2)
 {
-    return ((dap_chain_policy_t *)(a_list1->data))->activate.num == ((dap_chain_policy_t *)(a_list2->data))->activate.num ? 0 :
-        ((dap_chain_policy_t *)(a_list1->data))->activate.num > ((dap_chain_policy_t *)(a_list2->data))->activate.num ? 1 : -1;
+    dap_chain_policy_t
+        *l_policy1 = a_list1->data,
+        *l_policy2 = a_list2->data;
+    if (l_policy1->type != DAP_CHAIN_POLICY_ACTIVATE || l_policy2->type != DAP_CHAIN_POLICY_ACTIVATE) {
+        log_it(L_WARNING, "Compare wrong policy type");
+        return 0;
+    }
+    return ((dap_chain_policy_activate_t *)(l_policy1->data))->num == ((dap_chain_policy_activate_t *)(l_policy2->data))->num ? 0 :
+        ((dap_chain_policy_activate_t *)(l_policy1->data))->num > ((dap_chain_policy_activate_t *)(l_policy2->data))->num ? 1 : -1;
 }
 
 /**
@@ -122,20 +129,29 @@ int dap_chain_policy_add(dap_chain_policy_t *a_policy, uint64_t a_net_id)
         log_it(L_ERROR, "Can't find net %"DAP_UINT64_FORMAT_X" in policy list", a_net_id);
         return -2;
     }
-    if (dap_list_find(l_net_item->policies, a_policy, s_policy_num_compare)) {
-        log_it(L_ERROR, "CN-%u already added to net %"DAP_UINT64_FORMAT_X, a_policy->activate.num, a_net_id);
-        return -3;
-    }
-    l_net_item->policies = dap_list_insert_sorted(l_net_item->policies, a_policy, s_policy_num_compare);
-    for (size_t i = 0; i < a_policy->deactivate.count; ++i) {
-        uint32_t l_policy_num = a_policy->deactivate.nums[i];
-        if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_policy_num, NULL)) {
-            log_it(L_ERROR, "CN-%u already added to exception list net %"DAP_UINT64_FORMAT_X, l_policy_num, a_net_id);
-            continue;
-        }
-        l_net_item->exception_list = dap_list_append(l_net_item->exception_list, (void *)(uintptr_t)l_policy_num);
+    switch (a_policy->type) {
+        case DAP_CHAIN_POLICY_ACTIVATE:
+            if (dap_list_find(l_net_item->policies, a_policy, s_policy_num_compare)) {
+                log_it(L_ERROR, "CN-%u already added to net %"DAP_UINT64_FORMAT_X, ((dap_chain_policy_activate_t *)(a_policy->data))->num, a_net_id);
+                return -3;
+            }
+            l_net_item->policies = dap_list_insert_sorted(l_net_item->policies, a_policy, s_policy_num_compare);
+            l_net_item->last_num_policy = dap_max(((dap_chain_policy_activate_t *)(a_policy->data))->num, l_net_item->last_num_policy);
+            break;
+        case DAP_CHAIN_POLICY_DEACTIVATE:
+            for (size_t i = 0; i < ((dap_chain_policy_deactivate_t *)(a_policy->data))->count; ++i) {
+                uint32_t l_policy_num = ((dap_chain_policy_deactivate_t *)(a_policy->data))->nums[i];
+                if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_policy_num, NULL)) {
+                    log_it(L_ERROR, "CN-%u already added to exception list net %"DAP_UINT64_FORMAT_X, l_policy_num, a_net_id);
+                    continue;
+                }
+                l_net_item->exception_list = dap_list_append(l_net_item->exception_list, (void *)(uintptr_t)l_policy_num);
+            }
+            break;
+        default:
+            log_it(L_ERROR, "Unknow policy type %u", a_policy->type);
+            break;
     }
-    l_net_item->last_num_policy = dap_max(a_policy->activate.num, l_net_item->last_num_policy);
     return 0;
 }
 
@@ -178,28 +194,29 @@ bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id)
     if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)a_policy_num, NULL))
         return l_ret;
     // seach politics to condition check
-    dap_chain_policy_t l_to_search = {
-        .activate.num = a_policy_num
-    };
+    dap_chain_policy_t *l_to_search = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t), false);
+    l_to_search->type = DAP_CHAIN_POLICY_ACTIVATE;
+    ((dap_chain_policy_activate_t *)(l_to_search->data))->num = a_policy_num;
     dap_list_t *l_list_item = dap_list_find(l_net_item->policies, &l_to_search, s_policy_num_compare);
+    DAP_DELETE(l_to_search);
     if (!l_list_item) {
         if (l_net_item->last_num_policy > a_policy_num)  // use cumulative principle without check conditions
             return true;
         return l_ret;
     }
-    dap_chain_policy_t *l_policy_item = (dap_chain_policy_t *)l_list_item->data;
+    dap_chain_policy_activate_t *l_policy_item = (dap_chain_policy_activate_t *)(((dap_chain_policy_t *)l_list_item->data)->data);
     // condition check
-    if (DAP_FLAG_CHECK(l_policy_item->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS)) {
+    if (DAP_FLAG_CHECK(l_policy_item->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS)) {
         time_t l_current_time = dap_time_now();
-        if (l_current_time < l_policy_item->activate.ts_start || (l_policy_item->activate.ts_stop && l_current_time > l_policy_item->activate.ts_stop))
+        if (l_current_time < l_policy_item->ts_start || (l_policy_item->ts_stop && l_current_time > l_policy_item->ts_stop))
             return l_ret;
     }
-    if (DAP_FLAG_CHECK(l_policy_item->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM)) {
-        if (!l_policy_item->activate.chain_union.chain) {
+    if (DAP_FLAG_CHECK(l_policy_item->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM)) {
+        if (!l_policy_item->chain_union.chain) {
             log_it(L_ERROR, "Chain is null in policy item with upped DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM flag");
             return l_ret;
         }
-        if ( l_policy_item->activate.chain_union.chain->atom_num_last < l_policy_item->activate.block_start || (l_policy_item->activate.block_stop && l_policy_item->activate.chain_union.chain->atom_num_last > l_policy_item->activate.block_stop))
+        if ( l_policy_item->chain_union.chain->atom_num_last < l_policy_item->block_start || (l_policy_item->block_stop && l_policy_item->chain_union.chain->atom_num_last > l_policy_item->block_stop))
             return l_ret;
     }
     return true;
@@ -218,10 +235,12 @@ dap_chain_policy_t *dap_chain_policy_find(uint32_t a_policy_num, uint64_t a_net_
     dap_return_val_if_pass(!l_net_item, NULL);
     if (l_net_item->last_num_policy < a_policy_num)
         return NULL;
-    dap_chain_policy_t l_to_search = {
-        .activate.num = a_policy_num
-    };
+
+    dap_chain_policy_t *l_to_search = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t), false);
+    l_to_search->type = DAP_CHAIN_POLICY_ACTIVATE;
+    ((dap_chain_policy_activate_t *)(l_to_search->data))->num = a_policy_num;
     dap_list_t *l_find = dap_list_find(l_net_item->policies, &l_to_search, s_policy_num_compare);
+    DAP_DELETE(l_to_search);
     if (!l_find) {
         log_it(L_DEBUG, "Can't find CN-%u in net %"DAP_UINT64_FORMAT_X, a_policy_num, a_net_id);
         return NULL;
@@ -251,10 +270,11 @@ json_object *dap_chain_policy_list(uint64_t a_net_id)
     dap_string_t *l_active_str = dap_string_new("");
     dap_string_t *l_inactive_str = dap_string_new("");
     for (dap_list_t *l_iter = dap_list_first(l_net_item->policies); l_iter; l_iter = l_iter->next) {
-        if (dap_chain_policy_activated(((dap_chain_policy_t *)l_iter->data)->activate.num, a_net_id))
-            dap_string_append_printf(l_active_str, "CN-%u ", ((dap_chain_policy_t *)l_iter->data)->activate.num);
+        dap_chain_policy_activate_t *l_policy_activate =  (dap_chain_policy_activate_t *)((dap_chain_policy_t *)(l_iter->data))->data;
+        if (dap_chain_policy_activated(l_policy_activate->num, a_net_id))
+            dap_string_append_printf(l_active_str, "CN-%u ", l_policy_activate->num);
         else
-            dap_string_append_printf(l_inactive_str, "CN-%u ", ((dap_chain_policy_t *)l_iter->data)->activate.num);
+            dap_string_append_printf(l_inactive_str, "CN-%u ", l_policy_activate->num);
     }
     json_object_object_add(l_ret, "active", json_object_new_string(l_active_str->str));
     json_object_object_add(l_ret, "inactive", json_object_new_string(l_inactive_str->str));
@@ -275,44 +295,58 @@ json_object *dap_chain_policy_json_collect(dap_chain_policy_t *a_policy)
     json_object *l_ret = json_object_new_object();
 
     json_object_object_add(l_ret, "version", json_object_new_uint64(a_policy->version));
-    json_object_object_add(l_ret, "num", json_object_new_uint64(a_policy->activate.num));
-    if (a_policy->activate.ts_start) {
-        char l_time[DAP_TIME_STR_SIZE] = {};
-        dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, a_policy->activate.ts_start);
-        json_object_object_add(l_ret, "ts_start", json_object_new_string(l_time));
-    } else {
-        json_object_object_add(l_ret, "ts_start", json_object_new_int(0));
-    }
-    if (a_policy->activate.ts_stop) {
-        char l_time[DAP_TIME_STR_SIZE] = {};
-        dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, a_policy->activate.ts_stop);
-        json_object_object_add(l_ret, "ts_stop", json_object_new_string(l_time));
-    } else {
-        json_object_object_add(l_ret, "ts_stop", json_object_new_int(0));
-    }
-    json_object_object_add(l_ret, "block_start", json_object_new_uint64(a_policy->activate.block_start));
-    json_object_object_add(l_ret, "block_stop", json_object_new_uint64(a_policy->activate.block_stop));
-    if (a_policy->activate.block_start || a_policy->activate.block_stop) {
-        if (!a_policy->activate.chain_union.chain) {
-            json_object_object_add(l_ret, "chain", json_object_new_string("ERROR pointer chain is NULL"));
-        } else {
-            char l_chain_id[32] = { };
-            snprintf(l_chain_id, sizeof(l_chain_id) - 1, "0x%016"DAP_UINT64_FORMAT_x, a_policy->activate.chain_union.chain->id.uint64);
-            json_object_object_add(l_ret, "chain", json_object_new_string(l_chain_id));
+    json_object_object_add(l_ret, "type", json_object_new_string(dap_chain_policy_to_str(a_policy)));
+    switch (a_policy->type) {
+        case DAP_CHAIN_POLICY_ACTIVATE: {
+            dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)a_policy->data;
+            json_object_object_add(l_ret, "num", json_object_new_uint64(l_policy_activate->num));
+            if (l_policy_activate->ts_start) {
+                char l_time[DAP_TIME_STR_SIZE] = {};
+                dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, l_policy_activate->ts_start);
+                json_object_object_add(l_ret, "ts_start", json_object_new_string(l_time));
+            } else {
+                json_object_object_add(l_ret, "ts_start", json_object_new_int(0));
+            }
+            if (l_policy_activate->ts_stop) {
+                char l_time[DAP_TIME_STR_SIZE] = {};
+                dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, l_policy_activate->ts_stop);
+                json_object_object_add(l_ret, "ts_stop", json_object_new_string(l_time));
+            } else {
+                json_object_object_add(l_ret, "ts_stop", json_object_new_int(0));
+            }
+            json_object_object_add(l_ret, "block_start", json_object_new_uint64(l_policy_activate->block_start));
+            json_object_object_add(l_ret, "block_stop", json_object_new_uint64(l_policy_activate->block_stop));
+            if (l_policy_activate->block_start || l_policy_activate->block_stop) {
+                if (!l_policy_activate->chain_union.chain) {
+                    json_object_object_add(l_ret, "chain", json_object_new_string("ERROR pointer chain is NULL"));
+                } else {
+                    char l_chain_id[32] = { };
+                    snprintf(l_chain_id, sizeof(l_chain_id) - 1, "0x%016"DAP_UINT64_FORMAT_x, l_policy_activate->chain_union.chain->id.uint64);
+                    json_object_object_add(l_ret, "chain", json_object_new_string(l_chain_id));
+                }
+            } else {
+                json_object_object_add(l_ret, "chain", json_object_new_string(""));
+            }
+            json_object_object_add(l_ret, "description", json_object_new_string("WIKI"));
         }
-    } else {
-        json_object_object_add(l_ret, "chain", json_object_new_string(""));
-    }
-    if (a_policy->deactivate.count) {
-        dap_string_t *l_nums_list = dap_string_sized_new(a_policy->deactivate.count * (sizeof(uint32_t) + 4));
-        for (size_t i = 0; i < a_policy->deactivate.count; ++i) {
-            dap_string_append_printf(l_nums_list, "CN-%u ", a_policy->deactivate.nums[i]);
+            break;
+        
+        case DAP_CHAIN_POLICY_DEACTIVATE: {
+            dap_chain_policy_deactivate_t *l_policy_deactivate = (dap_chain_policy_deactivate_t *)a_policy->data;
+            if (l_policy_deactivate->count) {
+                dap_string_t *l_nums_list = dap_string_sized_new(l_policy_deactivate->count * (sizeof(uint32_t) + 4));
+                for (size_t i = 0; i < l_policy_deactivate->count; ++i) {
+                    dap_string_append_printf(l_nums_list, "CN-%u ", l_policy_deactivate->nums[i]);
+                }
+                json_object_object_add(l_ret, "deactivate", json_object_new_string(l_nums_list->str));
+                dap_string_free(l_nums_list, true);
+            } else {
+                json_object_object_add(l_ret, "deactivate", json_object_new_string(""));
+            }
         }
-        json_object_object_add(l_ret, "deactivate", json_object_new_string(l_nums_list->str));
-        dap_string_free(l_nums_list, true);
-    } else {
-        json_object_object_add(l_ret, "deactivate", json_object_new_string(""));
+            break;
+        default:
+            break;
     }
-    json_object_object_add(l_ret, "description", json_object_new_string("WIKI"));
     return l_ret;
 }
\ No newline at end of file
diff --git a/modules/chain/include/dap_chain_policy.h b/modules/chain/include/dap_chain_policy.h
index 2498bebe83..3409bb26bf 100644
--- a/modules/chain/include/dap_chain_policy.h
+++ b/modules/chain/include/dap_chain_policy.h
@@ -36,25 +36,36 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #define DAP_CHAIN_POLICY_PUBLIC_KEY_HASH_SIGN_VALIDATORS    0x1
 #define DAP_CHAIN_POLICY_OUT_EXT_USE_ENSURE                 0x2
 
+typedef enum {
+    DAP_CHAIN_POLICY_ACTIVATE = 0,
+    DAP_CHAIN_POLICY_DEACTIVATE
+} dap_chain_policy_type_t;
+
+typedef struct dap_chain_policy_activate {
+    uint64_t flags;
+    uint32_t num;
+    int64_t ts_start;
+    int64_t ts_stop;
+    uint64_t block_start;
+    uint64_t block_stop;
+    union {
+        dap_chain_id_t chain_id;
+        dap_chain_t *chain;
+    } chain_union;
+} DAP_ALIGN_PACKED dap_chain_policy_activate_t;
+
+typedef struct dap_chain_policy_deactivate {
+    uint64_t flags;
+    uint32_t count;
+    uint32_t nums[];
+} DAP_ALIGN_PACKED dap_chain_policy_deactivate_t;
+
 typedef struct dap_chain_policy {
     uint16_t version;
-    struct {
-        uint32_t num;
-        uint64_t flags;
-        int64_t ts_start;
-        int64_t ts_stop;
-        uint64_t block_start;
-        uint64_t block_stop;
-        union {
-            dap_chain_id_t chain_id;
-            dap_chain_t *chain;
-        } chain_union;
-    } activate;
-    struct {
-        uint32_t count;
-        uint32_t nums[];
-    } deactivate;
-} dap_chain_policy_t;
+    uint16_t type;
+    uint64_t data_size;
+    uint8_t data[];
+} DAP_ALIGN_PACKED dap_chain_policy_t;
 
 int dap_chain_policy_init();
 int dap_chain_policy_net_add(uint64_t a_net_id);
@@ -67,9 +78,30 @@ json_object *dap_chain_policy_json_collect(dap_chain_policy_t *a_policy);
 json_object *dap_chain_policy_list(uint64_t a_net_id);
 bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id);
 
+DAP_STATIC_INLINE size_t dap_chain_policy_deactivate_calc_size(size_t a_deactivate_count)
+{
+    return sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_deactivate_t) + sizeof(uint32_t) * a_deactivate_count;
+}
+
+DAP_STATIC_INLINE size_t dap_chain_policy_activate_calc_size()
+{
+    return sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t);
+}
+
 DAP_STATIC_INLINE size_t dap_chain_policy_get_size(dap_chain_policy_t *a_policy)
 {
-    return a_policy ? a_policy->deactivate.count * sizeof(uint32_t) + sizeof(dap_chain_policy_t) : 0;
+    return a_policy ? sizeof(dap_chain_policy_t)  + a_policy->data_size : 0;
+}
+
+DAP_STATIC_INLINE const char *dap_chain_policy_to_str(dap_chain_policy_t *a_policy)
+{
+    if(!a_policy)
+        return "NULL";
+    switch (a_policy->type) {
+        case DAP_CHAIN_POLICY_ACTIVATE: return ("DAP_CHAIN_POLICY_ACTIVATE");
+        case DAP_CHAIN_POLICY_DEACTIVATE: return ("DAP_CHAIN_POLICY_DEACTIVATE");
+        default: return ("UNKNOWN");
+    }
 }
 
 /**
diff --git a/modules/datum/dap_chain_datum_decree.c b/modules/datum/dap_chain_datum_decree.c
index 18f4d1fd54..2b6544165a 100644
--- a/modules/datum/dap_chain_datum_decree.c
+++ b/modules/datum/dap_chain_datum_decree.c
@@ -400,7 +400,7 @@ void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_d
                 json_object_object_add(a_json_out, "policy_num", json_object_new_string("WRONG SIZE"));
                 break;
             }
-            json_object_object_add(a_json_out, "policy_num", json_object_new_uint64(((dap_chain_policy_t *)(l_tsd->data))->activate.num));
+            json_object_object_add(a_json_out, "Policy type", json_object_new_string( dap_chain_policy_to_str((dap_chain_policy_t *)(l_tsd->data))));
             break;
 
         default:
diff --git a/modules/ledger/dap_chain_ledger_decree.c b/modules/ledger/dap_chain_ledger_decree.c
index 1e692d3beb..5895660de9 100644
--- a/modules/ledger/dap_chain_ledger_decree.c
+++ b/modules/ledger/dap_chain_ledger_decree.c
@@ -661,8 +661,11 @@ const char *l_ban_addr;
                 return -105;
             }
             l_policy = DAP_DUP_SIZE_RET_VAL_IF_FAIL(l_policy, dap_chain_policy_get_size(l_policy), -106);
-            if (DAP_FLAG_CHECK(l_policy->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM))
-                l_policy->activate.chain_union.chain = dap_chain_find_by_id(a_net->pub.id, l_policy->activate.chain_union.chain_id);
+            if (l_policy->type == DAP_CHAIN_POLICY_ACTIVATE) {
+                dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)l_policy->data;
+                DAP_FLAG_CHECK(l_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM);
+                l_policy_activate->chain_union.chain = dap_chain_find_by_id(a_net->pub.id, l_policy_activate->chain_union.chain_id);
+            }
             return dap_chain_policy_add(l_policy, a_net->pub.id.uint64);
         }
         default:
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index fa8e25035f..7071f10756 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -778,13 +778,13 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg)
     dap_chain_policy_t *l_new_policy = NULL;
     if (l_policy_num) {
         if (!dap_chain_policy_num_is_valid(l_policy_num)) {
-            log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U", maxval %u", l_policy_num, dap_maxuval(l_new_policy->activate.num));
+            log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U, l_policy_num);
         } else {
             dap_chain_policy_t *l_new_policy = NULL;
-            l_new_policy = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_policy_t, NULL, l_ret->pub.name, l_ret); 
+            l_new_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, dap_chain_policy_activate_calc_size(), NULL, l_ret->pub.name, l_ret); 
             l_new_policy->version = DAP_CHAIN_POLICY_VERSION;
-            l_new_policy->activate.num = l_policy_num;
-            l_new_policy->activate.flags = DAP_FLAG_ADD(l_new_policy->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG);
+            ((dap_chain_policy_activate_t *)(l_new_policy->data))->num = l_policy_num;
+            ((dap_chain_policy_activate_t *)(l_new_policy->data))->flags = DAP_FLAG_ADD(((dap_chain_policy_activate_t *)(l_new_policy->data))->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG);
             dap_chain_policy_add(l_new_policy, l_ret->pub.id.uint64);
         }
     }
@@ -794,7 +794,7 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg)
     for (uint16_t i = 0; i < l_policy_count; ++i) {
         l_policy_num = strtoull(l_policy_str[i], NULL, 10);
         if (!dap_chain_policy_num_is_valid(l_policy_num)) {
-            log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list, maxval %u", l_policy_num, dap_maxuval(l_new_policy->activate.num));
+            log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list", l_policy_num);
         } else {
             dap_chain_policy_add_to_exception_list(l_policy_num, l_ret->pub.id.uint64);
         }
diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index aa3b6f10ab..7c5a465946 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -5928,7 +5928,7 @@ int com_policy(int argc, char **argv, void **reply) {
         l_certs_count = 0;
     dap_cert_t **l_certs = NULL;
 
-    enum { CMD_NONE = 0, CMD_EXECUTE, CMD_FIND, CMD_LIST };  
+    enum { CMD_NONE = 0, CMD_EXECUTE, CMD_DEACTIVATE, CMD_FIND, CMD_LIST };  
     int l_arg_index = 1;
 
     int l_cmd = CMD_NONE;
@@ -5939,7 +5939,6 @@ int com_policy(int argc, char **argv, void **reply) {
     else if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "list", NULL))
         l_cmd = CMD_LIST;
 
-    dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-num", &l_num_str);
     dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-net", &l_net_str);
 
     if (!l_net_str) {
@@ -5958,16 +5957,43 @@ int com_policy(int argc, char **argv, void **reply) {
         return 0;
     }
 
+    dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-num", &l_num_str);
     if (!l_num_str) {
         dap_json_rpc_error_add(*a_json_arr_reply, -7, "Command policy require args -num");
         return -7;
     }
 
-    dap_chain_policy_t *l_policy = NULL;
-    uint64_t l_policy_num = strtoull(l_num_str, NULL, 10);
-    if (!dap_chain_policy_num_is_valid(l_policy_num)) {
-        dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy num sould be less or equal than %u and not equal 0", dap_maxval(l_policy->activate.num));
-        return -16;
+    void *l_policy_data = NULL;
+    size_t l_data_size = 0;
+    uint64_t l_policy_num = 0;
+    int l_policy_type = -1;
+    if (l_cmd == CMD_DEACTIVATE) {
+        l_policy_type = DAP_CHAIN_POLICY_DEACTIVATE;
+        l_deactivate_count = dap_str_symbol_count(l_num_str, ',') + 1;
+        l_deactivate_array = dap_strsplit(l_num_str, ",", l_deactivate_count);
+        l_data_size = dap_chain_policy_deactivate_calc_size(l_deactivate_count);
+        l_policy_data = DAP_NEW_Z(l_data_size);
+        if (!l_policy_data) {
+            log_it(L_ERROR, "%s", c_error_memory_alloc);
+            dap_strfreev(l_deactivate_array);
+        }
+        ((dap_chain_policy_deactivate_t *)l_policy_data)->count = l_deactivate_count;
+        for (size_t i = 0; i < l_deactivate_count; ++i) {
+            l_policy_num = strtoull(l_deactivate_array[i], NULL, 10);
+            if (!dap_chain_policy_num_is_valid(l_policy_num)) {
+                log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list", l_policy_num);
+                --((dap_chain_policy_deactivate_t *)l_policy_data)->count;
+                continue;
+            }
+            ((dap_chain_policy_deactivate_t *)l_policy_data)->nums[i] = l_policy_num;
+        }
+        dap_strfreev(l_deactivate_array);
+    } else {
+        l_policy_num = strtoull(l_num_str, NULL, 10);
+        if (!dap_chain_policy_num_is_valid(l_policy_num)) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy num sould be less or equal than %u and not equal 0", 77777);
+            return -16;
+        }
     }
 
     uint32_t l_last_num = dap_chain_policy_get_last_num(l_net->pub.id.uint64);
@@ -5977,16 +6003,10 @@ int com_policy(int argc, char **argv, void **reply) {
             dap_json_rpc_error_add(*a_json_arr_reply, -15, "Can't find policy CN-%u in net %s", l_policy_num, l_net_str);
             return -15;
         }
-        l_policy = dap_chain_policy_find(l_policy_num, l_net->pub.id.uint64);
-        if (!l_policy) {
-            dap_chain_policy_t l_to_print = {
-                .activate.num = l_policy_num
-            };
-            l_policy = &l_to_print;
-        }        
+        dap_chain_policy_t *l_policy = dap_chain_policy_find(l_policy_num, l_net->pub.id.uint64);
         json_object *l_answer = dap_chain_policy_json_collect(l_policy);
         if (l_answer) {
-            json_object_object_add(l_answer, "active", json_object_new_string(dap_chain_policy_activated(l_policy->activate.num, l_net->pub.id.uint64) ? "true" : "false"));
+            json_object_object_add(l_answer, "active", json_object_new_string(dap_chain_policy_activated(((dap_chain_policy_activate_t *)(l_policy->data))->num, l_net->pub.id.uint64) ? "true" : "false"));
             json_object_array_add(*a_json_arr_reply, l_answer);
         } else {
             json_object_array_add(*a_json_arr_reply, json_object_new_string("Empty reply"));
@@ -6002,7 +6022,7 @@ int com_policy(int argc, char **argv, void **reply) {
     dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-deactivate", &l_deactivate_str);
     dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-certs", &l_certs_str);
 
-    if (l_cmd == CMD_EXECUTE) {
+    if (l_cmd == CMD_EXECUTE || l_cmd == CMD_DEACTIVATE) {
         if (!l_certs_str) {
             dap_json_rpc_error_add(*a_json_arr_reply, -4, "Command 'execute' requires parameter -certs");
             return -4;
@@ -6019,88 +6039,79 @@ int com_policy(int argc, char **argv, void **reply) {
         return -15;
     }
 
-
-    if (l_deactivate_str) {
-        l_deactivate_count = dap_str_symbol_count(l_deactivate_str, ',') + 1;
-        l_deactivate_array = dap_strsplit(l_deactivate_str, ",", l_deactivate_count);
-    }
-    
-    l_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + l_deactivate_count * sizeof(uint32_t), -5);
-    
-    l_policy->version = DAP_CHAIN_POLICY_VERSION;
-    l_policy->activate.num = l_policy_num;
-
-    l_policy->deactivate.count = l_deactivate_count;
-    for (size_t i = 0; i < l_deactivate_count; ++i) {
-        l_policy_num = strtoull(l_deactivate_array[i], NULL, 10);
-        if (!dap_chain_policy_num_is_valid(l_policy_num)) {
-            log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list, maxval %u", l_policy_num, dap_maxuval(l_policy->activate.num));
-            --l_policy->deactivate.count;
-            continue;
+    if (l_cmd == CMD_EXECUTE) {
+        l_policy_type = DAP_CHAIN_POLICY_ACTIVATE;
+        l_data_size = sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t);
+        l_policy_data = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(void, l_data_size, -5);
+        dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)l_policy_data;
+        
+        l_policy_activate->num = l_policy_num;
+        if (l_ts_start_str) {
+            l_policy_activate->ts_start = dap_time_from_str_custom(l_ts_start_str, "%d/%m/%y-%H:%M:%S");
+            if (!l_policy_activate->ts_start) {
+                dap_json_rpc_error_add(*a_json_arr_reply, -13, "Can't read ts_start \"%s\"", l_ts_start_str);
+                DAP_DELETE(l_policy_activate);
+                return -13;
+            }
         }
-        l_policy->deactivate.nums[i] = l_policy_num;
-    }
-    dap_strfreev(l_deactivate_array);
-
 
-    if (l_ts_start_str) {
-        l_policy->activate.ts_start = dap_time_from_str_custom(l_ts_start_str, "%d/%m/%y-%H:%M:%S");
-        if (!l_policy->activate.ts_start) {
-            dap_json_rpc_error_add(*a_json_arr_reply, -13, "Can't read ts_start \"%s\"", l_ts_start_str);
-            DAP_DELETE(l_policy);
-            return -13;
+        if (l_ts_stop_str) {
+            l_policy_activate->ts_stop = dap_time_from_str_custom(l_ts_stop_str, "%d/%m/%y-%H:%M:%S");
+            if (!l_policy_activate->ts_stop) {
+                dap_json_rpc_error_add(*a_json_arr_reply, -14, "Can't read ts_stop \"%s\"", l_ts_stop_str);
+                DAP_DELETE(l_policy_activate);
+                return -14;
+            }
+            if (l_policy_activate->ts_stop <= l_policy_activate->ts_start) {
+                dap_json_rpc_error_add(*a_json_arr_reply, -12, "ts_start should less than ts_stop");
+                DAP_DELETE(l_policy_activate);
+                return -12;
+            }
         }
-    }
 
-    if (l_ts_stop_str) {
-        l_policy->activate.ts_stop = dap_time_from_str_custom(l_ts_stop_str, "%d/%m/%y-%H:%M:%S");
-        if (!l_policy->activate.ts_stop) {
-            dap_json_rpc_error_add(*a_json_arr_reply, -14, "Can't read ts_stop \"%s\"", l_ts_stop_str);
-            DAP_DELETE(l_policy);
-            return -14;
+        if (l_policy_activate->ts_start || l_policy_activate->ts_stop) {
+            l_policy_activate->flags = DAP_FLAG_ADD(l_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS);
         }
-        if (l_policy->activate.ts_stop <= l_policy->activate.ts_start) {
-            dap_json_rpc_error_add(*a_json_arr_reply, -12, "ts_start should less than ts_stop");
-            DAP_DELETE(l_policy);
-            return -12;
-        }
-    }
-
-    if (l_policy->activate.ts_start || l_policy->activate.ts_stop) {
-        l_policy->activate.flags = DAP_FLAG_ADD(l_policy->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS);
-    }
 
-    if (l_block_start_str)
-        l_policy->activate.block_start = strtoull(l_block_start_str, NULL, 10);
-    if (l_block_stop_str) {
-        l_policy->activate.block_stop = strtoull(l_block_stop_str, NULL, 10);
-        if (l_policy->activate.block_stop <= l_policy->activate.block_start) {
-            dap_json_rpc_error_add(*a_json_arr_reply, -13, "block_start should less than block_stop");
-            DAP_DELETE(l_policy);
-            return -13;
+        if (l_block_start_str)
+            l_policy_activate->block_start = strtoull(l_block_start_str, NULL, 10);
+        if (l_block_stop_str) {
+            l_policy_activate->block_stop = strtoull(l_block_stop_str, NULL, 10);
+            if (l_policy_activate->block_stop <= l_policy_activate->block_start) {
+                dap_json_rpc_error_add(*a_json_arr_reply, -13, "block_start should less than block_stop");
+                DAP_DELETE(l_policy_activate);
+                return -13;
+            }
         }
-    }
-    
-    if (l_policy->activate.block_start || l_policy->activate.block_stop) {
-        if (!l_chain_str) {
-            dap_json_rpc_error_add(*a_json_arr_reply, -8, "Command policy create with -block_start or -block_stop require args -chain");
-            DAP_DELETE(l_policy);
-            return -8;
+        
+        if (l_policy_activate->block_start || l_policy_activate->block_stop) {
+            if (!l_chain_str) {
+                dap_json_rpc_error_add(*a_json_arr_reply, -8, "Command policy create with -block_start or -block_stop require args -chain");
+                DAP_DELETE(l_policy_activate);
+                return -8;
+            }
+            dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str);
+            if (!l_chain) {
+                dap_json_rpc_error_add(*a_json_arr_reply, -9, "%s Chain not found", l_chain_str);
+                DAP_DELETE(l_policy_activate);
+                return -9;
+            }
+            l_policy_activate->chain_union.chain = l_chain;
+            l_policy_activate->flags = DAP_FLAG_ADD(l_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM);
         }
-        dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str);
-        if (!l_chain) {
-            dap_json_rpc_error_add(*a_json_arr_reply, -9, "%s Chain not found", l_chain_str);
-            DAP_DELETE(l_policy);
-            return -9;
+        if (!l_policy_activate->flags && l_policy_activate->num < l_last_num) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -16, "Specified policy already activated by CN-%u", l_last_num);
+            DAP_DELETE(l_policy_activate);
+            return -16;
         }
-        l_policy->activate.chain_union.chain = l_chain;
-        l_policy->activate.flags = DAP_FLAG_ADD(l_policy->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM);
-    }
-    if (!l_policy->activate.flags && l_policy->activate.num < l_last_num) {
-        dap_json_rpc_error_add(*a_json_arr_reply, -16, "Specified policy already activated by CN-%u", l_last_num);
-        DAP_DELETE(l_policy);
-        return -16;
     }
+
+    dap_chain_policy_t *l_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, l_data_size + sizeof(dap_chain_policy_t), -5, l_policy_data);
+    l_policy->data_size = l_data_size;
+    l_policy->version = DAP_CHAIN_POLICY_VERSION;
+    l_policy->type = l_policy_type;
+    memcpy(l_policy->data, l_policy_data, l_policy->data_size);
+    DAP_DELETE(l_policy_data);
     // if cmd none - only print preaparing result
     if (l_cmd == CMD_NONE) {
         json_object *l_answer = dap_chain_policy_json_collect(l_policy);
@@ -6117,8 +6128,8 @@ int com_policy(int argc, char **argv, void **reply) {
         return 0;
     }
     // change pointer to id to decree
-    if (l_policy->activate.chain_union.chain) {
-        l_policy->activate.chain_union.chain_id = l_policy->activate.chain_union.chain->id;
+    if (l_policy->type == DAP_CHAIN_POLICY_ACTIVATE && ((dap_chain_policy_activate_t *)(l_policy->data))->chain_union.chain) {
+        ((dap_chain_policy_activate_t *)(l_policy->data))->chain_union.chain_id = ((dap_chain_policy_activate_t *)(l_policy->data))->chain_union.chain->id;
     }
 
     dap_chain_datum_decree_t *l_decree = s_decree_policy_execute(l_net, l_policy);
-- 
GitLab


From 3e440574989cad1ea70ef635971c2d35341c09e1 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Tue, 4 Mar 2025 08:57:53 +0300
Subject: [PATCH 15/25] [*] update commands

---
 modules/node-cli/dap_chain_node_cli_cmd.c | 30 ++++++++++++++---------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index 7c5a465946..1cb359a206 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -5927,18 +5927,26 @@ int com_policy(int argc, char **argv, void **reply) {
         l_deactivate_count = 0,
         l_certs_count = 0;
     dap_cert_t **l_certs = NULL;
+    bool l_execute = false;
 
-    enum { CMD_NONE = 0, CMD_EXECUTE, CMD_DEACTIVATE, CMD_FIND, CMD_LIST };  
+    enum { CMD_NONE = 0, CMD_ACTIVATE, CMD_DEACTIVATE, CMD_FIND, CMD_LIST };  
     int l_arg_index = 1;
 
     int l_cmd = CMD_NONE;
-    if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "execute", NULL))
-        l_cmd = CMD_EXECUTE;
+    if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "activate", NULL))
+        l_cmd = CMD_ACTIVATE;
+    else if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "deactivate", NULL))
+            l_cmd = CMD_DEACTIVATE;
     else if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "find", NULL))
         l_cmd = CMD_FIND;
     else if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "list", NULL))
         l_cmd = CMD_LIST;
 
+    if (l_cmd == CMD_NONE) {
+        dap_json_rpc_error_add(*a_json_arr_reply, -4, "Unknown subcommand");
+        return -4;
+    }
+
     dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-net", &l_net_str);
 
     if (!l_net_str) {
@@ -6021,8 +6029,9 @@ int com_policy(int argc, char **argv, void **reply) {
     dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-block_stop", &l_block_stop_str);
     dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-deactivate", &l_deactivate_str);
     dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-certs", &l_certs_str);
+    l_execute = dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-execute", NULL);
 
-    if (l_cmd == CMD_EXECUTE || l_cmd == CMD_DEACTIVATE) {
+    if (l_execute) {
         if (!l_certs_str) {
             dap_json_rpc_error_add(*a_json_arr_reply, -4, "Command 'execute' requires parameter -certs");
             return -4;
@@ -6034,12 +6043,11 @@ int com_policy(int argc, char **argv, void **reply) {
         }
     }
 
-    if (l_policy_num == l_last_num) {
-        dap_json_rpc_error_add(*a_json_arr_reply, -15, "Specified policy num already existed");
-        return -15;
-    }
-
-    if (l_cmd == CMD_EXECUTE) {
+    if (l_cmd == CMD_ACTIVATE) {
+        if (l_policy_num == l_last_num) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -15, "Specified policy num already existed");
+            return -15;
+        }
         l_policy_type = DAP_CHAIN_POLICY_ACTIVATE;
         l_data_size = sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t);
         l_policy_data = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(void, l_data_size, -5);
@@ -6113,7 +6121,7 @@ int com_policy(int argc, char **argv, void **reply) {
     memcpy(l_policy->data, l_policy_data, l_policy->data_size);
     DAP_DELETE(l_policy_data);
     // if cmd none - only print preaparing result
-    if (l_cmd == CMD_NONE) {
+    if (!l_execute) {
         json_object *l_answer = dap_chain_policy_json_collect(l_policy);
         char l_time[DAP_TIME_STR_SIZE] = {};
         dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, dap_time_now());
-- 
GitLab


From e7dbd262ea7f6377f04491ffb39a69696a9eec25 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Tue, 4 Mar 2025 10:21:27 +0000
Subject: [PATCH 16/25] [*] fix error

---
 modules/chain/dap_chain_policy.c          | 84 ++++++++++++++---------
 modules/chain/include/dap_chain_policy.h  |  2 +-
 modules/node-cli/dap_chain_node_cli_cmd.c |  9 +--
 3 files changed, 56 insertions(+), 39 deletions(-)

diff --git a/modules/chain/dap_chain_policy.c b/modules/chain/dap_chain_policy.c
index 28f780d838..c4881d538f 100644
--- a/modules/chain/dap_chain_policy.c
+++ b/modules/chain/dap_chain_policy.c
@@ -66,6 +66,32 @@ DAP_STATIC_INLINE int s_policy_num_compare(dap_list_t  *a_list1, dap_list_t  *a_
         ((dap_chain_policy_activate_t *)(l_policy1->data))->num > ((dap_chain_policy_activate_t *)(l_policy2->data))->num ? 1 : -1;
 }
 
+DAP_STATIC_INLINE bool s_policy_is_cond(dap_chain_policy_t *a_policy)
+{
+    return a_policy->type == DAP_CHAIN_POLICY_ACTIVATE &&
+        (DAP_FLAG_CHECK(((dap_chain_policy_activate_t *)(a_policy->data))->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS) ||
+        DAP_FLAG_CHECK(((dap_chain_policy_activate_t *)(a_policy->data))->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM));
+}
+
+static bool s_policy_cond_activated(dap_chain_policy_activate_t *a_policy_activate)
+{
+    bool l_ret = false;
+    if (DAP_FLAG_CHECK(a_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS)) {
+        time_t l_current_time = dap_time_now();
+        if (l_current_time >= a_policy_activate->ts_start && (!a_policy_activate->ts_stop || l_current_time <= a_policy_activate->ts_stop))
+        l_ret |= true;
+    }
+    if (DAP_FLAG_CHECK(a_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM)) {
+        if (!a_policy_activate->chain_union.chain) {
+            log_it(L_ERROR, "Chain is null in policy item with upped DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM flag");
+            return l_ret;
+        }
+        if ( a_policy_activate->chain_union.chain->atom_num_last >= a_policy_activate->block_start && (!a_policy_activate->block_stop || a_policy_activate->chain_union.chain->atom_num_last <= a_policy_activate->block_stop))
+            l_ret |= true;
+    }
+    return l_ret;
+}
+
 /**
  * @brief init policy commands
  * @return 0 if pass, other if error
@@ -185,41 +211,23 @@ int dap_chain_policy_add_to_exception_list(uint32_t a_policy_num, uint64_t a_net
  */
 bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id)
 {
-    bool l_ret = false;
+    const bool l_ret_false = false;
     struct policy_net_list_item *l_net_item = s_net_find(a_net_id);
-    dap_return_val_if_pass(!l_net_item, l_ret);
-    if (l_net_item->last_num_policy < a_policy_num)
-        return l_ret;
+    dap_return_val_if_pass(!l_net_item, l_ret_false);
     // exception list check
     if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)a_policy_num, NULL))
-        return l_ret;
+        return l_ret_false;
     // seach politics to condition check
     dap_chain_policy_t *l_to_search = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t), false);
     l_to_search->type = DAP_CHAIN_POLICY_ACTIVATE;
     ((dap_chain_policy_activate_t *)(l_to_search->data))->num = a_policy_num;
-    dap_list_t *l_list_item = dap_list_find(l_net_item->policies, &l_to_search, s_policy_num_compare);
+    dap_list_t *l_list_item = dap_list_find(l_net_item->policies, l_to_search, s_policy_num_compare);
     DAP_DELETE(l_to_search);
-    if (!l_list_item) {
-        if (l_net_item->last_num_policy > a_policy_num)  // use cumulative principle without check conditions
-            return true;
-        return l_ret;
-    }
-    dap_chain_policy_activate_t *l_policy_item = (dap_chain_policy_activate_t *)(((dap_chain_policy_t *)l_list_item->data)->data);
-    // condition check
-    if (DAP_FLAG_CHECK(l_policy_item->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS)) {
-        time_t l_current_time = dap_time_now();
-        if (l_current_time < l_policy_item->ts_start || (l_policy_item->ts_stop && l_current_time > l_policy_item->ts_stop))
-            return l_ret;
+    if (l_list_item && s_policy_is_cond((dap_chain_policy_t *)l_list_item->data)) {
+        return s_policy_cond_activated((dap_chain_policy_activate_t *)((dap_chain_policy_t *)(l_list_item->data))->data);
     }
-    if (DAP_FLAG_CHECK(l_policy_item->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM)) {
-        if (!l_policy_item->chain_union.chain) {
-            log_it(L_ERROR, "Chain is null in policy item with upped DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM flag");
-            return l_ret;
-        }
-        if ( l_policy_item->chain_union.chain->atom_num_last < l_policy_item->block_start || (l_policy_item->block_stop && l_policy_item->chain_union.chain->atom_num_last > l_policy_item->block_stop))
-            return l_ret;
-    }
-    return true;
+    // cumulative return
+    return a_policy_num <= l_net_item->last_num_policy;
 }
 
 /**
@@ -239,7 +247,7 @@ dap_chain_policy_t *dap_chain_policy_find(uint32_t a_policy_num, uint64_t a_net_
     dap_chain_policy_t *l_to_search = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t), false);
     l_to_search->type = DAP_CHAIN_POLICY_ACTIVATE;
     ((dap_chain_policy_activate_t *)(l_to_search->data))->num = a_policy_num;
-    dap_list_t *l_find = dap_list_find(l_net_item->policies, &l_to_search, s_policy_num_compare);
+    dap_list_t *l_find = dap_list_find(l_net_item->policies, l_to_search, s_policy_num_compare);
     DAP_DELETE(l_to_search);
     if (!l_find) {
         log_it(L_DEBUG, "Can't find CN-%u in net %"DAP_UINT64_FORMAT_X, a_policy_num, a_net_id);
@@ -269,22 +277,30 @@ json_object *dap_chain_policy_list(uint64_t a_net_id)
 
     dap_string_t *l_active_str = dap_string_new("");
     dap_string_t *l_inactive_str = dap_string_new("");
+    if (l_net_item->last_num_policy)
+        dap_string_append_printf(l_active_str, "%s CN-%u ", dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_net_item->last_num_policy, NULL) ? "<" : "<=", l_net_item->last_num_policy);
+    json_object_object_add(l_ret, "cumulative active", json_object_new_string(l_active_str->str));
+    dap_string_erase(l_active_str, 0, -1);
     for (dap_list_t *l_iter = dap_list_first(l_net_item->policies); l_iter; l_iter = l_iter->next) {
         dap_chain_policy_activate_t *l_policy_activate =  (dap_chain_policy_activate_t *)((dap_chain_policy_t *)(l_iter->data))->data;
-        if (dap_chain_policy_activated(l_policy_activate->num, a_net_id))
-            dap_string_append_printf(l_active_str, "CN-%u ", l_policy_activate->num);
-        else
-            dap_string_append_printf(l_inactive_str, "CN-%u ", l_policy_activate->num);
+        if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_policy_activate->num, NULL))
+            continue;
+        if (s_policy_is_cond((dap_chain_policy_t *)(l_iter->data))) {
+            if (s_policy_cond_activated(l_policy_activate))
+                dap_string_append_printf(l_active_str, "CN-%u ", l_policy_activate->num);
+            else
+                dap_string_append_printf(l_inactive_str, "CN-%u ", l_policy_activate->num);
+        }
     }
-    json_object_object_add(l_ret, "active", json_object_new_string(l_active_str->str));
-    json_object_object_add(l_ret, "inactive", json_object_new_string(l_inactive_str->str));
+    json_object_object_add(l_ret, "conditional active", json_object_new_string(l_active_str->str));
+    json_object_object_add(l_ret, "conditional inactive", json_object_new_string(l_inactive_str->str));
     
     dap_string_free(l_active_str, true);
     dap_string_erase(l_inactive_str, 0, -1);
     for (dap_list_t *l_iter = dap_list_first(l_net_item->exception_list); l_iter; l_iter = l_iter->next) {
         dap_string_append_printf(l_inactive_str, "CN-%u ", (uint32_t)(uintptr_t)l_iter->data);
     }
-    json_object_object_add(l_ret, "in exception list", json_object_new_string(l_inactive_str->str));
+    json_object_object_add(l_ret, "exception list", json_object_new_string(l_inactive_str->str));
     dap_string_free(l_inactive_str, true);
     return l_ret;
 }
diff --git a/modules/chain/include/dap_chain_policy.h b/modules/chain/include/dap_chain_policy.h
index 3409bb26bf..5184524ab7 100644
--- a/modules/chain/include/dap_chain_policy.h
+++ b/modules/chain/include/dap_chain_policy.h
@@ -58,7 +58,7 @@ typedef struct dap_chain_policy_deactivate {
     uint64_t flags;
     uint32_t count;
     uint32_t nums[];
-} DAP_ALIGN_PACKED dap_chain_policy_deactivate_t;
+} dap_chain_policy_deactivate_t;
 
 typedef struct dap_chain_policy {
     uint16_t version;
diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index 1cb359a206..45c2ffe204 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -5979,11 +5979,12 @@ int com_policy(int argc, char **argv, void **reply) {
         l_policy_type = DAP_CHAIN_POLICY_DEACTIVATE;
         l_deactivate_count = dap_str_symbol_count(l_num_str, ',') + 1;
         l_deactivate_array = dap_strsplit(l_num_str, ",", l_deactivate_count);
-        l_data_size = dap_chain_policy_deactivate_calc_size(l_deactivate_count);
-        l_policy_data = DAP_NEW_Z(l_data_size);
+        l_data_size = sizeof(dap_chain_policy_deactivate_t) + l_deactivate_count * sizeof(uint32_t);
+        l_policy_data = DAP_NEW_Z_SIZE(void, l_data_size);
         if (!l_policy_data) {
-            log_it(L_ERROR, "%s", c_error_memory_alloc);
+            dap_json_rpc_error_add(*a_json_arr_reply, -16, "%s", c_error_memory_alloc);
             dap_strfreev(l_deactivate_array);
+            return -16;
         }
         ((dap_chain_policy_deactivate_t *)l_policy_data)->count = l_deactivate_count;
         for (size_t i = 0; i < l_deactivate_count; ++i) {
@@ -6049,7 +6050,7 @@ int com_policy(int argc, char **argv, void **reply) {
             return -15;
         }
         l_policy_type = DAP_CHAIN_POLICY_ACTIVATE;
-        l_data_size = sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t);
+        l_data_size = sizeof(dap_chain_policy_activate_t);
         l_policy_data = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(void, l_data_size, -5);
         dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)l_policy_data;
         
-- 
GitLab


From bb98dc4a86b8f1db84a8c8ed3e92f69a5378b23c Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Tue, 4 Mar 2025 11:00:54 +0000
Subject: [PATCH 17/25] [*] config and decree update

---
 modules/ledger/dap_chain_ledger_decree.c  |  4 ++--
 modules/node-cli/dap_chain_node_cli.c     | 11 ++++++++---
 modules/node-cli/dap_chain_node_cli_cmd.c | 11 +++++++----
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/modules/ledger/dap_chain_ledger_decree.c b/modules/ledger/dap_chain_ledger_decree.c
index 5895660de9..a0a62507d5 100644
--- a/modules/ledger/dap_chain_ledger_decree.c
+++ b/modules/ledger/dap_chain_ledger_decree.c
@@ -663,8 +663,8 @@ const char *l_ban_addr;
             l_policy = DAP_DUP_SIZE_RET_VAL_IF_FAIL(l_policy, dap_chain_policy_get_size(l_policy), -106);
             if (l_policy->type == DAP_CHAIN_POLICY_ACTIVATE) {
                 dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)l_policy->data;
-                DAP_FLAG_CHECK(l_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM);
-                l_policy_activate->chain_union.chain = dap_chain_find_by_id(a_net->pub.id, l_policy_activate->chain_union.chain_id);
+                if(DAP_FLAG_CHECK(l_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM));
+                    l_policy_activate->chain_union.chain = dap_chain_find_by_id(a_net->pub.id, l_policy_activate->chain_union.chain_id);
             }
             return dap_chain_policy_add(l_policy, a_net->pub.id.uint64);
         }
diff --git a/modules/node-cli/dap_chain_node_cli.c b/modules/node-cli/dap_chain_node_cli.c
index f6268aa2d6..1563297a62 100644
--- a/modules/node-cli/dap_chain_node_cli.c
+++ b/modules/node-cli/dap_chain_node_cli.c
@@ -381,7 +381,8 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                 "file clear_log\n"
                 "\t CAUTION !!! This command will clear the entire log file\n");
 
-    dap_cli_server_cmd_add ("policy", com_policy, "Policy commands", "policy - prepare or create policy execute decree\n"
+    dap_cli_server_cmd_add ("policy", com_policy, "Policy commands",
+                "policy activate - prepare policy activate decree\n"
                 "\t[execute] - used to create policy decree, otherwise show policy decree draft\n"
                 "\t-net <net_name>\n"
                 "\t-num <policy_num>\n"
@@ -390,8 +391,12 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                 "\t{\n\t\t[-block_start <block_num>] - block num to start policy\n"
                 "\t\t[-block_stop <block_num>] - block num to stop policy\n"
                 "\t\t-chain <chain_name> - chain name to check blocks num\n\t}\n"
-                "\t[-deactivate <num1[,num2,...,numN]>] - list deactivated policy\n"
-                "\t[-certs <cert1[,cert2,...,certN]>] - list signing certs\n"
+                "\t-certs <cert1[,cert2,...,certN]> - list signing certs\n"
+                "policy deactivate - prepare policy deactivate decree\n"
+                "\t[execute] - used to create policy decree, otherwise show policy decree draft\n"
+                "\t-net <net_name>\n"
+                "\t-num <num1[,num2,...,numN]> - deactivated policy list\n"
+                "\t-certs <cert1[,cert2,...,certN]> - list signing certs\n"
                 "policy find - find info about policy in net\n"
                 "\t-net <net_name>\n"
                 "\t-num <policy_num>\n"
diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index 45c2ffe204..c6d3c4d96c 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -5990,9 +5990,10 @@ int com_policy(int argc, char **argv, void **reply) {
         for (size_t i = 0; i < l_deactivate_count; ++i) {
             l_policy_num = strtoull(l_deactivate_array[i], NULL, 10);
             if (!dap_chain_policy_num_is_valid(l_policy_num)) {
-                log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list", l_policy_num);
-                --((dap_chain_policy_deactivate_t *)l_policy_data)->count;
-                continue;
+                dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy nums sould be less or equal than %u and not equal 0", dap_maxval((uint32_t)l_policy_num));
+                dap_strfreev(l_deactivate_array);
+                DAP_DELETE(l_policy_data);
+                return -16;
             }
             ((dap_chain_policy_deactivate_t *)l_policy_data)->nums[i] = l_policy_num;
         }
@@ -6000,7 +6001,7 @@ int com_policy(int argc, char **argv, void **reply) {
     } else {
         l_policy_num = strtoull(l_num_str, NULL, 10);
         if (!dap_chain_policy_num_is_valid(l_policy_num)) {
-            dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy num sould be less or equal than %u and not equal 0", 77777);
+            dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy num sould be less or equal than %u and not equal 0", dap_maxval((uint32_t)l_policy_num));
             return -16;
         }
     }
@@ -6035,11 +6036,13 @@ int com_policy(int argc, char **argv, void **reply) {
     if (l_execute) {
         if (!l_certs_str) {
             dap_json_rpc_error_add(*a_json_arr_reply, -4, "Command 'execute' requires parameter -certs");
+            DAP_DELETE(l_policy_data);
             return -4;
         }
         dap_cert_parse_str_list(l_certs_str, &l_certs, &l_certs_count);
         if (!l_certs || !l_certs_count) {
             dap_json_rpc_error_add(*a_json_arr_reply, -5, "Specified certificates not found");
+            DAP_DELETE(l_policy_data);
             return -5;
         }
     }
-- 
GitLab


From 653ecba994198fd3109338c6c0b7793aa8cb955a Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Wed, 5 Mar 2025 04:26:31 +0000
Subject: [PATCH 18/25] [*] fix flag check

---
 modules/ledger/dap_chain_ledger_decree.c  | 2 +-
 modules/node-cli/dap_chain_node_cli_cmd.c | 6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/modules/ledger/dap_chain_ledger_decree.c b/modules/ledger/dap_chain_ledger_decree.c
index a0a62507d5..ad7d0506cc 100644
--- a/modules/ledger/dap_chain_ledger_decree.c
+++ b/modules/ledger/dap_chain_ledger_decree.c
@@ -663,7 +663,7 @@ const char *l_ban_addr;
             l_policy = DAP_DUP_SIZE_RET_VAL_IF_FAIL(l_policy, dap_chain_policy_get_size(l_policy), -106);
             if (l_policy->type == DAP_CHAIN_POLICY_ACTIVATE) {
                 dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)l_policy->data;
-                if(DAP_FLAG_CHECK(l_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM));
+                if(DAP_FLAG_CHECK(l_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM))
                     l_policy_activate->chain_union.chain = dap_chain_find_by_id(a_net->pub.id, l_policy_activate->chain_union.chain_id);
             }
             return dap_chain_policy_add(l_policy, a_net->pub.id.uint64);
diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index c6d3c4d96c..9ebf3b83ab 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -6019,7 +6019,7 @@ int com_policy(int argc, char **argv, void **reply) {
             json_object_object_add(l_answer, "active", json_object_new_string(dap_chain_policy_activated(((dap_chain_policy_activate_t *)(l_policy->data))->num, l_net->pub.id.uint64) ? "true" : "false"));
             json_object_array_add(*a_json_arr_reply, l_answer);
         } else {
-            json_object_array_add(*a_json_arr_reply, json_object_new_string("Empty reply"));
+            json_object_array_add(*a_json_arr_reply, json_object_new_string("Detailed information not exist"));
         }
         return 0;
     }
@@ -6134,7 +6134,9 @@ int com_policy(int argc, char **argv, void **reply) {
         if (l_answer) {
             json_object_array_add(*a_json_arr_reply, l_answer);
         } else {
-            json_object_array_add(*a_json_arr_reply, json_object_new_string("Empty reply"));
+            dap_json_rpc_error_add(*a_json_arr_reply, -11, "Policy draft creation failed");
+            DAP_DELETE(l_policy);
+            return -11;
         }
         DAP_DELETE(l_policy);
         return 0;
-- 
GitLab


From 013f23024e5afc73c73a84acdab46799ac5ce29e Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Mon, 10 Mar 2025 12:14:53 +0000
Subject: [PATCH 19/25] [*] fix QA errors

---
 modules/chain/dap_chain_policy.c          | 5 ++---
 modules/node-cli/dap_chain_node_cli_cmd.c | 6 +-----
 2 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/modules/chain/dap_chain_policy.c b/modules/chain/dap_chain_policy.c
index c4881d538f..4094f761fc 100644
--- a/modules/chain/dap_chain_policy.c
+++ b/modules/chain/dap_chain_policy.c
@@ -162,7 +162,8 @@ int dap_chain_policy_add(dap_chain_policy_t *a_policy, uint64_t a_net_id)
                 return -3;
             }
             l_net_item->policies = dap_list_insert_sorted(l_net_item->policies, a_policy, s_policy_num_compare);
-            l_net_item->last_num_policy = dap_max(((dap_chain_policy_activate_t *)(a_policy->data))->num, l_net_item->last_num_policy);
+            if (!s_policy_is_cond(a_policy))
+                l_net_item->last_num_policy = dap_max(((dap_chain_policy_activate_t *)(a_policy->data))->num, l_net_item->last_num_policy);
             break;
         case DAP_CHAIN_POLICY_DEACTIVATE:
             for (size_t i = 0; i < ((dap_chain_policy_deactivate_t *)(a_policy->data))->count; ++i) {
@@ -241,8 +242,6 @@ dap_chain_policy_t *dap_chain_policy_find(uint32_t a_policy_num, uint64_t a_net_
     dap_return_val_if_pass(!a_policy_num, NULL);
     struct policy_net_list_item *l_net_item = s_net_find(a_net_id);
     dap_return_val_if_pass(!l_net_item, NULL);
-    if (l_net_item->last_num_policy < a_policy_num)
-        return NULL;
 
     dap_chain_policy_t *l_to_search = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t), false);
     l_to_search->type = DAP_CHAIN_POLICY_ACTIVATE;
diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index 9ebf3b83ab..ba1b092374 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -6009,10 +6009,6 @@ int com_policy(int argc, char **argv, void **reply) {
     uint32_t l_last_num = dap_chain_policy_get_last_num(l_net->pub.id.uint64);
 
     if (l_cmd == CMD_FIND) {
-        if (l_last_num < l_policy_num) {
-            dap_json_rpc_error_add(*a_json_arr_reply, -15, "Can't find policy CN-%u in net %s", l_policy_num, l_net_str);
-            return -15;
-        }
         dap_chain_policy_t *l_policy = dap_chain_policy_find(l_policy_num, l_net->pub.id.uint64);
         json_object *l_answer = dap_chain_policy_json_collect(l_policy);
         if (l_answer) {
@@ -6031,7 +6027,7 @@ int com_policy(int argc, char **argv, void **reply) {
     dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-block_stop", &l_block_stop_str);
     dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-deactivate", &l_deactivate_str);
     dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-certs", &l_certs_str);
-    l_execute = dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-execute", NULL);
+    l_execute = dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "execute", NULL);
 
     if (l_execute) {
         if (!l_certs_str) {
-- 
GitLab


From c601ad69e64246d377a9e0210be3ec18ed7d2860 Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Mon, 10 Mar 2025 12:40:19 +0000
Subject: [PATCH 20/25] [*] fix decree dump

---
 modules/datum/dap_chain_datum_decree.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/modules/datum/dap_chain_datum_decree.c b/modules/datum/dap_chain_datum_decree.c
index 2b6544165a..54ed219564 100644
--- a/modules/datum/dap_chain_datum_decree.c
+++ b/modules/datum/dap_chain_datum_decree.c
@@ -397,10 +397,10 @@ void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_d
 
         case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE:
             if (l_tsd->size != dap_chain_policy_get_size((dap_chain_policy_t *)(l_tsd->data))) {
-                json_object_object_add(a_json_out, "policy_num", json_object_new_string("WRONG SIZE"));
+                json_object_object_add(a_json_out, "policy_type", json_object_new_string("WRONG SIZE"));
                 break;
             }
-            json_object_object_add(a_json_out, "Policy type", json_object_new_string( dap_chain_policy_to_str((dap_chain_policy_t *)(l_tsd->data))));
+            json_object_object_add(a_json_out, "policy_type", json_object_new_string( dap_chain_policy_to_str((dap_chain_policy_t *)(l_tsd->data))));
             break;
 
         default:
-- 
GitLab


From c52b419b7804c32aef894ccefa1c55ca013d1d5c Mon Sep 17 00:00:00 2001
From: Dmitry Pyzyrkov <dpuzyrkov@gmail.com>
Date: Mon, 10 Mar 2025 19:26:17 +0700
Subject: [PATCH 21/25] [*] emit-delegate adds tds in right palce

---
 .../dap_chain_net_srv_emit_delegate.c         | 27 ++++++++++---------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index 320fb9b283..c2aef7e72b 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -200,7 +200,7 @@ static char *s_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_t *a_chain, const ch
 
 #define m_sign_fail(e,s) { dap_json_rpc_error_add(a_json_arr_reply, e, s); log_it(L_ERROR, "%s", s); return NULL; }
 
-#define m_tx_fail(e,s) { DAP_DELETE(l_tx); m_sign_fail(e,s) }
+#define m_tx_fail(e,s) { DAP_DELETE(l_tx); m_sign_fail(e,s); log_it(L_ERROR, "%s", s); }
 
 static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
                                                   const char *a_token_ticker, uint256_t a_value, uint256_t a_fee,
@@ -437,7 +437,11 @@ static bool s_is_key_present(dap_chain_tx_out_cond_t *a_cond, dap_enc_key_t *a_e
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
     dap_chain_addr_t **a_to_addr, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* a_tsd_items)
 {
-    dap_return_val_if_pass(!a_to_addr || !a_value || !a_addr_count || !a_enc_key || !a_tx_in_hash, NULL );
+    dap_return_val_if_pass(!a_to_addr, NULL);
+    dap_return_val_if_pass(!a_value, NULL);
+    dap_return_val_if_pass(!a_addr_count, NULL);
+    dap_return_val_if_pass(!a_enc_key, NULL);
+    dap_return_val_if_pass(!a_tx_in_hash, NULL);
     // create empty transaction
     dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
 
@@ -456,7 +460,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
         if (SUM_256_256(l_value, a_value[i], &l_value))
             m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
     }
-
+    log_it(L_DEBUG, "l_value sum %s", dap_chain_balance_print(l_value));
     bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr);
     if (l_net_fee_used && SUM_256_256(l_fee_total, l_net_fee, &l_fee_total))
         m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
@@ -502,7 +506,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
 
     // add 'out' or 'out_ext' item for emission
     for (size_t i = 0; i < a_addr_count; ++i) {
-        int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, a_to_addr[i], a_value[i]) :
+        int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &a_to_addr[i], a_value[i]) :
             dap_chain_datum_tx_add_out_ext_item(&l_tx, a_to_addr[i], a_value[i], l_tx_ticker);
         if (rc != 1)
             m_tx_fail(ERROR_COMPOSE, "Cant add tx output");
@@ -521,6 +525,12 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     }
     DAP_DELETE(l_out_cond);
 
+    if (a_addr_count > 1) {
+        tsd_items = dap_list_append(tsd_items, dap_chain_datum_tx_item_tsd_create(&a_addr_count, DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT, sizeof(uint32_t)));
+        if (!tsd_items) {
+             m_tx_fail(ERROR_COMPOSE, "Can't add TSD section item with addr count");
+        }
+    }
 
     // add track for takeoff from conditional value
     dap_chain_tx_tsd_t *l_takeoff_tsd = dap_chain_datum_tx_item_tsd_create(&l_value, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF, sizeof(uint256_t));
@@ -938,15 +948,6 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
     }
     dap_strfreev(l_to_addr_str_array);
 
-
-    if (l_addr_el_count > 1) {
-        l_tsd_list = dap_list_append(l_tsd_list, dap_chain_datum_tx_item_tsd_create(&l_addr_el_count, DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT, sizeof(uint32_t)));
-        if (!l_tsd_list) {
-            dap_json_rpc_error_add(*a_json_arr_reply, ERROR_COMPOSE, "Internal error in tsd list creation");
-            return ERROR_COMPOSE;
-        }
-    }
-
     // Create emission from conditional transaction
     dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_to_addr, l_value, l_addr_el_count, l_fee, &l_tx_in_hash, l_tsd_list);
     DAP_DEL_ARRAY(l_to_addr, l_addr_el_count);
-- 
GitLab


From dd9646411620e6f1224acacb9dd529d14cee97ab Mon Sep 17 00:00:00 2001
From: Dmitry Pyzyrkov <dpuzyrkov@gmail.com>
Date: Mon, 10 Mar 2025 20:53:42 +0700
Subject: [PATCH 22/25] [*] - additional log + some fixes

---
 .../dap_chain_net_srv_emit_delegate.c             | 15 ++++++++-------
 .../include/dap_chain_net_srv_emit_delegate.h     |  2 +-
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index c2aef7e72b..45f31bcfd0 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -435,7 +435,7 @@ static bool s_is_key_present(dap_chain_tx_out_cond_t *a_cond, dap_enc_key_t *a_e
 }
 
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
-    dap_chain_addr_t **a_to_addr, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* a_tsd_items)
+    dap_chain_addr_t *a_to_addr, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items)
 {
     dap_return_val_if_pass(!a_to_addr, NULL);
     dap_return_val_if_pass(!a_value, NULL);
@@ -460,7 +460,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
         if (SUM_256_256(l_value, a_value[i], &l_value))
             m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
     }
-    log_it(L_DEBUG, "l_value sum %s", dap_chain_balance_print(l_value));
+
     bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr);
     if (l_net_fee_used && SUM_256_256(l_fee_total, l_net_fee, &l_fee_total))
         m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
@@ -507,7 +507,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     // add 'out' or 'out_ext' item for emission
     for (size_t i = 0; i < a_addr_count; ++i) {
         int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &a_to_addr[i], a_value[i]) :
-            dap_chain_datum_tx_add_out_ext_item(&l_tx, a_to_addr[i], a_value[i], l_tx_ticker);
+            dap_chain_datum_tx_add_out_ext_item(&l_tx, &a_to_addr[i], a_value[i], l_tx_ticker);
         if (rc != 1)
             m_tx_fail(ERROR_COMPOSE, "Cant add tx output");
     }
@@ -519,6 +519,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     if (!l_out_cond)
         m_tx_fail(ERROR_MEMORY, c_error_memory_alloc);
     l_out_cond->header.value = l_value_back;
+    
     if (-1 == dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond)) {
         DAP_DELETE(l_out_cond);
         m_tx_fail(ERROR_COMPOSE, "Cant add emission cond output");
@@ -526,10 +527,9 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     DAP_DELETE(l_out_cond);
 
     if (a_addr_count > 1) {
-        tsd_items = dap_list_append(tsd_items, dap_chain_datum_tx_item_tsd_create(&a_addr_count, DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT, sizeof(uint32_t)));
-        if (!tsd_items) {
-             m_tx_fail(ERROR_COMPOSE, "Can't add TSD section item with addr count");
-        }
+        dap_chain_tx_tsd_t * l_addr_cnt_tsd = dap_chain_datum_tx_item_tsd_create(&a_addr_count, DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT, sizeof(uint32_t));
+        if (!l_addr_cnt_tsd || dap_chain_datum_tx_add_item(&l_tx, l_addr_cnt_tsd) != 1 )
+            m_tx_fail(ERROR_COMPOSE, "Can't add TSD section item with addr count");
     }
 
     // add track for takeoff from conditional value
@@ -949,6 +949,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
     dap_strfreev(l_to_addr_str_array);
 
     // Create emission from conditional transaction
+    
     dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_to_addr, l_value, l_addr_el_count, l_fee, &l_tx_in_hash, l_tsd_list);
     DAP_DEL_ARRAY(l_to_addr, l_addr_el_count);
     DAP_DEL_MULTY(l_value, l_to_addr, l_enc_key);
diff --git a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
index 1e14d527bf..9e4be649c2 100644
--- a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
+++ b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
@@ -14,7 +14,7 @@ int dap_chain_net_srv_emit_delegate_init();
 void dap_chain_net_srv_emit_delegate_deinit();
 
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_rweply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
-                                                dap_chain_addr_t **a_addr_to, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t *tsd_items);
+                                                dap_chain_addr_t *a_addr_to, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t *tsd_items);
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
                                                     uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items);
 
-- 
GitLab


From 5e7e9f44102585374b946a2dd7d27dc5050ed32b Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Mon, 10 Mar 2025 15:35:41 +0000
Subject: [PATCH 23/25] [*] adopt to one memory alloc to chain_addr array

---
 modules/chain/dap_chain_common.c              | 74 +++++++++++++++----
 modules/chain/include/dap_chain_common.h      |  1 +
 .../dap_chain_net_srv_emit_delegate.c         | 39 ++--------
 .../include/dap_chain_net_srv_emit_delegate.h |  2 +-
 4 files changed, 70 insertions(+), 46 deletions(-)

diff --git a/modules/chain/dap_chain_common.c b/modules/chain/dap_chain_common.c
index 3830f97d8d..d3ce228907 100644
--- a/modules/chain/dap_chain_common.c
+++ b/modules/chain/dap_chain_common.c
@@ -76,25 +76,73 @@ dap_chain_addr_str_t dap_chain_addr_to_str_static_(const dap_chain_addr_t *a_add
     return res;
 }
 
+/**
+ * @brief s_addr_from_str
+ * @param [out] a_addr - pointer to addr fill
+ * @param [in] a_str - string with one addr
+ * @return 0 if pass, other if error
+ */
+static int s_addr_from_str(dap_chain_addr_t *a_addr, const char *a_str)
+{
+    dap_return_val_if_pass(!a_addr || !a_str || !a_str[0], -1);
+    if (!dap_strcmp(a_str, "null") || !dap_strcmp(a_str, "0")) {
+        memset(a_addr, 0, sizeof(dap_chain_addr_t));
+        return 0;
+    }
+    int l_ret = 0;
+    size_t l_ret_size = DAP_ENC_BASE58_DECODE_SIZE(strlen(a_str));
+    dap_chain_addr_t *l_addr_cur = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_addr_t, l_ret_size, -2);
+    if (dap_enc_base58_decode(a_str, l_addr_cur) == sizeof(dap_chain_addr_t) && !dap_chain_addr_check_sum(l_addr_cur)) {
+        memcpy(a_addr, l_addr_cur, sizeof(dap_chain_addr_t));
+    } else {
+        l_ret = -3;
+    }
+    DAP_DELETE(l_addr_cur);
+    return l_ret;
+}
+
 /**
  * @brief dap_chain_str_to_addr
- * @param a_addr
- * @return
+ * @param a_str - string with one addr
+ * @return pointer to dap_chain_addr_t if pass, if not - NULL
  */
-dap_chain_addr_t* dap_chain_addr_from_str(const char *a_str)
+dap_chain_addr_t *dap_chain_addr_from_str(const char *a_str)
 {
-    size_t l_str_len = (a_str) ? strlen(a_str) : 0;
-    if(l_str_len <= 0)
+    dap_chain_addr_t *l_ret = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_addr_t, NULL);
+    if (s_addr_from_str(l_ret, a_str)) {
+        DAP_DELETE(l_ret);
         return NULL;
-    if (!dap_strcmp(a_str, "null") || !dap_strcmp(a_str, "0")) {
-        return DAP_NEW_Z(dap_chain_addr_t);
     }
-    size_t l_ret_size = DAP_ENC_BASE58_DECODE_SIZE(l_str_len);
-    dap_chain_addr_t *l_addr = DAP_NEW_Z_SIZE(dap_chain_addr_t, l_ret_size);
-    return ( dap_enc_base58_decode(a_str, l_addr) == sizeof(dap_chain_addr_t) ) 
-        && !dap_chain_addr_check_sum(l_addr)
-            ? l_addr
-            : ( DAP_DELETE(l_addr), NULL );
+    return l_ret;
+}
+
+
+/**
+ * @brief parce addrs string div by ',', alloc memory to addrs
+ * @param a_addr_str - ddrs string div by ','
+ * @param a_addr - pointer to memory alloc
+ * @return addr count
+ */
+size_t dap_chain_addr_from_str_array(const char *a_addr_str, dap_chain_addr_t **a_addr)
+{
+    dap_return_val_if_pass(!a_addr_str || !a_addr, NULL);
+    size_t l_count = dap_str_symbol_count(a_addr_str, ',') + 1;
+    dap_chain_addr_t *l_addr = DAP_NEW_Z_COUNT_RET_VAL_IF_FAIL(dap_chain_addr_t, l_count, 0);
+    char **l_addr_str_array = dap_strsplit(a_addr_str, ",", l_count);
+    if (!l_addr_str_array) {
+        DAP_DELETE(l_addr);
+        return 0;
+    }
+    for (size_t i = 0; i < l_count; ++i) {
+        if (s_addr_from_str(l_addr + i, l_addr_str_array[i])) {
+            DAP_DELETE(l_addr);
+            dap_strfreev(l_addr_str_array);
+            return 0;
+        }
+    }
+    dap_strfreev(l_addr_str_array);
+    *a_addr = l_addr;
+    return l_count;
 }
 
 bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr)
diff --git a/modules/chain/include/dap_chain_common.h b/modules/chain/include/dap_chain_common.h
index 1e758ae7c6..974b8e7e8b 100644
--- a/modules/chain/include/dap_chain_common.h
+++ b/modules/chain/include/dap_chain_common.h
@@ -227,6 +227,7 @@ dap_chain_addr_str_t dap_chain_addr_to_str_static_(const dap_chain_addr_t *a_add
 #define dap_chain_addr_to_str dap_chain_addr_to_str_static
 
 dap_chain_addr_t* dap_chain_addr_from_str(const char *str);
+size_t dap_chain_addr_from_str_array(const char *a_addr_str, dap_chain_addr_t **a_addr);
 bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr);
 
 dap_chain_srv_uid_t dap_chain_net_srv_uid_from_str(const char* a_str);
diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index 45f31bcfd0..541a4dc02a 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -435,7 +435,7 @@ static bool s_is_key_present(dap_chain_tx_out_cond_t *a_cond, dap_enc_key_t *a_e
 }
 
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
-    dap_chain_addr_t *a_to_addr, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items)
+    dap_chain_addr_t *a_to_addr, uint256_t *a_value, uint32_t a_addr_count /*!not change type!*/, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items)
 {
     dap_return_val_if_pass(!a_to_addr, NULL);
     dap_return_val_if_pass(!a_value, NULL);
@@ -506,8 +506,8 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
 
     // add 'out' or 'out_ext' item for emission
     for (size_t i = 0; i < a_addr_count; ++i) {
-        int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &a_to_addr[i], a_value[i]) :
-            dap_chain_datum_tx_add_out_ext_item(&l_tx, &a_to_addr[i], a_value[i], l_tx_ticker);
+        int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, a_to_addr + i, a_value[i]) :
+            dap_chain_datum_tx_add_out_ext_item(&l_tx, a_to_addr + i, a_value[i], l_tx_ticker);
         if (rc != 1)
             m_tx_fail(ERROR_COMPOSE, "Cant add tx output");
     }
@@ -835,7 +835,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
     const char *l_tx_in_hash_str = NULL, *l_addr_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL;
     
     uint256_t *l_value = NULL;
-    dap_chain_addr_t **l_to_addr = NULL;
+    dap_chain_addr_t *l_to_addr = NULL;
     uint32_t
         l_addr_el_count = 0,  // not change type! use in batching TSD section
         l_value_el_count = 0;
@@ -893,10 +893,11 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
         return ERROR_PARAM;
     }
 
-    l_addr_el_count = dap_str_symbol_count(l_addr_str, ',') + 1;
+    l_addr_el_count = dap_chain_addr_from_str_array(l_addr_str, &l_to_addr);
     l_value_el_count = dap_str_symbol_count(l_value_str, ',') + 1;
 
     if (l_addr_el_count != l_value_el_count) {
+        DAP_DELETE(l_to_addr);
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "num of '-to_addr' and '-value' should be equal");
         return ERROR_VALUE;
     }
@@ -923,35 +924,9 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
     }
     dap_strfreev(l_value_array);
 
-    l_to_addr = DAP_NEW_Z_COUNT(dap_chain_addr_t *, l_addr_el_count);
-    if (!l_to_addr) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        DAP_DELETE(l_value);
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_MEMORY, c_error_memory_alloc);
-        return ERROR_MEMORY;
-    }
-    char **l_to_addr_str_array = dap_strsplit(l_addr_str, ",", l_addr_el_count);
-    if (!l_to_addr_str_array) {
-        DAP_DEL_MULTY(l_to_addr, l_value);
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Can't read '-to_addr' arg");
-        return ERROR_PARAM;
-    }
-    for (size_t i = 0; i < l_addr_el_count; ++i) {
-        l_to_addr[i] = dap_chain_addr_from_str(l_to_addr_str_array[i]);
-        if(!l_to_addr[i]) {
-            DAP_DEL_ARRAY(l_to_addr, i);
-            DAP_DEL_MULTY(l_to_addr, l_value);
-            dap_strfreev(l_to_addr_str_array);
-            dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Incorrect addr format for string %s", l_addr_str);
-            return ERROR_VALUE;
-        }
-    }
-    dap_strfreev(l_to_addr_str_array);
-
     // Create emission from conditional transaction
     
     dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_to_addr, l_value, l_addr_el_count, l_fee, &l_tx_in_hash, l_tsd_list);
-    DAP_DEL_ARRAY(l_to_addr, l_addr_el_count);
     DAP_DEL_MULTY(l_value, l_to_addr, l_enc_key);
     dap_list_free_full(l_tsd_list, NULL);
     if (!l_tx) {
@@ -1099,7 +1074,7 @@ static int s_cli_info(int a_argc, char **a_argv, int a_arg_index, json_object **
             json_object_array_add(l_jobj_pkey_hashes, json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data) : dap_hash_fast_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data)));
         }
         if (l_tsd->type == DAP_CHAIN_TX_OUT_COND_TSD_STR) {
-            json_object_array_add(l_jobj_tags, json_object_new_string(l_tsd->data));
+            json_object_array_add(l_jobj_tags, json_object_new_string((char*)(l_tsd->data)));
         }
     }
     json_object_object_add(l_jobj_take_verify, "owner_hashes", l_jobj_pkey_hashes);
diff --git a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
index 9e4be649c2..79f5a47142 100644
--- a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
+++ b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
@@ -14,7 +14,7 @@ int dap_chain_net_srv_emit_delegate_init();
 void dap_chain_net_srv_emit_delegate_deinit();
 
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_rweply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
-                                                dap_chain_addr_t *a_addr_to, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t *tsd_items);
+                                                dap_chain_addr_t *a_addr_to, uint256_t *a_value, uint32_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t *tsd_items);
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
                                                     uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items);
 
-- 
GitLab


From 532977df924e662ca50de13d9a51b7fa2bbce05e Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Mon, 10 Mar 2025 15:44:40 +0000
Subject: [PATCH 24/25] [*] fix build error

---
 modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index 541a4dc02a..6e735cd22f 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -435,7 +435,7 @@ static bool s_is_key_present(dap_chain_tx_out_cond_t *a_cond, dap_enc_key_t *a_e
 }
 
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
-    dap_chain_addr_t *a_to_addr, uint256_t *a_value, uint32_t a_addr_count /*!not change type!*/, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items)
+    dap_chain_addr_t *a_to_addr, uint256_t *a_value, uint32_t a_addr_count /*!not change type!*/, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* a_tsd_items)
 {
     dap_return_val_if_pass(!a_to_addr, NULL);
     dap_return_val_if_pass(!a_value, NULL);
-- 
GitLab


From d934055ab73377939653fd86598d6fb75826947d Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Mon, 10 Mar 2025 16:26:23 +0000
Subject: [PATCH 25/25] [*] macos pipe error fix

---
 modules/chain/dap_chain_common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/chain/dap_chain_common.c b/modules/chain/dap_chain_common.c
index d3ce228907..388b636759 100644
--- a/modules/chain/dap_chain_common.c
+++ b/modules/chain/dap_chain_common.c
@@ -125,7 +125,7 @@ dap_chain_addr_t *dap_chain_addr_from_str(const char *a_str)
  */
 size_t dap_chain_addr_from_str_array(const char *a_addr_str, dap_chain_addr_t **a_addr)
 {
-    dap_return_val_if_pass(!a_addr_str || !a_addr, NULL);
+    dap_return_val_if_pass(!a_addr_str || !a_addr, 0);
     size_t l_count = dap_str_symbol_count(a_addr_str, ',') + 1;
     dap_chain_addr_t *l_addr = DAP_NEW_Z_COUNT_RET_VAL_IF_FAIL(dap_chain_addr_t, l_count, 0);
     char **l_addr_str_array = dap_strsplit(a_addr_str, ",", l_count);
-- 
GitLab