diff --git a/dap-sdk/core/include/dap_common.h b/dap-sdk/core/include/dap_common.h
index 164121dd11fe57bf04f86571482f2bfcc3217589..a5460b55f1b16422a19924985ac53fcf5b34aa2d 100755
--- a/dap-sdk/core/include/dap_common.h
+++ b/dap-sdk/core/include/dap_common.h
@@ -508,7 +508,10 @@ static inline void * dap_mempcpy(void * a_dest,const void * a_src,size_t n)
     return ((byte_t*) memcpy(a_dest,a_src,n))+n;
 }
 
-
+int dap_is_alpha_and_(char e);
+int dap_is_alpha(char e);
+int dap_is_digit(char e);
+char **dap_parse_items(const char *a_str, char a_delimiter, int *a_count, const int a_only_digit);
 
 #ifdef __MINGW32__
 int exec_silent(const char *a_cmd);
diff --git a/dap-sdk/core/src/dap_common.c b/dap-sdk/core/src/dap_common.c
index 2789fec964794a738da7f5df3c47f67aea44ddfb..f15e6cb0a91a5d1fe6c09ea96ca8c8c5a176a2cf 100755
--- a/dap-sdk/core/src/dap_common.c
+++ b/dap-sdk/core/src/dap_common.c
@@ -1097,3 +1097,83 @@ char* dap_ctime_r(time_t *a_time, char* a_buf){
         return "(null)\r\n";
 }
 
+int dap_is_alpha_and_(char e)
+{
+    if ((e >= '0' && e <= '9')||(e >= 'a' && e <= 'z')||(e >= 'A' && e <= 'Z')||(e == '_')) return 1;
+    return 0;
+}
+
+int dap_is_alpha(char e)
+{
+    if ((e >= '0' && e <= '9')||(e >= 'a' && e <= 'z')||(e >= 'A' && e <= 'Z')) return 1;
+    return 0;
+}
+int dap_is_digit(char e)
+{
+    if ((e >= '0' && e <= '9')) return 1;
+    return 0;
+}
+char **dap_parse_items(const char *a_str, char a_delimiter, int *a_count, const int a_only_digit)
+{
+    int l_count_temp = *a_count = 0;
+    int l_len_str = strlen(a_str);
+    if (l_len_str == 0) return NULL;
+    char *s, *l_temp_str;
+    s = l_temp_str = dap_strdup(a_str);
+
+    int l_buf = 0;
+    for (int i = 0; i < l_len_str; i++) {
+        if (s[i] == a_delimiter && !l_buf) {
+            s[i] = 0;
+            continue;
+        }
+        if (s[i] == a_delimiter && l_buf) {
+            s[i] = 0;
+            l_buf = 0;
+            continue;
+        }
+        if (!dap_is_alpha(s[i]) && l_buf) {
+            s[i] = 0;
+            l_buf = 0;
+            continue;
+        }
+        if (!dap_is_alpha(s[i]) && !l_buf) {
+            s[i] = 0;
+            continue;
+        }
+        if (a_only_digit) {
+            if (dap_is_digit(s[i])) {
+                l_buf++;
+                if (l_buf == 1) l_count_temp++;
+                continue;
+            }
+        } else if (dap_is_alpha(s[i])) {
+            l_buf++;
+            if (l_buf == 1) l_count_temp++;
+            continue;
+        }
+        if (!dap_is_alpha(s[i])) {
+            l_buf = 0;
+            s[i] = 0;
+            continue;
+        }
+    }
+
+    s = l_temp_str;
+    if (l_count_temp == 0) {
+        free (l_temp_str);
+        return NULL;
+    }
+
+    char **lines = DAP_CALLOC(l_count_temp, sizeof (void *));
+    for (int i = 0; i < l_count_temp; i++) {
+        while (*s == 0) s++;
+        lines[i] = strdup(s);
+        s = strchr(s, '\0');
+        s++;
+    }
+
+    free (l_temp_str);
+    *a_count = l_count_temp;
+    return lines;
+}
diff --git a/dap-sdk/crypto/src/dap_cert.c b/dap-sdk/crypto/src/dap_cert.c
index f813c276d6c9b3d1b66f57a20bc04ca374bf1bd2..8e77a4649d4d2e773c569adc4e32168d8cb2a6a1 100755
--- a/dap-sdk/crypto/src/dap_cert.c
+++ b/dap-sdk/crypto/src/dap_cert.c
@@ -848,4 +848,4 @@ void *dap_cert_get_meta_custom(dap_cert_t *a_cert, const char *a_field, size_t *
 void dap_cert_deinit()
 {
 
-}
\ No newline at end of file
+}
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index edda63085b9aa08e4508c50ef460ee9ffd2a5bfa..c118458f8a59b37f6c30fd7fc04dca6443d8a6ae 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -266,6 +266,9 @@ static dap_chain_type_t s_chain_type_from_str(const char *a_type_str)
     if(!dap_strcmp(a_type_str, "ca")) {
         return CHAIN_TYPE_CA;
     }
