diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1992d015edfde19a7c35e539ff46e389f60f56c4..f636bcbb1b833494a7a6f050b56fd67bd9a1c6ac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,8 +18,7 @@ endif()
 if(NOT DEFINED CELLFRAME_MODULES)
     include (dap-sdk/cmake/OS_Detection.cmake)
 
-    set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-esbocs cs-none
-                          srv-app srv-app-db srv-datum srv-stake srv-voting srv-bridge srv-xchange")
+    set(CELLFRAME_MODULES "core chains mining network cs-dag-poa cs-esbocs cs-none srv-stake srv-voting srv-bridge srv-xchange")
 
     if(LINUX OR DARWIN)
         set(CELLFRAME_MODULES "${CELLFRAME_MODULES} srv-vpn")
diff --git a/dap-sdk b/dap-sdk
index bb5982cd7e216b9ed7f55cb80d781ed259265903..f709ca0249c5c2118b0d01fdc6c68a369b0d9b49 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit bb5982cd7e216b9ed7f55cb80d781ed259265903
+Subproject commit f709ca0249c5c2118b0d01fdc6c68a369b0d9b49
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index 5fc8fa11461308a07281a83cffc9b818571b5933..712acc0c474c38d273adf3ce05957e65f213083a 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -257,14 +257,14 @@ static dap_chain_type_t s_chain_type_from_str(const char *a_type_str)
 
 /**
  * @brief s_datum_type_from_str
- * get datum type (DAP_CHAIN_DATUM_TOKEN_DECL, DAP_CHAIN_DATUM_TOKEN_EMISSION, DAP_CHAIN_DATUM_TX) by str value
+ * get datum type (DAP_CHAIN_DATUM_TOKEN, DAP_CHAIN_DATUM_TOKEN_EMISSION, DAP_CHAIN_DATUM_TX) by str value
  * @param a_type_str datum type in string value (token,emission,transaction)
  * @return uint16_t 
  */
 static uint16_t s_datum_type_from_str(const char *a_type_str)
 {
     if(!dap_strcmp(a_type_str, "token")) {
-        return DAP_CHAIN_DATUM_TOKEN_DECL;
+        return DAP_CHAIN_DATUM_TOKEN;
     }
     if(!dap_strcmp(a_type_str, "emission")) {
         return DAP_CHAIN_DATUM_TOKEN_EMISSION;
@@ -295,7 +295,7 @@ static uint16_t s_chain_type_convert(dap_chain_type_t a_type)
 {
     switch (a_type) {
     case CHAIN_TYPE_TOKEN: 
-        return DAP_CHAIN_DATUM_TOKEN_DECL;
+        return DAP_CHAIN_DATUM_TOKEN;
     case CHAIN_TYPE_EMISSION:
         return DAP_CHAIN_DATUM_TOKEN_EMISSION;
     case CHAIN_TYPE_TX:
@@ -607,6 +607,7 @@ int dap_chain_load_all(dap_chain_t *a_chain)
     if (!a_chain)
         return -2;
     if (a_chain->callback_load_from_gdb) {
+        a_chain->is_mapped = false;
         a_chain->callback_load_from_gdb(a_chain);
         return 0;
     }
diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c
index 65ab04d6b278bcaf66ab412c0a8b7561297d46f0..9fcb14a39e937e10c9bf57963764bd6acc8c13c1 100644
--- a/modules/chain/tests/dap_chain_ledger_tests.c
+++ b/modules/chain/tests/dap_chain_ledger_tests.c
@@ -40,14 +40,14 @@ dap_chain_datum_token_t  *dap_ledger_test_create_datum_decl(dap_cert_t *a_cert,
     if (a_tsd_section && a_size_tsd_section != 0) {
         l_token->header_native_decl.tsd_total_size = a_size_tsd_section;
         l_token = DAP_REALLOC(l_token, sizeof(dap_chain_datum_token_t) + a_size_tsd_section);
-        memcpy(l_token->data_n_tsd, a_tsd_section, a_size_tsd_section);
+        memcpy(l_token->tsd_n_signs, a_tsd_section, a_size_tsd_section);
     }
     dap_sign_t * l_sign = dap_cert_sign(a_cert,l_token,
                                         sizeof(*l_token) + a_size_tsd_section, 0);
     if (l_sign) {
         size_t l_sign_size = dap_sign_get_size(l_sign);
         l_token = DAP_REALLOC(l_token, sizeof(dap_chain_datum_token_t) + a_size_tsd_section + l_sign_size);
-        memcpy(l_token->data_n_tsd + a_size_tsd_section, l_sign, l_sign_size);
+        memcpy(l_token->tsd_n_signs + a_size_tsd_section, l_sign, l_sign_size);
         DAP_DELETE(l_sign);
         l_token->signs_total = 1;
         *a_token_size = sizeof(dap_chain_datum_token_t) + l_sign_size + a_size_tsd_section;
@@ -598,7 +598,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_hash_fast_t l_cond_returning_tx_hash = {0};
     dap_hash_fast(l_cond_returning_tx, dap_chain_datum_tx_get_size(l_cond_returning_tx), &l_cond_returning_tx_hash);
     int err_code = dap_ledger_tx_add(a_ledger, l_cond_returning_tx, &l_cond_returning_tx_hash, false);
-    printf("err_code = %s\n", dap_ledger_tx_check_err_str(err_code));
+    printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Returning of funds from cond transaction is");
     uint256_t l_cond_spending_balance_after = dap_ledger_test_print_balance(a_ledger, &l_cond_spending_addr);
     dap_assert(compare256(l_cond_spending_balance_after, dap_chain_uint256_from(2U)), "Returning of funds from conditional tx from ledger testing");
@@ -618,7 +618,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_hash_fast_t l_cond_tx_hash = {};
     dap_hash_fast(l_cond_tx, dap_chain_datum_tx_get_size(l_cond_tx), &l_cond_tx_hash);
     int err_code = dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false);
-    printf("err_code = %s\n", dap_ledger_tx_check_err_str(err_code));
+    printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Adding of stake cond transaction to ledger is");
 
     dap_assert(!dap_ledger_tx_remove(a_ledger, l_cond_tx, &l_cond_tx_hash), "Test of stake conditional transaction removing from ledger:");
@@ -633,7 +633,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_hash_fast_t l_stake_cond_tx_hash = {};
     dap_hash_fast(l_stake_cond_tx, dap_chain_datum_tx_get_size(l_stake_cond_tx), &l_stake_cond_tx_hash);
     int err_code = dap_ledger_tx_add(a_ledger, l_stake_cond_tx, &l_stake_cond_tx_hash, false);
-    printf("err_code = %s\n", dap_ledger_tx_check_err_str(err_code));
+    printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Adding of stake cond transaction to ledger is");
     sleep(3);
     // Create stake unlock tx
@@ -643,15 +643,15 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     
     dap_chain_datum_tx_t *l_unstake_cond_tx = dap_ledger_test_create_unstake_tx_cond(a_from_key, &l_stake_cond_tx_hash, dap_chain_uint256_from(20U), a_ledger);
     dap_hash_fast_t l_unstake_cond_tx_hash = {};
-    dap_hash_fast(l_unstake_cond_tx, dap_chain_datum_tx_get_size(l_stake_cond_tx), &l_unstake_cond_tx_hash);
+    dap_hash_fast(l_unstake_cond_tx, dap_chain_datum_tx_get_size(l_unstake_cond_tx), &l_unstake_cond_tx_hash);
     err_code = dap_ledger_tx_add(a_ledger, l_unstake_cond_tx, &l_unstake_cond_tx_hash, false);
-    printf("err_code = %s\n", dap_ledger_tx_check_err_str(err_code));
+    printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Adding of unstake cond transaction to ledger is");
     uint256_t l_balance_delegated_after_unstaking = dap_ledger_test_print_delegate_balance(a_ledger, &l_addr);
     dap_assert(!compare256(l_balance_delegated_after_unstaking, uint256_0), "Compare delegated token balance after creating unstake transactions:")
     
     err_code = dap_ledger_tx_remove(a_ledger, l_unstake_cond_tx, &l_unstake_cond_tx_hash);
-    printf("err_code = %s\n", dap_ledger_tx_check_err_str(err_code));
+    printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Test of unstake conditional transaction removing from ledger:");
     l_balance_after = dap_ledger_test_print_balance(a_ledger, &l_addr);
     dap_assert(!compare256(l_balance_delegated_after_unstaking, uint256_0), "Compare delegated token balance after removing unstake transaction:")
@@ -714,7 +714,7 @@ void dap_ledger_test_excess_supply(dap_ledger_t *a_ledger, dap_cert_t *a_cert, d
     size_t l_decl_size = 0;
     dap_chain_datum_token_t *l_decl = dap_ledger_test_create_datum_decl(a_cert, &l_decl_size, l_token_ticker,
                                                                               dap_chain_uint256_from(s_total_supply), NULL, 0, DAP_CHAIN_DATUM_TOKEN_FLAG_NONE);
-    dap_assert_PIF(!dap_ledger_token_add(a_ledger, l_decl, l_decl_size), "Adding token declaration to ledger.");
+    dap_assert_PIF(!dap_ledger_token_add(a_ledger, (byte_t *)l_decl, l_decl_size), "Adding token declaration to ledger.");
     dap_chain_datum_token_emission_t *l_femi = dap_chain_datum_emission_create(l_value_first_emi, l_token_ticker, a_addr);
     l_femi = dap_chain_datum_emission_add_sign(a_cert->enc_key, l_femi);
     dap_chain_hash_fast_t l_femi_hash = {0};
@@ -751,7 +751,7 @@ addr_key_container_t *gen_addr(dap_chain_net_id_t a_iddn){
     dap_chain_addr_fill_from_key(l_addr, l_new_key, a_iddn);
     l_container->enc_key = l_new_key;
     l_container->addr = l_addr;
-    l_container->str = dap_chain_addr_to_str(l_container->addr);
+    l_container->str = dap_strdup(dap_chain_addr_to_str(l_container->addr));
     return l_container;
 }
 
@@ -807,7 +807,7 @@ void dap_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a_cert,
                                                                                   //DAP_CHAIN_DATUM_TOKEN_FLAG_NONE);
                                                                                   l_flags_decl);
 
-        dap_assert_PIF(!dap_ledger_token_add(a_ledger, l_decl, l_decl_size),
+        dap_assert_PIF(!dap_ledger_token_add(a_ledger, (byte_t *)l_decl, l_decl_size),
                 "Can't added datum in ledger");
         //Check emission in not a white list
         dap_chain_datum_token_emission_t *l_emi = dap_chain_datum_emission_create(
@@ -873,16 +873,16 @@ void dap_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a_cert,
 //        l_datum_token_update->header_native_update.tsd_total_size = l_offset;
 //        l_datum_token_update->signs_total = 1;
 //        l_offset = 0;
-//        memcpy(l_datum_token_update->data_n_tsd, l_tsd_update_total_size, dap_tsd_size(l_tsd_update_total_size));
+//        memcpy(l_datum_token_update->tsd_n_signs, l_tsd_update_total_size, dap_tsd_size(l_tsd_update_total_size));
 //        l_offset += dap_tsd_size(l_tsd_update_total_size);
-//        memcpy(l_datum_token_update->data_n_tsd + l_offset, l_tsd_dis_flags, dap_tsd_size(l_tsd_dis_flags));
+//        memcpy(l_datum_token_update->tsd_n_signs + l_offset, l_tsd_dis_flags, dap_tsd_size(l_tsd_dis_flags));
 //        l_offset += dap_tsd_size(l_tsd_dis_flags);
 //        dap_sign_t * l_sign = dap_cert_sign(a_cert, l_datum_token_update,
 //                                           sizeof(*l_datum_token_update) - sizeof(uint16_t), 0);
 //        if (l_sign) {
 //            size_t l_sign_size = dap_sign_get_size(l_sign);
 //            l_datum_token_update = DAP_REALLOC(l_datum_token_update, sizeof(dap_chain_datum_token_t) + l_offset + l_sign_size);
-//            memcpy(l_datum_token_update->data_n_tsd + l_offset, l_sign, l_sign_size);
+//            memcpy(l_datum_token_update->tsd_n_signs + l_offset, l_sign, l_sign_size);
 //            DAP_DELETE(l_sign);
 //            size_t l_token_update_size = sizeof(dap_chain_datum_token_t) + l_sign_size + l_offset;
 //            dap_assert(!dap_ledger_token_add(a_ledger, l_datum_token_update, l_token_update_size),
@@ -921,7 +921,7 @@ void dap_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a_cert,
                 //DAP_CHAIN_DATUM_TOKEN_FLAG_NONE);
                                                                                   l_flags_decl);
 
-        dap_assert_PIF(!dap_ledger_token_add(a_ledger, l_decl, l_decl_size),
+        dap_assert_PIF(!dap_ledger_token_add(a_ledger, (byte_t *)l_decl, l_decl_size),
                        "Can't added datum in ledger");
         //Check emission at addr in block list
         dap_chain_datum_token_emission_t *l_emi_block = dap_chain_datum_emission_create(
@@ -1006,9 +1006,9 @@ void dap_ledger_test_run(void){
                                                                                     dap_chain_uint256_from(s_total_supply), NULL, 0, DAP_CHAIN_DATUM_TOKEN_FLAG_NONE);
     dap_assert_PIF(l_token_decl || l_token_decl_size == 0, "Generate token declaration.");
     int l_check_added_decl_token = 0;
-    l_check_added_decl_token = dap_ledger_token_decl_add_check(l_ledger, l_token_decl, l_token_decl_size);
+    l_check_added_decl_token = dap_ledger_token_add_check(l_ledger, (byte_t *)l_token_decl, l_token_decl_size);
     dap_assert_PIF(l_check_added_decl_token == 0, "Checking whether it is possible to add a token declaration to ledger.");
-    dap_assert_PIF(!dap_ledger_token_add(l_ledger, l_token_decl, l_token_decl_size), "Adding token declaration to ledger.");
+    dap_assert_PIF(!dap_ledger_token_add(l_ledger, (byte_t *)l_token_decl, l_token_decl_size), "Adding token declaration to ledger.");
 	
     // Create emission
     dap_chain_addr_t l_addr = {0};
@@ -1031,9 +1031,9 @@ void dap_ledger_test_run(void){
                                                      uint256_0, (byte_t*)l_tsd, dap_tsd_size(l_tsd), DAP_CHAIN_DATUM_TOKEN_FLAG_NONE);
     dap_assert_PIF(l_token_decl || l_token_decl_size == 0, "Generate delegated token declaration.");
     l_check_added_decl_token = 0;
-    l_check_added_decl_token = dap_ledger_token_decl_add_check(l_ledger, l_token_decl, l_token_decl_size);
+    l_check_added_decl_token = dap_ledger_token_add_check(l_ledger, (byte_t *)l_token_decl, l_token_decl_size);
     dap_assert_PIF(l_check_added_decl_token == 0, "Checking whether it is possible to add a token declaration to ledger.");
-    dap_assert_PIF(!dap_ledger_token_add(l_ledger, l_token_decl, l_token_decl_size), "Adding token declaration to ledger.");
+    dap_assert_PIF(!dap_ledger_token_add(l_ledger, (byte_t *)l_token_decl, l_token_decl_size), "Adding token declaration to ledger.");
 
     //first base tx
     dap_chain_datum_tx_t *l_base_tx = dap_ledger_test_create_datum_base_tx(l_emi_sign, &l_emi_hash, l_addr, l_cert);
diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c
index f70b98db1c44f4d8e48f4e285803295974fdf862..81773569cb7b68d306c0dd4c2241c6b942a40893 100644
--- a/modules/common/dap_chain_datum.c
+++ b/modules/common/dap_chain_datum.c
@@ -60,165 +60,6 @@ dap_chain_datum_t *dap_chain_datum_create(uint16_t a_type_id, const void *a_data
    memcpy(l_datum->data, a_data, (uint32_t)a_data_size);
    return  l_datum;
 }
-
-void dap_chain_datum_token_dump_tsd(dap_string_t *a_str_out, dap_chain_datum_token_t *a_token, size_t a_token_size, const char *a_hash_out_type)
-{
-    dap_tsd_t *l_tsd = dap_chain_datum_token_tsd_get(a_token, a_token_size);
-    if (l_tsd == NULL) {
-        dap_string_append_printf(a_str_out,"<CORRUPTED TSD SECTION>\n");
-        return;
-    }
-    size_t l_tsd_total_size = 0;
-    switch (a_token->type) {
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL:
-            switch (a_token->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-                    l_tsd_total_size = a_token->header_private_decl.tsd_total_size; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-                    l_tsd_total_size = a_token->header_native_decl.tsd_total_size; break;
-                default: break;
-            } break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE:
-            switch (a_token->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-                    l_tsd_total_size = a_token->header_private_update.tsd_total_size; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-                    l_tsd_total_size = a_token->header_native_update.tsd_total_size; break;
-                default: break;
-            } break;
-        default: break;
-    }
-    size_t l_tsd_size = 0;
-    for (size_t l_offset = 0; l_offset < l_tsd_total_size; l_offset += l_tsd_size) {
-        l_tsd = (dap_tsd_t *) (((byte_t*)l_tsd) + l_tsd_size);
-        l_tsd_size = l_tsd ? dap_tsd_size(l_tsd) : 0;
-        if (l_tsd_size == 0) {
-            log_it(L_ERROR,"Wrong zero TSD size, exiting dap_chain_datum_token_dump_tsd()");
-            return;
-        } else if (l_tsd_size+l_offset > l_tsd_total_size) {
-            log_it(L_WARNING, "<CORRUPTED TSD> too big size %u when left maximum %zu",
-                   l_tsd->size, l_tsd_total_size - l_offset);
-            return;
-        }
-        switch(l_tsd->type) {
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS: {
-            dap_string_append_printf(a_str_out,"flags_set: ");
-            uint16_t l_t = 0;
-            dap_chain_datum_token_flags_dump(a_str_out, _dap_tsd_get_scalar(l_tsd, &l_t));
-            continue;
-        }
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS: {
-            dap_string_append_printf(a_str_out,"flags_unset: ");
-            uint16_t l_t = 0;
-            dap_chain_datum_token_flags_dump(a_str_out, _dap_tsd_get_scalar(l_tsd, &l_t));
-            continue;
-        }
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY: {     // 256
-            uint256_t l_t = uint256_0;
-            dap_string_append_printf( a_str_out, "total_supply: %s\n",
-                                     dap_uint256_to_char(_dap_tsd_get_scalar(l_tsd, &l_t), NULL) );
-            continue;
-        }
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY_OLD: { // 128
-            uint128_t l_t = uint128_0;
-            dap_string_append_printf( a_str_out, "total_supply: %s\n",
-                                     dap_uint256_to_char(GET_256_FROM_128(_dap_tsd_get_scalar(l_tsd, &l_t)), NULL) );
-            continue;
-        }
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID: {
-            uint16_t l_t = 0;
-            dap_string_append_printf(a_str_out,"total_signs_valid: %u\n", _dap_tsd_get_scalar(l_tsd, &l_t));
-            continue;
-        }
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD:
-            if(l_tsd->size >= sizeof(dap_pkey_t)) {
-                const char *l_hash_str;
-                dap_pkey_t *l_pkey = (dap_pkey_t*)l_tsd->data;
-                dap_hash_fast_t l_hf = { };
-                if (!dap_pkey_get_hash(l_pkey, &l_hf)) {
-                    dap_string_append_printf(a_str_out,"total_pkeys_add: <WRONG CALCULATION FINGERPRINT>\n");
-                } else {
-                    if (!dap_strcmp(a_hash_out_type, "hex") || !dap_strcmp(a_hash_out_type, "content_hash"))
-                        l_hash_str = dap_chain_hash_fast_to_str_static(&l_hf);
-                    else
-                        l_hash_str = dap_enc_base58_encode_hash_to_str_static(&l_hf);
-                    dap_string_append_printf(a_str_out, "total_pkeys_add: %s\n", l_hash_str);
-                }
-            } else
-                    dap_string_append_printf(a_str_out,"total_pkeys_add: <WRONG SIZE %u>\n", l_tsd->size);
-            continue;
-
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE:
-                if(l_tsd->size == sizeof(dap_chain_hash_fast_t) ){
-                    const char *l_hash_str = (!dap_strcmp(a_hash_out_type,"hex")|| !dap_strcmp(a_hash_out_type, "content_hash"))
-                            ? dap_chain_hash_fast_to_str_static((dap_chain_hash_fast_t*) l_tsd->data)
-                            : dap_enc_base58_encode_hash_to_str_static((dap_chain_hash_fast_t*) l_tsd->data);
-                    dap_string_append_printf(a_str_out,"total_pkeys_remove: %s\n", l_hash_str);
-                } else
-                    dap_string_append_printf(a_str_out,"total_pkeys_remove: <WRONG SIZE %u>\n", l_tsd->size);
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK: {
-                dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
-                const char *l_balance, *l_tmp = dap_uint256_to_char(l_tsd_section->emission_rate, &l_balance);
-                dap_string_append_printf(a_str_out, "ticker_token_from: %s\nemission_rate: %s\n",
-                                         l_tsd_section->ticker_token_from, l_balance);
-            }continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD  :
-                dap_string_append_printf(a_str_out,"datum_type_allowed_add: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE  :
-                dap_string_append_printf(a_str_out,"datum_type_allowed_remove: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD  :
-                dap_string_append_printf(a_str_out,"datum_type_blocked_add: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE:
-                dap_string_append_printf(a_str_out,"datum_type_blocked_remove: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD:
-                dap_string_append_printf(a_str_out,"tx_sender_allowed_add: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE:
-                dap_string_append_printf(a_str_out,"tx_sender_allowed_remove: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD:
-                dap_string_append_printf(a_str_out,"tx_sender_blocked_add: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE:
-                dap_string_append_printf(a_str_out,"tx_sender_blocked_remove: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD:
-                dap_string_append_printf(a_str_out,"tx_receiver_allowed_add: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE:
-                dap_string_append_printf(a_str_out,"tx_receiver_allowed: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD:
-                dap_string_append_printf(a_str_out, "tx_receiver_blocked_add: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE:
-                dap_string_append_printf(a_str_out, "tx_receiver_blocked_remove: %s\n",
-                                         dap_tsd_get_string_const(l_tsd) );
-            continue;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION:
-                dap_string_append_printf(a_str_out, "description: '%s'\n", l_tsd->data);
-                continue;
-            default: dap_string_append_printf(a_str_out, "<0x%04hX>: <size %u>\n", l_tsd->type, l_tsd->size);
-        }
-    }
-}
-
 void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datum_token_t *a_token, size_t a_token_size, const char *a_hash_out_type)
 {
     dap_tsd_t *l_tsd = dap_chain_datum_token_tsd_get(a_token, a_token_size);
@@ -278,13 +119,6 @@ void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datu
             DAP_DELETE(l_balance);
             continue;
         }
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY_OLD: { // 128
-            uint128_t l_t = uint128_0;
-            char *l_balance = dap_chain_balance_print(GET_256_FROM_128(_dap_tsd_get_scalar(l_tsd, &l_t)));
-            json_object_object_add(json_obj_out, "total_supply", json_object_new_string(l_balance));
-            DAP_DELETE(l_balance);
-            continue;
-        }
         case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID: {
             uint16_t l_t = 0;
             json_object_object_add(json_obj_out, "total_signs_valid", json_object_new_int(_dap_tsd_get_scalar(l_tsd, &l_t)));
@@ -1009,201 +843,7 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum,
  * @brief dap_chain_net_dump_datum
  * process datum verification process. Can be:
  * if DAP_CHAIN_DATUM_TX, called dap_ledger_tx_add_check
- * if DAP_CHAIN_DATUM_TOKEN_DECL, called dap_ledger_token_decl_add_check
- * if DAP_CHAIN_DATUM_TOKEN_EMISSION, called dap_ledger_token_emission_add_check
- * @param a_str_out
- * @param a_datum
- */
-void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, const char *a_hash_out_type, dap_chain_net_id_t a_net_id)
-{
-    if( a_datum == NULL){
-        dap_string_append_printf(a_str_out,"==Datum is NULL\n");
-        return;
-    }
-    dap_hash_fast_t l_datum_hash;
-    dap_hash_fast(a_datum->data, a_datum->header.data_size, &l_datum_hash);
-    const char *l_hash_str = dap_strcmp(a_hash_out_type, "hex")
-            ? dap_enc_base58_encode_hash_to_str_static(&l_datum_hash)
-            : dap_chain_hash_fast_to_str_static(&l_datum_hash);
-    switch (a_datum->header.type_id) {
-        case DAP_CHAIN_DATUM_TOKEN_DECL: {
-            size_t l_token_size = a_datum->header.data_size;
-            dap_chain_datum_token_t * l_token = dap_chain_datum_token_read(a_datum->data, &l_token_size);
-            if(l_token_size < sizeof(dap_chain_datum_token_t)){
-                dap_string_append_printf(a_str_out,"==Datum has incorrect size. Only %zu, while at least %zu is expected\n",
-                                         l_token_size, sizeof(dap_chain_datum_token_t));
-                DAP_DEL_Z(l_token);
-                return;
-            }
-            dap_string_append_printf(a_str_out,"=== Datum Token Declaration ===\n");
-            dap_string_append_printf(a_str_out, "hash: %s\n", l_hash_str);
-            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);
-            dap_string_append_printf(a_str_out, "version: %d\n", l_token->version);
-            switch (l_token->type) {
-                case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL: {
-                    dap_string_append(a_str_out,"type: DECL\n");
-                    switch (l_token->subtype) {
-                        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:{
-                            dap_string_append(a_str_out,"subtype: PRIVATE\n");
-                            dap_string_append_printf(a_str_out, "decimals: %d\n", l_token->header_private_decl.decimals);
-                            dap_string_append_printf(a_str_out, "auth signs (valid/total) %u/%u\n", l_token->signs_valid, l_token->signs_total);
-                            dap_string_append_printf(a_str_out, "total_supply: %s\n", dap_uint256_to_char(l_token->total_supply, NULL));
-                            dap_string_append(a_str_out,"flags: ");
-                            dap_chain_datum_token_flags_dump(a_str_out, l_token->header_private_update.flags);
-                            dap_chain_datum_token_dump_tsd(a_str_out, l_token, l_token_size, a_hash_out_type);
-                            size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_update.tsd_total_size;
-                            dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_private_update.tsd_total_size,
-                                                             l_certs_field_size, a_hash_out_type);
-                        } break;
-                        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
-                            dap_string_append(a_str_out, "subtype: CF20\n");
-                            dap_string_append_printf(a_str_out, "decimals: %d\n", l_token->header_native_decl.decimals);
-                            dap_string_append_printf(a_str_out, "auth signs (valid/total) %u/%u\n", l_token->signs_valid, l_token->signs_total);
-                            dap_string_append_printf(a_str_out, "total_supply: %s\n", dap_uint256_to_char(l_token->total_supply, NULL));
-                            dap_string_append(a_str_out, "flags: ");
-                            dap_chain_datum_token_flags_dump(a_str_out, l_token->header_native_decl.flags);
-                            dap_chain_datum_token_dump_tsd(a_str_out, l_token, l_token_size, a_hash_out_type);
-                            size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_native_decl.tsd_total_size;
-                            dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_native_decl.tsd_total_size,
-                                                             l_certs_field_size, a_hash_out_type);
-                        } break;
-                        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC: {
-                            dap_chain_addr_t l_premine_addr = l_token->header_public.premine_address;
-                            dap_string_append(a_str_out, "subtype: PUBLIC\n");
-                            dap_string_append_printf(a_str_out, "premine_supply: %s", dap_uint256_to_char(l_token->header_public.premine_supply, NULL));
-                            dap_string_append_printf(a_str_out, "premine_address: %s", dap_chain_addr_to_str(&l_premine_addr));
-                            dap_string_append(a_str_out, "flags: ");
-                            dap_chain_datum_token_flags_dump(a_str_out, l_token->header_public.flags);
-                        } break;
-                    }
-                } break;
-                case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE: {
-                    dap_string_append(a_str_out,"type: UPDATE\n");
-                    switch (l_token->subtype) {
-                        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE: {
-                            dap_string_append(a_str_out,"subtype: PRIVATE\n");
-                            dap_string_append_printf(a_str_out, "decimals: %d\n", l_token->header_private_decl.decimals);
-                            dap_string_append_printf(a_str_out, "auth signs (valid/total) %u/%u\n", l_token->signs_valid, l_token->signs_total);
-                            dap_string_append_printf(a_str_out, "total_supply: %s\n", dap_uint256_to_char(l_token->total_supply, NULL));
-                            dap_string_append(a_str_out,"flags: ");
-                            dap_chain_datum_token_flags_dump(a_str_out, l_token->header_private_update.flags);
-                            dap_chain_datum_token_dump_tsd(a_str_out, l_token, l_token_size, a_hash_out_type);
-                            size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_update.tsd_total_size;
-                            dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_private_update.tsd_total_size,
-                                                             l_certs_field_size, a_hash_out_type);
-                        } break;
-                        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
-                            dap_string_append_printf(a_str_out,"subtype: CF20\n");
-                            dap_string_append_printf(a_str_out, "decimals: %d\n", l_token->header_native_update.decimals);
-                            dap_string_append_printf(a_str_out, "auth signs (valid/total) %u/%u\n", l_token->signs_valid, l_token->signs_total);
-                            dap_string_append_printf(a_str_out, "total_supply: %s\n", dap_uint256_to_char(l_token->total_supply, NULL));
-                            dap_string_append(a_str_out, "flags: ");
-                            dap_chain_datum_token_flags_dump(a_str_out, l_token->header_native_update.flags);
-                            dap_chain_datum_token_dump_tsd(a_str_out, l_token, l_token_size, a_hash_out_type);
-                            size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_native_update.tsd_total_size;
-                            dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_native_update.tsd_total_size,
-                                                             l_certs_field_size, a_hash_out_type);
-                        } break;
-                    }
-                } break;
-                default:
-                    dap_string_append(a_str_out,"type: UNKNOWN\n");
-                    break;
-            }
-            if (l_token->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE ) {
-                dap_string_append(a_str_out, "subtype: SIMPLE\n");
-                dap_string_append_printf(a_str_out, "decimals: %d\n", l_token->header_simple.decimals);
-                dap_string_append_printf(a_str_out, "sign_total: %hu\n", l_token->signs_total );
-                dap_string_append_printf(a_str_out, "sign_valid: %hu\n", l_token->signs_valid );
-                dap_string_append_printf(a_str_out, "total_supply: %s\n", dap_uint256_to_char(l_token->total_supply, NULL));
-                size_t l_certs_field_size = l_token_size - sizeof(*l_token);
-                dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd,
-                                                 l_certs_field_size, a_hash_out_type);
-            }
-            DAP_DELETE(l_token);
-        } break;
-        case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
-            size_t l_emission_size = a_datum->header.data_size;
-            dap_chain_datum_token_emission_t *l_emission = dap_chain_datum_emission_read(a_datum->data, &l_emission_size);
-            const char *l_coins_str, *l_value_str = dap_uint256_to_char(l_emission->hdr.value, &l_coins_str);
-            dap_string_append_printf(a_str_out, "emission: hash %s\n\t%s(%s) %s, type: %s, version: %d\n",
-                                    l_hash_str,
-                                    l_coins_str,
-                                    l_value_str,
-                                    l_emission->hdr.ticker,
-                                    c_dap_chain_datum_token_emission_type_str[l_emission->hdr.type],
-                                    l_emission->hdr.version);
-            dap_string_append_printf(a_str_out, "  to addr: %s\n", dap_chain_addr_to_str(&(l_emission->hdr.address)));
-            switch (l_emission->hdr.type) {
-            case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH:
-                dap_string_append_printf(a_str_out, "  signs_count: %d\n", l_emission->data.type_auth.signs_count);
-                dap_string_append_printf(a_str_out, "  tsd_total_size: %"DAP_UINT64_FORMAT_U"\n",
-                                         l_emission->data.type_auth.tsd_total_size);
-
-                if (  ( (void *) l_emission->tsd_n_signs + l_emission->data.type_auth.tsd_total_size) >
-                      ((void *) l_emission + l_emission_size) )
-                {
-                    log_it(L_ERROR, "Illformed DATUM type %d, TSD section is out-of-buffer (%" DAP_UINT64_FORMAT_U " vs %zu)",
-                        l_emission->hdr.type, l_emission->data.type_auth.tsd_total_size, l_emission_size);
-                    dap_string_append_printf(a_str_out, "  Skip incorrect or illformed DATUM");
-                    break;
-                }
-                dap_chain_datum_token_certs_dump(a_str_out, l_emission->tsd_n_signs + l_emission->data.type_auth.tsd_total_size,
-                                                l_emission->data.type_auth.size - l_emission->data.type_auth.tsd_total_size, a_hash_out_type);
-                break;
-            case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ALGO:
-                dap_string_append_printf(a_str_out, "  codename: %s\n", l_emission->data.type_algo.codename);
-                break;
-            case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT: {
-                char l_time_str[32];
-                // get time of create datum
-                if(dap_time_to_str_rfc822(l_time_str, sizeof(l_time_str), l_emission->data.type_presale.lock_time) < 1)
-                        l_time_str[0] = '\0';
-                dap_string_append_printf(a_str_out, "  flags: 0x%x, lock_time: %s\n", l_emission->data.type_presale.flags, l_time_str);
-                dap_string_append_printf(a_str_out, "  addr: %s\n", dap_chain_addr_to_str(&l_emission->data.type_presale.addr));
-            }
-            case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER:
-            case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_UNDEFINED:
-            default:
-                break;
-            }
-            DAP_DELETE(l_emission);
-        } break;
-        case DAP_CHAIN_DATUM_TX: {
-            dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)a_datum->data;
-            dap_chain_datum_dump_tx(l_tx, NULL, a_str_out, a_hash_out_type, &l_datum_hash, a_net_id);
-        } break;
-        case DAP_CHAIN_DATUM_DECREE:{
-            dap_chain_datum_decree_t *l_decree = (dap_chain_datum_decree_t *)a_datum->data;
-            size_t l_decree_size = dap_chain_datum_decree_get_size(l_decree);
-            dap_string_append_printf(a_str_out,"=== Datum decree ===\n");
-            dap_string_append_printf(a_str_out, "hash: %s\n", l_hash_str);
-            dap_string_append_printf(a_str_out, "size: %zd\n", l_decree_size);
-            dap_chain_datum_decree_dump(a_str_out, l_decree, l_decree_size, a_hash_out_type);
-        } break;
-        case DAP_CHAIN_DATUM_ANCHOR:{
-            dap_chain_datum_anchor_t *l_anchor = (dap_chain_datum_anchor_t *)a_datum->data;
-            size_t l_anchor_size = sizeof(dap_chain_datum_anchor_t) + l_anchor->header.data_size + l_anchor->header.signs_size;
-            dap_string_append_printf(a_str_out,"=== Datum anchor ===\n");
-            dap_string_append_printf(a_str_out, "hash: %s\n", l_hash_str);
-            dap_string_append_printf(a_str_out, "size: %zd\n", l_anchor_size);
-            dap_hash_fast_t l_decree_hash = { };
-            dap_chain_datum_anchor_get_hash_from_data(l_anchor, &l_decree_hash);
-            l_hash_str = dap_chain_hash_fast_to_str_static(&l_decree_hash);
-            dap_string_append_printf(a_str_out, "decree hash: %s\n", l_hash_str);
-            dap_chain_datum_anchor_certs_dump(a_str_out, l_anchor->data_n_sign + l_anchor->header.data_size, l_anchor->header.signs_size, a_hash_out_type);
-        } break;
-    }    
-}
-
-
-
-/**
- * @brief dap_chain_net_dump_datum
- * process datum verification process. Can be:
- * if DAP_CHAIN_DATUM_TX, called dap_ledger_tx_add_check
- * if DAP_CHAIN_DATUM_TOKEN_DECL, called dap_ledger_token_decl_add_check
+ * if DAP_CHAIN_DATUM_TOKEN, called dap_ledger_token_add_check
  * if DAP_CHAIN_DATUM_TOKEN_EMISSION, called dap_ledger_token_emission_add_check
  * @param a_obj_out
  * @param a_datum
@@ -1216,12 +856,12 @@ void dap_chain_datum_dump_json(json_object  *a_obj_out, dap_chain_datum_t *a_dat
     }
     json_object * json_obj_datum = json_object_new_object();
     dap_hash_fast_t l_datum_hash;
-    dap_hash_fast(a_datum->data, a_datum->header.data_size, &l_datum_hash);
+    dap_chain_datum_calc_hash(a_datum, &l_datum_hash);
     const char *l_hash_str = dap_strcmp(a_hash_out_type, "hex")
             ? dap_enc_base58_encode_hash_to_str_static(&l_datum_hash)
             : dap_chain_hash_fast_to_str_static(&l_datum_hash);
     switch (a_datum->header.type_id) {
-        case DAP_CHAIN_DATUM_TOKEN_DECL: {
+        case DAP_CHAIN_DATUM_TOKEN: {
             size_t l_token_size = a_datum->header.data_size;
             dap_chain_datum_token_t * l_token = dap_chain_datum_token_read(a_datum->data, &l_token_size);
             if(l_token_size < sizeof(dap_chain_datum_token_t)){
@@ -1251,7 +891,7 @@ void dap_chain_datum_dump_json(json_object  *a_obj_out, dap_chain_datum_t *a_dat
                             dap_chain_datum_token_flags_dump_to_json(json_obj_datum,l_token->header_private_update.flags);
                             dap_datum_token_dump_tsd_to_json(json_obj_datum,l_token, l_token_size, a_hash_out_type);               
                             size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_update.tsd_total_size;
-                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum,l_token->data_n_tsd + l_token->header_private_update.tsd_total_size,
+                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum,l_token->tsd_n_signs + l_token->header_private_update.tsd_total_size,
                                                              l_certs_field_size, a_hash_out_type);                            
                         } break;
                         case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
@@ -1265,7 +905,7 @@ void dap_chain_datum_dump_json(json_object  *a_obj_out, dap_chain_datum_t *a_dat
                             dap_chain_datum_token_flags_dump_to_json(json_obj_datum, l_token->header_native_decl.flags);
                             dap_datum_token_dump_tsd_to_json(json_obj_datum, l_token, l_token_size, a_hash_out_type);
                             size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_native_decl.tsd_total_size;
-                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->data_n_tsd + l_token->header_native_decl.tsd_total_size,
+                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->tsd_n_signs + l_token->header_native_decl.tsd_total_size,
                                                              l_certs_field_size, a_hash_out_type);
                         } break;
                         case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC: {
@@ -1293,7 +933,7 @@ void dap_chain_datum_dump_json(json_object  *a_obj_out, dap_chain_datum_t *a_dat
                             dap_chain_datum_token_flags_dump_to_json(json_obj_datum, l_token->header_private_update.flags);
                             dap_datum_token_dump_tsd_to_json(json_obj_datum, l_token, l_token_size, a_hash_out_type);
                             size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_update.tsd_total_size;
-                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->data_n_tsd + l_token->header_private_update.tsd_total_size,
+                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->tsd_n_signs + l_token->header_private_update.tsd_total_size,
                                                              l_certs_field_size, a_hash_out_type);
                         } break;
                         case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
@@ -1307,7 +947,7 @@ void dap_chain_datum_dump_json(json_object  *a_obj_out, dap_chain_datum_t *a_dat
                             dap_chain_datum_token_flags_dump_to_json(json_obj_datum, l_token->header_native_update.flags);
                             dap_datum_token_dump_tsd_to_json(json_obj_datum, l_token, l_token_size, a_hash_out_type);
                             size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_native_update.tsd_total_size;
-                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->data_n_tsd + l_token->header_native_update.tsd_total_size,
+                            dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->tsd_n_signs + l_token->header_native_update.tsd_total_size,
                                                              l_certs_field_size, a_hash_out_type);
                         } break;
                     }
@@ -1324,7 +964,7 @@ void dap_chain_datum_dump_json(json_object  *a_obj_out, dap_chain_datum_t *a_dat
                 json_object_object_add(json_obj_datum,"total_supply",json_object_new_string(dap_uint256_to_char(l_token->total_supply, NULL)));
                 
                 size_t l_certs_field_size = l_token_size - sizeof(*l_token);
-                dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->data_n_tsd,
+                dap_chain_datum_token_certs_dump_to_json(json_obj_datum, l_token->tsd_n_signs,
                                                  l_certs_field_size, a_hash_out_type);
             }
             DAP_DELETE(l_token);
diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c
index 33e053fda53f3fa834be3a22dfd88296f704ffdd..6d7b79800318759dff58658571c16dada8d70173 100644
--- a/modules/common/dap_chain_datum_token.c
+++ b/modules/common/dap_chain_datum_token.c
@@ -70,152 +70,109 @@ dap_tsd_t* dap_chain_datum_token_tsd_get(dap_chain_datum_token_t *a_token, size_
         log_it(L_WARNING, "Token size %lu < %lu header size, corrupted token datum", a_token_size, sizeof(dap_chain_datum_token_t));
         return NULL;
     }
-    return (dap_tsd_t*)a_token->data_n_tsd;
+    return (dap_tsd_t*)a_token->tsd_n_signs;
 }
 
 dap_chain_datum_token_t *dap_chain_datum_token_read(const byte_t *a_token_serial, size_t *a_token_size)
 {
-    dap_chain_datum_token_old_t *l_token_old = (dap_chain_datum_token_old_t*)a_token_serial;
-    size_t l_token_data_n_tsd_size = *a_token_size - sizeof(dap_chain_datum_token_old_t);
-    size_t l_token_size = l_token_data_n_tsd_size + sizeof(dap_chain_datum_token_t);
-    switch (((dap_chain_datum_token_t*)a_token_serial)->type) {
+    dap_return_val_if_fail(a_token_serial && a_token_size, NULL);
+    if (*a_token_size < sizeof(dap_chain_datum_token_old_t)) {
+        log_it(L_WARNING, "Too small token size %zu", *a_token_size);
+        return NULL;
+    }
+    dap_chain_datum_token_old_t *l_token_old = (dap_chain_datum_token_old_t *)a_token_serial;
+    size_t l_token_tsd_n_signs_size = *a_token_size - sizeof(dap_chain_datum_token_old_t);
+    size_t l_token_size = dap_chain_datum_token_is_old(l_token_old->type) ? l_token_tsd_n_signs_size + sizeof(dap_chain_datum_token_t)
+                                                                         : *a_token_size;
+    dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
+    if (!l_token) {
+        log_it(L_CRITICAL, c_error_memory_alloc);
+        return NULL;
+    }
+    switch (l_token_old->type) {
+
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE: {
-        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
-        if (!l_token) {
-            log_it(L_CRITICAL, c_error_memory_alloc);
-            return NULL;
-        }
         *l_token = (dap_chain_datum_token_t) {
                 .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL,
-                .version    = 1,
                 .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE,
-                .signs_valid    = l_token_old->signs_valid,
-                .signs_total    = l_token_old->signs_total,
-                .total_supply   = l_token_old->total_supply,
                 .header_simple.decimals = l_token_old->header_simple.decimals,
-        };
-        dap_stpcpy(l_token->ticker, l_token_old->ticker);
-        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
-        *a_token_size = l_token_size;
-        return l_token;
-    }
+        };    
+    } break;
+
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_DECL: {
-        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
-        if (!l_token) {
-            log_it(L_CRITICAL, c_error_memory_alloc);
-            return NULL;
-        }
         *l_token = (dap_chain_datum_token_t) {
                 .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL,
-                .version    = 1,
                 .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE,
-                .signs_valid    = l_token_old->signs_valid,
-                .signs_total    = l_token_old->signs_total,
-                .total_supply   = l_token_old->total_supply,
                 .header_private_decl.flags          = l_token_old->header_private_decl.flags,
                 .header_private_decl.tsd_total_size = l_token_old->header_private_decl.tsd_total_size,
                 .header_private_decl.decimals       = l_token_old->header_private_decl.decimals
         };
-        dap_stpcpy(l_token->ticker, l_token_old->ticker);
-        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
-        *a_token_size = l_token_size;
-        return l_token;
-    }
+    } break;
+
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_UPDATE: {
-        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
-        if (!l_token) {
-            log_it(L_CRITICAL, c_error_memory_alloc);
-            return NULL;
-        }
         *l_token = (dap_chain_datum_token_t) {
                 .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE,
-                .version    = 1,
                 .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE,
-                .signs_valid    = l_token_old->signs_valid,
-                .signs_total    = l_token_old->signs_total,
-                .total_supply   = l_token_old->total_supply,
                 .header_private_update.flags            = l_token_old->header_private_update.flags,
                 .header_private_update.tsd_total_size   = l_token_old->header_private_update.tsd_total_size,
                 .header_private_update.decimals         = l_token_old->header_private_update.decimals
         };
-        dap_stpcpy(l_token->ticker, l_token_old->ticker);
-        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
-        *a_token_size = l_token_size;
-        return l_token;
-    }
+    } break;
+
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_DECL: {
-        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
-        if (!l_token) {
-            log_it(L_CRITICAL, c_error_memory_alloc);
-            return NULL;
-        }
         *l_token = (dap_chain_datum_token_t) {
                 .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL,
-                .version    = 1,
                 .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE,
-                .signs_valid    = l_token_old->signs_valid,
-                .signs_total    = l_token_old->signs_total,
-                .total_supply   = l_token_old->total_supply,
                 .header_native_decl.flags           = l_token_old->header_native_decl.flags,
                 .header_native_decl.tsd_total_size  = l_token_old->header_native_decl.tsd_total_size,
                 .header_native_decl.decimals        = l_token_old->header_native_decl.decimals
         };
-        dap_stpcpy(l_token->ticker, l_token_old->ticker);
-        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
-        *a_token_size = l_token_size;
-        return l_token;
-    }
+    } break;
+
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_UPDATE: {
-        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
-        if (!l_token) {
-            log_it(L_CRITICAL, c_error_memory_alloc);
-            return NULL;
-        }
         *l_token = (dap_chain_datum_token_t) {
                 .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE,
-                .version    = 1,
                 .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE,
-                .signs_valid    = l_token_old->signs_valid,
-                .signs_total    = l_token_old->signs_total,
-                .total_supply   = l_token_old->total_supply,
                 .header_native_update.flags             = l_token_old->header_native_update.flags,
                 .header_native_update.tsd_total_size    = l_token_old->header_native_update.tsd_total_size,
                 .header_native_update.decimals          = l_token_old->header_native_update.decimals
         };
-        dap_stpcpy(l_token->ticker, l_token_old->ticker);
-        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
-        *a_token_size = l_token_size;
-        return l_token;
-    }
+    } break;
+
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC: {
-        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
-        if (!l_token) {
-            log_it(L_CRITICAL, c_error_memory_alloc);
-            return NULL;
-        }
         *l_token = (dap_chain_datum_token_t) {
                 .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL,
-                .version    = 1,
                 .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC,
-                .signs_valid    = l_token_old->signs_valid,
-                .signs_total    = l_token_old->signs_total,
-                .total_supply   = l_token_old->total_supply,
                 .header_public.flags            = l_token_old->header_public.flags,
                 .header_public.premine_supply   = l_token_old->header_public.premine_supply,
                 .header_public.premine_address  = l_token_old->header_public.premine_address
         };
-        dap_stpcpy(l_token->ticker, l_token_old->ticker);
-        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
-        *a_token_size = l_token_size;
-        return l_token;
-    }
+    } break;
+
     case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL:
     case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE:
-        return DAP_DUP_SIZE(a_token_serial, *a_token_size);
+        if (*a_token_size < sizeof(dap_chain_datum_token_t)) {
+            log_it(L_WARNING, "Too small token size %zu", *a_token_size);
+            DAP_DELETE(l_token);
+            return NULL;
+        }
+        return memcpy(l_token, a_token_serial, l_token_size);
+
     default:
         log_it(L_NOTICE, "Unknown token type '%d' read", ((dap_chain_datum_token_t*)a_token_serial)->type);
+        DAP_DELETE(l_token);
         return NULL;
     }
+
+    l_token->version = 2;
+    l_token->signs_valid = l_token_old->signs_valid;
+    l_token->signs_total = l_token_old->signs_total;
+    l_token->total_supply = l_token_old->total_supply;
+    dap_strncpy(l_token->ticker, l_token_old->ticker, DAP_CHAIN_TICKER_SIZE_MAX);
+    if (l_token_tsd_n_signs_size)
+        memcpy(l_token->tsd_n_signs, l_token_old->tsd_n_signs, l_token_tsd_n_signs_size);
+    *a_token_size = l_token_size;
+    return l_token;
 }
 
 /**
@@ -273,10 +230,10 @@ void dap_chain_datum_token_flags_dump_to_json(json_object * json_obj_out, uint16
 /**
  * @brief dap_chain_datum_token_certs_dump
  * @param a_str_out
- * @param a_data_n_tsd
+ * @param a_tsd_n_signs
  * @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, const char *a_hash_out_type)
+void dap_chain_datum_token_certs_dump(dap_string_t * a_str_out, byte_t * a_tsd_n_signs, size_t a_certs_size, const char *a_hash_out_type)
 {
     dap_string_append_printf(a_str_out, "signatures: ");
     if (!a_certs_size) {
@@ -288,7 +245,7 @@ void dap_chain_datum_token_certs_dump(dap_string_t * a_str_out, byte_t * a_data_
 
     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);
+        dap_sign_t *l_sign = (dap_sign_t *) (a_tsd_n_signs + 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");
@@ -319,10 +276,10 @@ void dap_chain_datum_token_certs_dump(dap_string_t * a_str_out, byte_t * a_data_
 /**
  * @brief dap_chain_datum_token_certs_dump_to_json
  * @param a_json_obj_out
- * @param a_data_n_tsd
+ * @param a_tsd_n_signs
  * @param a_certs_size
  */
-void dap_chain_datum_token_certs_dump_to_json(json_object *a_json_obj_out, byte_t * a_data_n_tsd, size_t a_certs_size, const char *a_hash_out_type)
+void dap_chain_datum_token_certs_dump_to_json(json_object *a_json_obj_out, byte_t * a_tsd_n_signs, size_t a_certs_size, const char *a_hash_out_type)
 {
     json_object_object_add(a_json_obj_out, "Signatures", json_object_new_string(""));
     if (!a_certs_size) {
@@ -334,7 +291,7 @@ void dap_chain_datum_token_certs_dump_to_json(json_object *a_json_obj_out, byte_
     json_object * json_arr_seg = json_object_new_array();
     for (int i = 1; l_offset < (a_certs_size); i++) {
         json_object * l_json_obj_out = json_object_new_object();
-        dap_sign_t *l_sign = (dap_sign_t *) (a_data_n_tsd + l_offset);
+        dap_sign_t *l_sign = (dap_sign_t *) (a_tsd_n_signs + l_offset);
         l_offset += dap_sign_get_size(l_sign);
         if (l_sign->header.sign_size == 0) {
             json_object_object_add(l_json_obj_out, "status", json_object_new_string("<CORRUPTED - 0 size signature>"));
@@ -367,88 +324,6 @@ void dap_chain_datum_token_certs_dump_to_json(json_object *a_json_obj_out, byte_
     json_object_object_add(a_json_obj_out, "status", json_arr_seg);
 }
 
-
-dap_sign_t ** dap_chain_datum_token_signs_parse(dap_chain_datum_token_t * a_datum_token, size_t a_datum_token_size, size_t *a_signs_total, size_t * a_signs_valid)
-{
-    assert(a_datum_token_size);
-    assert(a_datum_token);
-    assert(a_signs_total);
-    assert(a_signs_valid);
-    assert(a_datum_token_size >= sizeof(dap_chain_datum_token_old_t));
-    if (!a_datum_token->signs_total) {
-        log_it(L_ERROR, "No signs in datum token with ticker '%s', type %d", a_datum_token->ticker, a_datum_token->type);
-        return NULL;
-    }
-    *a_signs_total = 0;
-    *a_signs_valid = a_datum_token->signs_valid;
-    size_t l_offset = 0;
-    size_t l_signs_offset = 0;
-    switch (a_datum_token->type) {
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL:
-            switch (a_datum_token->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
-                    l_signs_offset = sizeof(dap_chain_datum_token_t);
-                    break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-                    l_signs_offset = sizeof(dap_chain_datum_token_t) + a_datum_token->header_private_decl.tsd_total_size;
-                    break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-                    l_signs_offset = sizeof(dap_chain_datum_token_t) + a_datum_token->header_native_decl.tsd_total_size;
-                    break;
-            }
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE:
-            switch (a_datum_token->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
-                    l_signs_offset = sizeof(dap_chain_datum_token_t);
-                    break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-                    l_signs_offset = sizeof(dap_chain_datum_token_t) + a_datum_token->header_private_update.tsd_total_size;
-                    break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-                    l_signs_offset = sizeof(dap_chain_datum_token_t) + a_datum_token->header_native_update.tsd_total_size;
-                    break;
-            }
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE:
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC:
-            l_signs_offset = sizeof(dap_chain_datum_token_old_t);
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_DECL:
-            l_signs_offset = sizeof(dap_chain_datum_token_old_t) + a_datum_token->header_private_decl.tsd_total_size;
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_UPDATE:
-            l_signs_offset = sizeof(dap_chain_datum_token_old_t) + a_datum_token->header_private_update.tsd_total_size;
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_DECL:
-            l_signs_offset = sizeof(dap_chain_datum_token_old_t) + a_datum_token->header_native_decl.tsd_total_size;
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_UPDATE:
-            l_signs_offset = sizeof(dap_chain_datum_token_old_t) + a_datum_token->header_native_update.tsd_total_size;
-            break;
-        default:
-            l_signs_offset = sizeof(dap_chain_datum_token_t);
-            break;
-    }
-    dap_sign_t **l_ret = DAP_NEW_Z_SIZE(dap_sign_t*, sizeof(dap_sign_t*) * a_datum_token->signs_total);
-    if (!l_ret) {
-        log_it(L_CRITICAL, "Out of memory!");
-        return NULL;
-    }
-    for (uint16_t i = 0; i < a_datum_token->signs_total && l_offset <= a_datum_token_size - l_signs_offset; ++i) {
-        l_ret[i] = (dap_sign_t*)((byte_t*)a_datum_token + l_signs_offset + l_offset);
-        size_t l_sign_size = dap_sign_get_size(l_ret[i]);
-        if (l_sign_size == 0 || l_sign_size > a_datum_token_size - l_offset) {
-            *a_signs_total = 0;
-            DAP_DELETE(l_ret);
-            return NULL;
-        }
-        (*a_signs_total)++;
-        l_offset += l_sign_size;
-    }
-    return l_ret;
-}
-
 /*                              Token emission section                          */
 
 dap_chain_datum_token_emission_t *dap_chain_datum_emission_create(uint256_t a_value, const char *a_ticker, dap_chain_addr_t *a_addr)
diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h
index cf461b6e3ada48df17313c01128347cacd56ad76..74f39e9ca3bff1a76be6016a9e46479d56f4e246 100644
--- a/modules/common/include/dap_chain_datum.h
+++ b/modules/common/include/dap_chain_datum.h
@@ -46,9 +46,9 @@
 #define DAP_CHAIN_DATUM_TX_REQUEST          0x0300
 
 /// Smart contract: DVM code section
-#define DAP_CHAIN_DATUM_WASM_CODE            0x0900
+#define DAP_CHAIN_DATUM_WASM_CODE           0x0900
 /// Smart contract: DVM code section
-#define DAP_CHAIN_DATUM_WASM_DATA            0x0901
+#define DAP_CHAIN_DATUM_WASM_DATA           0x0901
 
 /// Smart contract: EVM code section
 #define DAP_CHAIN_DATUM_EVM_CODE            0x0910
@@ -62,13 +62,13 @@
 
 /// Token
 /// Simple token decl
-#define DAP_CHAIN_DATUM_TOKEN_DECL           0xf000
-#define DAP_CHAIN_DATUM_TOKEN_EMISSION       0xf100
-#define DAP_CHAIN_DATUM_TOKEN_DISMISSAL      0xf200
+#define DAP_CHAIN_DATUM_TOKEN               0xf000
+#define DAP_CHAIN_DATUM_TOKEN_EMISSION      0xf100
+#define DAP_CHAIN_DATUM_TOKEN_DISMISSAL     0xf200
 
-#define DAP_CHAIN_DATUM_ANCHOR               0x0a00
+#define DAP_CHAIN_DATUM_ANCHOR              0x0a00
 
-#define DAP_CHAIN_DATUM_CUSTOM               0xffff
+#define DAP_CHAIN_DATUM_CUSTOM              0xffff
 
 #define DAP_DATUM_TYPE_STR(t, s)        \
     switch (t) {                        \
@@ -90,8 +90,8 @@
         s = "DATUM_SIGNER"; break;      \
     case DAP_CHAIN_DATUM_CUSTOM:        \
         s = "DATUM_CUSTOM"; break;      \
-    case DAP_CHAIN_DATUM_TOKEN_DECL:    \
-        s = "DATUM_TOKEN_DECL"; break;  \
+    case DAP_CHAIN_DATUM_TOKEN:    \
+        s = "DATUM_TOKEN"; break;  \
     case DAP_CHAIN_DATUM_TOKEN_EMISSION:\
         s = "DATUM_TOKEN_EMISSION"; break;\
     case DAP_CHAIN_DATUM_DECREE:        \
@@ -138,7 +138,14 @@ DAP_STATIC_INLINE size_t dap_chain_datum_size(const dap_chain_datum_t *a_datum)
 {
     if (!a_datum)
         return 0;
-    return  sizeof(a_datum->header) + a_datum->header.data_size;
+    return sizeof(a_datum->header) + a_datum->header.data_size;
+}
+
+DAP_STATIC_INLINE void dap_chain_datum_calc_hash(const dap_chain_datum_t *a_datum, dap_hash_fast_t *a_out_hash)
+{
+    if (!a_datum || !a_out_hash)
+        return;
+    dap_hash_fast(a_datum->data, a_datum->header.data_size, a_out_hash);
 }
 
 dap_chain_datum_t * dap_chain_datum_create(uint16_t a_type_id, const void * a_data, size_t a_data_size);
@@ -151,7 +158,6 @@ DAP_STATIC_INLINE const char *dap_chain_datum_type_id_to_str(uint16_t a_type_id)
     return l_ret;
 }
 
-void dap_chain_datum_token_dump_tsd(dap_string_t *a_str_out, dap_chain_datum_token_t *a_token, size_t a_token_size, const char *a_hash_out_type);
 void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datum_token_t *a_token, size_t a_token_size, const char *a_hash_out_type);
 void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, const char *a_hash_out_type, dap_chain_net_id_t a_net_id);
 bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
diff --git a/modules/common/include/dap_chain_datum_decree.h b/modules/common/include/dap_chain_datum_decree.h
index f8f40ea74fbd7f417d455d0f3b3f7729d280890a..1d6722f12c9e351a1f1f06788ae4d0dd81959c4a 100644
--- a/modules/common/include/dap_chain_datum_decree.h
+++ b/modules/common/include/dap_chain_datum_decree.h
@@ -291,7 +291,7 @@ void dap_chain_datum_decree_dump_json(json_object  *a_obj_out, dap_chain_datum_d
 /**
  * @brief dap_chain_datum_decree_certs_dump compose decree signatures output string
  * @param a_str_out pointer to output text buffer
- * @param a_data_n_tsd pointer to signs decree section
+ * @param a_tsd_n_signs pointer to signs decree section
  * @param a_certs_size size of decree signatures
  */
 void dap_chain_datum_decree_certs_dump(dap_string_t * a_str_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type);
diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h
index e993e219a04ba91d4d17bc605cb60def9943938c..0ca591b61e41fca0575a5ce2451d86c6ae9fa7da 100644
--- a/modules/common/include/dap_chain_datum_token.h
+++ b/modules/common/include/dap_chain_datum_token.h
@@ -34,7 +34,7 @@
 
 
 // Token declaration
-typedef struct dap_chain_datum_token_old{
+typedef struct dap_chain_datum_token_old {
     uint16_t type;
     char ticker[DAP_CHAIN_TICKER_SIZE_MAX];
     uint16_t signs_valid; // Emission auth signs
@@ -77,11 +77,11 @@ typedef struct dap_chain_datum_token_old{
         byte_t header[256]; // For future changes
     };
     uint16_t signs_total; // Emission auth signs
-    byte_t data_n_tsd[]; // Signs and/or types-size-data sections
+    byte_t tsd_n_signs[]; // Signs and/or types-size-data sections
 } DAP_ALIGN_PACKED dap_chain_datum_token_old_t;
 
 // Token declaration
-typedef struct dap_chain_datum_token{
+typedef struct dap_chain_datum_token {
     uint16_t type;
     uint16_t version;
     uint16_t subtype;
@@ -126,56 +126,44 @@ typedef struct dap_chain_datum_token{
         } DAP_ALIGN_PACKED header_public;
         byte_t header[256]; // For future changes
     };
-    byte_t data_n_tsd[]; // Signs and/or types-size-data sections
+    byte_t tsd_n_signs[]; // Signs and/or types-size-data sections
 } DAP_ALIGN_PACKED dap_chain_datum_token_t;
 
 typedef struct dap_chain_datum_token_tsd_delegate_from_stake_lock {
-    byte_t			ticker_token_from[DAP_CHAIN_TICKER_SIZE_MAX];
-    //	dap_hash_fast_t	hash_token_from;//TODO: ???
-    uint256_t		emission_rate;	// In "coins", 1^18 == 1.0
-    uint32_t		flags;			// Some emission flags for future
-    byte_t			padding[256];	// Some free space for future
+    byte_t      ticker_token_from[DAP_CHAIN_TICKER_SIZE_MAX];
+    uint256_t   emission_rate;  // In "coins", 1^18 == 1.0
+    byte_t      padding[4];     // Some free space for future
 } DAP_ALIGN_PACKED dap_chain_datum_token_tsd_delegate_from_stake_lock_t;
 
-// Token declaration type
-// Simple private token decl
-//#define DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE           0x0001
-// Extended declaration of privatetoken with in-time control
-//#define DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_DECL     0x0002
-// Token update
-//#define DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_UPDATE   0x0003
-// Open token with now ownership
-//#define DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC           0x0004
-
-// 256
+// Old token declaration & update types
 // Simple private token decl
 #define DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE               0x0005
 // Extended declaration of privatetoken with in-time control
 #define DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_DECL         0x0006
 // Token update
 #define DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_UPDATE       0x0007
-// Open token with now ownership
+// Open token with no ownership
 #define DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC               0x0008
 // Native token type
 #define DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_DECL          0x0009
 // Token update
 #define DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_UPDATE        0x000A
-// Open token with now ownership
+
 
 // New datum types with versioning and subtypes.
 // Declaration token
-#define DAP_CHAIN_DATUM_TOKEN_TYPE_DECL                      0x0010
+#define DAP_CHAIN_DATUM_TOKEN_TYPE_DECL                     0x0010
 // Updated token
-#define DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE                    0x0011
+#define DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE                   0x0011
 // Subtypes
 // Simple private token decl
-#define DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE                 0x0001
+#define DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE                0x0001
 // Extended declaration of privatetoken with in-time control
-#define DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE              0x0002
+#define DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE               0x0002
 // Native token
-#define DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE               0x0003
-// Open token with now ownership
-#define DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC               0x0004
+#define DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE                0x0003
+// Open token with no ownership
+#define DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC                0x0004
 
 
 // Macros for token flags
@@ -251,9 +239,8 @@ extern const char *c_dap_chain_datum_token_flag_str[];
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS                            0x0001
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS                          0x0002
 
-// Total supply limits
-#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY_OLD                     0x0003 // 128
-#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY                         0x0026 // 256
+// Total supply limit
+#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY                         0x0026
 
 // Set total signs count value to set to be valid
 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID                    0x0004
@@ -413,8 +400,7 @@ DAP_STATIC_INLINE int dap_chain_datum_token_get_delegated_ticker(char *a_buf, co
     if (!a_buf || !a_ticker)
         return -1;
     *a_buf = 'm';
-    strncpy(a_buf + 1, a_ticker, DAP_CHAIN_TICKER_SIZE_MAX - 2);
-    a_buf[DAP_CHAIN_TICKER_SIZE_MAX - 1] = '\0';
+    dap_strncpy(a_buf + 1, a_ticker, DAP_CHAIN_TICKER_SIZE_MAX - 1);
     return 0;
 }
 
@@ -522,9 +508,8 @@ extern const char *c_dap_chain_datum_token_emission_type_str[];
 dap_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_flags_dump_to_json(json_object * json_obj_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, const char *a_hash_out_type);
-void dap_chain_datum_token_certs_dump_to_json(json_object *a_json_obj_out, byte_t * a_data_n_tsd, size_t a_certs_size, const char *a_hash_out_type);
-dap_sign_t ** dap_chain_datum_token_signs_parse(dap_chain_datum_token_t * a_datum_token, size_t a_datum_token_size, size_t *a_signs_count, size_t * a_signs_valid);
+void dap_chain_datum_token_certs_dump(dap_string_t * a_str_out, byte_t * a_tsd_n_signs, size_t a_certs_size, const char *a_hash_out_type);
+void dap_chain_datum_token_certs_dump_to_json(json_object *a_json_obj_out, byte_t * a_tsd_n_signs, size_t a_certs_size, const char *a_hash_out_type);
 dap_chain_datum_token_t *dap_chain_datum_token_read(const byte_t *a_token_serial, size_t *a_token_size);
 
 dap_chain_datum_token_emission_t *dap_chain_datum_emission_create(uint256_t a_value, const char *a_ticker, dap_chain_addr_t *a_addr);
diff --git a/modules/common/include/dap_chain_datum_tx.h b/modules/common/include/dap_chain_datum_tx.h
index ae3eef5e42e62f99abf0f84015e6f2a46760d0de..e8a6ec192e5cdd3764526e9b2340aa223d5563d9 100644
--- a/modules/common/include/dap_chain_datum_tx.h
+++ b/modules/common/include/dap_chain_datum_tx.h
@@ -155,3 +155,18 @@ int dap_chain_datum_tx_verify_sign(dap_chain_datum_tx_t *a_tx);
 
 
 int dap_chain_datum_tx_get_fee_value (dap_chain_datum_tx_t *a_tx, uint256_t *a_value);
+
+/**
+ * @brief dap_chain_node_datum_tx_calc_hash
+ * @param a_tx
+ * @return
+ */
+DAP_STATIC_INLINE dap_chain_hash_fast_t* dap_chain_node_datum_tx_calc_hash(dap_chain_datum_tx_t *a_tx)
+{
+    dap_chain_hash_fast_t *tx_hash = DAP_NEW_Z(dap_chain_hash_fast_t);
+    if (!tx_hash) {
+        return NULL;
+    }
+    dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), tx_hash);
+    return tx_hash;
+}
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index 037b369271ab6f7f7754c53d0f0ecc3aeee6bbfe..6f12359e7035d108ee94a4fae35dffb1c0b2e3e3 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -379,7 +379,7 @@ void dap_chain_esbocs_add_block_collect(dap_chain_block_cache_t *a_block_cache,
     dap_chain_t *l_chain = a_block_collect_params->chain;
     if (a_type == DAP_CHAIN_BLOCK_COLLECT_BOTH || a_type == DAP_CHAIN_BLOCK_COLLECT_FEES) {
         dap_sign_t *l_sign = dap_chain_block_sign_get(a_block_cache->block, a_block_cache->block_size, 0);
-        if (dap_pkey_match_sign(a_block_collect_params->block_sign_pkey, l_sign)) {
+        if (dap_pkey_compare_with_sign(a_block_collect_params->block_sign_pkey, l_sign)) {
             dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain->net_id);
             assert(l_net);
             uint256_t l_value_fee = uint256_0;
@@ -559,7 +559,7 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf
         if (l_order->srv_uid.uint64 != DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ID)
             continue;
         dap_sign_t *l_order_sign = (dap_sign_t*)(l_order->ext_n_sign + l_order->ext_size);
-        if (!dap_pkey_match_sign(l_esbocs_pvt->block_sign_pkey, l_order_sign))
+        if (!dap_pkey_compare_with_sign(l_esbocs_pvt->block_sign_pkey, l_order_sign))
             continue;
         if (!l_order_service)
             l_order_service = l_order;
@@ -2768,8 +2768,12 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
         log_it(L_WARNING, "Incorrect header size with block %p on chain %s", a_block, a_blocks->chain->name);
         return  -7;
     }
-
-    if (a_block->hdr.meta_n_datum_n_signs_size &&
+    size_t l_offset = dap_chain_block_get_sign_offset(a_block, a_block_size);
+    if (!l_offset) {
+        log_it(L_WARNING, "Block with size %zu parsing error", a_block_size);
+        return -5;
+    }
+    if ((a_block->hdr.meta_n_datum_n_signs_size > l_offset || a_block->hdr.version == 2) &&
             a_block->hdr.meta_n_datum_n_signs_size != a_block_size - sizeof(a_block->hdr)) {
         log_it(L_WARNING, "Incorrect size with block %p on chain %s", a_block, a_blocks->chain->name);
         return -8;
@@ -2779,11 +2783,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
         // It's a block candidate, don't check signs
         return 0;
 
-    size_t l_offset = dap_chain_block_get_sign_offset(a_block, a_block_size);
-    if (!l_offset) {
-        log_it(L_WARNING, "Block with size %zu parsing error", a_block_size);
-        return -5;
-    }
+
     size_t l_signs_count = 0;
     dap_sign_t **l_signs = dap_sign_get_unique_signs(a_block->meta_n_datum_n_sign+l_offset,
                                             a_block_size-sizeof(a_block->hdr)-l_offset, &l_signs_count);
diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c
index d1d6aaa9fce6b698ab3f6964311f6f51632a4845..d559a8eceb40df4dd6dd41fec09c8d2e581b2192 100644
--- a/modules/mempool/dap_chain_mempool.c
+++ b/modules/mempool/dap_chain_mempool.c
@@ -91,7 +91,7 @@ char *dap_chain_mempool_datum_add(const dap_chain_datum_t *a_datum, dap_chain_t
     dap_return_val_if_pass(!a_datum, NULL);
 
     dap_chain_hash_fast_t l_key_hash;
-    dap_hash_fast(a_datum->data, a_datum->header.data_size, &l_key_hash);
+    dap_chain_datum_calc_hash(a_datum, &l_key_hash);
     char *l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
     const char *l_key_str_out = dap_strcmp(a_hash_out_type, "hex")
             ? dap_enc_base58_encode_hash_to_str_static(&l_key_hash)
@@ -99,7 +99,7 @@ char *dap_chain_mempool_datum_add(const dap_chain_datum_t *a_datum, dap_chain_t
 
     const char *l_type_str;
     switch (a_datum->header.type_id) {
-    case DAP_CHAIN_DATUM_TOKEN_DECL:
+    case DAP_CHAIN_DATUM_TOKEN:
         l_type_str = "token";
         break;
     case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
@@ -1205,13 +1205,13 @@ dap_chain_datum_token_emission_t *dap_chain_mempool_datum_emission_extract(dap_c
     dap_chain_datum_token_t *l_token = dap_ledger_token_ticker_check(l_net->pub.ledger, l_ticker);
     if (!l_token)
         return NULL;
-    if (l_token->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE && l_token->type == DAP_CHAIN_DATUM_TOKEN_DECL)
+    if (l_token->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE && l_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_DECL)
         return NULL;
     /*int l_signs_valid = 0;
     dap_sign_t *l_ems_sign = (dap_sign_t *)(l_emission->tsd_n_signs + l_emission->data.type_auth.tsd_total_size);
     for (int i = 0; i < l_emission->data.type_auth.signs_count; i++) {
         uint32_t l_ems_pkey_size = l_ems_sign->header.sign_pkey_size;
-        dap_sign_t *l_token_sign = (dap_sign_t *)(l_token->data_n_tsd + l_token->header_native_decl.tsd_total_size);
+        dap_sign_t *l_token_sign = (dap_sign_t *)(l_token->tsd_n_signs + l_token->header_native_decl.tsd_total_size);
         for (int j = 0; j < l_token->signs_total; j++) {
             if (l_ems_pkey_size == l_ems_sign->header.sign_pkey_size &&
                     !memcmp(l_token_sign->pkey_n_sign, l_ems_sign->pkey_n_sign, l_ems_pkey_size)) {
diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c
index 4099260c113ba0d5e282eb8412f50a9dea5eeb08..79b536b49915023c07a3596d7087c3a561b284c2 100644
--- a/modules/net/dap_chain_ledger.c
+++ b/modules/net/dap_chain_ledger.c
@@ -68,10 +68,11 @@ typedef struct dap_ledger_verificator {
     UT_hash_handle hh;
 } dap_ledger_verificator_t;
 
-typedef struct dap_chain_ledger_votings_callbacks{
+typedef struct dap_chain_ledger_votings_callbacks {
     dap_chain_ledger_voting_callback_t voting_callback;
     dap_chain_ledger_voting_delete_callback_t voting_delete_callback;
 } dap_chain_ledger_votings_callbacks_t;
+
 typedef struct dap_ledger_service_info {
     dap_chain_net_srv_uid_t service_uid;    // hash key
     char tag_str[32];   // tag string name
@@ -89,69 +90,6 @@ static dap_chain_ledger_votings_callbacks_t s_voting_callbacks;
 
 #define MAX_OUT_ITEMS   10
 
-static const char * const s_ledger_tx_check_err_str[] = {
-    [DAP_LEDGER_TX_CHECK_OK] = "DAP_LEDGER_TX_CHECK_OK",
-    [DAP_LEDGER_TX_CHECK_NULL_TX] = "DAP_LEDGER_TX_CHECK_NULL_TX",
-    [DAP_LEDGER_TX_CHECK_INVALID_TX_SIZE] = "DAP_LEDGER_TX_CHECK_INVALID_TX_SIZE",
-    [DAP_LEDGER_TX_ALREADY_CACHED] = "DAP_LEDGER_TX_ALREADY_CACHED",
-    [DAP_LEDGER_TX_CHECK_INVALID_TX_SIGN] = "DAP_LEDGER_TX_CHECK_INVALID_TX_SIGN",
-    [DAP_LEDGER_TX_CHECK_IN_EMS_ALREADY_USED] = "DAP_LEDGER_TX_CHECK_IN_EMS_ALREADY_USED",
-    [DAP_LEDGER_TX_CHECK_STAKE_LOCK_IN_EMS_ALREADY_USED] = "DAP_LEDGER_TX_CHECK_STAKE_LOCK_IN_EMS_ALREADY_USED",
-    [DAP_LEDGER_TX_CHECK_EMISSION_NOT_FOUND] = "DAP_LEDGER_TX_CHECK_EMISSION_NOT_FOUND",
-    [DAP_LEDGER_TX_CHECK_TX_NO_VALID_INPUTS] = "DAP_LEDGER_TX_CHECK_TX_NO_VALID_INPUTS",
-    [DAP_LEDGER_TX_CHECK_TICKER_NOT_FOUND] = "DAP_LEDGER_TX_CHECK_TICKER_NOT_FOUND",
-    [DAP_LEDGER_TX_CHECK_STAKE_LOCK_INVALID_TOKEN] = "DAP_LEDGER_TX_CHECK_STAKE_LOCK_INVALID_TOKEN",
-    [DAP_LEDGER_TX_CHECK_STAKE_LOCK_NO_OUT_COND_FOR_IN_EMS] = "DAP_LEDGER_TX_CHECK_STAKE_LOCK_NO_OUT_COND_FOR_IN_EMS",
-    [DAP_LEDGER_TX_CHECK_MULT256_OVERFLOW_EMS_LOCKED_X_RATE] = "DAP_LEDGER_TX_CHECK_MULT256_OVERFLOW_EMS_LOCKED_X_RATE",
-    [DAP_LEDGER_TX_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS] = "DAP_LEDGER_TX_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS",
-    [DAP_LEDGER_TX_CHECK_NO_OUT_ITEMS_FOR_BASE_TX] = "DAP_LEDGER_TX_CHECK_NO_OUT_ITEMS_FOR_BASE_TX",
-    [DAP_LEDGER_TX_CHECK_TOKEN_EMS_VALUE_EXEEDS_CUR_SUPPLY] = "DAP_LEDGER_TX_CHECK_TOKEN_EMS_VALUE_EXEEDS_CUR_SUPPLY",
-    [DAP_LEDGER_TX_CHECK_STAKE_LOCK_UNEXPECTED_VALUE] = "DAP_LEDGER_TX_CHECK_STAKE_LOCK_UNEXPECTED_VALUE",
-    [DAP_LEDGER_TX_CHECK_STAKE_LOCK_TICKER_NOT_FOUND] = "DAP_LEDGER_TX_CHECK_STAKE_LOCK_TICKER_NOT_FOUND",
-    [DAP_LEDGER_TX_CHECK_STAKE_LOCK_OTHER_TICKER_EXPECTED] = "DAP_LEDGER_TX_CHECK_STAKE_LOCK_OTHER_TICKER_EXPECTED",
-    [DAP_LEDGER_TX_CHECK_OUT_ITEM_ALREADY_USED] = "DAP_LEDGER_TX_CHECK_OUT_ITEM_ALREADY_USED",
-    [DAP_LEDGER_TX_CHECK_PREV_TX_NOT_FOUND] = "DAP_LEDGER_TX_CHECK_PREV_TX_NOT_FOUND",
-    [DAP_LEDGER_TX_CHECK_PREV_OUT_ITEM_NOT_FOUND] = "DAP_LEDGER_TX_CHECK_PREV_OUT_ITEM_NOT_FOUND",
-    [DAP_LEDGER_TX_CHECK_PKEY_HASHES_DONT_MATCH] = "DAP_LEDGER_TX_CHECK_PKEY_HASHES_DONT_MATCH",
-    [DAP_LEDGER_TX_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX] = "DAP_LEDGER_TX_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX",
-    [DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET] = "DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET",
-    [DAP_LEDGER_TX_CHECK_VERIFICATOR_CHECK_FAILURE] = "DAP_LEDGER_TX_CHECK_VERIFICATOR_CHECK_FAILURE",
-    [DAP_LEDGER_TX_CHECK_PREV_TICKER_NOT_FOUND] = "DAP_LEDGER_TX_CHECK_PREV_TICKER_NOT_FOUND",
-    [DAP_LEDGER_TX_CHECK_PREV_TOKEN_NOT_FOUND] = "DAP_LEDGER_TX_CHECK_PREV_TOKEN_NOT_FOUND",
-    [DAP_LEDGER_PERMISSION_CHECK_FAILED] = "DAP_LEDGER_PERMISSION_CHECK_FAILED",
-    [DAP_LEDGER_TX_CHECK_SUM_INS_NOT_EQUAL_SUM_OUTS] = "DAP_LEDGER_TX_CHECK_SUM_INS_NOT_EQUAL_SUM_OUTS",
-    [DAP_LEDGER_TX_CHECK_REWARD_ITEM_ALREADY_USED] = "DAP_LEDGER_TX_CHECK_REWARD_ITEM_ALREADY_USED",
-    [DAP_LEDGER_TX_CHECK_REWARD_ITEM_ILLEGAL] = "DAP_LEDGER_TX_CHECK_REWARD_ITEM_ILLEGAL"
-};
-
-static const char * const s_ledger_emission_add_err_str[] = {
-    [DAP_LEDGER_EMISSION_ADD_OK] = "DAP_LEDGER_EMISSION_ADD_OK",
-    [DAP_LEDGER_EMISSION_ADD_CHECK_EMS_IS_NULL] = "DAP_LEDGER_EMISSION_ADD_CHECK_EMS_IS_NULL",
-    [DAP_LEDGER_EMISSION_ADD_CHECK_EMS_ALREADY_CACHED] = "DAP_LEDGER_EMISSION_ADD_CHECK_EMS_ALREADY_CACHED",
-    [DAP_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_OVERFLOW] = "DAP_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_OVERFLOW",
-    [DAP_LEDGER_EMISSION_ADD_CHECK_VALUE_EXEEDS_CURRENT_SUPPLY] = "DAP_LEDGER_EMISSION_ADD_CHECK_VALUE_EXEEDS_CURRENT_SUPPLY",
-    [DAP_LEDGER_EMISSION_ADD_CHECK_NOT_ENOUGH_VALID_SIGNS] = "DAP_LEDGER_EMISSION_ADD_CHECK_NOT_ENOUGH_VALID_SIGNS",
-    [DAP_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN] = "DAP_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN",
-    [DAP_LEDGER_EMISSION_ADD_CHECK_ZERO_VALUE] = "DAP_LEDGER_EMISSION_ADD_CHECK_ZERO_VALUE",
-    [DAP_LEDGER_EMISSION_ADD_TSD_CHECK_FAILED] = "DAP_LEDGER_EMISSION_ADD_TSD_CHECK_FAILED"
-};
-
-static const char * const s_ledger_token_decl_err_str[] = {
-    [DAP_LEDGER_TOKEN_DECL_ADD_OK] = "DAP_LEDGER_TOKEN_DECL_ADD_OK",
-    [DAP_LEDGER_TOKEN_DECL_ADD_ERR_LEDGER_IS_NULL] = "DAP_LEDGER_TOKEN_DECL_ADD_ERR_LEDGER_IS_NULL",
-    [DAP_LEDGER_TOKEN_DECL_ADD_ERR_DECL_DUPLICATE] = "DAP_LEDGER_TOKEN_DECL_ADD_ERR_DECL_DUPLICATE",
-    [DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_CHECK] = "DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_CHECK",
-    [DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_ABSENT_TOKEN] = "DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_ABSENT_TOKEN",
-    [DAP_LEDGER_TOKEN_DECL_ADD_ERR_NOT_ENOUGH_VALID_SIGN] = "DAP_LEDGER_TOKEN_DECL_ADD_ERR_NOT_ENOUGH_VALID_SIGN",
-    [DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOTAL_SIGNS_EXCEED_UNIQUE_SIGNS] = "DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOTAL_SIGNS_EXCEED_UNIQUE_SIGNS"
-};
-
-char *dap_ledger_tx_check_err_str(int a_code) {
-    return (a_code >= DAP_LEDGER_TX_CHECK_OK) && (a_code < DAP_LEDGER_TX_CHECK_UNKNOWN)
-            ? (char*)s_ledger_tx_check_err_str[(dap_ledger_tx_check_t)a_code]
-            : dap_itoa(a_code);
-}
-
 typedef struct dap_ledger_stake_lock_item {
     dap_chain_hash_fast_t	tx_for_stake_lock_hash;
     dap_chain_hash_fast_t	tx_used_out;
@@ -176,11 +114,9 @@ typedef struct dap_ledger_token_update_item {
 } dap_ledger_token_update_item_t;
 
 typedef struct dap_ledger_token_item {
-    uint16_t version;
     char ticker[DAP_CHAIN_TICKER_SIZE_MAX];
-    uint16_t type;
     uint16_t subtype;
-    dap_chain_datum_token_t * datum_token;
+    dap_chain_datum_token_t *datum_token;
     uint64_t datum_token_size;
 
     uint256_t total_supply;
@@ -195,10 +131,10 @@ typedef struct dap_ledger_token_item {
 
     // for auth operations
     dap_pkey_t ** auth_pkeys;
-    dap_chain_hash_fast_t *auth_pkeys_hash;
+    dap_chain_hash_fast_t *auth_pkey_hashes;
     size_t auth_signs_total;
     size_t auth_signs_valid;
-    uint16_t           flags;
+    uint32_t           flags;
     dap_chain_addr_t * tx_recv_allow;
     size_t             tx_recv_allow_size;
     dap_chain_addr_t * tx_recv_block;
@@ -207,8 +143,12 @@ typedef struct dap_ledger_token_item {
     size_t             tx_send_allow_size;
     dap_chain_addr_t * tx_send_block;
     size_t             tx_send_block_size;
-    char *description_token;
-    size_t description_token_size;
+    char *description;
+    // For delegated tokens
+    bool is_delegated;
+    char delegated_from[DAP_CHAIN_TICKER_SIZE_MAX];
+    uint256_t emission_rate;
+
     UT_hash_handle hh;
 } dap_ledger_token_item_t;
 
@@ -354,9 +294,6 @@ static void s_threshold_emissions_proc( dap_ledger_t * a_ledger);
 static void s_threshold_txs_proc( dap_ledger_t * a_ledger);
 static void s_threshold_txs_free(dap_ledger_t *a_ledger);
 static void s_threshold_emission_free(dap_ledger_t *a_ledger);
-static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_ledger_token_item_t *a_token_item , dap_chain_datum_token_t * a_token, size_t a_token_size);
-static int s_tsd_sign_apply(dap_ledger_t *a_ledger, dap_ledger_token_item_t *a_token_item , dap_chain_datum_token_t *a_token, size_t a_token_size);
-static int s_ledger_permissions_check(dap_ledger_token_item_t *  a_token_item, uint16_t a_permission_id, const void * a_data,size_t a_data_size );
 static int s_sort_ledger_tx_item(dap_ledger_tx_item_t* a, dap_ledger_tx_item_t* b);
 
 static size_t s_threshold_emissions_max = 1000;
@@ -552,7 +489,7 @@ void dap_ledger_deinit()
  * Create empty dap_ledger_t structure
  * @return dap_ledger_t*
  */
-static dap_ledger_t * dap_ledger_handle_new(void)
+static dap_ledger_t *dap_ledger_handle_new(void)
 {
     dap_ledger_t *l_ledger = DAP_NEW_Z(dap_ledger_t);
     if ( !l_ledger ) {
@@ -578,7 +515,6 @@ static dap_ledger_t * dap_ledger_handle_new(void)
                                                                       (dap_timer_callback_t)s_threshold_txs_free, l_ledger);
     l_ledger_pvt->threshold_emissions_free_timer = dap_interval_timer_create(s_threshold_free_timer_tick,
                                                                             (dap_timer_callback_t) s_threshold_emission_free, l_ledger);                                                                          
-    l_ledger_pvt->mapped = dap_config_get_item_bool_default(g_config, "ledger", "mapped", true);
     return l_ledger;
 }
 
@@ -632,247 +568,781 @@ struct json_object *wallet_info_json_collect(dap_ledger_t *a_ledger, dap_ledger_
     return l_json;
 }
 
+inline static dap_ledger_token_item_t *s_ledger_find_token(dap_ledger_t *a_ledger, const char *a_token_ticker)
+{
+    dap_return_val_if_fail(a_ledger && a_token_ticker, NULL);
+    dap_ledger_token_item_t *l_token_item;
+    pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
+    HASH_FIND_STR(PVT(a_ledger)->tokens, a_token_ticker, l_token_item);
+    pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+    return l_token_item;
+}
+
 /**
- * @brief s_ledger_token_update_check
- * @param a_cur_token_item
- * @param a_token_update
- * @param a_token_update_size
- * @return true or false
+ * @brief s_token_tsd_parse
+ *
+ * @param a_ledger
+ * @param a_item_apply_to
+ * @param a_token
+ * @param a_token_size
+ * @return int
  */
-static bool s_ledger_token_update_check(dap_ledger_token_item_t *a_cur_token_item, dap_chain_datum_token_t *a_token_update, size_t a_token_update_size)
+static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain_datum_token_t *a_current_datum,
+                             dap_ledger_t *a_ledger, byte_t *a_tsd, size_t a_tsd_total_size, bool a_apply)
 {
-    dap_sign_t								**l_signs_upd_token;
-    size_t									auth_signs_total = 0;
-    size_t									auth_signs_valid = 0;
-    dap_ledger_token_update_item_t	*l_token_update_item;
-    dap_hash_fast_t							l_hash_token_update;
-
-    dap_hash_fast(a_token_update, a_token_update_size, &l_hash_token_update);
-    pthread_rwlock_rdlock(&a_cur_token_item->token_ts_updated_rwlock);
-    HASH_FIND(hh, a_cur_token_item->token_ts_updated, &l_hash_token_update, sizeof(dap_hash_fast_t),
-              l_token_update_item);
-    pthread_rwlock_unlock(&a_cur_token_item->token_ts_updated_rwlock);
-    if (l_token_update_item
-    &&	a_cur_token_item->last_update_token_time == l_token_update_item->updated_time) {
-        if (s_debug_more)
-            log_it(L_WARNING,"This update for token '%s' was already applied", a_token_update->ticker);
-        return false;
-    }
-
-    /*if (a_cur_token_item->auth_signs_total != a_token_update->signs_total
-    ||	a_cur_token_item->auth_signs_valid != a_token_update->signs_valid) {
-        if(s_debug_more)
-            log_it(L_WARNING,"Can't update token with ticker '%s' because: "
-                             "l_token_item auth signs total/valid == %lu/%lu | "
-                             "token_update auth signs total/valid == %hu/%hu",
-                   a_token_update->ticker,
-                   a_cur_token_item->auth_signs_total, a_cur_token_item->auth_signs_valid,
-                   a_token_update->signs_total, a_token_update->signs_valid);
-        return false;
-    }*/
-
-    l_signs_upd_token = dap_chain_datum_token_signs_parse(a_token_update, a_token_update_size,
-                                                          &auth_signs_total, &auth_signs_valid);
-    if (a_cur_token_item->auth_signs_valid > auth_signs_total) {
-        DAP_DEL_Z(l_signs_upd_token);
-        if(s_debug_more)
-            log_it(L_WARNING,"Can't update token with ticker '%s' because: "
-                             "l_token_item auth signs total/valid == %lu/%lu | "
-                             "token_update auth signs total/valid == %lu/%lu",
-                   a_token_update->ticker,
-                   a_cur_token_item->auth_signs_total, a_cur_token_item->auth_signs_valid,
-                   auth_signs_total, auth_signs_valid);
-        return false;
-    }
-    if(auth_signs_total) {
-        size_t l_valid_pkeys = 0;
-        for(uint16_t i = 0; i < auth_signs_total; i++){
-            dap_pkey_t *l_pkey_upd_token = dap_pkey_get_from_sign(l_signs_upd_token[i]);
-            for (size_t j = 0; j < a_cur_token_item->auth_signs_total; j++) {
-                if (dap_pkey_match(a_cur_token_item->auth_pkeys[j], l_pkey_upd_token)) {
-                    l_valid_pkeys++;
-                    break;
-                }
-            }
-            DAP_DELETE(l_pkey_upd_token);
-        }
-        if (a_cur_token_item->auth_signs_valid > l_valid_pkeys) {
-            DAP_DEL_Z(l_signs_upd_token);
-            if (s_debug_more)
-                log_it(L_WARNING, "Can't update token with ticker '%s' because: Insufficient number of valid signatures "
-                                  "for an token update. Verified %zu needs %zu.", a_token_update->ticker, l_valid_pkeys,
-                                  a_cur_token_item->auth_signs_valid);
-            return false;
-        }
-    }
-    DAP_DEL_Z(l_signs_upd_token);
-    if (!IS_ZERO_256(a_token_update->total_supply)){
-        if (compare256(a_token_update->total_supply, a_cur_token_item->total_supply) < 0) {//compare old 'total_supply' to updated
-            if(s_debug_more)
-                log_it(L_WARNING, "Can't update token with ticker '%s' because: the new 'total_supply' cannot be smaller than the old one", a_token_update->ticker);
-            return false;
-        }
-    }
-    // Check edit auth signs
-    size_t l_tsd_total_size = 0;
-    if (a_token_update->subtype  == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE)
-        l_tsd_total_size = a_token_update->header_native_update.tsd_total_size;
-    else if (a_token_update->subtype  == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE)
-        l_tsd_total_size = a_token_update->header_native_update.tsd_total_size;
-    // Checking that the TSD section with the threshold change is the only one.
-    //And getting lists of TSD sections with the removal and addition of certificates.
-    int l_quantity_tsd_section_edit_signs_emission = 0;
-    dap_tsd_t *l_tsd_signs_valid = NULL;
-    dap_list_t *l_tsd_list_remote_pkeys = NULL, *l_tsd_list_added_pkeys = NULL;
-    int l_quantity_tsd_remote_pkeys = 0, l_quantity_tsd_add_pkeys = 0;
-    for (size_t l_tsd_offset = 0; l_tsd_offset < l_tsd_total_size; ) {
-        dap_tsd_t *l_tsd = (dap_tsd_t*)((byte_t*)a_token_update->data_n_tsd + l_tsd_offset);
-        size_t l_tsd_size = dap_tsd_size(l_tsd);
-        if (l_tsd_size == 0) {
-            if (s_debug_more)
-                log_it(L_ERROR, "Token refresh datum %s contains a non-valid TSD section. Size TSD section is 0.", a_token_update->ticker);
-            return false;
-        } else if (l_tsd_size + l_tsd_offset > l_tsd_total_size) {
-            if (s_debug_more)
-                log_it(L_ERROR, "Token refresh datum %s contains a non-valid TSD section. "
-                                "The size of the TSD section and the offset exceed the set size of the TSD sections.", a_token_update->ticker);
-            return false;
+    if (!a_tsd_total_size) {
+        debug_if(a_item_apply_to, L_NOTICE, "No TSD sections in datum token");
+        return DAP_LEDGER_CHECK_OK;
+    }
+    dap_return_val_if_pass(a_apply && !a_item_apply_to, DAP_LEDGER_CHECK_INVALID_ARGS);
+    size_t l_new_signs_valid = a_item_apply_to ? a_item_apply_to->auth_signs_valid : 0;
+    size_t l_new_signs_total = a_item_apply_to ? a_item_apply_to->auth_signs_total : 0;
+    dap_pkey_t **l_new_pkeys = NULL;
+    dap_hash_fast_t *l_new_pkey_hashes = NULL;
+    bool l_was_pkeys_copied = false;
+    size_t l_new_tx_recv_allow_size = a_item_apply_to ? a_item_apply_to->tx_recv_allow_size : 0;
+    size_t l_new_tx_recv_block_size = a_item_apply_to ? a_item_apply_to->tx_recv_block_size : 0;
+    size_t l_new_tx_send_allow_size = a_item_apply_to ? a_item_apply_to->tx_send_allow_size : 0;
+    size_t l_new_tx_send_block_size = a_item_apply_to ? a_item_apply_to->tx_send_block_size : 0;
+    dap_chain_addr_t *l_new_tx_recv_allow = NULL, *l_new_tx_recv_block = NULL,
+                     *l_new_tx_send_allow = NULL, *l_new_tx_send_block = NULL;
+    bool l_was_tx_recv_allow_copied = false, l_was_tx_recv_block_copied = false,
+         l_was_tx_send_allow_copied = false, l_was_tx_send_block_copied = false;
+
+    int ret = DAP_LEDGER_CHECK_OK;
+    size_t l_tsd_size = 0;
+    dap_tsd_t *l_tsd = (dap_tsd_t *)a_tsd;
+    for (size_t l_offset = 0; l_offset < a_tsd_total_size; l_offset += l_tsd_size) {
+        if (l_offset + sizeof(dap_tsd_t) > a_tsd_total_size) {
+            log_it(L_WARNING, "Incorrect TSD section size, less than header");
+            ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+            goto ret_n_clear;
+        }
+        l_tsd = (dap_tsd_t *)((byte_t *)l_tsd + l_tsd_size);
+        l_tsd_size = dap_tsd_size(l_tsd);
+        if (l_offset + l_tsd_size > a_tsd_total_size) {
+            log_it(L_WARNING, "Wrong TSD size %zu, exiting TSD parse", l_tsd_size);
+            ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+            goto ret_n_clear;
         }
         switch (l_tsd->type) {
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID:
-                l_quantity_tsd_section_edit_signs_emission++;
-                l_tsd_signs_valid = l_tsd;
+        // set flags
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS: {
+            if (l_tsd->size != sizeof(uint16_t)) {
+                log_it(L_WARNING, "Wrong SET_FLAGS TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            if (!a_apply)
                 break;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE:
-                l_quantity_tsd_remote_pkeys++;
-                l_tsd_list_remote_pkeys = dap_list_append(l_tsd_list_remote_pkeys, l_tsd);
+            a_item_apply_to->flags |= dap_tsd_get_scalar(l_tsd, uint16_t);
+        } break;
+
+        // unset flags
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS: {
+            if (l_tsd->size != sizeof(uint16_t)) {
+                log_it(L_WARNING, "Wrong UNSET_FLAGS TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            if (!a_apply)
                 break;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD:
-                l_quantity_tsd_add_pkeys++;
-                l_tsd_list_added_pkeys = dap_list_append(l_tsd_list_added_pkeys, l_tsd);
+            a_item_apply_to->flags &= ~dap_tsd_get_scalar(l_tsd, uint16_t);
+        } break;
+
+        // set total supply
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY: { // 256
+            if (l_tsd->size != sizeof(uint256_t)) {
+                log_it(L_WARNING, "Wrong TOTAL_SUPPLY TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            if (!a_item_apply_to) {
+                log_it(L_WARNING, "Unexpected TOTAL_SUUPLY TSD section in datum token declaration");
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_FORBIDDEN;
+                goto ret_n_clear;
+            }
+            uint256_t l_new_supply = dap_tsd_get_scalar(l_tsd, uint256_t);
+            if (!IS_ZERO_256(a_item_apply_to->total_supply) && !IS_ZERO_256(l_new_supply) &&
+                    compare256(a_item_apply_to->total_supply, l_new_supply) < 0) { //compare old 'total_supply' can be updated
+                log_it(L_WARNING, "Can't update token with ticker '%s' because the new 'total_supply' can't be smaller than the old one", a_item_apply_to->ticker);
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_SUPPLY;
+                goto ret_n_clear;
+            }
+            if (!a_apply)
                 break;
-        }
-        l_tsd_offset += l_tsd_size;
-    }
-    if (l_quantity_tsd_section_edit_signs_emission > 1) {
-        if (s_debug_more) {
-            log_it(L_ERROR, "Datum contains %ud TSD sections of type DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID which is not true. "
-                            "There can be at most one such TSD section.", l_quantity_tsd_section_edit_signs_emission);
-        }
-        dap_list_free(l_tsd_list_added_pkeys);
-        dap_list_free(l_tsd_list_remote_pkeys);
-        return false;
-    }
-    //Check new count signs
-    size_t l_new_signs_total = auth_signs_total + l_quantity_tsd_add_pkeys - l_quantity_tsd_remote_pkeys;
-    if (l_tsd_signs_valid) {
-        uint16_t l_signs_valid_from_tsd = 0;
-        _dap_tsd_get_scalar(l_tsd_signs_valid, &l_signs_valid_from_tsd);
-        if (l_new_signs_total < (size_t)l_signs_valid_from_tsd || l_signs_valid_from_tsd < 1) {
-            dap_list_free(l_tsd_list_added_pkeys);
-            dap_list_free(l_tsd_list_remote_pkeys);
-            return false;
-        }
-    } else {
-        if (l_new_signs_total < auth_signs_valid){
-            dap_list_free(l_tsd_list_added_pkeys);
-            dap_list_free(l_tsd_list_remote_pkeys);
-            return false;
-        }
-    }
-    //Check valid remove_signs
-    bool isAccepted = false;
-    if (!l_tsd_list_remote_pkeys)
-        isAccepted = true;
-    else {
-        for (dap_list_t *l_ptr = l_tsd_list_remote_pkeys; l_ptr; l_ptr = dap_list_next(l_ptr)) {
-            dap_tsd_t *l_tsd = (dap_tsd_t *) l_ptr->data;
-            dap_hash_fast_t l_hash = { };
-            _dap_tsd_get_scalar(l_tsd, &l_hash);
-            bool accepted = false;
-            for (size_t i = 0; i < auth_signs_total; i++) {
-                if (dap_hash_fast_compare(&a_cur_token_item->auth_pkeys_hash[i], &l_hash)) {
-                    accepted = true;
+            a_item_apply_to->total_supply = l_new_supply;
+        } break;
+
+        // Allowed tx receiver addres list add, remove or clear
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD: {
+            if (l_tsd->size != sizeof(dap_chain_addr_t)) {
+                log_it(L_WARNING, "Wrong TX_RECEIVER_ALLOWED_ADD TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            // Check if its correct
+            dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+            if (dap_chain_addr_check_sum(l_add_addr)) {
+                log_it(L_WARNING, "Wrong address checksum in TSD param TX_RECEIVER_ALLOWED_ADD");
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR;
+                goto ret_n_clear;
+            }
+            if (!l_new_tx_recv_allow && l_new_tx_recv_allow_size && !l_was_tx_recv_allow_copied) {
+                assert(a_item_apply_to->tx_recv_allow);
+                // Deep copy addrs to sandbox
+                l_new_tx_recv_allow = DAP_DUP_SIZE(a_item_apply_to->tx_recv_allow, l_new_tx_recv_allow_size * sizeof(dap_chain_addr_t));
+                if (!l_new_tx_recv_allow) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
+                }
+            }
+            l_was_tx_recv_allow_copied = true;
+            // Check if its already present
+            for (size_t i = 0; i < l_new_tx_recv_allow_size; i++) { // Check for all the list
+                if (dap_chain_addr_compare(l_new_tx_recv_allow + i, l_add_addr)) { // Found
+                    log_it(L_WARNING, "TSD param TX_RECEIVER_ALLOWED_ADD has address %s thats already present in list",
+                                                                    dap_chain_addr_to_str(l_add_addr));
+                    ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH;
+                    goto ret_n_clear;
+                }
+            }
+            l_new_tx_recv_allow = l_new_tx_recv_allow
+                    ? DAP_REALLOC(l_new_tx_recv_allow, (l_new_tx_recv_allow_size + 1) * sizeof(dap_chain_addr_t))
+                    : DAP_NEW_Z(dap_chain_addr_t);
+            if (!l_new_tx_recv_allow) {
+                log_it(L_CRITICAL, c_error_memory_alloc);
+                ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                goto ret_n_clear;
+            }
+            l_new_tx_recv_allow[l_new_tx_recv_allow_size++] = *l_add_addr;
+        } break;
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE: {
+            if (l_tsd->size != sizeof(dap_chain_addr_t)) {
+                log_it(L_WARNING, "Wrong TX_RECEIVER_ALLOWED_REMOVE TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            // Check if its correct
+            dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+            if (dap_chain_addr_check_sum(l_add_addr)) {
+                log_it(L_WARNING, "Wrong address checksum in TSD param TX_RECEIVER_ALLOWED_REMOVE");
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR;
+                goto ret_n_clear;
+            }
+            if (!l_new_tx_recv_allow && l_new_tx_recv_allow_size && !l_was_tx_recv_allow_copied) {
+                assert(a_item_apply_to->tx_recv_allow);
+                // Deep copy addrs to sandbox
+                l_new_tx_recv_allow = DAP_DUP_SIZE(a_item_apply_to->tx_recv_allow, l_new_tx_recv_allow_size * sizeof(dap_chain_addr_t));
+                if (!l_new_tx_recv_allow) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
+                }
+            }
+            l_was_tx_recv_allow_copied = true;
+            // Check if its already present
+            size_t i = 0;
+            for ( ; i < l_new_tx_recv_allow_size; i++) // Check for all the list
+                if (dap_chain_addr_compare(l_new_tx_recv_allow + i, l_add_addr))
                     break;
+            if (i == l_new_tx_recv_allow_size) {
+                log_it(L_WARNING, "TSD param TX_RECEIVER_ALLOWED_REMOVE has address %s thats not present in list",
+                        dap_chain_addr_to_str(l_add_addr));
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH;
+                goto ret_n_clear;
+            }
+            // Addr removing
+            if (--l_new_tx_recv_allow_size > i)
+                memmove(l_new_tx_recv_allow + i, l_new_tx_recv_allow + i + 1,
+                        (l_new_tx_recv_allow_size - i - 1) * sizeof(dap_chain_addr_t));
+            // Memory clearing
+            if (l_new_tx_recv_allow_size)
+                l_new_tx_recv_allow = DAP_REALLOC(l_new_tx_recv_allow,
+                                                          l_new_tx_recv_allow_size * sizeof(dap_chain_addr_t));
+            else
+                DAP_DEL_Z(l_new_tx_recv_allow);
+        } break;
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_CLEAR: {
+            if (l_tsd->size != 0) {
+                log_it(L_WARNING, "Wrong TX_RECEIVER_ALLOWED_CLEAR TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            DAP_DEL_Z(l_new_tx_recv_allow);
+            l_new_tx_recv_allow_size = 0;
+            l_was_tx_recv_block_copied = true;
+        } break;
+
+        // Blocked tx receiver addres list add, remove or clear
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD: {
+            if (l_tsd->size != sizeof(dap_chain_addr_t)) {
+                log_it(L_WARNING, "Wrong TX_RECEIVER_BLOCKED_ADD TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            // Check if its correct
+            dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+            if (dap_chain_addr_check_sum(l_add_addr)) {
+                log_it(L_WARNING, "Wrong address checksum in TSD param TX_RECEIVER_BLOCKED_ADD");
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR;
+                goto ret_n_clear;
+            }
+            if (!l_new_tx_recv_block && l_new_tx_recv_block_size && !l_was_tx_recv_block_copied) {
+                assert(a_item_apply_to->tx_recv_block);
+                // Deep copy addrs to sandbox
+                l_new_tx_recv_block = DAP_DUP_SIZE(a_item_apply_to->tx_recv_block, l_new_tx_recv_block_size * sizeof(dap_chain_addr_t));
+                if (!l_new_tx_recv_block) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
                 }
             }
-            if (!accepted) {
-                if (s_debug_more) {
-                    char *l_hash_str = dap_hash_fast_to_str_new(&l_hash);
-                    log_it(L_ERROR,
-                           "It is expected that the TSD parameter DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE will contain only "
-                           "the hashes of the public keys of the signatures with which the given token was previously signed. But not %s",
-                           l_hash_str);
-                    DAP_DELETE(l_hash_str);
+            l_was_tx_recv_block_copied = true;
+            // Check if its already present
+            for (size_t i = 0; i < l_new_tx_recv_block_size; i++) { // Check for all the list
+                if (dap_chain_addr_compare(l_new_tx_recv_block + i, l_add_addr)) { // Found
+                    log_it(L_WARNING, "TSD param TX_RECEIVER_BLOCKED_ADD has address %s thats already present in list",
+                                                                    dap_chain_addr_to_str(l_add_addr));
+                    ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH;
+                    goto ret_n_clear;
                 }
             }
-            isAccepted = accepted;
-        }
-    }
-    if (!isAccepted) {
-        dap_list_free(l_tsd_list_added_pkeys);
-        dap_list_free(l_tsd_list_remote_pkeys);
-        return false;
-    }
-    //Check added signs
-    dap_chain_datum_token_t *l_token_tmp = DAP_DUP_SIZE(a_token_update, a_token_update_size);
-    if (!l_token_tmp) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        dap_list_free(l_tsd_list_added_pkeys);
-        dap_list_free(l_tsd_list_remote_pkeys);
-        return false;
-    }
+            l_new_tx_recv_block = l_new_tx_recv_block
+                    ? DAP_REALLOC(l_new_tx_recv_block, (l_new_tx_recv_block_size + 1) * sizeof(dap_chain_addr_t))
+                    : DAP_NEW_Z(dap_chain_addr_t);
+            if (!l_new_tx_recv_block) {
+                log_it(L_CRITICAL, c_error_memory_alloc);
+                ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                goto ret_n_clear;
+            }
+            l_new_tx_recv_block[l_new_tx_recv_block_size++] = *l_add_addr;
+        } break;
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE: {
+            if (l_tsd->size != sizeof(dap_chain_addr_t)) {
+                log_it(L_WARNING, "Wrong TX_RECEIVER_BLOCKED_REMOVE TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            // Check if its correct
+            dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+            if (dap_chain_addr_check_sum(l_add_addr)) {
+                log_it(L_WARNING, "Wrong address checksum in TSD param TX_RECEIVER_BLOCKED_REMOVE");
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR;
+                goto ret_n_clear;
+            }
+            if (!l_new_tx_recv_block && l_new_tx_recv_block_size && !l_was_tx_recv_block_copied) {
+                assert(a_item_apply_to->tx_recv_block);
+                // Deep copy addrs to sandbox
+                l_new_tx_recv_block = DAP_DUP_SIZE(a_item_apply_to->tx_recv_block, l_new_tx_recv_block_size * sizeof(dap_chain_addr_t));
+                if (!l_new_tx_recv_block) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
+                }
+            }
+            l_was_tx_recv_block_copied = true;
+            // Check if its already present
+            size_t i = 0;
+            for ( ; i < l_new_tx_recv_block_size; i++) // Check for all the list
+                if (dap_chain_addr_compare(l_new_tx_recv_block + i, l_add_addr))
+                    break;
+            if (i == l_new_tx_recv_block_size) {
+                log_it(L_WARNING, "TSD param TX_RECEIVER_BLOCKED_REMOVE has address %s thats not present in list",
+                        dap_chain_addr_to_str(l_add_addr));
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH;
+                goto ret_n_clear;
+            }
+            // Addr removing
+            if (--l_new_tx_recv_block_size > i)
+                memmove(l_new_tx_recv_block + i, l_new_tx_recv_block + i + 1,
+                        (l_new_tx_recv_block_size - i - 1) * sizeof(dap_chain_addr_t));
+            // Memory clearing
+            if (l_new_tx_recv_block_size)
+                l_new_tx_recv_block = DAP_REALLOC(l_new_tx_recv_block,
+                                                          l_new_tx_recv_block_size * sizeof(dap_chain_addr_t));
+            else
+                DAP_DEL_Z(l_new_tx_recv_block);
+        } break;
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_CLEAR: {
+            if (l_tsd->size != 0) {
+                log_it(L_WARNING, "Wrong TX_RECEIVER_BLOCKED_CLEAR TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            DAP_DEL_Z(l_new_tx_recv_block);
+            l_new_tx_recv_block_size = 0;
+            l_was_tx_recv_block_copied = true;
+        } break;
+
+        // Blocked tx sender addres list add, remove or clear
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD: {
+            if (l_tsd->size != sizeof(dap_chain_addr_t)) {
+                log_it(L_WARNING, "Wrong TX_SENDER_ALLOWED_ADD TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            // Check if its correct
+            dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+            if (dap_chain_addr_check_sum(l_add_addr)) {
+                log_it(L_WARNING, "Wrong address checksum in TSD param TX_SENDER_ALLOWED_ADD");
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR;
+                goto ret_n_clear;
+            }
+            if (!l_new_tx_send_allow && l_new_tx_send_allow_size && !l_was_tx_send_allow_copied) {
+                assert(a_item_apply_to->tx_send_allow);
+                // Deep copy addrs to sandbox
+                l_new_tx_send_allow = DAP_DUP_SIZE(a_item_apply_to->tx_send_allow, l_new_tx_send_allow_size * sizeof(dap_chain_addr_t));
+                if (!l_new_tx_send_allow) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
+                }
+            }
+            l_was_tx_send_allow_copied = true;
+            // Check if its already present
+            for (size_t i = 0; i < l_new_tx_send_allow_size; i++) { // Check for all the list
+                if (dap_chain_addr_compare(l_new_tx_send_allow + i, l_add_addr)) { // Found
+                    log_it(L_WARNING, "TSD param TX_SENDER_ALLOWED_ADD has address %s thats already present in list",
+                                                                    dap_chain_addr_to_str(l_add_addr));
+                    ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH;
+                    goto ret_n_clear;
+                }
+            }
+            l_new_tx_send_allow = l_new_tx_send_allow
+                    ? DAP_REALLOC(l_new_tx_send_allow, (l_new_tx_send_allow_size + 1) * sizeof(dap_chain_addr_t))
+                    : DAP_NEW_Z(dap_chain_addr_t);
+            if (!l_new_tx_send_allow) {
+                log_it(L_CRITICAL, c_error_memory_alloc);
+                ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                goto ret_n_clear;
+            }
+            l_new_tx_send_allow[l_new_tx_send_allow_size++] = *l_add_addr;
+        } break;
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE: {
+            if (l_tsd->size != sizeof(dap_chain_addr_t)) {
+                log_it(L_WARNING, "Wrong TX_SENDER_ALLOWED_REMOVE TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            // Check if its correct
+            dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+            if (dap_chain_addr_check_sum(l_add_addr)) {
+                log_it(L_WARNING, "Wrong address checksum in TSD param TX_SENDER_ALLOWED_REMOVE");
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR;
+                goto ret_n_clear;
+
+            }
+            if (!l_new_tx_send_allow && l_new_tx_send_allow_size && !l_was_tx_send_allow_copied) {
+                assert(a_item_apply_to->tx_send_allow);
+                // Deep copy addrs to sandbox
+                l_new_tx_send_allow = DAP_DUP_SIZE(a_item_apply_to->tx_send_allow, l_new_tx_send_allow_size * sizeof(dap_chain_addr_t));
+                if (!l_new_tx_send_allow) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
+                }
+            }
+            l_was_tx_send_allow_copied = true;
+            // Check if its already present
+            size_t i = 0;
+            for ( ; i < l_new_tx_send_allow_size; i++) // Check for all the list
+                if (dap_chain_addr_compare(l_new_tx_send_allow + i, l_add_addr))
+                    break;
+            if (i == l_new_tx_send_allow_size) {
+                log_it(L_WARNING, "TSD param TX_SENDER_ALLOWED_REMOVE has address %s thats not present in list",
+                        dap_chain_addr_to_str(l_add_addr));
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH;
+                goto ret_n_clear;
+            }
+            // Addr removing
+            if (--l_new_tx_send_allow_size > i)
+                memmove(l_new_tx_send_allow + i, l_new_tx_send_allow + i + 1,
+                        (l_new_tx_send_allow_size - i - 1) * sizeof(dap_chain_addr_t));
+            // Memory clearing
+            if (l_new_tx_send_allow_size)
+                l_new_tx_send_allow = DAP_REALLOC(l_new_tx_send_allow,
+                                                          l_new_tx_send_allow_size * sizeof(dap_chain_addr_t));
+            else
+                DAP_DEL_Z(l_new_tx_send_allow);
+        } break;
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_CLEAR: {
+            if (l_tsd->size != 0) {
+                log_it(L_WARNING, "Wrong TX_SENDER_ALLOWED_CLEAR TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            DAP_DEL_Z(l_new_tx_send_allow);
+            l_new_tx_send_allow_size = 0;
+            l_was_tx_send_allow_copied = true;
+        } break;
 
-    l_token_tmp->header_native_update.tsd_total_size = 0;
-    isAccepted = true;
-    for (dap_list_t *l_ptr = l_tsd_list_added_pkeys; l_ptr; l_ptr = dap_list_next(l_ptr)) {
-        dap_tsd_t *l_tsd = (dap_tsd_t*)l_ptr->data;
-        if (l_tsd->size >= sizeof(dap_pkey_t)) {
-            dap_pkey_t *l_pkey = (dap_pkey_t *) l_tsd->data;
-            dap_hash_fast_t l_hf_pkey = {0};
-            if (!dap_pkey_get_hash(l_pkey, &l_hf_pkey)) {
-                if (s_debug_more)
-                    log_it(L_ERROR, "Failed to calculate the hash for the public key located in the "
-                                    "DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD section of the TSD");
-                isAccepted = false;
+        // Blocked tx sender addres list add, remove or clear
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD: {
+            if (l_tsd->size != sizeof(dap_chain_addr_t)) {
+                log_it(L_WARNING, "Wrong TX_SENDER_BLOCKED_ADD TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            // Check if its correct
+            dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+            if (dap_chain_addr_check_sum(l_add_addr)) {
+                log_it(L_WARNING, "Wrong address checksum in TSD param TX_SENDER_BLOCKED_ADD");
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR;
+                goto ret_n_clear;
+            }
+            if (!l_new_tx_send_block && l_new_tx_send_block_size && !l_was_tx_send_block_copied) {
+                assert(a_item_apply_to->tx_send_block);
+                // Deep copy addrs to sandbox
+                l_new_tx_send_block = DAP_DUP_SIZE(a_item_apply_to->tx_send_block, l_new_tx_send_block_size * sizeof(dap_chain_addr_t));
+                if (!l_new_tx_send_block) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
+                }
+            }
+            l_was_tx_send_block_copied = true;
+            // Check if its already present
+            for (size_t i = 0; i < l_new_tx_send_block_size; i++) { // Check for all the list
+                if (dap_chain_addr_compare(l_new_tx_send_block + i, l_add_addr)) { // Found
+                    log_it(L_WARNING, "TSD param TX_SENDER_BLOCKED_ADD has address %s thats already present in list",
+                                                                    dap_chain_addr_to_str(l_add_addr));
+                    ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH;
+                    goto ret_n_clear;
+                }
+            }
+            if (!a_apply)
                 break;
+            l_new_tx_send_block = l_new_tx_send_block
+                    ? DAP_REALLOC(l_new_tx_send_block, (l_new_tx_send_block_size + 1) * sizeof(dap_chain_addr_t))
+                    : DAP_NEW_Z(dap_chain_addr_t);
+            if (!l_new_tx_send_block) {
+                log_it(L_CRITICAL, c_error_memory_alloc);
+                ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                goto ret_n_clear;
             }
-            for (size_t i = 0; i < a_cur_token_item->auth_signs_total; i++) {
-                if (dap_hash_fast_compare(&l_hf_pkey, &a_cur_token_item->auth_pkeys_hash[i])) {
-                    if (s_debug_more) {
-                        char *l_hf_str = dap_hash_fast_to_str_new(&l_hf_pkey);
-                        log_it(L_ERROR, "The public key with hash %s from the TSD section of the type "
-                                        "DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD cannot be added, because such "
-                                        "a key already exists in the ledger.", l_hf_str);
-                        DAP_DELETE(l_hf_str);
-                    }
-                    isAccepted = false;
+            l_new_tx_send_block[l_new_tx_send_block_size++] = *l_add_addr;
+        } break;
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE: {
+            if (l_tsd->size != sizeof(dap_chain_addr_t)) {
+                log_it(L_WARNING, "Wrong TX_SENDER_BLOCKED_REMOVE TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            // Check if its correct
+            dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t);
+            if (dap_chain_addr_check_sum(l_add_addr)) {
+                log_it(L_WARNING, "Wrong address checksum in TSD param TX_SENDER_BLOCKED_REMOVE");
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR;
+                goto ret_n_clear;
+            }
+            if (!l_new_tx_send_block && l_new_tx_send_block_size && !l_was_tx_send_block_copied) {
+                assert(a_item_apply_to->tx_send_block);
+                // Deep copy addrs to sandbox
+                l_new_tx_send_block = DAP_DUP_SIZE(a_item_apply_to->tx_send_block, l_new_tx_send_block_size * sizeof(dap_chain_addr_t));
+                if (!l_new_tx_send_block) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
+                }
+            }
+            l_was_tx_send_block_copied = true;
+            // Check if its already present
+            size_t i = 0;
+            for ( ; i < l_new_tx_send_block_size; i++) // Check for all the list
+                if (dap_chain_addr_compare(l_new_tx_send_block + i, l_add_addr))
                     break;
+            if (i == l_new_tx_send_block_size) {
+                log_it(L_WARNING, "TSD param TX_SENDER_BLOCKED_REMOVE has address %s thats not present in list",
+                        dap_chain_addr_to_str(l_add_addr));
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH;
+                goto ret_n_clear;
+            }
+            // Addr removing
+            if (--l_new_tx_send_block_size > i)
+                memmove(l_new_tx_send_block + i, l_new_tx_send_block + i + 1,
+                        (l_new_tx_send_block_size - i - 1) * sizeof(dap_chain_addr_t));
+            // Memory clearing
+            if (l_new_tx_send_block_size)
+                l_new_tx_send_block = DAP_REALLOC(l_new_tx_send_block,
+                                                          l_new_tx_send_block_size * sizeof(dap_chain_addr_t));
+            else
+                DAP_DEL_Z(l_new_tx_send_block);
+        } break;
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_CLEAR: {
+            if (l_tsd->size != 0) {
+                log_it(L_WARNING, "Wrong TX_SENDER_BLOCKED_CLEAR TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            DAP_DEL_Z(l_new_tx_send_block);
+            l_new_tx_send_block_size = 0;
+            l_was_tx_send_block_copied = true;
+        } break;
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION: {
+            if (l_tsd->size == 0 || l_tsd->data[l_tsd->size - 1] != 0) {
+                log_it(L_ERROR, "Wrong TOKEN_DESCRIPTION TSD format or size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            if (!a_apply)
+                break;
+            DAP_DEL_Z(a_item_apply_to->description);
+            a_item_apply_to->description = strdup((char *)l_tsd->data);
+        } break;
+
+        // Set signs count value need to emission be valid
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID: {
+            if (l_tsd->size != sizeof(uint16_t)) {
+                log_it(L_WARNING, "Wrong SIGNS_VALID TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            l_new_signs_valid = dap_tsd_get_scalar(l_tsd, uint16_t);
+        } break;
+
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD: {
+            if (l_tsd->size < sizeof(dap_pkey_t) || l_tsd->size != dap_pkey_get_size((dap_pkey_t *)l_tsd->data)) {
+                log_it(L_WARNING, "Wrong TOTAL_PKEYS_ADD TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            if (!l_new_pkeys && l_new_signs_total && !l_was_pkeys_copied) {
+                assert(a_item_apply_to->auth_pkeys);
+                assert(a_item_apply_to->auth_pkey_hashes);
+                // Deep copy pkeys & its hashes to sandbox
+                l_new_pkeys = DAP_NEW_SIZE(dap_pkey_t *, l_new_signs_total * sizeof(dap_pkey_t *));
+                if (!l_new_pkeys) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
+                }
+                for (size_t i = 0; i < l_new_signs_total; i++) {
+                    l_new_pkeys[i] = DAP_DUP_SIZE(a_item_apply_to->auth_pkeys[i], dap_pkey_get_size(a_item_apply_to->auth_pkeys[i]));
+                    if (!l_new_pkeys[i]) {
+                        log_it(L_CRITICAL, c_error_memory_alloc);
+                        ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                        goto ret_n_clear;
+                    }
+                }
+                assert(!l_new_pkey_hashes);
+                l_new_pkey_hashes = DAP_DUP_SIZE(a_item_apply_to->auth_pkey_hashes, l_new_signs_total * sizeof(dap_hash_t));
+                if (!l_new_pkey_hashes) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
                 }
             }
-        } else {
-            if (s_debug_more)
-                log_it(L_ERROR, "It is expected that the size %zu of information from the TSD section of type "
-                                "DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD will be greater than or equal to %zu.",
-                       dap_tsd_size(l_tsd), sizeof(dap_pkey_t));
-            isAccepted = false;
-            break;
-        }
-    }
-    dap_list_free(l_tsd_list_added_pkeys);
-    dap_list_free(l_tsd_list_remote_pkeys);
-    DAP_DELETE(l_token_tmp);
-    return isAccepted;
-}
+            l_was_pkeys_copied = true;
+            dap_pkey_t *l_new_auth_pkey = dap_tsd_get_object(l_tsd, dap_pkey_t);
+            dap_pkey_type_t l_pkey_type_correction = { .type = DAP_PKEY_TYPE_NULL };
+            if (dap_pkey_type_to_enc_key_type(l_new_auth_pkey->header.type) == DAP_ENC_KEY_TYPE_INVALID) {
+                dap_sign_type_t l_sign_type = { .type = l_new_auth_pkey->header.type.type }; // Legacy cratch
+                l_pkey_type_correction = dap_pkey_type_from_sign_type(l_sign_type);
+                if (l_pkey_type_correction.type == DAP_PKEY_TYPE_NULL) {
+                    log_it(L_WARNING, "Unknonw public key type %hu", l_new_auth_pkey->header.type.type);
+                    ret = DAP_LEDGER_CHECK_PARSE_ERROR;
+                    goto ret_n_clear;
+                }
+            }
+            // Check if its already present
+            dap_hash_t l_new_auth_pkey_hash;
+            dap_pkey_get_hash(l_new_auth_pkey, &l_new_auth_pkey_hash);
+            for (size_t i = 0; i < l_new_signs_total; i++) {
+                if (dap_pkey_compare(l_new_auth_pkey, l_new_pkeys[i])) {
+                    log_it(L_WARNING, "TSD param TOTAL_PKEYS_ADD has pkey %s thats already present in list",
+                                                                    dap_hash_fast_to_str_static(&l_new_auth_pkey_hash));
+                    ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_PKEY_MISMATCH;
+                    goto ret_n_clear;
+                }
+            }
+            l_new_pkeys = l_new_pkeys ? DAP_REALLOC(l_new_pkeys, (l_new_signs_total + 1) * sizeof(dap_pkey_t *))
+                                      : DAP_NEW_Z(dap_pkey_t *);
+            if (!l_new_pkeys) {
+                log_it(L_CRITICAL, c_error_memory_alloc);
+                ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                goto ret_n_clear;
+            }
+            // Pkey adding
+            l_new_pkeys[l_new_signs_total] = DAP_DUP_SIZE(l_new_auth_pkey, dap_pkey_get_size(l_new_auth_pkey));
+            if (!l_new_pkeys[l_new_signs_total]) {
+                log_it(L_CRITICAL, c_error_memory_alloc);
+                ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                goto ret_n_clear;
+            }
+            if (l_pkey_type_correction.type != DAP_PKEY_TYPE_NULL)
+                l_new_pkeys[l_new_signs_total]->header.type = l_pkey_type_correction;
+
+            l_new_pkey_hashes = l_new_pkey_hashes ? DAP_REALLOC(l_new_pkey_hashes, (l_new_signs_total + 1) * sizeof(dap_hash_t))
+                                                  : DAP_NEW_Z(dap_hash_t);
+            if (!l_new_pkey_hashes) {
+                log_it(L_CRITICAL, c_error_memory_alloc);
+                ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                goto ret_n_clear;
+            }
+            l_new_pkey_hashes[l_new_signs_total++] = l_new_auth_pkey_hash;
+        } break;
 
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE: {
+            if (l_tsd->size != sizeof(dap_hash_t)) {
+                log_it(L_WARNING, "Wrong TOTAL_PKEYS_REMOVE TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            if (!l_new_pkeys && l_new_signs_total && !l_was_pkeys_copied) {
+                assert(a_item_apply_to->auth_pkeys);
+                assert(a_item_apply_to->auth_pkey_hashes);
+                // Deep copy pkeys & its hashes to sandbox
+                l_new_pkeys = DAP_NEW_SIZE(dap_pkey_t *, l_new_signs_total * sizeof(dap_pkey_t *));
+                if (!l_new_pkeys) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
+                }
+                for (size_t i = 0; i < l_new_signs_total; i++) {
+                    l_new_pkeys[i] = DAP_DUP_SIZE(a_item_apply_to->auth_pkeys[i], dap_pkey_get_size(a_item_apply_to->auth_pkeys[i]));
+                    if (!l_new_pkeys[i]) {
+                        log_it(L_CRITICAL, c_error_memory_alloc);
+                        ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                        goto ret_n_clear;
+                    }
+                }
+                assert(!l_new_pkey_hashes);
+                l_new_pkey_hashes = DAP_DUP_SIZE(a_item_apply_to->auth_pkey_hashes, l_new_signs_total * sizeof(dap_hash_t));
+                if (!l_new_pkey_hashes) {
+                    log_it(L_CRITICAL, c_error_memory_alloc);
+                    ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+                    goto ret_n_clear;
+                }
+            }
+            l_was_pkeys_copied = true;
+            dap_hash_t l_new_auth_pkey_hash = dap_tsd_get_scalar(l_tsd, dap_hash_t);
+            // Check if its already present
+            size_t i = 0;
+            for ( ; i < l_new_signs_total; i++) // Check for all the list
+                if (dap_hash_fast_compare(l_new_pkey_hashes + i, &l_new_auth_pkey_hash))
+                    break;
+            if (i == l_new_signs_total) {
+                log_it(L_WARNING, "TSD param TOTAL_PKEYS_REMOVE has public key hash %s thats not present in list",
+                                                    dap_hash_fast_to_str_static(&l_new_auth_pkey_hash));
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_PKEY_MISMATCH;
+                goto ret_n_clear;
+            }
+            // Pkey removing
+            DAP_DELETE(l_new_pkeys[i]);
+            if (--l_new_signs_total > i) {
+                memmove(l_new_pkeys + i, l_new_pkeys + i + 1, (l_new_signs_total - i - 1) * sizeof(dap_pkey_t *));
+                memmove(l_new_pkey_hashes + i, l_new_pkey_hashes + i + 1, (l_new_signs_total - i - 1) * sizeof(dap_hash_t));
+            }
+            // Memory clearing
+            if (l_new_signs_total) {
+                l_new_pkeys = DAP_REALLOC(l_new_pkeys, l_new_signs_total * sizeof(dap_pkey_t *));
+                l_new_pkey_hashes = DAP_REALLOC(l_new_pkey_hashes, l_new_signs_total * sizeof(dap_hash_t));
+            } else
+                DAP_DEL_MULTY(l_new_pkeys, l_new_pkey_hashes);
+        } break;
 
-inline static dap_ledger_token_item_t *s_ledger_find_token(dap_ledger_t *a_ledger, const char *a_token_ticker)
-{
-    dap_ledger_token_item_t *l_token_item;
-    pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
-    HASH_FIND_STR(PVT(a_ledger)->tokens, a_token_ticker, l_token_item);
-    pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
-    return l_token_item;
+        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK: {
+            if (a_current_datum->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE) {
+                log_it(L_WARNING, "TSD section DELEGATE_EMISSION_FROM_STAKE_LOCK allowed for NATIVE subtype only");
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_FORBIDDEN;
+                goto ret_n_clear;
+            }
+            if (l_tsd->size != sizeof(dap_chain_datum_token_tsd_delegate_from_stake_lock_t) &&
+                    l_tsd->size != sizeof(dap_chain_datum_token_tsd_delegate_from_stake_lock_t) + 256 /* Legacy size */) {
+                log_it(L_WARNING, "Wrong DELEGATE_EMISSION_FROM_STAKE_LOCK TSD size %zu, exiting TSD parse", l_tsd_size);
+                ret = DAP_LEDGER_CHECK_INVALID_SIZE;
+                goto ret_n_clear;
+            }
+            dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_delegate = dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
+            const char *l_basic_token_ticker = (const char *)l_delegate->ticker_token_from;
+            char l_delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
+            dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker, l_basic_token_ticker);
+            if (dap_strcmp(l_delegated_ticker, a_current_datum->ticker)) {
+                log_it(L_WARNING, "Unexpected delegated token ticker %s (expected %s)", a_current_datum->ticker, l_delegated_ticker);
+                ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_OTHER_TICKER_EXPECTED;
+                goto ret_n_clear;
+            }
+            dap_ledger_token_item_t *l_basic_token = NULL;
+            HASH_FIND_STR(PVT(a_ledger)->tokens, l_basic_token_ticker, l_basic_token);
+            if (!l_basic_token) {
+                log_it(L_WARNING, "Basic token ticker %s for delegated token isn't found", l_basic_token_ticker);
+                ret = DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
+                goto ret_n_clear;
+            }
+            if (IS_ZERO_256(l_delegate->emission_rate)) {
+                log_it(L_WARNING, "Emission rate for delegated toke should not be a zero");
+                ret = DAP_LEDGER_CHECK_ZERO_VALUE;
+                goto ret_n_clear;
+            }
+            if (!a_apply)
+                break;
+            assert(a_item_apply_to);
+            a_item_apply_to->is_delegated = true;
+            strcpy(a_item_apply_to->delegated_from, l_basic_token->ticker);
+            a_item_apply_to->emission_rate = l_delegate->emission_rate;
+        } break;
+
+        default:
+            log_it(L_ERROR, "Unexpected TSD type %hu", l_tsd->type);
+            ret = DAP_LEDGER_CHECK_PARSE_ERROR;
+            goto ret_n_clear;
+        }
+    }
+    if (l_new_signs_total < l_new_signs_valid) {
+        ret = DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS;
+        goto ret_n_clear;
+    }
+    if (a_apply) {
+        if (l_was_tx_recv_allow_copied) {
+            a_item_apply_to->tx_recv_allow_size = l_new_tx_recv_allow_size;
+            DAP_DEL_Z(a_item_apply_to->tx_recv_allow);
+            a_item_apply_to->tx_recv_allow = l_new_tx_recv_allow;
+        }
+        if (l_was_tx_recv_block_copied) {
+            a_item_apply_to->tx_recv_block_size = l_new_tx_recv_block_size;
+            DAP_DEL_Z(a_item_apply_to->tx_recv_block);
+            a_item_apply_to->tx_recv_block = l_new_tx_recv_block;
+        }
+        if (l_was_tx_send_allow_copied) {
+            a_item_apply_to->tx_send_allow_size = l_new_tx_send_allow_size;
+            DAP_DEL_Z(a_item_apply_to->tx_send_allow);
+            a_item_apply_to->tx_send_allow = l_new_tx_send_allow;
+        }
+        if (l_was_tx_send_block_copied) {
+            a_item_apply_to->tx_send_block_size = l_new_tx_send_block_size;
+            DAP_DEL_Z(a_item_apply_to->tx_send_block);
+            a_item_apply_to->tx_send_block = l_new_tx_send_block;
+        }
+        a_item_apply_to->auth_signs_valid = l_new_signs_valid;
+        if (l_was_pkeys_copied) {
+            for (size_t i = 0; i < a_item_apply_to->auth_signs_total; i++)
+                DAP_DELETE(a_item_apply_to->auth_pkeys[i]);
+            DAP_DEL_Z(a_item_apply_to->auth_pkeys);
+            DAP_DEL_Z(a_item_apply_to->auth_pkey_hashes);
+            a_item_apply_to->auth_signs_total = l_new_signs_total;
+            a_item_apply_to->auth_pkeys = l_new_pkeys;
+            a_item_apply_to->auth_pkey_hashes = l_new_pkey_hashes;
+        }
+        return DAP_LEDGER_CHECK_OK;
+    }
+    // Checks passed
+ret_n_clear:
+    if (l_new_pkeys)
+        for (size_t i = 0; i < l_new_signs_total; i++)
+            DAP_DELETE(l_new_pkeys[i]);
+    DAP_DEL_MULTY(l_new_tx_recv_allow, l_new_tx_recv_block, l_new_tx_send_allow, l_new_tx_send_block, l_new_pkeys, l_new_pkey_hashes);
+    return ret;
 }
 
 /**
@@ -882,76 +1352,221 @@ inline static dap_ledger_token_item_t *s_ledger_find_token(dap_ledger_t *a_ledge
  * @param a_token_size
  * @return
  */
-int dap_ledger_token_decl_add_check(dap_ledger_t *a_ledger, dap_chain_datum_token_t *a_token, size_t a_token_size)
+int s_token_add_check(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_size,
+                      dap_ledger_token_item_t **a_token_item, dap_chain_datum_token_t **a_token_out,
+                      size_t *a_tsd_total_size, size_t *a_signs_size,
+                      dap_hash_fast_t *a_token_update_hash)
 {
-    if ( !a_ledger){
-        if(s_debug_more)
-            log_it(L_ERROR, "NULL ledger, can't add datum with token declaration!");
-        return  DAP_LEDGER_TOKEN_DECL_ADD_ERR_LEDGER_IS_NULL;
+    size_t l_token_size = a_token_size;
+    dap_chain_datum_token_t *l_token = dap_chain_datum_token_read(a_token, &l_token_size);
+    if (!l_token)
+        return DAP_LEDGER_CHECK_INVALID_SIZE;
+    if (l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE && l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_DECL) {
+        log_it(L_WARNING, "Unknown token type %hu", l_token->type);
+        DAP_DELETE(l_token);
+        return DAP_LEDGER_CHECK_PARSE_ERROR;
     }
-
-    bool l_update_token = a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE;
-    dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, a_token->ticker);
-    if	(l_token_item != NULL) {
+    if (!l_token->ticker[0] || l_token->ticker[DAP_CHAIN_TICKER_SIZE_MAX - 1]) {
+        log_it(L_WARNING, "Unreadable token ticker");
+        DAP_DELETE(l_token);
+        return DAP_LEDGER_CHECK_PARSE_ERROR;
+    }
+    char *ptr = l_token->ticker;
+    while (*ptr) {
+        if (!dap_ascii_isalnum(*ptr++)) {
+            log_it(L_WARNING, "Token ticker is not alpha-numeric");
+            DAP_DELETE(l_token);
+            return DAP_LEDGER_CHECK_PARSE_ERROR;
+        }
+    }
+    if (!l_token->signs_total) {
+        log_it(L_WARNING, "No auth signs in token '%s' datum!", l_token->ticker);
+        DAP_DELETE(l_token);
+        return DAP_LEDGER_TOKEN_ADD_CHECK_NOT_ENOUGH_UNIQUE_SIGNS;
+    }
+    bool l_update_token = l_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE;
+    dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, l_token->ticker);
+    dap_hash_fast_t l_token_update_hash = {};
+    if (l_token_item) {
         if (!l_update_token) {
-            log_it(L_WARNING, "Duplicate token declaration for ticker '%s'", a_token->ticker);
-            return DAP_LEDGER_TOKEN_DECL_ADD_ERR_DECL_DUPLICATE;
-        } else if (!s_ledger_token_update_check(l_token_item, a_token, a_token_size))
-            return DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_CHECK;
-    } else if (!l_token_item && l_update_token) {
-        log_it(L_WARNING, "Can't update token that doesn't exist for ticker '%s'", a_token->ticker);
-        return DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_ABSENT_TOKEN;
+            log_it(L_WARNING, "Duplicate token declaration for ticker '%s'", l_token->ticker);
+            DAP_DELETE(l_token);
+            return DAP_LEDGER_CHECK_ALREADY_CACHED;
+        }
+        if (l_token->signs_total < l_token_item->auth_signs_valid) {
+            log_it(L_WARNING, "Datum token for ticker '%s' has only %hu signatures out of %zu",
+                                            l_token->ticker, l_token->signs_total, l_token_item->auth_signs_valid);
+            DAP_DELETE(l_token);
+            return DAP_LEDGER_TOKEN_ADD_CHECK_NOT_ENOUGH_UNIQUE_SIGNS;
+        }
+        dap_hash_fast(l_token, l_token_size, &l_token_update_hash);
+        dap_ledger_token_update_item_t *l_token_update_item;
+        pthread_rwlock_rdlock(&l_token_item->token_ts_updated_rwlock);
+        HASH_FIND(hh, l_token_item->token_ts_updated, &l_token_update_hash, sizeof(dap_hash_fast_t), l_token_update_item);
+        pthread_rwlock_unlock(&l_token_item->token_ts_updated_rwlock);
+        if (l_token_update_item) {
+            log_it(L_WARNING, "This update for token '%s' was already applied", l_token->ticker);
+            DAP_DELETE(l_token);
+            return DAP_LEDGER_CHECK_ALREADY_CACHED;
+        }
+        if (a_token_update_hash)
+            *a_token_update_hash = l_token_update_hash;
+    } else if (l_update_token) {
+        log_it(L_WARNING, "Can't update token that doesn't exist for ticker '%s'", l_token->ticker);
+        DAP_DELETE(l_token);
+        return DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
+    } else if (l_token->signs_total < l_token->signs_valid) {
+        log_it(L_WARNING, "Datum token for ticker '%s' has only %hu signatures out of %hu",
+                                            l_token->ticker, l_token->signs_total, l_token->signs_valid);
+        DAP_DELETE(l_token);
+        return DAP_LEDGER_TOKEN_ADD_CHECK_NOT_ENOUGH_UNIQUE_SIGNS;
     }
-    // Check signs
-    size_t l_signs_unique = 0;
+    // Check TSD
     size_t l_size_tsd_section = 0;
-    switch (a_token->type) {
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL: {
-            switch (a_token->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-                    l_size_tsd_section = a_token->header_private_decl.tsd_total_size; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-                    l_size_tsd_section = a_token->header_native_decl.tsd_total_size; break;
-            }
-        }break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE: {
-            switch (a_token->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-                    l_size_tsd_section = a_token->header_private_update.tsd_total_size; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-                    l_size_tsd_section = a_token->header_native_update.tsd_total_size; break;
-            }
-        } break;
-    }
-    size_t l_signs_size = a_token_size - sizeof(dap_chain_datum_token_t) - l_size_tsd_section;
-    dap_sign_t **l_signs = dap_sign_get_unique_signs(a_token->data_n_tsd + l_size_tsd_section, l_signs_size, &l_signs_unique);
-    if (l_signs_unique == a_token->signs_total){
-        size_t l_signs_approve = 0;
-        uint16_t l_tmp_auth_signs = a_token->signs_total;
-        if (a_token->version == 2) a_token->signs_total = 0;
-        for (size_t i=0; i < l_signs_unique; i++)
-            if (!dap_sign_verify_all(l_signs[i], l_signs_size, a_token, sizeof(dap_chain_datum_token_t)+l_size_tsd_section))
-                l_signs_approve++;
-        a_token->signs_total = l_tmp_auth_signs;
-        if (l_signs_approve == a_token->signs_total){
-            return DAP_LEDGER_TOKEN_DECL_ADD_OK;
-        } else {
-            log_it(L_WARNING, "The token declaration has %zu valid signatures out of %hu.", l_signs_approve, a_token->signs_total);
-            return DAP_LEDGER_TOKEN_DECL_ADD_ERR_NOT_ENOUGH_VALID_SIGN;
+    if (l_update_token) {
+        switch (l_token->subtype) {
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
+            l_size_tsd_section = l_token->header_private_decl.tsd_total_size; break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
+            l_size_tsd_section = l_token->header_native_decl.tsd_total_size; break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC:
+            break;
+        default:
+            /* Bogdanoff, unknown token subtype update. What shall we TODO? */
+            log_it(L_WARNING, "Unknown token subtype '0x%0hX' update! Ticker: %s, total_supply: %s, signs_valid: %hu, signs_total: %hu",
+                   l_token->type, l_token->ticker, dap_uint256_to_char(l_token->total_supply, NULL),
+                   l_token->signs_valid, l_token->signs_total);
+            /* Dump it right now */
+            DAP_DELETE(l_token);
+            return DAP_LEDGER_CHECK_PARSE_ERROR;
         }
     } else {
-        log_it(L_WARNING, "The number of unique token signs %zu is less than total token signs set to %hu.",
-               l_signs_unique, a_token->signs_total);
-        return DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOTAL_SIGNS_EXCEED_UNIQUE_SIGNS;
+        switch (l_token->subtype) {
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
+            l_size_tsd_section = l_token->header_private_update.tsd_total_size; break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
+            l_size_tsd_section = l_token->header_native_update.tsd_total_size; break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC:
+            break;
+        default:
+            /* Bogdanoff, unknown token subtype declaration. What shall we TODO? */
+            log_it(L_WARNING, "Unknown token subtype '0x%0hX' declaration! Ticker: %s, total_supply: %s, signs_valid: %hu, signs_total: %hu",
+                   l_token->type, l_token->ticker, dap_uint256_to_char(l_token->total_supply, NULL),
+                   l_token->signs_valid, l_token->signs_total);
+            /* Dump it right now */
+            DAP_DELETE(l_token);
+            return DAP_LEDGER_CHECK_PARSE_ERROR;
+        }
     }
-    // Checks passed
-    return DAP_LEDGER_TOKEN_DECL_ADD_OK;
+    if (l_token_size < sizeof(dap_chain_datum_token_t) + l_size_tsd_section) {
+        log_it(L_WARNING, "Incorrect size %zu of datum token, expected at least %zu", l_token_size,
+                                                sizeof(dap_chain_datum_token_t) + l_size_tsd_section);
+        DAP_DELETE(l_token);
+        return DAP_LEDGER_CHECK_INVALID_SIZE;
+    }
+    // Check signs
+    byte_t *l_signs_ptr = l_token->tsd_n_signs + l_size_tsd_section;
+    size_t l_signs_size = 0, l_signs_offset = sizeof(dap_chain_datum_token_t) + l_size_tsd_section;
+    for (uint16_t l_signs_passed = 0; l_signs_passed < l_token->signs_total; l_signs_passed++) {
+        dap_sign_t *l_sign = (dap_sign_t *)(l_signs_ptr + l_signs_size);
+        if (l_token_size < l_signs_offset + l_signs_size + sizeof(dap_sign_t)) {
+            log_it(L_WARNING, "Incorrect size %zu of datum token, expected at least %zu", l_token_size,
+                                                    l_signs_offset + l_signs_size + sizeof(dap_sign_t));
+            DAP_DELETE(l_token);
+            return DAP_LEDGER_CHECK_INVALID_SIZE;
+        }
+        l_signs_size += dap_sign_get_size(l_sign);
+    }
+    if (l_token_size != l_signs_offset + l_signs_size) {
+        log_it(L_WARNING, "Incorrect size %zu of datum token, expected %zu", l_token_size, l_signs_offset + l_signs_size);
+        DAP_DELETE(l_token);
+        return DAP_LEDGER_CHECK_INVALID_SIZE;
+    }
+    size_t l_signs_unique = l_token->signs_total;
+    dap_sign_t **l_signs = dap_sign_get_unique_signs(l_signs_ptr, l_signs_size, &l_signs_unique);
+    if (l_signs_unique != l_token->signs_total) {
+        DAP_DEL_Z(l_signs);
+        log_it(L_WARNING, "The number of unique token signs %zu is less than total token signs set to %hu",
+               l_signs_unique, l_token->signs_total);
+        DAP_DELETE(l_token);
+        return DAP_LEDGER_TOKEN_ADD_CHECK_NOT_ENOUGH_UNIQUE_SIGNS;
+    }
+    bool l_legacy_type = a_token_size != l_token_size;
+    size_t l_signs_approve = 0;
+    size_t l_verify_size = 0;
+    uint16_t l_tmp_auth_signs = 0;
+    if (l_legacy_type)
+        l_verify_size = sizeof(dap_chain_datum_token_old_t) - sizeof(uint16_t);
+    else {
+        l_verify_size = l_signs_offset;
+        l_tmp_auth_signs = l_token->signs_total;
+        l_token->signs_total = 0;
+    }
+    for (size_t i = 0; i < l_signs_unique; i++) {
+        if (!dap_sign_verify(l_signs[i], l_legacy_type ? a_token : (void *)l_token, l_verify_size)) {
+            if (l_update_token) {
+                for (size_t j = 0; j < l_token_item->auth_signs_total; j++) {
+                    if (dap_pkey_compare_with_sign(l_token_item->auth_pkeys[j], l_signs[i])) {
+                        l_signs_approve++;
+                        break;
+                    }
+                }
+            } else
+                l_signs_approve++;
+        }
+    }
+    DAP_DELETE(l_signs);
+    if (!l_legacy_type)
+        l_token->signs_total = l_tmp_auth_signs;
+    size_t l_signs_need = l_update_token ? l_token_item->auth_signs_valid : l_token->signs_total;
+    if (l_signs_approve < l_signs_need) {
+        log_it(L_WARNING, "Datum token for ticker '%s' has only %zu valid signatures out of %zu",
+                                                l_token->ticker, l_signs_approve, l_signs_need);
+        DAP_DELETE(l_token);
+        return DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS;
+    }
+    // Check content & size of enclosed TSD sections
+    pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
+    int ret = s_token_tsd_parse(l_token_item, l_token, a_ledger, l_token->tsd_n_signs, l_size_tsd_section, false);
+    pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+    dap_ledger_hal_item_t *l_hash_found = NULL;
+    if (ret != DAP_LEDGER_CHECK_OK) {
+        if (s_hal_items) {
+            dap_hash_fast_t l_token_hash;
+            if (!dap_hash_fast_is_blank(&l_token_update_hash))
+                l_token_hash = l_token_update_hash;
+            else
+                dap_hash_fast(a_token, a_token_size, &l_token_hash);
+            HASH_FIND(hh, s_hal_items, &l_token_hash, sizeof(dap_hash_fast_t), l_hash_found);
+            debug_if(s_debug_more && l_hash_found, L_MSG, "Datum %s is whitelisted", dap_hash_fast_to_str_static(&l_token_hash));
+        }
+        if (!l_hash_found) {
+            DAP_DELETE(l_token);
+            return ret;
+        }
+    }
+    if (a_token_item)
+        *a_token_item = l_token_item;
+    if (a_token_out)
+        *a_token_out = l_token;
+    else
+        DAP_DELETE(l_token);
+    if (a_tsd_total_size)
+        *a_tsd_total_size = l_size_tsd_section;
+    if (a_signs_size)
+        *a_signs_size = l_signs_size;
+    return l_hash_found ? DAP_LEDGER_CHECK_WHITELISTED : DAP_LEDGER_CHECK_OK;
 }
 
-char *dap_ledger_token_decl_add_err_code_to_str(int a_code) {
-    return (a_code >= DAP_LEDGER_TOKEN_DECL_ADD_OK) && (a_code < DAP_LEDGER_TOKEN_DECL_ADD_UNKNOWN)
-            ? (char*)s_ledger_token_decl_err_str[(dap_ledger_token_decl_add_err_t)a_code]
-            : dap_itoa(a_code);
+int dap_ledger_token_add_check(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_size)
+{
+    dap_return_val_if_fail(a_ledger && a_token && a_token_size, DAP_LEDGER_CHECK_INVALID_ARGS);
+    int ret = s_token_add_check(a_ledger, a_token, a_token_size, NULL, NULL, NULL, NULL, NULL);
+    if (ret == DAP_LEDGER_CHECK_WHITELISTED)
+        ret = DAP_LEDGER_CHECK_OK;
+    return ret;
 }
 
 /**
@@ -962,14 +1577,235 @@ char *dap_ledger_token_decl_add_err_code_to_str(int a_code) {
  */
 dap_chain_datum_token_t *dap_ledger_token_ticker_check(dap_ledger_t *a_ledger, const char *a_token_ticker)
 {
-    if (!a_ledger) {
-        debug_if(s_debug_more, L_WARNING, "NULL ledger, can't find token ticker");
-        return NULL;
-    }
+    dap_return_val_if_fail(a_ledger && a_token_ticker, NULL);
     dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, a_token_ticker);
     return l_token_item ? l_token_item->datum_token : NULL;
 }
 
+/**
+ * @brief update current_supply in token cache
+ *
+ * @param a_ledger ledger object
+ * @param l_token_item token item object
+ */
+void s_ledger_token_cache_update(dap_ledger_t *a_ledger, dap_ledger_token_item_t *l_token_item)
+{
+    if (!PVT(a_ledger)->cached)
+        return;
+    char *l_gdb_group = dap_ledger_get_gdb_group(a_ledger, DAP_LEDGER_TOKENS_STR);
+    size_t l_cache_size = l_token_item->datum_token_size + sizeof(uint256_t);
+    uint8_t *l_cache = DAP_NEW_STACK_SIZE(uint8_t, l_cache_size);
+    if ( !l_cache ) {
+        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+        return;
+    }
+    memcpy(l_cache, &l_token_item->current_supply, sizeof(uint256_t));
+    memcpy(l_cache + sizeof(uint256_t), l_token_item->datum_token, l_token_item->datum_token_size);
+    if (dap_global_db_set(l_gdb_group, l_token_item->ticker, l_cache, l_cache_size, false, NULL, NULL)) {
+        char *l_supply = dap_chain_balance_print(l_token_item->current_supply);
+        log_it(L_WARNING, "Ledger cache mismatch, can't add token [%s] with supply %s", l_token_item->ticker, l_supply);
+        DAP_DELETE(l_supply);
+    }
+    DAP_DELETE(l_gdb_group);
+}
+
+static bool s_ledger_token_supply_check(dap_ledger_token_item_t *a_token_item, uint256_t a_value)
+{
+    if ((IS_ZERO_256(a_token_item->total_supply) || IS_ZERO_256(a_value)))
+        return true;
+    if (compare256(a_token_item->current_supply, a_value) >= 0)
+        return true;
+    char *l_supply_str = dap_chain_balance_print(a_token_item->current_supply);
+    char *l_value_str = dap_chain_balance_print(a_value);
+    log_it(L_WARNING, "Token current supply %s < emission value %s", l_supply_str, l_value_str);
+    DAP_DEL_MULTY(l_supply_str, l_value_str);
+    return false;
+}
+
+static bool s_ledger_token_supply_check_update(dap_ledger_t *a_ledger, dap_ledger_token_item_t *a_token_item, uint256_t a_value, bool a_for_removing)
+{
+    assert(a_token_item);
+    if ((IS_ZERO_256(a_token_item->total_supply) || IS_ZERO_256(a_value)))
+        return true;
+    if (!s_ledger_token_supply_check(a_token_item, a_value) && !a_for_removing)
+        return false;
+    int l_overflow = false;
+    if(a_for_removing)
+        l_overflow = SUM_256_256(a_token_item->current_supply, a_value, &a_token_item->current_supply);
+    else
+        l_overflow = SUBTRACT_256_256(a_token_item->current_supply, a_value, &a_token_item->current_supply);
+    assert(!l_overflow);
+    const char *l_balance; dap_uint256_to_char(a_token_item->current_supply, &l_balance);
+    log_it(L_NOTICE, "New current supply %s for token %s", l_balance, a_token_item->ticker);
+    s_ledger_token_cache_update(a_ledger, a_token_item);
+    return true;
+}
+
+/**
+ * @brief dap_ledger_token_add
+ * @param a_token
+ * @param a_token_size
+ * @return
+ */
+int dap_ledger_token_add(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_size)
+{
+    dap_return_val_if_fail(a_ledger && a_token && a_token_size, DAP_LEDGER_CHECK_INVALID_ARGS);
+    dap_ledger_token_item_t *l_token_item = NULL;
+    dap_chain_datum_token_t *l_token = NULL;
+    size_t l_tsd_total_size = 0, l_signs_size = 0;
+    dap_hash_fast_t l_token_update_hash;
+    int ret = s_token_add_check(a_ledger, a_token, a_token_size, &l_token_item, &l_token,
+                                &l_tsd_total_size, &l_signs_size, &l_token_update_hash);
+    if (ret != DAP_LEDGER_CHECK_OK && ret != DAP_LEDGER_CHECK_WHITELISTED)
+        return ret;
+
+    if (!l_token_item) {
+        assert(l_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_DECL);
+        l_token_item = DAP_NEW_Z(dap_ledger_token_item_t);
+        if ( !l_token_item ) {
+            DAP_DELETE(l_token);
+            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+            return DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+        }
+        *l_token_item = (dap_ledger_token_item_t) {
+                .subtype            = l_token->subtype,
+                .total_supply       = l_token->total_supply,
+                .current_supply     = l_token->total_supply,
+                .auth_signs_total   = l_token->signs_total,
+                .auth_signs_valid   = l_token->signs_valid,
+                .token_emissions_rwlock     = PTHREAD_RWLOCK_INITIALIZER,
+                .token_ts_updated_rwlock    = PTHREAD_RWLOCK_INITIALIZER,
+                .auth_pkeys         = DAP_NEW_Z_SIZE(dap_pkey_t*, sizeof(dap_pkey_t*) * l_token->signs_total),
+                .auth_pkey_hashes   = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, sizeof(dap_chain_hash_fast_t) * l_token->signs_total)
+        };
+        switch (l_token->subtype) {
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
+            l_token_item->flags = l_token->header_private_decl.flags; break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
+            l_token_item->flags = l_token->header_native_decl.flags; break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC:
+            l_token_item->flags = l_token->header_public.flags; break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
+        default:;
+        }
+        if ( !l_token_item->auth_pkeys ) {
+            DAP_DEL_MULTY(l_token, l_token_item);
+            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+            return DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+        };
+        if ( !l_token_item->auth_pkey_hashes ) {
+            DAP_DEL_MULTY(l_token, l_token_item->auth_pkeys, l_token_item);
+            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+            return DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+        }
+        size_t l_auth_signs_total = l_token->signs_total;
+        dap_sign_t **l_signs = dap_sign_get_unique_signs(l_token->tsd_n_signs + l_tsd_total_size,
+                                                         l_signs_size,
+                                                         &l_auth_signs_total);
+#define CLEAN_UP DAP_DEL_MULTY(l_token, l_token_item->auth_pkeys, l_token_item->auth_pkey_hashes, l_token_item)
+        if (!l_signs) {
+            CLEAN_UP;
+            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+            return DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+        }
+        dap_stpcpy((char *)l_token_item->ticker, l_token->ticker);
+        for (uint16_t k = 0; k < l_token_item->auth_signs_total; k++) {
+            l_token_item->auth_pkeys[k] = dap_pkey_get_from_sign(l_signs[k]);
+            if (!l_token_item->auth_pkeys[k]) {
+                CLEAN_UP;
+                log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+                return DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+            }
+            dap_pkey_get_hash(l_token_item->auth_pkeys[k], &l_token_item->auth_pkey_hashes[k]);
+        }
+#undef CLEAN_UP
+        DAP_DELETE(l_signs);
+        l_token_item->datum_token_size = sizeof(dap_chain_datum_token_t) + l_tsd_total_size + l_signs_size;
+        l_token_item->datum_token = l_token;
+        pthread_rwlock_wrlock(&PVT(a_ledger)->tokens_rwlock);
+        HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item);
+    } else {
+        assert(l_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE);
+        pthread_rwlock_wrlock(&PVT(a_ledger)->tokens_rwlock);
+        dap_ledger_token_update_item_t *l_token_update_item;
+        pthread_rwlock_wrlock(&l_token_item->token_ts_updated_rwlock);
+        HASH_FIND(hh, l_token_item->token_ts_updated, &l_token_update_hash, sizeof(dap_hash_fast_t), l_token_update_item);
+        if (l_token_update_item) {
+            pthread_rwlock_unlock(&l_token_item->token_ts_updated_rwlock);
+            pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+            log_it(L_ERROR, "Token update with hash %s already exist in token %s hash-table",
+                            dap_hash_fast_to_str_static(&l_token_update_hash), l_token->ticker);
+            DAP_DELETE(l_token);
+            return DAP_LEDGER_CHECK_APPLY_ERROR;
+        }
+        l_token_update_item = DAP_NEW(dap_ledger_token_update_item_t);
+        if (!l_token_update_item) {
+            pthread_rwlock_unlock(&l_token_item->token_ts_updated_rwlock);
+            pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+            log_it(L_CRITICAL, c_error_memory_alloc);
+            DAP_DELETE(l_token);
+            return DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
+        }
+        *l_token_update_item = (dap_ledger_token_update_item_t) {
+                .update_token_hash			= l_token_update_hash,
+                .datum_token_update			= l_token,
+                .datum_token_update_size	= sizeof(dap_chain_datum_token_t) + l_tsd_total_size + l_signs_size,
+                .updated_time               = dap_time_now()
+        };
+        HASH_ADD(hh, l_token_item->token_ts_updated, update_token_hash, sizeof(dap_chain_hash_fast_t), l_token_update_item);
+        pthread_rwlock_unlock(&l_token_item->token_ts_updated_rwlock);
+        l_token_item->last_update_token_time = l_token_update_item->updated_time;
+    }
+    if (ret != DAP_LEDGER_CHECK_WHITELISTED) {
+        ret = s_token_tsd_parse(l_token_item, l_token, a_ledger, l_token->tsd_n_signs, l_tsd_total_size, true);
+        assert(ret == DAP_LEDGER_CHECK_OK);
+    }
+    pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+    const char *l_balance_dbg = NULL, *l_declare_update_str = NULL, *l_type_str = NULL;
+    if (s_debug_more)
+        dap_uint256_to_char(l_token->total_supply, &l_balance_dbg);
+    switch (l_token->type) {
+    case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL:       l_declare_update_str = "declared"; break;
+    case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE:     l_declare_update_str = "updated"; break;
+    default: assert(false); break;
+    }
+    switch (l_token->subtype) {
+    case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:  l_type_str = "Simple"; break;
+    case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE: l_type_str = "Private"; break;
+    case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:  l_type_str = "CF20"; break;
+    case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC:  l_type_str = "Public"; break;
+    default: assert(false); break;
+    }
+    debug_if(s_debug_more, L_INFO, "%s token %s has been %s, total_supply: %s, signs_valid: %zu, signs_total: %zu",
+                                l_type_str, l_token_item->ticker, l_declare_update_str,
+                                l_balance_dbg, l_token_item->auth_signs_valid, l_token_item->auth_signs_total);
+
+    s_threshold_emissions_proc(a_ledger); /* TODO process thresholds only for no-consensus chains */
+    s_ledger_token_cache_update(a_ledger, l_token_item);
+    return ret;
+}
+
+int dap_ledger_token_load(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_size)
+{
+    if (dap_chain_net_get_load_mode(a_ledger->net)) {
+        const char *l_ticker = NULL;
+        switch (*(uint16_t *)a_token) {
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL:
+            l_ticker = ((dap_chain_datum_token_t *)a_token)->ticker;
+            break;
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE:
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC:
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_DECL:
+        case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_DECL:
+            l_ticker = ((dap_chain_datum_token_old_t *)a_token)->ticker;
+            break;
+        }
+        if (l_ticker && s_ledger_find_token(a_ledger, l_ticker))
+            return DAP_LEDGER_CHECK_OK;
+    }
+    return dap_ledger_token_add(a_ledger, a_token, a_token_size);
+}
+
 /**
  * @brief s_tx_header_print
  * prepare data for print, add time
@@ -1098,877 +1934,58 @@ static void s_dump_datum_tx_for_addr(dap_ledger_tx_item_t *a_item, bool a_unspen
             const char *l_dst_addr_str = l_dst_addr ? dap_chain_addr_to_str(l_dst_addr)
                                                     : dap_chain_tx_out_cond_subtype_to_str(
                                                           ((dap_chain_tx_out_cond_t *)l_list_out->data)->header.subtype);
-            json_object_object_add(l_json_obj_datum, "send", json_object_new_string(dap_uint256_to_char(l_value, NULL)));
-            json_object_object_add(l_json_obj_datum, "to addr", json_object_new_string(l_dst_addr_str));
-            json_object_object_add(l_json_obj_datum, "token", l_src_token ? json_object_new_string(l_src_token) : json_object_new_string("UNKNOWN"));
-            json_object_array_add(json_arr_out, l_json_obj_datum);
-        }
-        if (l_dst_addr && !memcmp(l_dst_addr, a_addr, sizeof(dap_chain_addr_t))) {
-            json_object * l_json_obj_datum = json_object_new_object();
-            if (!l_header_printed) {
-               s_tx_header_print(l_json_obj_datum, l_tx, a_hash_out_type, l_tx_hash);
-               l_header_printed = true;
-            }
-            const char *l_dst_token = (l_type == TX_ITEM_TYPE_OUT_EXT) ?
-                        (const char *)(((dap_chain_tx_out_ext_t *)l_list_out->data)->token) : NULL;
-            const char *l_src_addr_str = l_base_tx ? "emission"
-                                                   : (l_src_addr ? dap_chain_addr_to_str(l_src_addr)
-                                                                 : dap_chain_tx_out_cond_subtype_to_str(
-                                                                       l_src_subtype));
-            json_object_object_add(l_json_obj_datum, "recv ", json_object_new_string(dap_uint256_to_char(l_value, NULL)));
-            json_object_object_add(l_json_obj_datum, "token ", l_dst_token ? json_object_new_string(l_dst_token) :
-                                  (l_src_token ? json_object_new_string(l_src_token) : json_object_new_string("UNKNOWN")));
-            json_object_object_add(l_json_obj_datum, "from ", json_object_new_string(l_src_addr_str));
-            json_object_array_add(json_arr_out, l_json_obj_datum);
-        }
-    }
-    dap_list_free(l_list_out_items);
-}
-
-json_object *dap_ledger_token_tx_item_list(dap_ledger_t * a_ledger, dap_chain_addr_t *a_addr, const char *a_hash_out_type, bool a_unspent_only)
-{
-    json_object * json_arr_out = json_object_new_array();
-    if (!json_arr_out) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        return NULL;
-    }
-
-    //dap_chain_tx_hash_processed_ht_t *l_tx_data_ht = NULL;
-    dap_ledger_tx_item_t *l_tx_item, *l_tx_tmp;
-    dap_ledger_private_t * l_ledger_pvt = PVT(a_ledger);
-
-    pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock);
-    //unsigned test = dap_ledger_count(a_ledger);
-    HASH_ITER(hh, l_ledger_pvt->ledger_items, l_tx_item, l_tx_tmp) {
-        s_dump_datum_tx_for_addr(l_tx_item, a_unspent_only, a_ledger, a_addr, a_hash_out_type, json_arr_out);
-    }
-    pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
-
-    // if no history
-    if(!json_arr_out)
-    {
-        json_object * json_obj_addr = json_object_new_object();
-        json_object_object_add(json_obj_addr, "status:", json_object_new_string("empty"));
-        json_object_array_add(json_arr_out, json_obj_addr);
-    }
-    return json_arr_out;
-}
-
-/**
- * @brief update current_supply in token cache
- *
- * @param a_ledger ledger object
- * @param l_token_item token item object
- */
-void s_ledger_token_cache_update(dap_ledger_t *a_ledger, dap_ledger_token_item_t *l_token_item)
-{
-    if (!PVT(a_ledger)->cached)
-        return;
-    char *l_gdb_group = dap_ledger_get_gdb_group(a_ledger, DAP_LEDGER_TOKENS_STR);
-    size_t l_cache_size = l_token_item->datum_token_size + sizeof(uint256_t);
-    uint8_t *l_cache = DAP_NEW_STACK_SIZE(uint8_t, l_cache_size);
-    if ( !l_cache ) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        return;
-    }
-    memcpy(l_cache, &l_token_item->current_supply, sizeof(uint256_t));
-    memcpy(l_cache + sizeof(uint256_t), l_token_item->datum_token, l_token_item->datum_token_size);
-    if (dap_global_db_set(l_gdb_group, l_token_item->ticker, l_cache, l_cache_size, false, NULL, NULL)) {
-        char *l_supply = dap_chain_balance_print(l_token_item->current_supply);
-        log_it(L_WARNING, "Ledger cache mismatch, can't add token [%s] with supply %s", l_token_item->ticker, l_supply);
-        DAP_DELETE(l_supply);
-    }
-    DAP_DELETE(l_gdb_group);
-}
-
-static bool s_ledger_token_supply_check_unsafe(dap_ledger_token_item_t *a_token_item, uint256_t a_value)
-{
-    if (compare256(a_token_item->current_supply, a_value) >= 0)
-        return true;
-    char *l_supply_str = dap_chain_balance_print(a_token_item->current_supply);
-    char *l_value_str = dap_chain_balance_print(a_value);
-    log_it(L_WARNING, "Token current supply %s < emission value %s", l_supply_str, l_value_str);
-    DAP_DEL_MULTY(l_supply_str, l_value_str);
-    return false;
-}
-
-static bool s_ledger_token_supply_check(dap_ledger_token_item_t *a_token_item, uint256_t a_value)
-{
-    assert(a_token_item);
-    if (IS_ZERO_256(a_token_item->total_supply) || IS_ZERO_256(a_value))
-        return true;
-    return s_ledger_token_supply_check_unsafe(a_token_item, a_value);
-}
-
-static bool s_ledger_token_supply_check_update(dap_ledger_t *a_ledger, dap_ledger_token_item_t *a_token_item, uint256_t a_value, bool a_for_removing)
-{
-    assert(a_token_item);
-    if ((IS_ZERO_256(a_token_item->total_supply) || IS_ZERO_256(a_value)))
-        return true;
-    if (!s_ledger_token_supply_check_unsafe(a_token_item, a_value) && !a_for_removing)
-        return false;
-    int l_overflow = false;
-    if(a_for_removing)
-        l_overflow = SUM_256_256(a_token_item->current_supply, a_value, &a_token_item->current_supply);
-    else
-        l_overflow = SUBTRACT_256_256(a_token_item->current_supply, a_value, &a_token_item->current_supply);
-    assert(!l_overflow);
-    const char *l_balance; dap_uint256_to_char(a_token_item->current_supply, &l_balance);
-    log_it(L_NOTICE, "New current supply %s for token %s", l_balance, a_token_item->ticker);
-    s_ledger_token_cache_update(a_ledger, a_token_item);
-    return true;
-}
-
-
-/**
- * @brief s_ledger_update_token_add_in_hash_table
- * @param a_cur_token_item
- * @param a_token_update
- * @param a_token_update_size
- * @return true or false
- */
-static bool s_ledger_update_token_add_in_hash_table(dap_ledger_token_item_t *a_cur_token_item, dap_chain_datum_token_t *a_token_update, size_t a_token_update_size)
-{
-    dap_ledger_token_update_item_t	*l_token_update_item;
-    dap_hash_fast_t							l_hash_token_update;
-    bool									new_item = false;
-
-    dap_hash_fast(a_token_update, a_token_update_size, &l_hash_token_update);
-    pthread_rwlock_rdlock(&a_cur_token_item->token_ts_updated_rwlock);
-    HASH_FIND(hh, a_cur_token_item->token_ts_updated, &l_hash_token_update, sizeof(dap_hash_fast_t),
-              l_token_update_item);
-    pthread_rwlock_unlock(&a_cur_token_item->token_ts_updated_rwlock);
-    if (l_token_update_item
-    &&	a_cur_token_item->last_update_token_time == l_token_update_item->updated_time) {
-        if (s_debug_more)
-            log_it(L_WARNING, "Error: item 'dap_ledger_token_update_item_t' already exist in hash-table");
-        return false;
-    } else if (!l_token_update_item){
-        new_item = true;
-        l_token_update_item = DAP_NEW(dap_ledger_token_update_item_t);
-        if (!l_token_update_item) {
-            if (s_debug_more)
-                log_it(L_ERROR, "Error: memory allocation when try adding item 'dap_ledger_token_update_item_t' to hash-table");
-            return false;
-        }
-        *l_token_update_item = (dap_ledger_token_update_item_t) {
-                .update_token_hash			= l_hash_token_update,
-                .datum_token_update			= a_token_update,
-                .datum_token_update_size	= a_token_update_size
-        };
-    }
-
-    l_token_update_item->updated_time		= dap_time_now();
-
-    if (new_item) {
-        pthread_rwlock_wrlock(&a_cur_token_item->token_ts_updated_rwlock);
-        HASH_ADD(hh, a_cur_token_item->token_ts_updated, update_token_hash, sizeof(dap_chain_hash_fast_t), l_token_update_item);
-        pthread_rwlock_unlock(&a_cur_token_item->token_ts_updated_rwlock);
-    }
-
-    if (!l_token_update_item) {
-        if (s_debug_more)
-            log_it(L_ERROR, "Error: adding to hash-table. Be careful, there may be leaks");
-        return false;
-    }
-
-    a_cur_token_item->last_update_token_time = l_token_update_item->updated_time;
-
-    return true;
-}
-
-/**
- * @brief dap_ledger_token_add
- * @param a_token
- * @param a_token_size
- * @return
- */
-int dap_ledger_token_add(dap_ledger_t *a_ledger, dap_chain_datum_token_t *a_token, size_t a_token_size)
-{
-    if (!a_ledger || !a_token) {
-        debug_if(s_debug_more, L_ERROR, "NULL ledger, can't add datum with token declaration!");
-        return -1;
-    }
-
-    dap_chain_datum_token_t *l_token = a_token;
-    dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, l_token->ticker);
-    if (l_token_item) {
-        if (l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE
-                && l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_UPDATE
-                && l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_UPDATE) {
-            log_it(L_ERROR, "Duplicate token declaration for ticker '%s'", l_token->ticker);
-            DAP_DELETE(l_token);
-            return -3;
-        }
-        if (s_ledger_token_update_check(l_token_item, l_token, a_token_size)) {
-            if (!s_ledger_update_token_add_in_hash_table(l_token_item, l_token, a_token_size)) {
-                log_it(L_ERROR, "Failed to update token with ticker '%s' in ledger", l_token->ticker);
-                DAP_DELETE(l_token);
-                return -5;
-            }
-            if (!IS_ZERO_256(l_token->total_supply)) {
-                SUBTRACT_256_256(l_token_item->total_supply, l_token_item->current_supply, &l_token_item->current_supply);
-                SUBTRACT_256_256(l_token->total_supply, l_token_item->current_supply, &l_token_item->current_supply);
-            } else {
-                l_token_item->current_supply = l_token->total_supply;
-            }
-            l_token_item->total_supply = l_token->total_supply;
-            DAP_DELETE(l_token_item->datum_token);
-        } else {
-            log_it(L_ERROR, "Token with ticker '%s' update check failed", l_token->ticker);
-            DAP_DELETE(l_token);
-            return -2;
-        }
-    } else if (l_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE) {
-        log_it(L_WARNING, "Token with ticker '%s' does not yet exist, declare it first", l_token->ticker);
-        DAP_DELETE(l_token);
-        return -6;
-    }
-
-    if (!l_token_item) {
-        size_t l_auth_signs_total, l_auth_signs_valid;
-        dap_sign_t **l_signs = dap_chain_datum_token_signs_parse(l_token, a_token_size, &l_auth_signs_total, &l_auth_signs_valid);
-        if (!l_signs || !l_auth_signs_total) {
-            log_it(L_ERROR, "No auth signs in token '%s' datum!", l_token->ticker);
-            DAP_DELETE(l_token);
-            return -7;
-        }
-        l_token_item = DAP_NEW_Z(dap_ledger_token_item_t);
-        if ( !l_token_item ) {
-            DAP_DELETE(l_token);
-            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            return -8;
-        }
-        *l_token_item = (dap_ledger_token_item_t) {
-                .version        = l_token->version,
-                .type           = l_token->type,
-                .subtype        = l_token->subtype,
-                .total_supply   = l_token->total_supply,
-                .current_supply = l_token->total_supply,
-                .token_emissions_rwlock     = PTHREAD_RWLOCK_INITIALIZER,
-                .token_ts_updated_rwlock    = PTHREAD_RWLOCK_INITIALIZER,
-                .auth_pkeys         = DAP_NEW_Z_SIZE(dap_pkey_t*, sizeof(dap_pkey_t*) * l_token->signs_total),
-                .auth_pkeys_hash    = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, sizeof(dap_chain_hash_fast_t) * l_token->signs_total),
-                .auth_signs_total   = l_auth_signs_total,
-                .auth_signs_valid   = l_auth_signs_valid,
-                .description_token_size = 0
-        };
-        if ( !l_token_item->auth_pkeys ) {
-            DAP_DELETE(l_token);
-            DAP_DELETE(l_token_item);
-            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            return -6;
-        };
-        if ( !l_token_item->auth_pkeys ) {
-            DAP_DELETE(l_token);
-            DAP_DEL_Z(l_token_item->auth_pkeys);
-            DAP_DELETE(l_token_item);
-            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            return -6;
-        }
-        dap_stpcpy(l_token_item->ticker, l_token->ticker);
-        for (uint16_t k = 0; k < l_token_item->auth_signs_total; k++) {
-            l_token_item->auth_pkeys[k] = dap_pkey_get_from_sign(l_signs[k]);
-            dap_pkey_get_hash(l_token_item->auth_pkeys[k], &l_token_item->auth_pkeys_hash[k]);
-        }
-        DAP_DELETE(l_signs);
-    }
-
-
-    l_token_item->datum_token_size  = a_token_size;
-    l_token_item->datum_token       = l_token;
-    l_token_item->datum_token->type = l_token->type;
-
-    if(l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE
-            && l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_UPDATE
-            && l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_UPDATE) {
-        pthread_rwlock_wrlock(&PVT(a_ledger)->tokens_rwlock);
-        HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item);
-        pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
-    }
-    int l_res_token_tsd_parse = 0;
-
-    const char *l_balance_dbg = NULL;
-    if (s_debug_more)
-        dap_uint256_to_char(l_token->total_supply, &l_balance_dbg);
-
-#define CLEAN_UP DAP_DEL_MULTY(l_token, l_token_item->auth_pkeys, l_token_item->auth_pkeys_hash, l_token_item)
-
-    switch (l_token->type) {
-    case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL:
-        switch (l_token->subtype) {
-        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
-            debug_if(s_debug_more, L_INFO, "Simple token %s declared, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
-                   l_token->ticker, l_balance_dbg,
-                   l_token->signs_valid, l_token->signs_total);
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-            debug_if(s_debug_more, L_INFO, "Private token %s declared, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
-                    l_token->ticker, l_balance_dbg,
-                    l_token->signs_valid, l_token->signs_total);
-            l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, a_token_size);
-            s_tsd_sign_apply(a_ledger, l_token_item, l_token, a_token_size);
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-            debug_if(s_debug_more, L_INFO, "CF20 token %s declared, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
-                    l_token->ticker, l_balance_dbg,
-                    l_token->signs_valid, l_token->signs_total);
-            l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, a_token_size);
-            s_tsd_sign_apply(a_ledger, l_token_item, l_token, a_token_size);
-            break;
-        default:
-            /* Bogdanoff, unknown token subtype declaration. What shall we TODO? */
-            debug_if(s_debug_more, L_ERROR, "Unknown token subtype '0x%04X' declaration! Ticker: %s, total_supply: %s, total_signs_valid: %hu, signs_total: %hu"
-                     "Dump it!",
-                   l_token->type, l_token->ticker, l_balance_dbg,
-                   l_token->signs_valid, l_token->signs_total);
-            /* Dump it right now */
-            CLEAN_UP;
-            return -8;
-        } break;
-    case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE:
-        switch (l_token->subtype) {
-        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
-            debug_if(s_debug_more, L_INFO, "Simple token %s updated, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
-                   l_token->ticker, l_balance_dbg,
-                   l_token->signs_valid, l_token->signs_total);
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-            debug_if(s_debug_more, L_INFO, "Private token %s updated, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
-                    l_token->ticker, l_balance_dbg,
-                    l_token->signs_valid, l_token->signs_total);
-            l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, a_token_size);
-            s_tsd_sign_apply(a_ledger, l_token_item, l_token, a_token_size);
-            break;
-        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-            debug_if(s_debug_more, L_INFO, "CF20 token %s updated, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
-                    l_token->ticker, l_balance_dbg,
-                    l_token->signs_valid, l_token->signs_total);
-            l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, a_token_size);
-            s_tsd_sign_apply(a_ledger, l_token_item, l_token, a_token_size);
-            break;
-        default:
-            /* Bogdanoff, unknown token type update. What shall we TODO? */
-            debug_if(s_debug_more, L_ERROR, "Unknown token subtype '0x%04X' update! Ticker: %s, total_supply: %s, total_signs_valid: %hu, signs_total: %hu"
-                     "Dump it!",
-                   l_token->type, l_token->ticker, l_balance_dbg,
-                   l_token->signs_valid, l_token->signs_total);
-            /* Dump it right now */
-            CLEAN_UP;
-            return -8;
-        } break;
-    default:
-        debug_if(s_debug_more, L_ERROR, "Unknown token type 0x%04X, Dump it!", l_token->type);
-        CLEAN_UP;
-        return -8;
-    }
-    if (l_res_token_tsd_parse) {
-        debug_if(s_debug_more, L_ERROR, "Can't parse tsd section for %s token, code error: %i", l_token->ticker, l_res_token_tsd_parse);
-        CLEAN_UP;
-        return -1;
-    }
-#undef CLEAN_UP
-    s_threshold_emissions_proc(a_ledger); /* TODO process thresholds only for no-consensus chains */
-    s_ledger_token_cache_update(a_ledger, l_token_item);
-    return 0;
-}
-
-/**
- * @brief s_token_tsd_parse
- *
- * @param a_ledger
- * @param a_token_item
- * @param a_token
- * @param a_token_size
- * @return int
- */
-static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_ledger_token_item_t *a_token_item , dap_chain_datum_token_t * a_token, size_t a_token_size)
-{
-    UNUSED(a_ledger);
-    dap_tsd_t * l_tsd= dap_chain_datum_token_tsd_get(a_token,a_token_size);
-    size_t l_tsd_size=0;
-    size_t l_tsd_total_size = a_token->header_native_decl.tsd_total_size;
-    a_token_item->flags = a_token->header_native_decl.flags;
-
-    for( size_t l_offset=0; l_offset < l_tsd_total_size;  l_offset += l_tsd_size ){
-        l_tsd = (dap_tsd_t *)(((byte_t *)l_tsd ) + l_tsd_size);
-        l_tsd_size =  l_tsd? dap_tsd_size(l_tsd): 0;
-        if( l_tsd_size==0 ){
-            if(s_debug_more)
-                log_it(L_ERROR,"Wrong zero TSD size, exiting TSD parse");
-            break;
-        }else if (l_tsd_size + l_offset > l_tsd_total_size ){
-            if(s_debug_more)
-                log_it(L_ERROR,"Wrong %zd TSD size, exiting TSD parse", l_tsd_size);
-            break;
-        }
-        switch (l_tsd->type) {
-           // set flags
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS:{
-                uint16_t l_flags = 0;
-                a_token_item->flags |= _dap_tsd_get_scalar(l_tsd, &l_flags);
-            }break;
-
-           // unset flags
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS:{
-                uint16_t l_flags = 0;
-                a_token_item->flags &= ~_dap_tsd_get_scalar(l_tsd, &l_flags);
-            }break;
-
-            // set total supply
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY:{ // 256
-                a_token_item->total_supply = uint256_0;
-                _dap_tsd_get_scalar(l_tsd, &a_token_item->total_supply);
-            }break;
-
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY_OLD:{ // 128
-                uint128_t l_total_supply128 = uint128_0;
-                a_token_item->total_supply = GET_256_FROM_128(_dap_tsd_get_scalar(l_tsd,&l_total_supply128));
-            }break;
-
-            // Set total signs count value to set to be valid
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID:{
-                uint16_t l_signs_valid = 0;
-                a_token_item->auth_signs_valid = _dap_tsd_get_scalar(l_tsd, &l_signs_valid);
-            }break;
-
-            //Allowed tx receiver addres list add, remove or clear
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD:{
-                if( l_tsd->size == sizeof (dap_chain_addr_t) ){
-                    a_token_item->tx_recv_allow = a_token_item->tx_recv_allow
-                            ? DAP_REALLOC(a_token_item->tx_recv_allow, (a_token_item->tx_recv_allow_size + 1) * sizeof(*a_token_item->tx_recv_allow))
-                            : DAP_NEW_Z_SIZE(dap_chain_addr_t,sizeof(*a_token_item->tx_recv_allow));
-
-                    // Check if its correct
-                    dap_chain_addr_t * l_add_addr = (dap_chain_addr_t *) l_tsd->data;
-                    if (dap_chain_addr_check_sum(l_add_addr)) {
-                        debug_if(s_debug_more, L_ERROR, "Wrong address checksum in TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD");
-                        return -12;
-                    }
-                    // Check if its already present
-                    if (a_token_item->tx_recv_allow) {
-                        for( size_t i=0; i < a_token_item->tx_recv_allow_size; i++){ // Check for all the list
-                            if ( memcmp(&a_token_item->tx_recv_allow[i], l_tsd->data, l_tsd->size) == 0 ){ // Found
-                                debug_if(s_debug_more, L_ERROR,
-                                    "TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD has address %s thats already present in list",
-                                    dap_chain_addr_to_str((dap_chain_addr_t*) l_tsd->data ));
-                                DAP_DEL_Z(a_token_item->tx_recv_allow);
-                                return -11;
-                            }
-                        }
-                        if(a_token_item->tx_recv_allow){
-                            a_token_item->tx_recv_allow[a_token_item->tx_recv_allow_size] = *(dap_chain_addr_t*)l_tsd->data;
-                            a_token_item->tx_recv_allow_size++;
-                        }
-
-                    }else{
-                        log_it(L_ERROR,"Out of memory! Can't extend TX_RECEIVER_ALLOWED array");
-                        return -20;
-                    }
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD expected to have %zu bytes data length, not %u",
-                           sizeof (dap_chain_addr_t), l_tsd->size );
-                    return -10;
-                }
-            }break;
-
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE:{
-                if( l_tsd->size == sizeof (dap_chain_addr_t) ){
-                    // Check if its correct
-                    dap_chain_addr_t * l_add_addr = (dap_chain_addr_t *) l_tsd->data;
-                    if (dap_chain_addr_check_sum(l_add_addr)) {
-                        debug_if(s_debug_more, L_ERROR, "Wrong address checksum in TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE");
-                        return -12;
-                    }
-                    bool l_was_found=false;
-                    for( size_t i=0; i < a_token_item->tx_recv_allow_size; i++){ // Check for all the list
-                        if ( memcmp(&a_token_item->tx_recv_allow[i], l_tsd->data, l_tsd->size) == 0 ){ // Found
-                            if( i +1 != a_token_item->tx_recv_allow_size )
-                                memmove(&a_token_item->tx_recv_allow[i],&a_token_item->tx_recv_allow[i+1],
-                                        sizeof(*a_token_item->tx_recv_allow)*(a_token_item->tx_recv_allow_size-i-1 ) );
-                            a_token_item->tx_recv_allow_size--;
-                            l_was_found = true;
-                            break;
-                        }
-                    }
-                    // TODO
-                    UNUSED(l_was_found);
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE expected to have %zu bytes data length, not %u",
-                           sizeof (dap_chain_addr_t), l_tsd->size );
-                    return -10;
-                }
-            }break;
-
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_CLEAR:{
-                if( l_tsd->size == 0 ){
-                    if( a_token_item->tx_recv_allow )
-                        DAP_DEL_Z(a_token_item->tx_recv_allow);
-                    a_token_item->tx_recv_allow_size = 0;
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_CLEAR expected to have 0 bytes data length, not %u",
-                           l_tsd->size );
-                    return -10;
-                }
-            }break;
-
-
-            //Blocked tx receiver addres list add, remove or clear
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD:{
-                if( l_tsd->size == sizeof (dap_chain_addr_t) ){
-                    dap_chain_addr_t * l_addrs = a_token_item->tx_recv_block
-                            ? DAP_NEW_Z_SIZE(dap_chain_addr_t, sizeof(*a_token_item->tx_recv_block))
-                            : DAP_REALLOC(a_token_item->tx_recv_block,
-                                          (a_token_item->tx_recv_block_size + 1) * sizeof(*a_token_item->tx_recv_block));
-                    // Check if its correct
-                    dap_chain_addr_t * l_add_addr = (dap_chain_addr_t *) l_tsd->data;
-                    if (dap_chain_addr_check_sum(l_add_addr)) {
-                        DAP_DEL_Z(l_addrs);
-                        debug_if(s_debug_more, L_ERROR, "Wrong address checksum in TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD");
-                        return -12;
-                    }
-                    // Check if its already present
-                    if(a_token_item->tx_recv_block)
-                        for( size_t i=0; i < a_token_item->tx_recv_block_size; i++){ // Check for all the list
-                            if ( memcmp(&a_token_item->tx_recv_block[i], l_tsd->data, l_tsd->size) == 0 ){ // Found
-                                debug_if(s_debug_more, L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD has address %s thats already present in list",
-                                           dap_chain_addr_to_str((dap_chain_addr_t*) l_tsd->data ));
-                                DAP_DELETE(l_addrs);
-                                DAP_DEL_Z(a_token_item->tx_recv_allow);
-                                return -11;
-                            }
-                        }
-
-                    if(l_addrs) {
-                        l_addrs[a_token_item->tx_recv_block_size] = *(dap_chain_addr_t*)l_tsd->data;
-                        a_token_item->tx_recv_block_size++;
-                        a_token_item->tx_recv_block = l_addrs;
-
-                    } else {
-                        log_it(L_ERROR,"Out of memory! Can't extend TX_RECEIVER_BLOCKED array");
-                    }
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD expected to have %zu bytes data length, not %u",
-                           sizeof (dap_chain_addr_t), l_tsd->size );
-                    return -10;
-                }
-            }break;
-
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE:{
-                if( l_tsd->size == sizeof (dap_chain_addr_t) ){
-                    // Check if its correct
-                    dap_chain_addr_t * l_add_addr = (dap_chain_addr_t *) l_tsd->data;
-                    if (dap_chain_addr_check_sum(l_add_addr)) {
-                        debug_if(s_debug_more, L_ERROR, "Wrong address checksum in TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE");
-                        return -12;
-                    }
-                    bool l_was_found=false;
-                    for( size_t i=0; i < a_token_item->tx_recv_block_size; i++){ // Check for all the list
-                        if ( memcmp(&a_token_item->tx_recv_block[i], l_tsd->data, l_tsd->size) == 0 ){ // Found
-                            if( i +1 != a_token_item->tx_recv_block_size )
-                                memmove(&a_token_item->tx_recv_block[i],&a_token_item->tx_recv_block[i+1],
-                                        sizeof(*a_token_item->tx_recv_block)*(a_token_item->tx_recv_block_size-i-1 ) );
-                            a_token_item->tx_recv_block_size--;
-                            l_was_found = true;
-                            break;
-                        }
-                    }
-                    // TODO
-                    UNUSED(l_was_found);
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE expected to have %zu bytes data length, not %u",
-                           sizeof (dap_chain_addr_t), l_tsd->size );
-                    return -10;
-                }
-            }break;
-
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_CLEAR:{
-                if( l_tsd->size == 0 ){
-                    if( a_token_item->tx_recv_block )
-                        DAP_DEL_Z(a_token_item->tx_recv_block);
-                    a_token_item->tx_recv_block_size = 0;
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_CLEAR expected to have 0 bytes data length, not %u",
-                           l_tsd->size );
-                    return -10;
-                }
-            }break;
-
-            //Allowed tx sender addres list add, remove or clear
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD:{
-                if( l_tsd->size == sizeof (dap_chain_addr_t) ){
-                    dap_chain_addr_t * l_addrs = a_token_item->tx_send_allow ? DAP_NEW_Z_SIZE( dap_chain_addr_t,
-                                                                                              sizeof(*a_token_item->tx_send_allow) )
-                                : DAP_REALLOC(a_token_item->tx_send_allow,(a_token_item->tx_send_allow_size+1)*sizeof (*a_token_item->tx_send_allow) );
-                    // Check if its correct
-                    dap_chain_addr_t * l_add_addr = (dap_chain_addr_t *) l_tsd->data;
-                    if (dap_chain_addr_check_sum(l_add_addr)) {
-                        DAP_DEL_Z(l_addrs);
-                        debug_if(s_debug_more, L_ERROR, "Wrong address checksum in TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD");
-                        return -12;
-                    }
-                    // Check if its already present
-                    for( size_t i=0; i < a_token_item->tx_send_allow_size; i++){ // Check for all the list
-                        if ( memcmp(&a_token_item->tx_send_allow[i], l_tsd->data, l_tsd->size) == 0 ){ // Found
-                            debug_if(s_debug_more, L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD has address %s thats already present in list",
-                                     dap_chain_addr_to_str((dap_chain_addr_t*) l_tsd->data ));
-                            DAP_DELETE(l_addrs);
-                            return -11;
-                        }
-                    }
-                    if(l_addrs) {
-                        l_addrs[a_token_item->tx_send_allow_size] = *(dap_chain_addr_t*)l_tsd->data;
-                        a_token_item->tx_send_allow_size++;
-                        a_token_item->tx_send_allow = l_addrs;
-
-                    } else {
-                        log_it(L_ERROR,"Out of memory! Can't extend TX_SENDER_ALLOWED array");
-                    }
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD expected to have %zu bytes data length, not %u",
-                           sizeof (dap_chain_addr_t), l_tsd->size );
-                }
-            }break;
-
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE:{
-                if( l_tsd->size == sizeof (dap_chain_addr_t) ){
-                    // Check if its correct
-                    dap_chain_addr_t * l_add_addr = (dap_chain_addr_t *) l_tsd->data;
-                    if (dap_chain_addr_check_sum(l_add_addr)) {
-                        debug_if(s_debug_more, L_ERROR, "Wrong address checksum in TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE");
-                        return -12;
-                    }
-                    bool l_was_found=false;
-                    for( size_t i=0; i < a_token_item->tx_send_allow_size; i++){ // Check for all the list
-                        if ( memcmp(&a_token_item->tx_send_allow[i], l_tsd->data, l_tsd->size) == 0 ){ // Found
-                            if( i +1 != a_token_item->tx_send_allow_size )
-                                memmove(&a_token_item->tx_send_allow[i],&a_token_item->tx_send_allow[i+1],
-                                        sizeof(*a_token_item->tx_send_allow)*(a_token_item->tx_send_allow_size-i-1 ) );
-                            a_token_item->tx_send_allow_size--;
-                            l_was_found = true;
-                            break;
-                        }
-                    }
-                    // TODO
-                    UNUSED(l_was_found);
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE expected to have %zu bytes data length, not %u",
-                           sizeof (dap_chain_addr_t), l_tsd->size );
-                    return -10;
-                }
-            }break;
-
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_CLEAR:{
-                if( l_tsd->size == 0 ){
-                    if( a_token_item->tx_send_allow )
-                        DAP_DEL_Z(a_token_item->tx_send_allow);
-                    a_token_item->tx_send_allow_size = 0;
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_CLEAR expected to have 0 bytes data length, not %u",
-                           l_tsd->size );
-                    return -10;
-                }
-            }break;
-
-
-            //Blocked tx sender addres list add, remove or clear
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD:{
-                if( l_tsd->size == sizeof (dap_chain_addr_t) ){
-                    dap_chain_addr_t *l_addrs = a_token_item->tx_send_block
-                            ? DAP_NEW_Z_SIZE(dap_chain_addr_t, sizeof(*a_token_item->tx_send_block))
-                            : DAP_REALLOC(a_token_item->tx_send_block, (a_token_item->tx_send_block_size + 1) * sizeof(*a_token_item->tx_send_block));
-                    // Check if its correct
-                    dap_chain_addr_t * l_add_addr = (dap_chain_addr_t *) l_tsd->data;
-                    if (dap_chain_addr_check_sum(l_add_addr)) {
-                        DAP_DEL_Z(l_addrs);
-                        debug_if(s_debug_more, L_ERROR, "Wrong address checksum in TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD");
-                        return -12;
-                    }
-                    // Check if its already present
-                    for( size_t i=0; i < a_token_item->tx_send_block_size; i++){ // Check for all the list
-                        if ( memcmp(&a_token_item->tx_send_block[i], l_tsd->data, l_tsd->size) == 0 ){ // Found
-                            debug_if(s_debug_more, L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD has address %s thats already present in list",
-                                     dap_chain_addr_to_str((dap_chain_addr_t*) l_tsd->data ));
-                            DAP_DELETE(l_addrs);
-                            return -11;
-                        }
-                    }
-                    if(l_addrs) {
-                        l_addrs[a_token_item->tx_send_block_size] = *(dap_chain_addr_t*)l_tsd->data;
-                        a_token_item->tx_send_block_size++;
-                        a_token_item->tx_send_block = l_addrs;
-
-                    } else {
-                        log_it(L_ERROR,"Out of memory! Can't extend TX_SENDER_BLOCKED array");
-                    }
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD expected to have %zu bytes data length, not %u",
-                           sizeof (dap_chain_addr_t), l_tsd->size );
-                }
-            }break;
-
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE:{
-                if( l_tsd->size == sizeof (dap_chain_addr_t) ){
-                    // Check if its correct
-                    dap_chain_addr_t * l_add_addr = (dap_chain_addr_t *) l_tsd->data;
-                    if (dap_chain_addr_check_sum(l_add_addr)) {
-                        debug_if(s_debug_more, L_ERROR, "Wrong address checksum in TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE");
-                        return -12;
-                    }
-                    bool l_was_found=false;
-                    for( size_t i=0; i < a_token_item->tx_send_block_size; i++){ // Check for all the list
-                        if ( memcmp(&a_token_item->tx_send_block[i], l_tsd->data, l_tsd->size) == 0 ){ // Found
-                            if( i +1 != a_token_item->tx_send_block_size )
-                                memmove(&a_token_item->tx_send_block[i],&a_token_item->tx_send_block[i+1],
-                                        sizeof(*a_token_item->tx_send_block)*(a_token_item->tx_send_block_size-i-1 ) );
-                            a_token_item->tx_send_block_size--;
-                            l_was_found = true;
-                            break;
-                        }
-                    }
-                    // TODO
-                    UNUSED(l_was_found);
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE expected to have %zu bytes data length, not %u",
-                           sizeof (dap_chain_addr_t), l_tsd->size );
-                    return -10;
-                }
-            }break;
-
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_CLEAR:{
-                if( l_tsd->size == 0 ){
-                    if( a_token_item->tx_send_block )
-                        DAP_DEL_Z(a_token_item->tx_send_block);
-                    a_token_item->tx_send_block_size = 0;
-                }else{
-                    if(s_debug_more)
-                        log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_CLEAR expected to have 0 bytes data length, not %u",
-                           l_tsd->size );
-                    return -10;
-                }
-            }break;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION: {
-                if (l_tsd->size == 0){
-                    if (s_debug_more)
-                        log_it(L_ERROR, "TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION expected to "
-                                        "have 0 bytes data length");
-                    return  -10;
-                }
-                if (a_token_item->description_token_size != 0)
-                    DAP_DELETE(a_token_item->description_token);
-                a_token_item->description_token_size = l_tsd->size;
-                a_token_item->description_token = DAP_NEW_Z_SIZE(char, l_tsd->size);
-                memcpy(a_token_item->description_token, l_tsd->data, l_tsd->size);
-            } break;
-            default:{}
-        }
-    }
-    return 0;
-}
-
-static int s_tsd_sign_apply(dap_ledger_t *a_ledger, dap_ledger_token_item_t *a_token_item , dap_chain_datum_token_t *a_token, size_t a_token_size){
-    dap_tsd_t * l_tsd= dap_chain_datum_token_tsd_get(a_token,a_token_size);
-    size_t l_tsd_size=0;
-    size_t l_tsd_total_size = a_token->header_native_decl.tsd_total_size;
-    dap_tsd_t *l_new_signs_valid = NULL;
-    dap_list_t *l_remove_pkeys = NULL;
-    dap_list_t *l_added_pkeys = NULL;
-
-    for( size_t l_offset=0; l_offset < l_tsd_total_size;  l_offset += l_tsd_size ){
-        l_tsd = (dap_tsd_t *) (((byte_t*)l_tsd) + l_tsd_size);
-        l_tsd_size =  l_tsd? dap_tsd_size(l_tsd): 0;
-        if( l_tsd_size==0 ){
-            if(s_debug_more)
-                log_it(L_ERROR,"Wrong zero TSD size, exiting TSD parse");
-            break;
-        }else if (l_tsd_size + l_offset > l_tsd_total_size ){
-            if(s_debug_more)
-                log_it(L_ERROR,"Wrong %zd TSD size, exiting TSD parse", l_tsd_size);
-            break;
-        }
-        switch (l_tsd->type) {
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID:
-                l_new_signs_valid = l_tsd;
-                break;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD:
-                l_added_pkeys = dap_list_append(l_added_pkeys, l_tsd->data);
-                break;
-            case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE:
-                l_remove_pkeys = dap_list_append(l_remove_pkeys, l_tsd);
-                break;
+            json_object_object_add(l_json_obj_datum, "send", json_object_new_string(dap_uint256_to_char(l_value, NULL)));
+            json_object_object_add(l_json_obj_datum, "to addr", json_object_new_string(l_dst_addr_str));
+            json_object_object_add(l_json_obj_datum, "token", l_src_token ? json_object_new_string(l_src_token) : json_object_new_string("UNKNOWN"));
+            json_object_array_add(json_arr_out, l_json_obj_datum);
         }
-    }
-    for (dap_list_t *l_ptr = l_remove_pkeys; l_ptr; l_ptr = dap_list_next(l_ptr)) {
-        dap_tsd_t *l_tsd = l_ptr->data;
-        dap_hash_fast_t l_hash = { };
-        _dap_tsd_get_scalar(l_tsd, &l_hash);
-        for( size_t i=0; i<a_token_item->auth_signs_total; i++){
-            if (dap_hash_fast_compare(&l_hash, &a_token_item->auth_pkeys_hash[i] )){
-                if (i+1 != a_token_item->auth_signs_total){
-                    memmove(a_token_item->auth_pkeys+i,a_token_item->auth_pkeys+i+1,
-                            (a_token_item->auth_signs_total-i-1)*sizeof (void*));
-                    memmove(a_token_item->auth_pkeys_hash+i,a_token_item->auth_pkeys_hash+i+1,
-                            (a_token_item->auth_signs_total-i-1)*sizeof(dap_chain_hash_fast_t));
-                }
-                a_token_item->auth_signs_total--;
-                if(a_token_item->auth_signs_total) {
-                    // Type sizeof's misunderstanding in realloc?
-                    a_token_item->auth_pkeys = DAP_REALLOC(a_token_item->auth_pkeys,a_token_item->auth_signs_total*sizeof (dap_pkey_t*) );
-                    a_token_item->auth_pkeys_hash = DAP_REALLOC(a_token_item->auth_pkeys_hash,a_token_item->auth_signs_total*sizeof(dap_chain_hash_fast_t));
-                } else {
-                    DAP_DEL_Z(a_token_item->auth_pkeys);
-                    DAP_DEL_Z(a_token_item->auth_pkeys_hash);
-                }
-                break;
+        if (l_dst_addr && !memcmp(l_dst_addr, a_addr, sizeof(dap_chain_addr_t))) {
+            json_object * l_json_obj_datum = json_object_new_object();
+            if (!l_header_printed) {
+               s_tx_header_print(l_json_obj_datum, l_tx, a_hash_out_type, l_tx_hash);
+               l_header_printed = true;
             }
+            const char *l_dst_token = (l_type == TX_ITEM_TYPE_OUT_EXT) ?
+                        (const char *)(((dap_chain_tx_out_ext_t *)l_list_out->data)->token) : NULL;
+            const char *l_src_addr_str = l_base_tx ? "emission"
+                                                   : (l_src_addr ? dap_chain_addr_to_str(l_src_addr)
+                                                                 : dap_chain_tx_out_cond_subtype_to_str(
+                                                                       l_src_subtype));
+            json_object_object_add(l_json_obj_datum, "recv ", json_object_new_string(dap_uint256_to_char(l_value, NULL)));
+            json_object_object_add(l_json_obj_datum, "token ", l_dst_token ? json_object_new_string(l_dst_token) :
+                                  (l_src_token ? json_object_new_string(l_src_token) : json_object_new_string("UNKNOWN")));
+            json_object_object_add(l_json_obj_datum, "from ", json_object_new_string(l_src_addr_str));
+            json_object_array_add(json_arr_out, l_json_obj_datum);
         }
     }
-    for (dap_list_t *l_ptr = l_added_pkeys; l_ptr; l_ptr = dap_list_next(l_ptr)) {
-        dap_pkey_t *l_pkey = (dap_pkey_t*)l_ptr->data;
-        a_token_item->auth_signs_total++;
-        // Type sizeof's misunderstanding in realloc?
-        a_token_item->auth_pkeys = DAP_REALLOC(a_token_item->auth_pkeys,a_token_item->auth_signs_total*sizeof (dap_pkey_t*) );
-        a_token_item->auth_pkeys_hash = DAP_REALLOC(a_token_item->auth_pkeys_hash,a_token_item->auth_signs_total*sizeof (dap_chain_hash_fast_t));
-        a_token_item->auth_pkeys[a_token_item->auth_signs_total-1] = DAP_NEW_SIZE(dap_pkey_t, sizeof(dap_pkey_t)+l_pkey->header.size);
-        memcpy(a_token_item->auth_pkeys[a_token_item->auth_signs_total-1], l_pkey, sizeof(dap_pkey_t)+l_pkey->header.size);
-        dap_pkey_get_hash(l_pkey, &a_token_item->auth_pkeys_hash[a_token_item->auth_signs_total-1]);
-    }
-    if (l_new_signs_valid) {
-        uint16_t l_tmp = 0;
-        a_token_item->auth_signs_valid = _dap_tsd_get_scalar(l_new_signs_valid, &l_tmp);
-    }
-
-    if (l_added_pkeys) dap_list_free(l_added_pkeys);
-    if (l_remove_pkeys) dap_list_free(l_remove_pkeys);
-    return 0;
+    dap_list_free(l_list_out_items);
 }
 
-int dap_ledger_token_load(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_size)
+json_object *dap_ledger_token_tx_item_list(dap_ledger_t * a_ledger, dap_chain_addr_t *a_addr, const char *a_hash_out_type, bool a_unspent_only)
 {
-    dap_chain_datum_token_t *l_token = dap_chain_datum_token_read(a_token, &a_token_size);
+    json_object * json_arr_out = json_object_new_array();
+    if (!json_arr_out) {
+        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+        return NULL;
+    }
 
-    if (dap_chain_net_get_load_mode(a_ledger->net)) {
-        dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, l_token->ticker);
-        if (l_token_item
-                && l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE
-                && l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_UPDATE
-                && l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_UPDATE) {
-            DAP_DELETE(l_token);
-            return 0;
-        }
+    dap_ledger_tx_item_t *l_tx_item, *l_tx_tmp;
+    dap_ledger_private_t * l_ledger_pvt = PVT(a_ledger);
+
+    pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock);
+    HASH_ITER(hh, l_ledger_pvt->ledger_items, l_tx_item, l_tx_tmp) {
+        s_dump_datum_tx_for_addr(l_tx_item, a_unspent_only, a_ledger, a_addr, a_hash_out_type, json_arr_out);
+    }
+    pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
+
+    // if no history
+    if(!json_arr_out)
+    {
+        json_object * json_obj_addr = json_object_new_object();
+        json_object_object_add(json_obj_addr, "status:", json_object_new_string("empty"));
+        json_object_array_add(json_arr_out, json_obj_addr);
     }
-    return dap_ledger_token_add(a_ledger, l_token, a_token_size);
+    return json_arr_out;
 }
 
 json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset)
@@ -2165,45 +2182,31 @@ json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, siz
 }
 
 /**
- * @breif dap_ledger_token_auth_signs_valid
+ * @breif dap_ledger_token_get_auth_signs_valid
  * @param a_ledger
  * @param a_token_ticker
  * @return 0 if no ticker found
  */
-size_t dap_ledger_token_auth_signs_valid(dap_ledger_t *a_ledger, const char * a_token_ticker)
+size_t dap_ledger_token_get_auth_signs_valid(dap_ledger_t *a_ledger, const char *a_token_ticker)
 {
-    dap_ledger_token_item_t *l_token_item, *l_tmp_item;
-    pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
-    size_t l_res = 0;
-    HASH_ITER(hh, PVT(a_ledger)->tokens, l_token_item, l_tmp_item) {
-        if (!dap_strcmp(l_token_item->ticker, a_token_ticker)) {
-            l_res = l_token_item->auth_signs_valid;
-            break;
-        }
-    }
-    pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
-    return l_res;
+    dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, a_token_ticker);
+    if (!l_token_item)
+        return 0;
+    return l_token_item->auth_signs_valid;
 }
 
 /**
- * @breif dap_ledger_token_auth_signs_total
+ * @breif dap_ledger_token_get_auth_signs_total
  * @param a_ledger
  * @param a_token_ticker
  * @return
  */
-size_t dap_ledger_token_auth_signs_total(dap_ledger_t *a_ledger, const char * a_token_ticker)
+size_t dap_ledger_token_get_auth_signs_total(dap_ledger_t *a_ledger, const char *a_token_ticker)
 {
-    dap_ledger_token_item_t *l_token_item, *l_tmp_item;
-    pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
-    size_t l_res = 0;
-    HASH_ITER(hh, PVT(a_ledger)->tokens, l_token_item, l_tmp_item) {
-        if (!dap_strcmp(l_token_item->ticker, a_token_ticker)) {
-            l_res = l_token_item->auth_signs_total;
-            break;
-        }
-    }
-    pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
-    return l_res;
+    dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, a_token_ticker);
+    if (!l_token_item)
+        return 0;
+    return l_token_item->auth_signs_total;
 }
 
 /**
@@ -2212,96 +2215,65 @@ size_t dap_ledger_token_auth_signs_total(dap_ledger_t *a_ledger, const char * a_
  * @param a_token_ticker
  * @return
  */
-dap_list_t * dap_ledger_token_auth_pkeys_hashes(dap_ledger_t *a_ledger, const char * a_token_ticker)
+dap_list_t *dap_ledger_token_get_auth_pkeys_hashes(dap_ledger_t *a_ledger, const char *a_token_ticker)
 {
-    dap_list_t * l_ret = NULL;
-    dap_ledger_token_item_t *l_token_item, *l_tmp_item;
-    pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
-    HASH_ITER(hh, PVT(a_ledger)->tokens, l_token_item, l_tmp_item) {
-        if (!dap_strcmp(l_token_item->ticker, a_token_ticker)) {
-            debug_if(s_debug_more, L_INFO, " ! Token %s : total %lu auth signs", a_token_ticker, l_token_item->auth_signs_total);
-            for (size_t i = 0; i < l_token_item->auth_signs_total; i++) {
-                l_ret = dap_list_append(l_ret, (dap_chain_hash_fast_t*)(&l_token_item->auth_pkeys_hash[i]));
-            }
-            break;
-        }
-    }
-    pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+    dap_list_t *l_ret = NULL;
+    dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, a_token_ticker);
+    if (!l_token_item)
+        return l_ret;
+    debug_if(s_debug_more, L_INFO, " ! Token %s : total %lu auth signs", a_token_ticker, l_token_item->auth_signs_total);
+    for (size_t i = 0; i < l_token_item->auth_signs_total; i++)
+        l_ret = dap_list_append(l_ret, l_token_item->auth_pkey_hashes + i);
     return l_ret;
 }
 
-json_object *s_token_item_to_json(dap_ledger_token_item_t *a_token_item) {
+uint256_t dap_ledger_token_get_emission_rate(dap_ledger_t *a_ledger, const char *a_token_ticker)
+{
+    dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, a_token_ticker);
+    if (!l_token_item || !l_token_item->is_delegated)
+        return uint256_0;
+    return l_token_item->emission_rate;
+}
+
+json_object *s_token_item_to_json(dap_ledger_token_item_t *a_token_item)
+{
     json_object *json_obj_datum = json_object_new_object();
-    const char *l_type_str;
-    switch (a_token_item->type) {
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL: {
-            switch (a_token_item->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
-                    l_type_str = "SIMPLE"; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-                    l_type_str = "PRIVATE"; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-                    l_type_str = "CF20"; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC:
-                    l_type_str = "PUBLIC"; break;
-                default: l_type_str = "UNKNOWN"; break;
-            }
-        }break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE: {
-            switch (a_token_item->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
-                    l_type_str = "SIMPLE"; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
-                    l_type_str = "PRIVATE_UPDATE"; break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
-                    l_type_str = "CF20_UPDATE"; break;
-                default: l_type_str = "UNKNOWN"; break;
-            }
-        } break;
-        default:
-            l_type_str = "UNKNOWN"; break;
-    }
-    if ((a_token_item->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE)
-            ||	(a_token_item->type != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC)) {
-        char *l_balance_cur = dap_chain_balance_print(a_token_item->current_supply);
-        char *l_balance_total = dap_chain_balance_print(a_token_item->total_supply);
-        json_object_object_add(json_obj_datum, "-->Token name", json_object_new_string(a_token_item->ticker));
-        json_object_object_add(json_obj_datum, "type", json_object_new_string(l_type_str));
+    const char *l_type_str = NULL;
+    switch (a_token_item->subtype) {
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
+            l_type_str = "SIMPLE"; break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
+            l_type_str = "PRIVATE"; break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
+            l_type_str = "CF20"; break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC:
+            l_type_str = "PUBLIC"; break;
+        default: l_type_str = "UNKNOWN"; break;
+    }
+    json_object_object_add(json_obj_datum, "-->Token name", json_object_new_string(a_token_item->ticker));
+    json_object_object_add(json_obj_datum, "type", json_object_new_string(l_type_str));
+    if (a_token_item->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE && a_token_item->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC) {
         json_object_object_add(json_obj_datum, "flags", json_object_new_string(s_flag_str_from_code(a_token_item->datum_token->header_native_decl.flags)));
-        json_object_object_add(json_obj_datum, "description", a_token_item->description_token_size != 0 ?
-                               json_object_new_string(a_token_item->description_token) :
+        json_object_object_add(json_obj_datum, "description", a_token_item->description ?
+                               json_object_new_string(a_token_item->description) :
                                json_object_new_string("The token description is not set"));
-        json_object_object_add(json_obj_datum, "Supply current", json_object_new_string(l_balance_cur));
-        json_object_object_add(json_obj_datum, "Supply total", json_object_new_string(l_balance_total));
-        json_object_object_add(json_obj_datum, "Decimals", json_object_new_string("18"));
-        json_object_object_add(json_obj_datum, "Auth signs valid", json_object_new_int(a_token_item->auth_signs_valid));
-        json_object_object_add(json_obj_datum, "Auth signs total", json_object_new_int(a_token_item->auth_signs_total));
-        json_object_object_add(json_obj_datum, "TSD and Signs", json_object_new_string(""));
-        dap_datum_token_dump_tsd_to_json(json_obj_datum, a_token_item->datum_token, a_token_item->datum_token_size, "hex");
-        size_t l_certs_field_size = a_token_item->datum_token_size - sizeof(*a_token_item->datum_token) - a_token_item->datum_token->header_native_decl.tsd_total_size;
-        dap_chain_datum_token_certs_dump_to_json(json_obj_datum, a_token_item->datum_token->data_n_tsd + a_token_item->datum_token->header_native_decl.tsd_total_size,
-                                                l_certs_field_size, "hex");
-        json_object_object_add(json_obj_datum, "and TSD and Signs", json_object_new_string(""));
-        json_object_object_add(json_obj_datum, "Total emissions", json_object_new_int(HASH_COUNT(a_token_item->token_emissions)));
-        DAP_DEL_Z(l_balance_cur);
-        DAP_DEL_Z(l_balance_total);
-    } else {
-            char *l_balance_cur = dap_chain_balance_print(a_token_item->current_supply);
-            char *l_balance_total = dap_chain_balance_print(a_token_item->total_supply);
-            json_object_object_add(json_obj_datum, "-->Token name", json_object_new_string(a_token_item->ticker));
-            json_object_object_add(json_obj_datum, "Supply current", json_object_new_string(l_balance_cur));
-            json_object_object_add(json_obj_datum, "Supply total", json_object_new_string(l_balance_total));
-            json_object_object_add(json_obj_datum, "Decimals", json_object_new_string("18"));
-            json_object_object_add(json_obj_datum, "Auth signs valid", json_object_new_int(a_token_item->auth_signs_valid));
-            json_object_object_add(json_obj_datum, "Auth signs total", json_object_new_int(a_token_item->auth_signs_total));
-            json_object_object_add(json_obj_datum, "Signs", json_object_new_string(""));
-            size_t l_certs_field_size = a_token_item->datum_token_size - sizeof(*a_token_item->datum_token);
-            dap_chain_datum_token_certs_dump_to_json(json_obj_datum, a_token_item->datum_token->data_n_tsd,
-                                                     l_certs_field_size, "hex");
-            json_object_object_add(json_obj_datum, "Total emissions", json_object_new_int(HASH_COUNT(a_token_item->token_emissions)));
-            DAP_DEL_Z(l_balance_cur);
-            DAP_DEL_Z(l_balance_total);
     }
+    json_object_object_add(json_obj_datum, "Supply current", json_object_new_string(dap_uint256_to_char(a_token_item->current_supply, NULL)));
+    json_object_object_add(json_obj_datum, "Supply total", json_object_new_string(dap_uint256_to_char(a_token_item->total_supply, NULL)));
+    json_object_object_add(json_obj_datum, "Decimals", json_object_new_string("18"));
+    json_object_object_add(json_obj_datum, "Auth signs valid", json_object_new_int(a_token_item->auth_signs_valid));
+    json_object_object_add(json_obj_datum, "Auth signs total", json_object_new_int(a_token_item->auth_signs_total));
+    json_object *l_json_arr_pkeys = json_object_new_array();
+    for (uint16_t i = 0; i < a_token_item->auth_signs_total; i++) {
+        json_object *l_json_obj_out = json_object_new_object();
+        json_object_object_add(l_json_obj_out, "line", json_object_new_int(i));
+        json_object_object_add(l_json_obj_out, "hash", json_object_new_string(dap_hash_fast_to_str_static(a_token_item->auth_pkey_hashes + i)));
+        json_object_object_add(l_json_obj_out, "pkey_type", json_object_new_string(dap_pkey_type_to_str(a_token_item->auth_pkeys[i]->header.type)));
+        json_object_object_add(l_json_obj_out, "bytes", json_object_new_int(a_token_item->auth_pkeys[i]->header.size));
+        json_object_array_add(l_json_arr_pkeys, l_json_obj_out);
+    }
+    json_object_object_add(json_obj_datum, "Signature public keys", l_json_arr_pkeys);
+    json_object_object_add(json_obj_datum, "Total emissions", json_object_new_int(HASH_COUNT(a_token_item->token_emissions)));
     return json_obj_datum;
 }
 
@@ -2333,16 +2305,15 @@ json_object *dap_ledger_token_info(dap_ledger_t *a_ledger, size_t a_limit, size_
             l_arr_end = HASH_COUNT(PVT(a_ledger)->tokens);
         }
     }
-    size_t i_tmp = 0;
+    size_t i = 0;
     HASH_ITER(hh, PVT(a_ledger)->tokens, l_token_item, l_tmp_item) {
-        if (i_tmp < l_arr_start || i_tmp >= l_arr_end) {
-            i_tmp++;
+        if (i < l_arr_start || i >= l_arr_end) {
+            i++;
             continue;
         }
         json_obj_datum = s_token_item_to_json(l_token_item);
         json_object_array_add(json_arr_out, json_obj_datum);
-        i_tmp++;
-
+        i++;
     }
     pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
     return json_arr_out;
@@ -2695,15 +2666,10 @@ static bool s_load_cache_gdb_loaded_tokens_callback(dap_global_db_instance_t *a_
             log_it(L_WARNING, "Corrupted token with ticker [%s], need to 'ledger reload' to update cache", a_values[i].key);
             continue;
         }
-        // TODO: rework! Old token types may be passed unchecked!
-        dap_ledger_token_add(l_ledger, l_token, l_token_size);
-        dap_ledger_token_item_t *l_token_item = NULL;
-        HASH_FIND_STR(l_ledger_pvt->tokens, l_token->ticker, l_token_item);
-        if (!l_token_item) {
-            log_it(L_WARNING, "Can't load token with ticker [%s], need to 'ledger reload' to update cache", l_token->ticker);
-            continue;
-        }
-        l_token_item->current_supply = *(uint256_t*)a_values[i].value;
+        dap_ledger_token_add(l_ledger, (byte_t *)l_token, l_token_size);
+        dap_ledger_token_item_t *l_token_item = s_ledger_find_token(l_ledger, l_token->ticker);
+        if (l_token_item)
+            l_token_item->current_supply = *(uint256_t*)a_values[i].value;
     }
 
     char *l_gdb_group = dap_ledger_get_gdb_group(l_ledger, DAP_LEDGER_EMISSIONS_STR);
@@ -2755,6 +2721,7 @@ dap_ledger_t *dap_ledger_create(dap_chain_net_t *a_net, uint16_t a_flags)
     l_ledger_pvt->check_cells_ds = a_flags & DAP_LEDGER_CHECK_CELLS_DS;
     l_ledger_pvt->check_token_emission = a_flags & DAP_LEDGER_CHECK_TOKEN_EMISSION;
     l_ledger_pvt->cached = a_flags & DAP_LEDGER_CACHE_ENABLED;
+    l_ledger_pvt->mapped = a_flags & DAP_LEDGER_MAPPED;
     pthread_cond_init(&l_ledger_pvt->load_cond, NULL);
     pthread_mutex_init(&l_ledger_pvt->load_mutex, NULL);
 
@@ -2806,19 +2773,93 @@ dap_ledger_t *dap_ledger_create(dap_chain_net_t *a_net, uint16_t a_flags)
     return l_ledger;
 }
 
+enum ledger_permissions {
+    LEDGER_PERMISSION_RECEIVER_ALLOWED,
+    LEDGER_PERMISSION_RECEIVER_BLOCKED,
+    LEDGER_PERMISSION_SENDER_ALLOWED,
+    LEDGER_PERMISSION_SENDER_BLOCKED
+};
+
+/**
+ * @brief dap_ledger_permissions_check
+ * @param a_token_item
+ * @param a_permission_id
+ * @param a_data
+ * @param a_data_size
+ * @return
+ */
+static bool s_ledger_permissions_check(dap_ledger_token_item_t *a_token_item, enum ledger_permissions a_permission_id, dap_chain_addr_t *a_addr)
+{
+    dap_chain_addr_t *l_addrs = NULL;
+    size_t l_addrs_count = 0;
+    switch (a_permission_id) {
+    case LEDGER_PERMISSION_RECEIVER_ALLOWED:
+        l_addrs = a_token_item->tx_recv_allow;
+        l_addrs_count = a_token_item->tx_recv_allow_size;
+    break;
+    case LEDGER_PERMISSION_RECEIVER_BLOCKED:
+        l_addrs = a_token_item->tx_recv_block;
+        l_addrs_count = a_token_item->tx_recv_block_size;
+    break;
+    case LEDGER_PERMISSION_SENDER_ALLOWED:
+        l_addrs = a_token_item->tx_send_allow;
+        l_addrs_count = a_token_item->tx_send_allow_size;
+    break;
+    case LEDGER_PERMISSION_SENDER_BLOCKED:
+        l_addrs = a_token_item->tx_send_block;
+        l_addrs_count = a_token_item->tx_send_block_size;
+    break;
+    }
+    for (size_t n = 0; n < l_addrs_count; n++)
+        if (dap_chain_addr_compare(l_addrs + n, a_addr))
+            return true;
+    return false;
+}
+
+int s_ledger_addr_check(dap_ledger_token_item_t *a_token_item, dap_chain_addr_t *a_addr, bool a_receive)
+{
+    dap_return_val_if_fail(a_token_item && a_addr, DAP_LEDGER_CHECK_INVALID_ARGS);
+    if (dap_chain_addr_is_blank(a_addr))
+        return DAP_LEDGER_CHECK_OK;
+    if (a_receive) {
+        if ((a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_BLOCKED) ||
+                (a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN)) {
+            // Check we are in white list
+            if (!s_ledger_permissions_check(a_token_item, LEDGER_PERMISSION_RECEIVER_ALLOWED, a_addr))
+                return DAP_LEDGER_CHECK_ADDR_FORBIDDEN;
+        } else if ((a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_ALLOWED) ||
+                (a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_UNFROZEN)) {
+            // Check we are in black list
+            if (s_ledger_permissions_check(a_token_item, LEDGER_PERMISSION_RECEIVER_BLOCKED, a_addr))
+                return DAP_LEDGER_CHECK_ADDR_FORBIDDEN;
+        }
+    } else {
+        if ((a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_BLOCKED) ||
+                (a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_FROZEN)) {
+            // Check we are in white list
+            if (!s_ledger_permissions_check(a_token_item, LEDGER_PERMISSION_SENDER_ALLOWED, a_addr))
+                return DAP_LEDGER_CHECK_ADDR_FORBIDDEN;
+        } else if ((a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_ALLOWED) ||
+                (a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_UNFROZEN)) {
+            // Check we are in black list
+            if (s_ledger_permissions_check(a_token_item, LEDGER_PERMISSION_SENDER_BLOCKED, a_addr))
+                return DAP_LEDGER_CHECK_ADDR_FORBIDDEN;
+        }
+    }
+    return DAP_LEDGER_CHECK_OK;
+}
+
 int dap_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size, dap_chain_hash_fast_t *a_emission_hash)
 {
-    if (!a_token_emission || !a_token_emission_size)
-        return DAP_LEDGER_EMISSION_ADD_CHECK_EMS_IS_NULL;
+    dap_return_val_if_fail(a_token_emission && a_token_emission_size, DAP_LEDGER_CHECK_INVALID_ARGS);
 
-    int l_ret = DAP_LEDGER_EMISSION_ADD_OK;
+    int l_ret = DAP_LEDGER_CHECK_OK;
     dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
-
     const char *l_token_ticker = ((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.ticker;
     dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, l_token_ticker);
     if (!l_token_item) {
         log_it(L_ERROR, "Check emission: token %s was not found", l_token_ticker);
-        return DAP_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN;
+        return DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
     }
 
     dap_ledger_token_emission_item_t * l_token_emission_item = NULL;
@@ -2831,22 +2872,16 @@ int dap_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_
     pthread_rwlock_unlock(l_token_item ? &l_token_item->token_emissions_rwlock
                                        : &l_ledger_pvt->threshold_emissions_rwlock);
     if (l_token_emission_item) {
-        if(s_debug_more) {
-            char l_token_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-            dap_chain_hash_fast_to_str(a_emission_hash, l_token_hash_str, sizeof(l_token_hash_str));
-            if ( l_token_emission_item->datum_token_emission->hdr.version >= 2 ) {
-                log_it(L_ERROR, "Can't add token emission datum of %s %s ( %s ): already present in cache",
-                        dap_uint256_to_char(l_token_emission_item->datum_token_emission->hdr.value, NULL),
-                         l_token_ticker, l_token_hash_str);
-            } else
-                log_it(L_ERROR, "Can't add token emission datum of %"DAP_UINT64_FORMAT_U" %s ( %s ): already present in cache",
-                    l_token_emission_item->datum_token_emission->hdr.value64, l_token_ticker, l_token_hash_str);
-        }
-        l_ret = DAP_LEDGER_EMISSION_ADD_CHECK_EMS_ALREADY_CACHED;
-    }else if ( (! l_token_item) && ( l_threshold_emissions_count >= s_threshold_emissions_max)) {
-        if(s_debug_more)
-            log_it(L_WARNING,"Emissions threshold overflow, max %zu items", s_threshold_emissions_max);
-        l_ret = DAP_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_OVERFLOW;
+        debug_if(s_debug_more, L_ERROR, "Can't add token emission datum of %s %s ( %s ): already present in cache",
+                                    dap_uint256_to_char(l_token_emission_item->datum_token_emission->hdr.version >= 2
+                                                        ? l_token_emission_item->datum_token_emission->hdr.value
+                                                        : GET_256_FROM_64(l_token_emission_item->datum_token_emission->hdr.value64),
+                                                        NULL),
+                                    l_token_ticker, dap_chain_hash_fast_to_str_static(a_emission_hash));
+        l_ret = DAP_LEDGER_CHECK_ALREADY_CACHED;
+    } else if ( (! l_token_item) && ( l_threshold_emissions_count >= s_threshold_emissions_max)) {
+        debug_if(s_debug_more, L_WARNING, "Emissions threshold overflow, max %zu items", s_threshold_emissions_max);
+        l_ret = DAP_LEDGER_EMISSION_CHECK_THRESHOLD_OVERFLOW;
     }
     if (l_ret || !PVT(a_ledger)->check_token_emission)
         return l_ret;
@@ -2857,7 +2892,7 @@ int dap_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_
         if (l_hash_found) {
             char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
             dap_chain_hash_fast_to_str(a_emission_hash, l_hash_str, sizeof(l_hash_str));
-            debug_if(s_debug_more, L_MSG, "Event %s is whitelisted", l_hash_str);
+            debug_if(s_debug_more, L_MSG, "Datum %s is whitelisted", l_hash_str);
             return l_ret;
         }
     }
@@ -2869,24 +2904,26 @@ int dap_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_
     if (IS_ZERO_256((l_emission->hdr.value))) {
         log_it(L_ERROR, "Emission check: zero %s emission value", l_token_item->ticker);
         DAP_DELETE(l_emission);
-        return DAP_LEDGER_EMISSION_ADD_CHECK_ZERO_VALUE;
+        return DAP_LEDGER_CHECK_ZERO_VALUE;
     }
 
     if (!s_ledger_token_supply_check(l_token_item, l_emission->hdr.value))
-        return DAP_LEDGER_EMISSION_ADD_CHECK_VALUE_EXEEDS_CURRENT_SUPPLY;
+        return DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY;
 
     //additional check for private tokens
-    if ((l_token_item->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE)
+    if((l_token_item->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE)
         ||  (l_token_item->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE)) {
-        //s_ledger_permissions_check(l_token_item)
-        //    return -5;
-
+        if ((l_ret = s_ledger_addr_check(l_token_item, &((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.address, true))) {
+            log_it(L_WARNING, "Address %s is not in allowed to receive for emission of token %s",
+                   dap_chain_addr_to_str(&((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.address), l_token_item->ticker);
+            DAP_DELETE(l_emission);
+            return l_ret;
+        }
     }
     switch (l_emission->hdr.type){
-        case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH:{
+        case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH:{     
             dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, l_emission->hdr.ticker);
             if (l_token_item) {
-                assert(l_token_item->datum_token);
                 dap_sign_t *l_sign = (dap_sign_t *)(l_emission->tsd_n_signs + l_emission->data.type_auth.tsd_total_size);
                 size_t l_offset = (byte_t *)l_sign - (byte_t *)l_emission;
                 uint16_t l_aproves = 0, l_aproves_valid = l_token_item->auth_signs_valid;
@@ -2902,16 +2939,13 @@ int dap_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_
                 }
                 for (uint16_t i = 0; i < l_sign_auth_count && l_offset < l_emission_size; i++) {
                     if (dap_sign_verify_size(l_sign, l_emission_size - l_offset)) {
-                        dap_chain_hash_fast_t l_sign_pkey_hash;
-                        dap_sign_get_pkey_hash(l_sign, &l_sign_pkey_hash);
-                        // Find pkey in auth hashes
-                        for (uint16_t k=0; k< l_token_item->auth_signs_total; k++) {
-                            if (dap_hash_fast_compare(&l_sign_pkey_hash, &l_token_item->auth_pkeys_hash[k])) {
-                                // Verify if its token emission header signed
-                                if (!dap_sign_verify(l_sign, l_emi_ptr_check_size, l_sign_data_check_size)) {
+                        // Find pkey in auth pkeys
+                        for (uint16_t k = 0; k < l_token_item->auth_signs_total; k++) {
+                            if (dap_pkey_compare_with_sign(l_token_item->auth_pkeys[k], l_sign)) {
+                                // Verify if token emission is signed
+                                if (!dap_sign_verify(l_sign, l_emi_ptr_check_size, l_sign_data_check_size))
                                     l_aproves++;
-                                    break;
-                                }
+                                break;
                             }
                         }
                         size_t l_sign_size = dap_sign_get_size(l_sign);
@@ -2928,16 +2962,15 @@ int dap_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_
                     debug_if(s_debug_more, L_WARNING, "Emission of %s datoshi of %s:%s is wrong: only %u valid aproves when %u need",
                                 dap_uint256_to_char(l_emission->hdr.value, NULL), a_ledger->net->pub.name, l_emission->hdr.ticker,
                                 l_aproves, l_aproves_valid);
-                    l_ret = DAP_LEDGER_EMISSION_ADD_CHECK_NOT_ENOUGH_VALID_SIGNS;
+                    l_ret = DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS;
                     char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
                     dap_chain_hash_fast_to_str(a_emission_hash, l_hash_str, sizeof(l_hash_str));
                     log_it(L_MSG, "!!! Datum hash for HAL: %s", l_hash_str);
                 }
             }else{
-                debug_if(s_debug_more, L_WARNING,"Can't find token declaration %s:%s thats pointed in token emission datum",
-                    a_ledger->net->pub.name, l_emission->hdr.ticker);
-                    
-                l_ret = DAP_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN;
+                debug_if(s_debug_more, L_WARNING, "Can't find token declaration %s:%s thats pointed in token emission datum",
+                                                    a_ledger->net->pub.name, l_emission->hdr.ticker);
+                l_ret = DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
             }
         }break;
         default:{}
@@ -2946,50 +2979,6 @@ int dap_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_
     return l_ret;
 }
 
-bool s_ledger_token_address_check(dap_chain_addr_t * a_addrs, dap_chain_datum_token_emission_t *a_token_emission, size_t a_addrs_count)
-{
-    // if l_addrs is empty - nothing to check
-    dap_return_val_if_pass(!a_addrs, true);
-
-    for(size_t n = 0; n < a_addrs_count; n++ ){
-        dap_chain_addr_t l_addr = a_addrs[n];
-        if (memcmp(&l_addr,&a_token_emission->hdr.address,sizeof(dap_chain_addr_t))==0)
-            return true;
-    }
-
-    return false;
-}
-
-bool s_ledger_token_tsd_check(dap_ledger_token_item_t * a_token_item, dap_chain_datum_token_emission_t *a_token_emission)
-{
-    if (!a_token_item){
-        log_it(L_WARNING, "Token object is null. Probably, you set unknown token ticker in -token parameter");
-        return false;
-    }
-
-    // tsd section was parsed in s_token_tsd_parse
-
-    if ((a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_BLOCKED) ||
-        (a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN)) { // in white list
-        if (!s_ledger_token_address_check(a_token_item->tx_recv_allow, a_token_emission, a_token_item->tx_recv_allow_size)){
-            log_it(L_WARNING, "Address %s is not in tx_recv_allow for emission for token %s",
-                   dap_chain_addr_to_str(&a_token_emission->hdr.address), a_token_item->ticker);
-            return false;
-        }
-        return true;
-    }
-
-    if (a_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_ALLOWED) {
-        if (s_ledger_token_address_check(a_token_item->tx_recv_block, a_token_emission, a_token_item->tx_recv_block_size)){
-            log_it(L_WARNING, "Address %s is in tx_recv_block for emission for token %s",
-                   dap_chain_addr_to_str(&a_token_emission->hdr.address), a_token_item->ticker);
-            return false;
-        }
-    }
-
-    return true;
-}
-
 static void s_ledger_emission_cache_update(dap_ledger_t *a_ledger, dap_ledger_token_emission_item_t *a_emission_item)
 {
     if (!PVT(a_ledger)->cached)
@@ -3019,8 +3008,6 @@ int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emissi
 {
     dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
     dap_ledger_token_emission_item_t * l_token_emission_item = NULL;
-    char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-    dap_chain_hash_fast_to_str(a_emission_hash, l_hash_str, sizeof(l_hash_str));
     int l_ret = dap_ledger_token_emission_add_check(a_ledger, a_token_emission, a_token_emission_size, a_emission_hash);
     if (l_ret) {
         if (l_ret == DAP_CHAIN_CS_VERIFY_CODE_NO_DECREE) { // TODO remove emissions threshold
@@ -3028,13 +3015,13 @@ int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emissi
                 l_token_emission_item = DAP_NEW_Z(dap_ledger_token_emission_item_t);
                 if ( !l_token_emission_item ) {
                     log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-                    return DAP_LEDGER_EMISSION_ADD_MEMORY_PROBLEM;
+                    return DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
                 }
                 l_token_emission_item->datum_token_emission = DAP_DUP_SIZE(a_token_emission, a_token_emission_size);
                 if ( !l_token_emission_item->datum_token_emission ) {
                     DAP_DELETE(l_token_emission_item);
                     log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-                    return DAP_LEDGER_EMISSION_ADD_MEMORY_PROBLEM;
+                    return DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
                 }
                 l_token_emission_item->datum_token_emission_size = a_token_emission_size;
                 dap_hash_fast_t l_emi_hash = {0};
@@ -3056,7 +3043,7 @@ int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emissi
     const char *c_token_ticker = ((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.ticker;
     dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, c_token_ticker);
     if (!l_token_item && a_from_threshold)
-        return DAP_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN;
+        return DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
 
     // check if such emission is already present in table
     pthread_rwlock_rdlock( l_token_item ? &l_token_item->token_emissions_rwlock
@@ -3069,29 +3056,19 @@ int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emissi
         l_token_emission_item = DAP_NEW_Z(dap_ledger_token_emission_item_t);
         if ( !l_token_emission_item ) {
             log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            return DAP_LEDGER_EMISSION_ADD_MEMORY_PROBLEM;
+            return DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
         }
         l_token_emission_item->datum_token_emission_size = a_token_emission_size;
         l_token_emission_item->datum_token_emission_hash = *a_emission_hash;
         if (l_token_item) {
             l_token_emission_item->datum_token_emission = dap_chain_datum_emission_read(a_token_emission,
                                                                                         &l_token_emission_item->datum_token_emission_size);
-
-            //additional check for private tokens
-            if((l_token_item->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE)
-                ||  (l_token_item->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE)) {
-                if (!s_ledger_token_tsd_check(l_token_item, (dap_chain_datum_token_emission_t *)a_token_emission)) {
-                    DAP_DELETE(l_token_emission_item->datum_token_emission);
-                    DAP_DELETE(l_token_emission_item);
-                    return DAP_LEDGER_EMISSION_ADD_TSD_CHECK_FAILED;
-                }
-            }
             //Update value in ledger memory object
             if (!s_ledger_token_supply_check_update(a_ledger, l_token_item,
                                                     l_token_emission_item->datum_token_emission->hdr.value, false)) {
                 DAP_DELETE(l_token_emission_item->datum_token_emission);
                 DAP_DELETE(l_token_emission_item);
-                return DAP_LEDGER_EMISSION_ADD_CHECK_VALUE_EXEEDS_CURRENT_SUPPLY;
+                return DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY;
             }
 
             pthread_rwlock_wrlock(&l_token_item->token_emissions_rwlock);
@@ -3119,7 +3096,7 @@ int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emissi
             HASH_ADD(hh, l_ledger_pvt->threshold_emissions, datum_token_emission_hash,
                      sizeof(*a_emission_hash), l_token_emission_item);
             pthread_rwlock_unlock(&l_ledger_pvt->threshold_emissions_rwlock);
-            l_ret = -5;
+            l_ret = DAP_LEDGER_EMISSION_CHECK_THRESHOLDED;
             if (s_debug_more) {
                 const char *l_balance; dap_uint256_to_char(l_token_emission_item->datum_token_emission->hdr.value, &l_balance);
                 log_it(L_NOTICE, "Added token emission datum to emissions threshold: type=%s value=%s token=%s to_addr=%s ",
@@ -3133,7 +3110,7 @@ int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emissi
             if(s_debug_more)
                 log_it(L_WARNING,"threshold for emissions is overfulled (%zu max), dropping down new data, added nothing",
                    s_threshold_emissions_max);
-            l_ret = DAP_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_OVERFLOW;
+            l_ret = DAP_LEDGER_EMISSION_CHECK_THRESHOLD_OVERFLOW;
         }
     } else {
         if (l_token_item) {
@@ -3149,7 +3126,7 @@ int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emissi
                             ((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.value64, c_token_ticker, l_hash_str);
             }
         }
-        l_ret = DAP_LEDGER_EMISSION_ADD_CHECK_EMS_ALREADY_CACHED;
+        l_ret = DAP_LEDGER_CHECK_ALREADY_CACHED;
     }
     return l_ret;
 }
@@ -3236,12 +3213,6 @@ int dap_ledger_token_emission_load(dap_ledger_t *a_ledger, byte_t *a_token_emiss
     return dap_ledger_token_emission_add(a_ledger, a_token_emission, a_token_emission_size, a_token_emission_hash, false);
 }
 
-char *dap_ledger_token_emission_err_code_to_str(int a_code) {
-    return (a_code >= DAP_LEDGER_EMISSION_ADD_OK && a_code < DAP_LEDGER_EMISSION_ADD_UNKNOWN)
-            ? (char*)s_ledger_emission_add_err_str[(dap_ledger_emission_err_code_t)a_code]
-            : dap_itoa(a_code);
-}
-
 dap_ledger_token_emission_item_t *s_emission_item_find(dap_ledger_t *a_ledger,
                 const char *a_token_ticker, const dap_chain_hash_fast_t *a_token_emission_hash, dap_ledger_token_item_t **a_token_item)
 {
@@ -3309,65 +3280,6 @@ const char* dap_ledger_tx_get_token_ticker_by_hash(dap_ledger_t *a_ledger,dap_ch
     return l_item ? l_item->cache_data.token_ticker : NULL;
 }
 
-/**
- * @brief dap_ledger_addr_get_token_ticker_all_depricated
- * @param a_addr
- * @param a_tickers
- * @param a_tickers_size
- */
-void dap_ledger_addr_get_token_ticker_all_depricated(dap_ledger_t *a_ledger, dap_chain_addr_t * a_addr,
-        char *** a_tickers, size_t * a_tickers_size)
-{
-    dap_chain_hash_fast_t l_tx_first_hash = { 0 };
-    const dap_ledger_tx_item_t * l_tx_item = tx_item_find_by_addr(a_ledger, a_addr,NULL, &l_tx_first_hash);
-    char ** l_tickers = NULL;
-    size_t l_tickers_size = 10;
-    size_t l_tickers_pos = 0;
-
-    if(l_tx_item) {
-        l_tickers = DAP_NEW_Z_SIZE(char *, l_tickers_size * sizeof(char*));
-        if ( !l_tickers ) {
-            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            return;
-        }
-        while(l_tx_item) {
-            bool l_is_not_in_list = true;
-            for(size_t i = 0; i < l_tickers_size; i++) {
-                if (l_tickers[i]==NULL)
-                    break;
-                if(l_tickers[i] && strcmp(l_tickers[i], l_tx_item->cache_data.token_ticker) == 0) {
-                    l_is_not_in_list = false;
-                    break;
-                }
-            }
-            if(l_is_not_in_list) {
-                if((l_tickers_pos + 1) == l_tickers_size) {
-                    l_tickers_size += (l_tickers_size / 2);
-                    l_tickers = DAP_REALLOC(l_tickers, l_tickers_size);
-                    if ( !l_tickers ) {
-                        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-                        return;
-                    }
-                }
-                l_tickers[l_tickers_pos] = dap_strdup(l_tx_item->cache_data.token_ticker);
-                l_tickers_pos++;
-            }
-            dap_chain_hash_fast_t* l_tx_hash = dap_chain_node_datum_tx_calc_hash(l_tx_item->tx);
-            l_tx_item = tx_item_find_by_addr(a_ledger, a_addr, NULL, l_tx_hash);
-            DAP_DELETE(l_tx_hash);
-        }
-        l_tickers_size = l_tickers_pos + 1;
-        l_tickers = DAP_REALLOC(l_tickers, l_tickers_size * sizeof(char*));
-        if ( !l_tickers ) {
-            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            return;
-        }
-    }
-    *a_tickers = l_tickers;
-    *a_tickers_size = l_tickers_pos;
-}
-
-
 /**
  * @brief Get list of all tickets for ledger and address. If address is NULL returns all the tockens present in system
  * @param a_ledger
@@ -3431,7 +3343,7 @@ void dap_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chain_addr
 const char *dap_ledger_get_description_by_ticker(dap_ledger_t *a_ledger, const char *a_token_ticker){
     if (!a_ledger || !a_token_ticker)
         return NULL;
-    return s_ledger_find_token(a_ledger, a_token_ticker)->description_token;
+    return s_ledger_find_token(a_ledger, a_token_ticker)->description;
 }
 
 /**
@@ -3579,108 +3491,6 @@ bool dap_ledger_is_used_reward(dap_ledger_t *a_ledger, dap_hash_fast_t *a_block_
     return s_find_reward(a_ledger, &l_search_key);
 }
 
-/**
- * @brief dap_ledger_permissions_check
- * @param a_token_item
- * @param a_permission_id
- * @param a_data
- * @param a_data_size
- * @return
- */
-static int s_ledger_permissions_check(dap_ledger_token_item_t *  a_token_item, uint16_t a_permission_id, const void * a_data,size_t a_data_size )
-{
-    dap_chain_addr_t * l_addrs = NULL;
-    size_t l_addrs_count =0;
-    switch (a_permission_id) {
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD:
-            l_addrs = a_token_item->tx_recv_allow;
-            l_addrs_count = a_token_item->tx_recv_allow_size;
-        break;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD:
-            l_addrs = a_token_item->tx_recv_block;
-            l_addrs_count = a_token_item->tx_recv_block_size;
-        break;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD:
-            l_addrs = a_token_item->tx_send_allow;
-            l_addrs_count = a_token_item->tx_send_allow_size;
-        break;
-        case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD:
-            l_addrs = a_token_item->tx_send_block;
-            l_addrs_count = a_token_item->tx_send_block_size;
-        break;
-    }
-    if ( l_addrs && l_addrs_count){
-        if (a_data_size != sizeof (dap_chain_addr_t)){
-            log_it(L_ERROR,"Wrong data size %zd for ledger permission check", a_data_size);
-            return -2;
-        }
-        for(size_t n=0; n<l_addrs_count;n++ ){
-            if (memcmp(&l_addrs[n],a_data,a_data_size)==0)
-                return 0;
-        }
-        return -1;
-    }
-    return -10;
-}
-
-/**
- * Match the signature of the emission with the transaction
- *
- * return true or false
- */
-bool s_tx_match_sign(dap_chain_datum_token_emission_t *a_datum_emission, dap_chain_datum_tx_t *a_tx)
-{
-    if(!a_datum_emission || !a_tx) {
-        return false;
-    }
-    // First emission sign
-    dap_sign_t *l_emission_sign = (dap_sign_t*) (a_datum_emission->tsd_n_signs + a_datum_emission->data.type_auth.tsd_total_size);
-    size_t l_emission_sign_offset = (byte_t*) l_emission_sign - (byte_t*) a_datum_emission;
-    int l_emission_sign_num = a_datum_emission->data.type_auth.signs_count;
-
-    // Get all tx signs
-    int l_tx_sign_num = 0;
-    dap_list_t *l_list_sig = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_SIG, &l_tx_sign_num);
-
-    if(!l_emission_sign_num || !l_tx_sign_num)
-        return false;
-
-    size_t l_emission_size = dap_chain_datum_emission_get_size((uint8_t*) a_datum_emission);
-    dap_sign_t *l_sign = (dap_sign_t*) (a_datum_emission->tsd_n_signs + a_datum_emission->data.type_auth.tsd_total_size);
-    size_t l_offset = (byte_t*) l_sign - (byte_t*) a_datum_emission;
-    for(uint16_t i = 0; i < a_datum_emission->data.type_auth.signs_count && l_offset < l_emission_size; i++) {
-        if(dap_sign_verify_size(l_sign, l_emission_size - l_offset)) {
-            dap_chain_hash_fast_t l_sign_pkey_hash;
-            dap_sign_get_pkey_hash(l_sign, &l_sign_pkey_hash);
-
-            size_t l_sign_size = dap_sign_get_size(l_sign);
-            l_offset += l_sign_size;
-            l_sign = (dap_sign_t*) ((byte_t*) a_datum_emission + l_offset);
-        } else
-            break;
-    }
-    // For each emission signs
-    for(int l_sign_em_num = 0; l_sign_em_num < l_emission_sign_num && l_emission_sign_offset < l_emission_size; l_sign_em_num++) {
-        // For each tx signs
-        for(dap_list_t *it = l_list_sig; it; it = dap_list_next(it)) {
-            dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) it->data;
-            // Get sign from sign item
-            dap_sign_t *l_tx_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t*) l_tx_sig);
-            // Compare signs
-            if(dap_sign_compare_pkeys(l_emission_sign, l_tx_sign)) {
-                dap_list_free(l_list_sig);
-                return true;
-            }
-        }
-        // Go to the next emission sign
-        size_t l_sign_size = dap_sign_get_size(l_emission_sign);
-        l_emission_sign_offset += l_sign_size;
-        l_emission_sign = (dap_sign_t*) ((byte_t*) a_datum_emission + l_emission_sign_offset);
-    }
-    dap_list_free(l_list_sig);
-    return false;
-}
-
 static int s_callback_sign_compare(dap_list_t *a_list_elem, dap_list_t *a_sign_elem)
 {
     dap_pkey_t *l_key = (dap_pkey_t *)a_list_elem->data;
@@ -3689,7 +3499,7 @@ static int s_callback_sign_compare(dap_list_t *a_list_elem, dap_list_t *a_sign_e
         log_it(L_CRITICAL, "Invalid argument");
         return -1;
     }
-    return !dap_pkey_match_sign(l_key, l_sign);
+    return !dap_pkey_compare_with_sign(l_key, l_sign);
 }
 
 bool dap_ledger_tx_poa_signed(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
@@ -3761,7 +3571,6 @@ bool dap_ledger_tx_service_info(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_ha
 {
     //find tx
     dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
-    dap_chain_datum_tx_t *l_tx_ret = NULL;
     dap_ledger_tx_item_t *l_tx_item;
     pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock);
     HASH_FIND(hh, l_ledger_pvt->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_item);
@@ -3842,21 +3651,18 @@ bool dap_ledger_deduct_tx_tag(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx
  * return 0 OK, otherwise error
  */
 // Checking a new transaction before adding to the cache
-int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
-                                 dap_chain_datum_tx_t *a_tx,
-                                  dap_hash_fast_t *a_tx_hash,
-                                    bool a_from_threshold, 
-                                    dap_list_t **a_list_bound_items,
-                                     dap_list_t **a_list_tx_out,
-                                      char **a_main_ticker,
-                                      dap_chain_net_srv_uid_t *a_tag,
-                                      dap_chain_tx_tag_action_type_t *a_action, 
-                                      bool a_check_for_removing)
+static int s_tx_cache_check(dap_ledger_t *a_ledger,
+                            dap_chain_datum_tx_t *a_tx,
+                            dap_hash_fast_t *a_tx_hash,
+                            bool a_from_threshold,
+                            dap_list_t **a_list_bound_items,
+                            dap_list_t **a_list_tx_out,
+                            char **a_main_ticker,
+                            dap_chain_net_srv_uid_t *a_tag,
+                            dap_chain_tx_tag_action_type_t *a_action,
+                            bool a_check_for_removing)
 {
-    if (!a_tx) {
-        log_it(L_DEBUG, "NULL transaction, check broken");
-        return DAP_LEDGER_TX_CHECK_NULL_TX;
-    }
+    dap_return_val_if_fail(a_ledger && a_tx && a_tx_hash, DAP_LEDGER_CHECK_INVALID_ARGS);
     if (!dap_chain_net_get_load_mode(a_ledger->net) && !a_from_threshold && !a_check_for_removing) {
         dap_ledger_tx_item_t *l_ledger_item;
         pthread_rwlock_rdlock(&PVT(a_ledger)->ledger_rwlock);
@@ -3870,7 +3676,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                 if (a_tag) *a_tag = l_ledger_item->cache_data.tag;
                 if (a_action) *a_action = l_ledger_item->cache_data.action;
             }
-            return DAP_LEDGER_TX_ALREADY_CACHED;
+            return DAP_LEDGER_CHECK_ALREADY_CACHED;
         }
     }
 /*
@@ -3898,12 +3704,12 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                                  *l_value_cur = NULL, *l_tmp = NULL, *l_res = NULL;
     const char *l_token = NULL, *l_main_ticker = NULL;
 
-    int l_err_num = DAP_LEDGER_TX_CHECK_OK;
+    int l_err_num = DAP_LEDGER_CHECK_OK;
     int l_prev_tx_count = 0;
 
     // 1. Verify signature in current transaction
     if (!a_from_threshold && dap_chain_datum_tx_verify_sign(a_tx))
-        return DAP_LEDGER_TX_CHECK_INVALID_TX_SIGN;
+        return DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS;
 
     // ----------------------------------------------------------------
     // find all 'in' && 'in_cond' && 'in_ems' && 'in_reward'  items in current transaction
@@ -3924,7 +3730,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
          dap_ledger_tx_bound_t *l_bound_item = DAP_NEW_Z(dap_ledger_tx_bound_t);
         if (!l_bound_item) {
             log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            l_err_num = DAP_LEDGER_TX_CHECK_MEMORY_PROBLEM;
+            l_err_num = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
             break;
         }
         l_list_bound_items = dap_list_append(l_list_bound_items, l_bound_item);
@@ -3943,7 +3749,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
             dap_chain_tx_in_ems_t *l_tx_in_ems = it->data;
             l_token = l_tx_in_ems->header.ticker;
             if (!s_ledger_check_token_ticker(l_token)) {
-                l_err_num = DAP_LEDGER_TX_CHECK_INVALID_TICKER;
+                l_err_num = DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
                 break;
             }
             dap_hash_fast_t *l_emission_hash = &l_tx_in_ems->header.token_emission_hash;
@@ -3990,31 +3796,26 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                     l_err_num = DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION;
                     break;
                 }
-                dap_tsd_t *l_tsd;
+
                 dap_ledger_token_item_t *l_delegated_item = s_ledger_find_token(a_ledger, l_token);
                 if (!l_delegated_item) {
                     debug_if(s_debug_more, L_WARNING, "Token [%s] not found", l_token);
-                    l_err_num = DAP_LEDGER_TX_CHECK_TICKER_NOT_FOUND;
+                    l_err_num = DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
                     break;
                 }
-                dap_chain_datum_token_t *l_datum_token = l_delegated_item->datum_token;
-                if (l_datum_token->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE ||
-                        !(l_tsd = dap_tsd_find(l_datum_token->data_n_tsd,
-                                                  l_datum_token->header_native_decl.tsd_total_size,
-                                                  DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) {
+                if (!l_delegated_item->is_delegated) {
                     debug_if(s_debug_more, L_WARNING, "Token [%s] not valid for stake_lock transaction", l_token);
                     l_err_num = DAP_LEDGER_TX_CHECK_STAKE_LOCK_INVALID_TOKEN;
                     break;
                 }
-                dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
-                if (!dap_ledger_token_ticker_check(a_ledger, (char*)l_tsd_section->ticker_token_from)) {
-                    debug_if(s_debug_more, L_WARNING, "Token [%s] not found", l_tsd_section->ticker_token_from);
-                    l_err_num = DAP_LEDGER_TX_CHECK_TICKER_NOT_FOUND;
+                if (!dap_ledger_token_ticker_check(a_ledger, l_delegated_item->delegated_from)) {
+                    debug_if(s_debug_more, L_WARNING, "Token [%s] not found", l_delegated_item->delegated_from);
+                    l_err_num = DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
                     break;
                 }
 
                 if (l_girdled_ems)
-                    l_main_ticker = (const char *)l_tsd_section->ticker_token_from;
+                    l_main_ticker = l_delegated_item->delegated_from;
 
                 dap_chain_tx_out_cond_t *l_tx_stake_lock_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_stake_lock, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, NULL);
                 if (!l_tx_stake_lock_out_cond) {
@@ -4023,16 +3824,15 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                     break;
                 }
                 uint256_t l_value_expected ={};
-                if (MULT_256_COIN(l_tx_stake_lock_out_cond->header.value, l_tsd_section->emission_rate, &l_value_expected)!=0){
-                    if(s_debug_more){
-                        char * l_emission_rate_str = dap_chain_balance_print(l_tsd_section->emission_rate);
-                        char * l_locked_value_str = dap_chain_balance_print(l_tx_stake_lock_out_cond->header.value);
-                        log_it( L_WARNING, "Multiplication overflow for %s emission: locked value %s emission rate %s"
-                        , l_tx_in_ems->header.ticker, l_locked_value_str, l_emission_rate_str);
+                if (MULT_256_COIN(l_tx_stake_lock_out_cond->header.value, l_delegated_item->emission_rate, &l_value_expected)) {
+                    if (s_debug_more) {
+                        char *l_emission_rate_str = dap_chain_balance_to_coins(l_delegated_item->emission_rate);
+                        const char *l_locked_value_str; dap_uint256_to_char(l_tx_stake_lock_out_cond->header.value, &l_locked_value_str);
+                        log_it( L_WARNING, "Multiplication overflow for %s emission: locked value %s emission rate %s",
+                                                                l_tx_in_ems->header.ticker, l_locked_value_str, l_emission_rate_str);
                         DAP_DEL_Z(l_emission_rate_str);
-                        DAP_DEL_Z(l_locked_value_str);
                     }
-                    l_err_num = DAP_LEDGER_TX_CHECK_MULT256_OVERFLOW_EMS_LOCKED_X_RATE;
+                    l_err_num = DAP_LEDGER_CHECK_INTEGER_OVERFLOW;
                     break;
                 }
                 dap_chain_tx_out_ext_t *l_tx_out_ext = NULL;
@@ -4060,7 +3860,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                 } else
                     l_stake_lock_ems_value = l_tx_out_ext->header.value;
                 if (!s_ledger_token_supply_check(l_delegated_item, l_stake_lock_ems_value)) {
-                    l_err_num = DAP_LEDGER_TX_CHECK_TOKEN_EMS_VALUE_EXEEDS_CUR_SUPPLY;
+                    l_err_num = DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY;
                     break;
                 }
                 if (!EQUAL_256(l_value_expected, l_stake_lock_ems_value)) {
@@ -4084,10 +3884,10 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                     const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_ledger, l_emission_hash);
                     if (!l_tx_ticker) {
                         debug_if(s_debug_more, L_WARNING, "No ticker found for stake_lock tx [expected '%s']", l_tx_in_ems->header.ticker);
-                        l_err_num = DAP_LEDGER_TX_CHECK_STAKE_LOCK_TICKER_NOT_FOUND;
+                        l_err_num = DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
                         break;
                     }
-                    if (strcmp(l_tx_ticker, (char *)l_tsd_section->ticker_token_from)) {
+                    if (strcmp(l_tx_ticker, l_delegated_item->delegated_from)) {
                         debug_if(s_debug_more, L_WARNING, "Ticker '%s' != expected '%s'", l_tx_ticker, l_tx_in_ems->header.ticker);
                         l_err_num = DAP_LEDGER_TX_CHECK_STAKE_LOCK_OTHER_TICKER_EXPECTED;
                         break;
@@ -4180,11 +3980,11 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
             dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, l_token);
             if (!l_token_item) {
                 debug_if(s_debug_more, L_ERROR, "Native token ticker not found");
-                l_err_num = DAP_LEDGER_TX_CHECK_TICKER_NOT_FOUND;
+                l_err_num = DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
                 break;
             }
             if (!s_ledger_token_supply_check(l_token_item, l_value) && !a_check_for_removing) {
-                l_err_num = DAP_LEDGER_TX_CHECK_TOKEN_EMS_VALUE_EXEEDS_CUR_SUPPLY;
+                l_err_num = DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY;
                 break;
             }
             l_bound_item->token_item = l_token_item;
@@ -4319,38 +4119,21 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
 
                 if ( !l_token || !*l_token ) {
                     log_it(L_WARNING, "No token ticker found in previous transaction");
-                    l_err_num = DAP_LEDGER_TX_CHECK_PREV_TICKER_NOT_FOUND;
+                    l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER;
                     break;
                 }
                 // Get permissions
                 dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, l_token);
                 if (!l_token_item) {
                     debug_if(s_debug_more, L_WARNING, "Token with ticker %s not found", l_token);
-                    l_err_num = DAP_LEDGER_TX_CHECK_PREV_TOKEN_NOT_FOUND;
+                    l_err_num = DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
                     break;
                 }
                 // Check permissions
-                if ( (l_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_BLOCKED ) ||  // If all is blocked - check if we're
-                     (l_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN) ){ // in white list
-
-                    if (!dap_chain_addr_is_blank(l_addr_from) && s_ledger_permissions_check(l_token_item,
-                                                   DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD, l_addr_from,
-                                                  sizeof(*l_addr_from)) != 0 ){
-                        const char *l_tmp_tx_in_from = dap_chain_addr_to_str(l_addr_from);
-                        debug_if(s_debug_more, L_WARNING, "No permission for addr %s", l_tmp_tx_in_from ? l_tmp_tx_in_from : "(null)");
-                        l_err_num = DAP_LEDGER_PERMISSION_CHECK_FAILED;
-                        break;
-                    }
-                }
-                if ((l_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_ALLOWED ) || // If all is allowed - check if we're
-                    (l_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_SENDER_UNFROZEN ) ){ // in black list
-                    if (s_ledger_permissions_check(l_token_item, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD, l_addr_from,
-                                                  sizeof(*l_addr_from)) == 0 ){
-                        const char *l_tmp_tx_in_from = dap_chain_addr_to_str(l_addr_from);
-                        debug_if(s_debug_more, L_WARNING, "No permission for addr %s", l_tmp_tx_in_from ? l_tmp_tx_in_from : "(null)");
-                        l_err_num = DAP_LEDGER_PERMISSION_CHECK_FAILED;
-                        break;
-                    }
+                if (s_ledger_addr_check(l_token_item, l_addr_from, false) == DAP_LEDGER_CHECK_ADDR_FORBIDDEN) {
+                    debug_if(s_debug_more, L_WARNING, "No permission to send for addr %s", dap_chain_addr_to_str(l_addr_from));
+                    l_err_num = DAP_LEDGER_CHECK_ADDR_FORBIDDEN;
+                    break;
                 }
             } else { // l_cond_type == TX_ITEM_TYPE_IN_COND
                 if(*(uint8_t *)l_tx_prev_out != TX_ITEM_TYPE_OUT_COND) {
@@ -4360,6 +4143,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                 dap_chain_tx_out_cond_t *l_tx_prev_out_cond = NULL;
                 l_tx_prev_out_cond = (dap_chain_tx_out_cond_t *)l_tx_prev_out;
 
+                // 5a. Check for condition owner
                 // Get owner tx
                 dap_hash_fast_t *l_owner_tx_hash = dap_ledger_get_first_chain_tx_hash(a_ledger, l_tx_prev, l_tx_prev_out_cond);
                 dap_chain_datum_tx_t *l_owner_tx = l_tx_prev;
@@ -4367,9 +4151,6 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                     l_owner_tx = dap_ledger_tx_find_by_hash(a_ledger, l_owner_tx_hash);
                     DAP_DEL_Z(l_owner_tx_hash);
                 }
-
-                // 5a. Check for condition owner
-                dap_chain_tx_sig_t *l_tx_prev_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_tx_prev, NULL, TX_ITEM_TYPE_SIG, NULL);
                 dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL);
                 dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig);
                 dap_chain_tx_sig_t *l_owner_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_owner_tx, NULL, TX_ITEM_TYPE_SIG, NULL);
@@ -4390,9 +4171,10 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                     l_err_num = DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET;
                     break;
                 }
-                if (l_verificator->callback(a_ledger, l_tx_prev_out_cond, a_tx, l_owner) == false) {
-                    debug_if(s_debug_more, L_WARNING, "Verificator check error for conditional output %s",
-                                                        dap_chain_tx_out_cond_subtype_to_str(l_sub_tmp));
+                int l_verificator_error = l_verificator->callback(a_ledger, l_tx_prev_out_cond, a_tx, l_owner);
+                if (l_verificator_error != DAP_LEDGER_CHECK_OK) { // TODO add string representation for verificator return codes
+                    debug_if(s_debug_more, L_WARNING, "Verificator check error %d for conditional output %s",
+                                                                    l_verificator_error, dap_chain_tx_out_cond_subtype_to_str(l_sub_tmp));
                     l_err_num = DAP_LEDGER_TX_CHECK_VERIFICATOR_CHECK_FAILURE;
                     break;
                 }
@@ -4419,7 +4201,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
             // If not checked earlier
             if (!l_token || !*l_token) {
                 log_it(L_WARNING, "No token ticker found in previous transaction");
-                l_err_num = DAP_LEDGER_TX_CHECK_PREV_TICKER_NOT_FOUND;
+                l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER;
                 break;
             }
         }
@@ -4428,7 +4210,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
             l_value_cur = DAP_NEW_Z(dap_ledger_tokenizer_t);
             if ( !l_value_cur ) {
                 log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-                l_err_num = DAP_LEDGER_TX_CHECK_MEMORY_PROBLEM;
+                l_err_num = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
                 break;
             }
             strcpy(l_value_cur->token_ticker, l_token);
@@ -4438,7 +4220,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
         if (SUM_256_256(l_value_cur->sum, l_value, &l_value_cur->sum)) {
             debug_if(s_debug_more, L_WARNING, "Sum result overflow for tx_add_check with ticker %s",
                                     l_value_cur->token_ticker);
-            l_err_num = -88;
+            l_err_num = DAP_LEDGER_CHECK_INTEGER_OVERFLOW;
             break;
         }
     }
@@ -4472,7 +4254,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
         l_value_cur = DAP_NEW_Z(dap_ledger_tokenizer_t);
         if ( !l_value_cur ) {
             log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            l_err_num = DAP_LEDGER_TX_CHECK_MEMORY_PROBLEM;
+            l_err_num = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
             if ( l_list_bound_items )
                 dap_list_free_full(l_list_bound_items, NULL);
             HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) {
@@ -4502,7 +4284,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
         case TX_ITEM_TYPE_OUT_OLD: {
             dap_chain_tx_out_old_t *l_tx_out = (dap_chain_tx_out_old_t *)it->data;
             if (l_multichannel) { // token ticker is mandatory for multichannel transactions
-                l_err_num = -16;
+                l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER;
                 break;
             }
             l_value = dap_chain_uint256_from(l_tx_out->header.value);
@@ -4515,7 +4297,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                 if (l_main_ticker)
                     l_token = l_main_ticker;
                 else {
-                    l_err_num = -16;
+                    l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER;
                     break;
                 }
             }
@@ -4525,8 +4307,8 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
         } break;
         case TX_ITEM_TYPE_OUT_EXT: { // 256
             dap_chain_tx_out_ext_t *l_tx_out = (dap_chain_tx_out_ext_t *)it->data;
-            if (!l_multichannel) { // token ticker is depricated for single-channel transactions
-                l_err_num = -16;
+            if (!l_multichannel) { // token ticker is forbiden for single-channel transactions
+                l_err_num = DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT;
                 break;
             }
             l_value = l_tx_out->header.value;
@@ -4543,7 +4325,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                     l_token = l_main_ticker;
                 else {
                     log_it(L_WARNING, "No conditional output support for multichannel transaction");
-                    l_err_num = -18;
+                    l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER;
                     break;
                 }
             }
@@ -4552,7 +4334,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
             if (l_tax_check && l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE &&
                     SUBTRACT_256_256(l_taxed_value, l_value, &l_taxed_value)) {
                 log_it(L_WARNING, "Fee is greater than sum of inputs");
-                l_err_num = -98;
+                l_err_num = DAP_LEDGER_CHECK_INTEGER_OVERFLOW;
                 break;
             }
         } break;
@@ -4566,7 +4348,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
                 l_value_cur = DAP_NEW_Z(dap_ledger_tokenizer_t);
                 if ( !l_value_cur ) {
                     log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-                    l_err_num = DAP_LEDGER_TX_CHECK_MEMORY_PROBLEM;
+                    l_err_num = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY;
                     break;
                 }
                 strcpy(l_value_cur->token_ticker, l_token);
@@ -4576,41 +4358,23 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
         if (SUM_256_256(l_value_cur->sum, l_value, &l_value_cur->sum)) {
             debug_if(s_debug_more, L_WARNING, "Sum result overflow for tx_add_check with ticker %s",
                                     l_value_cur->token_ticker);
-            l_err_num = -77;
+            l_err_num = DAP_LEDGER_CHECK_INTEGER_OVERFLOW;
             break;
         }
 
-        // Get permissions for token
+        // Find token item
         dap_ledger_token_item_t *l_token_item = s_ledger_find_token(a_ledger, l_token);
         if (!l_token_item) {
             debug_if(s_debug_more, L_WARNING, "Token with ticker %s not found", l_token);
-            l_err_num = -15;
+            l_err_num = DAP_LEDGER_CHECK_TICKER_NOT_FOUND;
             break;
         }
         // Check permissions
-
-        if ( (l_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_BLOCKED )||   //  If all is blocked or frozen
-             (l_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_FROZEN) ){ //  check if we're in white list
-            if(!dap_chain_addr_is_blank(&l_tx_out_to) && s_ledger_permissions_check(l_token_item, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD,&l_tx_out_to ,
-                                          sizeof (l_tx_out_to)) != 0 ){
-                const char *l_tmp_tx_out_to = dap_chain_addr_to_str(&l_tx_out_to);
-                debug_if(s_debug_more, L_WARNING, "No permission for addr %s", l_tmp_tx_out_to?l_tmp_tx_out_to:"(null)");
-                l_err_num = -20;
-                break;
-            }
-        }
-        if ( (l_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_ALLOWED )||
-             (l_token_item->flags & DAP_CHAIN_DATUM_TOKEN_FLAG_ALL_RECEIVER_UNFROZEN )
-             ){ // If all is allowed - check if we're in black list
-            if(s_ledger_permissions_check(l_token_item, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD ,&l_tx_out_to,
-                                          sizeof (l_tx_out_to)) == 0 ){
-                const char *l_tmp_tx_out_to = dap_chain_addr_to_str(&l_tx_out_to);
-                debug_if(s_debug_more, L_WARNING, "No permission for addr %s", l_tmp_tx_out_to?l_tmp_tx_out_to:"(null)");
-                l_err_num = -22;
-                break;
-            }
+        if (s_ledger_addr_check(l_token_item, &l_tx_out_to, true) == DAP_LEDGER_CHECK_ADDR_FORBIDDEN) {
+            debug_if(s_debug_more, L_WARNING, "No permission to receive for addr %s", dap_chain_addr_to_str(&l_tx_out_to));
+            l_err_num = DAP_LEDGER_CHECK_ADDR_FORBIDDEN;
+            break;
         }
-
         if (l_fee_check && dap_chain_addr_compare(&l_tx_out_to, &a_ledger->net->pub.fee_addr) &&
                 !dap_strcmp(l_value_cur->token_ticker, a_ledger->net->pub.native_ticker))
             SUM_256_256(l_fee_sum, l_value, &l_fee_sum);
@@ -4650,13 +4414,13 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
             char *l_current_fee = dap_chain_balance_to_coins(l_fee_sum);
             char *l_expected_fee = dap_chain_balance_to_coins(a_ledger->net->pub.fee_value);
             log_it(L_WARNING, "Fee value is invalid, expected %s pointed %s", l_expected_fee, l_current_fee);
-            l_err_num = -54;
+            l_err_num = DAP_LEDGER_TX_CHECK_NOT_ENOUGH_FEE;
             DAP_DEL_Z(l_current_fee);
             DAP_DEL_Z(l_expected_fee);
         }
         if (l_tax_check && SUBTRACT_256_256(l_taxed_value, l_fee_sum, &l_taxed_value)) {
             log_it(L_WARNING, "Fee is greater than sum of inputs");
-            l_err_num = -89;
+            l_err_num = DAP_LEDGER_CHECK_INTEGER_OVERFLOW;
         }
     }
 
@@ -4668,7 +4432,7 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
             char *l_current_tax_str = dap_chain_balance_to_coins(l_tax_sum);
             char *l_expected_tax_str = dap_chain_balance_to_coins(l_expected_tax);
             log_it(L_WARNING, "Tax value is invalid, expected %s pointed %s", l_expected_tax_str, l_current_tax_str);
-            l_err_num = -55;
+            l_err_num = DAP_LEDGER_TX_CHECK_NOT_ENOUGH_TAX;
             DAP_DEL_Z(l_current_tax_str);
             DAP_DEL_Z(l_expected_tax_str);
         }
@@ -4734,20 +4498,18 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger,
  */
 int dap_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, size_t a_datum_size, dap_hash_fast_t *a_datum_hash)
 {
-    dap_return_val_if_pass(!a_tx, DAP_LEDGER_TX_CHECK_NULL_TX);
+    dap_return_val_if_fail(a_tx && a_ledger, DAP_LEDGER_CHECK_INVALID_ARGS);
 
     size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx);
     if (l_tx_size != a_datum_size) {
         log_it (L_WARNING, "Inconsistent datum TX: datum size %zu != tx size %zu", a_datum_size, l_tx_size);
-        return DAP_LEDGER_TX_CHECK_INVALID_TX_SIZE;
+        return DAP_LEDGER_CHECK_INVALID_SIZE;
     }
-
-    int l_ret_check = dap_ledger_tx_cache_check(a_ledger, a_tx, a_datum_hash,
-                                                      false, NULL, NULL, NULL, NULL, NULL, false);
+    int l_ret_check = s_tx_cache_check(a_ledger, a_tx, a_datum_hash, false, NULL, NULL, NULL, NULL, NULL, false);
     if(s_debug_more) {
         if (l_ret_check)
             log_it(L_NOTICE, "Ledger TX adding check not passed for TX %s: error %s",
-                   dap_chain_hash_fast_to_str_static(a_datum_hash), dap_ledger_tx_check_err_str(l_ret_check));
+                   dap_chain_hash_fast_to_str_static(a_datum_hash), dap_ledger_check_error_str(l_ret_check));
         else
             log_it(L_INFO, "Ledger TX adding check passed for TX %s", dap_chain_hash_fast_to_str_static(a_datum_hash));
     }
@@ -4816,7 +4578,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
     dap_chain_net_srv_uid_t l_tag =  { .uint64 = 0 }; 
     dap_chain_tx_tag_action_type_t l_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
 
-    if( (l_ret_check = dap_ledger_tx_cache_check(a_ledger, a_tx, a_tx_hash, a_from_threshold,
+    if( (l_ret_check = s_tx_cache_check(a_ledger, a_tx, a_tx_hash, a_from_threshold,
                                                        &l_list_bound_items, &l_list_tx_out,
                                                        &l_main_token_ticker, &l_tag, &l_action, false))) {
         if (l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS ||
@@ -4855,7 +4617,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
             }
         } else {
             debug_if(s_debug_more, L_WARNING, "dap_ledger_tx_add() tx %s not passed the check: %s ", l_tx_hash_str,
-                        dap_ledger_tx_check_err_str(l_ret_check));
+                        dap_ledger_check_error_str(l_ret_check));
         }
         
         if ( l_list_bound_items )
@@ -5197,11 +4959,11 @@ int dap_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap
     // Get boundary items list into l_list_bound_items
     // Get tx outs list into l_list_tx_out
     int l_ret_check;
-    if( (l_ret_check = dap_ledger_tx_cache_check(a_ledger, a_tx, a_tx_hash, false,
+    if( (l_ret_check = s_tx_cache_check(a_ledger, a_tx, a_tx_hash, false,
                                                        &l_list_bound_items, &l_list_tx_out,
                                                        &l_main_token_ticker, NULL, NULL, true))) {
         debug_if(s_debug_more, L_WARNING, "dap_ledger_tx_remove() tx %s not passed the check: %s ", l_tx_hash_str,
-                    dap_ledger_tx_check_err_str(l_ret_check));
+                    dap_ledger_check_error_str(l_ret_check));
         return l_ret_check;
     }
 
@@ -5478,7 +5240,7 @@ int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_c
         HASH_FIND_BYHASHVALUE(hh, PVT(a_ledger)->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value, l_tx_item);
         if (l_tx_item) {
             pthread_rwlock_unlock(&PVT(a_ledger)->ledger_rwlock);
-            return DAP_LEDGER_TX_ALREADY_CACHED;
+            return DAP_LEDGER_CHECK_ALREADY_CACHED;
         }
         HASH_FIND_BYHASHVALUE(hh, PVT(a_ledger)->threshold_txs, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value, l_tx_item);
         pthread_rwlock_unlock(&PVT(a_ledger)->ledger_rwlock);
@@ -5552,7 +5314,7 @@ void dap_ledger_purge(dap_ledger_t *a_ledger, bool a_preserve_db)
         pthread_rwlock_unlock(&l_token_current->token_emissions_rwlock);
         DAP_DELETE(l_token_current->datum_token);
         DAP_DELETE(l_token_current->auth_pkeys);
-        DAP_DELETE(l_token_current->auth_pkeys_hash);
+        DAP_DELETE(l_token_current->auth_pkey_hashes);
         DAP_DEL_Z(l_token_current->tx_recv_allow);
         DAP_DEL_Z(l_token_current->tx_recv_block);
         DAP_DEL_Z(l_token_current->tx_send_allow);
@@ -6556,8 +6318,8 @@ const char *dap_ledger_tx_calculate_main_ticker(dap_ledger_t *a_ledger, dap_chai
 {
     char *l_main_ticker = NULL;
     dap_chain_hash_fast_t *l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx);
-    int l_rc = dap_ledger_tx_cache_check(a_ledger, a_tx, l_tx_hash, false, NULL, NULL, &l_main_ticker, NULL, NULL, false);  
-    if (l_rc == DAP_LEDGER_TX_ALREADY_CACHED)
+    int l_rc = s_tx_cache_check(a_ledger, a_tx, l_tx_hash, false, NULL, NULL, &l_main_ticker, NULL, NULL, false);
+    if (l_rc == DAP_LEDGER_CHECK_ALREADY_CACHED)
         l_main_ticker = (char *)dap_ledger_tx_get_token_ticker_by_hash(a_ledger, l_tx_hash);
     DAP_DEL_Z(l_tx_hash);
 
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 570b45583fa91dc3865d3fb1b926dd506c9742fc..f6e2b577971868399474b47462176370aa6d8515 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -574,10 +574,10 @@ int s_link_manager_fill_net_info(dap_link_t *a_link)
     return 0;
 }
 
-json_object *s_net_sync_status(dap_chain_net_t *a_net) {
-// sanity check
+json_object *s_net_sync_status(dap_chain_net_t *a_net)
+{
+    // sanity check
     dap_return_val_if_pass(!a_net, NULL);
-    size_t l_count_atoms = 0;
 
     json_object *l_jobj_chains_array = json_object_new_object();
     dap_chain_t *l_chain = NULL;
@@ -2127,10 +2127,14 @@ int s_net_init(const char *a_net_name, uint16_t a_acl_idx)
     default:
         l_ledger_flags |= DAP_LEDGER_CHECK_CELLS_DS | DAP_LEDGER_CHECK_TOKEN_EMISSION;
     }
-    // init LEDGER model
-    l_net->pub.ledger = dap_ledger_create(l_net, l_ledger_flags);
+    if (dap_config_get_item_bool_default(g_config, "ledger", "mapped", true))
+        l_ledger_flags |= DAP_LEDGER_MAPPED;
 
     for (dap_chain_t *l_chain = l_net->pub.chains; l_chain; l_chain = l_chain->next) {
+        if (l_chain->callback_load_from_gdb) {
+            l_ledger_flags &= ~DAP_LEDGER_MAPPED;
+            continue;
+        }
         if (!l_chain->callback_get_poa_certs)
             continue;
         l_net->pub.keys = l_chain->callback_get_poa_certs(l_chain, NULL, NULL);
@@ -2140,6 +2144,8 @@ int s_net_init(const char *a_net_name, uint16_t a_acl_idx)
     if (!l_net->pub.keys)
         log_it(L_WARNING, "PoA certificates for net %s not found", l_net->pub.name);
 
+    // init LEDGER model
+    l_net->pub.ledger = dap_ledger_create(l_net, l_ledger_flags);
     // Decrees initializing
     dap_chain_net_decree_init(l_net);
 
@@ -2977,7 +2983,7 @@ void dap_chain_net_proc_mempool(dap_chain_net_t *a_net)
  * @brief dap_chain_net_verify_datum_for_add
  * process datum verification process. Can be:
  *   if DAP_CHAIN_DATUM_TX, called dap_ledger_tx_add_check
- *   if DAP_CHAIN_DATUM_TOKEN_DECL, called dap_ledger_token_decl_add_check
+ *   if DAP_CHAIN_DATUM_TOKEN, called dap_ledger_token_add_check
  *   if DAP_CHAIN_DATUM_TOKEN_EMISSION, called dap_ledger_token_emission_add_check
  *   if DAP_CHAIN_DATUM_DECREE
  * @param a_net
@@ -2994,8 +3000,8 @@ int dap_chain_net_verify_datum_for_add(dap_chain_t *a_chain, dap_chain_datum_t *
     switch (a_datum->header.type_id) {
     case DAP_CHAIN_DATUM_TX:
         return dap_ledger_tx_add_check(l_net->pub.ledger, (dap_chain_datum_tx_t *)a_datum->data, a_datum->header.data_size, a_datum_hash);
-    case DAP_CHAIN_DATUM_TOKEN_DECL:
-        return dap_ledger_token_decl_add_check(l_net->pub.ledger, (dap_chain_datum_token_t *)a_datum->data, a_datum->header.data_size);
+    case DAP_CHAIN_DATUM_TOKEN:
+        return dap_ledger_token_add_check(l_net->pub.ledger, a_datum->data, a_datum->header.data_size);
     case DAP_CHAIN_DATUM_TOKEN_EMISSION:
         return dap_ledger_token_emission_add_check(l_net->pub.ledger, a_datum->data, a_datum->header.data_size, a_datum_hash);
     case DAP_CHAIN_DATUM_DECREE:
@@ -3013,14 +3019,12 @@ int dap_chain_net_verify_datum_for_add(dap_chain_t *a_chain, dap_chain_datum_t *
     return 0;
 }
 
-char *dap_chain_net_verify_datum_err_code_to_str(dap_chain_datum_t *a_datum, int a_code){
+const char *dap_chain_net_verify_datum_err_code_to_str(dap_chain_datum_t *a_datum, int a_code){
     switch (a_datum->header.type_id) {
     case DAP_CHAIN_DATUM_TX:
-        return dap_ledger_tx_check_err_str(a_code);
-    case DAP_CHAIN_DATUM_TOKEN_DECL:
-        return dap_ledger_token_decl_add_err_code_to_str(a_code);
+    case DAP_CHAIN_DATUM_TOKEN:
     case DAP_CHAIN_DATUM_TOKEN_EMISSION:
-        return dap_ledger_token_emission_err_code_to_str(a_code);
+        return dap_ledger_check_error_str(a_code);
     default:
         return !a_code ? "DAP_CHAIN_DATUM_VERIFY_OK" : dap_itoa(a_code);
 
@@ -3211,7 +3215,7 @@ int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t
             }
             return dap_chain_net_anchor_load(l_anchor, a_chain, a_datum_hash);
         }
-        case DAP_CHAIN_DATUM_TOKEN_DECL:
+        case DAP_CHAIN_DATUM_TOKEN:
             return dap_ledger_token_load(l_ledger, a_datum->data, a_datum->header.data_size);
 
         case DAP_CHAIN_DATUM_TOKEN_EMISSION:
@@ -3267,7 +3271,7 @@ int dap_chain_datum_remove(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, siz
             }
             return dap_chain_net_anchor_unload(l_anchor, a_chain, a_datum_hash);
         }
-        case DAP_CHAIN_DATUM_TOKEN_DECL:
+        case DAP_CHAIN_DATUM_TOKEN:
             return 0;
 
         case DAP_CHAIN_DATUM_TOKEN_EMISSION:
diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c
index 46d6c126472ff3e5c110872b348a772d2e4116d5..f8ae4a95ce09ddb10667a3e41439f75529b175c4 100644
--- a/modules/net/dap_chain_net_decree.c
+++ b/modules/net/dap_chain_net_decree.c
@@ -316,7 +316,7 @@ int dap_chain_net_decree_load(dap_chain_datum_decree_t * a_decree, dap_chain_t *
     size_t l_data_size = dap_chain_datum_decree_get_size(a_decree);
 
     if ((ret_val = s_decree_verify(l_net, a_decree, l_data_size, a_decree_hash, true)) != 0) {
-        log_it(L_ERROR, "Decree verification failed!");
+        //log_it(L_ERROR, "Decree verification failed!");
         return ret_val;
     }
 
diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c
index 3ab907653d4e1793692bf5e5ada09723fb71a6b1..1603d8fdbf88ab95364dda0360d4d3bc1f2efcf2 100644
--- a/modules/net/dap_chain_node.c
+++ b/modules/net/dap_chain_node.c
@@ -262,7 +262,7 @@ bool dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_datum_t *a_d
         log_it(L_WARNING, "Can't get datum hash from hash string");
         return false;
     }
-    dap_hash_fast(a_datum->data, a_datum->header.data_size, &l_real_hash);
+    dap_chain_datum_calc_hash(a_datum, &l_real_hash);
     if (!dap_hash_fast_compare(&l_datum_hash, &l_real_hash)) {
         log_it(L_WARNING, "Datum hash from mempool key and real datum hash are different");
         return false;
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index d712c847fd89b06bfd1475e4d56f9e869e93c556..89c504dc313be30eaac4748f3090b01b9c653066 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -2395,7 +2395,7 @@ static dap_chain_datum_token_t * s_sign_cert_in_cycle(dap_cert_t ** l_certs, dap
         if (l_sign) {
             size_t l_sign_size = dap_sign_get_size(l_sign);
             l_datum_token = DAP_REALLOC(l_datum_token, sizeof(*l_datum_token) + (*l_datum_signs_offset) + l_sign_size);
-            memcpy(l_datum_token->data_n_tsd + *l_datum_signs_offset, l_sign, l_sign_size);
+            memcpy(l_datum_token->tsd_n_signs + *l_datum_signs_offset, l_sign, l_sign_size);
             *l_datum_signs_offset += l_sign_size;
             DAP_DELETE(l_sign);
             log_it(L_DEBUG,"<-- Signed with '%s'", l_certs[i]->name);
@@ -2489,8 +2489,7 @@ int com_token_decl_sign(int a_argc, char **a_argv, void **a_str_reply)
                 l_datum_hash_hex_str, &l_datum_size, NULL, NULL )) != NULL) {
 
             // Check if its token declaration
-            if(l_datum->header.type_id == DAP_CHAIN_DATUM_TOKEN_DECL ||
-                l_datum->header.type_id == DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE) {
+            if(l_datum->header.type_id == DAP_CHAIN_DATUM_TOKEN) {
                 dap_chain_datum_token_t *l_datum_token = DAP_DUP_SIZE(l_datum->data, l_datum->header.data_size);    // for realloc
                 DAP_DELETE(l_datum);
                 if ((l_datum_token->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE)
@@ -2501,7 +2500,7 @@ int com_token_decl_sign(int a_argc, char **a_argv, void **a_str_reply)
                 uint16_t l_tmp_signs_total = l_datum_token->signs_total;
                 l_datum_token->signs_total = 0;
                 for (i = 1; i <= l_tmp_signs_total; i++){
-                    dap_sign_t *l_sign = (dap_sign_t *)(l_datum_token->data_n_tsd + l_tsd_size + l_signs_size);
+                    dap_sign_t *l_sign = (dap_sign_t *)(l_datum_token->tsd_n_signs + l_tsd_size + l_signs_size);
                     if( dap_sign_verify(l_sign, l_datum_token, sizeof(*l_datum_token) + l_tsd_size) ) {
                         log_it(L_WARNING, "Wrong signature %zu for datum_token with key %s in mempool!", i, l_datum_hash_out_str);
                         dap_cli_server_cmd_set_reply_text(a_str_reply,
@@ -2526,7 +2525,7 @@ int com_token_decl_sign(int a_argc, char **a_argv, void **a_str_reply)
                                                             &l_sign_counter);
                 l_datum_token->signs_total += l_sign_counter;
                 size_t l_token_size = sizeof(*l_datum_token) + l_data_size;
-                dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_DECL,
+                dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN,
                                                                      l_datum_token, l_token_size);
                 DAP_DELETE(l_datum_token);
                 // Calc datum's hash
@@ -2670,7 +2669,7 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a
             const char *l_datum_type = dap_chain_datum_type_id_to_str(l_datum->header.type_id);
             dap_hash_fast_t l_datum_real_hash = {0};
             dap_hash_fast_t l_datum_hash_from_key = {0};
-            dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_datum_real_hash);
+            dap_chain_datum_calc_hash(l_datum, &l_datum_real_hash);
             dap_chain_hash_fast_from_str(l_objs[i].key, &l_datum_hash_from_key);
             char buff_time[DAP_TIME_STR_SIZE];
             dap_time_to_str_rfc822(buff_time, DAP_TIME_STR_SIZE, l_datum->header.ts_create);
@@ -2750,10 +2749,10 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a
                         dap_chain_addr_t l_addr_from;
                         dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *) l_datum->data;
 
-                        int l_ledger_rc = DAP_LEDGER_TX_CHECK_NULL_TX;
+                        int l_ledger_rc = DAP_LEDGER_CHECK_INVALID_ARGS;
                         const char *l_main_ticker = dap_ledger_tx_calculate_main_ticker(a_net->pub.ledger, l_tx,
                                                                                   &l_ledger_rc);
-                        char *l_ledger_rc_str = dap_ledger_tx_check_err_str(l_ledger_rc);
+                        const char *l_ledger_rc_str = dap_ledger_check_error_str(l_ledger_rc);
 
                         json_object *l_jobj_main_ticker = json_object_new_string(
                                 l_main_ticker ? l_main_ticker : "UNKNOWN");
@@ -3353,7 +3352,7 @@ int _cmd_mempool_check(dap_chain_net_t *a_net, dap_chain_t *a_chain, const char
             dap_chain_hash_fast_to_str(&l_atom_hash, l_atom_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
             json_object *l_obj_atom = json_object_new_object();
             json_object *l_jobj_atom_hash = json_object_new_string(l_atom_hash_str);
-            json_object *l_jobj_atom_err = json_object_new_string(dap_ledger_tx_check_err_str(l_ret_code));
+            json_object *l_jobj_atom_err = json_object_new_string(dap_ledger_check_error_str(l_ret_code));
             if (!l_obj_atom || !l_jobj_atom_hash || !l_jobj_atom_err) {
                 json_object_put(l_jobj_datum);
                 json_object_put(l_obj_atom);
@@ -3460,7 +3459,7 @@ int _cmd_mempool_proc(dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *
         DAP_DELETE(l_gdb_group_mempool);
         return DAP_COM_MEMPOOL_PROC_LIST_ERROR_CAN_NOT_CONVERT_DATUM_HASH_TO_DIGITAL_FORM;
     }
-    dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_real_hash);
+    dap_chain_datum_calc_hash(l_datum, &l_real_hash);
     if (!dap_hash_fast_compare(&l_datum_hash, &l_real_hash)) {
         dap_json_rpc_error_add(DAP_COM_MEMPOOL_PROC_LIST_ERROR_REAL_HASH_DATUM_DOES_NOT_MATCH_HASH_DATA_STRING,
                                "Error! Datum's real hash doesn't match datum's hash string %s",
@@ -4147,8 +4146,8 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, void **
     const char* l_remove_signs = NULL;
     dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-new_certs", &l_new_certs_str);
     dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-remove_certs", &l_remove_signs);
-    const char *l_description_token  = NULL;
-    dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-description", &l_description_token);
+    const char *l_description  = NULL;
+    dap_cli_server_cmd_find_option_val(a_argv, 0, a_argc, "-description", &l_description);
 
     //Added remove signs
     if (l_remove_signs) {
@@ -4188,8 +4187,8 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, void **
         }
         DAP_DEL_Z(l_new_certs);
     }
-    if (l_description_token) {
-        dap_tsd_t *l_desc_token = dap_tsd_create_string(DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION, l_description_token);
+    if (l_description) {
+        dap_tsd_t *l_desc_token = dap_tsd_create_string(DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION, l_description);
         l_tsd_list = dap_list_append(l_tsd_list, l_desc_token);
         l_tsd_total_size += dap_tsd_size(l_desc_token);
         a_params->ext.parsed_tsd_size += dap_tsd_size(l_desc_token);
@@ -4522,11 +4521,11 @@ int com_token_decl(int a_argc, char ** a_argv, void **a_str_reply)
                     default: log_it(L_DEBUG, "== 0x%04X: binary data %u size ",l_tsd->type, l_tsd->size );
                 }
                 size_t l_tsd_size = dap_tsd_size(l_tsd);
-                memcpy(l_datum_token->data_n_tsd + l_datum_data_offset, l_tsd, l_tsd_size);
+                memcpy(l_datum_token->tsd_n_signs + l_datum_data_offset, l_tsd, l_tsd_size);
                 l_datum_data_offset += l_tsd_size;
             }
             if (l_params->ext.parsed_tsd) {
-                memcpy(l_datum_token->data_n_tsd + l_datum_data_offset,
+                memcpy(l_datum_token->tsd_n_signs + l_datum_data_offset,
                        l_params->ext.parsed_tsd,
                        l_params->ext.tsd_total_size);
                 l_datum_data_offset += l_params->ext.tsd_total_size;
@@ -4574,7 +4573,7 @@ int com_token_decl(int a_argc, char ** a_argv, void **a_str_reply)
             return -9;
     }
 
-    dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_DECL,
+    dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN,
                                                          l_datum_token,
                                                          sizeof(*l_datum_token) + l_datum_data_offset);
     DAP_DELETE(l_datum_token);
@@ -4582,7 +4581,7 @@ int com_token_decl(int a_argc, char ** a_argv, void **a_str_reply)
 
     // Calc datum's hash
     dap_chain_hash_fast_t l_key_hash;
-    dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_key_hash);
+    dap_chain_datum_calc_hash(l_datum, &l_key_hash);
     char *l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
     const char *l_key_str_out = dap_strcmp(l_hash_out_type, "hex") ?
                            dap_enc_base58_encode_hash_to_str_static(&l_key_hash) : l_key_str;
@@ -4737,7 +4736,7 @@ int com_token_update(int a_argc, char ** a_argv, void **a_str_reply)
             // Add TSD sections in the end
             // Add TSD sections in the end
             if (l_params->ext.tsd_total_size) {
-                memcpy(l_datum_token->data_n_tsd, l_params->ext.parsed_tsd, l_params->ext.parsed_tsd_size);
+                memcpy(l_datum_token->tsd_n_signs, l_params->ext.parsed_tsd, l_params->ext.parsed_tsd_size);
                 DAP_DELETE(l_params->ext.parsed_tsd);
             }
             log_it(L_DEBUG, "%s token declaration update '%s' initialized", (	l_params->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE)	?
@@ -4779,7 +4778,7 @@ int com_token_update(int a_argc, char ** a_argv, void **a_str_reply)
         return -9;
     }
 
-    dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN_DECL,
+    dap_chain_datum_t * l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TOKEN,
                                                          l_datum_token,
                                                          sizeof(*l_datum_token) + l_datum_data_offset);
     DAP_DELETE(l_datum_token);
@@ -4787,7 +4786,7 @@ int com_token_update(int a_argc, char ** a_argv, void **a_str_reply)
 
     // Calc datum's hash
     dap_chain_hash_fast_t l_key_hash;
-    dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_key_hash);
+    dap_chain_datum_calc_hash(l_datum, &l_key_hash);
     char *l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
     const char *l_key_str_out = dap_strcmp(l_hash_out_type, "hex") ?
                            dap_enc_base58_encode_hash_to_str_static(&l_key_hash) : l_key_str;
@@ -4803,7 +4802,7 @@ int com_token_update(int a_argc, char ** a_argv, void **a_str_reply)
     }
     bool l_placed = !dap_global_db_set_sync(l_gdb_group_mempool, l_key_str, (uint8_t *)l_datum, l_datum_size, false);
     DAP_DELETE(l_gdb_group_mempool);
-    dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s with token update datum for ticker %s is%s placed in datum pool",
+    dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s with token update for ticker %s is%s placed in datum pool",
                                       l_key_str_out, l_ticker, l_placed ? "" : " not");
     DAP_DELETE(l_key_str);
     DAP_DELETE(l_datum);
@@ -7071,7 +7070,7 @@ int com_tx_verify(int a_argc, char **a_argv, void **reply)
     if (l_ret) {
         l_jobj_verfiy = json_object_new_boolean(false);
         l_jobj_error = json_object_new_object();
-        json_object *l_jobj_err_str = json_object_new_string(dap_ledger_tx_check_err_str(l_ret));
+        json_object *l_jobj_err_str = json_object_new_string(dap_ledger_check_error_str(l_ret));
         json_object *l_jobj_err_code = json_object_new_int64(l_ret);
         json_object_object_add(l_jobj_error, "code", l_jobj_err_code);
         json_object_object_add(l_jobj_error, "message", l_jobj_err_str);
@@ -7948,7 +7947,7 @@ static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, void **a_str_
             goto end;
         }
 
-        dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_hash_tmp);
+        dap_chain_datum_calc_hash(l_datum, &l_hash_tmp);
     }
 
     dap_chain_atom_iter_t *l_iter = NULL;
@@ -7963,7 +7962,7 @@ static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, void **a_str_
         for (size_t i = 0; i < l_datums_count; i++) {
             dap_chain_datum_t *l_datum = l_datums[i];
             dap_hash_fast_t l_hash;
-            dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_hash);
+            dap_chain_datum_calc_hash(l_datum, &l_hash);
             if (!memcmp(l_hash_tmp.raw, l_hash.raw, DAP_CHAIN_HASH_FAST_SIZE)) {
                 dap_cli_server_cmd_set_reply_text(a_str_reply, "found!");
                 found = 1;
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index 30b35d585fa78d48c264c1e1eb7ef4b81a87d96e..e988cb3ed57fde2c6f93eb627054f0b545631a08 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -25,7 +25,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <pthread.h>
-
+#include "uthash.h"
 #include "dap_cli_server.h"
 #include "dap_common.h"
 #include "dap_enc_base58.h"
@@ -34,7 +34,6 @@
 #include "dap_list.h"
 #include "dap_hash.h"
 #include "dap_time.h"
-
 #include "dap_chain_cell.h"
 #include "dap_chain_datum.h"
 #include "dap_chain_datum_token.h"
@@ -46,22 +45,10 @@
 #include "dap_chain_net_decree.h"
 #include "dap_chain_mempool.h"
 #include "dap_math_convert.h"
-
 #include "dap_json_rpc_errors.h"
 
 #define LOG_TAG "chain_node_cli_cmd_tx"
 
-#include "uthash.h"
-// for dap_db_history_filter()
-typedef struct dap_tx_data {
-    dap_chain_hash_fast_t tx_hash;
-    char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
-    dap_chain_datum_t *datum;
-    UT_hash_handle hh;
-    //useless
-    char tx_hash_str[70];
-    dap_chain_addr_t addr;
-} dap_tx_data_t;
 
 
 /**
@@ -193,7 +180,7 @@ json_object * dap_db_tx_history_to_json(dap_chain_hash_fast_t* a_tx_hash,
                                                                                        : json_object_new_null());
 
     json_object_object_add(json_obj_datum, "ret_code", json_object_new_int(l_ret_code));
-    json_object_object_add(json_obj_datum, "ret_code_str", json_object_new_string(dap_ledger_tx_check_err_str(l_ret_code)));
+    json_object_object_add(json_obj_datum, "ret_code_str", json_object_new_string(dap_ledger_check_error_str(l_ret_code)));
 
     dap_chain_net_srv_uid_t uid;
     char *service_name;
@@ -291,7 +278,7 @@ static void s_tx_header_print(json_object* json_obj_datum, dap_chain_tx_hash_pro
     json_object_object_add(json_obj_datum, "hash", json_object_new_string(l_tx_hash_str));
     json_object_object_add(json_obj_datum, "atom_hash", json_object_new_string(l_atom_hash_str));
     json_object_object_add(json_obj_datum, "ret_code", json_object_new_int(a_ret_code));
-    json_object_object_add(json_obj_datum, "ret_code_str", json_object_new_string(dap_ledger_tx_check_err_str(a_ret_code)));
+    json_object_object_add(json_obj_datum, "ret_code_str", json_object_new_string(dap_ledger_check_error_str(a_ret_code)));
 
 
     dap_chain_net_srv_uid_t uid;
@@ -834,7 +821,7 @@ static json_object* dap_db_chain_history_token_list(dap_chain_t * a_chain, const
     dap_chain_datum_iter_t *l_datum_iter = a_chain->callback_datum_iter_create(a_chain);
     for (dap_chain_datum_t *l_datum = a_chain->callback_datum_iter_get_first(l_datum_iter);
             l_datum; l_datum = a_chain->callback_datum_iter_get_next(l_datum_iter)) {
-        if (l_datum->header.type_id != DAP_CHAIN_DATUM_TOKEN_DECL)
+        if (l_datum->header.type_id != DAP_CHAIN_DATUM_TOKEN)
             continue;
         size_t l_token_size = l_datum->header.data_size;
         dap_chain_datum_token_t *l_token = dap_chain_datum_token_read(l_datum->data, &l_token_size);
@@ -915,161 +902,6 @@ static size_t dap_db_net_history_token_list(dap_chain_net_t * l_net, const char
     return l_token_num_total;
 }
 
-/**
- * @brief dap_db_history_filter
- * Get data according the history log
- *
- * return history string
- * @param a_chain
- * @param a_ledger
- * @param a_filter_token_name
- * @param a_filtr_addr_base58
- * @param a_hash_out_type
- * @param a_datum_start
- * @param a_datum_end
- * @param a_total_datums
- * @param a_tx_hash_processed
- * @return char*
- */
-static char* dap_db_history_filter(dap_chain_t * a_chain, dap_ledger_t *a_ledger, const char *a_filter_token_name, const char *a_filtr_addr_base58, const char *a_hash_out_type, long a_datum_start, long a_datum_end, long *a_total_datums, dap_chain_tx_hash_processed_ht_t *a_tx_hash_processed)
-{
-    if (!a_chain->callback_atom_get_datums) {
-        log_it(L_WARNING, "Not defined callback_atom_get_datums for chain \"%s\"", a_chain->name);
-        return NULL;
-    }
-    dap_string_t *l_str_out = dap_string_new(NULL);
-    if (!l_str_out) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-        return NULL;
-    }
-    // list all transactions
-    dap_tx_data_t *l_tx_data_hash = NULL;
-    dap_chain_cell_t *l_cell = a_chain->cells;
-    do {
-        // load transactions
-        size_t l_atom_size = 0;
-        dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain, l_cell->id, NULL);
-        size_t l_datum_num = 0, l_token_num = 0, l_emission_num = 0, l_tx_num = 0;
-        size_t l_datum_num_global = a_total_datums ? *a_total_datums : 0;
-        for (dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size);
-                l_atom && l_atom_size; l_atom = a_chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size)) {
-            size_t l_datums_count = 0;
-            dap_chain_datum_t **l_datums = a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count);
-            if (!l_datums || !l_datums_count)
-                continue;
-            for(size_t l_datum_n = 0; l_datum_n < l_datums_count; l_datum_n++) {
-                dap_chain_datum_t *l_datum = l_datums[l_datum_n];
-                if(!l_datum)
-                    continue;
-                char l_time_str[DAP_TIME_STR_SIZE];
-                // get time of create datum
-                if(dap_time_to_str_rfc822(l_time_str, DAP_TIME_STR_SIZE, l_datum->header.ts_create) < 1)
-                    l_time_str[0] = '\0';
-                switch (l_datum->header.type_id) {
-                // token
-                case DAP_CHAIN_DATUM_TOKEN_DECL: {
-                    // no token necessary for addr
-                    if(a_filtr_addr_base58)
-                        break;
-                    dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data;
-                    //if(a_datum_start < 0 || (l_datum_num >= a_datum_start && l_datum_num < a_datum_end))
-                    // datum out of page
-                    if(a_datum_start >= 0 && (l_datum_num+l_datum_num_global < (size_t)a_datum_start || l_datum_num+l_datum_num_global >= (size_t)a_datum_end)){
-                        l_token_num++;
-                        break;
-                    }
-                    if(!a_filter_token_name || !dap_strcmp(l_token->ticker, a_filter_token_name)) {
-                        dap_chain_datum_dump(l_str_out, l_datum, a_hash_out_type, a_chain->net_id);
-                        dap_string_append(l_str_out, "\n");
-                        l_token_num++;
-                    }
-                } break;
-
-                // emission
-                case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
-                    // datum out of page
-                    if(a_datum_start >= 0 && (l_datum_num+l_datum_num_global < (size_t)a_datum_start || l_datum_num+l_datum_num_global >= (size_t)a_datum_end)) {
-                         l_emission_num++;
-                         break;
-                    }
-                    dap_chain_datum_token_emission_t *l_token_em =  (dap_chain_datum_token_emission_t *)l_datum->data;
-                    if(!a_filter_token_name || !dap_strcmp(l_token_em->hdr.ticker, a_filter_token_name)) {
-                        // filter for addr
-                        if (a_filtr_addr_base58 && dap_strcmp(a_filtr_addr_base58, dap_chain_addr_to_str(&(l_token_em->hdr.address)))) {
-                             break;
-                        }
-                        dap_chain_datum_dump(l_str_out, l_datum, a_hash_out_type, a_chain->net_id);
-                        dap_string_append(l_str_out, "\n");
-                        l_emission_num++;
-                    }
-                } break;
-
-                // transaction
-                case DAP_CHAIN_DATUM_TX:{
-                    // datum out of page
-                    if(a_datum_start >= 0 && (l_datum_num+l_datum_num_global < (size_t)a_datum_start || l_datum_num+l_datum_num_global >= (size_t)a_datum_end)) {
-                        l_tx_num++;
-                        break;
-                    }
-                    dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)l_datum->data;
-                    //calc tx hash
-                    dap_chain_hash_fast_t l_tx_hash;
-                    dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash);
-                    dap_chain_tx_hash_processed_ht_t *l_sht = NULL;
-                    HASH_FIND(hh, a_tx_hash_processed, &l_tx_hash, sizeof(dap_chain_hash_fast_t), l_sht);
-                    json_object * l_json_obj_datum = json_object_new_object();
-                    if (l_sht != NULL ||
-                            !s_dap_chain_datum_tx_out_data(l_tx, a_ledger, l_json_obj_datum, a_hash_out_type, &l_tx_hash)) {
-                        l_datum_num--;
-                        break;
-                    }
-                    l_sht = DAP_NEW_Z(dap_chain_tx_hash_processed_ht_t);
-                    if (!l_sht) {
-                        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-                        return NULL;
-                    }
-                    l_sht->hash = l_tx_hash;
-                    HASH_ADD(hh, a_tx_hash_processed, hash, sizeof(dap_chain_hash_fast_t), l_sht);
-                    l_tx_num++;
-                } break;
-
-                default: {
-                    const char *l_type_str;
-                    DAP_DATUM_TYPE_STR(l_datum->header.type_id, l_type_str);
-                    dap_string_append_printf(l_str_out, "datum type %s\n", l_type_str);
-                    } break;
-                }
-                l_datum_num++;
-            }
-        }
-        a_chain->callback_atom_iter_delete(l_atom_iter);
-        //total
-        dap_string_append_printf(l_str_out,
-                "---------------\ntokens: %zu\nemissions: %zu\ntransactions: %zu\ntotal datums: %zu", l_token_num,
-                l_emission_num, l_tx_num, l_datum_num);
-
-        // return total datums
-        if(a_total_datums)
-            *a_total_datums = l_datum_num;
-        // delete hashes
-        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);
-        }
-        l_cell = l_cell->hh.next;
-    } while (l_cell);
-
-    // if no history
-    if(!l_str_out->len)
-        dap_string_append(l_str_out, "empty");
-    char *l_ret_str = l_str_out ? dap_string_free(l_str_out, false) : NULL;
-    return l_ret_str;
-}
 
 /**
  * @brief com_ledger
@@ -1085,13 +917,10 @@ int com_ledger(int a_argc, char ** a_argv, void **reply)
     json_object ** json_arr_reply = (json_object **) reply;
     enum { CMD_NONE, CMD_LIST, CMD_TX_INFO };
     int arg_index = 1;
-    const char *l_addr_base58 = NULL;
-    const char *l_wallet_name = NULL;
     const char *l_net_str = NULL;
     const char *l_tx_hash_str = NULL;
     const char *l_hash_out_type = NULL;
 
-    dap_chain_net_t * l_net = NULL;
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-H", &l_hash_out_type);
     if(!l_hash_out_type)
         l_hash_out_type = "hex";
@@ -1294,13 +1123,13 @@ int com_token(int a_argc, char ** a_argv, void **a_str_reply)
         const char *l_token_name_str = NULL;
         dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-name", &l_token_name_str);
         if(!l_token_name_str) {
-                dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TOKEN_PARAM_ERR, "command requires parameter '-name' <token name>");
-                return -DAP_CHAIN_NODE_CLI_COM_TOKEN_PARAM_ERR;
+            dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TOKEN_PARAM_ERR, "command requires parameter '-name' <token name>");
+            return -DAP_CHAIN_NODE_CLI_COM_TOKEN_PARAM_ERR;
         }
-        json_object* json_obj_tx = json_object_new_object();
-        if(!dap_db_net_history_token_list(l_net, l_token_name_str, l_hash_out_type, json_obj_tx)){
-            json_object_put(json_obj_tx);
-            dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TOKEN_FOUND_ERR, "token '%s' not found\n", l_token_name_str);               
+        json_object *json_obj_tx = json_object_new_object();
+        if (!dap_db_net_history_token_list(l_net, l_token_name_str, l_hash_out_type, json_obj_tx)) {
+            dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_TOKEN_FOUND_ERR, "token '%s' not found\n", l_token_name_str);\
+            return -DAP_CHAIN_NODE_CLI_COM_TOKEN_UNKNOWN;
         }
         json_object_array_add(*json_arr_reply, json_obj_tx);
         return DAP_CHAIN_NODE_CLI_COM_TOKEN_OK;
diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h
index 57a457f65c424d6b64f86821ea42a3de5043083a..b54200afe368c4e63b633eef83c91e2ec8821ac4 100644
--- a/modules/net/include/dap_chain_ledger.h
+++ b/modules/net/include/dap_chain_ledger.h
@@ -48,25 +48,30 @@ typedef struct dap_ledger {
 /**
  * @brief Error codes for accepting a transaction to the ledger.
  */
-typedef enum dap_ledger_tx_check{
-    DAP_LEDGER_TX_CHECK_OK = 0,
-    DAP_LEDGER_TX_CHECK_NULL_TX,
-    DAP_LEDGER_TX_CHECK_INVALID_TX_SIZE,
-    DAP_LEDGER_TX_ALREADY_CACHED,
-    DAP_LEDGER_TX_CHECK_INVALID_TX_SIGN,
+typedef enum dap_ledger_check_error {
+    DAP_LEDGER_CHECK_OK = 0,
+    DAP_LEDGER_CHECK_INVALID_ARGS,
+    DAP_LEDGER_CHECK_INVALID_SIZE,
+    DAP_LEDGER_CHECK_ALREADY_CACHED,
+    DAP_LEDGER_CHECK_PARSE_ERROR,
+    DAP_LEDGER_CHECK_APPLY_ERROR,
+    DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY,
+    DAP_LEDGER_CHECK_INTEGER_OVERFLOW,
+    DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS,
+    DAP_LEDGER_CHECK_TICKER_NOT_FOUND,
+    DAP_LEDGER_CHECK_ZERO_VALUE,
+    DAP_LEDGER_CHECK_ADDR_FORBIDDEN,
+    DAP_LEDGER_CHECK_WHITELISTED,
+    /* TX check return codes */
     DAP_LEDGER_TX_CHECK_IN_EMS_ALREADY_USED,
     DAP_LEDGER_TX_CHECK_STAKE_LOCK_IN_EMS_ALREADY_USED,
     DAP_LEDGER_TX_CHECK_EMISSION_NOT_FOUND,
     DAP_LEDGER_TX_CHECK_TX_NO_VALID_INPUTS,
-    DAP_LEDGER_TX_CHECK_TICKER_NOT_FOUND,
     DAP_LEDGER_TX_CHECK_STAKE_LOCK_INVALID_TOKEN,
     DAP_LEDGER_TX_CHECK_STAKE_LOCK_NO_OUT_COND_FOR_IN_EMS,
-    DAP_LEDGER_TX_CHECK_MULT256_OVERFLOW_EMS_LOCKED_X_RATE,
     DAP_LEDGER_TX_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS,
     DAP_LEDGER_TX_CHECK_NO_OUT_ITEMS_FOR_BASE_TX,
-    DAP_LEDGER_TX_CHECK_TOKEN_EMS_VALUE_EXEEDS_CUR_SUPPLY,
     DAP_LEDGER_TX_CHECK_STAKE_LOCK_UNEXPECTED_VALUE,
-    DAP_LEDGER_TX_CHECK_STAKE_LOCK_TICKER_NOT_FOUND,
     DAP_LEDGER_TX_CHECK_STAKE_LOCK_OTHER_TICKER_EXPECTED,
     DAP_LEDGER_TX_CHECK_OUT_ITEM_ALREADY_USED,
     DAP_LEDGER_TX_CHECK_PREV_TX_NOT_FOUND,
@@ -76,46 +81,84 @@ typedef enum dap_ledger_tx_check{
     DAP_LEDGER_TX_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX,
     DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET,
     DAP_LEDGER_TX_CHECK_VERIFICATOR_CHECK_FAILURE,
-    DAP_LEDGER_TX_CHECK_PREV_TICKER_NOT_FOUND,
-    DAP_LEDGER_TX_CHECK_PREV_TOKEN_NOT_FOUND,
-    DAP_LEDGER_PERMISSION_CHECK_FAILED,
     DAP_LEDGER_TX_CHECK_SUM_INS_NOT_EQUAL_SUM_OUTS,
     DAP_LEDGER_TX_CHECK_REWARD_ITEM_ALREADY_USED,
     DAP_LEDGER_TX_CHECK_REWARD_ITEM_ILLEGAL,
-    DAP_LEDGER_TX_CHECK_INVALID_TICKER,
-    DAP_LEDGER_TX_CHECK_MEMORY_PROBLEM,
-    /* add custom codes here */
-
-    DAP_LEDGER_TX_CHECK_UNKNOWN /* MAX */
-} dap_ledger_tx_check_t;
-
-typedef enum dap_ledger_emission_err{
-    DAP_LEDGER_EMISSION_ADD_OK = 0,
-    DAP_LEDGER_EMISSION_ADD_CHECK_EMS_IS_NULL,
-    DAP_LEDGER_EMISSION_ADD_CHECK_EMS_ALREADY_CACHED,
-    DAP_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_OVERFLOW,
-    DAP_LEDGER_EMISSION_ADD_CHECK_VALUE_EXEEDS_CURRENT_SUPPLY,
-    DAP_LEDGER_EMISSION_ADD_CHECK_NOT_ENOUGH_VALID_SIGNS,
-    DAP_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN,
-    DAP_LEDGER_EMISSION_ADD_CHECK_ZERO_VALUE,
-    DAP_LEDGER_EMISSION_ADD_TSD_CHECK_FAILED,
-    /* add custom codes here */
-    DAP_LEDGER_EMISSION_ADD_MEMORY_PROBLEM,
-    DAP_LEDGER_EMISSION_ADD_UNKNOWN /* MAX */
-} dap_ledger_emission_err_code_t;
-
-typedef enum dap_ledger_token_decl_add_err{
-    DAP_LEDGER_TOKEN_DECL_ADD_OK = 0,
-    DAP_LEDGER_TOKEN_DECL_ADD_ERR_LEDGER_IS_NULL,
-    DAP_LEDGER_TOKEN_DECL_ADD_ERR_DECL_DUPLICATE,
-    DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_CHECK,
-    DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_ABSENT_TOKEN,
-    DAP_LEDGER_TOKEN_DECL_ADD_ERR_NOT_ENOUGH_VALID_SIGN,
-    DAP_LEDGER_TOKEN_DECL_ADD_ERR_TOTAL_SIGNS_EXCEED_UNIQUE_SIGNS,
-    /* add custom codes here */
-
-    DAP_LEDGER_TOKEN_DECL_ADD_UNKNOWN /* MAX */
-} dap_ledger_token_decl_add_err_t;
+    DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER,
+    DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT,
+    DAP_LEDGER_TX_CHECK_NOT_ENOUGH_FEE,
+    DAP_LEDGER_TX_CHECK_NOT_ENOUGH_TAX,
+    /* Emisssion check return codes */
+    DAP_LEDGER_EMISSION_CHECK_THRESHOLDED,
+    DAP_LEDGER_EMISSION_CHECK_THRESHOLD_OVERFLOW,
+    DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY,
+    /* Token declaration/update return codes */
+    DAP_LEDGER_TOKEN_ADD_CHECK_NOT_ENOUGH_UNIQUE_SIGNS,
+    DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_SUPPLY,
+    DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR,
+    DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH,
+    DAP_LEDGER_TOKEN_ADD_CHECK_TSD_PKEY_MISMATCH,
+    DAP_LEDGER_TOKEN_ADD_CHECK_TSD_FORBIDDEN,
+    DAP_LEDGER_TOKEN_ADD_CHECK_TSD_OTHER_TICKER_EXPECTED
+} dap_ledger_check_error_t;
+
+DAP_STATIC_INLINE const char *dap_ledger_check_error_str(dap_ledger_check_error_t a_error)
+{
+    switch (a_error) {
+    case DAP_LEDGER_CHECK_OK: return "No error";
+    case DAP_LEDGER_CHECK_INVALID_ARGS: return "Invalid arguments";
+    case DAP_LEDGER_CHECK_INVALID_SIZE: return "Incorrect size of datum or datum's content";
+    case DAP_LEDGER_CHECK_ALREADY_CACHED: return "Datum already cached in ledger";
+    case DAP_LEDGER_CHECK_PARSE_ERROR: return "Incorrect datum interrnal structure, can't pasre it";
+    case DAP_LEDGER_CHECK_APPLY_ERROR: return "Datum can't be applied";
+    case DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY: return "Not enough memory";
+    case DAP_LEDGER_CHECK_INTEGER_OVERFLOW: return "Incorrect datum values relationship lead to integer overflow, can't process";
+    case DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS: return "No enough valid signatures in datum";
+    case DAP_LEDGER_CHECK_TICKER_NOT_FOUND: return "Can't find specified token ticker";
+    case DAP_LEDGER_CHECK_ZERO_VALUE: return "Unacceptable zero value";
+    case DAP_LEDGER_CHECK_ADDR_FORBIDDEN: return "Specified address is forbidden";
+    case DAP_LEDGER_CHECK_WHITELISTED: return "Datum is in hard accept list";
+    /* TX check return codes */
+    case DAP_LEDGER_TX_CHECK_IN_EMS_ALREADY_USED: return "Double spend attempt for emission";
+    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_IN_EMS_ALREADY_USED: return "Double spend attempt for stake-lock emission";
+    case DAP_LEDGER_TX_CHECK_EMISSION_NOT_FOUND: return "Specified emission not found in ledger";
+    case DAP_LEDGER_TX_CHECK_TX_NO_VALID_INPUTS: return "Transaction has no valid inputs, can't process";
+    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_INVALID_TOKEN: return "Incorrect deledated token specified in stake-lock transaction";
+    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_NO_OUT_COND_FOR_IN_EMS: return "Condtional output for stake-lock emission not found";
+    case DAP_LEDGER_TX_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS: return "Tokenized output for stake-lock girdled emission not found";
+    case DAP_LEDGER_TX_CHECK_NO_OUT_ITEMS_FOR_BASE_TX: return "Output for basic transaction not found";
+    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_UNEXPECTED_VALUE: return "Incorrect value for stake-lock emission, should be stake * rate";
+    case DAP_LEDGER_TX_CHECK_STAKE_LOCK_OTHER_TICKER_EXPECTED: return "Incorrect token ticker for stake-lock emission";
+    case DAP_LEDGER_TX_CHECK_OUT_ITEM_ALREADY_USED: return "Double spend attempt for transaction output";
+    case DAP_LEDGER_TX_CHECK_PREV_TX_NOT_FOUND: return "No previous transaction found";
+    case DAP_LEDGER_TX_CHECK_PREV_OUT_ITEM_NOT_FOUND: return "Specified output number not found in previous transaction";
+    case DAP_LEDGER_TX_CHECK_PREV_OUT_ITEM_MISSTYPED: return "Previuos transaction output has unknown type, possible ledger corruption";
+    case DAP_LEDGER_TX_CHECK_PKEY_HASHES_DONT_MATCH: return "Trying to spend transaction output from wrongful wallet";
+    case DAP_LEDGER_TX_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX: return "Double spend attempt within single transaction";
+    case DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET: return "No verificator found for specified conditional ipnput";
+    case DAP_LEDGER_TX_CHECK_VERIFICATOR_CHECK_FAILURE: return "Verificator check return error";
+    case DAP_LEDGER_TX_CHECK_SUM_INS_NOT_EQUAL_SUM_OUTS: return "Sum of transaction outputs isn't equal to sum of its inputs";
+    case DAP_LEDGER_TX_CHECK_REWARD_ITEM_ALREADY_USED: return "Double spend attempt for reward";
+    case DAP_LEDGER_TX_CHECK_REWARD_ITEM_ILLEGAL: return "Wrongful reward item in transaction";
+    case DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER: return "Can't calculate main ticker found for transaction";
+    case DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT: return "Tokenized out is forbidden for single-channel trandactions";
+    case DAP_LEDGER_TX_CHECK_NOT_ENOUGH_FEE: return "Not enough network fee for transaction processing";
+    case DAP_LEDGER_TX_CHECK_NOT_ENOUGH_TAX: return "Not enough sovereign tax provided with current transaction";
+    /* Emisssion check return codes */
+    case DAP_LEDGER_EMISSION_CHECK_THRESHOLDED: return "No token ticker found for emission, move it to the threshold";
+    case DAP_LEDGER_EMISSION_CHECK_THRESHOLD_OVERFLOW: return "Emissions threshold overfulled";
+    case DAP_LEDGER_EMISSION_CHECK_VALUE_EXCEEDS_CURRENT_SUPPLY: return "Value of emission execeeds current token supply";
+    /* Token declaration/update return codes */
+    case DAP_LEDGER_TOKEN_ADD_CHECK_NOT_ENOUGH_UNIQUE_SIGNS: return "Not all token signs is unique";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_SUPPLY: return "Specified supply must be greater than current one";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR: return "Specified address has invalid format";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH: return "Specified address can't be processed cause double (for adding) or absent (for removing)";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_PKEY_MISMATCH: return "Specified public key or its hash can't be processed cause double (for adding) or absent (for removing)";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_FORBIDDEN: return "Specified TSD section type is not allowed in datum token of specified type";
+    case DAP_LEDGER_TOKEN_ADD_CHECK_TSD_OTHER_TICKER_EXPECTED: return "Incorrect token ticker for delegated token";
+    default: return "Unknown error";
+    }
+}
 
 typedef enum dap_chan_ledger_notify_opcodes{
     DAP_LEDGER_NOTIFY_OPCODE_ADDED = 'a', // 0x61
@@ -151,7 +194,7 @@ typedef struct dap_ledger_datum_iter {
     void *cur_ledger_tx_item;
 } dap_ledger_datum_iter_t;
 
-typedef bool (*dap_ledger_verificator_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_tx_out_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner);
+typedef int (*dap_ledger_verificator_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_tx_out_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner);
 typedef void (*dap_ledger_updater_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_prev_cond);
 typedef void (* dap_ledger_tx_add_notify_t)(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chan_ledger_notify_opcodes_t a_opcode);
 typedef void (* dap_ledger_bridged_tx_notify_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, void *a_arg, dap_chan_ledger_notify_opcodes_t a_opcode);
@@ -166,22 +209,24 @@ typedef bool (*dap_ledger_tag_check_callback_t)(dap_ledger_t *a_ledger, dap_chai
 #define DAP_LEDGER_CACHE_RELOAD_ONCE_UUID "0c92b759-a565-448f-b8bd-99103dacf7fc"
 
 // Checks the emission of the token, usualy on zero chain
-#define DAP_LEDGER_CHECK_TOKEN_EMISSION    0x0001
+#define DAP_LEDGER_CHECK_TOKEN_EMISSION     0x0001
 
 // Check double spending in local cell
-#define DAP_LEDGER_CHECK_LOCAL_DS          0x0002
+#define DAP_LEDGER_CHECK_LOCAL_DS           0x0002
 
 // Check the double spending in all cells
-#define DAP_LEDGER_CHECK_CELLS_DS          0x0100
+#define DAP_LEDGER_CHECK_CELLS_DS           0x0100
+
+#define DAP_LEDGER_CACHE_ENABLED            0x0200
 
-#define DAP_LEDGER_CACHE_ENABLED           0x0200
+#define DAP_LEDGER_MAPPED                   0x0400
 
 // Error code for no previous transaction (for stay in mempool)
 #define DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS     DAP_LEDGER_TX_CHECK_PREV_TX_NOT_FOUND
 // Error code for no emission for a transaction (for stay in mempool)
 #define DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION     DAP_LEDGER_TX_CHECK_EMISSION_NOT_FOUND
 // Error code for not enough valid emission signs (for stay in mempool)
-#define DAP_CHAIN_CS_VERIFY_CODE_NOT_ENOUGH_SIGNS   DAP_LEDGER_EMISSION_ADD_CHECK_NOT_ENOUGH_VALID_SIGNS
+#define DAP_CHAIN_CS_VERIFY_CODE_NOT_ENOUGH_SIGNS   DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS
 // Error code for no decree for anchor (for stay in mempool)
 #define DAP_CHAIN_CS_VERIFY_CODE_NO_DECREE          -1113
 
@@ -205,21 +250,6 @@ void dap_ledger_handle_free(dap_ledger_t *a_ledger);
 
 void dap_ledger_set_local_cell_id(dap_ledger_t *a_ledger, dap_chain_cell_id_t a_local_cell_id);
 
-/**
- * @brief dap_chain_node_datum_tx_calc_hash
- * @param a_tx
- * @return
- */
-DAP_STATIC_INLINE dap_chain_hash_fast_t* dap_chain_node_datum_tx_calc_hash(dap_chain_datum_tx_t *a_tx)
-{
-    dap_chain_hash_fast_t *tx_hash = DAP_NEW_Z(dap_chain_hash_fast_t);
-    if (!tx_hash) {
-        return NULL;
-    }
-    dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), tx_hash);
-    return tx_hash;
-}
-
 DAP_STATIC_INLINE char *dap_ledger_get_gdb_group(dap_ledger_t *a_ledger, const char *a_suffix)
 {
     return a_ledger && a_ledger->net->pub.name && a_suffix
@@ -238,8 +268,6 @@ int dap_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap
 
 int dap_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, size_t a_datum_size, dap_hash_fast_t *a_datum_hash);
 
-char* dap_ledger_tx_check_err_str(int a_code);
-
 /**
  * Print list transaction from ledger
  *
@@ -259,10 +287,9 @@ dap_chain_datum_token_t *dap_ledger_token_ticker_check(dap_ledger_t * a_ledger,
  *
  */
 
-int dap_ledger_token_add(dap_ledger_t *a_ledger, dap_chain_datum_token_t *a_token, size_t a_token_size);
+int dap_ledger_token_add(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_size);
 int dap_ledger_token_load(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_size);
-int dap_ledger_token_decl_add_check(dap_ledger_t *a_ledger, dap_chain_datum_token_t *a_token, size_t a_token_size);
-char *dap_ledger_token_decl_add_err_code_to_str(int a_code);
+int dap_ledger_token_add_check(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_size);
 json_object *dap_ledger_token_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset);
 json_object *dap_ledger_token_info_by_name(dap_ledger_t *a_ledger, const char *a_token_ticker);
 
@@ -273,9 +300,10 @@ json_object *dap_ledger_threshold_info(dap_ledger_t *a_ledger, size_t a_limit, s
 json_object *dap_ledger_threshold_hash_info(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *l_tx_treshold_hash, size_t a_limit, size_t a_offset);
 json_object *dap_ledger_balance_info(dap_ledger_t *a_ledger, size_t a_limit, size_t a_offset);
 
-size_t dap_ledger_token_auth_signs_valid(dap_ledger_t *a_ledger, const char * a_token_ticker);
-size_t dap_ledger_token_auth_signs_total(dap_ledger_t *a_ledger, const char * a_token_ticker);
-dap_list_t * dap_ledger_token_auth_pkeys_hashes(dap_ledger_t *a_ledger, const char * a_token_ticker);
+size_t dap_ledger_token_get_auth_signs_valid(dap_ledger_t *a_ledger, const char *a_token_ticker);
+size_t dap_ledger_token_get_auth_signs_total(dap_ledger_t *a_ledger, const char *a_token_ticker);
+dap_list_t *dap_ledger_token_get_auth_pkeys_hashes(dap_ledger_t *a_ledger, const char *a_token_ticker);
+uint256_t dap_ledger_token_get_emission_rate(dap_ledger_t *a_ledger, const char *a_token_ticker);
 
 /**
  * Add token emission datum
@@ -283,9 +311,8 @@ dap_list_t * dap_ledger_token_auth_pkeys_hashes(dap_ledger_t *a_ledger, const ch
 int dap_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size,
                                         dap_hash_fast_t *a_emission_hash, bool a_from_threshold);
 int dap_ledger_token_emission_load(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size, dap_hash_fast_t *a_token_emission_hash);
-char *dap_ledger_token_emission_err_code_to_str(int a_code);
 
-// Check if it addable
+// Checking a new transaction before adding to the cache
 int dap_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size, dap_chain_hash_fast_t *a_emission_hash);
 
 /* Add stake-lock item */
@@ -316,18 +343,6 @@ bool dap_ledger_tx_service_info(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_ha
 
 int dap_ledger_service_add(dap_chain_net_srv_uid_t a_uid, char *tag_str, dap_ledger_tag_check_callback_t a_callback);
 
-
-// Checking a new transaction before adding to the cache
-int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, 
-                                        dap_chain_datum_tx_t *a_tx, 
-                                        dap_hash_fast_t *a_tx_hash,
-                                        bool a_from_threshold, 
-                                        dap_list_t **a_list_bound_items, 
-                                        dap_list_t **a_list_tx_out, 
-                                        char **a_main_ticker,
-                                        dap_chain_net_srv_uid_t *a_tag,
-                                        dap_chain_tx_tag_action_type_t *a_action, bool a_check_for_removing);
-
 const char *dap_ledger_tx_calculate_main_ticker(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, int *a_ledger_rc);
 
 /**
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index 6e62d461f70fb3948bcfad59038a16bd2368dedb..5cfa52d7c014c2f8aa05af933eedc7ddd03c112a 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -54,7 +54,7 @@ typedef enum dap_chain_net_state {
     NET_STATE_ONLINE
 } dap_chain_net_state_t;
 
-typedef struct dap_chain_net{
+typedef struct dap_chain_net {
     struct {
         dap_chain_net_id_t id;
         char * name;
@@ -181,7 +181,7 @@ dap_chain_net_t *dap_chain_net_iter_start();
 dap_chain_net_t *dap_chain_net_iter_next(dap_chain_net_t*);
 
 int dap_chain_net_verify_datum_for_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, dap_hash_fast_t *a_datum_hash);
-char *dap_chain_net_verify_datum_err_code_to_str(dap_chain_datum_t *a_datum, int a_code);
+const char *dap_chain_net_verify_datum_err_code_to_str(dap_chain_datum_t *a_datum, int a_code);
 
 void dap_chain_add_mempool_notify_callback(dap_chain_t *a_chain, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg);
 void dap_chain_net_add_nodelist_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg);
@@ -235,4 +235,4 @@ enum dap_chain_net_json_rpc_error_list{
 dap_chain_net_decree_t *dap_chain_net_get_net_decree(dap_chain_net_t *a_net);
 void dap_chain_net_set_net_decree(dap_chain_net_t *a_net, dap_chain_net_decree_t *a_decree);
 decree_table_t **dap_chain_net_get_decrees(dap_chain_net_t *a_net);
-anchor_table_t **dap_chain_net_get_anchors(dap_chain_net_t *a_net);
\ No newline at end of file
+anchor_table_t **dap_chain_net_get_anchors(dap_chain_net_t *a_net);
diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c
index a99b12f0c1091883f3985b8ec8e79a9020536774..8e55f3f3175e698d97497aff3eb96844f3179412 100644
--- a/modules/net/srv/dap_chain_net_srv.c
+++ b/modules/net/srv/dap_chain_net_srv.c
@@ -78,9 +78,9 @@ static int s_cli_net_srv(int argc, char **argv, void **reply);
 static void s_load(const char * a_path);
 static void s_load_all();
 
-static bool s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_cond_t *a_cond,
+static int s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_cond_t *a_cond,
                                        dap_chain_datum_tx_t *a_tx_in, bool a_owner);
-static bool s_fee_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_cond_t *a_cond,
+static int s_fee_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_cond_t *a_cond,
                                        dap_chain_datum_tx_t *a_tx_in, bool a_owner);
 static int s_str_to_price_unit(const char *a_price_unit_str, dap_chain_net_srv_price_unit_uid_t *a_price_unit);
 
@@ -649,7 +649,7 @@ static int s_cli_net_srv( int argc, char **argv, void **a_str_reply)
  * @param a_owner
  * @return
  */
-static bool s_fee_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t UNUSED_ARG *a_cond,
+static int s_fee_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t UNUSED_ARG *a_cond,
                                        dap_chain_datum_tx_t *a_tx_in, bool UNUSED_ARG a_owner)
 {
     dap_chain_net_t *l_net = a_ledger->net;
@@ -660,9 +660,9 @@ static bool s_fee_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_
             continue;
         dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0);
         if (!l_tx_in_cond)
-            return false;
+            return -1;
         if (dap_hash_fast_is_blank(&l_tx_in_cond->header.tx_prev_hash))
-            return false;
+            return -2;
         size_t l_block_size = 0;
         dap_chain_block_t *l_block = (dap_chain_block_t *)l_chain->callback_block_find_by_tx_hash(
                                                     l_chain, &l_tx_in_cond->header.tx_prev_hash, &l_block_size);
@@ -670,14 +670,14 @@ static bool s_fee_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_
             continue;
         dap_sign_t *l_sign_block = dap_chain_block_sign_get(l_block, l_block_size, 0);
         if (!l_sign_block)
-            return false;
+            return -3;
 
         // TX sign is already verified, just compare pkeys
         dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx_in, NULL, TX_ITEM_TYPE_SIG, NULL);
         dap_sign_t *l_sign_tx = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig);
-        return dap_sign_compare_pkeys(l_sign_block, l_sign_tx);
+        return dap_sign_compare_pkeys(l_sign_block, l_sign_tx) ? 0 : -5;
     }
-    return false;
+    return -4;
 }
 
 /**
@@ -689,16 +689,16 @@ static bool s_fee_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_
  * @param a_owner
  * @return
  */
-static bool s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_cond_t *a_cond,
+static int s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_cond_t *a_cond,
                                        dap_chain_datum_tx_t *a_tx_in, bool a_owner)
 {
     if (a_owner)
-        return true;
+        return 0;
     dap_chain_datum_tx_receipt_t *l_receipt = (dap_chain_datum_tx_receipt_t *)
                                                dap_chain_datum_tx_item_get(a_tx_in, NULL, TX_ITEM_TYPE_RECEIPT, NULL);
     if (!l_receipt){
         log_it(L_ERROR, "Can't find receipt.");
-        return false;
+        return -1;
     }
 
     // Check provider sign
@@ -706,12 +706,12 @@ static bool s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out
 
     if (!l_sign){
         log_it(L_ERROR, "Can't get provider sign from receipt.");
-        return false;
+        return -2;
     }
 
     if (dap_sign_verify_all(l_sign, dap_sign_get_size(l_sign), &l_receipt->receipt_info, sizeof(l_receipt->receipt_info))){
         log_it(L_ERROR, "Provider sign in receipt not passed verification.");
-        return false;
+        return -3;
     }
 
     // Checking the signature matches the provider's signature
@@ -719,7 +719,7 @@ static bool s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out
     dap_hash_fast_t l_provider_pkey_hash = {};
     if (!dap_sign_get_pkey_hash(l_sign, &l_provider_pkey_hash)){
         log_it(L_ERROR, "Can't get pkey hash from provider sign.");
-        return false;
+        return -4;
     }
 
     int l_item_size = 0;
@@ -732,34 +732,34 @@ static bool s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out
     l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_sig);
     if (!l_sign){
         log_it(L_ERROR, "Provider sign from tx sig_item");
-        return false;
+        return -5;
     }
 
     if(!dap_sign_get_pkey_hash(l_sign, &l_tx_sign_pkey_hash)){
         log_it(L_ERROR, "Can't get pkey hash from tx provider signature");
-        return false;
+        return -6;
     }
 
     if(!dap_hash_fast_compare(&l_tx_sign_pkey_hash, &l_provider_pkey_hash)){
         log_it(L_ERROR, "Provider signature in receipt and tx is different.");
-        return false;
+        return -7;
     }
 
     // Check client sign
     l_sign = dap_chain_datum_tx_receipt_sign_get(l_receipt, l_receipt->size, 1);
     if (!l_sign){
         log_it(L_ERROR, "Can't get client signature from receipt.");
-        return false;
+        return -8;
     }
     dap_hash_fast_t l_pkey_hash = {};
     if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash)){
         log_it(L_ERROR, "Can't get pkey hash from receipt client signature");
-        return false;
+        return -9;
     }
 
     if(!dap_hash_fast_compare(&l_pkey_hash, &a_cond->subtype.srv_pay.pkey_hash)){
         log_it(L_ERROR, "Client signature in receipt is invalid!");
-        return false;
+        return -10;
     }
 
     // Check price is less than maximum
@@ -771,13 +771,13 @@ static bool s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out
     if (l_receipt->receipt_info.units != 0){
         DIV_256(l_receipt->receipt_info.value_datoshi, GET_256_FROM_64(l_receipt->receipt_info.units), &l_unit_price);
     } else {
-        return false;
+        return -11;
     }
 
     if( !IS_ZERO_256(l_prev_out_cond->subtype.srv_pay.unit_price_max_datoshi) &&
         compare256(l_unit_price, l_prev_out_cond->subtype.srv_pay.unit_price_max_datoshi) > 0){
         log_it(L_ERROR, "Value in receipt is exceed max allowable price.");
-        return false;
+        return -12;
     }
 
     // check remainder on srv pay cond out is valid
@@ -814,10 +814,10 @@ static bool s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out
     if (compare256(l_value, l_cond_out_value)){
         log_it(L_ERROR, "Value in tx out is invalid!");
         dap_list_free(l_list_out);
-        return false;
+        return -13;
     }
     dap_list_free(l_list_out);
-    return true;
+    return 0;
 }
 
 dap_chain_net_srv_price_t * dap_chain_net_srv_get_price_from_order(dap_chain_net_srv_t *a_srv, const char *a_config_section, dap_chain_hash_fast_t* a_order_hash){
diff --git a/modules/service/stake/dap_chain_net_srv_stake_lock.c b/modules/service/stake/dap_chain_net_srv_stake_lock.c
index a4eaa6675376fc3c32503a85fb57f25d8e4eb60c..7c6651107e2aea476f78f921fe10ea76d3ea1b1e 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_lock.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_lock.c
@@ -108,7 +108,7 @@ dap_chain_datum_t *s_stake_unlock_datum_create(dap_chain_net_t *a_net, dap_enc_k
                                                const char *a_delegated_ticker_str, uint256_t a_delegated_value,int *res);
 // Callbacks
 static void s_stake_lock_callback_updater(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_prev_out_item);
-static bool s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner);
+static int s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner);
 
 static inline int s_tsd_str_cmp(const byte_t *a_tsdata, size_t a_tsdsize,  const char *str ) {
     size_t l_strlen = (size_t)strlen(str);
@@ -251,19 +251,10 @@ int dap_chain_net_srv_stake_lock_init()
 {
     dap_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, s_stake_lock_callback_verificator, s_stake_lock_callback_updater, NULL);
     dap_cli_server_cmd_add("stake_lock", s_cli_stake_lock, "Stake lock service commands",
-       "Command:"
-                "stake_lock hold\n"
-                "Required parameters:\n"
-                "-net <net name> -w <wallet name> -time_staking <in YYMMDD>\n"
-                "-token <ticker> -value <value> -fee <value>\n"
-                "Optional parameters:\n"
-                "-chain <chain> -reinvest <percentage from 1 to 100>\n"
-                "Command:"
-                "stake_lock take\n"
-                "Required parameters:\n"
-                "-net <net name> -w <wallet name> -tx <transaction hash> -fee <value>\n"
-                "Optional parameters:\n"
-                "-chain <chain>\n"
+                "stake_lock hold -net <net_name> -w <wallet_name> -time_staking <YYMMDD> -token <ticker> -value <value> -fee <value>"
+                            "[-chain <chain_name>] [-reinvest <percentage>]\n"
+                "stake_lock take -net <net_name> -w <wallet_name> -tx <transaction_hash> -fee <value>"
+                            "[-chain <chain_name>]\n"
     );
     s_debug_more = dap_config_get_item_bool_default(g_config, "ledger", "debug_more", false);
 
@@ -310,8 +301,6 @@ static enum error_code s_cli_hold(int a_argc, char **a_argv, int a_arg_index, da
     dap_chain_wallet_t					*l_wallet;
     dap_chain_addr_t					*l_addr_holder;
     dap_chain_datum_token_t 			*l_delegated_token;
-    dap_tsd_t							*l_tsd;
-    dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section;
 
     dap_string_append_printf(output_line, "---> HOLD <---\n");
 
@@ -352,24 +341,14 @@ static enum error_code s_cli_hold(int a_argc, char **a_argv, int a_arg_index, da
 
     dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker_str, l_ticker_str);
 
-    if (NULL == (l_delegated_token = dap_ledger_token_ticker_check(l_ledger, l_delegated_ticker_str))
-    ||	(l_delegated_token->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE)
-    ||	!l_delegated_token->header_native_decl.tsd_total_size
-    ||	NULL == (l_tsd = dap_tsd_find(l_delegated_token->data_n_tsd, l_delegated_token->header_native_decl.tsd_total_size,
-                                      DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) {
-        dap_string_append_printf(output_line, "'%s'", l_delegated_ticker_str);
+    if (NULL == (l_delegated_token = dap_ledger_token_ticker_check(l_ledger, l_delegated_ticker_str)))
         return NO_DELEGATED_TOKEN_ERROR;
-    }
-
-    l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
-    if (!l_tsd_section || strcmp(l_ticker_str, (char*)l_tsd_section->ticker_token_from))
-        return TOKEN_ERROR;
 
-    if (IS_ZERO_256(l_tsd_section->emission_rate))
+    uint256_t l_emission_rate = dap_ledger_token_get_emission_rate(l_ledger, l_delegated_ticker_str);
+    if (IS_ZERO_256(l_emission_rate))
         return TOKEN_ERROR;
 
-    MULT_256_COIN(l_value, l_tsd_section->emission_rate, &l_value_delegated);
-    if (IS_ZERO_256(l_value_delegated))
+    if (MULT_256_COIN(l_value, l_emission_rate, &l_value_delegated) || IS_ZERO_256(l_value_delegated))
         return COINS_FORMAT_ERROR;
 
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str);
@@ -418,7 +397,7 @@ static enum error_code s_cli_hold(int a_argc, char **a_argv, int a_arg_index, da
     dap_time_t l_time_now = dap_time_now();
     if (l_time_staking < l_time_now)
         return TIME_ERROR;
-    l_time_staking  -= l_time_now;
+    l_time_staking -= l_time_now;
 
     if (dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-reinvest", &l_reinvest_percent_str)
     && NULL != l_reinvest_percent_str) {
@@ -499,8 +478,6 @@ static enum error_code s_cli_take(int a_argc, char **a_argv, int a_arg_index, da
     dap_chain_datum_t					*l_datum;
     dap_chain_t							*l_chain;
     dap_chain_datum_token_t				*l_delegated_token;
-    dap_tsd_t							*l_tsd;
-    dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section;
 
     dap_string_append_printf(output_line, "---> TAKE <---\n");
 
@@ -558,25 +535,15 @@ static enum error_code s_cli_take(int a_argc, char **a_argv, int a_arg_index, da
 
         dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker_str, l_ticker_str);
 
-        if (NULL == (l_delegated_token = dap_ledger_token_ticker_check(l_ledger, l_delegated_ticker_str))
-            ||	(l_delegated_token->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE)
-            ||	!l_delegated_token->header_native_decl.tsd_total_size
-            ||	NULL == (l_tsd = dap_tsd_find(l_delegated_token->data_n_tsd,
-                                              l_delegated_token->header_native_decl.tsd_total_size,
-                                              DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) {
-            dap_string_append_printf(output_line, "'%s'", l_delegated_ticker_str);
+        if (NULL == (l_delegated_token = dap_ledger_token_ticker_check(l_ledger, l_delegated_ticker_str)))
             return NO_DELEGATED_TOKEN_ERROR;
-        }
 
-        l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
-        if (!l_tsd_section || strcmp(l_ticker_str, (char*)l_tsd_section->ticker_token_from))
-            return TOKEN_ERROR;
+        uint256_t l_emission_rate = dap_ledger_token_get_emission_rate(l_ledger, l_delegated_ticker_str);
 
-        if (!IS_ZERO_256(l_tsd_section->emission_rate)) {
-            MULT_256_COIN(l_tx_out_cond->header.value, l_tsd_section->emission_rate, &l_value_delegated);
-            if (IS_ZERO_256(l_value_delegated))
-                return COINS_FORMAT_ERROR;
-        }
+        if (IS_ZERO_256(l_emission_rate) ||
+                MULT_256_COIN(l_tx_out_cond->header.value, l_emission_rate, &l_value_delegated) ||
+                IS_ZERO_256(l_value_delegated))
+            return COINS_FORMAT_ERROR;
     }
 
     if (!dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-w", &l_wallet_str)
@@ -1019,65 +986,56 @@ static char *s_update_date_by_using_month_count(char *time, uint8_t month_count)
  * @param a_owner
  * @return
  */
-static bool s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner)
+static int s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner)
 {
     dap_chain_datum_tx_t									*l_burning_tx       = NULL;
     dap_chain_datum_tx_receipt_t							*l_receipt          = NULL;
     uint256_t												l_value_delegated   = {};
     dap_hash_fast_t											l_burning_tx_hash;
-    dap_chain_datum_token_tsd_delegate_from_stake_lock_t	*l_tsd_section;
-    dap_tsd_t												*l_tsd;
     dap_chain_tx_in_cond_t									*l_tx_in_cond;
     const char												*l_prev_tx_ticker;
     dap_chain_datum_token_t									*l_delegated_token;
     char 													l_delegated_ticker_str[DAP_CHAIN_TICKER_SIZE_MAX];
 
     if (!a_owner)
-        return false;
+        return -1;
+
+    if (a_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_BY_TIME &&
+            a_cond->subtype.srv_stake_lock.time_unlock > dap_time_now())
+        return -2;
 
-    if (a_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_BY_TIME) {
-        if (a_cond->subtype.srv_stake_lock.time_unlock > dap_time_now())
-            return false;
-    }
     if (NULL == (l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(
                                                             a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0)))
-        return false;
+        return -3;
     if (dap_hash_fast_is_blank(&l_tx_in_cond->header.tx_prev_hash))
         return false;
     if (NULL == (l_prev_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(
                                                             a_ledger, &l_tx_in_cond->header.tx_prev_hash)))
-        return false;
+        return -4;
 
     dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker_str, l_prev_tx_ticker);
 
     if (a_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_CREATE_BASE_TX ||
             a_cond->subtype.srv_stake_lock.flags & DAP_CHAIN_NET_SRV_STAKE_LOCK_FLAG_EMIT) {
-        if (NULL == (l_delegated_token = dap_ledger_token_ticker_check(a_ledger, l_delegated_ticker_str))
-            ||	(l_delegated_token->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE)
-            ||	!l_delegated_token->header_native_decl.tsd_total_size
-            ||	NULL == (l_tsd = dap_tsd_find(l_delegated_token->data_n_tsd,
-                                              l_delegated_token->header_native_decl.tsd_total_size,
-                                              DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) {
-            return false;
-        }
+        if (NULL == (l_delegated_token = dap_ledger_token_ticker_check(a_ledger, l_delegated_ticker_str)))
+            return -5;
 
-        l_tsd_section = _dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
+        uint256_t l_emission_rate = dap_ledger_token_get_emission_rate(a_ledger, l_delegated_ticker_str);
 
-        if (!IS_ZERO_256(l_tsd_section->emission_rate)) {
-            MULT_256_COIN(a_cond->header.value, l_tsd_section->emission_rate, &l_value_delegated);
-            if (IS_ZERO_256(l_value_delegated))
-                return false;
-        }
+        if (IS_ZERO_256(l_emission_rate) ||
+                MULT_256_COIN(a_cond->header.value, l_emission_rate, &l_value_delegated) ||
+                IS_ZERO_256(l_value_delegated))
+            return -6;
 
         l_receipt = (dap_chain_datum_tx_receipt_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_RECEIPT, 0);
         if (l_receipt) {
             if (!dap_chain_net_srv_uid_compare_scalar(l_receipt->receipt_info.srv_uid, DAP_CHAIN_NET_SRV_STAKE_LOCK_ID))
-                return false;
+                return -7;
             if (!l_receipt->exts_size)
-                return false;
+                return -8;
             l_burning_tx_hash = *(dap_hash_fast_t*)l_receipt->exts_n_signs;
             if (dap_hash_fast_is_blank(&l_burning_tx_hash))
-                return false;
+                return -9;
             l_burning_tx = dap_ledger_tx_find_by_hash(a_ledger, &l_burning_tx_hash);
             if (!l_burning_tx) {
                 char l_burning_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
@@ -1086,7 +1044,7 @@ static bool s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_
                 dap_get_data_hash_str_static(a_tx_in, dap_chain_datum_tx_get_size(a_tx_in), l_take_tx_hash_str);
                 debug_if(s_debug_more, L_ERROR, "[Legacy] Can't find burning tx with hash %s, obtained from the receipt of take tx %s",
                        l_burning_tx_hash_str, l_take_tx_hash_str);
-                return false;
+                return -10;
             }
         } else
             l_burning_tx = a_tx_in;
@@ -1113,7 +1071,7 @@ static bool s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_
         dap_list_free(l_outs_list);
         if (IS_ZERO_256(l_blank_out_value)) {
             log_it(L_ERROR, "Can't find OUT with BLANK addr in burning TX");
-            return false;
+            return -11;
         }
 
         if (s_debug_more) {
@@ -1131,12 +1089,12 @@ static bool s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_
             SUM_256_256(l_value_delegated, GET_256_FROM_64(10), &l_value_delegated);
             if (!EQUAL_256(l_blank_out_value, l_value_delegated)) {
                 log_it(L_ERROR, "Burning and delegated value mismatch");
-                return false;
+                return -12;
             }
         }
     }
 
-    return true;
+    return 0;
 }
 
 /**
diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
index bf15114299f40463be651107d60a5b19b553e62e..cd25bbb34f3c2ebec37003596d1339507e55d950 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
@@ -48,7 +48,7 @@
 
 static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply);
 
-static bool s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond,
+static int s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond,
                                                       dap_chain_datum_tx_t *a_tx_in, bool a_owner);
 static void s_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond);
 
@@ -197,21 +197,21 @@ void dap_chain_net_srv_stake_pos_delegate_deinit()
     s_srv_stake_list = NULL;
 }
 
-static bool s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond,
+static int s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_cond,
                                          dap_chain_datum_tx_t *a_tx_in, bool a_owner)
 {
     dap_chain_net_srv_stake_t *l_srv_stake = s_srv_stake_by_net_id(a_ledger->net->pub.id);
-    dap_return_val_if_fail(l_srv_stake, false);
+    dap_return_val_if_fail(l_srv_stake, -1);
     // It's a order conditional TX
     if (dap_chain_addr_is_blank(&a_cond->subtype.srv_stake_pos_delegate.signing_addr) ||
             a_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64 == 0) {
         if (a_owner)
-            return true;
+            return 0;
         int l_out_idx = 0;
         dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(a_tx_in, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_out_idx);
         if (!l_tx_out_cond) {
             log_it(L_ERROR, "Condition not found in conditional tx");
-            return false;
+            return -2;
         }
         if (compare256(l_tx_out_cond->header.value, a_cond->header.value)) {
             char *l_in_value = dap_chain_balance_to_coins(l_tx_out_cond->header.value);
@@ -219,35 +219,35 @@ static bool s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_ou
             log_it(L_WARNING, "In value %s is not equal to out value %s", l_in_value, l_out_value);
             DAP_DELETE(l_in_value);
             DAP_DELETE(l_out_value);
-            return false;
+            return -3;
         }
         if (l_tx_out_cond->tsd_size != a_cond->tsd_size ||
                 memcmp(l_tx_out_cond->tsd, a_cond->tsd, a_cond->tsd_size)) {
             log_it(L_WARNING, "Conditional out and conditional in have different TSD sections");
-            return false;
+            return -4;
         }
         if (dap_chain_addr_is_blank(&l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr) ||
                 l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64 == 0) {
             log_it(L_WARNING, "Not blank address or key fields in order conditional tx");
-            return false;
+            return -5;
         }
-        return true;
+        return 0;
     }
     // It's a delegation conitional TX
     dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0);
     if (!l_tx_in_cond) {
         log_it(L_ERROR, "Conditional in item not found in checking tx");
-        return false;
+        return -6;
     }
     dap_hash_fast_t *l_prev_hash = &l_tx_in_cond->header.tx_prev_hash;
     if (dap_hash_fast_is_blank(l_prev_hash)) {
         log_it(L_ERROR, "Blank hash of prev tx in tx_in_cond");
-        return false;
+        return -7;
     }
     dap_chain_datum_tx_t *l_prev_tx = dap_ledger_tx_find_by_hash(a_ledger, l_prev_hash);
     if (!l_prev_tx) {
         log_it(L_ERROR, "Previous tx not found for now but is found in ledger before");
-        return false;
+        return -8;
     }
     bool l_owner = false;
     dap_chain_tx_in_cond_t *l_tx_prev_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(l_prev_tx, 0, TX_ITEM_TYPE_IN_COND, 0);
@@ -259,28 +259,28 @@ static bool s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_ou
         dap_sign_t *l_owner_sign = dap_chain_datum_tx_get_sign(l_owner_tx, 0);
         if (!l_owner_sign) {
             log_it(L_ERROR, "Can't get owner sign");
-            return false;
+            return -9;
         }
         dap_sign_t *l_taker_sign = dap_chain_datum_tx_get_sign(a_tx_in, 0);
         if (!l_taker_sign) {
             log_it(L_ERROR, "Can't get taker sign");
-            return false;
+            return -10;
         }
         l_owner = dap_sign_compare_pkeys(l_taker_sign, l_owner_sign);
     }
     if (!l_owner) {
         log_it(L_WARNING, "Trying to spend conditional tx not by owner");
-        return false;
+        return -11;
     }
     if (a_tx_in->header.ts_created < 1706227200) // Jan 26 2024 00:00:00 GMT, old policy rules
-        return true;
+        return 0;
     dap_chain_net_srv_stake_item_t *l_stake;
     HASH_FIND(ht, l_srv_stake->tx_itemlist, l_prev_hash, sizeof(dap_hash_t), l_stake);
     if (l_stake) {
         log_it(L_WARNING, "Key is active with delegation decree, need to revoke it first");
-        return false;
+        return -12;
     }
-    return true;
+    return 0;
 }
 
 static void s_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond)
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index 18c75acb556405503da65da0899da6e2c00f38e6..674a158492f94896347f7e16932eb77b3becc3ff 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -60,7 +60,7 @@ static dap_chain_net_srv_fee_item_t *s_service_fees = NULL; // Governance statem
 static pthread_rwlock_t s_service_fees_rwlock = PTHREAD_RWLOCK_INITIALIZER;
 
 static void s_callback_decree (dap_chain_net_srv_t * a_srv, dap_chain_net_t *a_net, dap_chain_t * a_chain, dap_chain_datum_decree_t * a_decree, size_t a_decree_size);
-static bool s_xchange_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_cond_t *a_cond,
+static int s_xchange_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_cond_t *a_cond,
                             dap_chain_datum_tx_t *a_tx_in, bool a_owner);
 const dap_chain_net_srv_uid_t c_dap_chain_net_srv_xchange_uid = {.uint64= DAP_CHAIN_NET_SRV_XCHANGE_ID};
 
@@ -241,22 +241,22 @@ void dap_chain_net_srv_xchange_deinit()
  * @param a_owner
  * @return
  */
-static bool s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_tx_out_cond,
+static int s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_tx_out_cond,
                                            dap_chain_datum_tx_t *a_tx_in, bool a_owner)
 {
     if (a_owner)
-        return true;
+        return 0;
     if(!a_tx_in || !a_tx_out_cond)
-        return false;
+        return -1;
 
     dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0);
     if (!l_tx_in_cond)
-        return false;
+        return -2;
     if (dap_hash_fast_is_blank(&l_tx_in_cond->header.tx_prev_hash))
-        return false;
+        return -3;
     const char *l_sell_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_tx_in_cond->header.tx_prev_hash);
     if (!l_sell_ticker)
-        return false;
+        return -4;
     const char *l_buy_ticker = a_tx_out_cond->subtype.srv_xchange.buy_token;
 
     uint256_t l_buy_val = {}, l_fee_val = {},
@@ -318,11 +318,11 @@ static bool s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_
 
     uint256_t l_sell_val, l_buyer_val_expected;
     if (compare256(l_sell_again_val, a_tx_out_cond->header.value) >= 0)
-        return false;
+        return -5;
     SUBTRACT_256_256(a_tx_out_cond->header.value, l_sell_again_val, &l_sell_val);
     MULT_256_COIN(l_sell_val, a_tx_out_cond->subtype.srv_xchange.rate, &l_buyer_val_expected);
     if (compare256(l_buyer_val_expected, l_buy_val) > 0)
-        return false;
+        return -6;
 
     /* Check the condition for fee verification success
      * out_ext.fee_addr(fee_ticker).value >= fee_value
@@ -331,9 +331,9 @@ static bool s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_
         if (l_service_fee_type == SERIVCE_FEE_NATIVE_PERCENT || l_service_fee_type == SERVICE_FEE_OWN_PERCENT)
             MULT_256_COIN(l_service_fee_val, l_sell_val, &l_service_fee_val);
         if (compare256(l_fee_val, l_service_fee_val) < 0)
-            return false;
+            return -7;
     }
-    return true;
+    return 0;
 }
 
 /**
diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c
index 760f1b45fc045830008a5a843da9b391b122155b..dc602a255c339bcea7e0b091fd6543eb2491123f 100644
--- a/modules/type/blocks/dap_chain_block.c
+++ b/modules/type/blocks/dap_chain_block.c
@@ -66,7 +66,7 @@ dap_chain_block_t *dap_chain_block_new(dap_chain_hash_fast_t *a_prev_block, size
         return NULL;
     }
     l_block->hdr.signature = DAP_CHAIN_BLOCK_SIGNATURE;
-    l_block->hdr.version = 1;
+    l_block->hdr.version = 2;
     l_block->hdr.ts_created = time(NULL);
 
     size_t l_block_size = sizeof(l_block->hdr);
@@ -371,7 +371,7 @@ bool dap_chain_block_sign_match_pkey(const dap_chain_block_t *a_block, size_t a_
             log_it(L_WARNING, "Empty or corrupted sign");
             return false;
         }
-        if (dap_pkey_match_sign(a_sign_pkey, l_sign))
+        if (dap_pkey_compare_with_sign(a_sign_pkey, l_sign))
             return true;
         l_offset += l_sign_size;
     }
diff --git a/modules/type/blocks/tests/dap_chain_blocks_test.c b/modules/type/blocks/tests/dap_chain_blocks_test.c
index 289a18c3e170273816afe78593de3dbb38912460..1faa1f2e7e92ab83b2d12f607809b0ec39cd3617 100644
--- a/modules/type/blocks/tests/dap_chain_blocks_test.c
+++ b/modules/type/blocks/tests/dap_chain_blocks_test.c
@@ -36,7 +36,7 @@ bool dap_chain_block_test_compare_chain_hash_lists(dap_chain_t* a_chain, dap_lis
     dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size_from_iter);
     for (dap_list_t *l_branch_temp = a_atoms_hash_list; l_branch_temp && l_atom; 
         l_branch_temp = l_branch_temp->next, l_atom = a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size_from_iter)){
-        dap_test_msg("Check block %s : num %d and %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash), l_iter->cur_num,
+        dap_test_msg("Check block %s : num %" DAP_UINT64_FORMAT_U " and %s", dap_chain_hash_fast_to_str_static(l_iter->cur_hash), l_iter->cur_num,
                                             dap_chain_hash_fast_to_str_static((dap_hash_fast_t*)l_branch_temp->data));
         if (!dap_hash_fast_compare(l_iter->cur_hash, (dap_hash_fast_t*)l_branch_temp->data)){
             a_chain->callback_atom_iter_delete(l_iter);
@@ -186,4 +186,4 @@ void dap_chain_blocks_test()
     dap_assert_PIF(ret_val == ATOM_PASS, "Add existing block into middle of forked chain. Must be passed: ");
 
     dap_pass_msg("Fork handling test: ")
-}
\ No newline at end of file
+}
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index 0ce700904af8229199d96890c481b74bc9d344d8..81c8c3552e8efd8522c46b5e5330a3c2a13c2df4 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -404,7 +404,7 @@ static int s_dap_chain_add_atom_to_events_table(dap_chain_cs_dag_t *a_dag, dap_c
         return -1;
     }
     dap_hash_fast_t l_datum_hash;
-    dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_datum_hash);
+    dap_chain_datum_calc_hash(l_datum, &l_datum_hash);
     int l_ret = dap_chain_datum_add(a_dag->chain, l_datum, l_datum_size, &l_datum_hash);
     if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX)  // && l_ret == 0
         PVT(a_dag)->tx_count++;
@@ -611,7 +611,7 @@ static bool s_chain_callback_datums_pool_proc(dap_chain_t *a_chain, dap_chain_da
     dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain);
     /* If datum passes thru rounds, let's check if it wasn't added before */
     dap_chain_hash_fast_t l_datum_hash;
-    dap_hash_fast(a_datum->data, a_datum->header.data_size, &l_datum_hash);
+    dap_chain_datum_calc_hash(a_datum, &l_datum_hash);
     if (!l_dag->is_add_directly) {
         bool l_dup_found = false;
         size_t l_objs_count = 0;
@@ -774,8 +774,9 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t *a_c
             return ATOM_ACCEPT;
         }
     }
-    if (dap_chain_cs_dag_event_calc_size(l_event, a_atom_size) != a_atom_size) {
-        debug_if(s_debug_more, L_WARNING, "Event size not equal to expected");
+    size_t l_atom_size = dap_chain_cs_dag_event_calc_size(l_event, a_atom_size);
+    if (l_atom_size != a_atom_size) {
+        log_it(L_WARNING, "Event size %zu not equal to expected %zu", l_atom_size, a_atom_size);
         return  ATOM_REJECT;
     }
 
@@ -804,26 +805,24 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t *a_c
     }
 
     //chain coherence
-    if (! PVT(l_dag)->events ){
-        res = ATOM_MOVE_TO_THRESHOLD;
-        //log_it(L_DEBUG, "*** event %p goes to threshold", l_event);
-    } else {
-        //log_it(L_DEBUG, "*** event %p hash count %d",l_event, l_event->header.hash_count);
-        for (size_t i = 0; i< l_event->header.hash_count; i++) {
-            dap_chain_hash_fast_t * l_hash =  ((dap_chain_hash_fast_t *) l_event->hashes_n_datum_n_signs) + i;
-            dap_chain_cs_dag_event_item_t * l_event_search = NULL;
-            pthread_mutex_lock(l_events_mutex);
-            HASH_FIND(hh, PVT(l_dag)->events ,l_hash ,sizeof (*l_hash),  l_event_search);
-            pthread_mutex_unlock(l_events_mutex);
-            if (l_event_search == NULL) {
-                if(s_debug_more) {
-                    char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
-                    dap_chain_hash_fast_to_str(l_hash, l_hash_str, sizeof(l_hash_str));
-                    log_it(L_WARNING, "Hash %s wasn't in hashtable of previously parsed", l_hash_str);
-                }
-                res = ATOM_MOVE_TO_THRESHOLD;
-                break;
+    if (! PVT(l_dag)->events )
+        return ATOM_MOVE_TO_THRESHOLD;
+
+    for (size_t i = 0; i< l_event->header.hash_count; i++) {
+        dap_chain_hash_fast_t * l_hash =  ((dap_chain_hash_fast_t *) l_event->hashes_n_datum_n_signs) + i;
+        dap_chain_cs_dag_event_item_t * l_event_search = NULL;
+        pthread_mutex_lock(l_events_mutex);
+        HASH_FIND(hh, PVT(l_dag)->events ,l_hash ,sizeof (*l_hash),  l_event_search);
+        pthread_mutex_unlock(l_events_mutex);
+        if (l_event_search == NULL) {
+            if(s_debug_more) {
+                char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
+                dap_chain_hash_fast_to_str(l_hash, l_hash_str, sizeof(l_hash_str));
+                log_it(L_WARNING, "Hash %s wasn't in hashtable of previously parsed, event %s goes to threshold",
+                                        l_hash_str, dap_hash_fast_to_str_static(a_atom_hash));
             }
+            res = ATOM_MOVE_TO_THRESHOLD;
+            break;
         }
     }
 
@@ -938,7 +937,7 @@ dap_chain_cs_dag_event_item_t* s_dag_proc_treshold(dap_chain_cs_dag_t * a_dag)
     dap_chain_cs_dag_event_item_t * l_event_item = NULL, * l_event_item_tmp = NULL;
     pthread_mutex_lock(&PVT(a_dag)->events_mutex);
     int l_count = HASH_COUNT(PVT(a_dag)->events_treshold);
-    log_it(L_DEBUG, "*** %d events in threshold", l_count);
+    debug_if(s_debug_more, L_DEBUG, "*** %d events in threshold", l_count);
     HASH_ITER(hh, PVT(a_dag)->events_treshold, l_event_item, l_event_item_tmp) {
         dap_dag_threshold_verification_res_t ret = dap_chain_cs_dag_event_verify_hashes_with_treshold(a_dag, l_event_item->event);
         if (ret == DAP_THRESHOLD_OK) {
diff --git a/modules/type/none/dap_chain_cs_none.c b/modules/type/none/dap_chain_cs_none.c
index e6d7b4d14c0e1672fa57fa6dab2fd1d6e8dfdb61..65b7dc8771afa0cedf4492b89bbdaf9a8a429719 100644
--- a/modules/type/none/dap_chain_cs_none.c
+++ b/modules/type/none/dap_chain_cs_none.c
@@ -88,7 +88,7 @@ static dap_chain_datum_t *s_nonconsensus_callback_datum_iter_get_first(dap_chain
 static dap_chain_datum_t *s_nonconsensus_callback_datum_iter_get_next(dap_chain_datum_iter_t *a_datum_iter);
 static dap_chain_datum_t *s_nonconsensus_callback_datum_find_by_hash(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_datum_hash,
                                                                    dap_chain_hash_fast_t *a_atom_hash, int *a_ret_code);
-
+static uint64_t s_nonconsensus_callback_get_count_atom(dap_chain_t *a_chain);
 static int s_cs_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg);
 static void s_nonconsensus_delete(dap_chain_t *a_chain);
 
@@ -123,12 +123,12 @@ static void s_nonconsensus_callback_mempool_notify(dap_store_obj_t *a_obj, void
 
 static void s_changes_callback_notify(dap_store_obj_t *a_obj, void *a_arg)
 {
-    dap_return_if_fail(dap_store_obj_get_type(a_obj) == DAP_GLOBAL_DB_OPTYPE_ADD && a_obj->value_len && a_obj->value);
+    dap_return_if_fail(a_obj->value_len && a_obj->value);
     dap_chain_t *l_chain = a_arg;
     if (dap_store_obj_get_type(a_obj) == DAP_GLOBAL_DB_OPTYPE_DEL)
         return;
     dap_hash_fast_t l_hash = {};
-    dap_hash_fast(a_obj->value, a_obj->value_len, &l_hash);
+    dap_chain_hash_fast_from_hex_str(a_obj->key, &l_hash);
     s_nonconsensus_callback_atom_add(l_chain, (dap_chain_datum_t *)a_obj->value, a_obj->value_len, &l_hash);
 }
 
@@ -195,7 +195,8 @@ static int s_cs_callback_new(dap_chain_t *a_chain, dap_config_t UNUSED_ARG *a_ch
 
     a_chain->callback_atom_get_datums = s_nonconsensus_callback_atom_get_datum;
     a_chain->callback_atom_get_timestamp = s_nonconsensus_callback_atom_get_timestamp;
-
+    // Get atom count in chain
+    a_chain->callback_count_atom = s_nonconsensus_callback_get_count_atom;
     // Datum callbacks
     a_chain->callback_datum_iter_create = s_nonconsensus_callback_datum_iter_create;
     a_chain->callback_datum_iter_delete = s_nonconsensus_callback_datum_iter_delete;
@@ -264,7 +265,7 @@ static void s_nonconsensus_ledger_load(dap_chain_t *a_chain)
         dap_global_db_obj_t *it = l_values + i;
         // load ledger
         dap_hash_fast_t l_hash = {};
-        dap_hash_fast(it->value, it->value_len, &l_hash);
+        dap_chain_hash_fast_from_hex_str(it->key, &l_hash);
         s_nonconsensus_callback_atom_add(a_chain, it->value, it->value_len, &l_hash);
         log_it(L_DEBUG,"Load mode, doesn't save item %s:%s", it->key, l_nochain_pvt->group_datums);
     }
@@ -286,7 +287,7 @@ static size_t s_nonconsensus_callback_datums_pool_proc(dap_chain_t * a_chain, da
         dap_chain_datum_t *l_datum = a_datums[i];
         dap_hash_fast_t l_datum_hash;
         char l_db_key[DAP_CHAIN_HASH_FAST_STR_SIZE];
-        dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_datum_hash);
+        dap_chain_datum_calc_hash(l_datum, &l_datum_hash);
         dap_chain_hash_fast_to_str(&l_datum_hash, l_db_key, sizeof(l_db_key));
         int l_rc = dap_chain_net_verify_datum_for_add(a_chain, l_datum, &l_datum_hash);
         if (l_rc != 0) {
@@ -521,6 +522,16 @@ static dap_chain_datum_t **s_nonconsensus_callback_atom_get_datum(dap_chain_atom
         return NULL;
 }
 
+static uint64_t s_nonconsensus_callback_get_count_atom(dap_chain_t *a_chain)
+{
+    dap_return_val_if_fail(a_chain, 0);
+    dap_nonconsensus_datum_hash_item_t *l_head = PVT(DAP_NONCONSENSUS(a_chain))->hash_items;
+    dap_nonconsensus_datum_hash_item_t *tmp;
+    uint64_t l_counter;
+    DL_COUNT(l_head, tmp, l_counter);
+    return l_counter;
+}
+
 static dap_chain_datum_iter_t *s_nonconsensus_callback_datum_iter_create(dap_chain_t *a_chain)
 {
     dap_chain_datum_iter_t *l_ret = DAP_NEW_Z(dap_chain_datum_iter_t);
diff --git a/project.yaml b/project.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b6755cc4839b38db5664ad426d50f56ff3698ff8
--- /dev/null
+++ b/project.yaml
@@ -0,0 +1,20 @@
+
+build_dependencies:
+  deb:
+    - 'build-essential'
+    - 'cmake'
+    - 'libmagic-dev'
+    - 'libsqlite3-dev'
+    - 'libjson-c-dev' 
+    - 'libffi-dev'
+    - 'file'
+    - 'python3-dev'
+    - 'curl'
+    - 'jq'
+    - 'xsltproc'
+    
+
+deploy_dependencies:
+  deb:
+    - 'ssh'
+