diff --git a/CMakeLists.txt b/CMakeLists.txt
index 88ef2c6dcd42bed393cc591c5c0f90d5c4e6e5d6..a5a304ef07ce40e349071ebdf0df1d475b2589ae 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.3-2")
+set(CELLFRAME_SDK_NATIVE_VERSION "2.3-3")
 add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"")
 
 set(DAPSDK_MODULES "")
diff --git a/dap-sdk/core/include/dap_binary_tree.h b/dap-sdk/core/include/dap_binary_tree.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2eaba9ffaeca7296831affc9207c841bbc38ced
--- /dev/null
+++ b/dap-sdk/core/include/dap_binary_tree.h
@@ -0,0 +1,50 @@
+/*
+ * Authors:
+ * Roman Khlopkov <roman.khlopkov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net
+ * Copyright  (c) 2017-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/>.
+*/
+
+#pragma once
+
+#include <string.h>
+#include "dap_common.h"
+#include "dap_list.h"
+
+typedef const char *dap_binary_tree_key_t;
+#define KEY_LS(a, b) (strcmp(a, b) < 0)
+#define KEY_GT(a, b) (strcmp(a, b) > 0)
+#define KEY_EQ(a, b) (strcmp(a, b) == 0)
+
+typedef struct dap_binary_tree {
+    dap_binary_tree_key_t key;
+    void *data;
+    struct dap_binary_tree *left;
+    struct dap_binary_tree *right;
+} dap_binary_tree_t;
+
+dap_list_t *dap_binary_tree_inorder_list(dap_binary_tree_t *a_tree_root);
+void *dap_binary_tree_search(dap_binary_tree_t *a_tree_root, dap_binary_tree_key_t a_key);
+void *dap_binary_tree_minimum(dap_binary_tree_t *a_tree_root);
+void *dap_binary_tree_maximum(dap_binary_tree_t *a_tree_root);
+dap_binary_tree_t *dap_binary_tree_insert(dap_binary_tree_t *a_tree_root, dap_binary_tree_key_t a_key, void *a_data);
+dap_binary_tree_t *dap_binary_tree_delete(dap_binary_tree_t *a_tree_root, dap_binary_tree_key_t a_key);
+size_t dap_binary_tree_count(dap_binary_tree_t *a_tree_root);
+void dap_binary_tree_clear(dap_binary_tree_t *a_tree_root);
diff --git a/dap-sdk/core/include/dap_common.h b/dap-sdk/core/include/dap_common.h
index d423cf25ad46505590c1a7db28525bc113b08f02..9452a02cbed7a7c64a2559f3f8abb8eceb0311cf 100755
--- a/dap-sdk/core/include/dap_common.h
+++ b/dap-sdk/core/include/dap_common.h
@@ -393,6 +393,13 @@ void dap_digit_from_string2(const char *num_str, void *raw, size_t raw_len);
 void *dap_interval_timer_create(unsigned int a_msec, dap_timer_callback_t a_callback, void *a_param);
 int dap_interval_timer_delete(void *a_timer);
 
+uint16_t dap_lendian_get16(const uint8_t *a_buf);
+void dap_lendian_put16(uint8_t *a_buf, uint16_t a_val);
+uint32_t dap_lendian_get32(const uint8_t *a_buf);
+void dap_lendian_put32(uint8_t *a_buf, uint32_t a_val);
+uint64_t dap_lendian_get64(const uint8_t *a_buf);
+void dap_lendian_put64(uint8_t *a_buf, uint64_t a_val);
+
 #ifdef __MINGW32__
 int exec_silent(const char *a_cmd);
 #endif
diff --git a/dap-sdk/core/include/dap_math_ops.h b/dap-sdk/core/include/dap_math_ops.h
index 5a8e8feeb3f7ad97788c53f93856b25b24b82fc4..d67bad88e18d48a11ebf3fb6d4abde20f41aa39d 100755
--- a/dap-sdk/core/include/dap_math_ops.h
+++ b/dap-sdk/core/include/dap_math_ops.h
@@ -1,5 +1,7 @@
 #pragma once
 #include <stdint.h>
+
+#include "dap_common.h"
 //#include "common/int-util.h"
 
 #if defined(__GNUC__) ||defined (__clang__)
@@ -12,12 +14,20 @@ typedef __int128 _dap_int128_t;
 #if !defined (int128_t)
 typedef __int128 int128_t;
 #endif
+
 #if !defined (uint128_t)
 typedef unsigned __int128 uint128_t;
-#else
-typedef unsigned uint64_t[2] uint128_t;
 #endif
+
+#endif
+
+#if __SIZEOF_INT128__ != 16
+typedef union uint128{uint64_t u64[2];} uint128_t;
+typedef union int128{int64_t i64[2];} int128_t;
+
 #endif