+    if(!dap_strcmp(a_type_str, "signer")) {
+	    return CHAIN_TYPE_SIGNER;
+    }
     return CHAIN_TYPE_LAST;
 }
 
@@ -295,6 +298,9 @@ static uint16_t s_datum_type_from_str(const char *a_type_str)
     if(!dap_strcmp(a_type_str, "transaction")) {
         return DAP_CHAIN_DATUM_256_TX;
     }
+    if (!dap_strcmp(a_type_str, "signer")) {
+        return DAP_CHAIN_DATUM_SIGNER;
+    }
     return DAP_CHAIN_DATUM_CUSTOM;
 }
 
diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h
index 6925d627291f1202e534e3f0040bdb36412dec0a..65d3b5840f3d8a6dbd66b95dc4af3abd0ce1f566 100644
--- a/modules/chain/include/dap_chain.h
+++ b/modules/chain/include/dap_chain.h
@@ -95,6 +95,7 @@ typedef enum dap_chain_type
     CHAIN_TYPE_EMISSION,
     CHAIN_TYPE_TX,
     CHAIN_TYPE_CA,
+    CHAIN_TYPE_SIGNER,
     CHAIN_TYPE_LAST
     // CHAIN_TYPE_256_TOKEN, // 256
     // CHAIN_TYPE_256_EMISSION, // 256
diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h
index 3ccaaf44e17095818053103ef450859feab6cbca..042789f2d47e2a2863e822494942eaa774343243 100644
--- a/modules/common/include/dap_chain_datum.h
+++ b/modules/common/include/dap_chain_datum.h
@@ -55,6 +55,7 @@
 
 /// CA with public key and self signed metadata
 #define DAP_CHAIN_DATUM_CA                  0x0c00
+#define DAP_CHAIN_DATUM_SIGNER              0x0c01
 
 /// Token
 /// Simple token decl
@@ -84,6 +85,8 @@
             s = "DATUM_EVM_DATA"; break;    \
         case DAP_CHAIN_DATUM_CA:            \
             s = "DATUM_CA"; break;          \
+	case DAP_CHAIN_DATUM_SIGNER:        \
+            s = "DATUM_SIGNER"; break;      \
         case DAP_CHAIN_DATUM_CUSTOM:        \
             s = "DATUM_CUSTOM"; break;      \
         case DAP_CHAIN_DATUM_TOKEN_DECL:    \
diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
index 6b763948e957d283f07c21107deffb15819687d2..a71a7f79b6142b5e1a60dcb85bd6ebf35d933c61 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -302,7 +302,6 @@ static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_net_c
 
     const char * l_events_sign_cert = NULL;
     if ( ( l_events_sign_cert = dap_config_get_item_str(a_chain_net_cfg,"dag-poa","events-sign-cert") ) != NULL ) {
-
         if ( ( PVT(l_poa)->events_sign_cert = dap_cert_find_by_name(l_events_sign_cert)) == NULL ){
             log_it(L_ERROR,"Can't load events sign certificate, name \"%s\" is wrong",l_events_sign_cert);
         }else
diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c
index 415910ef4d43c9b4cb2e4f153d464d3d13cec7c3..2cc6f6d04ed91ce54ee5913da1571cc65598c343 100644
--- a/modules/consensus/none/dap_chain_cs_none.c
+++ b/modules/consensus/none/dap_chain_cs_none.c
@@ -368,6 +368,8 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
             if ( dap_cert_chain_file_save(l_datum, a_chain->net_name) < 0 )
                 return ATOM_REJECT;
         }break;
+	case DAP_CHAIN_DATUM_SIGNER:
+				break;
         default: return ATOM_REJECT;
     }
 
diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c
index e72a1242c09f04606ce71c772202e3d60b03ae63..8834d39989aaf83202bff19f6b2f6bd546b9444d 100644
--- a/modules/mempool/dap_chain_mempool.c
+++ b/modules/mempool/dap_chain_mempool.c
@@ -93,6 +93,7 @@ char *dap_chain_mempool_datum_add(dap_chain_datum_t * a_datum, dap_chain_t * a_c
     } else {
         log_it(L_WARNING, "Can't place data's hash %s was placed in mempool", l_key_str);
         DAP_DELETE(l_key_str);
+	l_key_str = NULL;
     }
     DAP_DELETE(l_gdb_group);
     return l_key_str;
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index 09745c70f49314a71740572eead1de2d47bfb82c..c3ed8698873fde589373462351ff00ef44043f4f 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -928,7 +928,10 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
             "global_db flush \n\n"
 //                    "global_db wallet_info set -addr <wallet address> -cell <cell id> \n\n"
             );
