diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4eb71372f3de98d3f9b4d738d19bfa0c5b0acd13..4b0b4cfebdd67ef29b3a37bd9db3356ba8643fb0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ project(cellframe-sdk C)
 cmake_minimum_required(VERSION 2.8)
 
 set(CMAKE_C_STANDARD 11)
-set(CELLFRAME_SDK_NATIVE_VERSION "2.1-2")
+set(CELLFRAME_SDK_NATIVE_VERSION "2.1-4")
 include(cmake/OS_Detection.cmake)
 add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"")
 
diff --git a/dap-sdk/core/include/dap_file_utils.h b/dap-sdk/core/include/dap_file_utils.h
index 92cfe9812c49b4540b6c1d608de58e3470ce7a3e..9bc55055d72e00a02bdfc5d0d30ac3cca3ab4060 100755
--- a/dap-sdk/core/include/dap_file_utils.h
+++ b/dap-sdk/core/include/dap_file_utils.h
@@ -44,6 +44,9 @@
 
 #else
 
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
 #define DAP_DIR_SEPARATOR '/'
 #define DAP_DIR_SEPARATOR_S "/"
 #define DAP_IS_DIR_SEPARATOR(c) ((c) == DAP_DIR_SEPARATOR)
@@ -102,4 +105,10 @@ char* dap_path_get_dirname(const char *a_file_name);
  */
 dap_list_name_directories_t *dap_get_subs(const char *a_path_name);
 
+
+/*
+ * Reads an entire file into allocated memory, with error checking.
+ */
+bool dap_file_get_contents(const char *filename, char **contents, size_t *length);
+
 #endif // _FILE_UTILS_H_
diff --git a/dap-sdk/core/src/dap_file_utils.c b/dap-sdk/core/src/dap_file_utils.c
index 910c64a79ee21dfc1aa2463b6cc3f39921b93894..8a666b8900eaafa1ad63be8eb47083da5f3b3b94 100755
--- a/dap-sdk/core/src/dap_file_utils.c
+++ b/dap-sdk/core/src/dap_file_utils.c
@@ -25,6 +25,11 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #if (OS_TARGET == OS_MACOS)
     #include <stdio.h>
 #else
@@ -404,3 +409,203 @@ dap_list_name_directories_t *dap_get_subs(const char *a_path_dir){
 #endif
     return list;
 }
+
+static bool get_contents_stdio(const char *filename, FILE *f, char **contents, size_t *length)
+{
+    char buf[4096];
+    size_t bytes; /* always <= sizeof(buf) */
+    char *str = NULL;
+    size_t total_bytes = 0;
+    size_t total_allocated = 0;
+    char *tmp;
+    assert(f != NULL);
+    while(!feof(f)) {
+        int save_errno;
+
+        bytes = fread(buf, 1, sizeof(buf), f);
+        save_errno = errno;
+
+        if(total_bytes > ULONG_MAX - bytes)
+            goto file_too_large;
+
+        /* Possibility of overflow eliminated above. */
+        while(total_bytes + bytes >= total_allocated) {
+            if(str) {
+                if(total_allocated > ULONG_MAX / 2)
+                    goto file_too_large;
+                total_allocated *= 2;
+            }
+            else {
+                total_allocated = MIN(bytes + 1, sizeof(buf));
+            }
+
+            tmp = DAP_REALLOC(str, total_allocated);
+
+            if(tmp == NULL)
+                goto error;
+
+            str = tmp;
+        }
+
+        if(ferror(f))
+            goto error;
+
+        assert(str != NULL);
+        memcpy(str + total_bytes, buf, bytes);
+        total_bytes += bytes;
+    }
+
+    fclose(f);
+
+    if(total_allocated == 0)
+            {
+        str = DAP_NEW_SIZE(char, 1);
+        total_bytes = 0;
+    }
+
+    str[total_bytes] = '\0';
+
+    if(length)
+        *length = total_bytes;
+
+    *contents = str;
+
+    return true;
+
+    file_too_large:
+    error:
+
+    DAP_DELETE(str);
+    fclose(f);
+    return false;
+}
+
+#ifndef _WIN32
+
+static bool dap_get_contents_regfile(const char *filename, struct stat *stat_buf, int fd, char **contents,
+        size_t *length)
+{
+    char *buf;
+    size_t bytes_read;
+    size_t size;
+    size_t alloc_size;
+
+    size = stat_buf->st_size;
+
+    alloc_size = size + 1;
+    buf = DAP_NEW_SIZE(char, alloc_size);
+
+    if(buf == NULL) {
+        goto error;
+    }
+
+    bytes_read = 0;
+    while(bytes_read < size) {
+        size_t rc;
+
+        rc = read(fd, buf + bytes_read, size - bytes_read);
+
+        if(rc < 0) {
+            if(errno != EINTR) {
+                DAP_DELETE(buf);
+                goto error;
+            }
+        }
+        else if(rc == 0)
+            break;
+        else
+            bytes_read += rc;
+    }
+
+    buf[bytes_read] = '\0';
+
+    if(length)
+        *length = bytes_read;
+
+    *contents = buf;
+
+    close(fd);
+
+    return true;
+
+    error:
+
+    close(fd);
+
+    return false;
+}
+
+static bool dap_get_contents_posix(const char *filename, char **contents, size_t *length)
+{
+    struct stat stat_buf;
+    int fd;
+
+    /* O_BINARY useful on Cygwin */
+    fd = open(filename, O_RDONLY | O_BINARY);
+
+    if(fd < 0)
+        return false;
+
+    /* I don't think this will ever fail, aside from ENOMEM, but. */
+    if(fstat(fd, &stat_buf) < 0) {
+        close(fd);
+        return false;
+    }
+
+    if(stat_buf.st_size > 0 && S_ISREG(stat_buf.st_mode)) {
+        bool retval = dap_get_contents_regfile(filename,
+                &stat_buf,
+                fd,
+                contents,
+                length);
+        return retval;
+    }
+    else {
+        FILE *f;
+        bool retval;
+        f = fdopen(fd, "r");
+        if(f == NULL)
+            return false;
+        retval = get_contents_stdio(filename, f, contents, length);
+        return retval;
+    }
+}
+
+#else  /* _WIN32 */
+
+static bool dap_get_contents_win32(const char *filename, char **contents, size_t *length)
+{
+    FILE *f;
+    bool retval;
+
+    f = fopen(filename, "rb");
+
+    if(f == NULL)
+    {
+        return false;
+    }
+    retval = get_contents_stdio (filename, f, contents, length);
+    return retval;
+}
+
+#endif
+
+/*
+ * Reads an entire file into allocated memory, with error checking.
+ */
+bool dap_file_get_contents(const char *filename, char **contents, size_t *length)
+{
+    dap_return_val_if_fail(filename != NULL, false);
+    dap_return_val_if_fail(contents != NULL, false);
+
+    *contents = NULL;
+    if(length)
+        *length = 0;
+
+#ifdef _WIN32
+  return dap_get_contents_win32 (filename, contents, length);
+#else
+    return dap_get_contents_posix(filename, contents, length);
+#endif
+}
+
diff --git a/dap-sdk/net/core/dap_events_socket.c b/dap-sdk/net/core/dap_events_socket.c
index d297d1aecdee9ae289438ad437fb0700300a88fc..6060e27a3f02081a19c98a942885ceeace575afb 100644
--- a/dap-sdk/net/core/dap_events_socket.c
+++ b/dap-sdk/net/core/dap_events_socket.c
@@ -174,7 +174,7 @@ dap_events_socket_t *dap_events_socket_find( int sock, struct dap_events *a_even
   dap_events_socket_t *ret = NULL;
   if(!a_events)
       return NULL;
-  pthread_rwlock_rdlock( &a_events->sockets_rwlock );
+  pthread_rwlock_wrlock( &a_events->sockets_rwlock );
   if(a_events->sockets)
       HASH_FIND_INT( a_events->sockets, &sock, ret );
   pthread_rwlock_unlock( &a_events->sockets_rwlock );
diff --git a/dap-sdk/net/stream/stream/dap_stream.c b/dap-sdk/net/stream/stream/dap_stream.c
index d6769440874667f6a4182fd522cdc95a66426d41..adc20540126577325035768c18a2f47330ce9269 100644
--- a/dap-sdk/net/stream/stream/dap_stream.c
+++ b/dap-sdk/net/stream/stream/dap_stream.c
@@ -776,7 +776,7 @@ void stream_proc_pkt_in(dap_stream_t * a_stream)
 
         // Find channel
         dap_stream_ch_t * ch = NULL;
-        pthread_rwlock_rdlock (&a_stream->rwlock);
+        pthread_rwlock_wrlock (&a_stream->rwlock);
         for(size_t i=0;i<a_stream->channel_count;i++){
             if(a_stream->channel[i]->proc){
                 if(a_stream->channel[i]->proc->id == l_ch_pkt->hdr.id ){
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index b8aba895c5b025c991d3b01d6a06d883875e6dfd..08039a78ea10dae69067211070d5acf0bb2640f4 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -189,7 +189,7 @@ dap_chain_t * dap_chain_find_by_id(dap_chain_net_id_t a_chain_net_id,dap_chain_i
     };
     dap_chain_item_t * l_ret_item = NULL;
 
-    pthread_rwlock_rdlock(&s_chain_items_rwlock);
+    pthread_rwlock_wrlock(&s_chain_items_rwlock);
     HASH_FIND(hh,s_chain_items,&l_chain_item_id,sizeof(dap_chain_item_id_t),l_ret_item);
     pthread_rwlock_unlock(&s_chain_items_rwlock);
     if ( l_ret_item ){
diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index 646f888ebce4b32d8cc91c9a8b64fc8f368a48f2..64c463ef26a9bb90905582b74c1c95f293def162 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -315,7 +315,7 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, const dap_
 
     const char * c_token_ticker = a_token_emission->hdr.ticker;
     dap_chain_ledger_token_item_t * l_token_item = NULL;
-    pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->tokens_rwlock);
     HASH_FIND_STR(l_ledger_priv->tokens, c_token_ticker, l_token_item);
     pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock);
 
@@ -326,7 +326,7 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, const dap_
     //dap_chain_hash_fast_t * l_token_emission_hash_ptr = &l_token_emission_hash;
     dap_hash_fast(a_token_emission, a_token_emission_size, &l_token_emission_hash);
     char * l_hash_str = dap_chain_hash_fast_to_str_new(&l_token_emission_hash);
-    pthread_rwlock_rdlock( l_token_item ?
+    pthread_rwlock_wrlock( l_token_item ?
                                &l_token_item->token_emissions_rwlock :
                                &l_ledger_priv->treshold_emissions_rwlock
                                );
@@ -364,7 +364,7 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger,
 
     const char * c_token_ticker = a_token_emission->hdr.ticker;
     dap_chain_ledger_token_item_t * l_token_item = NULL;
-    pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->tokens_rwlock);
     HASH_FIND_STR(l_ledger_priv->tokens, c_token_ticker, l_token_item);
     pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock);
 
@@ -436,12 +436,12 @@ dap_chain_datum_token_emission_t * dap_chain_ledger_token_emission_find(dap_ledg
     dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_datum_token_emission_t * l_token_emission = NULL;
     dap_chain_ledger_token_item_t * l_token_item = NULL;
-    pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->tokens_rwlock);
     HASH_FIND_STR(l_ledger_priv->tokens, a_token_ticker, l_token_item);
 
     if(l_token_item) {
         dap_chain_ledger_token_emission_item_t * l_token_emission_item = NULL;
-        pthread_rwlock_rdlock( &l_token_item->token_emissions_rwlock);
+        pthread_rwlock_wrlock( &l_token_item->token_emissions_rwlock);
         HASH_FIND(hh, l_token_item->token_emissions, a_token_emission_hash, sizeof(*a_token_emission_hash),
                 l_token_emission_item);
         if( l_token_emission_item)
@@ -567,7 +567,7 @@ static dap_chain_datum_tx_t* s_find_datum_tx_by_hash(dap_ledger_t *a_ledger,
     dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_datum_tx_t *l_tx_ret = NULL;
     dap_chain_ledger_tx_item_t *l_tx_item;
-    pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     HASH_FIND(hh, l_ledger_priv->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_item); // tx_hash already in the hash?
     if(l_tx_item) {
         l_tx_ret = l_tx_item->tx;
@@ -613,8 +613,10 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
      */
 
     dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
-    if(!a_tx)
+    if(!a_tx){
+        log_it(L_DEBUG, "NULL transaction, check broken");
         return -1;
+    }
 
     dap_list_t *l_list_bound_items = NULL;
 
@@ -822,6 +824,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                     dap_list_free_full(l_list_bound_items, free);
                 if (l_list_tx_out)
                     dap_list_free(l_list_tx_out);
+                log_it(L_ERROR, "Emission for tx_token wasn't found");
                 return -6;
             }
         }
@@ -1150,7 +1153,7 @@ _dap_int128_t dap_chain_ledger_count(dap_ledger_t *a_ledger)
     _dap_int128_t l_ret = 0;
     dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
-    pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp)
     {
         l_ret++;
@@ -1171,7 +1174,7 @@ uint64_t dap_chain_ledger_count_from_to(dap_ledger_t * a_ledger, time_t a_ts_fro
     uint64_t l_ret = 0;
     dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
-    pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     if ( a_ts_from && a_ts_to) {
         HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){
             if ( l_iter_current->ts_created >= a_ts_from && l_iter_current->ts_created <= a_ts_to )
@@ -1286,7 +1289,7 @@ uint64_t dap_chain_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_ch
     */
     dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
     dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
-    pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp)
     {
         dap_chain_datum_tx_t *l_cur_tx = l_iter_current->tx;
@@ -1346,7 +1349,7 @@ static dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger,
     bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash);
     bool is_search_enable = is_null_hash;
     dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
-    pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp)
     {
         // If a_token is setup we check if its not our token - miss it
@@ -1423,7 +1426,7 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_pkey(dap_ledger_t *a_led
     bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash);
     bool is_search_enable = is_null_hash;
     dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
-    pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp)
     {
         dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx;
@@ -1469,7 +1472,7 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t
     bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash);
     bool is_search_enable = is_null_hash;
     dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
-    pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
+    pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
     HASH_ITER(hh, l_ledger_priv->ledger_items, l_iter_current, l_item_tmp)
     {
         dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx;
diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c
index 3e789732cd26aab1bb4d610c91c2898e825fd4e1..be7b4e66c1ca411353de65f628fe9829be625b3c 100644
--- a/modules/channel/chain/dap_stream_ch_chain.c
+++ b/modules/channel/chain/dap_stream_ch_chain.c
@@ -194,6 +194,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                                 dap_chain_hash_fast_t l_atom_hash;
                                 dap_hash_fast(l_lasts[i], l_chain->callback_atom_get_size(l_lasts[i]),
                                         &l_atom_hash);
+                                pthread_mutex_lock(&l_ch_chain->mutex);
                                 HASH_FIND(hh, l_ch_chain->request_atoms_lasts, &l_atom_hash, sizeof(l_atom_hash),
                                         l_item);
                                 if(l_item == NULL) { // Not found, add new lasts
@@ -203,6 +204,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                                     HASH_ADD(hh, l_ch_chain->request_atoms_lasts, atom_hash, sizeof(l_atom_hash),
                                             l_item);
                                 }
+                                pthread_mutex_unlock(&l_ch_chain->mutex);
                                 //else
                                 //    DAP_DELETE(l_lasts[i]);
                             }
@@ -535,12 +537,13 @@ void dap_stream_ch_chain_go_idle ( dap_stream_ch_chain_t * a_ch_chain)
     memset(&a_ch_chain->request_last_ts, 0, sizeof(a_ch_chain->request_last_ts));
 
     dap_chain_atom_item_t *l_atom_item = NULL, *l_atom_item_tmp = NULL;
-
+    pthread_mutex_lock(&a_ch_chain->mutex);
     HASH_ITER( hh,a_ch_chain->request_atoms_lasts, l_atom_item, l_atom_item_tmp)
         HASH_DEL(a_ch_chain->request_atoms_lasts, l_atom_item);
 
     HASH_ITER( hh, a_ch_chain->request_atoms_processed, l_atom_item, l_atom_item_tmp )
         HASH_DEL(a_ch_chain->request_atoms_processed, l_atom_item);
+    pthread_mutex_unlock(&a_ch_chain->mutex);
     dap_stream_ch_set_ready_to_write(a_ch_chain->ch, false);
 
 }
@@ -702,6 +705,7 @@ void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg)
                 if(l_ch_chain->callback_notify_packet_out)
                     l_ch_chain->callback_notify_packet_out(l_ch_chain, l_send_pkt_type, NULL, 0, l_ch_chain->callback_notify_arg);
             }else{ // Process one chain from l_ch_chain->request_atoms_lasts
+                pthread_mutex_lock(&l_ch_chain->mutex);
                 HASH_ITER(hh,l_ch_chain->request_atoms_lasts, l_atom_item, l_atom_item_tmp) {
                     dap_chain_atom_item_t * l_atom_item_proc = NULL;
                     // Check if its processed already
@@ -756,6 +760,7 @@ void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg)
                         HASH_DEL(l_ch_chain->request_atoms_lasts, l_atom_item);
                     }
                 }