+
+
 #endif
 
 typedef union dap_uint128{
diff --git a/dap-sdk/core/libdap.pri b/dap-sdk/core/libdap.pri
index bf87862a3cb15373b69076707321308244cfb4ac..5353c311b6d7014f825b80cf266312e1f5b5a506 100755
--- a/dap-sdk/core/libdap.pri
+++ b/dap-sdk/core/libdap.pri
@@ -3,6 +3,8 @@ QMAKE_CFLAGS_RELEASE = -std=gnu11
 unix {
     include(src/unix/unix.pri)
     DEFINES += DAP_OS_UNIX
+}
+unix: !android {
     LIBS += -lrt
 }
 darwin {
@@ -18,6 +20,7 @@ win32 {
 }
 
 HEADERS += $$PWD/include/dap_common.h \
+    $$PWD/include/dap_binary_tree.h \
     $$PWD/include/dap_config.h \
     $$PWD/include/dap_math_ops.h \
     $$PWD/include/uthash.h \
@@ -32,6 +35,7 @@ HEADERS += $$PWD/include/dap_common.h \
     $$PWD/include/dap_string.h
 
 SOURCES += $$PWD/src/dap_common.c \
+    $$PWD/src/dap_binary_tree.c \
     $$PWD/src/dap_config.c \
     $$PWD/src/dap_file_utils.c \
     $$PWD/src/dap_circular_buffer.c \
diff --git a/dap-sdk/core/src/dap_binary_tree.c b/dap-sdk/core/src/dap_binary_tree.c
new file mode 100644
index 0000000000000000000000000000000000000000..adb787653849832e070a9458522e231c29058778
--- /dev/null
+++ b/dap-sdk/core/src/dap_binary_tree.c
@@ -0,0 +1,203 @@
+/*
+ * Authors:
+ * Roman Khlopkov <roman.khlopkov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source commdatay https://gitlab.demlabs.net
+ * Copyright  (c) 2017-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_binary_tree.h"
+
+
+
+static void s_list_construct(dap_list_t *a_list, dap_binary_tree_t *a_elm)
+{
+    if (a_elm != NULL) {
+        s_list_construct(a_list, a_elm->left);
+        dap_list_append(a_list, a_elm->data);
+        s_list_construct(a_list, a_elm->right);
+    }
+}
+
+dap_list_t *dap_binary_tree_inorder_list(dap_binary_tree_t *a_tree_root) {
+    if (!a_tree_root) {
+        return NULL;
+    }
+    dap_list_t *l_tmp = dap_list_alloc();
+    s_list_construct(l_tmp, a_tree_root);
+    dap_list_t *l_list = l_tmp->next;
+    l_list->prev = NULL;
+    dap_list_free1(l_tmp);
+    return l_list;
+}
+
+static dap_binary_tree_t *s_tree_search(dap_binary_tree_t *a_elm, dap_binary_tree_key_t a_key)
+{
+    if (a_elm == NULL || KEY_EQ(a_key, a_elm->key))
+        return a_elm;
+    if (KEY_LS(a_key, a_elm->key)) {
+        return s_tree_search(a_elm->left, a_key);
+    } else {
+        return s_tree_search(a_elm->right, a_key);
+    }
+}
+
+void *dap_binary_tree_search(dap_binary_tree_t *a_tree_root, dap_binary_tree_key_t a_key)
+{
+    dap_binary_tree_t *l_res = s_tree_search(a_tree_root, a_key);
+    if (l_res) {
+        return l_res->data;
+    }
+    return NULL;
+}
+
+static dap_binary_tree_t *s_tree_minimum(dap_binary_tree_t *a_elm)
+{
+  if (a_elm->left == NULL)
+     return a_elm;
+  return s_tree_minimum(a_elm->left);
+}
+
+void *dap_binary_tree_minimum(dap_binary_tree_t *a_tree_root)
+{
+    dap_binary_tree_t *l_res = s_tree_minimum(a_tree_root);
+    if (l_res) {
+        return l_res->data;
+    }
+    return NULL;
+}
+
+static dap_binary_tree_t *s_tree_maximum(dap_binary_tree_t *a_elm)
+{
+  if (a_elm->right == NULL)
+     return a_elm;
+  return s_tree_maximum(a_elm->right);
+}
+
+void *dap_binary_tree_maximum(dap_binary_tree_t *a_tree_root)
+{
+    dap_binary_tree_t *l_res = s_tree_maximum(a_tree_root);
+    if (l_res) {
+        return l_res->data;
+    }
+    return NULL;
+}
+
+static dap_binary_tree_t *s_tree_insert(dap_binary_tree_t *a_elm, dap_binary_tree_key_t a_key, void *a_data)
+{
+    if (a_elm == NULL) {
+        dap_binary_tree_t* l_elm = DAP_NEW_Z(dap_binary_tree_t);
+        l_elm->left = l_elm->right = NULL;
+        l_elm->key = a_key;
+        l_elm->data = a_data;
+        return l_elm;
+    }
+    if (KEY_LS(a_key, a_elm->key)) {
+        a_elm->left = s_tree_insert(a_elm->left, a_key, a_data);
+    } else if (KEY_GT(a_key, a_elm->key)) {
+        a_elm->right = s_tree_insert(a_elm->right, a_key, a_data);
+    } else { //if KEY_EQ(a_key, a_elm->key)
+        a_elm->data = a_data;
+    }
+    return a_elm;
+}
+
+dap_binary_tree_t *dap_binary_tree_insert(dap_binary_tree_t *a_tree_root, dap_binary_tree_key_t a_key, void *a_data)
+{
+    return s_tree_insert(a_tree_root, a_key, a_data);
+}
+
+static dap_binary_tree_t *s_tree_delete(dap_binary_tree_t *a_elm, dap_binary_tree_key_t a_key)
+{
+    if (a_elm == NULL) {
+        return a_elm;
+    }
+    if (KEY_LS(a_key, a_elm->key)) {
+        a_elm->left = s_tree_delete(a_elm->left, a_key);
+    } else if (KEY_GT(a_key, a_elm->key)) {
+        a_elm->right = s_tree_delete(a_elm->right, a_key);
+    } else if (a_elm->left && a_elm->right) {
+        dap_binary_tree_t *l_tmp = s_tree_minimum(a_elm->right);
+        a_elm->key = l_tmp->key;
+        a_elm->data = l_tmp->data;
+        a_elm->right = s_tree_delete(a_elm->right, a_elm->key);
+    } else if (a_elm->left) {
+        DAP_DELETE(a_elm->data);
+        DAP_DELETE(a_elm);
+        a_elm = a_elm->left;
+    } else if (a_elm->right) {
+        DAP_DELETE(a_elm->data);
+        DAP_DELETE(a_elm);
+        a_elm = a_elm->right;
+    } else {
+        DAP_DELETE(a_elm->data);
+        DAP_DELETE(a_elm);
+        a_elm = NULL;
+    }
+    return a_elm;
+}
+
+/**
+ * @brief dap_binary_tree_delete - remove element with key from a tree
+ * @param a_tree_root - root of a tree
+ * @param a_key - a key value
+ * @return !!a new tree root
+ */
+dap_binary_tree_t *dap_binary_tree_delete(dap_binary_tree_t *a_tree_root, dap_binary_tree_key_t a_key)
+{
+    return s_tree_delete(a_tree_root, a_key);
+}
+
+
+void s_tree_count(dap_binary_tree_t *a_elm, size_t *a_count)
+{
+    if (a_elm != NULL) {
+        s_tree_count(a_elm->left, a_count);
+        (*a_count)++;
+        s_tree_count(a_elm->right, a_count);
+    }
+}
+
+size_t dap_binary_tree_count(dap_binary_tree_t *a_tree_root)
+{
+    size_t l_ret = 0;
+    s_tree_count(a_tree_root, &l_ret);
+    return l_ret;
+}
+
+dap_binary_tree_t *s_tree_clear(dap_binary_tree_t *a_elm)
+{
+    if (!a_elm) {
+        return NULL;
+    }
+    if (a_elm->left) {
+        a_elm->left = s_tree_clear(a_elm->left);
+    }
+    if (a_elm->right) {
+        a_elm->right = s_tree_clear(a_elm->right);
+    }
+    DAP_DELETE(a_elm->data);
+    DAP_DELETE(a_elm);
+    return NULL;
+}
+
+void dap_binary_tree_clear(dap_binary_tree_t *a_tree_root)
+{
+    s_tree_clear(a_tree_root);
+}
diff --git a/dap-sdk/core/src/dap_common.c b/dap-sdk/core/src/dap_common.c
index 7e80bd379a80c7669e8c40740fc190d86c437f6a..0ca421272c00cdf2aa687a21d61e4d44f7ea8570 100755
--- a/dap-sdk/core/src/dap_common.c
+++ b/dap-sdk/core/src/dap_common.c
@@ -947,3 +947,72 @@ int dap_interval_timer_delete(void *a_timer)
     #endif
 #endif
 }
+
+/**
+ * @brief dap_lendian_get16 Get uint16 from little endian memory
+ * @param a_buf a buffer read from
+ * @return uint16 in host endian memory
+ */
+uint16_t dap_lendian_get16(const uint8_t *a_buf)
+{
+    uint8_t u = *a_buf;
+    return (uint16_t)(*(a_buf + 1)) << 8 | u;
+}
+
+/**
+ * @brief dap_lendian_put16 Put uint16 to little endian memory
+ * @param buf a buffer write to
+ * @param val uint16 in host endian memory
+ * @return none
+ */
+void dap_lendian_put16(uint8_t *a_buf, uint16_t a_val)
+{
+    *(a_buf) = a_val;
+    *(a_buf + 1) = a_val >> 8;
+}
+
+/**
+ * @brief dap_lendian_get32 Get uint32 from little endian memory
+ * @param a_buf a buffer read from
+ * @return uint32 in host endian memory
+ */
+uint32_t dap_lendian_get32(const uint8_t *a_buf)
+{
+    uint16_t u = dap_lendian_get16(a_buf);
+    return (uint32_t)dap_lendian_get16(a_buf + 2) << 16 | u;
+}
+
+/**
+ * @brief dap_lendian_put32 Put uint32 to little endian memory
+ * @param buf a buffer write to
+ * @param val uint32 in host endian memory
+ * @return none
+ */
+void dap_lendian_put32(uint8_t *a_buf, uint32_t a_val)
+{
+    dap_lendian_put16(a_buf, a_val);
+    dap_lendian_put16(a_buf + 2, a_val >> 16);
+}
+
+/**
+ * @brief dap_lendian_get64 Get uint64 from little endian memory
+ * @param a_buf a buffer read from
+ * @return uint64 in host endian memory
+ */
+uint64_t dap_lendian_get64(const uint8_t *a_buf)
+{
+    uint32_t u = dap_lendian_get32(a_buf);
+    return (uint64_t)dap_lendian_get32(a_buf + 4) << 32 | u;
+}
+
+/**
+ * @brief dap_lendian_put64 Put uint64 to little endian memory
+ * @param buf a buffer write to
+ * @param val uint64 in host endian memory
+ * @return none
+ */
+void dap_lendian_put64(uint8_t *a_buf, uint64_t a_val)
+{
+    dap_lendian_put32(a_buf, a_val);
+    dap_lendian_put32(a_buf + 4, a_val >> 32);
+}
diff --git a/dap-sdk/crypto/include/dap_cert.h b/dap-sdk/crypto/include/dap_cert.h
index 82ce8d4cd85904489ad77dfd9956cb11496e128c..9ba4e00ec17c8232b469a25c2c2e5e89f2b4e0d1 100755
--- a/dap-sdk/crypto/include/dap_cert.h
+++ b/dap-sdk/crypto/include/dap_cert.h
@@ -26,17 +26,34 @@
 
 #include "dap_sign.h"
 #include "dap_pkey.h"
-
+#include "dap_binary_tree.h"
 #include "dap_enc.h"
 #include "dap_enc_key.h"
 
 #define DAP_CERT_ITEM_NAME_MAX 40
 
+typedef enum dap_cert_metadata_type {
+    DAP_CERT_META_STRING,
+    DAP_CERT_META_BOOL,
+    DAP_CERT_META_INT,
+    DAP_CERT_META_DATETIME,
+    DAP_CERT_META_DATETIME_PERIOD,
+    DAP_CERT_META_SIGN,
+    DAP_CERT_META_CUSTOM
+} dap_cert_metadata_type_t;
+
+typedef struct dap_cert_metadata {
+    const char *key;
+    uint32_t length;
+    dap_cert_metadata_type_t type : 8;
+    byte_t value[];
+} dap_cert_metadata_t;
+
 typedef struct dap_cert {
     dap_enc_key_t * enc_key;
     char name[DAP_CERT_ITEM_NAME_MAX];
     void * _pvt;
-    char * metadata;
+    dap_binary_tree_t * metadata;
 } dap_cert_t;
 
 #ifdef __cplusplus
@@ -87,6 +104,25 @@ void dap_cert_deinit();
 void dap_cert_delete(dap_cert_t * a_cert);
 void dap_cert_delete_by_name(const char * a_cert_name);
 
+dap_cert_metadata_t *dap_cert_new_meta(const char *a_key, dap_cert_metadata_type_t a_type, void *a_value, size_t a_value_size);
+void dap_cert_add_meta(dap_cert_t *a_cert, const char *a_key, dap_cert_metadata_type_t a_type, void *a_value, size_t a_value_size);
+void dap_cert_add_meta_scalar(dap_cert_t *a_cert, const char *a_key, dap_cert_metadata_type_t a_type, uint64_t a_value, size_t a_value_size);
+#define dap_cert_add_meta_string(a_cert, a_key, a_str) dap_cert_add_meta(a_cert, a_key, DAP_CERT_META_STRING, (void *)a_str, strlen(a_str))
+#define dap_cert_add_meta_sign(a_cert, a_key, a_sign) dap_cert_add_meta(a_cert, a_key, DAP_CERT_META_SIGN, (void *)a_sign, dap_sign_get_size(a_sign))
+#define dap_cert_add_meta_custom(a_cert, a_key, a_val, a_size) dap_cert_add_meta(a_cert, a_key, DAP_CERT_META_CUSTOM, a_val, a_size)
+#define dap_cert_add_meta_bool(a_cert, a_key, a_bool) dap_cert_add_meta_scalar(a_cert, a_key, DAP_CERT_META_BOOL, a_bool, sizeof(bool))
+#define dap_cert_add_meta_int(a_cert, a_key, a_int) dap_cert_add_meta_scalar(a_cert, a_key, DAP_CERT_META_INT, a_int, sizeof(int))
+#define dap_cert_add_meta_time(a_cert, a_key, a_time) dap_cert_add_meta_scalar(a_cert, a_key, DAP_CERT_META_DATETIME, a_time, sizeof(time_t))
+#define dap_cert_add_meta_period(a_cert, a_key, a_period) dap_cert_add_meta_scalar(a_cert, a_key, DAP_CERT_META_DATETIME_PERIOD, a_period, sizeof(time_t))
+
+char *dap_cert_get_meta_string(dap_cert_t *a_cert, const char *a_field);
+bool dap_cert_get_meta_bool(dap_cert_t *a_cert, const char *a_field);
+int dap_cert_get_meta_int(dap_cert_t *a_cert, const char *a_field);
+time_t dap_cert_get_meta_time(dap_cert_t *a_cert, const char *a_field);
+time_t dap_cert_get_meta_period(dap_cert_t *a_cert, const char *a_field);
+dap_sign_t *dap_cert_get_meta_sign(dap_cert_t *a_cert, const char *a_field);
+void *dap_cert_get_meta_custom(dap_cert_t *a_cert, const char *a_field, size_t *a_meta_size_out);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/dap-sdk/crypto/include/dap_cert_file.h b/dap-sdk/crypto/include/dap_cert_file.h
index 6ab2293a4343bdd14c28bfccb7d9eae2f636cdd5..2753faa1e7872f9a6e14ccc9043d18cc27b9ffe8 100755
--- a/dap-sdk/crypto/include/dap_cert_file.h
+++ b/dap-sdk/crypto/include/dap_cert_file.h
@@ -53,6 +53,11 @@ typedef struct dap_cert_file{
     uint8_t data[];
 }DAP_ALIGN_PACKED dap_cert_file_t;
 
+typedef struct dap_cert_file_aux {
+    size_t *buf;
+    size_t idx;
+} dap_cert_file_aux_t;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/dap-sdk/crypto/src/dap_cert.c b/dap-sdk/crypto/src/dap_cert.c
index 4c00e0763cb350276663e6d035b12a6fddcd1735..fe22a7a369c3961fe352a1955797d10b2d5d5d26 100755
--- a/dap-sdk/crypto/src/dap_cert.c
+++ b/dap-sdk/crypto/src/dap_cert.c
@@ -336,7 +336,7 @@ void dap_cert_delete(dap_cert_t * a_cert)
     if( a_cert->enc_key )
         dap_enc_key_delete (a_cert->enc_key );
     if( a_cert->metadata )
-        DAP_DELETE (a_cert->metadata );
+        dap_binary_tree_clear(a_cert->metadata);
     if (a_cert->_pvt)
         DAP_DELETE( a_cert->_pvt );
     DAP_DELETE (a_cert );
@@ -447,8 +447,34 @@ void dap_cert_dump(dap_cert_t * a_cert)
     printf ("Signature type: %s\n", dap_sign_type_to_str( dap_sign_type_from_key_type(a_cert->enc_key->type) ) );
     printf ("Private key size: %lu\n",a_cert->enc_key->priv_key_data_size);
     printf ("Public key size: %lu\n", a_cert->enc_key->pub_key_data_size);
-    printf ("Metadata section size: %lu\n",a_cert->metadata?strlen(a_cert->metadata):0);
+    size_t l_meta_items_cnt = dap_binary_tree_count(a_cert->metadata);
+    printf ("Metadata section count: %lu\n", l_meta_items_cnt);
     printf ("Certificates signatures chain size: %lu\n",dap_cert_count_cert_sign (a_cert));
+    if (l_meta_items_cnt) {
+        printf ("Metadata sections\n");
+        dap_list_t *l_meta_list = dap_binary_tree_inorder_list(a_cert->metadata);
+        dap_list_t *l_meta_list_item = dap_list_first(l_meta_list);
+        while (l_meta_list_item) {
+            dap_cert_metadata_t *l_meta_item = (dap_cert_metadata_t *)l_meta_list_item->data;
+            char *l_str;
+            switch (l_meta_item->type) {
+            case DAP_CERT_META_STRING:
+                l_str = strndup((char *)l_meta_item->value, l_meta_item->length);
+                printf("%s\t%u\t%u\t%s\n", l_meta_item->key, l_meta_item->type, l_meta_item->length, l_str);
+                free(l_str);
+                break;
+            case DAP_CERT_META_INT:
+            case DAP_CERT_META_BOOL:
+                printf("%s\t%u\t%u\t%u\n", l_meta_item->key, l_meta_item->type, l_meta_item->length, *(uint32_t *)l_meta_item->value);
+                break;
+            default:
+                printf("%s\t%u\t%u\t0x%016lX\n", l_meta_item->key, l_meta_item->type, l_meta_item->length, *(uint64_t *)l_meta_item->value);
+                break;
+            }
+            l_meta_list_item = l_meta_list_item->next;
+        }
+        dap_list_free(l_meta_list);
+    }
 }
 
 /**
@@ -512,6 +538,201 @@ void dap_cert_add_folder(const char *a_folder_path)
         log_it(L_WARNING, "Can't add folder %s to cert manager",a_folder_path);
 }
 
+dap_cert_metadata_t *dap_cert_new_meta(const char *a_key, dap_cert_metadata_type_t a_type, void *a_value, size_t a_value_size)
+{
+    if (!a_key || a_type > DAP_CERT_META_CUSTOM || (!a_value && a_value_size)) {
+        log_it(L_WARNING, "Incorrect arguments for dap_cert_new_meta()");
+        return NULL;
+    }
+    size_t l_meta_item_size = sizeof(dap_cert_metadata_t) + a_value_size + strlen(a_key) + 1;
+    dap_cert_metadata_t *l_new_meta = DAP_NEW_SIZE(void, l_meta_item_size);
+    l_new_meta->length = a_value_size;
+    l_new_meta->type = a_type;
+    memcpy((void *)l_new_meta->value, a_value, a_value_size);
+    dap_stpcpy((char *)&l_new_meta->value[a_value_size], a_key);
+    l_new_meta->key = (const char *)&l_new_meta->value[a_value_size];
+    return l_new_meta;
+}
+
+/**
+ * @brief dap_cert_add_meta Add metadata to certificate
+ * @param a_cert
+ * @param a_key
+ * @param a_type
+ * @param a_value
+ * @param a_value_size
+ */
+void dap_cert_add_meta(dap_cert_t *a_cert, const char *a_key, dap_cert_metadata_type_t a_type, void *a_value, size_t a_value_size)
+{
+    if (!a_cert) {
+        log_it(L_WARNING, "Certificate pointer to add metadata is NULL");
+        return;
+    }
+    dap_cert_metadata_t *l_new_meta = dap_cert_new_meta(a_key, a_type, a_value, a_value_size);
+    dap_binary_tree_t *l_new_root = dap_binary_tree_insert(a_cert->metadata, l_new_meta->key, (void *)l_new_meta);
+    if (!a_cert->metadata) {
+        a_cert->metadata = l_new_root;
+    }
+}
+
+void dap_cert_add_meta_scalar(dap_cert_t *a_cert, const char *a_key, dap_cert_metadata_type_t a_type, uint64_t a_value, size_t a_value_size)
+{
+    void *l_value;
+    byte_t l_tmp8;
+    uint16_t l_tmp16;
+    uint32_t l_tmp32;
+    uint64_t l_tmp64;
+    switch (a_type) {
+    case DAP_CERT_META_STRING:
+    case DAP_CERT_META_SIGN:
+    case DAP_CERT_META_CUSTOM:
+        log_it(L_WARNING, "incoorect metadata type for dap_cert_add_meta_scalar()");
+        return;
+    default:
+        switch (a_value_size) {
+        case 1:
+            l_tmp8 = a_value;
+            l_value = &l_tmp8;
+            break;
+        case 2:
+            l_tmp16 = a_value;
+            l_value = (void *)&l_tmp16;
+            break;
+        case 4:
+            l_tmp32 = a_value;
+            l_value = (void *)&l_tmp32;
+            break;
+        case 8:
+        default:
+            l_tmp64 = a_value;
+            l_value = (void *)&l_tmp64;
+            break;
+        }
+        break;
+    }
+    dap_cert_add_meta(a_cert, a_key, a_type, l_value, a_value_size);
+}
+
+/**
+ * @brief dap_cert_get_meta
+ * @param a_cert
+ * @param a_field
+ */
+dap_cert_metadata_t *dap_cert_get_meta(dap_cert_t *a_cert, const char *a_field)
+{
+    return dap_binary_tree_search(a_cert->metadata, a_field);
+}
+
+char *dap_cert_get_meta_string(dap_cert_t *a_cert, const char *a_field)
+{
+    dap_cert_metadata_t *l_meta = dap_cert_get_meta(a_cert, a_field);
+    if (!l_meta) {
+        return NULL;
+    }
+    if (l_meta->type != DAP_CERT_META_STRING) {
+        log_it(L_DEBUG, "Requested and actual metadata types are not equal");
+        return NULL;
+    }
+    return strndup((char *)&l_meta->value[0], l_meta->length);
+}
+
+bool dap_cert_get_meta_bool(dap_cert_t *a_cert, const char *a_field)
+{
+    dap_cert_metadata_t *l_meta = dap_cert_get_meta(a_cert, a_field);
+    if (!l_meta) {
+        return -1;
+    }
+    if (l_meta->type != DAP_CERT_META_BOOL) {
+        log_it(L_DEBUG, "Requested and actual metadata types are not equal");
+        return -1;
+    }
+    if (l_meta->length != sizeof(bool)) {
+        log_it(L_DEBUG, "Metadata field corrupted");
+    }
+    return *(bool *)&l_meta->value[0];
+}
+
+int dap_cert_get_meta_int(dap_cert_t *a_cert, const char *a_field)
+{
+    dap_cert_metadata_t *l_meta = dap_cert_get_meta(a_cert, a_field);
+    if (!l_meta) {
+        return -1;
+    }
+    if (l_meta->type != DAP_CERT_META_INT) {
+        log_it(L_DEBUG, "Requested and actual metadata types are not equal");
+        return -1;
+    }
+    if (l_meta->length != sizeof(int)) {
+        log_it(L_DEBUG, "Metadata field corrupted");
+    }
+    return *(int *)&l_meta->value[0];
+}
+
+time_t dap_cert_get_meta_time(dap_cert_t *a_cert, const char *a_field)
+{
+    dap_cert_metadata_t *l_meta = dap_cert_get_meta(a_cert, a_field);
+    if (!l_meta) {
+        return -1;
+    }
+    if (l_meta->type != DAP_CERT_META_DATETIME) {
+        log_it(L_DEBUG, "Requested and actual metadata types are not equal");
+        return -1;
+    }
+    if (l_meta->length != sizeof(time_t)) {
+        log_it(L_DEBUG, "Metadata field corrupted");
+    }
+    return *(time_t *)&l_meta->value[0];
+}
+
+time_t dap_cert_get_meta_period(dap_cert_t *a_cert, const char *a_field)
+{
+    dap_cert_metadata_t *l_meta = dap_cert_get_meta(a_cert, a_field);
+    if (!l_meta) {
+        return -1;
+    }
+    if (l_meta->type != DAP_CERT_META_DATETIME_PERIOD) {
+        log_it(L_DEBUG, "Requested and actual metadata types are not equal");
+        return -1;
+    }
+    if (l_meta->length != sizeof(time_t)) {
+        log_it(L_DEBUG, "Metadata field corrupted");
+    }
+    return *(time_t *)&l_meta->value[0];
+}
+
+dap_sign_t *dap_cert_get_meta_sign(dap_cert_t *a_cert, const char *a_field)
+{
+    dap_cert_metadata_t *l_meta = dap_cert_get_meta(a_cert, a_field);
+    if (!l_meta) {
+        return NULL;
+    }
+    if (l_meta->type != DAP_CERT_META_SIGN) {
+        log_it(L_DEBUG, "Requested and actual metadata types are not equal");
+        return NULL;
+    }
+    dap_sign_t *l_ret = (dap_sign_t *)&l_meta->value[0];
+    if (l_meta->length != dap_sign_get_size(l_ret)) {
+        log_it(L_DEBUG, "Metadata field corrupted");
+    }
+    return l_ret;
+}
+
+void *dap_cert_get_meta_custom(dap_cert_t *a_cert, const char *a_field, size_t *a_meta_size_out)
+{
+    dap_cert_metadata_t *l_meta = dap_cert_get_meta(a_cert, a_field);
+    if (!l_meta) {
+        return NULL;
+    }
+    if (l_meta->type != DAP_CERT_META_CUSTOM) {
+        log_it(L_DEBUG, "Requested and actual metadata types are not equal");
+        return NULL;
+    }
+    if (a_meta_size_out) {
+        *a_meta_size_out = l_meta->length;
+    }
+    return (void *)&l_meta->value[0];
+}
+
 /**
  * @brief dap_cert_deinit
  */
