From e2860893d933e4ef76bc8bb18828050ae336453d Mon Sep 17 00:00:00 2001
From: "Constantin P." <papizh.konstantin@demlabs.net>
Date: Tue, 24 Sep 2024 12:35:45 +0000
Subject: [PATCH] Decree application fix

---
 modules/chain/tests/dap_chain_ledger_tests.c |  2 +-
 modules/net/dap_chain_ledger.c               | 41 +++++++++++---------
 modules/net/dap_chain_net.c                  |  2 +
 modules/net/dap_chain_net_anchor.c           | 10 ++---
 modules/net/dap_chain_net_decree.c           | 22 +++++------
 modules/net/include/dap_chain_ledger.h       |  1 +
 modules/net/include/dap_chain_net_decree.h   |  2 +-
 7 files changed, 43 insertions(+), 37 deletions(-)

diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c
index 2dd5bfa832..1e2a84476a 100644
--- a/modules/chain/tests/dap_chain_ledger_tests.c
+++ b/modules/chain/tests/dap_chain_ledger_tests.c
@@ -351,7 +351,7 @@ int dap_ledger_test_create_reward_decree(dap_chain_t *a_chain, dap_chain_net_id_
     dap_hash_fast_t l_decree_hash = {};
     dap_hash_fast(l_decree, l_decree_size, &l_decree_hash);
     // a_chain->callback_atom_add();
-    dap_assert_PIF(dap_chain_net_decree_apply(&l_decree_hash, l_decree, a_chain)==0, "Decree applying:");
+    dap_assert_PIF(dap_chain_net_decree_apply(&l_decree_hash, l_decree, a_chain, false)==0, "Decree applying:");
     return 0;
 }
 
diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c
index 5c1ef173ea..f20e687aaf 100644
--- a/modules/net/dap_chain_ledger.c
+++ b/modules/net/dap_chain_ledger.c
@@ -276,8 +276,8 @@ typedef struct dap_ledger_private {
     dap_list_t *bridged_tx_notifiers;
     dap_list_t *tx_add_notifiers;
     dap_ledger_cache_tx_check_callback_t cache_tx_check_callback;
-    // HAL
-    dap_ledger_hal_item_t *hal_items;
+    // White- and blacklist
+    dap_ledger_hal_item_t *hal_items, *hrl_items;
 } dap_ledger_private_t;
 
 #define PVT(a) ( (dap_ledger_private_t *) a->_internal )
@@ -561,6 +561,12 @@ inline static dap_ledger_hal_item_t *s_check_hal(dap_ledger_t *a_ledger, dap_has
     return ret;
 }
 