-
+    dap_chain_node_cli_cmd_item_create("mempool", com_signer, "Sign operations",
+               "mempool sign -net <net name> -chain <chain name> -file <filename> [-mime <(SIGNER_FILENAME,SIGNER_FILENAME_SHORT,SIGNER_FILESIZE,SIGNER_DATE,SIGNER_MIME_MAGIC) or (SIGNER_ALL_FLAGS)>]\n"
+               "mempool check -net <net name> ((-file <filename>) or (-hash <hash>)) [-mime <(SIGNER_FILENAME,SIGNER_FILENAME_SHORT,SIGNER_FILESIZE,SIGNER_DATE,SIGNER_MIME_MAGIC) or (SIGNER_ALL_FLAGS)>]\n"
+                                          );
     dap_chain_node_cli_cmd_item_create("node", com_node, "Work with node",
             "node add  -net <net name> -addr {<node address> | -alias <node alias>} {-port <port>} -cell <cell id>  {-ipv4 <ipv4 external address> | -ipv6 <ipv6 external address>}\n\n"
                     "node del  -net <net name> -addr <node address> | -alias <node alias>\n\n"
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 1501362a3e9153ccbd704a5cd70863da455f243a..55b797a4dcfc9b1111faf886d161c957e435affe 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -35,6 +35,8 @@
 #include <assert.h>
 #include <ctype.h>
 #include <dirent.h>
+#include <magic.h>
+#include <sys/stat.h>
 
 #ifdef WIN32
 #include <winsock2.h>
@@ -4516,3 +4518,556 @@ int cmd_gdb_import(int argc, char ** argv, char ** a_str_reply)
     json_object_put(l_json);
     return 0;
 }
