From 9952d2f22beba2044d196e69a21285dbeb39fbd3 Mon Sep 17 00:00:00 2001
From: "daniil.frolov" <daniil.frolov@demlabs.net>
Date: Thu, 13 Mar 2025 14:30:11 +0300
Subject: [PATCH] [+] Refactor ban list. Move it to GDB

---
 .../dap_stream_ch_chain_net_srv.c             | 126 ++++++++++++------
 modules/net/srv/include/dap_chain_net_srv.h   |   6 +-
 2 files changed, 86 insertions(+), 46 deletions(-)

diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
index a930241aa2..bdca09bfc8 100644
--- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
+++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
@@ -96,7 +96,9 @@ static void s_start_receipt_timeout_timer(dap_chain_net_srv_usage_t *a_usage);
 static bool s_stream_ch_packet_in(dap_stream_ch_t* ch , void* arg);
 static bool s_stream_ch_packet_out(dap_stream_ch_t* ch , void* arg);
 
-static bool s_unban_client(dap_chain_net_srv_banlist_item_t *a_item);
+static bool s_check_client_is_banned(dap_chain_net_srv_usage_t *a_usage);
+static void s_ban_client(dap_chain_net_srv_usage_t *a_usage);
+static void s_unban_client(dap_chain_net_srv_usage_t *a_usage);
 
 static int s_pay_service(dap_chain_net_srv_usage_t *a_usage, dap_chain_datum_tx_receipt_t *a_receipt);
 
@@ -193,19 +195,86 @@ void s_stream_ch_delete(dap_stream_ch_t* a_ch , UNUSED_ARG void *a_arg)
     DAP_DEL_Z(a_ch->internal);
 }
 
-static bool s_unban_client(dap_chain_net_srv_banlist_item_t *a_item)
+static char *s_get_ban_group(dap_chain_net_srv_usage_t *a_usage)
 {
-// sanity check
-    dap_return_val_if_pass(!a_item, false);
-// func work
-    log_it(L_DEBUG, "Unban client");
-    pthread_mutex_lock(a_item->ht_mutex);
-    HASH_DEL(*(a_item->ht_head), a_item);
-    pthread_mutex_unlock(a_item->ht_mutex);
-    DAP_DELETE(a_item);
+    dap_hash_fast_t price_pkey_hash = {};
+
+    dap_chain_net_srv_price_t *l_price = a_usage->price;
+
+    dap_hash_fast_t price_pkey_hash = {};
+    size_t l_key_size = 0;
+    uint8_t *l_pub_key = dap_enc_key_serialize_pub_key(l_price->receipt_sign_cert->enc_key, &l_key_size);
+    if (!l_pub_key || !l_key_size)
+    {
+        log_it(L_ERROR, "Can't get pkey from cert %s.", l_price->receipt_sign_cert->name);
+        return NULL;
+    }
+
+    dap_hash_fast(l_pub_key, l_key_size, &price_pkey_hash);
+    DAP_DELETE(l_pub_key);
+    char* l_pkey_hash_str = dap_chain_hash_fast_to_str_new(&price_pkey_hash);
+
+    char *l_ban_list_group =  dap_strdup_printf("local.%s.0x%016"DAP_UINT64_FORMAT_x".ban_list.%s", a_usage->net->pub.gdb_groups_prefix, a_usage->service->uid.uint64, l_pkey_hash_str);
+    DAP_DEL_Z(l_pkey_hash_str);
+
+    return l_ban_list_group;
+}
+
+static bool s_check_client_is_banned(dap_chain_net_srv_usage_t *a_usage)
+{
+    char *l_ban_group = s_get_ban_group(a_usage);
+    size_t l_data_size = 0;
+    byte_t* l_ret = dap_global_db_get_sync(l_ban_group, dap_hash_fast_to_str_static(&a_usage->client_pkey_hash), &l_data_size, NULL, NULL);
+    if(!l_ret)
+    {
+        DAP_DELETE(l_ban_group);
+        return false;
+    }
+
+    if(*(dap_time_t*)l_ret < dap_time_now()){
+        DAP_DELETE(l_ban_group);
+        return true;
+    }
+        
+    s_unban_client(a_usage);
+    DAP_DELETE(l_ban_group);
     return false;
 }
 