+                pthread_mutex_unlock(&l_ch_chain->mutex);
             }
             //assert(l_ch_chain->request_atoms_lasts == NULL);
             //l_ch_chain->request_atoms_lasts = l_chains_lasts_new;
diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c
index d0c8a39a530444b29c0714ee2b2cc8f1c05051b9..017e3d238717688379e60c587de666f07dd14b19 100644
--- a/modules/common/dap_chain_datum_token.c
+++ b/modules/common/dap_chain_datum_token.c
@@ -64,3 +64,74 @@ dap_chain_datum_token_tsd_t * dap_chain_datum_token_tsd_create(uint16_t a_type,
     return l_tsd;
 
 }
+
+/**
+ * @brief dap_chain_datum_token_tsd_get
+ * @param a_token
+ * @param a_token_size
+ * @return
+ */
+dap_chain_datum_token_tsd_t* dap_chain_datum_token_tsd_get(dap_chain_datum_token_t * a_token, size_t a_token_size)
+{
+    // Check if token type could have tsd section
+    size_t l_hdr_size;
+    size_t l_tsd_size;
+    switch( a_token->type){
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL:
+            l_hdr_size = sizeof (a_token->header_private_decl);
+            if (l_hdr_size> a_token_size){
+                log_it(L_WARNING, "Token size smaller then header, corrupted data");
+                return NULL;
+            }
+            l_tsd_size = a_token->header_private_decl.tsd_total_size;
+        break;
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE:
+            l_hdr_size = sizeof(a_token->header_private_update);
+            if (l_hdr_size> a_token_size){
+                log_it(L_WARNING, "Token size smaller then header, corrupted data");
+                return NULL;
+            }
+            l_tsd_size = a_token->header_private_update.tsd_total_size;
+        break;
+        default: return NULL;
+    }
+
+    if (l_tsd_size+l_hdr_size > a_token_size){
+        log_it(L_WARNING, "TSD size %zd overlaps with header, corrupted data");
+    }else if (l_tsd_size +l_hdr_size == a_token_size){
+        log_it(L_INFO, "No signatures at all, returning pointer to the top of data");
+        return (dap_chain_datum_token_tsd_t*) a_token->data_n_tsd;
+    }
+
+    // Pass through signatures to find top of TSD section
+    size_t l_offset = 0;
+    while( l_offset < (a_token_size - l_hdr_size-l_tsd_size) ){
+        dap_sign_t* l_sign = (dap_sign_t*) (a_token->data_n_tsd + l_offset);
+        if (l_sign->header.sign_size == 0){
+            log_it( L_WARNING, "Corrupted signature, 0 size");
+            return NULL;
+        }
+        l_offset += dap_sign_get_size( l_sign);
+    }
+    if ( l_offset + l_hdr_size +l_tsd_size <= a_token_size  )
+        return (dap_chain_datum_token_tsd_t*) (a_token->data_n_tsd+l_offset);
+    else{
+        log_it(L_WARNING, "Signatures overlaps with TSD section, corrupted data");
+        return NULL;
+    }
+}
+
+/**
+ * @brief dap_chain_datum_token_flags_dump
+ * @param a_str_out
+ * @param a_flags
+ */
+void dap_chain_datum_token_flags_dump(dap_string_t * a_str_out, uint16_t a_flags)
+{
+    for ( uint16_t i = 0;  (2^i) <=DAP_CHAIN_DATUM_TOKEN_FLAG_MAX; i++ ){
+        if(   a_flags & (2^i) )
+            dap_string_append_printf(a_str_out,"%s%s", c_dap_chain_datum_token_flag_str[2^i],
+                    (2^i)==DAP_CHAIN_DATUM_TOKEN_FLAG_MAX?",":"\n"  );
+    }
+}
+
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index 695c7e02a6dd8ccca54a81e675c8008171bc22fc..f347de9d1a40e2a85816ca6ab105bab9fcefb570 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -24,8 +24,10 @@
 */
 #pragma once
 #include "dap_chain_common.h"
+#include "dap_hash.h"
 #include "dap_sign.h"
 
+#include "dap_string.h"
 #include "dap_strfuncs.h"
 
 // Token declaration