diff --git a/dap-sdk/crypto/src/dap_cert_file.c b/dap-sdk/crypto/src/dap_cert_file.c
index e6880ce440b80a9cdd4c9e3c21b077def3e531a8..cad1955c2d228d65d6a7e3399cfe6f212950b8d5 100755
--- a/dap-sdk/crypto/src/dap_cert_file.c
+++ b/dap-sdk/crypto/src/dap_cert_file.c
@@ -32,6 +32,8 @@
 
 #define LOG_TAG "dap_cert_file"
 
+static const char s_key_inheritor[] = "Inheritor";
+
 /**
  * @brief dap_cert_file_save
  * @param a_cert
@@ -64,6 +66,150 @@ int dap_cert_file_save(dap_cert_t * a_cert, const char * a_cert_file_path)
     }
 }
 
+// balance the binary tree
+void s_balance_the_tree(dap_cert_file_aux_t *a_reorder, size_t a_left_idx, size_t a_right_idx)
+{
+    if (a_left_idx == a_right_idx) {
+        a_reorder->buf[a_reorder->idx++] = a_left_idx;
+        return;
+    }
+    size_t i = (a_left_idx + a_right_idx) / 2 + 1;
+    a_reorder->buf[a_reorder->idx++] = i;
+    s_balance_the_tree(a_reorder, a_left_idx, i - 1);
+    if (i < a_right_idx) {
+        s_balance_the_tree(a_reorder, i + 1, a_right_idx);
+    }
+}
+
+void dap_cert_deserialize_meta(dap_cert_t *a_cert, const uint8_t *a_data, size_t a_size)
+{
+    dap_cert_metadata_t **l_meta_arr = NULL;
+    size_t l_mem_shift = 0;
+    size_t l_meta_items_count = 0;
+    while (l_mem_shift < a_size) {
+        const char *l_key_str = (const char *)&a_data[l_mem_shift];
+        if (!l_key_str) {
+            break;
+        }
+        l_mem_shift += strlen(l_key_str) + 1;
+        uint32_t l_value_size = dap_lendian_get32(&a_data[l_mem_shift]);
+        l_mem_shift += sizeof(uint32_t);
+        dap_cert_metadata_type_t l_meta_type = (dap_cert_metadata_type_t)a_data[l_mem_shift++];
+        const uint8_t *l_value = &a_data[l_mem_shift];
+        l_mem_shift += l_value_size;
+        uint16_t l_tmp16;
+        uint32_t l_tmp32;
+        uint64_t l_tmp64;
+        switch (l_meta_type) {
+        case DAP_CERT_META_STRING:
+        case DAP_CERT_META_SIGN:
+        case DAP_CERT_META_CUSTOM:
+            break;
+        default:
+            switch (l_value_size) {
+            case 1:
+                break;
+            case 2:
+                l_tmp16 = dap_lendian_get16(l_value);
+                l_value = (const uint8_t *)&l_tmp16;
+                break;
+            case 4:
+                l_tmp32 = dap_lendian_get32(l_value);
+                l_value = (const uint8_t *)&l_tmp32;
+                break;
+            case 8:
+            default:
+                l_tmp64 = dap_lendian_get64(l_value);
+                l_value = (const uint8_t *)&l_tmp64;
+                break;
+            }
+            break;
+        }
+        dap_cert_metadata_t *l_new_meta = dap_cert_new_meta(l_key_str, l_meta_type, (void *)l_value, l_value_size);
+        if (l_meta_arr == NULL) {
+            l_meta_arr = DAP_NEW(dap_cert_metadata_t *);
+        } else {
+            l_meta_arr = DAP_REALLOC(l_meta_arr, (l_meta_items_count + 1) * sizeof(dap_cert_metadata_t *));
+        }
+        l_meta_arr[l_meta_items_count++] = l_new_meta;
+    }
+    size_t l_reorder_arr[l_meta_items_count];
+    dap_cert_file_aux_t l_reorder = {l_reorder_arr, 0};
+    s_balance_the_tree(&l_reorder, 0, l_meta_items_count - 1);
+    size_t n = l_reorder_arr[0];
+    a_cert->metadata = dap_binary_tree_insert(NULL, l_meta_arr[n]->key, (void *)l_meta_arr[n]);
+    for (size_t i = 1; i < l_meta_items_count; i++) {
+        n = l_reorder_arr[i];
+        dap_binary_tree_insert(a_cert->metadata, l_meta_arr[n]->key, (void *)l_meta_arr[n]);
+    }
+    DAP_DELETE(l_meta_arr);
+}
+
+uint8_t *dap_cert_serialize_meta(dap_cert_t *a_cert, size_t *a_buflen_out)
+{
+    if (!a_cert) {
+        return NULL;
+    }
+    if ( a_cert->enc_key->_inheritor_size) {
+        dap_cert_add_meta_custom(a_cert, s_key_inheritor, a_cert->enc_key->_inheritor, a_cert->enc_key->_inheritor_size);
+    }
+    dap_list_t *l_meta_list = dap_binary_tree_inorder_list(a_cert->metadata);
+    if (!l_meta_list) {
+        return NULL;
+    }
+    dap_list_t *l_meta_list_item = dap_list_first(l_meta_list);
+    uint8_t *l_buf = NULL;
+    size_t l_mem_shift = 0;
+    while (l_meta_list_item) {
+        dap_cert_metadata_t *l_meta_item = l_meta_list_item->data;
+        size_t l_meta_item_size = sizeof(dap_cert_metadata_t) - sizeof(const char *) + l_meta_item->length + strlen(l_meta_item->key) + 1;
+        if (l_buf) {
+            l_buf = DAP_REALLOC(l_buf, l_mem_shift + l_meta_item_size);
+        } else {
+            l_buf = DAP_NEW_SIZE(uint8_t, l_meta_item_size);
+        }
+        strcpy((char *)&l_buf[l_mem_shift], l_meta_item->key);
+        l_mem_shift += strlen(l_meta_item->key) + 1;
+        dap_lendian_put32(&l_buf[l_mem_shift], l_meta_item->length);
+        l_mem_shift += sizeof(uint32_t);
+        l_buf[l_mem_shift++] = l_meta_item->type;
+        switch (l_meta_item->type) {
+        case DAP_CERT_META_STRING:
+        case DAP_CERT_META_SIGN:
+        case DAP_CERT_META_CUSTOM:
+            memcpy(&l_buf[l_mem_shift], l_meta_item->value, l_meta_item->length);
+            l_mem_shift += l_meta_item->length;
+            break;
+        default:
+            switch (l_meta_item->length) {
+            case 1:
+                l_buf[l_mem_shift++] = l_meta_item->value[0];
+                break;
+            case 2:
+                dap_lendian_put16(&l_buf[l_mem_shift], *(uint16_t *)&l_meta_item->value[0]);
+                l_mem_shift += 2;
+                break;
+            case 4:
+                dap_lendian_put32(&l_buf[l_mem_shift], *(uint32_t *)&l_meta_item->value[0]);
+                l_mem_shift += 4;
+                break;
+            case 8:
+            default:
+                dap_lendian_put64(&l_buf[l_mem_shift], *(uint64_t *)&l_meta_item->value[0]);
+                l_mem_shift += 8;
+                break;
+            }
+            break;
+        }
+        l_meta_list_item = l_meta_list_item->next;
+    }
+    dap_list_free(l_meta_list);
+    if (a_buflen_out) {
+        *a_buflen_out = l_mem_shift;
+    }
+    return l_buf;
+}
+
 /**
  * @brief dap_cert_file_save_to_mem
  * @param a_cert
@@ -79,12 +225,14 @@ uint8_t* dap_cert_mem_save(dap_cert_t * a_cert, uint32_t *a_cert_size_out)
 
     size_t l_priv_key_data_size = a_cert->enc_key->priv_key_data_size;
     size_t l_pub_key_data_size = a_cert->enc_key->pub_key_data_size;
+    size_t l_metadata_size = l_key->_inheritor_size;
     uint8_t *l_pub_key_data = a_cert->enc_key->pub_key_data_size ?
                 dap_enc_key_serealize_pub_key(l_key, &l_pub_key_data_size) :
                 NULL;
     uint8_t *l_priv_key_data = a_cert->enc_key->priv_key_data ?
                 dap_enc_key_serealize_priv_key(l_key, &l_priv_key_data_size) :
                 NULL;
+    uint8_t *l_metadata = dap_cert_serialize_meta(a_cert, &l_metadata_size);
 
     l_hdr.sign = dap_cert_FILE_HDR_SIGN;
     l_hdr.type = dap_cert_FILE_TYPE_PUBLIC;
@@ -103,13 +251,17 @@ uint8_t* dap_cert_mem_save(dap_cert_t * a_cert, uint32_t *a_cert_size_out)
     l_hdr.version = dap_cert_FILE_VERSION;
     l_hdr.data_size = l_pub_key_data_size;
     l_hdr.data_pvt_size = l_priv_key_data_size;
-    l_hdr.metadata_size = l_key->_inheritor_size;
+    l_hdr.metadata_size = l_metadata_size;
 
     l_hdr.ts_last_used = l_key->last_used_timestamp;
     l_hdr.sign_type = dap_sign_type_from_key_type ( l_key->type );
 
 
-    l_data = DAP_NEW_SIZE(void, sizeof(l_hdr) + DAP_CERT_ITEM_NAME_MAX + l_priv_key_data_size + l_pub_key_data_size + l_hdr.metadata_size);
+    l_data = DAP_NEW_SIZE(void, sizeof(l_hdr) + DAP_CERT_ITEM_NAME_MAX + l_priv_key_data_size + l_pub_key_data_size + l_metadata_size);
+    if (!l_data) {
+        log_it(L_ERROR,"Certificate \"%s\" was not serialized",a_cert->name);
+        goto lb_exit;
+    }
 
     memcpy(l_data +l_data_offset, &l_hdr ,sizeof(l_hdr) );
     l_data_offset += sizeof(l_hdr);
@@ -125,17 +277,21 @@ uint8_t* dap_cert_mem_save(dap_cert_t * a_cert, uint32_t *a_cert_size_out)
         l_data_offset += l_priv_key_data_size;
     }
 
-    if ( l_key->_inheritor_size ) {
-        memcpy(l_data +l_data_offset, l_key->_inheritor ,l_key->_inheritor_size );
-        l_data_offset += l_key->_inheritor_size;
+    if (l_metadata_size) {
+        memcpy(l_data + l_data_offset, l_metadata, l_metadata_size);
+        l_data_offset += l_metadata_size;
     }
 lb_exit:
     DAP_DELETE(l_pub_key_data);
-    DAP_DELETE(l_priv_key_data);
-    if (l_data)
-        log_it(L_NOTICE,"Certificate \"%s\" successfully serialized",a_cert->name);
-    else
-        log_it(L_ERROR,"Certificate \"%s\" was not serialized",a_cert->name);
+    if ( l_priv_key_data_size ) {
+        DAP_DELETE(l_priv_key_data);
+    }
+    if ( l_metadata_size ) {
+        DAP_DELETE(l_metadata);
+    }
+
+    log_it(L_NOTICE,"Certificate \"%s\" successfully serialized",a_cert->name);
+
     if(a_cert_size_out)
         *a_cert_size_out = l_data_offset;
     return l_data;
@@ -217,8 +373,9 @@ dap_cert_t* dap_cert_mem_load(const void * a_data, size_t a_data_size)
             dap_enc_key_deserealize_priv_key(l_ret->enc_key, l_data + l_data_offset, l_hdr.data_pvt_size);
             l_data_offset += l_hdr.data_pvt_size;
         }
-        if(l_hdr.metadata_size > 0 && l_ret->enc_key->_inheritor && l_ret->enc_key->_inheritor_size == l_hdr.metadata_size) {
-            memcpy(l_ret->enc_key->_inheritor, l_data + l_data_offset, l_ret->enc_key->_inheritor_size);
+        if ( l_hdr.metadata_size > 0 ){
+            dap_cert_deserialize_meta(l_ret, l_data + l_data_offset, l_hdr.metadata_size);
+            l_data_offset += l_hdr.metadata_size;
         }
         dap_enc_key_update(l_ret->enc_key);
         log_it(L_NOTICE,"Successfully loaded certificate %s", l_ret->name);
diff --git a/dap-sdk/crypto/src/dap_sign.c b/dap-sdk/crypto/src/dap_sign.c
index b27c2c2c57e74c182b9bcfd22df6c1c2cc3cd5c5..fea8f12eb6a982aa7b9b851f77db13304ce158f0 100755
--- a/dap-sdk/crypto/src/dap_sign.c
+++ b/dap-sdk/crypto/src/dap_sign.c
@@ -479,14 +479,14 @@ dap_multi_sign_t *dap_multi_sign_deserialize(dap_sign_type_enum_t a_type, uint8_
     l_mem_shift++;
     memcpy(&l_sign->sign_count, &a_sign[l_mem_shift], 1);
     l_mem_shift++;
-    l_sign->key_seq = DAP_NEW_SIZE(dap_multi_sign_keys_t, l_sign->sign_count * sizeof(dap_multi_sign_keys_t));
+    l_sign->key_seq = DAP_NEW_Z_SIZE(dap_multi_sign_keys_t, l_sign->sign_count * sizeof(dap_multi_sign_keys_t));
     for (int i = 0; i < l_sign->sign_count; i++) {
         memcpy(&l_sign->key_seq[i].num, &a_sign[l_mem_shift], 1);
         l_mem_shift++;
         memcpy(&l_sign->key_seq[i].type, &a_sign[l_mem_shift], sizeof(dap_sign_type_t));
         l_mem_shift += sizeof(dap_sign_type_t);
     }
-    l_sign->meta = DAP_NEW_SIZE(dap_multi_sign_meta_t, l_sign->sign_count * sizeof(dap_multi_sign_meta_t));
+    l_sign->meta = DAP_NEW_Z_SIZE(dap_multi_sign_meta_t, l_sign->sign_count * sizeof(dap_multi_sign_meta_t));
     size_t l_pkeys_size = 0, l_signes_size = 0;
     for (int i = 0; i < l_sign->sign_count; i++) {
         memcpy(&l_sign->meta[i].pkey_size, &a_sign[l_mem_shift], sizeof(uint32_t));
@@ -496,13 +496,13 @@ dap_multi_sign_t *dap_multi_sign_deserialize(dap_sign_type_enum_t a_type, uint8_
         l_mem_shift += sizeof(uint32_t);
         l_signes_size += l_sign->meta[i].sign_size;
     }
-    l_sign->key_hashes = DAP_NEW_SIZE(dap_chain_hash_fast_t, l_sign->total_count * sizeof(dap_chain_hash_fast_t));
+    l_sign->key_hashes = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, l_sign->total_count * sizeof(dap_chain_hash_fast_t));
     for (int i = 0; i < l_sign->total_count; i++) {
         memcpy(&l_sign->key_hashes[i], &a_sign[l_mem_shift], sizeof(dap_chain_hash_fast_t));
         l_mem_shift += sizeof(dap_chain_hash_fast_t);
     }
     uint32_t l_data_shift = 0, l_data_size = 0;
-    l_sign->pub_keys = DAP_NEW_SIZE(uint8_t, l_pkeys_size);
+    l_sign->pub_keys = DAP_NEW_Z_SIZE(uint8_t, l_pkeys_size);
     for (int i = 0; i < l_sign->sign_count; i++) {
         l_data_size = l_sign->meta[i].pkey_size;
         memcpy( &l_sign->pub_keys[l_data_shift], &a_sign[l_mem_shift],l_data_size);
@@ -510,7 +510,7 @@ dap_multi_sign_t *dap_multi_sign_deserialize(dap_sign_type_enum_t a_type, uint8_
         l_data_shift += l_data_size;
     }
     l_data_shift = l_data_size = 0;
-    l_sign->sign_data = DAP_NEW_SIZE(uint8_t, l_signes_size);
+    l_sign->sign_data = DAP_NEW_Z_SIZE(uint8_t, l_signes_size);
     for (int i = 0; i < l_sign->sign_count; i++) {
         l_data_size = l_sign->meta[i].sign_size;
         memcpy(&l_sign->sign_data[l_data_shift], &a_sign[l_mem_shift], l_data_size);
@@ -632,7 +632,7 @@ dap_multi_sign_t *dap_multi_sign_create(dap_multi_sign_params_t *a_params, const
     dap_multi_sign_t *l_sign = DAP_NEW_Z(dap_multi_sign_t);
     l_sign->type = a_params->type;
     l_sign->total_count = a_params->total_count;
-    l_sign->key_hashes = DAP_NEW_SIZE(dap_chain_hash_fast_t, a_params->total_count * sizeof(dap_chain_hash_fast_t));
+    l_sign->key_hashes = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, a_params->total_count * sizeof(dap_chain_hash_fast_t));
     for (int i = 0; i < a_params->total_count; i++) {
         if (!dap_hash_fast(a_params->keys[i]->pub_key_data, a_params->keys[i]->pub_key_data_size, &l_sign->key_hashes[i])) {
             log_it (L_ERROR, "Can't create multi-signature hash");
@@ -641,8 +641,8 @@ dap_multi_sign_t *dap_multi_sign_create(dap_multi_sign_params_t *a_params, const
         }
     }
     l_sign->sign_count = a_params->sign_count;
-    l_sign->key_seq = DAP_NEW_SIZE(dap_multi_sign_keys_t, a_params->sign_count * sizeof(dap_multi_sign_keys_t));
-    l_sign->meta = DAP_NEW_SIZE(dap_multi_sign_meta_t, a_params->sign_count * sizeof(dap_multi_sign_meta_t));
+    l_sign->key_seq = DAP_NEW_Z_SIZE(dap_multi_sign_keys_t, a_params->sign_count * sizeof(dap_multi_sign_keys_t));
+    l_sign->meta = DAP_NEW_Z_SIZE(dap_multi_sign_meta_t, a_params->sign_count * sizeof(dap_multi_sign_meta_t));
     for (int i = 0; i < l_sign->sign_count; i++) {
         uint8_t l_num = a_params->key_seq[i];
         l_sign->key_seq[i].num = l_num;
@@ -674,7 +674,7 @@ dap_multi_sign_t *dap_multi_sign_create(dap_multi_sign_params_t *a_params, const
         uint8_t *l_pkey = dap_sign_get_pkey(l_dap_sign_step, &l_pkey_size);
         l_sign->meta[i].pkey_size = l_pkey_size;
         if (l_pkeys_mem_shift == 0) {
-            l_sign->pub_keys = DAP_NEW_SIZE(uint8_t, l_pkey_size);
+            l_sign->pub_keys = DAP_NEW_Z_SIZE(uint8_t, l_pkey_size);
         } else {
             l_sign->pub_keys = DAP_REALLOC(l_sign->pub_keys, l_pkeys_mem_shift + l_pkey_size);
         }
@@ -683,7 +683,7 @@ dap_multi_sign_t *dap_multi_sign_create(dap_multi_sign_params_t *a_params, const
         uint8_t *l_sign_step = dap_sign_get_sign(l_dap_sign_step, &l_sign_size);
         l_sign->meta[i].sign_size = l_sign_size;
         if (l_signs_mem_shift == 0) {
-            l_sign->sign_data = DAP_NEW_SIZE(uint8_t, l_sign_size);
+            l_sign->sign_data = DAP_NEW_Z_SIZE(uint8_t, l_sign_size);
         } else {
             l_sign->sign_data = DAP_REALLOC(l_sign->sign_data, l_signs_mem_shift + l_sign_size);
         }
diff --git a/dap-sdk/crypto/src/newhope/newhope.pri b/dap-sdk/crypto/src/newhope/newhope.pri
index 7f618fd998c64c703a491a08b0d0f6240454243c..19a232bca15fc416a165badc40c3aba904019c59 100755
--- a/dap-sdk/crypto/src/newhope/newhope.pri
+++ b/dap-sdk/crypto/src/newhope/newhope.pri
@@ -1,3 +1,3 @@
-INCLUDEPATH += $$PW
+INCLUDEPATH += $$PWD
 HEADERS += $$PWD/newhope_api.h  $$PWD/newhope_cpakem.h  $$PWD/newhope_cpapke.h  $$PWD/newhope_ntt.h  $$PWD/newhope_params.h  $$PWD/newhope_poly.h  $$PWD/newhope_reduce.h
 SOURCES += $$PWD/newhope_cpakem.c  $$PWD/newhope_cpapke.c  $$PWD/newhope_ntt.c  $$PWD/newhope_poly.c  $$PWD/newhope_precomp.c  $$PWD/newhope_reduce.c
diff --git a/dap-sdk/crypto/src/ringct20/ringct20_params.c b/dap-sdk/crypto/src/ringct20/ringct20_params.c
index a0642d9046d1c21b3f76c2f9be1324e9d44642b6..b5bdb89009b6dcfcbb37bfee6d9bf8d79f201a2c 100644
--- a/dap-sdk/crypto/src/ringct20/ringct20_params.c
+++ b/dap-sdk/crypto/src/ringct20/ringct20_params.c
@@ -73,7 +73,7 @@ uint8_t H_bpoly_MAXSEC[14*NEWHOPE_RINGCT20_POLYBYTES] = {
 
 #elif (NEWHOPE_RINGCT20_N == 1024)
 #error "NEWHOPE_RINGCT20_N must be either 512 or 1024.. NEWHOPE_RINGCT20_N == 1024 not implemented yet"
-#elif
+#else
 #error "NEWHOPE_RINGCT20_N must be either 512 or 1024.."
 #endif
 
diff --git a/dap-sdk/crypto/test/crypto/dap_enc_sign_multi_test.c b/dap-sdk/crypto/test/crypto/dap_enc_sign_multi_test.c
index 2a7a47bb0b41e63943080599a161a5e1af92b295..ffb2c87b5c6d7d3088639b2cc2443721ceb230c9 100755
--- a/dap-sdk/crypto/test/crypto/dap_enc_sign_multi_test.c
+++ b/dap-sdk/crypto/test/crypto/dap_enc_sign_multi_test.c
@@ -69,5 +69,5 @@ void dap_enc_multi_sign_tests_run()
     dap_print_module_name("dap_enc_sign_multi");
     init_test_case();
 
-    benchmark_mgs_time("Signing and verifying message 1 time", benchmark_test_time(test_signing_verifying, 1));
+    benchmark_mgs_time("Signing and verifying message 1 time", benchmark_test_time(test_signing_verifying, 10));
 }
diff --git a/dap-sdk/crypto/test/crypto/main.c b/dap-sdk/crypto/test/crypto/main.c
index fe0887d99f357598c5d9eedbefd79a7f94e6049d..e1073d68602601603c7c5642bea5ce86e1f94b68 100755
--- a/dap-sdk/crypto/test/crypto/main.c
+++ b/dap-sdk/crypto/test/crypto/main.c
@@ -20,7 +20,7 @@ int main(void)
  // switch off debug info from library
     dap_log_level_set(L_CRITICAL);
     const int  test_numbers = 100;
-    //dap_enc_multi_sign_tests_run();return 0;
+    dap_enc_multi_sign_tests_run();
     dap_enc_newhope_tests_run(test_numbers);
     test_encypt_decrypt      (test_numbers, DAP_ENC_KEY_TYPE_SEED_OFB,  32);
     test_encypt_decrypt_fast (test_numbers, DAP_ENC_KEY_TYPE_SEED_OFB,  32);
diff --git a/dap-sdk/net/client/dap_client_http.c b/dap-sdk/net/client/dap_client_http.c
index e9dbec618e364a15545771afa808ee62e42b77d3..2371d6cd58d2faba7729b5275fed15dbb1f72a30 100644
--- a/dap-sdk/net/client/dap_client_http.c
+++ b/dap-sdk/net/client/dap_client_http.c
@@ -383,8 +383,8 @@ void* dap_client_http_request_custom(const char *a_uplink_addr, uint16_t a_uplin
         dap_events_socket_create_after(l_ev_socket);
     }
     else {
-        log_it(L_ERROR, "Remote address can't connected (%s:%u) with sock_id %d err=%d", a_uplink_addr, a_uplink_port,
-                l_socket, errno);
+        log_it(L_ERROR, "Remote address can't connected (%s:%u) with sock_id %d err: %s", a_uplink_addr, a_uplink_port,
+                l_socket, strerror(errno));
         //l_ev_socket->no_close = false;
         dap_events_socket_kill_socket(l_ev_socket);
         //shutdown(l_ev_socket->socket, SHUT_RDWR);
diff --git a/dap-sdk/net/core/dap_events.c b/dap-sdk/net/core/dap_events.c
index 0d8e6009e7635933d49ea3d98c91982ade5d3f38..5bc14c605485a164b3a94987c1b07a4ae1e6292f 100644
--- a/dap-sdk/net/core/dap_events.c
+++ b/dap-sdk/net/core/dap_events.c
@@ -289,7 +289,7 @@ static void *thread_worker_function(void *arg)
 //  memset( &events, 0, sizeof(events) );
 
     size_t total_sent;
-    int bytes_sent;
+    int bytes_sent = 0;
 
     while(1) {
 
diff --git a/dap-sdk/net/core/dap_events_socket.c b/dap-sdk/net/core/dap_events_socket.c
index 6060e27a3f02081a19c98a942885ceeace575afb..2d5ad7d20f40971b3dfb2f06cf858f79404f688d 100644
--- a/dap-sdk/net/core/dap_events_socket.c
+++ b/dap-sdk/net/core/dap_events_socket.c
@@ -264,6 +264,12 @@ int dap_events_socket_kill_socket( dap_events_socket_t *a_es )
     return -1;
   }
 
+  if( !a_es->dap_worker ) {
+      log_it( L_WARNING, "%s: socket %u has no worker thread", __PRETTY_FUNCTION__, a_es->socket );
+      a_es->kill_signal = true;
+      return 0;
+  }
+
   uint32_t tn = a_es->dap_worker->number_thread;
 
   dap_worker_t *w = a_es->dap_worker;
diff --git a/dap-sdk/net/core/dap_server.c b/dap-sdk/net/core/dap_server.c
index dd199b333ba93de547e37584e4b2684bb0ce1b0d..f50290948436b444260c62a2e1b59e6b9dad0ad4 100644
--- a/dap-sdk/net/core/dap_server.c
+++ b/dap-sdk/net/core/dap_server.c
@@ -66,6 +66,7 @@
 
 #include "dap_common.h"
 #include "dap_server.h"
+#include "dap_strfuncs.h"
 
 #define LOG_TAG "server"
 
@@ -740,8 +741,6 @@ int32_t dap_server_loop( dap_server_t *d_server )
   static uint32_t pickthread = 0;  // just for test
   pthread_t thread_listener[ DAP_MAX_THREADS ];
 
-  if ( !d_server ) return 1;
-
   for( uint32_t i = 0; i < _count_threads; ++i ) {
 
     EPOLL_HANDLE efd = epoll_create1( 0 );
@@ -767,49 +766,55 @@ int32_t dap_server_loop( dap_server_t *d_server )
   struct epoll_event  pev;
   struct epoll_event  events[ 16 ];
 
-  memset(&pev, 0, sizeof(pev));
-  pev.events = EPOLLIN | EPOLLERR;
-  pev.data.fd = d_server->socket_listener;
+  if(d_server){
+      memset(&pev, 0, sizeof(pev));
+      pev.events = EPOLLIN | EPOLLERR;
+      pev.data.fd = d_server->socket_listener;
 
-  if( epoll_ctl( efd, EPOLL_CTL_ADD, d_server->socket_listener, &pev) != 0 ) {
-    log_it( L_ERROR, "epoll_ctl failed 004" );
-    goto error;
+      if( epoll_ctl( efd, EPOLL_CTL_ADD, d_server->socket_listener, &pev) != 0 ) {
+          log_it( L_ERROR, "epoll_ctl failed 004" );
+          goto error;
+      }
   }
 
   while( !bQuitSignal ) {
+    if(d_server){
+      int32_t n = epoll_wait( efd, &events[0], 16, -1 );
 
-    int32_t n = epoll_wait( efd, &events[0], 16, -1 );
+      if ( bQuitSignal )
+        break;
 
-    if ( bQuitSignal )
-      break;
+      if ( n <= 0 ) {
+        if ( errno == EINTR )
+          continue;
+        log_it( L_ERROR, "Server wakeup no events / error" );
+        break;
+      }
 
-    if ( n <= 0 ) {
-      if ( errno == EINTR )
-        continue;
-      log_it( L_ERROR, "Server wakeup no events / error" );
-      break;
-    }
+      for( int32_t i = 0; i < n; ++ i ) {
 
-    for( int32_t i = 0; i < n; ++ i ) {
+        if ( events[i].events & EPOLLIN ) {
 
-      if ( events[i].events & EPOLLIN ) {
+          int client_fd = accept( events[i].data.fd, 0, 0 );
 
-        int client_fd = accept( events[i].data.fd, 0, 0 );
+          if ( client_fd < 0 ) {
+            log_it( L_ERROR, "accept_cb: error accept socket");
+            continue;
+          }
 
-        if ( client_fd < 0 ) {
-          log_it( L_ERROR, "accept_cb: error accept socket");
-          continue;
+          set_nonblock_socket( client_fd );
+          dap_server_add_socket( client_fd, -1 );
+        }
+        else if( events[i].events & EPOLLERR ) {
+          log_it( L_ERROR, "Server socket error event" );
+          goto exit;
         }
 
-        set_nonblock_socket( client_fd );
-        dap_server_add_socket( client_fd, -1 );
-      }
-      else if( events[i].events & EPOLLERR ) {
-        log_it( L_ERROR, "Server socket error event" );
-        goto exit;
-      }
-
-    } // for
+      } // for
+    }else{
+      static const int c_dap_server_client_mode_tick_rate = 200;
+      dap_usleep(DAP_USEC_PER_SEC / c_dap_server_client_mode_tick_rate);
+    }
 
   } // while
 
diff --git a/dap-sdk/net/stream/stream/dap_stream.c b/dap-sdk/net/stream/stream/dap_stream.c
index adc20540126577325035768c18a2f47330ce9269..34cc1b870fc73139417608397faa518038aafc90 100644
--- a/dap-sdk/net/stream/stream/dap_stream.c
+++ b/dap-sdk/net/stream/stream/dap_stream.c
@@ -476,7 +476,7 @@ void s_data_read(dap_client_remote_t* a_client, void * arg)
     int * ret = (int *) arg;
 
     if (s_dump_packet_headers ) {
-        log_it(L_DEBUG,"dap_stream_data_read: client->buf_in_size=%u" ,
+        log_it(L_DEBUG,"dap_stream_data_read: ready_to_write=%s, client->buf_in_size=%u" ,
                (a_client->flags & DAP_SOCK_READY_TO_WRITE)?"true":"false", a_client->buf_in_size );
     }
     *ret = dap_stream_data_proc_read( l_stream);
diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index 03ee9c0cb8d3f8bd8378b43f723c10e560705216..a484ac82a6a934365f06707fcaee4bcac0899b0e 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -912,8 +912,10 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
         // delete transaction from the cache list
         //ret = dap_chain_ledger_tx_remove(a_ledger, l_tx_hash);
         // there should be no duplication
-        log_it(L_WARNING, "Transaction (hash=0x%x)  deleted from cache because there is an attempt to add it to cache",
-                l_tx_hash);
+        char * l_hash_str = dap_chain_hash_fast_to_str_new(l_tx_hash);
+        log_it(L_WARNING, "Transaction (hash=%s)  deleted from cache because there is an attempt to add it to cache",
+               l_hash_str);
+        DAP_DELETE(l_hash_str);
         ret = 1;
         goto FIN;
     }
diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c
index 72febb8922a11d6f9c35cb0d2c067a5826af66f6..031b3ebffe787f381a9cc175f629239d14a36e10 100644
--- a/modules/common/dap_chain_datum_token.c
+++ b/modules/common/dap_chain_datum_token.c
@@ -125,13 +125,58 @@ dap_chain_datum_token_tsd_t* dap_chain_datum_token_tsd_get(dap_chain_datum_token
 void dap_chain_datum_token_flags_dump(dap_string_t * a_str_out, uint16_t a_flags)
 {
     if(!a_flags){
-        dap_string_append_printf(a_str_out, "<NONE>\n");
+        dap_string_append_printf(a_str_out, "%s\n",
+                c_dap_chain_datum_token_flag_str[DAP_CHAIN_DATUM_TOKEN_FLAG_NONE]);
         return;
     }
-    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"  );
+    bool is_first = true;
+    for ( uint16_t i = 0;  i <= DAP_CHAIN_DATUM_TOKEN_FLAG_MAX; i++){
+        if(   a_flags &  (1 << i) ){
+            if(is_first)
+                is_first = false;
+            else
+                dap_string_append_printf(a_str_out,", ");
+            dap_string_append_printf(a_str_out,"%s", c_dap_chain_datum_token_flag_str[i]);
+        }
+        if(i == DAP_CHAIN_DATUM_TOKEN_FLAG_MAX)
+            dap_string_append_printf(a_str_out, "\n");
     }
 }
 
+
+/**
+ * @brief dap_chain_datum_token_certs_dump
+ * @param a_str_out
+ * @param a_data_n_tsd
+ * @param a_certs_size
+ */
+void dap_chain_datum_token_certs_dump(dap_string_t * a_str_out, byte_t * a_data_n_tsd, size_t a_certs_size) {
+    dap_string_append_printf(a_str_out, "signatures: ");
+    if (!a_certs_size) {
+        dap_string_append_printf(a_str_out, "<NONE>\n");
+        return;
+    }
+
+    dap_string_append_printf(a_str_out, "\n");
+
+    size_t l_offset = 0;
+    for (int i = 1; l_offset < (a_certs_size); i++) {
+        dap_sign_t *l_sign = (dap_sign_t *) (a_data_n_tsd + l_offset);
+        l_offset += dap_sign_get_size(l_sign);
+        if (l_sign->header.sign_size == 0) {
+            dap_string_append_printf(a_str_out, "<CORRUPTED - 0 size signature>\n");
+            continue;
+        }
+
+        dap_chain_hash_fast_t l_pkey_hash = {0};
+        if (dap_sign_get_pkey_hash(l_sign, &l_pkey_hash) == false) {
+            dap_string_append_printf(a_str_out, "<CORRUPTED - can't calc hash>\n");
+            continue;
+        }
+
+        char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_pkey_hash);
+
+        dap_string_append_printf(a_str_out, "%d) %s, %s, %lu bytes\n", i, l_hash_str,
+                                 dap_sign_type_to_str(l_sign->header.type), l_sign->header.sign_size);
+    }
+}
diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h
index 059855fbfe05c49a30250ed7f15b33a67a5a1421..c2b2d7651ce46a6428a936e82765a974ba73c448 100644
--- a/modules/common/include/dap_chain_common.h
+++ b/modules/common/include/dap_chain_common.h
@@ -210,11 +210,21 @@ void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_cha
 int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr);
 
 static inline long double dap_chain_balance_to_coins( uint128_t a_balance){
-    return (long double) a_balance / DATOSHI_LD;
+#ifdef DAP_GLOBAL_IS_INT128
+        return (long double) a_balance / DATOSHI_LD;
+#else
+    return (long double)   (a_balance.u64[0] / DATOSHI_LD);
+#endif
 }
 
 static inline uint128_t dap_chain_coins_to_balance( long double a_balance){
+#ifdef DAP_GLOBAL_IS_INT128
     return (uint128_t)( a_balance * DATOSHI_LD) ;
+#else
+    uint128_t l_ret={0};
+    l_ret.u64[0]=a_balance *DATOSHI_LD;
+    return l_ret;
+#endif
 }
 
 /**
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index 32e2f42eb5787b38fb40bb1ebb78bbbdd80ee4c5..d130cec690b5597b0cd196cf8b8974d980de3709 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -237,6 +237,7 @@ 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);
+void dap_chain_datum_token_certs_dump(dap_string_t * a_str_out, byte_t * a_data_n_tsd, size_t a_certs_size);
 
 #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)
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 30e9e292fa1acf50b62c867a96d97b9275ef2a7a..05a171839ec0eefcae8021b17ddc2493e9743801 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -2111,7 +2111,7 @@ dap_chain_datum_tx_t * dap_chain_net_get_tx_by_hash(dap_chain_net_t * a_net, dap
 dap_list_t * dap_chain_net_get_add_gdb_group(dap_chain_net_t * a_net, dap_chain_node_addr_t a_node_addr)
 {
     dap_list_t *l_list_groups = NULL;
-    if(!PVT(a_net)->gdb_sync_nodes_addrs || !a_net)
+    if(!a_net || !PVT(a_net) || !PVT(a_net)->gdb_sync_nodes_addrs)
         return NULL;
     for(uint16_t i = 0; i < PVT(a_net)->gdb_sync_nodes_addrs_count; i++) {
         if(a_node_addr.uint64 == PVT(a_net)->gdb_sync_nodes_addrs[i].uint64) {
@@ -2161,6 +2161,11 @@ void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_da
         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;
+            if(l_token_size < sizeof(dap_chain_datum_token_t)){
+                dap_string_append_printf(a_str_out,"==Datum has incorrect size. Only %lu, while at least %lu is expected\n",
+                                         l_token_size, sizeof(dap_chain_datum_token_t));
+                return;
+            }
             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);
@@ -2217,7 +2222,7 @@ void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_da
                                     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_string_append_printf(a_str_out,"total_signs_remove: %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);
@@ -2281,13 +2286,14 @@ void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_da
                     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_chain_datum_token_tsd_t * l_tsd_first = dap_chain_datum_token_tsd_get(l_token, l_token_size);
+                    if (l_tsd_first == 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){
+                            dap_chain_datum_token_tsd_t * l_tsd = (void*)l_tsd_first + l_offset;
                             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);
@@ -2295,7 +2301,7 @@ void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_da
                             }
                             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_string_append_printf(a_str_out,"total_supply: %lu\n",
                                                              dap_chain_datum_token_tsd_get_scalar(l_tsd, uint128_t) );
                                 break;
                                 case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID :
@@ -2332,6 +2338,9 @@ void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_da
 
                         }
                     }
+
+                    size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_decl.tsd_total_size;
+                    dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd, l_certs_field_size);
                 }break;
                 case DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC:{
                     dap_string_append_printf(a_str_out,"type: PUBLIC\n");
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 1513a12acc6be27e541c70dbba42ca760b2024b5..c6a23444b02b427c36398af89258a60977dc6f80 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -1145,11 +1145,10 @@ int com_node(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply)
         // TODO add progress info to console
         res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_SYNCED, timeout_ms);
         if(res < 0) {
+            dap_chain_node_cli_set_reply_text(a_str_reply, "Error: can't sync with node "NODE_ADDR_FP_STR,
+                                            NODE_ADDR_FP_ARGS_S(l_node_client->remote_node_addr));
             dap_chain_node_client_close(l_node_client);
             DAP_DELETE(l_remote_node_info);
-            dap_chain_node_cli_set_reply_text(a_str_reply, "Error: can't sync with node "NODE_ADDR_FP_STR,
-                    NODE_ADDR_FP_ARGS_S(l_node_client->remote_node_addr));
-
             log_it(L_WARNING, "Gdb synced err -2");
             return -2;
 
@@ -2294,7 +2293,7 @@ int com_token_update(int argc, char ** argv, void *arg_func, char ** a_str_reply
                              dap_chain_node_cli_set_reply_text(a_str_reply, "Flag can't be \"%s\"",*l_str_flags);
                              return -20;
                          }
-                         l_flags |= l_flag;
+                         l_flags |= (1<<l_flag);
                          l_str_flags++;
                      }
                      // Add flags as set_flags TDS section
@@ -2337,6 +2336,7 @@ int com_token_update(int argc, char ** argv, void *arg_func, char ** a_str_reply
                     l_tsd_total_size+= dap_chain_datum_token_tsd_size( l_tsd);
                 }else if ( strcmp( argv[l_arg_index],"-total_signs_valid" )==0){ // Signs valid
                     uint16_t l_param_value = (uint16_t)atoi(l_arg_param);
+                    l_signs_total = l_param_value;
                     dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_create_scalar(
                                                             DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID, l_param_value);
                     dap_list_append( l_tsd_list, l_tsd);
@@ -2604,7 +2604,7 @@ int com_token_decl(int argc, char ** argv, void *arg_func, char ** a_str_reply)
                              dap_chain_node_cli_set_reply_text(a_str_reply, "Flag can't be \"%s\"",*l_str_flags);
                              return -20;
                          }
-                         l_flags |= l_flag;
+                         l_flags |= (1<<l_flag);
                          l_str_flags++;
                      }
                 } else if ( strcmp( argv[l_arg_index],"-total_supply" )==0){ // Total supply
@@ -2613,8 +2613,9 @@ int com_token_decl(int argc, char ** argv, void *arg_func, char ** a_str_reply)
                                                             DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY, l_param_value);
                     dap_list_append( l_tsd_list, l_tsd);
                     l_tsd_total_size+= dap_chain_datum_token_tsd_size( l_tsd);
-                }else if ( strcmp( argv[l_arg_index],"-signs_valid" )==0){ // Signs valid
+                }else if ( strcmp( argv[l_arg_index],"-total_signs_valid" )==0){ // Signs valid
                     uint16_t l_param_value = (uint16_t)atoi(l_arg_param);
+                    l_signs_total = l_param_value;
                     dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_create_scalar(
                                                             DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID, l_param_value);
                     dap_list_append( l_tsd_list, l_tsd);
@@ -2700,7 +2701,7 @@ int com_token_decl(int argc, char ** argv, void *arg_func, char ** a_str_reply)
                 }
                 switch (l_tsd->type){
                     case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY:
-                        log_it(L_DEBUG,"== TOTAL_SUPPLY: %llf.20",
+                        log_it(L_DEBUG,"== TOTAL_SUPPLY: %0.9llf",
                                dap_chain_balance_to_coins( dap_chain_datum_token_tsd_get_scalar(l_tsd,uint128_t) ) );
                     break;
                     case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID:
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index 32ea1ae2e53b6934179c906c5133317717deb78f..3424ca612fb9782b33cb37f6e18df8379d56fe2d 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -275,11 +275,11 @@ char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * a_chain)
     dap_tx_data_t *l_iter_current, *l_item_tmp;
     HASH_ITER(hh, l_tx_data_hash , l_iter_current, l_item_tmp)
     {
+        HASH_DEL(l_tx_data_hash, l_iter_current);
         // delete datum
         DAP_DELETE(l_iter_current->datum);
         // delete struct
         DAP_DELETE(l_iter_current);
-        HASH_DEL(l_tx_data_hash, l_iter_current);
     }
 
     // if no history
diff --git a/modules/net/dap_dns_server.c b/modules/net/dap_dns_server.c
index 64322e2a78ffeaddfe244950483f47c55ef56923..b781f9892fc52a2404acecc367f787bc7c24c813 100644
--- a/modules/net/dap_dns_server.c
+++ b/modules/net/dap_dns_server.c
@@ -33,7 +33,6 @@
 #include "dap_chain_global_db.h"
 #include "dap_chain_global_db_remote.h"
 
-#define UNUSED(x) (void)(x)
 #define LOG_TAG "dap_dns_server"
 
 static dap_dns_server_t *s_dns_server;
@@ -315,7 +314,6 @@ void dap_dns_server_start() {
         return;
     }
     s_dns_server->instance->client_read_callback = dap_dns_client_read;
-    s_dns_server->instance->client_read_callback = *dap_dns_client_read;
     s_dns_server->instance->client_write_callback = NULL;
     s_dns_server->instance->client_new_callback = NULL;
     s_dns_server->instance->client_delete_callback = NULL;
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index 1e6acf8751e67bf2731d745c008da99144a21fa4..78c1198dab82402a7b7cc4551c2d0cb554baa83b 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -587,7 +587,9 @@ static int s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_pt
                 dap_chain_cs_dag_event_item_t * l_event_search = NULL;
                 HASH_FIND(hh, PVT(l_dag)->events ,l_hash ,sizeof (*l_hash),  l_event_search);
                 if ( l_event_search == NULL ){
-                    log_it(L_DEBUG, "Hash %s wasn't in hashtable of previously parsed", l_hash);
+                    char * l_hash_str = dap_chain_hash_fast_to_str_new(l_hash);
+                    log_it(L_DEBUG, "Hash %s wasn't in hashtable of previously parsed", l_hash_str);
+                    DAP_DELETE(l_hash_str);
                     return 1;
                 }