+bool dap_ledger_datum_is_blacklisted(dap_ledger_t *a_ledger, dap_hash_fast_t a_hash) {
+    dap_ledger_hal_item_t *ret = NULL;
+    HASH_FIND(hh, PVT(a_ledger)->hrl_items, &a_hash, sizeof(dap_hash_fast_t), ret);
+    return debug_if(s_debug_more && ret, L_MSG, "Datum %s is blacklisted", dap_hash_fast_to_str_static(&a_hash)), !!ret;
+}
+
 inline static dap_ledger_token_item_t *s_ledger_find_token(dap_ledger_t *a_ledger, const char *a_token_ticker)
 {
     dap_return_val_if_fail(a_ledger && a_token_ticker, NULL);
@@ -2557,27 +2563,24 @@ dap_ledger_t *dap_ledger_create(dap_chain_net_t *a_net, uint16_t a_flags)
         if (strlen(l_entry_name) > 4) {
             if ( strncmp (l_entry_name + strlen(l_entry_name)-4,".cfg",4) == 0 ) { // its .cfg file
                 l_entry_name [strlen(l_entry_name)-4] = 0;
-                log_it(L_DEBUG,"Open chain config \"%s\"...",l_entry_name);
+                log_it(L_DEBUG,"Open chain config \"%s.%s\"...", a_net->pub.name, l_entry_name);
                 l_chains_path = dap_strdup_printf("network/%s/%s", a_net->pub.name, l_entry_name);
                 dap_config_t * l_cfg = dap_config_open(l_chains_path);
-                uint16_t l_whitelist_size;
-                const char **l_whitelist = dap_config_get_array_str(l_cfg, "ledger", "hard_accept_list", &l_whitelist_size);
-                for (uint16_t i = 0; i < l_whitelist_size; ++i) {
-                    dap_ledger_hal_item_t *l_hal_item = DAP_NEW_Z(dap_ledger_hal_item_t);
-                    if (!l_hal_item) {
-                        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-                        DAP_DEL_Z(l_ledger_pvt);
-                        DAP_DEL_Z(l_ledger);
-                        dap_config_close(l_cfg);
-                        DAP_DELETE (l_entry_name);
-                        closedir(l_chains_dir);
-                        return NULL;
-                    }
-                    dap_chain_hash_fast_from_str(l_whitelist[i], &l_hal_item->hash);
-                    HASH_ADD(hh, l_ledger_pvt->hal_items, hash, sizeof(l_hal_item->hash), l_hal_item);
+                uint16_t l_whitelist_size, l_blacklist_size, i;
+                const char **l_whitelist = dap_config_get_array_str(l_cfg, "ledger", "hard_accept_list", &l_whitelist_size),
+                           **l_blacklist = dap_config_get_array_str(l_cfg, "ledger", "hard_reject_list", &l_blacklist_size);
+                for (i = 0; i < l_blacklist_size; ++i) {
+                    dap_ledger_hal_item_t *l_item = DAP_NEW_Z(dap_ledger_hal_item_t);
+                    dap_chain_hash_fast_from_str(l_blacklist[i], &l_item->hash);
+                    HASH_ADD(hh, l_ledger_pvt->hrl_items, hash, sizeof(dap_hash_fast_t), l_item);
+                }
+                for (i = 0; i < l_whitelist_size; ++i) {
+                    dap_ledger_hal_item_t *l_item = DAP_NEW_Z(dap_ledger_hal_item_t);
+                    dap_chain_hash_fast_from_str(l_whitelist[i], &l_item->hash);
+                    HASH_ADD(hh, l_ledger_pvt->hal_items, hash, sizeof(dap_hash_fast_t), l_item);
                 }
                 dap_config_close(l_cfg);
-                log_it(L_DEBUG, "HAL items count for chain %s : %d", l_entry_name, l_whitelist_size);
+                log_it(L_DEBUG, "Chain %s.%s has %d datums in HAL and %d datums in HRL", a_net->pub.name, l_entry_name, l_whitelist_size, l_blacklist_size);
             }
         }
         DAP_DELETE (l_entry_name);
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 25fd42f600..d0a40eba61 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -2806,6 +2806,8 @@ int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t
         return -101;
     }
     dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger;
+    if ( dap_ledger_datum_is_blacklisted(l_ledger, *a_datum_hash) )
+        return log_it(L_ERROR, "Datum is blackilsted"), -100;
     switch (a_datum->header.type_id) {
         case DAP_CHAIN_DATUM_DECREE: {
             dap_chain_datum_decree_t *l_decree = (dap_chain_datum_decree_t *)a_datum->data;
diff --git a/modules/net/dap_chain_net_anchor.c b/modules/net/dap_chain_net_anchor.c
index 5b71028393..84984130f3 100644
--- a/modules/net/dap_chain_net_anchor.c
+++ b/modules/net/dap_chain_net_anchor.c
@@ -168,7 +168,7 @@ int dap_chain_net_anchor_load(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *
         return -109;
     }
 
-    if ((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain)) != 0){
+    if ((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain, true)) != 0){
         debug_if(s_debug_more, L_WARNING, "Decree applying failed");
         return ret_val;
     }
@@ -315,7 +315,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t
                         return -109;
                     }
 
-                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain))!=0){
+                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain, true))!=0){
                         log_it(L_WARNING,"Decree applying failed");
                         return ret_val;
                     }