@@ -148,24 +150,27 @@ typedef struct dap_chain_datum_token_tsd{
 // Set total signs count value to set to be valid
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID   0x0004
 
+// Remove owner signature by pkey fingerprint
+#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_REMOVE  0x0005
+
 // Add owner signature's pkey fingerprint
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_ADD     0x0006
 
-// Remove owner signature by pkey fingerprint
-#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_REMOVE  0x0007
 
 
 
 /// ------- Permissions list flags, grouped by update-remove-clear operations --------
+// Blocked datum types list add, remove or clear
+#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD          0x0007
+#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE       0x0008
+#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_CLEAR        0x0009
+
+
 // Allowed datum types list add, remove or clear
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD          0x0010
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE       0x0011
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_CLEAR        0x0012
 
-// Blocked datum types list add, remove or clear
-#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD          0x0013
-#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE       0x0014
-#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_CLEAR        0x0015
 
 //Allowed tx receiver addres list add, remove or clear
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD          0x0014
@@ -230,12 +235,15 @@ extern const char *c_dap_chain_datum_token_emission_type_str[];
 ///
 
 dap_chain_datum_token_tsd_t * dap_chain_datum_token_tsd_create(uint16_t a_type, const void * a_data, size_t a_data_size);
+dap_chain_datum_token_tsd_t* dap_chain_datum_token_tsd_get(dap_chain_datum_token_t * a_token,  size_t a_token_size);
+void dap_chain_datum_token_flags_dump(dap_string_t * a_str_out, uint16_t a_flags);
+
 #define dap_chain_datum_token_tsd_create_scalar(type,value) dap_chain_datum_token_tsd_create (type, &value, sizeof(value) )
 #define dap_chain_datum_token_tsd_get_scalar(a,typeconv)  *((typeconv*) a->data)
 
 // NULL-terminated string
 #define dap_chain_datum_token_tsd_create_string(type,str) dap_chain_datum_token_tsd_create (type,str, dap_strlen(str))
-#define dap_chain_datum_token_tsd_get_string(a)  ((char*) a->data )
-#define dap_chain_datum_token_tsd_get_string_const(a)  ((const char*) a->data )
+#define dap_chain_datum_token_tsd_get_string(a)  ( ((char*) a->data )[a->size-1] == '\0'? (char*) a->data  : "<CORRUPTED STRING>" )
+#define dap_chain_datum_token_tsd_get_string_const(a)  ( ((const char*) a->data )[a->size-1] == '\0'? (const char*) a->data : "<CORRUPTED STRING>" )
 
 #define dap_chain_datum_token_tsd_size(a) (sizeof(*a)+a->size)
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 817a8666efa59c87a67ec6423bfa442d6b46a531..82c303ddcda2ddc1187c66c57cf6bf3db5aea045 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -106,6 +106,7 @@ typedef struct dap_chain_net_pvt{
 #else
     HANDLE state_proc_cond;
 #endif
+    pthread_mutex_t state_mutex_cond;
     dap_chain_node_role_t node_role;
     uint32_t  flags;
     time_t    last_sync;
@@ -134,7 +135,6 @@ typedef struct dap_chain_net_pvt{
 
     dap_chain_net_state_t state;
     dap_chain_net_state_t state_target;
-    dap_chain_net_state_t state_new;
 } dap_chain_net_pvt_t;
 
 typedef struct dap_chain_net_item{
@@ -209,10 +209,19 @@ inline static const char * s_net_state_to_str(dap_chain_net_state_t l_state)
  */
 int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_new_state)
 {
-    if (PVT(a_net)->state_new == a_new_state){
+    if (PVT(a_net)->state_target == a_new_state){
         log_it(L_WARNING,"Already going to state %s",s_net_state_to_str(a_new_state));
     }
-    PVT(a_net)->state_new = a_new_state;
+    PVT(a_net)->state_target = a_new_state;
+    pthread_mutex_lock( &PVT(a_net)->state_mutex_cond);
+    // set flag for sync
+    PVT(a_net)->flags |= F_DAP_CHAIN_NET_GO_SYNC;
+#ifndef _WIN32
+    pthread_cond_signal( &PVT(a_net)->state_proc_cond );
+#else
+    SetEvent( PVT(a_net)->state_proc_cond );
+#endif
+    pthread_mutex_unlock( &PVT(a_net)->state_mutex_cond);
     return 0;
 }
 
@@ -266,87 +275,84 @@ static void s_chain_callback_notify(void * a_arg, dap_chain_t *a_chain, dap_chai
  */
 static int s_net_states_proc(dap_chain_net_t * l_net)
 {
-#if DAP_DEBUG
-    dap_chain_net_pvt_t *pvt_debug = PVT(l_net);
-#endif
+
+    dap_chain_net_pvt_t *l_pvt_net = PVT(l_net);
+
     int ret=0;
 
-    switch ( PVT(l_net)->state ){
+    switch ( l_pvt_net->state ){
         case NET_STATE_OFFLINE:{
-            if (PVT(l_net)->state_new != NET_STATE_UNDEFINED) {
-                PVT(l_net)->state_target = PVT(l_net)->state_new;
-                PVT(l_net)->state_new = NET_STATE_UNDEFINED;
-            }
             // reset current link
-            PVT(l_net)->links_count = 0;
+            l_pvt_net->links_count = 0;
             // delete all links
-            dap_chain_node_client_close(PVT(l_net)->links);
-            PVT(l_net)->links_addrs_count = 0;
-            if ( PVT(l_net)->links_addrs )
-                DAP_DELETE(PVT(l_net)->links_addrs);
-            PVT(l_net)->links_addrs = NULL;
-
-            if ( PVT(l_net)->state_target != NET_STATE_OFFLINE ){
-                PVT(l_net)->state = NET_STATE_LINKS_PREPARE;
+            dap_chain_node_client_close(l_pvt_net->links);
+            l_pvt_net->links = NULL;
+            l_pvt_net->links_addrs_count = 0;
+            if ( l_pvt_net->links_addrs )
+                DAP_DELETE(l_pvt_net->links_addrs);
+            l_pvt_net->links_addrs = NULL;
+
+            if ( l_pvt_net->state_target != NET_STATE_OFFLINE ){
+                l_pvt_net->state = NET_STATE_LINKS_PREPARE;
                 break;
             }
             // disable SYNC_GDB
-            PVT(l_net)->flags &= ~F_DAP_CHAIN_NET_GO_SYNC;
-            PVT(l_net)->last_sync = 0;
+            l_pvt_net->flags &= ~F_DAP_CHAIN_NET_GO_SYNC;
+            l_pvt_net->last_sync = 0;
         } break;
         case NET_STATE_LINKS_PREPARE:{
             log_it(L_NOTICE,"%s.state: NET_STATE_LINKS_PREPARE",l_net->pub.name);
-            switch (PVT(l_net)->node_role.enums) {
+            switch (l_pvt_net->node_role.enums) {
                 case NODE_ROLE_ROOT:
                 case NODE_ROLE_ROOT_MASTER:
                 case NODE_ROLE_ARCHIVE:
                 case NODE_ROLE_CELL_MASTER:{
                     // This roles load predefined links from global_db
-                    if ( PVT(l_net)->node_info ) {
-                        if (PVT(l_net)->links_addrs )
-                            DAP_DELETE(PVT(l_net)->links_addrs);
-                        PVT(l_net)->links_addrs_count = PVT(l_net)->node_info->hdr.links_number;
-                        PVT(l_net)->links_addrs = DAP_NEW_Z_SIZE( dap_chain_node_addr_t,
-                                                                  PVT(l_net)->links_addrs_count * sizeof(dap_chain_node_addr_t));
-                        for (size_t i =0 ; i < PVT(l_net)->node_info->hdr.links_number; i++ ){
-                            PVT(l_net)->links_addrs[i].uint64 = PVT(l_net)->node_info->links[i].uint64;
+                    if ( l_pvt_net->node_info ) {
+                        if (l_pvt_net->links_addrs )
+                            DAP_DELETE(l_pvt_net->links_addrs);
+                        l_pvt_net->links_addrs_count = l_pvt_net->node_info->hdr.links_number;
+                        l_pvt_net->links_addrs = DAP_NEW_Z_SIZE( dap_chain_node_addr_t,
+                                                                  l_pvt_net->links_addrs_count * sizeof(dap_chain_node_addr_t));
+                        for (size_t i =0 ; i < l_pvt_net->node_info->hdr.links_number; i++ ){
+                            l_pvt_net->links_addrs[i].uint64 = l_pvt_net->node_info->links[i].uint64;
                         }
                     }else {
                         log_it(L_WARNING,"No nodeinfo in global_db to prepare links for connecting, find nearest 3 links and fill global_db");
                     }
 
                     // add other root nodes for connect
-                    //if(!PVT(l_net)->links_addrs_count)
+                    //if(!l_pvt_net->links_addrs_count)
                     {
                         // use no more then 4 root node
-                        int l_use_root_nodes = min(4, PVT(l_net)->seed_aliases_count);
-                        if(!PVT(l_net)->links_addrs_count) {
-                            PVT(l_net)->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t,
+                        int l_use_root_nodes = min(4, l_pvt_net->seed_aliases_count);
+                        if(!l_pvt_net->links_addrs_count) {
+                            l_pvt_net->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t,
                                     l_use_root_nodes * sizeof(dap_chain_node_addr_t));
                         }
                         else{
-                            PVT(l_net)->links_addrs = DAP_REALLOC(PVT(l_net)->links_addrs,
-                                    (PVT(l_net)->links_addrs_count+l_use_root_nodes) * sizeof(dap_chain_node_addr_t));
-                            memset(PVT(l_net)->links_addrs + PVT(l_net)->links_addrs_count, 0,
+                            l_pvt_net->links_addrs = DAP_REALLOC(l_pvt_net->links_addrs,
+                                    (l_pvt_net->links_addrs_count+l_use_root_nodes) * sizeof(dap_chain_node_addr_t));
+                            memset(l_pvt_net->links_addrs + l_pvt_net->links_addrs_count, 0,
                                     l_use_root_nodes * sizeof(dap_chain_node_addr_t));
                         }
 
                         for(uint16_t i = 0; i < l_use_root_nodes; i++) {
-                            dap_chain_node_addr_t * l_node_addr = dap_chain_node_alias_find(l_net, PVT(l_net)->seed_aliases[i]);
+                            dap_chain_node_addr_t * l_node_addr = dap_chain_node_alias_find(l_net, l_pvt_net->seed_aliases[i]);
                             if(l_node_addr) {
-                                PVT(l_net)->links_addrs[PVT(l_net)->links_addrs_count].uint64 = l_node_addr->uint64;
-                                PVT(l_net)->links_addrs_count++;
+                                l_pvt_net->links_addrs[l_pvt_net->links_addrs_count].uint64 = l_node_addr->uint64;
+                                l_pvt_net->links_addrs_count++;
                             }
                         }
                     }
                     // shuffle the order of the nodes
-                    for(size_t i = 0; i < PVT(l_net)->links_addrs_count; i++) {
-                        unsigned int l_new_node_pos = rand() % (PVT(l_net)->links_addrs_count);
+                    for(size_t i = 0; i < l_pvt_net->links_addrs_count; i++) {
+                        unsigned int l_new_node_pos = rand() % (l_pvt_net->links_addrs_count);
                         if(i == l_new_node_pos)
                             continue;
-                        uint64_t l_tmp_uint64 = PVT(l_net)->links_addrs[i].uint64;
-                        PVT(l_net)->links_addrs[i].uint64 = PVT(l_net)->links_addrs[l_new_node_pos].uint64;
-                        PVT(l_net)->links_addrs[l_new_node_pos].uint64 = l_tmp_uint64;
+                        uint64_t l_tmp_uint64 = l_pvt_net->links_addrs[i].uint64;
+                        l_pvt_net->links_addrs[i].uint64 = l_pvt_net->links_addrs[l_new_node_pos].uint64;
+                        l_pvt_net->links_addrs[l_new_node_pos].uint64 = l_tmp_uint64;
                     }
 
 
@@ -357,7 +363,7 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
                     // If we haven't any assigned shard - connect to root-0
                     if(1) { //if(l_net->pub.cell_id.uint64 == 0) {
 
-                    //dap_chain_net_pvt_t *pvt_debug = PVT(l_net);
+                    //dap_chain_net_pvt_t *pvt_debug = l_pvt_net;
                     // get current node address
                     dap_chain_node_addr_t l_address;
                     l_address.uint64 = dap_chain_net_get_cur_addr(l_net) ?
@@ -368,8 +374,8 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
                     dap_chain_node_info_t *l_cur_node_info = dap_chain_node_info_read(l_net, &l_address);
 
                     if ( l_cur_node_info ) {
-                        uint16_t l_links_addrs_count = l_cur_node_info->hdr.links_number + PVT(l_net)->seed_aliases_count;
-                        PVT(l_net)->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t,
+                        uint16_t l_links_addrs_count = l_cur_node_info->hdr.links_number + l_pvt_net->seed_aliases_count;
+                        l_pvt_net->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t,
                                 l_links_addrs_count * sizeof(dap_chain_node_addr_t));
 
                         // add linked nodes for connect
@@ -381,37 +387,37 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
                                 // if only nodes from the same cell of cell=0
                                 if(!l_cur_node_info->hdr.cell_id.uint64 ||
                                     l_cur_node_info->hdr.cell_id.uint64 == l_remore_node_info->hdr.cell_id.uint64) {
-                                    PVT(l_net)->links_addrs[PVT(l_net)->links_addrs_count].uint64 =
+                                    l_pvt_net->links_addrs[l_pvt_net->links_addrs_count].uint64 =
                                             l_remore_node_info->hdr.address.uint64;
-                                    PVT(l_net)->links_addrs_count++;
+                                    l_pvt_net->links_addrs_count++;
                                 }
                                 DAP_DELETE(l_remore_node_info);
                             }
                         }
                     }
                     // if no links then add root nodes for connect
-                    if(!PVT(l_net)->links_addrs_count){
+                    if(!l_pvt_net->links_addrs_count){
                         // use no more then 4 root node
-                        int l_use_root_nodes = min(4, PVT(l_net)->seed_aliases_count);
-                        PVT(l_net)->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t,
+                        int l_use_root_nodes = min(4, l_pvt_net->seed_aliases_count);
+                        l_pvt_net->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t,
                                 l_use_root_nodes * sizeof(dap_chain_node_addr_t));
 
                         for(uint16_t i = 0; i < l_use_root_nodes; i++) {
-                            dap_chain_node_addr_t * l_node_addr = dap_chain_node_alias_find(l_net, PVT(l_net)->seed_aliases[i]);
+                            dap_chain_node_addr_t * l_node_addr = dap_chain_node_alias_find(l_net, l_pvt_net->seed_aliases[i]);
                             if(l_node_addr) {
-                                PVT(l_net)->links_addrs[PVT(l_net)->links_addrs_count].uint64 = l_node_addr->uint64;
-                                PVT(l_net)->links_addrs_count++;
+                                l_pvt_net->links_addrs[l_pvt_net->links_addrs_count].uint64 = l_node_addr->uint64;
+                                l_pvt_net->links_addrs_count++;
                             }
                         }
                     }
                     // shuffle the order of the nodes
-                    for(size_t i = 0; i < PVT(l_net)->links_addrs_count; i++) {
-                        unsigned int l_new_node_pos = rand() % (PVT(l_net)->links_addrs_count);
+                    for(size_t i = 0; i < l_pvt_net->links_addrs_count; i++) {
+                        unsigned int l_new_node_pos = rand() % (l_pvt_net->links_addrs_count);
                         if(i==l_new_node_pos)
                             continue;
-                        uint64_t l_tmp_uint64 = PVT(l_net)->links_addrs[i].uint64;
-                        PVT(l_net)->links_addrs[i].uint64 = PVT(l_net)->links_addrs[l_new_node_pos].uint64;
-                        PVT(l_net)->links_addrs[l_new_node_pos].uint64 = l_tmp_uint64;
+                        uint64_t l_tmp_uint64 = l_pvt_net->links_addrs[i].uint64;
+                        l_pvt_net->links_addrs[i].uint64 = l_pvt_net->links_addrs[l_new_node_pos].uint64;
+                        l_pvt_net->links_addrs[l_new_node_pos].uint64 = l_tmp_uint64;
                     }
                     DAP_DELETE(l_cur_node_info);
                 }else {
@@ -419,40 +425,40 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
                     }
                 } break;
             }
-            if ( PVT(l_net)->state_target > NET_STATE_LINKS_PREPARE ){
-                if ( PVT(l_net)->links_addrs_count>0 ) { // If links are present
-                    PVT(l_net)->state = NET_STATE_LINKS_CONNECTING;
-                    log_it(L_DEBUG,"Prepared %u links, start to establish them", PVT(l_net)->links_addrs_count );
+            if ( l_pvt_net->state_target > NET_STATE_LINKS_PREPARE ){
+                if ( l_pvt_net->links_addrs_count>0 ) { // If links are present
+                    l_pvt_net->state = NET_STATE_LINKS_CONNECTING;
+                    log_it(L_DEBUG,"Prepared %u links, start to establish them", l_pvt_net->links_addrs_count );
                 } else {
                     log_it(L_WARNING,"No links for connecting, return back to OFFLINE state");
-                    PVT(l_net)->state = NET_STATE_OFFLINE;
+                    l_pvt_net->state = NET_STATE_OFFLINE;
                     // remove looping
-                    PVT(l_net)->state_target = NET_STATE_OFFLINE;
+                    l_pvt_net->state_target = NET_STATE_OFFLINE;
                 }
             }else {
                 log_it(L_WARNING,"Target state is NET_STATE_LINKS_PREPARE? Realy?");
-                PVT(l_net)->state = NET_STATE_OFFLINE;
+                l_pvt_net->state = NET_STATE_OFFLINE;
             }
         }
         break;
 
         case NET_STATE_LINKS_CONNECTING:{
-            size_t l_links_count = PVT(l_net)->links_count;
+            size_t l_links_count = l_pvt_net->links_count;
             if(l_links_count >= s_required_links_count || (l_links_count + 1) >= s_max_links_count) {
                 // TODO what if other failed and we want more?
             }
-            if (l_links_count < PVT(l_net)->links_addrs_count) {
-                PVT(l_net)->links_count++;
+            if (l_links_count < l_pvt_net->links_addrs_count) {
+                l_pvt_net->links_count++;
             } else {
                 log_it(L_NOTICE, "Can't establish enough links, go to offline");
-                PVT(l_net)->state = NET_STATE_OFFLINE;
-                PVT(l_net)->state_target = NET_STATE_OFFLINE;
+                l_pvt_net->state = NET_STATE_OFFLINE;
+                l_pvt_net->state_target = NET_STATE_OFFLINE;
                 break;
             }
             log_it(L_DEBUG, "%s.state: NET_STATE_LINKS_CONNECTING",l_net->pub.name);
             log_it(L_DEBUG, "Establishing connection with " NODE_ADDR_FP_STR,
-                   NODE_ADDR_FP_ARGS_S( PVT(l_net)->links_addrs[l_links_count]) );
-            dap_chain_node_info_t *l_link_node_info = dap_chain_node_info_read(l_net, &PVT(l_net)->links_addrs[l_links_count]);
+                   NODE_ADDR_FP_ARGS_S( l_pvt_net->links_addrs[l_links_count]) );
+            dap_chain_node_info_t *l_link_node_info = dap_chain_node_info_read(l_net, &l_pvt_net->links_addrs[l_links_count]);
             if ( l_link_node_info ) {
                 dap_chain_node_client_t *l_node_client = dap_chain_node_client_connect(l_link_node_info);
                 if(!l_node_client) {
@@ -465,11 +471,12 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
                 int res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
                 if (res == 0 ){
                     log_it(L_DEBUG, "Connected link %u", l_links_count);
-                    PVT(l_net)->links = l_node_client;
-                    PVT(l_net)->state = NET_STATE_LINKS_ESTABLISHED;
+                    l_pvt_net->links = l_node_client;
+                    l_pvt_net->state = NET_STATE_LINKS_ESTABLISHED;
                 }else {
                     log_it(L_DEBUG, "Cant establish link %u", l_links_count);
                     dap_chain_node_client_close(l_node_client);
+                    l_node_client = NULL;
                 }
             }
         }
@@ -477,31 +484,31 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
 
         case NET_STATE_LINKS_ESTABLISHED:{
             log_it(L_DEBUG,"%s.state: NET_STATE_LINKS_ESTABLISHED",l_net->pub.name);
-            switch (PVT(l_net)->state_target) {
+            switch (l_pvt_net->state_target) {
                 case NET_STATE_ONLINE:{ // Online
-                    switch ( PVT(l_net)->node_role.enums ){
+                    switch ( l_pvt_net->node_role.enums ){
                         case NODE_ROLE_ROOT_MASTER:
                         case NODE_ROLE_ROOT:{
                             /*dap_chain_node_client_t * l_node_client = NULL, *l_node_client_tmp = NULL;
 
                             // Send everybody your address when linked
-                            HASH_ITER(hh,PVT(l_net)->links,l_node_client,l_node_client_tmp){
+                            HASH_ITER(hh,l_pvt_net->links,l_node_client,l_node_client_tmp){
                                 dap_stream_ch_chain_net_pkt_write(dap_client_get_stream_ch(
                                                   l_node_client->client, dap_stream_ch_chain_net_get_id()),
                                                    DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR, l_net->pub.id,
                                                    dap_chain_net_get_cur_addr(l_net),
                                                    sizeof (dap_chain_node_addr_t) );
                             }*/
-                            PVT(l_net)->state = NET_STATE_SYNC_GDB;
+                            l_pvt_net->state = NET_STATE_SYNC_GDB;
                         }break;
                         case NODE_ROLE_CELL_MASTER:
                         case NODE_ROLE_MASTER:{
-                            PVT(l_net)->state = NET_STATE_SYNC_GDB;//NET_STATE_ADDR_REQUEST;
+                            l_pvt_net->state = NET_STATE_SYNC_GDB;//NET_STATE_ADDR_REQUEST;
                         } break;
                        default:{
                         // get addr for current node if it absent
                         if(!dap_chain_net_get_cur_addr_int(l_net))
-                            PVT(l_net)->state = NET_STATE_ADDR_REQUEST;
+                            l_pvt_net->state = NET_STATE_ADDR_REQUEST;
                         else
                             PVT( l_net)->state = NET_STATE_SYNC_GDB;
                        }
@@ -510,33 +517,33 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
                 break;
 
                 case NET_STATE_SYNC_GDB: // we need only to sync gdb
-                    PVT(l_net)->state = NET_STATE_SYNC_GDB ;
-                    if ( PVT(l_net)->addr_request_attempts >=10 && PVT(l_net)->state == NET_STATE_ADDR_REQUEST){
-                        PVT(l_net)->addr_request_attempts = 0;
-                        switch( PVT(l_net)->state_target){
+                    l_pvt_net->state = NET_STATE_SYNC_GDB ;
+                    if ( l_pvt_net->addr_request_attempts >=10 && l_pvt_net->state == NET_STATE_ADDR_REQUEST){
+                        l_pvt_net->addr_request_attempts = 0;
+                        switch( l_pvt_net->state_target){
                             case NET_STATE_ONLINE:
                             case NET_STATE_SYNC_GDB:
-                                PVT(l_net)->state = NET_STATE_SYNC_GDB;
+                                l_pvt_net->state = NET_STATE_SYNC_GDB;
                                 break;
 
                             case NET_STATE_SYNC_CHAINS:
-                                PVT(l_net)->state = NET_STATE_SYNC_CHAINS;
+                                l_pvt_net->state = NET_STATE_SYNC_CHAINS;
                                 break;
                             default: {
-                                PVT(l_net)->state = NET_STATE_OFFLINE;
-                                PVT(l_net)->state_target = NET_STATE_OFFLINE;
+                                l_pvt_net->state = NET_STATE_OFFLINE;
+                                l_pvt_net->state_target = NET_STATE_OFFLINE;
                             }
                         }
                     }
                     break;
 
                 case NET_STATE_SYNC_CHAINS:
-                    PVT(l_net)->state = (PVT(l_net)->node_info && PVT(l_net)->node_info->hdr.address.uint64)?
+                    l_pvt_net->state = (l_pvt_net->node_info && l_pvt_net->node_info->hdr.address.uint64)?
                                 NET_STATE_SYNC_CHAINS : NET_STATE_ADDR_REQUEST;
                     break;
 
                 case NET_STATE_ADDR_REQUEST :
-                    PVT(l_net)->state = NET_STATE_ADDR_REQUEST;
+                    l_pvt_net->state = NET_STATE_ADDR_REQUEST;
                     break;
                 default: break;
             }
@@ -544,7 +551,7 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
         // get addr for remote node
         case NET_STATE_ADDR_REQUEST: {
             int l_is_addr_leased = 0;
-            dap_chain_node_client_t *l_node_client = PVT(l_net)->links;
+            dap_chain_node_client_t *l_node_client = l_pvt_net->links;
             uint8_t l_ch_id = dap_stream_ch_chain_net_get_id(); // Channel id for chain net request
             dap_stream_ch_t *l_ch_chain = dap_client_get_stream_ch(l_node_client->client, l_ch_id);
             // set callback for l_ch_id
@@ -557,27 +564,28 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
             if (res == 0) {
                 log_it(L_WARNING,"Can't send NODE_ADDR_REQUEST packet");
                 dap_chain_node_client_close(l_node_client);
-                PVT(l_net)->state = NET_STATE_LINKS_CONNECTING;
+                l_node_client = NULL;
+                l_pvt_net->state = NET_STATE_LINKS_CONNECTING;
                 break; // try with another link
             }
             // wait for finishing of request
             int timeout_ms = 5000; // 5 sec = 5 000 ms
             // TODO add progress info to console
-            PVT(l_net)->addr_request_attempts++;
+            l_pvt_net->addr_request_attempts++;
             int l_res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_NODE_ADDR_LEASED, timeout_ms);
             switch (l_res) {
                 case -1:
                     log_it(L_WARNING,"Timeout with addr leasing");
                     // try again 3 times
-                    if (PVT(l_net)->addr_request_attempts < 3) {
+                    if (l_pvt_net->addr_request_attempts < 3) {
                         break;
                     }
-                    PVT(l_net)->state = NET_STATE_LINKS_CONNECTING;
+                    l_pvt_net->state = NET_STATE_LINKS_CONNECTING;
                     break; // try with another link
                 case 0:
                     log_it(L_INFO, "Node address leased");
                     l_is_addr_leased++;
-                    PVT(l_net)->addr_request_attempts = 0;
+                    l_pvt_net->addr_request_attempts = 0;
                     break;
                 default:
                     if (l_node_client->last_error[0]) {
@@ -585,17 +593,17 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
                         l_node_client->last_error[0] = '\0';
                     }
                     log_it(L_INFO, "Node address request error %d", l_res);
-                    PVT(l_net)->state = NET_STATE_LINKS_CONNECTING;
+                    l_pvt_net->state = NET_STATE_LINKS_CONNECTING;
                     break;
             }
             if (l_is_addr_leased > 0) {
-                PVT(l_net)->state = NET_STATE_SYNC_GDB;
+                l_pvt_net->state = NET_STATE_SYNC_GDB;
             }
         }
         break;
         case NET_STATE_SYNC_GDB:{
             // send request
-            dap_chain_node_client_t *l_node_client = PVT(l_net)->links;
+            dap_chain_node_client_t *l_node_client = l_pvt_net->links;
             dap_stream_ch_chain_sync_request_t l_sync_gdb = {};
             // Get last timestamp in log
             l_sync_gdb.id_start = (uint64_t) dap_db_log_get_last_id_remote(l_node_client->remote_node_addr.uint64);
@@ -622,7 +630,8 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
             if (l_res == 0) {
                 log_it(L_WARNING, "Can't send GDB sync request");
                 dap_chain_node_client_close(l_node_client);
-                PVT(l_net)->state = NET_STATE_LINKS_CONNECTING;
+                l_node_client = NULL;
+                l_pvt_net->state = NET_STATE_LINKS_CONNECTING;
                 break;  //try another link
             }
 
@@ -643,21 +652,22 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
             if (l_res) { // try another link
                 break;
             }
-            if(PVT(l_net)->state_target >= NET_STATE_SYNC_CHAINS){
-                PVT(l_net)->state = NET_STATE_SYNC_CHAINS;
+            if(l_pvt_net->state_target >= NET_STATE_SYNC_CHAINS){
+                l_pvt_net->state = NET_STATE_SYNC_CHAINS;
             } else {
-                PVT(l_net)->state = NET_STATE_ONLINE;
+                l_pvt_net->flags &= ~F_DAP_CHAIN_NET_GO_SYNC;
+                l_pvt_net->state = NET_STATE_ONLINE;
             }
         }
         break;
 
         case NET_STATE_SYNC_CHAINS: {
-            dap_chain_node_client_t *l_node_client = PVT(l_net)->links;
+            dap_chain_node_client_t *l_node_client = l_pvt_net->links;
             uint8_t l_ch_id = dap_stream_ch_chain_get_id(); // Channel id for global_db and chains sync
             dap_stream_ch_t *l_ch_chain = dap_client_get_stream_ch(l_node_client->client, l_ch_id);
             if(!l_ch_chain) {
                 log_it(L_DEBUG,"Can't get stream_ch for id='%c' ", l_ch_id);
-                PVT(l_net)->state = NET_STATE_LINKS_CONNECTING;
+                l_pvt_net->state = NET_STATE_LINKS_CONNECTING;
                 break;
             }
             dap_chain_t * l_chain = NULL;
@@ -695,7 +705,7 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
                         {
                             struct timespec l_to;
                             clock_gettime( CLOCK_MONOTONIC, &l_to);
-                            PVT(l_net)->last_sync = l_to.tv_sec;
+                            l_pvt_net->last_sync = l_to.tv_sec;
                         }
                         break;
                     default:
@@ -709,36 +719,35 @@ static int s_net_states_proc(dap_chain_net_t * l_net)
                 //DAP_DELETE( l_atom_iter );
             }
             dap_chain_node_client_close(l_node_client);
+            l_node_client = NULL;
             if (l_sync_errors) {
-                PVT(l_net)->state = NET_STATE_LINKS_CONNECTING;
+                l_pvt_net->state = NET_STATE_LINKS_CONNECTING;
                 break;
             }
             log_it(L_INFO, "Synchronization done");
-            PVT(l_net)->state = NET_STATE_ONLINE;
-            PVT(l_net)->links_count = 0;
+            l_pvt_net->flags &= ~F_DAP_CHAIN_NET_GO_SYNC;
+            l_pvt_net->state = NET_STATE_ONLINE;
+            l_pvt_net->links_count = 0;
         }
         break;
 
         case NET_STATE_ONLINE: {
-            if (PVT(l_net)->state_new != NET_STATE_UNDEFINED) {
-                PVT(l_net)->state_target = PVT(l_net)->state_new;
-                PVT(l_net)->state_new = NET_STATE_UNDEFINED;
-            }
-            switch ( PVT(l_net)->state_target) {
+            if (l_pvt_net->flags & F_DAP_CHAIN_NET_GO_SYNC)
+            {
+                switch ( l_pvt_net->state_target) {
                 // disconnect
                 case NET_STATE_OFFLINE:
-                    PVT(l_net)->state = NET_STATE_OFFLINE;
+                    l_pvt_net->state = NET_STATE_OFFLINE;
                     log_it(L_NOTICE, "Going to disconnet");
                     break;
                 case NET_STATE_ONLINE:
-                    if((PVT(l_net)->flags & F_DAP_CHAIN_NET_GO_SYNC) == 0)
-                        break;
                 case NET_STATE_SYNC_GDB:
                 case NET_STATE_SYNC_CHAINS:
                     // if flag set then go to SYNC_GDB
-                    PVT(l_net)->state = NET_STATE_LINKS_CONNECTING;
+                    l_pvt_net->state = NET_STATE_LINKS_CONNECTING;
                     break;
                 default: break;
+                }
             }
         }
         break;
@@ -770,18 +779,45 @@ static void *s_net_proc_thread ( void *a_net )
     dap_chain_net_t *l_net = (dap_chain_net_t *)a_net;
     dap_chain_net_pvt_t *p_net = (dap_chain_net_pvt_t *)(void *)l_net->pvt;
 
+    const uint64_t l_timeout_ms = 60000;// 60 sec
+
     // set callback to update data
     //dap_chain_global_db_set_callback_for_update_base(s_net_proc_thread_callback_update_db);
 
     while( !(p_net->flags & F_DAP_CHAIN_NET_SHUTDOWN) ) {
+
         // check or start sync
         s_net_states_proc( l_net );
-        // checking whether new sync is needed
         struct timespec l_to;
+#ifndef _WIN32
+        int l_ret = 0;
+        // prepare for signal waiting
+        clock_gettime( CLOCK_MONOTONIC, &l_to );
+        int64_t l_nsec_new = l_to.tv_nsec + l_timeout_ms * 1000000ll;
+        // if the new number of nanoseconds is more than a second
+        if(l_nsec_new > (long) 1e9) {
+            l_to.tv_sec += l_nsec_new / (long) 1e9;
+            l_to.tv_nsec = l_nsec_new % (long) 1e9;
+        }
+        else
+            l_to.tv_nsec = (long) l_nsec_new;
+        pthread_mutex_lock( &p_net->state_mutex_cond );
+        // wait if flag not set then go to SYNC_GDB
+        while ((p_net->flags & F_DAP_CHAIN_NET_GO_SYNC) == 0 && l_ret == 0) {
+            // signal waiting
+            l_ret = pthread_cond_timedwait( &p_net->state_proc_cond, &p_net->state_mutex_cond, &l_to );
+        }
+        pthread_mutex_unlock(&p_net->state_mutex_cond);
+#else // WIN32
+
+        WaitForSingleObject( p_net->state_proc_cond, (uint32_t)l_timeout_ms );
+
+#endif
+        // checking whether new sync is needed
         time_t l_sync_timeout = 300; // 300 sec = 5 min
         clock_gettime(CLOCK_MONOTONIC, &l_to);
         // start sync every l_sync_timeout sec
-        if(p_net->last_sync && l_to.tv_sec >= p_net->last_sync + l_sync_timeout) {
+        if(l_to.tv_sec >= p_net->last_sync + l_sync_timeout) {
             p_net->flags |= F_DAP_CHAIN_NET_GO_SYNC;
         }
     }
@@ -1099,12 +1135,12 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply)
                 dap_chain_net_state_go_to(l_net, NET_STATE_ONLINE);
                 dap_chain_node_cli_set_reply_text(a_str_reply, "Network \"%s\" go from state %s to %s",
                                                     l_net->pub.name,c_net_states[PVT(l_net)->state],
-                                                    c_net_states[PVT(l_net)->state_new]);
+                                                    c_net_states[PVT(l_net)->state_target]);
             } else if ( strcmp(l_go_str,"offline") == 0 ) {
                 dap_chain_net_state_go_to(l_net, NET_STATE_OFFLINE);
                 dap_chain_node_cli_set_reply_text(a_str_reply, "Network \"%s\" go from state %s to %s",
                                                     l_net->pub.name,c_net_states[PVT(l_net)->state],
-                                                    c_net_states[PVT(l_net)->state_new]);
+                                                    c_net_states[PVT(l_net)->state_target]);
 
             }
             else if(strcmp(l_go_str, "sync") == 0) {
@@ -2096,3 +2132,201 @@ int dap_chain_net_verify_datum_for_add(dap_chain_net_t *a_net, dap_chain_datum_t
         default: return 0;
     }
 }
+
+/**
+ * @brief dap_chain_net_dump_datum
+ * @param a_str_out
+ * @param a_datum
+ */
+void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_datum)
+{
+    if( a_datum == NULL){
+        dap_string_append_printf(a_str_out,"==Datum is NULL\n");
+        return;
+    }
+    switch (a_datum->header.type_id){
+        case DAP_CHAIN_DATUM_TOKEN_DECL:{
+            dap_chain_datum_token_t * l_token = (dap_chain_datum_token_t*) a_datum->data;
+            size_t l_token_size = a_datum->header.data_size;
+            dap_string_append_printf(a_str_out,"==Datum Token Declaration\n");
+            dap_string_append_printf(a_str_out, "ticker: %s\n", l_token->ticker);
+            dap_string_append_printf(a_str_out, "size: %zd\n", l_token_size);
+            switch (l_token->type) {
+                case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE:{
+                    dap_string_append_printf(a_str_out, "type: SIMPLE\n");
+                    dap_string_append_printf(a_str_out, "sign_total: %u\n", l_token->header_private.signs_total );
+                    dap_string_append_printf(a_str_out, "sign_valid: %u\n", l_token->header_private.signs_valid );
+                    dap_string_append_printf(a_str_out, "total_supply: %u\n", l_token->header_private.total_supply );
+                }break;
+                case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE:{
+                    dap_string_append_printf(a_str_out,"type: PRIVATE_UPDATE\n");
+                    dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_get(l_token, l_token_size);
+                    if (l_tsd == NULL)
+                        dap_string_append_printf(a_str_out,"<CORRUPTED TSD SECTION>\n");
+                    else{
+                        size_t l_offset = 0;
+                        size_t l_offset_max = l_token->header_private_decl.tsd_total_size;
+                        while( l_offset< l_offset_max){
+                            if ( (l_tsd->size+l_offset) >l_offset_max){
+                                log_it(L_WARNING, "<CORRUPTED TSD> too big size %zd when left maximum %zd",
+                                       l_tsd->size, l_offset_max - l_offset);
+                                return;
+                            }
+                            switch( l_tsd->type){
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS:
+                                    dap_string_append_printf(a_str_out,"flags_set: ");
+                                    dap_chain_datum_token_flags_dump(a_str_out,
+                                                                     dap_chain_datum_token_tsd_get_scalar(l_tsd, uint16_t));
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS:
+                                    dap_string_append_printf(a_str_out,"flags_unset: ");
+                                    dap_chain_datum_token_flags_dump(a_str_out,
+                                                                     dap_chain_datum_token_tsd_get_scalar(l_tsd, uint16_t));
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY:
+                                    dap_string_append_printf(a_str_out,"total_supply: %u\n",
+                                                             dap_chain_datum_token_tsd_get_scalar(l_tsd, uint128_t) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID :
+                                    dap_string_append_printf(a_str_out,"total_signs_valid: %u\n",
+                                                             dap_chain_datum_token_tsd_get_scalar(l_tsd, uint16_t) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_ADD :
+                                    if(l_tsd->size == sizeof(dap_chain_hash_fast_t) ){
+                                        char *l_hash_str = dap_chain_hash_fast_to_str_new(
+                                                    (dap_chain_hash_fast_t*) l_tsd->data );
+                                        dap_string_append_printf(a_str_out,"total_signs_add: %s\n", l_hash_str );
+                                        DAP_DELETE( l_hash_str );
+                                    }else
+                                        dap_string_append_printf(a_str_out,"total_signs_add: <WRONG SIZE %zd>\n", l_tsd->size);
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_REMOVE :
+                                    if(l_tsd->size == sizeof(dap_chain_hash_fast_t) ){
+                                        char *l_hash_str = dap_chain_hash_fast_to_str_new(
+                                                    (dap_chain_hash_fast_t*) l_tsd->data );
+                                        dap_string_append_printf(a_str_out,"total_signs_remoev: %s\n", l_hash_str );
+                                        DAP_DELETE( l_hash_str );
+                                    }else
+                                        dap_string_append_printf(a_str_out,"total_signs_add: <WRONG SIZE %zd>\n", l_tsd->size);
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD  :
+                                    dap_string_append_printf(a_str_out,"datum_type_allowed_add: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE  :
+                                    dap_string_append_printf(a_str_out,"datum_type_allowed_remove: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD  :
+                                    dap_string_append_printf(a_str_out,"datum_type_blocked_add: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE:
+                                    dap_string_append_printf(a_str_out,"datum_type_blocked_remove: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD:
+                                    dap_string_append_printf(a_str_out,"tx_sender_allowed_add: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE:
+                                    dap_string_append_printf(a_str_out,"tx_sender_allowed_remove: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD:
+                                    dap_string_append_printf(a_str_out,"tx_sender_blocked_add: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE:
+                                    dap_string_append_printf(a_str_out,"tx_sender_blocked_remove: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD:
+                                    dap_string_append_printf(a_str_out,"tx_receiver_allowed_add: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE:
+                                    dap_string_append_printf(a_str_out,"tx_receiver_allowed: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD:
+                                    dap_string_append_printf(a_str_out, "tx_receiver_blocked_add: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE:
+                                    dap_string_append_printf(a_str_out, "tx_receiver_blocked_remove: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                default: dap_string_append_printf(a_str_out, "<0x%04X>: <size %zd>\n", l_tsd->type, l_tsd->size);
+                            }
+                            l_offset += dap_chain_datum_token_tsd_size(l_tsd);
+
+                        }
+                    }
+                }break;
+                case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL:{
+                    dap_string_append_printf(a_str_out,"type: PRIVATE_DECL\n");
+                    dap_string_append_printf(a_str_out,"flags: ");
+                    dap_chain_datum_token_flags_dump(a_str_out, l_token->header_private_decl.flags);
+                    dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_get(l_token, l_token_size);
+                    if (l_tsd == NULL)
+                        dap_string_append_printf(a_str_out,"<CORRUPTED TSD SECTION>\n");
+                    else{
+                        size_t l_offset = 0;
+                        size_t l_offset_max = l_token->header_private_decl.tsd_total_size;
+                        while( l_offset< l_offset_max){
+                            if ( (l_tsd->size+l_offset) >l_offset_max){
+                                log_it(L_WARNING, "<CORRUPTED TSD> too big size %zd when left maximum %zd",
+                                       l_tsd->size, l_offset_max - l_offset);
+                                return;
+                            }
+                            switch( l_tsd->type){
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY:
+                                    dap_string_append_printf(a_str_out,"total_supply: %u\n",
+                                                             dap_chain_datum_token_tsd_get_scalar(l_tsd, uint128_t) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID :
+                                    dap_string_append_printf(a_str_out,"total_signs_valid: %u\n",
+                                                             dap_chain_datum_token_tsd_get_scalar(l_tsd, uint16_t) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD  :
+                                    dap_string_append_printf(a_str_out,"datum_type_allowed: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD  :
+                                    dap_string_append_printf(a_str_out,"datum_type_blocked: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD:
+                                    dap_string_append_printf(a_str_out,"tx_sender_allowed: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD:
+                                    dap_string_append_printf(a_str_out,"tx_sender_blocked: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD:
+                                    dap_string_append_printf(a_str_out,"tx_receiver_allowed: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD:
+                                    dap_string_append_printf(a_str_out, "tx_receiver_blocked: %s\n",
+                                                             dap_chain_datum_token_tsd_get_string_const(l_tsd) );
+                                break;
+                                default: dap_string_append_printf(a_str_out, "<0x%04X>: <size %zd>\n", l_tsd->type, l_tsd->size);
+                            }
+                            l_offset += dap_chain_datum_token_tsd_size(l_tsd);
+
+                        }
+                    }
+                }break;
+                case DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC:{
+                    dap_string_append_printf(a_str_out,"type: PUBLIC\n");
+                }break;
+                default:
+                    dap_string_append_printf(a_str_out,"type: UNKNOWN\n");
+            }
+
+        }break;
+    }
+}
diff --git a/modules/net/dap_chain_net_news.c b/modules/net/dap_chain_net_news.c
new file mode 100644
index 0000000000000000000000000000000000000000..9a132c43ce37f003602e2053f3627ab27f289903
--- /dev/null
+++ b/modules/net/dap_chain_net_news.c
@@ -0,0 +1,126 @@
+/*
+ * Authors:
+ * Alexander Lysikov <alexander.lysikov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * Kelvin Project https://github.com/kelvinblockchain
+ * Copyright  (c) 2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+ DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DAP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stddef.h>
+
+#include "dap_common.h"
+#include "dap_string.h"
+#include "dap_strfuncs.h"
+#include "dap_file_utils.h"
+#include "dap_config.h"
+
+#include "http_status_code.h"
+#include "dap_http_simple.h"
+#include "dap_enc_http.h"
+//#include "<dap_chain_global_db_driver.h>
+#include "dap_chain_global_db.h"
+#include "dap_chain_net_news.h"
+#define LOG_TAG "chain_net_news"
+
+#define NEWS_URL "/news"
+#define GROUP_NEWS "cdb.news"
+#define DEFAULT_LANG "en"
+
+/* Set news in the selected language
+ * a_lang - a language like "en", "ru", "fr"
+ * a_data_news - news data
+ * a_data_news_len length of news
+ */
+int dap_chain_net_news_write(char *a_lang, byte_t *a_data_news, size_t a_data_news_len)
+{
+    if(!a_data_news || !a_data_news_len)
+        return -2;
+    if(!a_lang)
+        a_lang = DEFAULT_LANG;
+    size_t l_data_len_out = 0;
+    if(dap_chain_global_db_gr_set(a_lang, a_data_news, a_data_news_len, GROUP_NEWS))
+        return 0;
+    return -1;
+}
+
+/* Get news in the selected language
+ * a_lang - a language like "en", "ru", "fr"
+ */
+byte_t* dap_chain_net_news_read(const char *a_lang, size_t *a_news_len)
+{
+    if(!a_lang)
+        return NULL;
+    byte_t *l_ret_data = NULL;
+    size_t l_data_len_num = 0;
+    dap_store_obj_t *l_obj = dap_chain_global_db_obj_gr_get(a_lang, &l_data_len_num, GROUP_NEWS);
+    if(l_obj && l_obj->value_len) {
+        l_ret_data = DAP_NEW_Z_SIZE(byte_t, l_obj->value_len);
+        memcpy(l_ret_data, l_obj->value, l_obj->value_len);
+        if(a_news_len)
+            *a_news_len = l_obj->value_len;
+    }
+    dap_store_obj_free(l_obj, l_data_len_num);
+    return l_ret_data;
+}
+
+/**
+ * @brief news_http_proc
+ * @param a_http_simple
+ * @param a_arg
+ */
+static void news_http_proc(struct dap_http_simple *a_http_simple, void * a_arg)
+{
+    log_it(L_DEBUG, "news_http_proc request");
+    http_status_code_t * return_code = (http_status_code_t*) a_arg;
+    const char *l_lang = DEFAULT_LANG;
+    if(dap_strcmp(a_http_simple->http->url_path, NEWS_URL)) {
+        l_lang = a_http_simple->http->url_path;
+    }
+
+    if(l_lang)
+    {
+        size_t l_news_data_len = 0;
+        // get news in the selected language
+        char *l_news_data = dap_chain_net_news_read(l_lang, &l_news_data_len);
+        // get news in the default language
+        if(!l_news_data && dap_strcmp(a_http_simple->http->in_query_string, "LocalNewsOnly"))
+            l_news_data = dap_chain_net_news_read(DEFAULT_LANG, &l_news_data_len);
+        a_http_simple->reply = l_news_data ? l_news_data : dap_strdup("no news");
+        a_http_simple->reply_size = l_news_data_len;
+        *return_code = Http_Status_OK;
+    }
+    else {
+        log_it(L_ERROR, "Wrong request. Must be %s/<lang_code>, example http:/<addr>%s/en", NEWS_URL, NEWS_URL);
+        a_http_simple->reply = dap_strdup_printf("Wrong request. Must be %s/<lang_code>, example http:/<addr>%s/en",
+        NEWS_URL, NEWS_URL);
+        a_http_simple->reply_size = strlen(a_http_simple->reply);
+        *return_code = Http_Status_NotFound;
+    }
+}
+
+/**
+ * @brief dap_chain_net_news_add_proc
+ * @param sh HTTP server instance
+ */
+void dap_chain_net_news_add_proc(struct dap_http * sh)
+{
+    const char * url = NEWS_URL;
+    dap_http_simple_proc_add(sh, url, 14096, news_http_proc);
+}
+
diff --git a/modules/net/dap_chain_net_news.h b/modules/net/dap_chain_net_news.h
new file mode 100644
index 0000000000000000000000000000000000000000..0982b05159e95c2af2484f1512deeb21a51c235f
--- /dev/null
+++ b/modules/net/dap_chain_net_news.h
@@ -0,0 +1,39 @@
+/*
+ * Authors:
+ * Alexander Lysikov <alexander.lysikov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * Kelvin Project https://github.com/kelvinblockchain
+ * Copyright  (c) 2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+ DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DAP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dap_http.h"
+
+/* Set news in the selected language
+ * a_lang - a language like "en", "ru", "fr"
+ * a_data_news - news data
+ * a_data_news_len length of news
+ */
+int dap_chain_net_news_write(char *a_lang, byte_t *a_data_news, size_t a_data_news_len);
+
+/* Get news in the selected language
+ * a_lang - a language like "en", "ru", "fr"
+ */
+byte_t* dap_chain_net_news_read(const char *a_lang, size_t *a_news_len);
+
+void dap_chain_net_news_add_proc(struct dap_http * sh);
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index 3b742cf1404bdb19ba646cc8cbecbe078c580c00..abd8b8ccc318935218057caae1ff6a5b00e5a480 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -1011,6 +1011,12 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
     dap_chain_node_cli_cmd_item_create ("exit", com_exit, NULL, "Stop application and exit",
                 "exit\n" );
 
+#ifndef _WIN32
+    // News
+    dap_chain_node_cli_cmd_item_create("news", com_news, NULL, "Add News for VPN clients. Language code is a text code like \"en\", \"ru\", \"fr\"",
+            "news [-text <news text> | -file <filename with news>] -lang <language code> \n");
+
+#endif
     // create thread for waiting of clients
     pthread_t l_thread_id;
 
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 14c7a183cb08342f4ea1a4d6456b065c3b351b82..2d2a9b7752b34ac494314c42eb112c2124ee3761 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -2014,13 +2014,8 @@ int com_mempool_list(int argc, char ** argv, void *arg_func, char ** a_str_reply
                 dap_string_append_printf(l_str_tmp, "%s: type_id=%s  data_size=%u ts_create=%s", // \n included in timestamp
                         l_objs[i].key, c_datum_type_str[l_datum->header.type_id],
                         l_datum->header.data_size, ctime_r(&l_ts_create, buf));
-                if ( l_datum->header.type_id == DAP_CHAIN_DATUM_TOKEN_DECL ){
-                    dap_chain_datum_token_t * l_datum_token = (dap_chain_datum_token_t *) l_datum->data;
-                    dap_string_append_printf(l_str_tmp,
-                         "\tDAP_CHAIN_DATUM_TOKEN_DECL: type=%u ticker=\"%s\" signs_total=%u signs_valid=%u\n",
-                                             l_datum_token->type, l_datum_token->ticker,
-                                             l_datum_token->header_private.signs_total, l_datum_token->header_private.signs_valid );
-                }
+
+                dap_chain_net_dump_datum(l_str_tmp, l_datum);
             }
             // Clean up
             dap_chain_global_db_objs_delete(l_objs, l_objs_size);
diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c
index 2b19601490269bec6ebfa8ff457d7d4858909e49..b8d1c88a33f71d79ccfedc03a82205f0450ae625 100644
--- a/modules/net/dap_chain_node_client.c
+++ b/modules/net/dap_chain_node_client.c
@@ -335,10 +335,10 @@ static void s_ch_chain_callback_notify_packet_in(dap_stream_ch_chain_t* a_ch_cha
                                 l_lasts = l_chain->callback_atom_iter_get_lasts(l_iter, &l_lasts_size);
                                 if ( l_lasts){
                                     for(size_t i = 0; i < l_lasts_size; i++) {
-                                        pthread_mutex_lock(&l_node_client->wait_mutex);
                                         dap_chain_atom_item_t * l_item = NULL;
                                         dap_chain_hash_fast_t l_atom_hash;
                                         dap_hash_fast(l_lasts[i], l_chain->callback_atom_get_size(l_lasts[i]), &l_atom_hash);
+                                        pthread_mutex_lock(&a_ch_chain->mutex);
                                         HASH_FIND(hh, a_ch_chain->request_atoms_lasts, &l_atom_hash, sizeof(l_atom_hash), l_item);
                                         if(l_item == NULL) { // Not found, add new lasts
                                             l_item = DAP_NEW_Z(dap_chain_atom_item_t);
@@ -348,7 +348,7 @@ static void s_ch_chain_callback_notify_packet_in(dap_stream_ch_chain_t* a_ch_cha
                                         }
                                         //else
                                         //    DAP_DELETE(l_lasts[i]);
-                                        pthread_mutex_unlock(&l_node_client->wait_mutex);
+                                        pthread_mutex_unlock(&a_ch_chain->mutex);
                                     }
                                     DAP_DELETE(l_lasts);
                                 }
@@ -523,7 +523,8 @@ void dap_chain_node_client_close(dap_chain_node_client_t *a_client)
         CloseHandle( a_client->wait_cond );
 #endif
         pthread_mutex_destroy(&a_client->wait_mutex);
-        DAP_DEL_Z(a_client);
+        a_client->client = NULL;
+        DAP_DELETE(a_client);
     }
 }
 
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index 463a6e777c4d46d4e445f648d362c6077acc9fea..174cfb338759548a74010e1f9f13fd8841777d29 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -44,6 +44,7 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include <stdint.h>
 #include <string.h>
 #include "dap_strfuncs.h"
+#include "dap_string.h"
 #include "dap_chain_common.h"
 #include "dap_chain_node.h"
 #include "dap_chain.h"
@@ -60,8 +61,7 @@ typedef  enum dap_chain_net_state{
     NET_STATE_ADDR_REQUEST, // Waiting for address assign
     NET_STATE_SYNC_GDB,
     NET_STATE_SYNC_CHAINS,
-    NET_STATE_ONLINE,
-    NET_STATE_UNDEFINED
+    NET_STATE_ONLINE
 } dap_chain_net_state_t;
 
 typedef struct dap_chain_net{
@@ -153,3 +153,4 @@ dap_chain_net_t **dap_chain_net_list(size_t *a_size);
 dap_list_t * dap_chain_net_get_add_gdb_group(dap_chain_net_t * a_net, dap_chain_node_addr_t a_node_addr);
 
 int dap_chain_net_verify_datum_for_add(dap_chain_net_t *a_net, dap_chain_datum_t * a_datum );
+void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_datum);
diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h
index 505911d1d5af8a0fee5bc35d09a802266fa7457b..9ceb6f9efdd97101c97c67eff78bcf12ace1bcfe 100644
--- a/modules/net/include/dap_chain_node_cli_cmd.h
+++ b/modules/net/include/dap_chain_node_cli_cmd.h
@@ -133,6 +133,11 @@ int com_stats(int argc, char ** argv, void *arg_func, char **str_reply);
 
 int com_exit(int argc, char ** argv, void *arg_func, char **str_reply);
 
+#ifndef _WIN32
+// Add News for VPN clients
+int com_news(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply);
+#endif
+
 // vpn_client command
 int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply);
 
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index 873be6125e2d4227abed8fe5fef109549bfd8ed5..eb12e8dda3955cb23ca27f342088a9439df36799 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -291,7 +291,7 @@ static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t
     else
         PVT(l_dag)->events_treshold = l_events;
     //HASH_ADD(hh, PVT(l_dag)->events_treshold, hash, sizeof(l_event_item->hash), l_event_item);
-
+    pthread_rwlock_unlock( l_events_rwlock );
     if ( l_events == PVT(l_dag)->events){
         dap_chain_cs_dag_event_item_t * l_event_last = NULL;
         // Check the events and update the lasts
@@ -300,11 +300,13 @@ static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t
                   l_event->hashes_n_datum_n_signs + l_event->header.hash_count*sizeof (*l_link_hash) );
                   l_link_hash += sizeof (dap_chain_hash_fast_t ) ) {
             l_event_last = NULL;
+            pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock);
             HASH_FIND(hh,PVT(l_dag)->events_lasts_unlinked,&l_link_hash,sizeof(*l_link_hash), l_event_last);
             if ( l_event_last ){ // If present in unlinked - remove
                 HASH_DEL(PVT(l_dag)->events_lasts_unlinked,l_event_last);
-                DAP_DELETE(l_event_last);
+                DAP_DEL_Z(l_event_last);
             }
+            pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock);
 
         }
         // and then adds itself
@@ -312,8 +314,9 @@ static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t
         l_event_last->ts_added = l_event_item->ts_added;
         l_event_last->event = l_event;
         dap_hash_fast(l_event, dap_chain_cs_dag_event_calc_size(l_event),&l_event_last->hash );
-
+        pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock);
         HASH_ADD(hh,PVT(l_dag)->events_lasts_unlinked,hash,sizeof (l_event_last->hash),l_event_last);
+        pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock);
     }
 
     // add datum from event to ledger
@@ -391,8 +394,10 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain
 
     for (size_t d = 0; d <a_datums_count ; d++){
         dap_chain_datum_t * l_datum = a_datums[d];
-        if(l_datum == NULL) // Was wrong datum thats not passed checks
+        if(l_datum == NULL){ // Was wrong datum thats not passed checks
+            log_it(L_WARNING,"Datum in mempool processing comes NULL");
             continue;
+        }
 
         // Verify for correctness
         dap_chain_net_t * l_net = dap_chain_net_by_id( a_chain->net_id);
@@ -444,12 +449,13 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain
         // Now link with ext events
         dap_chain_cs_dag_event_item_t *l_event_ext_item = NULL;
         // is_single_line - only one link inside
-        if(!l_dag->is_single_line || !l_hashes_linked)
-        if( PVT(l_dag)->events_lasts_unlinked && l_hashes_linked < l_hashes_size) { // Take then the first one if any events_lasts are present
-                l_event_ext_item = PVT(l_dag)->events_lasts_unlinked;
-                memcpy(&l_hashes[l_hashes_linked], &l_event_ext_item->hash, sizeof(l_event_ext_item->hash));
-                l_hashes_linked++;
-            }
+        if(!l_dag->is_single_line || !l_hashes_linked){
+            if( PVT(l_dag)->events_lasts_unlinked && l_hashes_linked < l_hashes_size) { // Take then the first one if any events_lasts are present
+                    l_event_ext_item = PVT(l_dag)->events_lasts_unlinked;
+                    memcpy(&l_hashes[l_hashes_linked], &l_event_ext_item->hash, sizeof(l_event_ext_item->hash));
+                    l_hashes_linked++;
+                }
+        }
 
         if (l_hashes_linked || s_seed_mode ) {
             dap_chain_cs_dag_event_t * l_event = NULL;
@@ -540,7 +546,7 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain
 dap_chain_cs_dag_event_t* dap_chain_cs_dag_find_event_by_hash(dap_chain_cs_dag_t * a_dag, dap_chain_hash_fast_t * a_hash)
 {
     dap_chain_cs_dag_event_item_t* l_event_item = NULL;
-    pthread_rwlock_rdlock( &PVT(a_dag)->events_rwlock );
+    pthread_rwlock_wrlock( &PVT(a_dag)->events_rwlock );
     HASH_FIND(hh, PVT(a_dag)->events ,a_hash,sizeof(*a_hash), l_event_item);
     dap_chain_cs_dag_event_t * l_event = l_event_item->event;
     pthread_rwlock_unlock( &PVT(a_dag)->events_rwlock );
@@ -617,11 +623,13 @@ void s_dag_events_lasts_delete_linked_with_event(dap_chain_cs_dag_t * a_dag, dap
     for (size_t i = 0; i< a_event->header.hash_count; i++) {
         dap_chain_hash_fast_t * l_hash =  ((dap_chain_hash_fast_t *) a_event->hashes_n_datum_n_signs) + i;
         dap_chain_cs_dag_event_item_t * l_event_item = NULL;
+        pthread_rwlock_wrlock(&PVT(a_dag)->events_rwlock);
         HASH_FIND(hh, PVT(a_dag)->events_lasts_unlinked ,l_hash ,sizeof (*l_hash),  l_event_item);
         if ( l_event_item ){
             HASH_DEL(PVT(a_dag)->events_lasts_unlinked,l_event_item);
-            DAP_DELETE(l_event_item);
+            DAP_DEL_Z(l_event_item);
         }
+        pthread_rwlock_wrlock(&PVT(a_dag)->events_rwlock);
     }
 }
 
@@ -660,7 +668,7 @@ int dap_chain_cs_dag_event_verify_hashes_with_treshold(dap_chain_cs_dag_t * a_da
 void dap_chain_cs_dag_proc_treshold(dap_chain_cs_dag_t * a_dag)
 {
     // TODO Process finish treshold. For now - easiest from possible
-    pthread_rwlock_rdlock(&PVT(a_dag)->events_rwlock);
+    pthread_rwlock_wrlock(&PVT(a_dag)->events_rwlock);
     dap_chain_cs_dag_event_item_t * l_event_item = NULL, * l_event_item_tmp = NULL;
     HASH_ITER(hh,PVT(a_dag)->events_treshold,l_event_item, l_event_item_tmp){
         dap_chain_cs_dag_event_t * l_event = l_event_item->event;
@@ -782,10 +790,12 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_lasts( dap_chain_ato
 
         dap_chain_cs_dag_event_item_t * l_event_item = NULL, *l_event_item_tmp = NULL;
         size_t i = 0;
+        pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock);
         HASH_ITER(hh,PVT(l_dag)->events_lasts_unlinked, l_event_item,l_event_item_tmp){
             l_ret[i] = l_event_item->event;
             i++;
         }
+        pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock);
         return l_ret;
     }
     return NULL;
@@ -1120,10 +1130,22 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply)
                                                       l_event_hash_str);
                     ret = 0;
                 }else {
-                    dap_chain_node_cli_set_reply_text(a_str_reply,
-                                                      "Can't remove event 0x%s from the new forming round ",
-                                                      l_event_hash_str);
-                    ret = -1;
+                    dap_chain_cs_dag_event_item_t * l_event_item = NULL;
+                    HASH_FIND(hh,PVT(l_dag)->events,&l_event_hash,sizeof(l_event_hash),l_event_item);
+
+                    if ( l_event_item ){
+                        HASH_DELETE(hh, PVT(l_dag)->events, l_event_item);
+                        log_it(L_WARNING,"Dropped event 0x%s from chains! Hope you know what are you doing!", l_event_hash_str );
+                        dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                          "Dropped event 0x%s from chains! Hope you know what are you doing! ",
+                                                          l_event_hash_str );
+                        dap_chain_save_all(l_chain);
+                    }else {
+                        dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                          "Can't remove event 0x%s ",
+                                                          l_event_hash_str);
+                        ret = -1;
+                    }
                 }
                 DAP_DELETE( l_gdb_group_events );
                 dap_chain_net_sync_gdb(l_net);
@@ -1140,7 +1162,9 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply)
 
                     }else if ( strcmp(l_from_events_str,"events_lasts") == 0){
                         dap_chain_cs_dag_event_item_t * l_event_item = NULL;
+                        pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock);
                         HASH_FIND(hh,PVT(l_dag)->events_lasts_unlinked,&l_event_hash,sizeof(l_event_hash),l_event_item);
+                        pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock);
                         if ( l_event_item )
                             l_event = l_event_item->event;
                         else {
@@ -1151,7 +1175,9 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply)
                         }
                     }else if ( strcmp(l_from_events_str,"events") == 0){
                         dap_chain_cs_dag_event_item_t * l_event_item = NULL;
+                        pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock);
                         HASH_FIND(hh,PVT(l_dag)->events,&l_event_hash,sizeof(l_event_hash),l_event_item);
+                        pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock);
                         if ( l_event_item )
                             l_event = l_event_item->event;
                         else {
@@ -1201,7 +1227,7 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply)
 
                     // Nested datum
                     dap_string_append_printf(l_str_tmp,"\t\t\t\tdatum:\tdatum_size: %u\n",l_datum_size);
-                    dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tversion:=%0x02X\n", l_datum->header.version_id);
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tversion:=0x%02X\n", l_datum->header.version_id);
                     dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\ttype_id:=%s\n", c_datum_type_str[l_datum->header.type_id]);
                     dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tts_create=%s\n",ctime_r( &l_datum_ts_create,buf ));
                     dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tdata_size=%u\n", l_datum->header.data_size);
@@ -1227,6 +1253,7 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply)
                         DAP_DELETE( l_addr_str);
                         dap_enc_key_delete(l_sign_key);
                     }
+                    dap_chain_net_dump_datum(l_str_tmp, l_datum);
 
                     dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
                     dap_string_free(l_str_tmp,false);