+
+/*
+ * block code signer
+ */
+/*
+ * enum for dap_chain_sign_file
+ */
+typedef enum {
+    SIGNER_ALL_FLAGS             = 0x1f,
+    SIGNER_FILENAME              = 1 << 0,   // flag - full filename
+    SIGNER_FILENAME_SHORT        = 1 << 1,   // flag - filename without extension
+    SIGNER_FILESIZE              = 1 << 2,   // flag - size of file
+    SIGNER_DATE                  = 1 << 3,   // flag - date
+    SIGNER_MIME_MAGIC            = 1 << 4,   // flag - mime magic
+    SIGNER_COUNT                 = 5         // count flags
+} dap_sign_signer_file_t;
+
+static int s_sign_file(const char *a_filename, dap_sign_signer_file_t a_flags, const char *a_cert_name,
+                       dap_sign_t **a_signed, dap_chain_hash_fast_t *a_hash);
+static int s_signer_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str_reply);
+static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str_reply);
+static uint8_t *s_byte_to_hex(const char *a_line, size_t *a_size);
+static uint8_t s_get_num(uint8_t a_byte, int a_pp);
+struct opts {
+    char *name;
+    uint32_t cmd;
+};
+
+#define BUILD_BUG(condition) ((void)sizeof(char[1-2*!!(condition)]))
+
+int com_signer(int a_argc, char **a_argv, char **a_str_reply)
+{
+    enum {
+        CMD_NONE, CMD_SIGN, CMD_CHECK
+    };
+
+    int arg_index = 1;
+    int cmd_num = CMD_NONE;
+
+    struct opts l_opts[] = {
+    { "sign", CMD_SIGN },
+    { "check", CMD_CHECK }
+    };
+
+    size_t l_len_opts = sizeof(l_opts) / sizeof(struct opts);
+    for (int i = 0; i < l_len_opts; i++) {
+        if (dap_chain_node_cli_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), l_opts[i].name, NULL)) {
+            cmd_num = l_opts[i].cmd;
+            break;
+        }
+    }
+
+    if(cmd_num == CMD_NONE) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "command %s not recognized", a_argv[1]);
+        return -1;
+    }
+    switch (cmd_num) {
+    case CMD_SIGN:
+        return s_signer_cmd(arg_index, a_argc, a_argv, a_str_reply);
+        break;
+    case CMD_CHECK:
+        return s_check_cmd(arg_index, a_argc, a_argv, a_str_reply);
+        break;
+    }
+
+    return -1;
+}
+
+static int s_get_key_from_file(const char *a_file, const char *a_mime, const char *a_cert_name, dap_sign_t **a_sign);
+
+static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str_reply)
+{
+    int l_ret = 0;
+    enum {OPT_FILE, OPT_HASH, OPT_NET, OPT_MIME, OPT_CERT,
+          OPT_COUNT};
+    struct opts l_opts_check[] = {
+    { "-file", OPT_FILE },
+    { "-hash", OPT_HASH },
+    { "-net", OPT_NET },
+    { "-mime", OPT_MIME },
+    { "-cert", OPT_CERT }
+    };
+
+    BUILD_BUG((sizeof(l_opts_check)/sizeof(struct opts)) != OPT_COUNT);
+
+    char *l_str_opts_check[OPT_COUNT] = {0};
+    for (int i = 0; i < OPT_COUNT; i++) {
+        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, l_opts_check[i].name, (const char **) &l_str_opts_check[i]);
+    }
+
+    if (!l_str_opts_check[OPT_CERT]) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s need to be selected", l_opts_check[OPT_CERT].name);
+        return -1;
+    }
+    if (l_str_opts_check[OPT_HASH] && l_str_opts_check[OPT_FILE]) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "you can select is only one from (file or hash)");
+        return -1;
+    }
+
+    dap_chain_net_t *l_network = dap_chain_net_by_name(l_str_opts_check[OPT_NET]);
+    if (!l_network) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s network not found", l_str_opts_check[OPT_NET]);
+        return -1;
+    }
+
+
+    dap_chain_t *l_chain = dap_chain_net_get_chain_by_chain_type(l_network, CHAIN_TYPE_SIGNER);
+    if (!l_chain) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Not found datum signer in network %s", l_str_opts_check[OPT_NET]);
+        return -1;
+    }
+
+    dap_sign_t *l_sign = NULL;
+    dap_chain_datum_t *l_datum = NULL;
+    dap_global_db_obj_t *l_objs = NULL;
+    char *l_gdb_group = NULL;
+
+    l_gdb_group = dap_chain_net_get_gdb_group_mempool(l_chain);
+    if (!l_gdb_group) {
+        l_ret = -1;
+        goto end;
+    }
+
+    printf("....%p\n", l_chain->cells);
+
+    if (l_str_opts_check[OPT_HASH]) {
+#if 0
+        size_t l_size_store_datum = 0;
+        dap_store_obj_t *l_store_datum = dap_chain_global_db_obj_gr_get(l_str_opts_check[OPT_HASH], &l_size_store_datum, l_gdb_group);
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s datum by hash: %s",
+                                          l_size_store_datum ? "found" : "not found",
+                                          l_str_opts_check[OPT_HASH]);
+#endif
+
+    }
+
+    if (l_str_opts_check[OPT_FILE]) {
+        l_ret = s_get_key_from_file(l_str_opts_check[OPT_FILE], l_str_opts_check[OPT_MIME], l_str_opts_check[OPT_CERT], &l_sign);
+        if (!l_ret) {
+            l_ret = -1;
+            goto end;
+        }
+#if 0
+        dap_chain_hash_fast_t l_key_hash;
+        dap_hash_fast(l_sign->pkey_n_sign, l_sign->header.sign_size, &l_key_hash);
+        char *l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
+        if (l_key_str) {
+            size_t l_size_store_datum = 0;
+            dap_store_obj_t *l_store_datum = dap_chain_global_db_obj_gr_get(l_key_str, &l_size_store_datum, l_gdb_group);
+            dap_chain_node_cli_set_reply_text(a_str_reply, "%s datum by file: %s",
+                                              l_size_store_datum ? "found" : "not found",
+                                              l_str_opts_check[OPT_FILE]);
+            DAP_FREE(l_key_str);
+        }
+#endif
+#if 0
+        dap_chain_cell_id_t l_cell_id = {0};
+        dap_chain_atom_iter_t *l_iter = NULL;
+        for (uint64_t i = 0; i >= 0; i++) {
+            l_iter = l_chain->callback_atom_iter_create(l_chain, l_cell_id);
+            if (l_iter) {
+                size_t l_size = 0;
+                dap_chain_datum_t *l_datum = l_chain->callback_atom_iter_get_next(l_iter, &l_size);
+                if (l_datum) {
+                    printf("l_size: %ld\n", l_size);
+                    for (size_t i = 0; i < l_size; i++) {
+
+                        dap_hash_fast_t l_hash;
+                        dap_chain_hash_fast_from_str(l_datum[i].data, &l_hash);
+                        char *l_key = dap_hash_fast_to_str_new(&l_hash);
+                        printf("key: %s\n", l_key);
+                    }
+
+
+                }
+            } else break;
+            l_cell_id.uint64++;
+        }
+#endif
+    }
+
+
+end:
+
+    if (l_gdb_group) DAP_FREE(l_gdb_group);
+
+
+    return 0;
+}
+
+static int s_get_key_from_file(const char *a_file, const char *a_mime, const char *a_cert_name, dap_sign_t **a_sign)
+{
+    char **l_items_mime = NULL;
+    int l_items_mime_count = 0;
+    uint32_t l_flags_mime = 0;
+
+
+
+    if (a_mime) {
+        l_items_mime = dap_parse_items(a_mime, ',', &l_items_mime_count, 0);
+    }
+
+    if (l_items_mime && l_items_mime_count > 0) {
+        struct opts l_opts_flags[] = {
+        { "SIGNER_ALL_FLAGS", SIGNER_ALL_FLAGS },
+        { "SIGNER_FILENAME", SIGNER_FILENAME },
+        { "SIGNER_FILENAME_SHORT", SIGNER_FILENAME_SHORT },
+        { "SIGNER_FILESIZE", SIGNER_FILESIZE },
+        { "SIGNER_DATE", SIGNER_DATE },
+        { "SIGNER_MIME_MAGIC", SIGNER_MIME_MAGIC }
+        };
+        int l_len_opts_flags = sizeof(l_opts_flags) / sizeof (struct opts);
+        for (int i = 0; i < l_len_opts_flags; i++) {
+            for (int isub = 0; isub < l_items_mime_count; isub++) {
+                if (!strncmp (l_opts_flags[i].name, l_items_mime[isub], strlen(l_items_mime[isub]) + 1)) {
+                    l_flags_mime |= l_opts_flags[i].cmd;
+                    break;
+                }
+            }
+
+        }
+
+        /* free l_items_mime */
+        for (int i = 0; i < l_items_mime_count; i++) {
+            if (l_items_mime[i]) DAP_FREE(l_items_mime[i]);
+        }
+        DAP_FREE(l_items_mime);
+        l_items_mime_count = 0;
+    }
+    if (l_flags_mime == 0) l_flags_mime = SIGNER_ALL_FLAGS;
+
+    dap_chain_hash_fast_t l_hash;
+
+
+    int l_ret = s_sign_file(a_file, l_flags_mime, a_cert_name, a_sign, &l_hash);
+
+    return l_ret;
+}
+
+static int s_signer_cmd(int a_arg_index, int a_argc, char **a_argv, char **a_str_reply)
+{
+    enum {
+        OPT_FILE, OPT_MIME, OPT_NET, OPT_CHAIN, OPT_CERT,
+        OPT_COUNT
+    };
+    struct opts l_opts_signer[] = {
+    { "-file", OPT_FILE },
+    { "-mime", OPT_MIME },
+    { "-net", OPT_NET },
+    { "-chain", OPT_CHAIN },
+    { "-cert", OPT_CERT }
+    };
+
+    BUILD_BUG((sizeof(l_opts_signer)/sizeof(struct opts)) != OPT_COUNT);
+
+    a_arg_index++;
+
+    char *l_opts_sign[OPT_COUNT] = {0};
+    for (int i = 0; i < OPT_COUNT; i++) {
+        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, l_opts_signer[i].name, (const char **) &l_opts_sign[i]);
+    }
+
+    if (!l_opts_sign[OPT_CERT]) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s need to be selected", l_opts_signer[OPT_CERT].name);
+        return -1;
+    }
+
+
+    dap_chain_net_t *l_network = dap_chain_net_by_name(l_opts_sign[OPT_NET]);
+    if (!l_network) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s network not found", l_opts_sign[OPT_NET]);
+        return -1;
+    }
+
+    dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(l_network, l_opts_sign[OPT_CHAIN]);
+    if (!l_chain) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s chain not found", l_opts_sign[OPT_CHAIN]);
+        return -1;
+    }
+
+    int l_ret = 0;
+    dap_sign_t *l_sign = NULL;
+    dap_chain_datum_t *l_datum = NULL;
+    dap_global_db_obj_t *l_objs = NULL;
+
+    printf("#\n");
+    l_ret = s_get_key_from_file(l_opts_sign[OPT_FILE], l_opts_sign[OPT_MIME], l_opts_sign[OPT_CERT], &l_sign);
+    if (!l_ret) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "%s cert not found", l_opts_sign[OPT_CERT]);
+        l_ret = -1;
+        goto end;
+    }
+
+
+    printf("##\n");
+
+    l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_SIGNER, l_sign->pkey_n_sign, l_sign->header.sign_size);
+    if (!l_datum) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "not created datum");
+        l_ret = -1;
+        goto end;
+    }
+
+    printf("###\n");
+
+#if 0
+    char *l_hash_str = dap_chain_mempool_datum_add(l_datum, l_chain);
+    dap_chain_node_cli_set_reply_text(a_str_reply, "%s by certificate is signed %s", l_opts_sign[OPT_FILE],
+                                      l_hash_str ? "successfull": "not successfull");
+
+    if (l_hash_str) {
+        l_ret = 0;
+        DAP_FREE(l_hash_str);
+    }
+    printf("####\n");
+#endif
+    dap_chain_cell_id_t l_cell_id = {0};
+    dap_chain_cell_create_fill(l_chain, l_cell_id);
+    l_ret = l_chain->callback_add_datums(l_chain, &l_datum, 1);
+    printf("l_ret datum: %d\n", l_ret);
+
+end:
+
+    if (l_datum) DAP_FREE(l_datum);
+
+    return l_ret;
+}
+
+
+
+/*
+SIGNER_ALL_FLAGS             = 0 << 0,
+SIGNER_FILENAME              = 1 << 0,   // flag - full filename
+SIGNER_FILENAME_SHORT        = 1 << 1,   // flag - filename without extension
+SIGNER_FILESIZE              = 1 << 2,   // flag - size of file
+SIGNER_DATE                  = 1 << 3,   // flag - date
+SIGNER_MIME_MAGIC            = 1 << 4,   // flag - mime magic
+SIGNER_COUNT
+*/
+
+static char *s_strdup_by_index (const char *a_file, const int a_index);
+static dap_tsd_t *s_alloc_metadata (const char *a_file, const int a_meta);
+static uint8_t *s_concat_hash_and_mimetypes (dap_chain_hash_fast_t *a_chain, dap_list_t *a_meta_list, int a_index_meta, size_t *a_fullsize);
+
+/*
+ * dap_sign_file - sign a file with flags.
+ * flags - (SIGNER_FILENAME, SIGNER_FILENAME_SHORT, SIGNER_FILESIZE, SIGNER_DATE, SIGNER_MIME_MAGIC) or SIGNER_ALL_FLAGS
+ * example
+ * int ret = dap_sign_file ("void.png", SIGNER_ALL_FLAGS); it's sign file with all mime types.
+ * example
+ * int ret = dap_sign_file ("void.png", SIGNER_FILENAME | SIGNER_FILESIZE | SIGNER_DATE);
+ */
+/**
+ * @brief dap_chain_sign_file
+ * @param a_chain
+ * @param a_filename
+ * @param a_flags
+ * @return
+ */
+static int s_sign_file(const char *a_filename, dap_sign_signer_file_t a_flags, const char *a_cert_name,
+                       dap_sign_t **a_signed, dap_chain_hash_fast_t *a_hash)
+{
+    uint32_t l_shift = 1;
+    int l_count_meta = 0;
+    int l_index_meta = 0;
+    char *l_buffer = NULL;
+
+    if (a_flags == SIGNER_ALL_FLAGS) {
+        l_count_meta = SIGNER_COUNT;
+        a_flags = SIGNER_FILENAME | SIGNER_FILENAME_SHORT | SIGNER_FILESIZE | SIGNER_DATE | SIGNER_MIME_MAGIC;
+    }
+
+    do {
+        if (a_flags <= 0) break;
+
+        for (int i = 0; i < SIGNER_COUNT; i++) {
+            if (l_shift | a_flags) l_count_meta++;
+            l_shift <<= 1;
+        }
+    } while (0);
+
+    size_t l_file_content_size;
+    if (!dap_file_get_contents(a_filename, &l_buffer, &l_file_content_size)) return 0;
+
+    l_shift = 1;
+    dap_list_t *l_std_list = NULL;
+
+
+    for (int i = 0; i < l_count_meta; i++) {
+        if (l_shift | a_flags) {
+            dap_tsd_t *l_item = s_alloc_metadata(a_filename, l_shift & a_flags);
+            if (l_item) {
+                l_std_list = dap_list_append(l_std_list, l_item);
+                l_index_meta++;
+            }
+        }
+        l_shift <<= 1;
+    }
+
+    int l_ret = 0;
+
+    dap_cert_t *l_cert = dap_cert_find_by_name(a_cert_name);
+    if (!l_cert) {
+        DAP_FREE(l_buffer);
+        return 0;
+    }
+
+    if (!dap_hash_fast(l_buffer, l_file_content_size, a_hash)) {
+        DAP_FREE(l_buffer);
+        return 0;
+    }
+
+    size_t l_full_size_for_sign;
+    uint8_t *l_data = s_concat_hash_and_mimetypes (a_hash, l_std_list, l_index_meta, &l_full_size_for_sign);
+    if (!l_data) {
+        DAP_FREE(l_buffer);
+        return 0;
+    }
+    *a_signed = dap_sign_create(l_cert->enc_key, l_data, l_full_size_for_sign, 0);
+    if (*a_signed == NULL) {
+        DAP_FREE(l_buffer);
+        return 0;
+    }
+
+
+    DAP_FREE(l_buffer);
+    return 1;
+}
+
+static byte_t *s_concat_meta (dap_list_t *a_meta, int a_index_meta, size_t *a_fullsize)
+{
+    if (a_fullsize)
+        *a_fullsize = 0;
+
+    int l_len = 0;
+    int l_n;
+    int l_part = 256;
+    int l_power = 1;
+    byte_t *l_buf = DAP_CALLOC(l_part * l_power++, 1);
+    int l_total = l_part;
+    int l_counter = 0;
+    int l_part_power = l_part;
+    int l_index = 0;
+
+    for ( dap_list_t* l_iter = dap_list_first(a_meta); l_iter; l_iter = l_iter->next){
+        if (!l_iter->data) continue;
+        dap_tsd_t * l_tsd = (dap_tsd_t *) l_iter->data;
+        size_t l_tsd_size = dap_tsd_size(l_tsd);
+        l_index = l_counter;
+        l_counter += l_tsd_size;
+        if (l_counter >= l_part_power) {
+            l_part_power = l_part * l_power++;
+            l_buf = (byte_t *) DAP_REALLOC(l_buf, l_part_power);
+
+        }
+        memcpy (&l_buf[l_index], l_tsd->data, l_tsd_size);
+    }
+
+    if (a_fullsize)
+        *a_fullsize = l_counter;
+
+    return l_buf;
+}
+
+static uint8_t *s_concat_hash_and_mimetypes (dap_chain_hash_fast_t *a_chain_hash, dap_list_t *a_meta_list, int a_index_meta, size_t *a_fullsize)
+{
+    if (!a_fullsize) return NULL;
+    byte_t *l_buf = s_concat_meta (a_meta_list, a_index_meta, a_fullsize);
+    if (!l_buf) return (uint8_t *) l_buf;
+
+    size_t l_len_meta_buf = *a_fullsize;
+    *a_fullsize += sizeof (a_chain_hash->raw) + 1;
+    uint8_t *l_fullbuf = DAP_CALLOC(*a_fullsize, 1);
+    uint8_t *l_s = l_fullbuf;
+
+    memcpy(l_s, a_chain_hash->raw, sizeof(a_chain_hash->raw));
+    l_s += sizeof (a_chain_hash->raw);
+    memcpy(l_s, l_buf, l_len_meta_buf);
+    DAP_FREE(l_buf);
+
+    return l_fullbuf;
+}
+
+
+static char *s_strdup_by_index (const char *a_file, const int a_index)
+{
+    char *l_buf = DAP_CALLOC(a_index + 1, 1);
+    strncpy (l_buf, a_file, a_index);
+    return l_buf;
+}
+
+static dap_tsd_t *s_alloc_metadata (const char *a_file, const int a_meta)
+{
+    switch (a_meta) {
+        case SIGNER_FILENAME:
+            return dap_tsd_create_string(SIGNER_FILENAME, a_file);
+            break;
+        case SIGNER_FILENAME_SHORT:
+            {
+                char *l_filename_short = NULL;
+                if (l_filename_short = strrchr(a_file, '.')) {
+                    int l_index_of_latest_point = l_filename_short - a_file;
+                    l_filename_short = s_strdup_by_index (a_file, l_index_of_latest_point);
+                    if (!l_filename_short) return NULL;
+                    dap_tsd_t *l_ret = dap_tsd_create_string(SIGNER_FILENAME_SHORT, l_filename_short);
+                    free (l_filename_short);
+                    return l_ret;
+                }
+            }
+            break;
+        case SIGNER_FILESIZE:
+            {
+                struct stat l_st;
+                stat (a_file, &l_st);
+                return dap_tsd_create_scalar(SIGNER_FILESIZE, l_st.st_size);
+            }
+            break;
+        case SIGNER_DATE:
+            {
+                struct stat l_st;
+                stat (a_file, &l_st);
+                char *l_ctime = ctime(&l_st.st_ctime);
+                char *l = NULL;
+                if (l = strchr(l_ctime, '\n')) *l = 0;
+                return dap_tsd_create_string(SIGNER_DATE, l_ctime);
+            }
+            break;
+        case SIGNER_MIME_MAGIC:
+            {
+                magic_t l_magic = magic_open(MAGIC_MIME);
+                if (l_magic == NULL) return NULL;
+                if (magic_load (l_magic, NULL)) {
+                    magic_close(l_magic);
+                    return NULL;
+                }
+                const char *l_str_magic_file = NULL;
+                dap_tsd_t *l_ret = NULL;
+                do {
+                        l_str_magic_file = magic_file (l_magic, a_file);
+                    if (!l_str_magic_file) break;
+                    l_ret = dap_tsd_create_string(SIGNER_MIME_MAGIC, l_str_magic_file);
+                } while (0);
+                magic_close (l_magic);
+                return l_ret;
+
+            }
+            break;
+        default:
+            return NULL;
+    }
+
+    return NULL;
+}
diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h
index 0a35ddba34ef04ff885eb20ea877e1980f7d207d..4ac0d989e399f6214028df72a42f0043cdd13e4e 100644
--- a/modules/net/include/dap_chain_node_cli_cmd.h
+++ b/modules/net/include/dap_chain_node_cli_cmd.h
@@ -146,4 +146,4 @@ int com_mempool_proc(int argc, char ** argv, char ** a_str_reply);
 int com_mempool_add_ca( int a_argc,  char ** a_argv, char ** a_str_reply);
 int com_chain_ca_pub( int a_argc,  char ** a_argv, char ** a_str_reply);
 int com_chain_ca_copy( int a_argc,  char ** a_argv, char ** a_str_reply);