@@ -351,7 +351,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t
                         log_it(L_WARNING,"Can not find datum hash in anchor data");
                         return -109;
                     }
-                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain))!=0){
+                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain, true))!=0){
                         log_it(L_WARNING,"Decree applying failed");
                         return ret_val;
                     }
@@ -368,7 +368,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t
                         log_it(L_WARNING,"Can not find datum hash in anchor data");
                         return -109;
                     }
-                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain))!=0){
+                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain, true))!=0){
                         log_it(L_WARNING,"Decree applying failed");
                         return ret_val;
                     }
@@ -389,7 +389,7 @@ int dap_chain_net_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t
                         return -109;
                     }
 
-                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain))!=0){
+                    if((ret_val = dap_chain_net_decree_apply(&l_hash, NULL, a_chain, true))!=0){
                         log_it(L_WARNING,"Decree applying failed");
                         return ret_val;
                     }
diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c
index 6aafb2826a..28fbef933c 100644
--- a/modules/net/dap_chain_net_decree.c
+++ b/modules/net/dap_chain_net_decree.c
@@ -52,7 +52,7 @@ typedef struct decree_table {
 
 // Private fuctions prototype
 static bool s_verify_pkey (dap_sign_t *a_sign, dap_chain_net_t *a_net);
-static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_load_mode);
+static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_anchored);
 static int s_service_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply);
 
 static bool s_debug_more = false;
@@ -119,7 +119,7 @@ void dap_chain_net_decree_purge(dap_chain_net_t *a_net)
     dap_chain_net_decree_init(a_net);
 }
 
-static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_decree, size_t a_data_size, dap_chain_hash_fast_t *a_decree_hash, bool a_load_mode)
+static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_decree, size_t a_data_size, dap_chain_hash_fast_t *a_decree_hash, bool a_anchored)
 {
     if (a_data_size < sizeof(dap_chain_datum_decree_t)) {
         log_it(L_WARNING, "Decree size is too small");
@@ -205,7 +205,7 @@ static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_d
     int l_ret = 0;
     switch(a_decree->header.type) {
     case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON:
-        l_ret = s_common_decree_handler(a_decree, a_net, false, a_load_mode);
+        l_ret = s_common_decree_handler(a_decree, a_net, false, a_anchored);
         break;
     case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE:
         l_ret = s_service_decree_handler(a_decree, a_net, false);
@@ -227,7 +227,7 @@ int dap_chain_net_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t
     return s_decree_verify(a_net, a_decree, a_data_size, a_decree_hash, false);
 }
 
-int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_decree_t *a_decree, dap_chain_t *a_chain)
+int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_decree_t *a_decree, dap_chain_t *a_chain, bool a_anchored)
 {
     int ret_val = 0;
     dap_chain_net_t *l_net = NULL;
@@ -282,7 +282,7 @@ int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_d
     // Process decree
     switch(l_new_decree->decree->header.type) {
     case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON:
-        ret_val = s_common_decree_handler(l_new_decree->decree, l_net, true, false);
+        ret_val = s_common_decree_handler(l_new_decree->decree, l_net, true, a_anchored);
         break;
     case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE:
         ret_val = s_service_decree_handler(l_new_decree->decree, l_net, true);
@@ -318,12 +318,12 @@ int dap_chain_net_decree_load(dap_chain_datum_decree_t * a_decree, dap_chain_t *
 
     size_t l_data_size = dap_chain_datum_decree_get_size(a_decree);
 
-    if ((ret_val = s_decree_verify(l_net, a_decree, l_data_size, a_decree_hash, true)) != 0) {
+    if ((ret_val = s_decree_verify(l_net, a_decree, l_data_size, a_decree_hash, false)) != 0) {
         //log_it(L_ERROR, "Decree verification failed!");
         return ret_val;
     }
 
-    return dap_chain_net_decree_apply(a_decree_hash, a_decree, a_chain);
+    return dap_chain_net_decree_apply(a_decree_hash, a_decree, a_chain, false);
 }
 
 int dap_chain_net_decree_reset_applied(dap_chain_net_t *a_net, dap_chain_hash_fast_t *a_decree_hash)
@@ -356,7 +356,7 @@ static bool s_verify_pkey (dap_sign_t *a_sign, dap_chain_net_t *a_net)
     return false;
 }
 
-static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_load_mode)
+static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_anchored)
 {
     uint256_t l_value;
     uint32_t l_sign_type;
@@ -433,10 +433,8 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                 log_it(L_WARNING,"Can't get signer node address from decree.");
                 return -108;
             }