+static void s_ban_client(dap_chain_net_srv_usage_t *a_usage)
+{
+    dap_time_t l_end_of_ban_timestamp = dap_time_now() + a_usage->service->grace_period * 10; // ban client for 10x grace periods
+
+    char *l_ban_group = s_get_ban_group(a_usage);
+
+    int l_ret = dap_global_db_set_sync(l_ban_group, dap_hash_fast_to_str_static(&a_usage->client_pkey_hash), &l_end_of_ban_timestamp, sizeof(l_end_of_ban_timestamp), false);
+    if(l_ret)
+    {
+        log_it(L_DEBUG, "Can't add client to ban list group in GDB. Error code: %d", l_ret);
+        DAP_DELETE(l_ban_group);
+        return;
+    }
+    DAP_DELETE(l_ban_group);
+}
+
+static void s_unban_client(dap_chain_net_srv_usage_t *a_usage)
+{
+    char *l_ban_group = s_get_ban_group(a_usage);
+    size_t l_data_size = 0;
+    byte_t* l_ret = dap_global_db_get_sync(l_ban_group, dap_hash_fast_to_str_static(&a_usage->client_pkey_hash), &l_data_size, NULL, NULL);
+    if(l_ret && l_data_size == sizeof(dap_time_t))
+    {
+        int l_ret = dap_global_db_del_sync(l_ban_group, dap_hash_fast_to_str_static(&a_usage->client_pkey_hash));
+        if(l_ret)
+        {
+            log_it(L_DEBUG, "Can't remove client from ban list group in GDB. Error code: %d", l_ret);
+            DAP_DELETE(l_ban_group);
+            return;
+        }
+        DAP_DELETE(l_ban_group);
+    }
+}
+
 static bool s_receipt_timeout_handler(dap_chain_net_srv_usage_t *a_usage)
 {
     log_it(L_WARNING, "Waiting receipt signing from client timeout!");
@@ -468,11 +537,7 @@ static bool s_service_start(dap_stream_ch_t *a_ch , dap_stream_ch_chain_net_srv_
         // Check tx
         if (!l_tx){
             // Start grace
-            dap_chain_net_srv_banlist_item_t *l_item = NULL;
-            pthread_mutex_lock(&l_srv->banlist_mutex);
-            HASH_FIND(hh, l_srv->ban_list, &l_usage->client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
-            pthread_mutex_unlock(&l_srv->banlist_mutex);
-            if (l_item) {   // client banned
+            if (s_check_client_is_banned(l_usage)) {   // client banned
                 log_it(L_DEBUG, "Client %s is banned!", dap_chain_hash_fast_to_str_static(&l_usage->client_pkey_hash));
                 l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_BANNED_PKEY_HASH;
                 if(a_ch)
@@ -1006,7 +1071,7 @@ static int s_pay_service(dap_chain_net_srv_usage_t *a_usage, dap_chain_datum_tx_
     char *l_hash_str = dap_hash_fast_to_str_new(&a_usage->tx_cond_hash);
     log_it(L_NOTICE, "Trying create input tx cond from tx %s with active receipt", l_hash_str);
     DAP_DEL_Z(l_hash_str);
-    int ret_status = 0;
+    int ret_status = 0;   
     char *l_tx_in_hash_str = dap_chain_mempool_tx_create_cond_input(a_usage->net, &a_usage->tx_cond_hash, a_usage->price->wallet_addr,
                                                                         a_usage->price->receipt_sign_cert->enc_key, a_receipt, "hex", &ret_status);
     switch (ret_status){
@@ -1019,7 +1084,6 @@ static int s_pay_service(dap_chain_net_srv_usage_t *a_usage, dap_chain_datum_tx_
         case DAP_CHAIN_MEMPOOl_RET_STATUS_NO_COND_OUT:{
             dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_usage->net->pub.ledger, &a_usage->tx_cond_hash);
             if (l_tx){
-                // TODO check tx have cont in with right service
                 int l_out_cond_idx = 0;
                 dap_chain_tx_out_cond_t *l_out_cond = NULL;
                 dap_chain_tx_in_cond_t *l_in_cond = (dap_chain_tx_in_cond_t*)dap_chain_datum_tx_item_get(l_tx, &l_out_cond_idx, NULL, TX_ITEM_TYPE_IN_COND, NULL);
@@ -1038,6 +1102,7 @@ static int s_pay_service(dap_chain_net_srv_usage_t *a_usage, dap_chain_datum_tx_
                     return PAY_SERVICE_STATUS_NOT_ENOUGH;
                 }
             }else 
+
                 return PAY_SERVICE_STATUS_TX_ERROR;
         }break;
         case DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_ENOUGH:{
@@ -1173,29 +1238,7 @@ static void s_service_state_go_to_error(dap_chain_net_srv_usage_t *a_usage)
 
     if (a_usage && a_usage->service_state == DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_GRACE) {   // add client pkey hash to banlist
         a_usage->is_active = 0;
-        if (a_usage->service) {
-            dap_chain_net_srv_banlist_item_t *l_item = NULL;
-            pthread_mutex_lock(&a_usage->service->banlist_mutex);
-            HASH_FIND(hh, a_usage->service->ban_list, &a_usage->client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
-            if (l_item)
-                pthread_mutex_unlock(&a_usage->service->banlist_mutex);
-            else {
-                l_item = DAP_NEW_Z(dap_chain_net_srv_banlist_item_t);
-                if (!l_item) {
-                    log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-                    pthread_mutex_unlock(&a_usage->service->banlist_mutex);
-                    return;
-                }
-                log_it(L_DEBUG, "Add client to banlist");
-                l_item->client_pkey_hash = a_usage->client_pkey_hash;
-                l_item->ht_mutex = &a_usage->service->banlist_mutex;
-                l_item->ht_head = &a_usage->service->ban_list;
-                HASH_ADD(hh, a_usage->service->ban_list, client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
-                pthread_mutex_unlock(&a_usage->service->banlist_mutex);
-                dap_timerfd_start(a_usage->service->grace_period * 1000 * 10, (dap_timerfd_callback_t)s_unban_client, l_item);
-            }
-        }
-
+        s_ban_client(a_usage);
     } else if (l_srv_session->usage_active)
         dap_chain_net_srv_usage_delete(l_srv_session);
 }
@@ -1362,7 +1405,8 @@ static void s_service_substate_pay_service(dap_chain_net_srv_usage_t *a_usage)
             }
         }
         dap_chain_datum_tx_receipt_t *l_receipt = NULL;
-        if (a_usage->service_substate == DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_FIRST_RECEIPT_SIGN)
+        if (a_usage->service_state == DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_GRACE || 
+            a_usage->service_state == DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_IDLE)
             l_receipt = a_usage->receipt;
         else 
             l_receipt = a_usage->receipt_next;
diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h
index eccc01d336..c355798e2f 100755
--- a/modules/net/srv/include/dap_chain_net_srv.h
+++ b/modules/net/srv/include/dap_chain_net_srv.h
@@ -120,9 +120,7 @@ typedef void (*dap_chain_net_srv_callback_decree_t)(dap_chain_net_srv_t* a_srv,
 
 typedef struct dap_chain_net_srv_banlist_item {
     dap_chain_hash_fast_t client_pkey_hash;
-    pthread_mutex_t *ht_mutex;
-    struct dap_chain_net_srv_banlist_item **ht_head;
-    UT_hash_handle hh;
+    dap_time_t end_of_ban_timestamp;
 } dap_chain_net_srv_banlist_item_t;
 
 typedef struct dap_chain_net_srv_callbacks {
@@ -165,8 +163,6 @@ typedef struct dap_chain_net_srv
 
     bool allow_free_srv;
     uint32_t grace_period;
-    pthread_mutex_t banlist_mutex;
-    dap_chain_net_srv_banlist_item_t *ban_list;
 
     dap_chain_net_srv_callbacks_t callbacks;
 
-- 
GitLab