-
+int com_signer(int a_argc, char **a_argv, char **a_str_reply);
diff --git a/modules/service/stake/dap_chain_net_srv_stake.c b/modules/service/stake/dap_chain_net_srv_stake.c
index 62f1e2522a39545a5ea08ddf00ad37c73f195e56..89f9534e1988fc9fc4ef7b7df5f772270b76a6c7 100644
--- a/modules/service/stake/dap_chain_net_srv_stake.c
+++ b/modules/service/stake/dap_chain_net_srv_stake.c
@@ -397,7 +397,8 @@ static bool s_stake_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_net_t *a_net)
         return false;
     }
     // Processing will be made according to autoprocess policy
-    if (!dap_chain_mempool_datum_add(l_datum, l_chain)) {
+    char *l_ret = NULL;
+    if ((l_ret = dap_chain_mempool_datum_add(l_datum, l_chain)) == NULL) {
         DAP_DELETE(l_datum);
         return false;
     }
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index e38168e51a839f904d87819a86c4899d8bc28dff..45662257bd4190e85330d488f3b1963fa0b1f055 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -329,7 +329,8 @@ static bool s_xchange_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_net_t *a_net)
         return false;
     }
     // Processing will be made according to autoprocess policy
-    if (!dap_chain_mempool_datum_add(l_datum, l_chain)) {
+    char *l_ret = NULL;
+    if ((l_ret = dap_chain_mempool_datum_add(l_datum, l_chain)) == NULL) {
         DAP_DELETE(l_datum);
         return false;
     }
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index c9b8a95cbe473211080b0d48e85cb415eda38ac2..e46648a74c18018bc198c1beeccfed11059353c6 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -330,6 +330,9 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger
             return DAP_CHAIN_DATUM_CA;
         }
         break;
+	case DAP_CHAIN_DATUM_SIGNER: {
+		return DAP_CHAIN_DATUM_SIGNER;
+    	}
         default:
             return -1;
     }
@@ -443,6 +446,9 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
             if(s_debug_more)
                 log_it(L_DEBUG, "... DATUM_CA");
             break;
+     	case DAP_CHAIN_DATUM_SIGNER:
+	    ret = ATOM_ACCEPT;
+	    break;
         default:
             if (s_debug_more) {
                 l_event_hash_str = dap_chain_hash_fast_to_str_new(&l_event_item->hash);
@@ -574,12 +580,12 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain
                 }
             pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock);
         }
-
         if (l_hashes_linked || s_seed_mode ) {
             dap_chain_cs_dag_event_t * l_event = NULL;
             size_t l_event_size = 0;
-            if(l_dag->callback_cs_event_create)
+            if(l_dag->callback_cs_event_create) {
                 l_event = l_dag->callback_cs_event_create(l_dag,l_datum,l_hashes,l_hashes_linked,&l_event_size);
+	    }
             if ( l_event&&l_event_size){ // Event is created
                 if (l_dag->is_add_directy) {
                     l_cell = a_chain->cells;