-            if (a_load_mode) {
-                assert(!a_apply);
+            if (!a_anchored)
                 break;
-            }
             if (dap_chain_net_srv_stake_verify_key_and_node(&l_addr, &l_node_addr)) {
                 debug_if(s_debug_more, L_WARNING, "Key and node verification error");
                 return -109;
@@ -485,6 +483,8 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                 log_it(L_WARNING, "Can't apply this decree to specified chain");
                 return -115;
             }
+            if (!a_anchored)
+                break;
             uint16_t l_decree_count = (uint16_t)dap_chain_uint256_to(l_value);
             uint16_t l_current_count = dap_chain_net_srv_stake_get_total_keys(a_net->pub.id, NULL);
             if (l_decree_count > l_current_count) {
diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h
index 9074e4dcf5..f4c2860910 100644
--- a/modules/net/include/dap_chain_ledger.h
+++ b/modules/net/include/dap_chain_ledger.h
@@ -451,6 +451,7 @@ dap_chain_datum_tx_t *dap_ledger_datum_iter_get_last(dap_ledger_datum_iter_t *a_
 void dap_ledger_tx_add_notify(dap_ledger_t *a_ledger, dap_ledger_tx_add_notify_t a_callback, void *a_arg);
 void dap_ledger_bridged_tx_notify_add(dap_ledger_t *a_ledger, dap_ledger_bridged_tx_notify_t a_callback, void *a_arg);
 
+bool dap_ledger_datum_is_blacklisted(dap_ledger_t *a_ledger, dap_hash_fast_t a_hash);
 
 bool dap_ledger_cache_enabled(dap_ledger_t *a_ledger);
 void dap_ledger_set_cache_tx_check_callback(dap_ledger_t *a_ledger, dap_ledger_cache_tx_check_callback_t a_callback);
diff --git a/modules/net/include/dap_chain_net_decree.h b/modules/net/include/dap_chain_net_decree.h
index 270db17d76..6cf2e6eff0 100644
--- a/modules/net/include/dap_chain_net_decree.h
+++ b/modules/net/include/dap_chain_net_decree.h
@@ -36,7 +36,7 @@ int dap_chain_net_decree_deinit(dap_chain_net_t *a_net);
 
 void dap_chain_net_decree_purge(dap_chain_net_t *a_net);
 
-int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_decree_t * a_decree, dap_chain_t *a_chain);
+int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_decree_t * a_decree, dap_chain_t *a_chain, bool a_anchored);
 int dap_chain_net_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_decree, size_t a_data_size, dap_chain_hash_fast_t *a_decree_hash);
 int dap_chain_net_decree_load(dap_chain_datum_decree_t * a_decree, dap_chain_t *a_chain, dap_chain_hash_fast_t *a_decree_hash);
 dap_chain_datum_decree_t *dap_chain_net_decree_get_by_hash(dap_chain_net_t *a_net, dap_hash_fast_t *a_hash, bool *is_applied);
-- 
GitLab