From afa350d4d074b5672fa7c098e2dbae7415d6a63f Mon Sep 17 00:00:00 2001
From: Roman Khlopkov <roman.khlopkov@demlabs.net>
Date: Fri, 11 Mar 2022 15:26:06 +0000
Subject: [PATCH] hotfix-5685

---
 dap-sdk/core/src/dap_strfuncs.c               |   2 +-
 dap-sdk/crypto/include/dap_pkey.h             |   9 -
 dap-sdk/crypto/src/dap_cert.c                 |  35 +--
 dap-sdk/crypto/src/dap_pkey.c                 |  58 ++--
 dap-sdk/net/client/dap_client_pvt.c           |  34 +--
 dap-sdk/net/client/include/dap_client_pvt.h   |   3 +-
 dap-sdk/net/core/dap_events_socket.c          |  18 +-
 dap-sdk/net/core/dap_worker.c                 |   2 +-
 .../http_server/http_client/dap_http_header.c |  30 +-
 .../http_client/include/dap_http_header.h     |   4 +-
 dap-sdk/net/stream/stream/CMakeLists.txt      |   2 +-
 dap-sdk/net/stream/stream/dap_stream.c        | 165 +++++++----
 dap-sdk/net/stream/stream/dap_stream_pkt.c    |   1 +
 .../net/stream/stream/include/dap_stream.h    |   5 +-
 modules/chain/dap_chain_ledger.c              |  30 +-
 .../dap_stream_ch_chain_net_srv.c             | 212 ++++----------
 .../dap_stream_ch_chain_net_srv.h             |   5 +-
 .../include/dap_stream_ch_chain_net_srv_pkt.h |   1 -
 modules/common/dap_chain_datum_tx.c           |   4 +-
 modules/common/dap_chain_datum_tx_items.c     |  30 +-
 modules/common/dap_chain_datum_tx_receipt.c   |  27 +-
 modules/common/include/dap_chain_common.h     |   6 +-
 modules/common/include/dap_chain_datum_tx.h   |   2 +-
 .../common/include/dap_chain_datum_tx_items.h |   2 +-
 .../include/dap_chain_datum_tx_receipt.h      |  14 +-
 modules/mempool/dap_chain_mempool.c           | 250 ++---------------
 modules/mempool/include/dap_chain_mempool.h   |  15 +-
 modules/net/dap_chain_net.c                   |   6 +-
 modules/net/dap_chain_node_cli.c              |   4 +-
 modules/net/dap_chain_node_cli_cmd.c          |  87 +++---
 modules/net/dap_chain_node_cli_cmd_tx.c       |   4 +-
 modules/net/dap_chain_node_client.c           |  19 +-
 modules/net/srv/dap_chain_net_srv.c           | 127 +++++++--
 modules/net/srv/dap_chain_net_srv_client.c    | 115 +++++---
 modules/net/srv/dap_chain_net_srv_common.c    |  77 -----
 .../srv/dap_chain_net_srv_stream_session.c    |   1 -
 modules/net/srv/include/dap_chain_net_srv.h   | 263 ++++++++++++++----
 .../srv/include/dap_chain_net_srv_client.h    |  16 +-
 .../srv/include/dap_chain_net_srv_common.h    | 209 --------------
 .../net/srv/include/dap_chain_net_srv_order.h |   2 +-
 .../dap_chain_net_srv_stream_session.h        |   8 +-
 .../service/stake/dap_chain_net_srv_stake.c   |   2 +-
 modules/service/vpn/dap_chain_net_srv_vpn.c   | 230 +--------------
 .../service/vpn/dap_chain_net_srv_vpn_cmd.c   |   1 +
 .../service/vpn/dap_chain_net_vpn_client.c    | 125 ++++++++-
 .../vpn/include/dap_chain_net_vpn_client.h    |   2 +
 .../xchange/dap_chain_net_srv_xchange.c       |   9 +-
 47 files changed, 939 insertions(+), 1334 deletions(-)
 delete mode 100644 modules/net/srv/dap_chain_net_srv_common.c
 delete mode 100755 modules/net/srv/include/dap_chain_net_srv_common.h

diff --git a/dap-sdk/core/src/dap_strfuncs.c b/dap-sdk/core/src/dap_strfuncs.c
index 58a01af802..11622f085b 100755
--- a/dap-sdk/core/src/dap_strfuncs.c
+++ b/dap-sdk/core/src/dap_strfuncs.c
@@ -29,7 +29,7 @@ bool dap_isstralnum(const char *c)
 
     for (size_t i = 0; i < str_len; i++)
     {
-        if (!isalnum(c[i]))
+        if (!isalnum(c[i]) && c[i] != '_' && c[i] != '-')
             return false;
     }
 
diff --git a/dap-sdk/crypto/include/dap_pkey.h b/dap-sdk/crypto/include/dap_pkey.h
index 93040b6a06..50256f7eca 100755
--- a/dap-sdk/crypto/include/dap_pkey.h
+++ b/dap-sdk/crypto/include/dap_pkey.h
@@ -68,13 +68,4 @@ typedef struct dap_pkey{
     uint8_t pkey[]; /// @param pkey @brief raw pkey dat
 } DAP_ALIGN_PACKED dap_pkey_t;
 
-static dap_pkey_t m_dap_pkey_null; // For sizeof nothing more
-
 dap_pkey_t *dap_pkey_from_enc_key(dap_enc_key_t *a_key);
-static inline size_t dap_pkey_from_enc_key_output_calc(dap_enc_key_t *a_key)
-{
-    return sizeof(m_dap_pkey_null.header)+ a_key->pub_key_data_size;
-}
-
-int dap_pkey_from_enc_key_output(dap_enc_key_t *a_key, void * a_output);
-
diff --git a/dap-sdk/crypto/src/dap_cert.c b/dap-sdk/crypto/src/dap_cert.c
index 9f660c5bb2..32bbdd3608 100755
--- a/dap-sdk/crypto/src/dap_cert.c
+++ b/dap-sdk/crypto/src/dap_cert.c
@@ -296,27 +296,30 @@ void dap_cert_delete_by_name(const char * a_cert_name)
 dap_cert_t * dap_cert_find_by_name(const char * a_cert_name)
 {
     dap_cert_item_t * l_cert_item = NULL;
+    dap_cert_t *l_ret = NULL;
     HASH_FIND_STR(s_certs,a_cert_name,l_cert_item);
     if ( l_cert_item ){
-        return l_cert_item->cert ;
+        l_ret = l_cert_item->cert ;
     } else {
-            dap_cert_t *l_cert = NULL;
-            uint16_t l_ca_folders_size = 0;
-            char **l_ca_folders;
-            char *l_cert_path = NULL;
-            l_ca_folders = dap_config_get_array_str(g_config, "resources", "ca_folders", &l_ca_folders_size);
-            for (uint16_t i = 0; i < l_ca_folders_size; ++i) {
-                l_cert_path = dap_strjoin("", l_ca_folders[i], "/", a_cert_name, ".dcert", (char*)NULL);
-                l_cert = dap_cert_file_load(l_cert_path);
-                if (l_cert) {
-                    goto ret;
-                }
+        dap_cert_t *l_cert = NULL;
+        uint16_t l_ca_folders_size = 0;
+        char **l_ca_folders;
+        char *l_cert_path = NULL;
+        l_ca_folders = dap_config_get_array_str(g_config, "resources", "ca_folders", &l_ca_folders_size);
+        for (uint16_t i = 0; i < l_ca_folders_size; ++i) {
+            l_cert_path = dap_strjoin("", l_ca_folders[i], "/", a_cert_name, ".dcert", (char*)NULL);
+            l_cert = dap_cert_file_load(l_cert_path);
+            if (l_cert) {
+                break;
             }
-    ret:
-            if (l_cert_path)
-                DAP_DELETE(l_cert_path);
-            return l_cert;
         }
+        if (l_cert_path)
+            DAP_DELETE(l_cert_path);
+        l_ret = l_cert;
+    }
+    if (!l_ret)
+        log_it(L_DEBUG, "Can't load cert '%s'", a_cert_name);
+    return l_ret;
 }
 
 dap_list_t *dap_cert_get_all_mem()
diff --git a/dap-sdk/crypto/src/dap_pkey.c b/dap-sdk/crypto/src/dap_pkey.c
index a8a40a9ecb..0b3c969fed 100755
--- a/dap-sdk/crypto/src/dap_pkey.c
+++ b/dap-sdk/crypto/src/dap_pkey.c
@@ -37,56 +37,38 @@
  */
 dap_pkey_t* dap_pkey_from_enc_key(dap_enc_key_t *a_key)
 {
-    if (a_key->pub_key_data_size > 0 ){
-        dap_pkey_t * l_ret = NULL;
-        l_ret = DAP_NEW_Z_SIZE(dap_pkey_t,dap_pkey_from_enc_key_output_calc(a_key));
-        if( dap_pkey_from_enc_key_output(a_key,l_ret) != 0 ) {
-            DAP_DELETE(l_ret);
-            return NULL;
-        }else
-            return l_ret;
-    }
-
-    return NULL;
-}
-
-/**
- * @brief dap_pkey_from_enc_key_output
- * convert encryption key to public key and placed it in output buffer
- * @param a_key dap_enc_key_t encryption key object
- * @param a_output output data
- * @return result
- */
-int dap_pkey_from_enc_key_output(dap_enc_key_t *a_key, void * a_output)
-{
-    dap_pkey_t * l_output = (dap_pkey_t *) a_output;
+    dap_pkey_type_t l_type;
     if (a_key->pub_key_data_size > 0 ){
         switch (a_key->type) {
             case DAP_ENC_KEY_TYPE_SIG_BLISS:
-                l_output->header.type.type = PKEY_TYPE_SIGN_BLISS ;
-            break;
+                l_type.type = PKEY_TYPE_SIGN_BLISS; break;
             case DAP_ENC_KEY_TYPE_SIG_TESLA:
-                l_output->header.type.type = PKEY_TYPE_SIGN_TESLA ;
-            break;
+                l_type.type = PKEY_TYPE_SIGN_TESLA; break;
             case DAP_ENC_KEY_TYPE_SIG_PICNIC:
-                l_output->header.type.type = PKEY_TYPE_SIGN_PICNIC ;
-            break;
+                l_type.type = PKEY_TYPE_SIGN_PICNIC; break;
             case DAP_ENC_KEY_TYPE_SIG_DILITHIUM:
-                l_output->header.type.type = PKEY_TYPE_SIGN_DILITHIUM;
-            break;
-
+                l_type.type = PKEY_TYPE_SIGN_DILITHIUM; break;
             default:
                 log_it(L_WARNING,"No serialization preset");
-                return -1;
+                return NULL;
         }
-        l_output->header.size = a_key->pub_key_data_size;
-        memcpy(l_output->pkey,a_key->pub_key_data,a_key->pub_key_data_size);
-        return 0;
+        size_t l_pub_key_size;
+        uint8_t *l_pkey = dap_enc_key_serealize_pub_key(a_key, &l_pub_key_size);
+        if (!l_pkey) {
+            log_it(L_WARNING,"Serialization failed");
+            return NULL;
+        }
+        dap_pkey_t *l_ret = DAP_NEW_SIZE(dap_pkey_t, sizeof(dap_pkey_t) + l_pub_key_size);
+        l_ret->header.type = l_type;
+        l_ret->header.size = (uint32_t)l_pub_key_size;
+        memcpy(&l_ret->pkey, l_pkey, l_pub_key_size);
+        DAP_DELETE(l_pkey);
+        return l_ret;
     }else{
         log_it(L_WARNING, "No public key in the input enc_key object");
-        return -2;
+        return NULL;
     }
-    return -3;
+    return NULL;
 }
 
 
diff --git a/dap-sdk/net/client/dap_client_pvt.c b/dap-sdk/net/client/dap_client_pvt.c
index ef20377f13..dc92421fe3 100644
--- a/dap-sdk/net/client/dap_client_pvt.c
+++ b/dap-sdk/net/client/dap_client_pvt.c
@@ -82,7 +82,7 @@
 static int s_max_attempts = 3;
 static int s_timeout = 20;
 static bool s_debug_more = false;
-static time_t s_client_timeout_read_after_connect_seconds = 5;
+static time_t s_client_timeout_active_after_connect_seconds = 15;
 
 
 static bool s_stage_status_after(dap_client_pvt_t * a_client_internal);
@@ -127,8 +127,8 @@ int dap_client_pvt_init()
     s_max_attempts = dap_config_get_item_int32_default(g_config, "dap_client", "max_tries", s_max_attempts);
     s_timeout = dap_config_get_item_int32_default(g_config, "dap_client", "timeout", s_timeout);
     s_debug_more = dap_config_get_item_bool_default(g_config, "dap_client", "debug_more", false);
-    s_client_timeout_read_after_connect_seconds = (time_t) dap_config_get_item_uint32_default(g_config,
-                                                  "dap_client","timeout_read_after_connect", s_client_timeout_read_after_connect_seconds);
+    s_client_timeout_active_after_connect_seconds = (time_t) dap_config_get_item_uint32_default(g_config,
+                                                  "dap_client","timeout_active_after_connect", s_client_timeout_active_after_connect_seconds);
 
     return 0;
 }
@@ -218,7 +218,7 @@ static void s_stream_connected(dap_client_pvt_t * a_client_pvt)
     dap_events_socket_uuid_t * l_es_uuid_ptr = DAP_NEW_Z(dap_events_socket_uuid_t);
     assert(a_client_pvt->stream_es);
     *l_es_uuid_ptr = a_client_pvt->stream_es->uuid;
-    if( dap_timerfd_start_on_worker(a_client_pvt->stream_es->worker, s_client_timeout_read_after_connect_seconds * 1000, s_stream_timer_timeout_after_connected_check ,l_es_uuid_ptr) == NULL ){
+    if( dap_timerfd_start_on_worker(a_client_pvt->stream_es->worker, s_client_timeout_active_after_connect_seconds * 1000, s_stream_timer_timeout_after_connected_check ,l_es_uuid_ptr) == NULL ){
         log_it(L_ERROR,"Can't run timer for stream after connect check for esocket uuid %"DAP_UINT64_FORMAT_U, *l_es_uuid_ptr);
         DAP_DEL_Z(l_es_uuid_ptr);
     }
@@ -239,7 +239,7 @@ static bool s_stream_timer_timeout_check(void * a_arg)
     dap_events_socket_t * l_es = dap_worker_esocket_find_uuid(l_worker, *l_es_uuid_ptr);
     if(l_es){
         if (l_es->flags & DAP_SOCK_CONNECTING ){
-            dap_client_pvt_t * l_client_pvt = (dap_client_pvt_t *)l_es->_inheritor;
+            dap_client_pvt_t * l_client_pvt = ESOCKET_CLIENT_PVT(l_es);
             if (dap_client_pvt_find(l_client_pvt->uuid)) {
                 log_it(L_WARNING,"Connecting timeout for stream uplink request http://%s:%u/, possible network problems or host is down",
                        l_client_pvt->uplink_addr, l_client_pvt->uplink_port);
@@ -280,9 +280,9 @@ static bool s_stream_timer_timeout_after_connected_check(void * a_arg)
 
     dap_events_socket_t * l_es = dap_worker_esocket_find_uuid(l_worker, *l_es_uuid_ptr);
     if( l_es ){
-        dap_client_pvt_t * l_client_pvt = (dap_client_pvt_t *)l_es->_inheritor;
+        dap_client_pvt_t * l_client_pvt = ESOCKET_CLIENT_PVT(l_es);
         if (dap_client_pvt_find(l_client_pvt->uuid)) {
-            if ( time(NULL)- l_client_pvt->ts_last_read >= s_client_timeout_read_after_connect_seconds){
+            if ( time(NULL)- l_client_pvt->ts_last_active >= s_client_timeout_active_after_connect_seconds){
 
                 log_it(L_WARNING,"Activity timeout for streaming uplink http://%s:%u/, possible network problems or host is down",
                        l_client_pvt->uplink_addr, l_client_pvt->uplink_port);
@@ -321,7 +321,7 @@ static bool s_enc_init_delay_before_request_timer_callback(void * a_arg)
     dap_worker_t * l_worker = dap_events_get_current_worker(dap_events_get_default());
     dap_events_socket_t * l_es = dap_worker_esocket_find_uuid(l_worker, *l_es_uuid_ptr);
     if(l_es){
-        dap_client_pvt_t * l_client_pvt =(dap_client_pvt_t*) l_es->_inheritor;
+        dap_client_pvt_t *l_client_pvt = ESOCKET_CLIENT_PVT(l_es);
         s_stage_status_after(l_client_pvt);
     }
     DAP_DEL_Z(l_es_uuid_ptr);
@@ -527,7 +527,7 @@ static bool s_stage_status_after(dap_client_pvt_t * a_client_pvt)
                             assert(a_client_pvt->stream_es);
                             dap_events_socket_uuid_t * l_stream_es_uuid_ptr = DAP_NEW_Z(dap_events_socket_uuid_t);
                             *l_stream_es_uuid_ptr  = a_client_pvt->stream_es->uuid;
-                            dap_timerfd_start_on_worker(a_client_pvt->worker, (unsigned long)s_client_timeout_read_after_connect_seconds * 1000,
+                            dap_timerfd_start_on_worker(a_client_pvt->worker, (unsigned long)s_client_timeout_active_after_connect_seconds * 1000,
                                                         s_stream_timer_timeout_check,l_stream_es_uuid_ptr);
                         }
                         else if (l_err != EINPROGRESS && l_err != -1){
@@ -556,7 +556,7 @@ static bool s_stage_status_after(dap_client_pvt_t * a_client_pvt)
                             dap_worker_add_events_socket( a_client_pvt->stream_es, l_worker);
                             dap_events_socket_uuid_t * l_stream_es_uuid_ptr = DAP_NEW_Z(dap_events_socket_uuid_t);
                             *l_stream_es_uuid_ptr = a_client_pvt->stream_es->uuid;
-                            dap_timerfd_start_on_worker(a_client_pvt->worker, (unsigned long)s_client_timeout_read_after_connect_seconds * 1000,
+                            dap_timerfd_start_on_worker(a_client_pvt->worker, (unsigned long)s_client_timeout_active_after_connect_seconds * 1000,
                                                         s_stream_timer_timeout_check,l_stream_es_uuid_ptr);
                         }
                     }
@@ -1220,7 +1220,7 @@ static void s_stage_stream_streaming(dap_client_t * a_client, void* arg)
  */
 static void s_stream_es_callback_connected(dap_events_socket_t * a_es)
 {
-    dap_client_pvt_t * l_client_pvt =(dap_client_pvt_t*) a_es->_inheritor;
+    dap_client_pvt_t *l_client_pvt = ESOCKET_CLIENT_PVT(a_es);
     s_stream_connected(l_client_pvt);
 }
 
@@ -1234,7 +1234,7 @@ static void s_stream_es_callback_delete(dap_events_socket_t *a_es, void *arg)
     (void) arg;
     log_it(L_INFO, "Stream delete callback");
 
-    dap_client_pvt_t *l_client_pvt = (dap_client_pvt_t *)a_es->_inheritor;
+    dap_client_pvt_t *l_client_pvt = ESOCKET_CLIENT_PVT(a_es);
     a_es->_inheritor = NULL; // To prevent delete in reactor
 
     if(l_client_pvt == NULL) {
@@ -1270,9 +1270,9 @@ static void s_stream_es_callback_delete(dap_events_socket_t *a_es, void *arg)
 static void s_stream_es_callback_read(dap_events_socket_t * a_es, void * arg)
 {
     (void) arg;
-    dap_client_pvt_t * l_client_pvt =(dap_client_pvt_t *) a_es->_inheritor;
+    dap_client_pvt_t *l_client_pvt = ESOCKET_CLIENT_PVT(a_es);
 
-    l_client_pvt->ts_last_read = time(NULL);
+    l_client_pvt->ts_last_active = time(NULL);
     switch (l_client_pvt->stage) {
         case STAGE_STREAM_SESSION:
             dap_client_go_stage(l_client_pvt->client, STAGE_STREAM_STREAMING, s_stage_stream_streaming);
@@ -1316,8 +1316,8 @@ static void s_stream_es_callback_read(dap_events_socket_t * a_es, void * arg)
 static void s_stream_es_callback_write(dap_events_socket_t * a_es, void * arg)
 {
     (void) arg;
-    dap_client_pvt_t * l_client_pvt = a_es->_inheritor;
-
+    dap_client_pvt_t *l_client_pvt = ESOCKET_CLIENT_PVT(a_es);
+    l_client_pvt->ts_last_active = time(NULL);
     if (l_client_pvt->stage_status == STAGE_STATUS_ERROR || !l_client_pvt->stream)
         return;
     switch (l_client_pvt->stage) {
@@ -1351,7 +1351,7 @@ static void s_stream_es_callback_write(dap_events_socket_t * a_es, void * arg)
  */
 static void s_stream_es_callback_error(dap_events_socket_t * a_es, int a_error)
 {
-    dap_client_pvt_t *l_client_pvt = (dap_client_pvt_t *) a_es->_inheritor;
+    dap_client_pvt_t *l_client_pvt = ESOCKET_CLIENT_PVT(a_es);
     if (!l_client_pvt)
         return;
     l_client_pvt = dap_client_pvt_find(l_client_pvt->uuid);
diff --git a/dap-sdk/net/client/include/dap_client_pvt.h b/dap-sdk/net/client/include/dap_client_pvt.h
index 81af1d0618..ce9e00607d 100644
--- a/dap-sdk/net/client/include/dap_client_pvt.h
+++ b/dap-sdk/net/client/include/dap_client_pvt.h
@@ -91,7 +91,7 @@ typedef struct dap_client_internal
     bool is_encrypted_headers;
     bool is_close_session;// the last request in session, in the header will be added "SessionCloseAfterRequest: true"
     bool is_closed_by_timeout;
-    time_t ts_last_read;
+    time_t ts_last_active;
 
     bool is_always_reconnect; // Always reconnect ever number of tries are over
     dap_client_callback_data_size_t request_response_callback;
@@ -100,6 +100,7 @@ typedef struct dap_client_internal
 } dap_client_pvt_t;
 
 #define DAP_CLIENT_PVT(a) (a ? (dap_client_pvt_t*) a->_internal : NULL)
+#define ESOCKET_CLIENT_PVT(a) (a ? (dap_client_pvt_t *) a->_inheritor : NULL)
 
 int dap_client_pvt_init();
 void dap_client_pvt_deinit();
diff --git a/dap-sdk/net/core/dap_events_socket.c b/dap-sdk/net/core/dap_events_socket.c
index ea25e2cf6f..39360da853 100644
--- a/dap-sdk/net/core/dap_events_socket.c
+++ b/dap-sdk/net/core/dap_events_socket.c
@@ -1427,7 +1427,7 @@ int dap_events_socket_event_signal( dap_events_socket_t * a_es, uint64_t a_value
     else
         l_n = -1;
 
-    if(l_n != 0){
+    if(l_n == -1){
         log_it(L_ERROR,"Haven't sent pointer in pipe out queue, code %d", l_n);
         DAP_DELETE(l_es_w_data);
     }
@@ -1567,7 +1567,7 @@ void dap_events_socket_worker_poll_update_unsafe(dap_events_socket_t * a_esocket
         int l_errno=0;
         if (a_esocket->type == DESCRIPTOR_TYPE_EVENT ){
             EV_SET(l_event, a_esocket->socket, EVFILT_USER,EV_ADD| EV_CLEAR ,0,0, &a_esocket->kqueue_event_catched_data );
-            if( kevent( l_kqueue_fd,l_event,1,NULL,0,NULL)!=0){
+            if( kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) == -1){
                 l_is_error = true;
                 l_errno = errno;
             }
@@ -1575,7 +1575,7 @@ void dap_events_socket_worker_poll_update_unsafe(dap_events_socket_t * a_esocket
             EV_SET(l_event, a_esocket->socket, l_filter,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket);
             if( a_esocket->flags & DAP_SOCK_READY_TO_READ ){
                 EV_SET(l_event, a_esocket->socket, EVFILT_READ,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket);
-                if( kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) != 1 ){
+                if( kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) == -1 ){
                     l_is_error = true;
                     l_errno = errno;
                 }
@@ -1583,7 +1583,7 @@ void dap_events_socket_worker_poll_update_unsafe(dap_events_socket_t * a_esocket
             if( !l_is_error){
                 if( a_esocket->flags & DAP_SOCK_READY_TO_WRITE || a_esocket->flags &DAP_SOCK_CONNECTING ){
                     EV_SET(l_event, a_esocket->socket, EVFILT_WRITE,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket);
-                    if(kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) != 1){
+                    if(kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) == -1){
                         l_is_error = true;
                         l_errno = errno;
                     }
@@ -1638,7 +1638,7 @@ void dap_events_socket_set_readable_unsafe( dap_events_socket_t *a_esocket, bool
         if( l_kqueue_fd>0 ){
             int l_kevent_ret = kevent(l_kqueue_fd,&l_event,1,NULL,0,NULL);
             int l_errno = errno;
-            if ( l_kevent_ret !=1 && l_errno != EINPROGRESS ){
+            if ( l_kevent_ret == -1 && l_errno != EINPROGRESS ){
                 char l_errbuf[128];
                 l_errbuf[0]=0;
                 strerror_r(l_errno, l_errbuf, sizeof (l_errbuf));
@@ -1706,7 +1706,7 @@ void dap_events_socket_set_writable_unsafe( dap_events_socket_t *a_esocket, bool
         if( l_kqueue_fd>0 ){
             int l_kevent_ret=kevent(l_kqueue_fd,&l_event,1,NULL,0,NULL);
             int l_errno = errno;
-            if ( l_kevent_ret!=l_expected_reply && l_errno != EINPROGRESS && l_errno != ENOENT ){
+            if ( l_kevent_ret == -1 && l_errno != EINPROGRESS && l_errno != ENOENT ){
                 char l_errbuf[128];
                 l_errbuf[0]=0;
                 strerror_r(l_errno, l_errbuf, sizeof (l_errbuf));
@@ -1870,7 +1870,7 @@ void dap_events_socket_remove_from_worker_unsafe( dap_events_socket_t *a_es, dap
         struct kevent * l_event = &a_es->kqueue_event;
         if (a_es->kqueue_base_filter){
             EV_SET(l_event, a_es->socket, a_es->kqueue_base_filter ,EV_DELETE, 0,0,a_es);
-            if ( kevent( a_worker->kqueue_fd,l_event,1,NULL,0,NULL) != 1 ) {
+            if ( kevent( a_worker->kqueue_fd,l_event,1,NULL,0,NULL) == -1 ) {
                 int l_errno = errno;
                 char l_errbuf[128];
                 strerror_r(l_errno, l_errbuf, sizeof (l_errbuf));
@@ -1884,7 +1884,7 @@ void dap_events_socket_remove_from_worker_unsafe( dap_events_socket_t *a_es, dap
 
             if(a_es->flags & DAP_SOCK_READY_TO_WRITE){
                 EV_SET(l_event, a_es->socket, EVFILT_WRITE ,EV_DELETE, 0,0,a_es);
-                if ( kevent( a_worker->kqueue_fd,l_event,1,NULL,0,NULL) != 0 ) {
+                if ( kevent( a_worker->kqueue_fd,l_event,1,NULL,0,NULL) == -1 ) {
                     int l_errno = errno;
                     char l_errbuf[128];
                     strerror_r(l_errno, l_errbuf, sizeof (l_errbuf));
@@ -1894,7 +1894,7 @@ void dap_events_socket_remove_from_worker_unsafe( dap_events_socket_t *a_es, dap
             }
             if(a_es->flags & DAP_SOCK_READY_TO_READ){
                 EV_SET(l_event, a_es->socket, EVFILT_READ ,EV_DELETE, 0,0,a_es);
-                if ( kevent( a_worker->kqueue_fd,l_event,1,NULL,0,NULL) != 0 ) {
+                if ( kevent( a_worker->kqueue_fd,l_event,1,NULL,0,NULL) == -1 ) {
                     int l_errno = errno;
                     char l_errbuf[128];
                     strerror_r(l_errno, l_errbuf, sizeof (l_errbuf));
diff --git a/dap-sdk/net/core/dap_worker.c b/dap-sdk/net/core/dap_worker.c
index 83d7c90e29..4726a1548d 100644
--- a/dap-sdk/net/core/dap_worker.c
+++ b/dap-sdk/net/core/dap_worker.c
@@ -565,7 +565,7 @@ void *dap_worker_thread(void *arg)
                     default:{}
                 }
                 //if(s_debug_reactor)
-                    log_it(L_INFO,"RDHUP event on esocket %p (%"DAP_FORMAT_SOCKET") type %d", l_cur, l_cur->socket, l_cur->type );
+                    log_it(L_WARNING, "RDHUP event on esocket %p (%"DAP_FORMAT_SOCKET") type %d", l_cur, l_cur->socket, l_cur->type );
             }
 
             // If its outgoing connection
diff --git a/dap-sdk/net/server/http_server/http_client/dap_http_header.c b/dap-sdk/net/server/http_server/http_client/dap_http_header.c
index 4e5bb1c44e..5164c7d544 100644
--- a/dap-sdk/net/server/http_server/http_client/dap_http_header.c
+++ b/dap-sdk/net/server/http_server/http_client/dap_http_header.c
@@ -138,17 +138,14 @@ int dap_http_header_parse(struct dap_http_client * cl_ht, const char * str)
  * @param value Header's value
  * @return Pointer to the new HTTP header's structure
  */
-dap_http_header_t* dap_http_header_add(dap_http_header_t ** top, const char*name, const char * value)
+dap_http_header_t *dap_http_header_add(dap_http_header_t **a_top, const char *a_name, const char *a_value)
 {
-    dap_http_header_t * nh = (dap_http_header_t*) calloc(1,sizeof(dap_http_header_t));
+    dap_http_header_t *l_new_header = DAP_NEW_Z(dap_http_header_t);
   //  log_it(L_DEBUG,"Added header %s",name);
-    nh->name=strdup(name);
-    nh->value=strdup(value);
-    nh->next=*top;
-    if(*top)
-        (*top)->prev=nh;
-    *top=nh;
-    return nh;
+    l_new_header->name=dap_strdup(a_name);
+    l_new_header->value=dap_strdup(a_value);
+    DL_APPEND(*a_top, l_new_header);
+    return l_new_header;
 }
 
 
@@ -182,17 +179,12 @@ dap_http_header_t * dap_http_out_header_add_f(dap_http_client_t * ht, const char
  * @brief dap_http_header_remove Removes header from the list
  * @param dap_hdr HTTP header
  */
-void dap_http_header_remove(dap_http_header_t ** top, dap_http_header_t * hdr )
+void dap_http_header_remove(dap_http_header_t **a_top, dap_http_header_t *a_hdr)
 {
-    if(hdr->prev)
-        hdr->prev=hdr->next;
-    else
-        *top=hdr->next;
-
-    if(hdr->next)
-        hdr->next->prev=hdr->prev;
-    free(hdr->name);
-    free(hdr->value);
+    DL_DELETE(*a_top, a_hdr);
+    DAP_DELETE(a_hdr->name);
+    DAP_DELETE(a_hdr->value);
+    DAP_DELETE(a_hdr);
 }
 
 void print_dap_http_headers(dap_http_header_t * top)
diff --git a/dap-sdk/net/server/http_server/http_client/include/dap_http_header.h b/dap-sdk/net/server/http_server/http_client/include/dap_http_header.h
index f3b1e8e284..f84a55faf8 100644
--- a/dap-sdk/net/server/http_server/http_client/include/dap_http_header.h
+++ b/dap-sdk/net/server/http_server/http_client/include/dap_http_header.h
@@ -37,7 +37,7 @@ void dap_http_header_deinit(); // Deinit module
 
 int dap_http_header_parse(struct dap_http_client * cl_ht, const char * str);
 
-dap_http_header_t * dap_http_header_add(dap_http_header_t ** top, const char*name, const char * value);
+dap_http_header_t *dap_http_header_add(dap_http_header_t **a_top, const char *a_name, const char *a_value);
 
 dap_http_header_t * dap_http_out_header_add(struct dap_http_client * ht, const char*name, const char * value);
 dap_http_header_t * dap_http_out_header_add_f(struct dap_http_client * ht, const char*name, const char * value,...);
@@ -46,7 +46,7 @@ dap_http_header_t * dap_http_header_find(dap_http_header_t * top, const char*nam
 
 dap_http_header_t * dap_http_headers_dup(dap_http_header_t * a_top);
 
-void dap_http_header_remove(dap_http_header_t ** top,dap_http_header_t * hdr );
+void dap_http_header_remove(dap_http_header_t **a_top, dap_http_header_t *a_hdr);
 
 // For debug output
 void print_dap_http_headers(dap_http_header_t * top);
diff --git a/dap-sdk/net/stream/stream/CMakeLists.txt b/dap-sdk/net/stream/stream/CMakeLists.txt
index 16fb98fc4e..11d4b6896a 100755
--- a/dap-sdk/net/stream/stream/CMakeLists.txt
+++ b/dap-sdk/net/stream/stream/CMakeLists.txt
@@ -7,7 +7,7 @@ file(GLOB STREAM_HDRS include/*.h)
 add_library(${PROJECT_NAME} STATIC ${STREAM_SRCS} ${STREAM_HDRS})
 
 target_link_libraries(dap_stream dap_core dap_server_core dap_crypto
-    dap_http_server dap_enc_server dap_session dap_stream_ch)
+    dap_http_server dap_enc_server dap_session dap_stream_ch dap_client)
 
 target_include_directories(dap_stream INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
diff --git a/dap-sdk/net/stream/stream/dap_stream.c b/dap-sdk/net/stream/stream/dap_stream.c
index a36776d860..05299ac450 100644
--- a/dap-sdk/net/stream/stream/dap_stream.c
+++ b/dap-sdk/net/stream/stream/dap_stream.c
@@ -52,6 +52,7 @@
 #include "dap_http_client.h"
 #include "dap_http_header.h"
 #include "dap_stream_worker.h"
+#include "dap_client_pvt.h"
 
 #define LOG_TAG "dap_stream"
 #define HEADER_WITH_SIZE_FIELD 12  //This count of bytes enough for allocate memory for stream packet
@@ -67,6 +68,8 @@ static void s_http_client_data_read(dap_http_client_t * a_http_client, void * a_
 
 static void s_esocket_callback_worker_assign(dap_events_socket_t * a_esocket, dap_worker_t * a_worker);
 static void s_esocket_callback_worker_unassign(dap_events_socket_t * a_esocket, dap_worker_t * a_worker);
+static void s_client_callback_worker_assign(dap_events_socket_t * a_esocket, dap_worker_t * a_worker);
+static void s_client_callback_worker_unassign(dap_events_socket_t * a_esocket, dap_worker_t * a_worker);
 
 static void s_esocket_data_read(dap_events_socket_t* a_esocket, void * a_arg);
 static void s_esocket_write(dap_events_socket_t* a_esocket, void * a_arg);
@@ -78,7 +81,8 @@ static dap_stream_t * s_stream_new(dap_http_client_t * a_http_client); // Create
 static void s_http_client_new(dap_http_client_t * a_esocket, void * a_arg);
 static void s_http_client_delete(dap_http_client_t * a_esocket, void * a_arg);
 
-static bool s_callback_keepalive( void * a_arg);
+static bool s_callback_server_keepalive(void *a_arg);
+static bool s_callback_client_keepalive(void *a_arg);
 
 static bool s_dump_packet_headers = false;
 static bool s_debug = false;
@@ -259,19 +263,44 @@ void check_session( unsigned int a_id, dap_events_socket_t *a_esocket )
  */
 dap_stream_t * s_stream_new(dap_http_client_t * a_http_client)
 {
-    dap_stream_t * ret= DAP_NEW_Z(dap_stream_t);
-
-    ret->esocket = a_http_client->esocket;
-    ret->stream_worker = (dap_stream_worker_t*) a_http_client->esocket->worker->_inheritor;
-    ret->conn_http=a_http_client;
-    ret->buf_defrag_size = 0;
-    ret->seq_id = 0;
-    ret->client_last_seq_id_packet = (size_t)-1;
+    dap_stream_t *l_ret= DAP_NEW_Z(dap_stream_t);
+
+    l_ret->esocket = a_http_client->esocket;
+    l_ret->stream_worker = (dap_stream_worker_t *)a_http_client->esocket->worker->_inheritor;
+    l_ret->conn_http=a_http_client;
+    l_ret->buf_defrag_size = 0;
+    l_ret->seq_id = 0;
+    l_ret->client_last_seq_id_packet = (size_t)-1;
+    // Start server keep-alive timer
+    dap_events_socket_uuid_t *l_es_uuid = DAP_NEW_Z(dap_events_socket_uuid_t);
+    *l_es_uuid = l_ret->esocket->uuid;
+    l_ret->keepalive_timer = dap_timerfd_start_on_worker(l_ret->esocket->worker,
+                                                         STREAM_KEEPALIVE_TIMEOUT * 1000,
+                                                         (dap_timerfd_callback_t)s_callback_server_keepalive,
+                                                         l_es_uuid);
+    l_ret->esocket->callbacks.worker_assign_callback = s_esocket_callback_worker_assign;
+    l_ret->esocket->callbacks.worker_unassign_callback = s_esocket_callback_worker_unassign;
+    a_http_client->_inheritor = l_ret;
+    log_it(L_NOTICE,"New stream instance");
+    return l_ret;
+}
 
-    a_http_client->_inheritor=ret;
 
-    log_it(L_NOTICE,"New stream instance");
-    return ret;
+/**
+ * @brief dap_stream_new_es
+ * @param a_es
+ * @return
+ */
+dap_stream_t* dap_stream_new_es_client(dap_events_socket_t * a_esocket)
+{
+    dap_stream_t *l_ret = DAP_NEW_Z(dap_stream_t);
+    l_ret->esocket = a_esocket;
+    l_ret->esocket_uuid = a_esocket->uuid;
+    l_ret->buf_defrag_size=0;
+    l_ret->is_client_to_uplink = true;
+    l_ret->esocket->callbacks.worker_assign_callback = s_client_callback_worker_assign;
+    l_ret->esocket->callbacks.worker_unassign_callback = s_client_callback_worker_unassign;
+    return l_ret;
 }
 
 
@@ -314,23 +343,6 @@ static void s_esocket_callback_delete(dap_events_socket_t* a_esocket, void * a_a
     dap_stream_delete(l_stream);
 }
 
-
-/**
- * @brief dap_stream_new_es
- * @param a_es
- * @return
- */
-dap_stream_t* dap_stream_new_es_client(dap_events_socket_t * a_esocket)
-{
-    dap_stream_t * ret= DAP_NEW_Z(dap_stream_t);
-    ret->esocket = a_esocket;
-    ret->esocket_uuid = a_esocket->uuid;
-    ret->buf_defrag_size=0;
-    ret->is_client_to_uplink = true;
-    return ret;
-}
-
-
 /**
  * @brief stream_header_read Read headers callback for HTTP
  * @param a_http_client HTTP client structure
@@ -412,16 +424,6 @@ static void s_http_client_headers_write(dap_http_client_t * a_http_client, void
 
         a_http_client->state_read=DAP_HTTP_CLIENT_STATE_DATA;
         dap_events_socket_set_readable_unsafe(a_http_client->esocket,true);
-        // Connection is established, setting up keepalive timer
-        if (!l_stream->keepalive_timer) {
-            dap_events_socket_uuid_t * l_es_uuid= DAP_NEW_Z(dap_events_socket_uuid_t);
-            *l_es_uuid = a_http_client->esocket->uuid;
-            l_stream->keepalive_timer = dap_timerfd_start_on_worker(a_http_client->esocket->worker,
-                                                                    STREAM_KEEPALIVE_TIMEOUT * 1000,
-                                                                    s_callback_keepalive,
-                                                                    l_es_uuid);
-        }
-
     }
 }
 
@@ -452,16 +454,14 @@ static void s_esocket_callback_worker_assign(dap_events_socket_t * a_esocket, da
     assert(l_http_client);
     dap_stream_t * l_stream = DAP_STREAM(l_http_client);
     assert(l_stream);
-    if (a_esocket->type == DESCRIPTOR_TYPE_SOCKET_UDP ||
-            (l_http_client->state_read == DAP_HTTP_CLIENT_STATE_DATA && l_http_client->state_write == DAP_HTTP_CLIENT_STATE_DATA )) {
-        if (!l_stream->keepalive_timer) {
-            dap_events_socket_uuid_t * l_es_uuid= DAP_NEW_Z(dap_events_socket_uuid_t);
-            *l_es_uuid = a_esocket->uuid;
-            l_stream->keepalive_timer = dap_timerfd_start_on_worker(a_worker,
-                                                                    STREAM_KEEPALIVE_TIMEOUT * 1000,
-                                                                    (dap_timerfd_callback_t)s_callback_keepalive,
-                                                                    l_es_uuid);
-        }
+    // Restart server keepalive timer if it was unassigned before
+    if (!l_stream->keepalive_timer) {
+        dap_events_socket_uuid_t * l_es_uuid= DAP_NEW_Z(dap_events_socket_uuid_t);
+        *l_es_uuid = a_esocket->uuid;
+        l_stream->keepalive_timer = dap_timerfd_start_on_worker(a_worker,
+                                                                STREAM_KEEPALIVE_TIMEOUT * 1000,
+                                                                (dap_timerfd_callback_t)s_callback_server_keepalive,
+                                                                l_es_uuid);
     }
 }
 
@@ -482,6 +482,35 @@ static void s_esocket_callback_worker_unassign(dap_events_socket_t * a_esocket,
     l_stream->keepalive_timer = NULL;
 }
 
+static void s_client_callback_worker_assign(dap_events_socket_t * a_esocket, dap_worker_t * a_worker)
+{
+    dap_client_pvt_t *l_client_pvt = ESOCKET_CLIENT_PVT(a_esocket);
+    assert(l_client_pvt);
+    dap_stream_t *l_stream = l_client_pvt->stream;
+    assert(l_stream);
+    // Start client keepalive timer or restart it, if it was unassigned before
+    if (!l_stream->keepalive_timer) {
+        dap_events_socket_uuid_t * l_es_uuid= DAP_NEW_Z(dap_events_socket_uuid_t);
+        *l_es_uuid = a_esocket->uuid;
+        l_stream->keepalive_timer = dap_timerfd_start_on_worker(a_worker,
+                                                                STREAM_KEEPALIVE_TIMEOUT * 1000,
+                                                                (dap_timerfd_callback_t)s_callback_client_keepalive,
+                                                                l_es_uuid);
+    }
+}
+
+static void s_client_callback_worker_unassign(dap_events_socket_t * a_esocket, dap_worker_t * a_worker)
+{
+    UNUSED(a_worker);
+    dap_client_pvt_t *l_client_pvt = ESOCKET_CLIENT_PVT(a_esocket);
+    assert(l_client_pvt);
+    dap_stream_t *l_stream = l_client_pvt->stream;
+    assert(l_stream);
+    DAP_DEL_Z(l_stream->keepalive_timer->callback_arg);
+    dap_timerfd_delete(l_stream->keepalive_timer);
+    l_stream->keepalive_timer = NULL;
+}
+
 
 /**
  * @brief s_data_read
@@ -558,8 +587,7 @@ static void s_http_client_data_read(dap_http_client_t * a_http_client, void * ar
  */
 static void s_http_client_new(dap_http_client_t * a_http_client, void * arg)
 {
-    a_http_client->esocket->callbacks.worker_assign_callback = s_esocket_callback_worker_assign;
-    a_http_client->esocket->callbacks.worker_unassign_callback = s_esocket_callback_worker_unassign;
+
 }
 
 
@@ -760,6 +788,7 @@ size_t dap_stream_data_proc_read (dap_stream_t *a_stream)
  */
 static void s_stream_proc_pkt_in(dap_stream_t * a_stream)
 {
+    a_stream->is_active = true;
     dap_stream_pkt_t * l_pkt = a_stream->pkt_buf_in;
     size_t l_pkt_size = a_stream->pkt_buf_in_data_size;
     a_stream->pkt_buf_in=NULL;
@@ -819,12 +848,9 @@ static void s_stream_proc_pkt_in(dap_stream_t * a_stream)
         l_ret_pkt.type = STREAM_PKT_TYPE_ALIVE;
         memcpy(l_ret_pkt.sig, c_dap_stream_sig, sizeof(l_ret_pkt.sig));
         dap_events_socket_write_unsafe(a_stream->esocket, &l_ret_pkt, sizeof(l_ret_pkt));
-        // Reset client keepalive timer
-        if (a_stream->keepalive_timer) {
-            dap_timerfd_reset(a_stream->keepalive_timer);
-        }
     } break;
     case STREAM_PKT_TYPE_ALIVE:
+        a_stream->is_active = false; // To prevent keep-alive concurrency
         //log_it(L_DEBUG, "Keep alive response recieved");
         break;
     default:
@@ -868,14 +894,29 @@ static bool s_detect_loose_packet(dap_stream_t * a_stream)
  * @param a_arg
  * @return
  */
-static bool s_callback_keepalive( void * a_arg)
+static bool s_callback_keepalive(void *a_arg, bool a_server_side)
 {
     if (!a_arg)
         return false;
     dap_events_socket_uuid_t * l_es_uuid = (dap_events_socket_uuid_t*) a_arg;
     dap_worker_t * l_worker = dap_events_get_current_worker(dap_events_get_default());
     dap_events_socket_t * l_es = dap_worker_esocket_find_uuid(l_worker, *l_es_uuid);
-    if( l_es){
+    if (l_es) {
+        dap_stream_t *l_stream = NULL;
+        if (a_server_side) {
+            dap_http_client_t *l_http_client = DAP_HTTP_CLIENT(l_es);
+            assert(l_http_client);
+            l_stream = DAP_STREAM(l_http_client);
+        } else {
+            dap_client_pvt_t *l_client_pvt = ESOCKET_CLIENT_PVT(l_es);
+            assert(l_client_pvt);
+            l_stream = l_client_pvt->stream;
+        }
+        assert(l_stream);
+        if (l_stream->is_active) {
+            l_stream->is_active = false;
+            return true;
+        }
         if(s_debug)
             log_it(L_DEBUG,"Keepalive for sock fd %"DAP_FORMAT_SOCKET" uuid 0x%016"DAP_UINT64_FORMAT_x, l_es->socket, *l_es_uuid);
         dap_stream_pkt_hdr_t l_pkt = {};
@@ -890,3 +931,13 @@ static bool s_callback_keepalive( void * a_arg)
         return false; // Socket is removed from worker
     }
 }
+
+static bool s_callback_client_keepalive(void *a_arg)
+{
+    return s_callback_keepalive(a_arg, false);
+}
+
+static bool s_callback_server_keepalive(void *a_arg)
+{
+    return s_callback_keepalive(a_arg, true);
+}
diff --git a/dap-sdk/net/stream/stream/dap_stream_pkt.c b/dap-sdk/net/stream/stream/dap_stream_pkt.c
index 38d14061d3..5031551bd0 100644
--- a/dap-sdk/net/stream/stream/dap_stream_pkt.c
+++ b/dap-sdk/net/stream/stream/dap_stream_pkt.c
@@ -138,6 +138,7 @@ size_t dap_stream_pkt_read_unsafe( dap_stream_t * a_stream, dap_stream_pkt_t * a
 
 size_t dap_stream_pkt_write_unsafe(dap_stream_t * a_stream, const void * a_data, size_t a_data_size)
 {
+    a_stream->is_active = true;
     size_t ret=0;
     dap_stream_pkt_hdr_t pkt_hdr;
 
diff --git a/dap-sdk/net/stream/stream/include/dap_stream.h b/dap-sdk/net/stream/stream/include/dap_stream.h
index b6685a93c4..519a4c2066 100644
--- a/dap-sdk/net/stream/stream/include/dap_stream.h
+++ b/dap-sdk/net/stream/stream/include/dap_stream.h
@@ -53,16 +53,15 @@ typedef struct dap_stream {
     int id;
     dap_stream_session_t * session;
     dap_events_socket_t * esocket; // Connection
-    // uint128_t esocket_uuid;
-    uint64_t esocket_uuid;
+    dap_events_socket_uuid_t esocket_uuid;
     dap_stream_worker_t * stream_worker;
     struct dap_http_client * conn_http; // HTTP-specific
 
     dap_timerfd_t *keepalive_timer;
+    bool is_active;
 
     char * service_key;
 
-    bool is_live;
     bool is_client_to_uplink ;
 
     struct dap_stream_pkt * in_pkt;
diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index dd4510905f..b061929b00 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -1020,7 +1020,7 @@ bool s_update_token_cache(dap_ledger_t *a_ledger, dap_chain_ledger_token_item_t
     if (l_token_cache->header_private.current_supply >= l_emission_value)
     {
        l_token_cache->header_private.current_supply -= l_emission_value;
-       log_it(L_DEBUG,"New current supply %lld for token %s", l_token_cache->header_private.current_supply, l_token_item->ticker);
+       log_it(L_DEBUG,"New current supply %"DAP_UINT64_FORMAT_U" for token %s", l_token_cache->header_private.current_supply, l_token_item->ticker);
 
        // Update value in ledger memory object
 
@@ -1028,7 +1028,7 @@ bool s_update_token_cache(dap_ledger_t *a_ledger, dap_chain_ledger_token_item_t
     }                
     else
     {
-       log_it(L_WARNING,"Token current supply %lld lower, than emission value = %lld", l_token_cache->header_private.current_supply, 
+       log_it(L_WARNING,"Token current supply %"DAP_UINT64_FORMAT_U" lower, than emission value = %"DAP_UINT64_FORMAT_U, l_token_cache->header_private.current_supply,
                                         l_emission_value);
 
             DAP_DELETE(l_gdb_group);
@@ -1067,7 +1067,7 @@ void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger)
             l_token_item->total_supply = l_token_item->datum_token->header_private.total_supply;
             l_token_item->type = l_token_item->datum_token->type;
             l_token_item->current_supply = l_token_item->datum_token->header_private.current_supply;
-            log_it(L_DEBUG,"Ledger cache datum_token current_supply %lld, ticker: %s", l_token_item->current_supply, l_token_item->ticker);
+            log_it(L_DEBUG,"Ledger cache datum_token current_supply %"DAP_UINT64_FORMAT_U", ticker: %s", l_token_item->current_supply, l_token_item->ticker);
             l_token_item->auth_signs= dap_chain_datum_token_simple_signs_parse(l_token_item->datum_token, l_objs[i].value_len,
                                                                                        &l_token_item->auth_signs_total,
                                                                                        &l_token_item->auth_signs_valid );
@@ -1864,11 +1864,6 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 l_err_num = -8;
                 break;
             }
-            if (! l_token_item){
-                l_err_num = -16;
-                log_it(L_ERROR,"Can't find token item for conditioned tx out");
-                break;
-            }
             // 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_sign_t *l_prev_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_prev_sig);
@@ -2477,9 +2472,11 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,
         // If debug mode dump the UTXO
         if (dap_log_level_get() == L_DEBUG && s_debug_more) {
             for (size_t i =0; i < (size_t) l_item_tmp->cache_data.n_outs; i++){
-                dap_chain_tx_out_t * l_tx_out = l_tist_tmp->data;
+                dap_chain_tx_out_t *l_tx_out = l_tist_tmp->data;
+                if (l_tx_out->header.type != TX_ITEM_TYPE_OUT)
+                    continue;
                 char * l_tx_out_addr_str = dap_chain_addr_to_str( &l_tx_out->addr );
-                log_it(L_DEBUG,"Added tx out to %s",l_tx_out_addr_str );
+                log_it(L_DEBUG, "Added tx out to %s", l_tx_out_addr_str);
                 DAP_DELETE (l_tx_out_addr_str);
             }
         }
@@ -2504,7 +2501,7 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,
 
         size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx);
         memcpy(l_item_tmp->tx, a_tx, l_tx_size);
-        pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
+        pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
         HASH_ADD(hh, l_ledger_priv->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_item_tmp); // tx_hash_fast: name of key field
         pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
         // Count TPS
@@ -3021,10 +3018,7 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_pkey(dap_ledger_t *a_led
     bool is_search_enable = is_null_hash;
     dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp;
     pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
-    HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp)
-    {
-        pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
-
+    HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) {
         dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx;
         dap_chain_hash_fast_t *l_tx_hash_tmp = &l_iter_current->tx_hash_fast;
         // start searching from the next hash after a_tx_first_hash
@@ -3047,7 +3041,6 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_pkey(dap_ledger_t *a_led
                 break;
             }
         }
-        pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
     }
     pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
     return l_cur_tx;
@@ -3071,9 +3064,7 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_le
     dap_chain_tx_out_cond_t *l_tx_out_cond = NULL;
     int l_tx_out_cond_idx;
     pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
-    HASH_ITER(hh, l_ledger_priv->ledger_items, l_iter_current, l_item_tmp)
-    {
-        pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
+    HASH_ITER(hh, l_ledger_priv->ledger_items, l_iter_current, l_item_tmp) {
         dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx;
         dap_chain_hash_fast_t *l_tx_hash_tmp = &l_iter_current->tx_hash_fast;
         // start searching from the next hash after a_tx_first_hash
@@ -3093,7 +3084,6 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_le
             }
             break;
         }
-        pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock);
     }
     pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
     if (a_out_cond) {
diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
index 37704e62ab..afe3d152c6 100644
--- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
+++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
@@ -38,7 +38,6 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include "dap_chain_mempool.h"
 
 #include "dap_chain_net_srv.h"
-#include "dap_chain_net_srv_common.h"
 #include "dap_chain_net_srv_stream_session.h"
 
 
@@ -83,16 +82,6 @@ void dap_stream_ch_chain_net_srv_deinit(void)
 
 }
 
-/**
- * @brief Set srv uid - for client
- */
-void dap_stream_ch_chain_net_srv_set_srv_uid(dap_stream_ch_t* a_ch, dap_chain_net_srv_uid_t a_srv_uid)
-{
-    // save srv id
-    dap_stream_ch_chain_net_srv_t * l_ch_chain_net_srv = DAP_STREAM_CH_CHAIN_NET_SRV(a_ch);
-    l_ch_chain_net_srv->srv_uid.uint64 = a_srv_uid.uint64;
-}
-
 /**
  * @brief s_stream_ch_new
  * @param a_ch
@@ -103,8 +92,9 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch , void* arg)
     (void ) arg;
     a_ch->internal=DAP_NEW_Z(dap_stream_ch_chain_net_srv_t);
     dap_stream_ch_chain_net_srv_t * l_ch_chain_net_srv = DAP_STREAM_CH_CHAIN_NET_SRV(a_ch);
-    pthread_mutex_init( &l_ch_chain_net_srv->mutex,NULL);
-    if (a_ch->stream->session->_inheritor == NULL && a_ch->stream->session != NULL)
+    l_ch_chain_net_srv->ch_uuid = a_ch->uuid;
+    l_ch_chain_net_srv->ch = a_ch;
+    if (a_ch->stream->session && !a_ch->stream->session->_inheritor)
         dap_chain_net_srv_stream_session_create( a_ch->stream->session );
     else if ( a_ch->stream->session == NULL)
         log_it( L_ERROR, "No session at all!");
@@ -144,6 +134,7 @@ static bool s_grace_period_control(dap_chain_net_srv_grace_t *a_grace)
     dap_stream_ch_chain_net_srv_pkt_error_t l_err;
     memset(&l_err, 0, sizeof(l_err));
     dap_chain_net_srv_t * l_srv = NULL;
+    dap_chain_net_srv_usage_t *l_usage = NULL;
     dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(a_grace->stream_worker, a_grace->ch_uuid);
 
     if (l_ch== NULL )
@@ -212,12 +203,11 @@ static bool s_grace_period_control(dap_chain_net_srv_grace_t *a_grace)
             }
         }
     }
-    dap_chain_net_srv_usage_t *l_usage = NULL;
     if (!a_grace->usage) {
         l_usage = dap_chain_net_srv_usage_add(l_srv_session, l_net, l_srv);
         if ( !l_usage ){ // Usage can't add
-            log_it( L_WARNING, "Usage can't add");
-            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_USAGE_CANT_ADD;
+            log_it( L_WARNING, "Can't add usage");
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE;
             goto free_exit;
         }
 
@@ -237,7 +227,6 @@ static bool s_grace_period_control(dap_chain_net_srv_grace_t *a_grace)
         l_usage->tx_cond = l_tx;
     }
     dap_chain_net_srv_price_t * l_price = NULL;
-    dap_chain_datum_tx_receipt_t * l_receipt = NULL;
     const char * l_ticker = NULL;
     if (l_srv->pricelist && !l_grace_start) {
         l_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_request->hdr.tx_cond );
@@ -280,10 +269,9 @@ static bool s_grace_period_control(dap_chain_net_srv_grace_t *a_grace)
                 l_price->value_datoshi = 0;
             }
             l_usage->price = l_price;
-            // TODO extend callback to pass ext and ext size from service callbacks
-            l_receipt = dap_chain_net_srv_issue_receipt( l_usage->service, l_usage, l_usage->price,NULL,0 );
-            dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST, l_receipt, l_receipt->size);
-            DAP_DELETE(l_receipt);
+            l_usage->receipt = dap_chain_net_srv_issue_receipt(l_usage->service, l_usage->price, NULL, 0);
+            dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST,
+                                           l_usage->receipt, l_usage->receipt->size);
         }else{
             l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_PRICE_NOT_FOUND ;
             goto free_exit;
@@ -367,14 +355,19 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
     memset(&l_err,0,sizeof (l_err));
 
     if(l_ch_pkt ) {
+        if(l_ch_chain_net_srv->notify_callback) {
+            l_ch_chain_net_srv->notify_callback(l_ch_chain_net_srv, l_ch_pkt->hdr.type, l_ch_pkt, l_ch_chain_net_srv->notify_callback_arg);
+            return; // It's a client behind this
+        }
         switch (l_ch_pkt->hdr.type) {
             // for send test data
             case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST:{
-                int l_err_code = 0;
                 dap_stream_ch_chain_net_srv_pkt_test_t *l_request = (dap_stream_ch_chain_net_srv_pkt_test_t*) l_ch_pkt->data;
                 size_t l_request_size = l_request->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t);
-                if(l_ch_pkt->hdr.size != l_request_size) {
-                    log_it(L_WARNING, "Wrong request size, less or more than required");
+                if (l_ch_pkt->hdr.size != l_request_size) {
+                    log_it(L_WARNING, "Wrong response size %u, required %zu", l_ch_pkt->hdr.size, l_request_size);
+                    l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_SIZE;
+                    dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof(l_err));
                     break;
                 }
                 struct timeval l_recvtime2;
@@ -383,52 +376,33 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                 //printf("\n%lu.%06lu \n", (unsigned long) l_request->recv_time2.tv_sec, (unsigned long) l_request->recv_time2.tv_usec);
                 dap_chain_hash_fast_t l_data_hash;
                 dap_hash_fast(l_request->data, l_request->data_size, &l_data_hash);
-                if(l_request->data_size>0 && !dap_hash_fast_compare(&l_data_hash, &(l_request->data_hash))){
-                    l_err_code+=2;
+                if (l_request->data_size > 0 && !dap_hash_fast_compare(&l_data_hash, &l_request->data_hash)) {
+                    l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_HASH;
+                    dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof(l_err));
+                    break;
                 }
-
                 // create data to send back
                 dap_stream_ch_chain_net_srv_pkt_test_t *l_request_out = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_test_t, sizeof(dap_stream_ch_chain_net_srv_pkt_test_t) + l_request->data_size_recv);
                 // copy info from recv message
                 memcpy(l_request_out,l_request, sizeof(dap_stream_ch_chain_net_srv_pkt_test_t));
-                l_request_out->data_size = l_request->data_size_recv;
-                randombytes(l_request_out->data, l_request_out->data_size);
-                l_request_out->err_code = l_err_code;
-                dap_hash_fast(l_request_out->data, l_request_out->data_size, &l_request_out->data_hash);
+                if (l_request->data_size_recv) {
+                    l_request_out->data_size = l_request->data_size_recv;
+                    randombytes(l_request_out->data, l_request_out->data_size);
+                    dap_hash_fast(l_request_out->data, l_request_out->data_size, &l_request_out->data_hash);
+                }
+                l_request_out->err_code = 0;
                 strncpy(l_request_out->ip_send,a_ch->stream->esocket->hostaddr  , sizeof(l_request_out->ip_send)-1);
-
                 // Thats to prevent unaligned pointer
                 struct timeval l_tval;
                 gettimeofday(&l_tval, NULL);
                 l_request_out->send_time2.tv_sec = l_tval.tv_sec;
                 l_request_out->send_time2.tv_usec = l_tval.tv_usec;
-
                 // send response
                 dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE, l_request_out,
                                                l_request_out->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t));
                 DAP_DELETE(l_request_out);
             } break;
 
-            // for receive test data.
-            case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE: {
-                dap_stream_ch_chain_net_srv_pkt_test_t *l_request = (dap_stream_ch_chain_net_srv_pkt_test_t *) l_ch_pkt->data;
-                size_t l_request_size = l_request->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t);
-                if(l_ch_pkt->hdr.size != l_request_size) {
-                    log_it(L_WARNING, "Wrong request size, less or more than required");
-                    break;
-                }
-                struct timeval l_recv_time;
-                gettimeofday(&l_recv_time, NULL);
-                l_request->recv_time1 = l_recv_time;
-                dap_chain_hash_fast_t l_data_hash;
-                dap_hash_fast(l_request->data, l_request->data_size, &l_data_hash);
-                if(!dap_hash_fast_compare(&l_data_hash, &(l_request->data_hash))) {
-                    l_request->err_code += 4;
-                }
-                dap_stream_ch_set_ready_to_write_unsafe(a_ch, false);
-            } break;
-
-        	// only for server
             case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST:{
                 if (l_ch_pkt->hdr.size < sizeof(dap_stream_ch_chain_net_srv_pkt_request_hdr_t) ){
                     log_it( L_WARNING, "Wrong request size, less than minimum");
@@ -438,49 +412,24 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                 // Parse the request
                 l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, l_ch_pkt->hdr.size);
                 memcpy(l_grace->request, l_ch_pkt->data, l_ch_pkt->hdr.size);
+                l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64;
                 l_grace->request_size = l_ch_pkt->hdr.size;
                 l_grace->ch_uuid = a_ch->uuid;
                 l_grace->stream_worker = a_ch->stream_worker;
                 s_grace_period_control(l_grace);
             } break;
 
-            // only for client
-            case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST:{
-                log_it( L_NOTICE, "Requested smth to sign");
-                dap_chain_datum_tx_receipt_t * l_receipt = (dap_chain_datum_tx_receipt_t *) l_ch_pkt->data;
-                size_t l_receipt_size = l_ch_pkt->hdr.size;
-                // create receipt copy, because l_receipt may be reallocated inside dap_chain_datum_tx_receipt_create()!
-                dap_chain_datum_tx_receipt_t *l_receipt_new = dap_chain_datum_tx_receipt_create(l_receipt->receipt_info.srv_uid,
-                        l_receipt->receipt_info.units_type,
-                        l_receipt->receipt_info.units,
-                        l_receipt->receipt_info.value_datoshi,
-                        l_receipt->exts_n_signs, l_receipt->exts_size);
-                //l_srv_session->usages
-                ///l_usage->service->uid.uint64;
-                //dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find( l_srv_session, l_pkt->hdr.usage_id );
-                dap_chain_net_srv_t * l_srv = dap_chain_net_srv_get(l_ch_chain_net_srv->srv_uid);
-                if(l_srv && l_srv->callback_client_sign_request) {
-                    // Sign receipt
-                    l_srv->callback_client_sign_request(l_srv, 0, NULL, &l_receipt_new, l_receipt_size);
-                    dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE,
-                                                   l_receipt_new, l_receipt_new->size);
-                }
-                DAP_DELETE(l_receipt_new);
-                // TODO sign smth
-            } break;
-
-            // only for server
             case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE:{
-                if (l_ch_pkt->hdr.size <= sizeof(dap_chain_receipt_info_t) + 1) {
+                if (l_ch_pkt->hdr.size < sizeof(dap_chain_receipt_info_t)) {
                     log_it(L_ERROR, "Wrong sign response size, %u when expected at least %zu with smth", l_ch_pkt->hdr.size,
-                           sizeof(dap_chain_receipt_info_t)+1 );
+                           sizeof(dap_chain_receipt_info_t));
                     break;
                 }
                 dap_chain_datum_tx_receipt_t * l_receipt = (dap_chain_datum_tx_receipt_t *) l_ch_pkt->data;
                 size_t l_receipt_size = l_ch_pkt->hdr.size;
                 dap_chain_net_srv_usage_t * l_usage= NULL, *l_tmp= NULL;
                 bool l_is_found = false;
-                pthread_mutex_lock(& l_srv_session->parent->mutex );
+                pthread_mutex_lock(& l_srv_session->parent->mutex );    // TODO rework it with packet usage_id
                 HASH_ITER(hh, l_srv_session->usages, l_usage, l_tmp){
                     if ( l_usage->receipt_next ){ // If we have receipt next
                         if ( memcmp(&l_usage->receipt_next->receipt_info, &l_receipt->receipt_info,sizeof (l_receipt->receipt_info) )==0 ){
@@ -571,14 +520,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                 if (! l_usage->receipt_next && l_usage->receipt){
                     DAP_DELETE(l_usage->receipt);
                     l_usage->receipt = DAP_NEW_SIZE(dap_chain_datum_tx_receipt_t,l_receipt_size);
-                    l_usage->receipt_size = l_receipt_size;
                     l_is_first_sign = true;
                     l_usage->is_active = true;
                     memcpy( l_usage->receipt, l_receipt, l_receipt_size);
                 } else if (l_usage->receipt_next ){
                     DAP_DELETE(l_usage->receipt_next);
                     l_usage->receipt_next = DAP_NEW_SIZE(dap_chain_datum_tx_receipt_t,l_receipt_size);
-                    l_usage->receipt_next_size = l_receipt_size;
                     l_usage->is_active = true;
                     memcpy( l_usage->receipt_next, l_receipt, l_receipt_size);
                 }
@@ -586,18 +533,20 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                 // Store receipt if any problems with transactions
                 dap_chain_hash_fast_t l_receipt_hash={0};
                 dap_hash_fast(l_receipt,l_receipt_size,&l_receipt_hash);
-                char * l_receipt_hash_str = dap_chain_hash_fast_to_str_new(&l_receipt_hash);
-                dap_chain_global_db_gr_set( l_receipt_hash_str,l_receipt,l_receipt_size,"local.receipts");
+                char * l_receipt_hash_str = dap_chain_hash_fast_to_str_new(&l_receipt_hash);   
+                dap_chain_global_db_gr_set(l_receipt_hash_str, DAP_DUP_SIZE(l_receipt, l_receipt_size),
+                                           l_receipt_size, "local.receipts");
                 l_receipt_hash_str = NULL; // To prevent usage of this pointer when it will be free by GDB processor
                 size_t l_success_size;
                 dap_chain_hash_fast_t *l_tx_in_hash  = NULL;
                 if (!l_usage->is_grace) {
                     // Form input transaction
-                    dap_chain_addr_t *l_wallet_addr = dap_chain_wallet_get_addr(l_usage->wallet, l_usage->net->pub.id);
+                    dap_chain_addr_t *l_wallet_addr = dap_chain_wallet_get_addr(l_usage->price->wallet, l_usage->net->pub.id);
                     l_tx_in_hash = dap_chain_mempool_tx_create_cond_input(l_usage->net, &l_usage->tx_cond_hash, l_wallet_addr,
-                                                                          dap_chain_wallet_get_key(l_usage->wallet, 0),
-                                                                          l_receipt, l_receipt_size);
+                                                                          dap_chain_wallet_get_key(l_usage->price->wallet, 0),
+                                                                          l_receipt);
                     if ( l_tx_in_hash){
+                        memcpy(&l_usage->tx_cond_hash, l_tx_in_hash, sizeof(dap_chain_hash_fast_t));
                         char * l_tx_in_hash_str = dap_chain_hash_fast_to_str_new(l_tx_in_hash);
                         log_it(L_NOTICE, "Formed tx %s for input with active receipt", l_tx_in_hash_str);
                         DAP_DELETE(l_tx_in_hash_str);
@@ -630,42 +579,18 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                 if ( l_is_first_sign && l_usage->service->callback_response_success){
                     if( l_usage->service->callback_response_success(l_usage->service,l_usage->id,  l_usage->client,
                                                                 l_receipt, l_receipt_size ) !=0 ){
-                        log_it(L_NOTICE, "No success by service callback, inactivating service usage");
+                        log_it(L_NOTICE, "No success by service success callback, inactivating service usage");
                         l_usage->is_active = false;
                     }
-                    // issue receipt next
-                    l_usage->receipt_next = dap_chain_net_srv_issue_receipt( l_usage->service, l_usage, l_usage->price ,NULL,0);
-                    l_usage->receipt_next_size = l_usage->receipt_next->size;
-                    dap_stream_ch_pkt_write_unsafe( a_ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST ,
-                                             l_usage->receipt_next, l_usage->receipt_next->size);
-
                 }else if ( l_usage->service->callback_receipt_next_success){
-                    if (l_usage->service->callback_receipt_next_success(l_usage->service,l_usage->id,  l_usage->client,
+                    if (l_usage->service->callback_receipt_next_success(l_usage->service, l_usage->id, l_usage->client,
                                                                 l_receipt, l_receipt_size ) != 0 ){
-                        log_it(L_NOTICE, "No success by service callback, inactivating service usage");
+                        log_it(L_NOTICE, "No success by service receipt_next callback, inactivating service usage");
                         l_usage->is_active = false;
                     }
                 }
             } break;
 
-            case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS:{
-                log_it( L_NOTICE, "Responsed with success");
-                // TODO code for service client mode
-                dap_stream_ch_chain_net_srv_pkt_success_t * l_success = (dap_stream_ch_chain_net_srv_pkt_success_t*)l_ch_pkt->data;
-                size_t l_success_size = l_ch_pkt->hdr.size;
-                dap_chain_net_srv_t * l_srv = dap_chain_net_srv_get(l_success->hdr.srv_uid);
-                if ( l_srv && l_srv->callback_client_success){
-                    // Create client for client)
-                    dap_chain_net_srv_client_remote_t *l_client = DAP_NEW_Z( dap_chain_net_srv_client_remote_t);
-                    l_client->ch = a_ch;
-                    l_client->stream_worker = a_ch->stream_worker;
-                    l_client->ts_created = time(NULL);
-                    l_client->session_id = a_ch->stream->session->id;
-                    l_srv->callback_client_success(l_srv, l_success->hdr.usage_id,  l_client, l_success, l_success_size );
-                    //l_success->hdr.net_id, l_success->hdr.srv_uid, l_success->hdr.usage_id
-                }
-            } break;
-
             case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA:{
                 if (l_ch_pkt->hdr.size < sizeof(dap_stream_ch_chain_net_srv_pkt_data_hdr_t) ){
                     log_it( L_WARNING, "Wrong request size, less than minimum");
@@ -684,46 +609,31 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                     dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) );
                     break;
                 }
-                if (l_usage == NULL){
-                    if (!l_srv->callback_stream_ch_read_with_out_data)
-                        break;
-                    size_t l_out_data_size = 0;
-                    void *l_out_data = l_srv->callback_stream_ch_read_with_out_data( l_srv, 0, NULL, l_pkt->data, l_pkt_size, &l_out_data_size);
-                    if (l_out_data && l_out_data_size) {
-                        dap_stream_ch_chain_net_srv_pkt_data_t *l_data = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_data_t,
-                                                                                        sizeof(dap_stream_ch_chain_net_srv_pkt_data_t) + l_out_data_size);
-                        l_data->hdr.version = 1;
-                        l_data->hdr.srv_uid = l_srv->uid;
-                        l_data->hdr.usage_id = l_pkt->hdr.usage_id;
-                        l_data->hdr.data_size = l_out_data_size;
-                        memcpy(l_data->data, l_out_data, l_out_data_size);
-                        dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA, l_data, sizeof(dap_stream_ch_chain_net_srv_pkt_data_t)+l_out_data_size);
-                        DAP_FREE(l_data);
-                    }
-                } else {
-                    if (!l_srv->callback_stream_ch_read)
+                if (!l_srv->callback_custom_data)
                         break;
-                    l_srv->callback_stream_ch_read( l_srv,l_usage->id, l_usage->client, l_pkt->data, l_pkt_size);
+                size_t l_out_data_size = 0;
+                void *l_out_data = l_srv->callback_custom_data(l_srv, l_usage, l_pkt->data, l_pkt_size, &l_out_data_size);
+                if (l_out_data && l_out_data_size) {
+                    dap_stream_ch_chain_net_srv_pkt_data_t *l_data = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_data_t,
+                                                                                    sizeof(dap_stream_ch_chain_net_srv_pkt_data_t) + l_out_data_size);
+                    l_data->hdr.version = 1;
+                    l_data->hdr.srv_uid = l_srv->uid;
+                    l_data->hdr.usage_id = l_pkt->hdr.usage_id;
+                    l_data->hdr.data_size = l_out_data_size;
+                    memcpy(l_data->data, l_out_data, l_out_data_size);
+                    dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_DATA, l_data, sizeof(dap_stream_ch_chain_net_srv_pkt_data_t)+l_out_data_size);
+                    DAP_FREE(l_data);
                 }
-
-
             } break;
-
-            case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR:{
-                if ( l_ch_pkt->hdr.size == sizeof (dap_stream_ch_chain_net_srv_pkt_error_t) ){
-                    dap_stream_ch_chain_net_srv_pkt_error_t * l_err = (dap_stream_ch_chain_net_srv_pkt_error_t *) l_ch_pkt->data;
-                    log_it( L_NOTICE, "Remote responsed with error code 0x%08X", l_err->code );
-                    // TODO code for service client mode
-                }else{
-                    log_it(L_ERROR, "Wrong error response size, %u when expected %zu", l_ch_pkt->hdr.size,
-                           sizeof ( dap_stream_ch_chain_net_srv_pkt_error_t) );
-                }
-            } break;
-
+            // only for client
+            case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE:
+            case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST:
+            case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR:
+            case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS:
+            case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_DATA:
+                break;
             default: log_it( L_WARNING, "Unknown packet type 0x%02X", l_ch_pkt->hdr.type);
         }
-        if(l_ch_chain_net_srv->notify_callback)
-            l_ch_chain_net_srv->notify_callback(l_ch_chain_net_srv, l_ch_pkt->hdr.type, l_ch_pkt, l_ch_chain_net_srv->notify_callback_arg);
     }
 
 }
diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h
index 01fb26820b..19a2599899 100644
--- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h
+++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h
@@ -24,7 +24,7 @@
 
 #pragma once
 
-#include "dap_chain_net_srv_common.h"
+#include "dap_stream_worker.h"
 #include "dap_stream_ch_pkt.h"
 #include "dap_chain_net_srv_stream_session.h"
 
@@ -34,8 +34,9 @@ typedef void (*dap_stream_ch_chain_net_srv_callback_packet_t)(dap_stream_ch_chai
         dap_stream_ch_pkt_t *, void *);
 
 typedef struct dap_stream_ch_chain_net_srv {
-    pthread_mutex_t mutex;
     dap_chain_net_srv_uid_t srv_uid;
+    dap_stream_ch_t *ch;
+    dap_stream_ch_uuid_t ch_uuid;
     dap_stream_ch_chain_net_srv_callback_packet_t notify_callback;
     void *notify_callback_arg;
 } dap_stream_ch_chain_net_srv_t;
diff --git a/modules/channel/chain-net-srv/include/dap_stream_ch_chain_net_srv_pkt.h b/modules/channel/chain-net-srv/include/dap_stream_ch_chain_net_srv_pkt.h
index aec3d53789..0b78c06d44 100644
--- a/modules/channel/chain-net-srv/include/dap_stream_ch_chain_net_srv_pkt.h
+++ b/modules/channel/chain-net-srv/include/dap_stream_ch_chain_net_srv_pkt.h
@@ -31,7 +31,6 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include <stddef.h>
 #include <stdint.h>
 
-#include "dap_chain_net_srv_common.h"
 #include "dap_chain_net_srv_stream_session.h"
 
 
diff --git a/modules/common/dap_chain_datum_tx.c b/modules/common/dap_chain_datum_tx.c
index 6f48ec58ed..6946ec4ef7 100644
--- a/modules/common/dap_chain_datum_tx.c
+++ b/modules/common/dap_chain_datum_tx.c
@@ -75,7 +75,7 @@ int dap_chain_datum_tx_add_item(dap_chain_datum_tx_t **a_tx, const uint8_t *a_it
     if(!size)
         return -1;
     dap_chain_datum_tx_t *tx_cur = *a_tx;
-    tx_cur = (dap_chain_datum_tx_t*) realloc(tx_cur, dap_chain_datum_tx_get_size(tx_cur) + size);
+    tx_cur = (dap_chain_datum_tx_t *)DAP_REALLOC(tx_cur, dap_chain_datum_tx_get_size(tx_cur) + size);
     memcpy((uint8_t*) tx_cur->tx_items + tx_cur->header.tx_items_size, a_item, size);
     tx_cur->header.tx_items_size += size;
     *a_tx = tx_cur;
@@ -179,7 +179,7 @@ int dap_chain_datum_tx_add_out_ext_item(dap_chain_datum_tx_t **a_tx, const dap_c
  *
  * return 1 Ok, -1 Error
  */
-int dap_chain_datum_tx_add_out_cond_item(dap_chain_datum_tx_t **a_tx, dap_enc_key_t *a_key, dap_chain_net_srv_uid_t a_srv_uid,
+int dap_chain_datum_tx_add_out_cond_item(dap_chain_datum_tx_t **a_tx, dap_pkey_t *a_key, dap_chain_net_srv_uid_t a_srv_uid,
         uint64_t a_value, uint64_t a_value_max_per_unit, dap_chain_net_srv_price_unit_uid_t a_unit, const void *a_cond, size_t a_cond_size)
 {
     dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_pay(
diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c
index 8e62f58083..6ded7d564f 100644
--- a/modules/common/dap_chain_datum_tx_items.c
+++ b/modules/common/dap_chain_datum_tx_items.c
@@ -76,9 +76,9 @@ static size_t dap_chain_tx_pkey_get_size(const dap_chain_tx_pkey_t *a_item)
     return size;
 }
 
-static size_t dap_chain_tx_sig_get_size(const dap_chain_tx_sig_t *item)
+static size_t dap_chain_tx_sig_get_size(const dap_chain_tx_sig_t *a_item)
 {
-    size_t size = sizeof(dap_chain_tx_sig_t) + item->header.sig_size;
+    size_t size = sizeof(dap_chain_tx_sig_t) + a_item->header.sig_size;
     return size;
 }
 
@@ -89,6 +89,12 @@ static size_t dap_chain_tx_token_get_size(const dap_chain_tx_token_t *a_item)
     return size;
 }
 
+static size_t dap_chain_datum_tx_receipt_get_size(const dap_chain_datum_tx_receipt_t *a_item)
+{
+    size_t size = a_item->size;
+    return size;
+}
+
 /**
  * Get item type
  *
@@ -121,7 +127,8 @@ size_t dap_chain_datum_item_tx_get_size(const uint8_t *a_item)
         size = dap_chain_tx_out_ext_get_size((const dap_chain_tx_out_ext_t*) a_item);
         break;
     case TX_ITEM_TYPE_RECEIPT: // Receipt
-        size = dap_chain_datum_tx_receipt_get_size((const dap_chain_datum_tx_receipt_t*) a_item);
+        size = dap_chain_datum_tx_receipt_get_size((const dap_chain_datum_tx_receipt_t *)a_item);
+        break;
     case TX_ITEM_TYPE_IN_COND: // Transaction inputs with condition
         size = dap_chain_tx_in_cond_get_size((const dap_chain_tx_in_cond_t*) a_item);
         break;
@@ -229,15 +236,12 @@ dap_chain_tx_out_ext_t* dap_chain_datum_tx_item_out_ext_create(const dap_chain_a
  *
  * return item, NULL Error
  */
-dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_enc_key_t *a_key, dap_chain_net_srv_uid_t a_srv_uid,
+dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_pkey_t *a_key, dap_chain_net_srv_uid_t a_srv_uid,
         uint64_t a_value,uint64_t a_value_max_per_unit, dap_chain_net_srv_price_unit_uid_t a_unit,
                                                                  const void *a_params, size_t a_params_size)
 {
-    if(!a_key || !a_params)
+    if (!a_key || !a_key->pkey)
         return NULL;
-    size_t l_pub_key_size = 0;
-    uint8_t *l_pub_key = dap_enc_key_serealize_pub_key(a_key, &l_pub_key_size);
-
 
     dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + a_params_size);
     if(l_item == NULL)
@@ -245,13 +249,15 @@ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_enc
 
     l_item->header.item_type = TX_ITEM_TYPE_OUT_COND;
     l_item->header.value = a_value;
-    l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY; // By default creatre cond for service pay. Rework with smth more flexible
+    l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY;
     l_item->subtype.srv_pay.srv_uid = a_srv_uid;
     l_item->subtype.srv_pay.unit = a_unit;
     l_item->subtype.srv_pay.unit_price_max_datoshi = a_value_max_per_unit;
-    dap_hash_fast( l_pub_key, l_pub_key_size, & l_item->subtype.srv_pay.pkey_hash);
-    l_item->params_size = (uint32_t)a_params_size;
-    memcpy(l_item->params, a_params, a_params_size);
+    dap_hash_fast(a_key->pkey,a_key->header.size, &l_item->subtype.srv_pay.pkey_hash);
+    if (a_params && a_params_size) {
+        l_item->params_size = (uint32_t)a_params_size;
+        memcpy(l_item->params, a_params, a_params_size);
+    }
     return l_item;
 }
 
diff --git a/modules/common/dap_chain_datum_tx_receipt.c b/modules/common/dap_chain_datum_tx_receipt.c
index d4428f85e5..fb0a27d4b8 100644
--- a/modules/common/dap_chain_datum_tx_receipt.c
+++ b/modules/common/dap_chain_datum_tx_receipt.c
@@ -45,13 +45,14 @@ dap_chain_datum_tx_receipt_t * dap_chain_datum_tx_receipt_create( dap_chain_net_
                                                                     uint64_t a_units, uint64_t a_value_datoshi,
                                                                   const void * a_ext, size_t a_ext_size)
 {
-    dap_chain_datum_tx_receipt_t * l_ret = DAP_NEW_Z_SIZE(dap_chain_datum_tx_receipt_t, dap_chain_datum_tx_receipt_get_size_hdr() +a_ext_size );
+    dap_chain_datum_tx_receipt_t *l_ret = DAP_NEW_Z_SIZE(dap_chain_datum_tx_receipt_t,
+                                                         sizeof(dap_chain_datum_tx_receipt_t) + a_ext_size);
     l_ret->type = TX_ITEM_TYPE_RECEIPT;
     l_ret->receipt_info.units_type = a_units_type;
     l_ret->receipt_info.srv_uid = a_srv_uid;
     l_ret->receipt_info.units = a_units;
     l_ret->receipt_info.value_datoshi = a_value_datoshi;
-    l_ret->size = dap_chain_datum_tx_receipt_get_size_hdr()+a_ext_size;
+    l_ret->size = sizeof(dap_chain_datum_tx_receipt_t) + a_ext_size;
 
     if( a_ext_size && a_ext){
         l_ret->exts_size = a_ext_size;
@@ -60,27 +61,25 @@ dap_chain_datum_tx_receipt_t * dap_chain_datum_tx_receipt_create( dap_chain_net_
     return  l_ret;
 }
 
-size_t dap_chain_datum_tx_receipt_sign_add(dap_chain_datum_tx_receipt_t ** a_receipt, size_t a_receipt_size, dap_enc_key_t *a_key )
+dap_chain_datum_tx_receipt_t *dap_chain_datum_tx_receipt_sign_add(dap_chain_datum_tx_receipt_t *a_receipt, dap_enc_key_t *a_key)
 {
-    dap_chain_datum_tx_receipt_t *l_receipt = *a_receipt;
-    if ( ! *a_receipt ){
+    if (!a_receipt) {
         log_it( L_ERROR, "NULL receipt, can't add sign");
-        return 0;
+        return NULL;
     }
-    dap_sign_t * l_sign = dap_sign_create(a_key,&l_receipt->receipt_info,sizeof (l_receipt->receipt_info),0);
+    dap_sign_t * l_sign = dap_sign_create(a_key, &a_receipt->receipt_info, sizeof(a_receipt->receipt_info), 0);
     size_t l_sign_size = l_sign? dap_sign_get_size( l_sign ) : 0;
     if ( ! l_sign || ! l_sign_size ){
         log_it( L_ERROR, "Can't sign the receipt, may be smth with key?");
-        return 0;
+        return NULL;
     }
-    l_receipt= (dap_chain_datum_tx_receipt_t*) DAP_REALLOC(l_receipt, a_receipt_size+l_sign_size);
+    dap_chain_datum_tx_receipt_t *l_receipt = (dap_chain_datum_tx_receipt_t *)
+                                                DAP_REALLOC(a_receipt, a_receipt->size + l_sign_size);
     memcpy(l_receipt->exts_n_signs + l_receipt->exts_size, l_sign, l_sign_size);
-    a_receipt_size += l_sign_size;
-    l_receipt->size = a_receipt_size;
+    l_receipt->size += l_sign_size;
     l_receipt->exts_size += l_sign_size;
-    DAP_DELETE( l_sign );
-    *a_receipt = l_receipt;
-    return a_receipt_size;
+    DAP_DELETE(l_sign);
+    return l_receipt;
 }
 
 /**
diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h
index 9af0957ee2..c6b60a080f 100644
--- a/modules/common/include/dap_chain_common.h
+++ b/modules/common/include/dap_chain_common.h
@@ -207,11 +207,15 @@ enum dap_chain_tx_item_type {
 typedef byte_t dap_chain_tx_item_type_t;
 
 
-typedef struct dap_chain_receipt{
+typedef struct dap_chain_receipt_info {
     dap_chain_net_srv_uid_t srv_uid; // Service UID
+#if DAP_CHAIN_NET_SRV_UID_SIZE == 8
+    uint64_t addition;
+#endif
     dap_chain_net_srv_price_unit_uid_t units_type;
     uint64_t units; // Unit of service (seconds, megabytes, etc.) Only for SERV_CLASS_PERMANENT
     uint64_t value_datoshi; // Receipt value
+    uint64_t padding[3];    // For future 256-bit values
 } dap_chain_receipt_info_t;
 
 
diff --git a/modules/common/include/dap_chain_datum_tx.h b/modules/common/include/dap_chain_datum_tx.h
index 54885c4863..6c598c4ae6 100644
--- a/modules/common/include/dap_chain_datum_tx.h
+++ b/modules/common/include/dap_chain_datum_tx.h
@@ -119,7 +119,7 @@ int dap_chain_datum_tx_add_out_ext_item(dap_chain_datum_tx_t **a_tx, const dap_c
  *
  * return 1 Ok, -1 Error
  */
-int dap_chain_datum_tx_add_out_cond_item(dap_chain_datum_tx_t **a_tx, dap_enc_key_t *a_key, dap_chain_net_srv_uid_t a_srv_uid,
+int dap_chain_datum_tx_add_out_cond_item(dap_chain_datum_tx_t **a_tx, dap_pkey_t *a_key, dap_chain_net_srv_uid_t a_srv_uid,
         uint64_t a_value, uint64_t a_value_max_per_unit, dap_chain_net_srv_price_unit_uid_t a_unit, const void *a_cond, size_t a_cond_size);
 
 /**
diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h
index 6fb2f647cd..ec68fcf58f 100644
--- a/modules/common/include/dap_chain_datum_tx_items.h
+++ b/modules/common/include/dap_chain_datum_tx_items.h
@@ -111,7 +111,7 @@ dap_chain_tx_out_ext_t* dap_chain_datum_tx_item_out_ext_create(const dap_chain_a
  *
  * return item, NULL Error
  */
-dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_enc_key_t *a_key, dap_chain_net_srv_uid_t a_srv_uid,
+dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_pkey_t *a_key, dap_chain_net_srv_uid_t a_srv_uid,
         uint64_t a_value, uint64_t a_value_max_per_unit, dap_chain_net_srv_price_unit_uid_t a_unit,
                                                                  const void *a_cond, size_t a_cond_size);
 /**
diff --git a/modules/common/include/dap_chain_datum_tx_receipt.h b/modules/common/include/dap_chain_datum_tx_receipt.h
index 4d5effd8f8..15f8707ffd 100644
--- a/modules/common/include/dap_chain_datum_tx_receipt.h
+++ b/modules/common/include/dap_chain_datum_tx_receipt.h
@@ -33,9 +33,10 @@
  */
 typedef struct dap_chain_datum_tx_receipt {
     dap_chain_tx_item_type_t type; // Transaction item type
+    byte_t padding[3];
     dap_chain_receipt_info_t receipt_info; // Receipt itself
-    uint16_t size;
-    uint16_t exts_size;
+    uint64_t size;
+    uint64_t exts_size;
     byte_t exts_n_signs[]; // Signatures, first from provider, second from client
 }DAP_ALIGN_PACKED dap_chain_datum_tx_receipt_t;
 
@@ -44,19 +45,12 @@ typedef struct dap_chain_datum_tx_receipt {
 extern "C" {
 #endif
 
-static inline size_t dap_chain_datum_tx_receipt_get_size_hdr(){ return 1+sizeof (dap_chain_receipt_info_t)+sizeof (uint16_t) +sizeof (uint16_t); }
-
 dap_chain_datum_tx_receipt_t * dap_chain_datum_tx_receipt_create( dap_chain_net_srv_uid_t srv_uid,
                                                                   dap_chain_net_srv_price_unit_uid_t units_type,
                                                                     uint64_t units, uint64_t value_datoshi, const void * a_ext, size_t a_ext_size);
-size_t dap_chain_datum_tx_receipt_sign_add(dap_chain_datum_tx_receipt_t ** a_receipt, size_t a_receipt_size, dap_enc_key_t *a_key );
+dap_chain_datum_tx_receipt_t *dap_chain_datum_tx_receipt_sign_add(dap_chain_datum_tx_receipt_t *a_receipt, dap_enc_key_t *a_key );
 dap_sign_t* dap_chain_datum_tx_receipt_sign_get(dap_chain_datum_tx_receipt_t * l_receipt, size_t l_receipt_size , uint16_t sign_position);
 uint16_t dap_chain_datum_tx_receipt_signs_count(dap_chain_datum_tx_receipt_t * l_receipt, size_t l_receipt_size);
-static inline uint16_t dap_chain_datum_tx_receipt_get_size(const dap_chain_datum_tx_receipt_t * l_receipt)
-{
-    return l_receipt->size;
-}
-
 
 #ifdef __cplusplus
 }
diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c
index e72a1242c0..749b19926b 100644
--- a/modules/mempool/dap_chain_mempool.c
+++ b/modules/mempool/dap_chain_mempool.c
@@ -346,11 +346,10 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a
 
 }
 
-dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t * a_net,dap_chain_hash_fast_t *a_tx_prev_hash,
-                                                              const dap_chain_addr_t* a_addr_to, dap_enc_key_t *l_key_tx_sign,
-                                                              dap_chain_datum_tx_receipt_t * l_receipt, size_t l_receipt_size)
+dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t * a_net, dap_chain_hash_fast_t *a_tx_prev_hash,
+                                                              const dap_chain_addr_t* a_addr_to, dap_enc_key_t *a_key_tx_sign,
+                                                              dap_chain_datum_tx_receipt_t * l_receipt)
 {
-    UNUSED(l_receipt_size);
     dap_ledger_t * l_ledger = a_net ? dap_chain_ledger_by_net_name( a_net->pub.name ) : NULL;
     if ( ! a_net || ! l_ledger || ! a_addr_to )
         return NULL;
@@ -368,10 +367,11 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t *
     uint64_t l_value_send = l_receipt->receipt_info.value_datoshi;
 
     // add 'in_cond' items
-    dap_chain_datum_tx_t *l_tx_cond = dap_chain_ledger_tx_find_by_hash(l_ledger, a_tx_prev_hash);
+    dap_chain_hash_fast_t *l_tx_prev_hash = a_tx_prev_hash;
+    dap_chain_datum_tx_t *l_tx_cond = dap_chain_ledger_tx_find_by_hash(l_ledger, l_tx_prev_hash);
     int l_prev_cond_idx;
     dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_cond, &l_prev_cond_idx);
-    if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, a_tx_prev_hash, l_prev_cond_idx)) {
+    if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, l_tx_prev_hash, l_prev_cond_idx)) { // TX already spent
         dap_chain_datum_tx_t *l_tx_tmp;
         dap_chain_hash_fast_t l_tx_cur_hash = { 0 }; // start hash
         dap_chain_tx_out_cond_t *l_tmp_cond;
@@ -401,8 +401,11 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t *
             log_it(L_WARNING, "Requested conditional transaction is already used out");
             return NULL;
         }
+        l_prev_cond_idx = l_tmp_cond_idx;
+        l_out_cond = l_tmp_cond;
+        l_tx_prev_hash = dap_chain_node_datum_tx_calc_hash(l_tx_tmp);
     }
-    if (dap_chain_datum_tx_add_in_cond_item(&l_tx, a_tx_prev_hash, l_prev_cond_idx, pos-1) != 0 ){
+    if (dap_chain_datum_tx_add_in_cond_item(&l_tx, l_tx_prev_hash, l_prev_cond_idx, pos-1) != 0 ){
         dap_chain_datum_tx_delete(l_tx);
         log_it( L_ERROR, "Cant add tx cond input");
         return NULL;
@@ -416,16 +419,14 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t *
     }
 
     //add 'out_cond' item
-    size_t l_size = dap_chain_datum_item_tx_get_size((uint8_t *)l_out_cond);
-    dap_chain_tx_out_cond_t *l_out_cond_new = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, l_size);
-    memcpy(l_out_cond_new, l_out_cond, l_size);
-    l_out_cond_new->header.value -= l_value_send;
-    dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond_new);
-    DAP_DELETE(l_out_cond_new);
+    uint64_t l_old_val = l_out_cond->header.value;
+    l_out_cond->header.value -= l_value_send;
+    dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond);
+    l_out_cond->header.value = l_old_val;
 
     // add 'sign' items
-    if (l_key_tx_sign){
-        if(dap_chain_datum_tx_add_sign_item(&l_tx, l_key_tx_sign) != 1) {
+    if (a_key_tx_sign){
+        if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_tx_sign) != 1) {
             dap_chain_datum_tx_delete(l_tx);
             log_it( L_ERROR, "Can't add sign output");
             return NULL;
@@ -462,26 +463,26 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t *
  *
  * return dap_chain_datum_t, NULL if Error
  */
-static dap_chain_datum_t* dap_chain_tx_create_cond(dap_chain_net_t * a_net,
-        dap_enc_key_t *a_key_from, dap_enc_key_t *a_key_cond,
-        const dap_chain_addr_t* a_addr_from,
+static dap_chain_datum_t* dap_chain_tx_create_cond(dap_chain_net_t *a_net,
+        dap_enc_key_t *a_key_from, dap_pkey_t *a_key_cond,
         const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
-        uint64_t a_value,uint64_t a_value_per_unit_max, dap_chain_net_srv_price_unit_uid_t a_unit,
+        uint64_t a_value, uint64_t a_value_per_unit_max, dap_chain_net_srv_price_unit_uid_t a_unit,
         dap_chain_net_srv_uid_t a_srv_uid, uint64_t a_value_fee, const void *a_cond, size_t a_cond_size)
 {
     dap_ledger_t * l_ledger = a_net ? dap_chain_ledger_by_net_name( a_net->pub.name ) : NULL;
     // check valid param
-    if(!a_net || ! l_ledger || !a_key_from || !a_key_from->priv_key_data || !a_key_from->priv_key_data_size ||
-            !dap_chain_addr_check_sum(a_addr_from) ||
-            !a_value)
+    if(!a_net || ! l_ledger || !a_key_from || !a_key_from->priv_key_data || !a_key_from->priv_key_data_size || !a_value)
         return NULL;
 
     // find the transactions from which to take away coins
     uint64_t l_value_transfer = 0; // how many coins to transfer
     uint64_t l_value_need = a_value + a_value_fee;
+    // where to take coins for service
+    dap_chain_addr_t l_addr_from;
+    dap_chain_addr_fill_from_key(&l_addr_from, a_key_from, a_net->pub.id);
     // list of transaction with 'out' items
     dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, a_token_ticker,
-                                                                             a_addr_from, l_value_need, &l_value_transfer);
+                                                                             &l_addr_from, l_value_need, &l_value_transfer);
     if(!l_list_used_out) {
         log_it( L_ERROR, "nothing to tranfer (not enough funds)");
         return NULL;
@@ -509,7 +510,7 @@ static dap_chain_datum_t* dap_chain_tx_create_cond(dap_chain_net_t * a_net,
         // coin back
         uint64_t l_value_back = l_value_transfer - l_value_pack;
         if(l_value_back) {
-            if(dap_chain_datum_tx_add_out_item(&l_tx, a_addr_from, l_value_back) != 1) {
+            if(dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_from, l_value_back) != 1) {
                 dap_chain_datum_tx_delete(l_tx);
                 log_it( L_ERROR, "Cant add coin back output");
                 return NULL;
@@ -528,62 +529,6 @@ static dap_chain_datum_t* dap_chain_tx_create_cond(dap_chain_net_t * a_net,
     dap_chain_datum_t *l_datum = dap_chain_datum_create( DAP_CHAIN_DATUM_TX, l_tx, l_tx_size );
 
     return l_datum;
-    /*dap_chain_hash_fast_t *l_key_hash = DAP_NEW_Z( dap_chain_hash_fast_t );
-    dap_hash_fast( l_tx, l_tx_size, l_key_hash );
-    DAP_DELETE( l_tx );
-
-    char * l_key_str = dap_chain_hash_fast_to_str_new( l_key_hash );
-    char * l_gdb_group = dap_chain_net_get_gdb_group_mempool_by_chain_type( a_net ,CHAIN_TYPE_TX);
-    if( dap_chain_global_db_gr_set( dap_strdup(l_key_str), (uint8_t *) l_datum, dap_chain_datum_size(l_datum)
-                                   , l_gdb_group ) ) {
-        log_it(L_NOTICE, "Transaction %s placed in mempool", l_key_str);
-    }
-    DAP_DELETE(l_gdb_group);
-    DAP_DELETE(l_key_str);
-
-    return l_key_hash;*/
-}
-
-/**
- * Make transfer transaction & insert to database
- *
- * return 0 Ok, -2 not enough funds to transfer, -1 other Error
- */
-dap_chain_hash_fast_t* dap_chain_proc_tx_create_cond(dap_chain_net_t * a_net,
-        dap_enc_key_t *a_key_from, dap_enc_key_t *a_key_cond,
-        const dap_chain_addr_t* a_addr_from,
-        const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
-        uint64_t a_value,uint64_t a_value_per_unit_max, dap_chain_net_srv_price_unit_uid_t a_unit,
-        dap_chain_net_srv_uid_t a_srv_uid, uint64_t a_value_fee, const void *a_cond, size_t a_cond_size)
-{
-
-    dap_chain_t *l_chain = NULL;
-    if(a_net->pub.default_chain)
-        l_chain = a_net->pub.default_chain;
-    else
-        l_chain = dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_TX);
-
-    if(!l_chain)
-            return NULL;
-    // Make transfer transaction
-    dap_chain_datum_t *l_datum = dap_chain_tx_create_cond(a_net,a_key_from, a_key_cond, a_addr_from,
-            a_token_ticker,a_value,a_value_per_unit_max, a_unit,
-            a_srv_uid, a_value_fee, a_cond, a_cond_size);
-
-    if(!l_datum)
-        return NULL;
-    size_t l_datums_number = l_chain->callback_add_datums(l_chain, &l_datum, 1);
-    if(!l_datums_number)
-            return NULL;
-
-    dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)&(l_datum->data);
-    size_t l_tx_size = l_datum->header.data_size;
-
-    dap_chain_hash_fast_t *l_key_hash = DAP_NEW_Z( dap_chain_hash_fast_t );
-    dap_hash_fast( l_tx, l_tx_size, l_key_hash );
-    //DAP_DELETE( l_tx );
-
-    return l_key_hash;
 }
 
 /**
@@ -592,16 +537,15 @@ dap_chain_hash_fast_t* dap_chain_proc_tx_create_cond(dap_chain_net_t * a_net,
  * return 0 Ok, -2 not enough funds to transfer, -1 other Error
  */
 dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond(dap_chain_net_t * a_net,
-        dap_enc_key_t *a_key_from, dap_enc_key_t *a_key_cond,
-        const dap_chain_addr_t* a_addr_from,
+        dap_enc_key_t *a_key_from, dap_pkey_t *a_key_cond,
         const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
         uint64_t a_value,uint64_t a_value_per_unit_max, dap_chain_net_srv_price_unit_uid_t a_unit,
         dap_chain_net_srv_uid_t a_srv_uid, uint64_t a_value_fee, const void *a_cond, size_t a_cond_size)
 {
     // Make transfer transaction
-    dap_chain_datum_t *l_datum = dap_chain_tx_create_cond(a_net,a_key_from, a_key_cond, a_addr_from,
-            a_token_ticker,a_value,a_value_per_unit_max, a_unit,
-            a_srv_uid, a_value_fee, a_cond, a_cond_size);
+    dap_chain_datum_t *l_datum = dap_chain_tx_create_cond(a_net,a_key_from, a_key_cond,
+                                                          a_token_ticker,a_value,a_value_per_unit_max, a_unit,
+                                                          a_srv_uid, a_value_fee, a_cond, a_cond_size);
 
     if(!l_datum)
         return NULL;
@@ -617,7 +561,7 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond(dap_chain_net_t * a_net,
     char * l_gdb_group = dap_chain_net_get_gdb_group_mempool_by_chain_type( a_net ,CHAIN_TYPE_TX);
     if( dap_chain_global_db_gr_set( dap_strdup(l_key_str), (uint8_t *) l_datum, dap_chain_datum_size(l_datum)
                                    , l_gdb_group ) ) {
-        log_it(L_NOTICE, "Transaction %s placed in mempool", l_key_str);
+        log_it(L_NOTICE, "Transaction %s placed in mempool group %s", l_key_str, l_gdb_group);
     }
     DAP_DELETE(l_gdb_group);
     DAP_DELETE(l_key_str);
@@ -625,140 +569,6 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond(dap_chain_net_t * a_net,
     return l_key_hash;
 }
 
-/**
- * Make receipt transaction & insert to cache
- *
- * return 0 Ok, -2 not enough funds to transfer, -1 other Error
- */
-int dap_chain_mempool_tx_create_receipt(uint64_t a_value)
-//(dap_enc_key_t *a_key_from, dap_enc_key_t *a_key_cond,
-//        const dap_chain_addr_t* a_addr_from, const dap_chain_addr_t* a_addr_cond,
-//        const dap_chain_addr_t* a_addr_fee, const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
-//        uint64_t a_value, uint64_t a_value_fee, const void *a_cond, size_t a_cond_size)
-{
-    // check valid param
-/*    if(!a_key_from || !a_key_from->priv_key_data || !a_key_from->priv_key_data_size ||
-            !dap_chain_addr_check_sum(a_addr_from) || !dap_chain_addr_check_sum(a_addr_cond) ||
-            (a_addr_fee && !dap_chain_addr_check_sum(a_addr_fee)) || !a_value)
-        return -1;*/
-/*
-    // find the transactions from which to take away coins
-    dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items
-    uint64_t l_value_transfer = 0; // how many coins to transfer
-    {
-        dap_chain_hash_fast_t l_tx_cur_hash = { 0 };
-        uint64_t l_value_need = a_value + a_value_fee;
-        while(l_value_transfer < l_value_need)
-        {
-            // Get the transaction in the cache by the addr in out item
-            const dap_chain_datum_tx_t *l_tx = dap_chain_ledger_tx_find_by_addr(a_addr_from,
-                    &l_tx_cur_hash);
-            if(!l_tx)
-                break;
-            // Get all item from transaction by type
-            int l_item_count = 0;
-            dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get((dap_chain_datum_tx_t*) l_tx, TX_ITEM_TYPE_OUT,
-                    &l_item_count);
-            dap_list_t *l_list_tmp = l_list_out_items;
-            int l_out_idx_tmp = 0; // current index of 'out' item
-            while(l_list_tmp) {
-                dap_chain_tx_out_t *out_item = l_list_tmp->data;
-                // if 'out' item has addr = a_addr_from
-                if(out_item && &out_item->addr && !memcmp(a_addr_from, &out_item->addr, sizeof(dap_chain_addr_t))) {
-
-                    // Check whether used 'out' items
-                    if(!dap_chain_ledger_tx_hash_is_used_out_item(&l_tx_cur_hash, l_out_idx_tmp)) {
-
-                        list_used_item_t *item = DAP_NEW(list_used_item_t);
-                        memcpy(&item->tx_hash_fast, &l_tx_cur_hash, sizeof(dap_chain_hash_fast_t));
-                        item->num_idx_out = l_out_idx_tmp;
-                        item->value = out_item->header.value;
-                        l_list_used_out = dap_list_append(l_list_used_out, item);
-                        l_value_transfer += item->value;
-                        // already accumulated the required value, finish the search for 'out' items
-                        if(l_value_transfer >= l_value_need) {
-                            break;
-                        }
-                    }
-                }
-                // go to the next 'out' item in l_tx transaction
-                l_out_idx_tmp++;
-                l_list_tmp = dap_list_next(l_list_tmp);
-            }
-            dap_list_free(l_list_out_items);
-        }
-
-        // nothing to tranfer (not enough funds)
-        if(!l_list_used_out || l_value_transfer < l_value_need) {
-            dap_list_free_full(l_list_used_out, free);
-            return -2;
-        }
-    }
-
-    // create empty transaction
-    dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
-    // add 'in' items
-    {
-        dap_list_t *l_list_tmp = l_list_used_out;
-        uint64_t l_value_to_items = 0; // how many coins to transfer
-        while(l_list_tmp) {
-            list_used_item_t *item = l_list_tmp->data;
-            if(dap_chain_datum_tx_add_in_item(&l_tx, &item->tx_hash_fast, item->num_idx_out) == 1) {
-                l_value_to_items += item->value;
-            }
-            l_list_tmp = dap_list_next(l_list_tmp);
-        }
-        assert(l_value_to_items == l_value_transfer);
-        dap_list_free_full(l_list_used_out, free);
-    }
-    // add 'out_cond' and 'out' items
-    {
-        uint64_t l_value_pack = 0; // how much coin add to 'out' items
-        if(dap_chain_datum_tx_add_out_cond_item(&l_tx, a_key_cond, (dap_chain_addr_t*) a_addr_cond, a_value, a_cond,
-                a_cond_size) == 1) {
-            l_value_pack += a_value;
-            // transaction fee
-            if(a_addr_fee) {
-                if(dap_chain_datum_tx_add_out_item(&l_tx, a_addr_fee, a_value_fee) == 1)
-                    l_value_pack += a_value_fee;
-            }
-        }
-        // coin back
-        uint64_t l_value_back = l_value_transfer - l_value_pack;
-        if(l_value_back) {
-            if(dap_chain_datum_tx_add_out_item(&l_tx, a_addr_from, l_value_back) != 1) {
-                dap_chain_datum_tx_delete(l_tx);
-                return -1;
-            }
-        }
-    }
-
-    // add 'sign' items
-    if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_from) != 1) {
-        dap_chain_datum_tx_delete(l_tx);
-        return -1;
-    }
-
-    size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx);
-    dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, l_tx_size);
-
-    dap_chain_hash_fast_t l_key_hash;
-    dap_hash_fast(l_tx, l_tx_size, &l_key_hash);
-    DAP_DELETE(l_tx);
-
-    char * l_key_str = dap_chain_hash_fast_to_str_new(&l_key_hash);
-    if(dap_chain_global_db_gr_set(dap_strdup(l_key_str), (uint8_t *) l_datum, dap_chain_datum_size(l_datum)
-            , c_dap_datum_mempool_gdb_group)) {
-        log_it(L_NOTICE, "Transaction %s placed in mempool", l_key_str);
-        // add transaction to ledger
-        if(dap_chain_ledger_tx_add((dap_chain_datum_tx_t*) l_datum->data) < 0)
-            log_it(L_ERROR, "Transaction %s not placed in LEDGER", l_key_str);
-    }
-    DAP_DELETE(l_key_str);*/
-
-    return 0;
-}
-
 uint8_t* dap_datum_mempool_serialize(dap_datum_mempool_t *datum_mempool, size_t *size)
 {
     size_t a_request_size = 2 * sizeof(uint16_t), shift_size = 0;
diff --git a/modules/mempool/include/dap_chain_mempool.h b/modules/mempool/include/dap_chain_mempool.h
index 0e8b0be25b..cc701e21f2 100644
--- a/modules/mempool/include/dap_chain_mempool.h
+++ b/modules/mempool/include/dap_chain_mempool.h
@@ -51,21 +51,14 @@ dap_hash_fast_t*  dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key
         uint64_t a_value, uint64_t a_value_fee);
 
 // Make transfer transaction & insert to cache
-dap_chain_hash_fast_t* dap_chain_proc_tx_create_cond(dap_chain_net_t * a_net,
-        dap_enc_key_t *a_key_from, dap_enc_key_t *a_key_cond,
-        const dap_chain_addr_t* a_addr_from,
-        const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
-        uint64_t a_value,uint64_t a_value_per_unit_max, dap_chain_net_srv_price_unit_uid_t a_unit,
-        dap_chain_net_srv_uid_t a_srv_uid, uint64_t a_value_fee, const void *a_cond, size_t a_cond_size);
 dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond(dap_chain_net_t * a_net,
-        dap_enc_key_t *a_key_from, dap_enc_key_t *a_key_cond,
-        const dap_chain_addr_t* a_addr_from,
+        dap_enc_key_t *a_key_from, dap_pkey_t *a_key_cond,
         const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
-        uint64_t a_value,uint64_t a_value_per_unit_max, dap_chain_net_srv_price_unit_uid_t a_unit,
+        uint64_t a_value, uint64_t a_value_per_unit_max, dap_chain_net_srv_price_unit_uid_t a_unit,
         dap_chain_net_srv_uid_t a_srv_uid, uint64_t a_value_fee, const void *a_cond, size_t a_cond_size);
 
-dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t * a_net,dap_chain_hash_fast_t *a_tx_prev_hash,
-        const dap_chain_addr_t* a_addr_to, dap_enc_key_t * l_key_tx_sign, dap_chain_datum_tx_receipt_t * l_receipt, size_t l_receipt_size);
+dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t * a_net, dap_chain_hash_fast_t *a_tx_prev_hash,
+        const dap_chain_addr_t* a_addr_to, dap_enc_key_t * a_key_tx_sign, dap_chain_datum_tx_receipt_t * l_receipt);
 
 int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a_key_from,
         const dap_chain_addr_t* a_addr_from, const dap_chain_addr_t* a_addr_to,
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 5a1e291f5c..1c058b6e83 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -1442,7 +1442,7 @@ void s_set_reply_text_node_status(char **a_str_reply, dap_chain_net_t * a_net){
  * @return true 
  * @return false 
  */
-bool s_chain_net_ledger_cache_reload(dap_chain_net_t *l_net)
+void s_chain_net_ledger_cache_reload(dap_chain_net_t *l_net)
 {
     dap_chain_ledger_purge(l_net->pub.ledger, false);
     dap_chain_t *l_chain;
@@ -2458,9 +2458,9 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx)
             case NODE_ROLE_LIGHT:
             default:
                 log_it(L_INFO,"Light node role established");
-
         }
-
+        if (!l_net_pvt->only_static_links)
+            l_net_pvt->only_static_links = dap_config_get_item_bool_default(l_cfg, "general", "static_links_only", false);
         if (s_seed_mode || !dap_config_get_item_bool_default(g_config ,"general", "auto_online",false ) ) { // If we seed we do everything manual. First think - prefil list of node_addrs and its aliases
             l_target_state = NET_STATE_OFFLINE;
         }
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index 40159b3fc9..8d70b8514e 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -1083,8 +1083,8 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
     dap_chain_node_cli_cmd_item_create ("tx_create", com_tx_create, "Make transaction",
             "tx_create -net <net name> -chain <chain name> -from_wallet <name> -to_addr <addr> -token <token ticker> -value <value> [-fee <addr> -value_fee <val>]\n" );
     dap_chain_node_cli_cmd_item_create ("tx_cond_create", com_tx_cond_create, "Make cond transaction",
-            "tx_cond_create -net <net name> -token <token_ticker> -wallet_f <wallet_from> -wallet_t <wallet_to>"
-                                        "-value <value_datoshi> -unit <mb|kb|b|sec|day> -service <vpn>\n" );
+            "tx_cond_create -net <net name> -token <token ticker> -wallet <from wallet> -cert <public cert>"
+                                        "-value <value datoshi> -unit <mb | kb | b | sec | day> -srv_uid <numeric uid>\n" );
     dap_chain_node_cli_cmd_item_create ("tx_verify", com_tx_verify, "Verifing transaction in mempool",
             "tx_verify -net <net name> -chain <chain name> -tx <tx_hash>\n" );
 
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index cb98b415db..ed77f43c7f 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -3505,12 +3505,12 @@ int com_tx_cond_create(int a_argc, char ** a_argv, char **a_str_reply)
     int arg_index = 1;
     const char *c_wallets_path = dap_chain_wallet_get_path(g_config);
     const char * l_token_ticker = NULL;
-    const char * l_wallet_from_str = NULL;
-    const char * l_wallet_to_str = NULL; //l_addr_to_str
+    const char * l_wallet_str = NULL;
+    const char * l_cert_str = NULL; //l_addr_to_str
     const char * l_value_datoshi_str = NULL;
     const char * l_net_name = NULL;
     const char * l_unit_str = NULL;
-    const char * l_service_str = NULL;
+    const char * l_srv_uid_str = NULL;
     uint64_t l_value_datoshi = 0;
 
     const char * l_hash_out_type = NULL;
@@ -3518,16 +3518,16 @@ int com_tx_cond_create(int a_argc, char ** a_argv, char **a_str_reply)
     if(!l_hash_out_type)
         l_hash_out_type = "hex";
     if(dap_strcmp(l_hash_out_type,"hex") && dap_strcmp(l_hash_out_type,"base58")) {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "invalid parameter -H, valid values: -H <hex | base58>");
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Invalid parameter -H, valid values: -H <hex | base58>");
         return -1;
     }
 
     // Token ticker
     dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-token", &l_token_ticker);
     // Wallet name - from
-    dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-wallet_f", &l_wallet_from_str);
+    dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-wallet", &l_wallet_str);
     // Wallet address - to
-    dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-wallet_t", &l_wallet_to_str);
+    dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-cert", &l_cert_str);
     // value datoshi
     dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-value", &l_value_datoshi_str);
     // net
@@ -3535,18 +3535,18 @@ int com_tx_cond_create(int a_argc, char ** a_argv, char **a_str_reply)
     // unit
     dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-unit", &l_unit_str);
     // service
-    dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-service", &l_service_str);
+    dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "-srv_uid", &l_srv_uid_str);
 
     if(!l_token_ticker) {
         dap_chain_node_cli_set_reply_text(a_str_reply, "tx_cond_create requires parameter '-token'");
         return -1;
     }
-    if(!l_wallet_from_str) {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "tx_cond_create requires parameter '-wallet_f'");
+    if(!l_wallet_str) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "tx_cond_create requires parameter '-wallet'");
         return -2;
     }
-    if(!l_wallet_to_str) {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "tx_cond_create requires parameter '-wallet_t'");
+    if(!l_cert_str) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "tx_cond_create requires parameter '-cert'");
         return -3;
     }
     if(!l_value_datoshi_str) {
@@ -3562,17 +3562,14 @@ int com_tx_cond_create(int a_argc, char ** a_argv, char **a_str_reply)
         dap_chain_node_cli_set_reply_text(a_str_reply, "tx_cond_create requires parameter '-unit={mb|kb|b|sec|day}'");
         return -6;
     }
-    if(!l_service_str) {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "tx_cond_create requires parameter '-service={vpn}'");
+    if(!l_srv_uid_str) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "tx_cond_create requires parameter '-srv_uid'");
         return -7;
     }
     dap_chain_net_srv_uid_t l_srv_uid = {};
-    if(!dap_strcmp(l_service_str, "vpn"))
-        l_srv_uid.uint64 = 0x0000000000000001;
-    //dap_chain_addr_t *addr_to = dap_chain_addr_from_str(l_addr_to_str);
+    l_srv_uid.uint64 = l_value_datoshi = strtoll(l_srv_uid_str, NULL, 10);
     if(!l_srv_uid.uint64) {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "can't recognize service='%s' unit must look like {vpn}",
-                l_service_str);
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Can't find service UID %s ", l_srv_uid_str);
         return -8;
     }
 
@@ -3589,58 +3586,46 @@ int com_tx_cond_create(int a_argc, char ** a_argv, char **a_str_reply)
         l_price_unit.enm = SERV_UNIT_B;
 
     if(l_price_unit.enm == SERV_UNIT_UNDEFINED) {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "can't recognize unit='%s' unit must look like {mb|kb|b|sec|day}",
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Can't recognize unit='%s' unit must look like {mb|kb|b|sec|day}",
                 l_unit_str);
         return -9;
     }
 
     l_value_datoshi = strtoll(l_value_datoshi_str, NULL, 10);
     if(!l_value_datoshi) {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "can't recognize value='%s' as a number", l_value_datoshi_str);
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Can't recognize value='%s' as a number", l_value_datoshi_str);
         return -10;
     }
 
     dap_chain_net_t * l_net = l_net_name ? dap_chain_net_by_name(l_net_name) : NULL;
     if(!l_net) {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "can't find net '%s'", l_net_name);
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Can't find net '%s'", l_net_name);
         return -11;
     }
-    dap_chain_wallet_t *l_wallet_from = dap_chain_wallet_open(l_wallet_from_str, c_wallets_path);
-    if(!l_wallet_from) {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "can't open wallet '%s'", l_wallet_from);
+    dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, c_wallets_path);
+    if(!l_wallet) {
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Can't open wallet '%s'", l_wallet);
         return -12;
     }
-    dap_chain_wallet_t *l_wallet_cond = dap_chain_wallet_open(l_wallet_to_str, c_wallets_path);
-    if(!l_wallet_to_str) {
-        dap_chain_wallet_close(l_wallet_from);
-        dap_chain_node_cli_set_reply_text(a_str_reply, "can't open wallet '%s'", l_wallet_to_str);
+    dap_cert_t *l_cert_cond = dap_cert_find_by_name(l_cert_str);
+    if(!l_cert_cond) {
+        dap_chain_wallet_close(l_wallet);
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Can't find cert '%s'", l_cert_str);
         return -13;
     }
-    dap_enc_key_t *l_key_from = dap_chain_wallet_get_key(l_wallet_from, 0);
-    dap_enc_key_t *l_key_cond = dap_chain_wallet_get_key(l_wallet_cond, 0);
-
-
-    // where to take coins for service
-    const dap_chain_addr_t *l_addr_from = dap_chain_wallet_get_addr(l_wallet_from, l_net->pub.id);
-    // who will be use service, usually the same address (addr_from)
-    //const dap_chain_addr_t *l_addr_cond = dap_chain_wallet_get_addr(l_wallet_cond, l_net->pub.id);
-
-
-/*    //dap_chain_net_srv_abstract_t l_cond;
-//    dap_chain_net_srv_abstract_set(&l_cond, SERV_CLASS_PERMANENT, SERV_ID_VPN, l_value, SERV_UNIT_MB,
-//            "test vpn service");
-//    dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name((const char *) c_net_name);
-
-    int res = dap_chain_mempool_tx_create_cond(NULL, l_key, l_key_cond, addr_from,
-            addr_cond,
-            NULL, l_token_ticker, l_value, 0, (const void*) &l_cond, sizeof(dap_chain_net_srv_abstract_t));
-*/
+    dap_enc_key_t *l_key_from = dap_chain_wallet_get_key(l_wallet, 0);
+    dap_pkey_t *l_key_cond = dap_pkey_from_enc_key(l_cert_cond->enc_key);
+    if (!l_key_cond) {
+        dap_chain_wallet_close(l_wallet);
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Cert '%s' doesn't contain a valid public key", l_cert_str);
+        return -14;
+    }
 
-    dap_chain_hash_fast_t *l_tx_cond_hash = dap_chain_mempool_tx_create_cond(l_net, l_key_from, l_key_cond, l_addr_from, l_token_ticker,
-            l_value_datoshi, 0, l_price_unit, l_srv_uid, 0, NULL, 0);
+    dap_chain_hash_fast_t *l_tx_cond_hash = dap_chain_mempool_tx_create_cond(l_net, l_key_from, l_key_cond, l_token_ticker,
+                                                                             l_value_datoshi, 0, l_price_unit, l_srv_uid, 0, NULL, 0);
 
-    dap_chain_wallet_close(l_wallet_from);
-    dap_chain_wallet_close(l_wallet_cond);
+    dap_chain_wallet_close(l_wallet);
+    DAP_DELETE(l_key_cond);
 
     char *l_hash_str;
     if(!dap_strcmp(l_hash_out_type, "hex")) {
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index ba3502ec18..a31617d2f2 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -197,8 +197,8 @@ static bool s_dap_chain_datum_tx_out_data(dap_chain_datum_tx_t *a_datum,
             break;
         case TX_ITEM_TYPE_RECEIPT:
             dap_string_append_printf(a_str_out, "\t Receipt:\n"
-                                                "\t\t size: %u\n"
-                                                "\t\t ext size:%u\n"
+                                                "\t\t size: %"DAP_UINT64_FORMAT_U"\n"
+                                                "\t\t ext size: %"DAP_UINT64_FORMAT_U"\n"
                                                 "\t\t Info:"
                                                 "\t\t\t   units: 0x%016"DAP_UINT64_FORMAT_x"\n"
                                                 "\t\t\t   uid: 0x%016"DAP_UINT64_FORMAT_x"\n"
diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c
index 1226334c2a..ebb1c62614 100644
--- a/modules/net/dap_chain_node_client.c
+++ b/modules/net/dap_chain_node_client.c
@@ -53,15 +53,12 @@
 #include "dap_timerfd.h"
 #include "dap_hash.h"
 #include "dap_uuid.h"
-//#include "dap_http_client_simple.h"
 #include "dap_client_pvt.h"
 #include "dap_chain_global_db_remote.h"
 #include "dap_chain_global_db_hist.h"
-
 #include "dap_chain.h"
 #include "dap_chain_cell.h"
-
-#include "dap_chain_net_srv_common.h"
+#include "dap_chain_net_srv.h"
 #include "dap_stream_worker.h"
 #include "dap_stream_ch_pkt.h"
 #include "dap_stream_ch_chain.h"
@@ -70,8 +67,6 @@
 #include "dap_stream_ch_chain_net_pkt.h"
 #include "dap_stream_ch_chain_net_srv.h"
 #include "dap_stream_pkt.h"
-
-//#include "dap_chain_common.h"
 #include "dap_chain_node_client.h"
 
 #define LOG_TAG "dap_chain_node_client"
@@ -98,7 +93,7 @@ static void s_ch_chain_callback_notify_packet_in(dap_stream_ch_chain_t* a_ch_cha
 static bool dap_chain_node_client_connect_internal(dap_chain_node_client_t *a_node_client, const char *a_active_channels);
 
 bool s_stream_ch_chain_debug_more = false;
-uint32_t s_timer_update_states=60;
+uint32_t s_timer_update_states = 1200;
 
 /**
  * @brief dap_chain_node_client_init
@@ -107,7 +102,7 @@ uint32_t s_timer_update_states=60;
 int dap_chain_node_client_init(void)
 {
     s_stream_ch_chain_debug_more = dap_config_get_item_bool_default(g_config,"stream_ch_chain","debug_more",false);
-    s_timer_update_states = dap_config_get_item_uint32_default(g_config,"node_client","timer_update_states",60);
+    s_timer_update_states = dap_config_get_item_uint32_default(g_config, "node_client","timer_update_states", s_timer_update_states);
     return 0;
 }
 
@@ -485,19 +480,19 @@ static void s_ch_chain_callback_notify_packet_in(dap_stream_ch_chain_t* a_ch_cha
             if (l_node_client->cur_cell)
                 l_cell_id = l_node_client->cur_cell->id;
             // Check if we have some more chains and cells in it to sync
+            dap_chain_node_addr_t l_node_addr;
+            l_node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net);
             if( l_node_client->cur_chain ){
                 l_chain_id=l_node_client->cur_chain->id;
                 if (s_stream_ch_chain_debug_more) {
-                    dap_chain_node_addr_t * l_node_addr = dap_chain_net_get_cur_addr(l_net);
                     log_it(L_INFO,"In: Link %s."NODE_ADDR_FP_STR" started to sync %s chain",l_net->pub.name,
-                           NODE_ADDR_FP_ARGS(l_node_addr), l_node_client->cur_chain->name );
+                           NODE_ADDR_FP_ARGS_S(l_node_addr), l_node_client->cur_chain->name );
                 }
                 dap_stream_ch_chain_pkt_write_unsafe(l_node_client->ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_REQ,
                                                      l_net->pub.id.uint64 ,
                                                      l_chain_id.uint64,l_cell_id.uint64,NULL,0);
             }else{ // If no - over with sync process
-                dap_chain_node_addr_t *l_node_addr = dap_chain_net_get_cur_addr(l_net);
-                log_it(L_INFO, "In: State node %s."NODE_ADDR_FP_STR" is SYNCED",l_net->pub.name, NODE_ADDR_FP_ARGS(l_node_addr) );
+                log_it(L_INFO, "In: State node %s."NODE_ADDR_FP_STR" is SYNCED",l_net->pub.name, NODE_ADDR_FP_ARGS_S(l_node_addr) );
                 bool l_have_waiting = dap_chain_net_sync_unlock(l_net, l_node_client);
                 l_node_client->state = NODE_CLIENT_STATE_SYNCED;
                 if (dap_chain_net_get_target_state(l_net) == NET_STATE_ONLINE)
diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c
index c6460868eb..6e61ace127 100644
--- a/modules/net/srv/dap_chain_net_srv.c
+++ b/modules/net/srv/dap_chain_net_srv.c
@@ -593,6 +593,23 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
     return ret;
 }
 
+bool dap_chain_net_srv_pay_verificator(dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner)
+{
+    if (!a_owner)
+        return false;
+    dap_chain_datum_tx_receipt_t *l_receipt = (dap_chain_datum_tx_receipt_t *)
+                                               dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_RECEIPT, NULL);
+    if (!l_receipt)
+        return false;
+    dap_sign_t *l_sign = dap_chain_datum_tx_receipt_sign_get(l_receipt, l_receipt->size, 1);
+    if (!l_sign)
+        return false;
+    dap_hash_fast_t l_pkey_hash;
+    if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash))
+        return false;
+    return dap_hash_fast_compare(&l_pkey_hash, &a_cond->subtype.srv_pay.pkey_hash);
+}
+
 /**
  * @brief dap_chain_net_srv_add
  * @param a_uid
@@ -601,10 +618,13 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
  * @param a_callback_response_error
  * @return
  */
-dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid,dap_chain_net_srv_callback_data_t a_callback_request,
+dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid,
+                                           const char *a_config_section,
+                                           dap_chain_net_srv_callback_data_t a_callback_request,
                                            dap_chain_net_srv_callback_data_t a_callback_response_success,
                                            dap_chain_net_srv_callback_data_t a_callback_response_error,
-                                           dap_chain_net_srv_callback_data_t a_callback_receipt_next_success)
+                                           dap_chain_net_srv_callback_data_t a_callback_receipt_next_success,
+                                           dap_chain_net_srv_callback_custom_data_t a_callback_custom_data)
 {
     service_list_t *l_sdata = NULL;
     dap_chain_net_srv_t * l_srv = NULL;
@@ -618,10 +638,87 @@ dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid,dap_cha
         l_srv->callback_response_success = a_callback_response_success;
         l_srv->callback_response_error = a_callback_response_error;
         l_srv->callback_receipt_next_success = a_callback_receipt_next_success;
+        l_srv->callback_custom_data = a_callback_custom_data;
         pthread_mutex_init(&l_srv->banlist_mutex, NULL);
         l_sdata = DAP_NEW_Z(service_list_t);
         memcpy(&l_sdata->uid, &l_uid, sizeof(l_uid));
         l_sdata->srv = l_srv;
+        if (a_config_section) {
+            l_srv->grace_period = dap_config_get_item_uint32_default(g_config, a_config_section, "grace_period", 60);
+            //! IMPORTANT ! This fetch is single-action and cannot be further reused, since it modifies the stored config data
+            //! it also must NOT be freed within this module !
+            uint16_t l_pricelist_count = 0;
+            char **l_pricelist = dap_config_get_array_str(g_config, a_config_section, "pricelist", &l_pricelist_count); // must not be freed!
+            for (uint16_t i = 0; i < l_pricelist_count; i++) {
+                dap_chain_net_srv_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_price_t);
+                short l_iter = 0;
+                char *l_ctx;
+                for (char *l_price_token = strtok_r(l_pricelist[i], ":", &l_ctx); l_price_token || l_iter == 6; l_price_token = strtok_r(NULL, ":", &l_ctx), ++l_iter) {
+                    //log_it(L_DEBUG, "Tokenizer: %s", l_price_token);
+                    switch (l_iter) {
+                    case 0:
+                        l_price->net_name = l_price_token;
+                        if (!(l_price->net = dap_chain_net_by_name(l_price->net_name))) {
+                            log_it(L_ERROR, "Error parsing pricelist: can't find network \"%s\"", l_price_token);
+                            DAP_DELETE(l_price);
+                            break;
+                        }
+                        continue;
+                    case 1:
+                        l_price->value_datoshi = dap_chain_uint128_to(dap_chain_coins_to_balance(l_price_token));
+                        if (!l_price->value_datoshi) {
+                            log_it(L_ERROR, "Error parsing pricelist: text on 2nd position \"%s\" is not floating number", l_price_token);
+                            l_iter = 0;
+                            DAP_DELETE(l_price);
+                            break;
+                        }
+                        continue;
+                    case 2:
+                        dap_stpcpy(l_price->token, l_price_token);
+                        continue;
+                    case 3:
+                        l_price->units = strtoul(l_price_token, NULL, 10);
+                        if (!l_price->units) {
+                            log_it(L_ERROR, "Error parsing pricelist: text on 4th position \"%s\" is not unsigned integer", l_price_token);
+                            l_iter = 0;
+                            DAP_DELETE(l_price);
+                            break;
+                        }
+                        continue;
+                    case 4:
+                        if (!strcmp(l_price_token,      "SEC"))
+                            l_price->units_uid.enm = SERV_UNIT_SEC;
+                        else if (!strcmp(l_price_token, "DAY"))
+                            l_price->units_uid.enm = SERV_UNIT_DAY;
+                        else if (!strcmp(l_price_token, "MB"))
+                            l_price->units_uid.enm = SERV_UNIT_MB;
+                        else {
+                            log_it(L_ERROR, "Error parsing pricelist: wrong unit type \"%s\"", l_price_token);
+                            l_iter = 0;
+                            DAP_DELETE(l_price);
+                            break;
+                        }
+                        continue;
+                    case 5:
+                        if (!(l_price->wallet = dap_chain_wallet_open(l_price_token, dap_config_get_item_str_default(g_config, "resources", "wallets_path", NULL)))) {
+                            log_it(L_ERROR, "Error parsing pricelist: can't open wallet \"%s\"", l_price_token);
+                            l_iter = 0;
+                            DAP_DELETE(l_price);
+                            break;
+                        }
+                        continue;
+                    case 6:
+                        log_it(L_INFO, "Price item correct, added to service");
+                        DL_APPEND(l_srv->pricelist, l_price);
+                        break;
+                    default:
+                        break;
+                    }
+                    log_it(L_DEBUG, "Done with price item %d", i);
+                    break; // double break exits tokenizer loop and steps to next price item
+                }
+            }
+        }
         HASH_ADD(hh, s_srv_list, uid, sizeof(l_srv->uid), l_sdata);
     }else{
         log_it(L_ERROR, "Already present service with 0x%016"DAP_UINT64_FORMAT_X, a_uid.uint64);
@@ -642,10 +739,8 @@ dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid,dap_cha
  */
 int dap_chain_net_srv_set_ch_callbacks(dap_chain_net_srv_uid_t a_uid,
                                        dap_chain_net_srv_callback_ch_t a_callback_stream_ch_opened,
-                                       dap_chain_net_srv_callback_data_t a_callback_stream_ch_read,
-                                       dap_chain_net_srv_callback_data_with_out_data_t a_callback_stream_ch_read_with_out_data,
-                                       dap_chain_net_srv_callback_ch_t a_callback_stream_ch_write,
-                                       dap_chain_net_srv_callback_ch_t a_callback_stream_ch_closed
+                                       dap_chain_net_srv_callback_ch_t a_callback_stream_ch_closed,
+                                       dap_chain_net_srv_callback_ch_t a_callback_stream_ch_write
                                        )
 {
     service_list_t *l_sdata = NULL;
@@ -658,10 +753,8 @@ int dap_chain_net_srv_set_ch_callbacks(dap_chain_net_srv_uid_t a_uid,
     if( l_sdata ) {
         l_srv = l_sdata->srv;
         l_srv->callback_stream_ch_opened = a_callback_stream_ch_opened;
-        l_srv->callback_stream_ch_read = a_callback_stream_ch_read;
-        l_srv->callback_stream_ch_read_with_out_data = a_callback_stream_ch_read_with_out_data;
-        l_srv->callback_stream_ch_write = a_callback_stream_ch_write;
         l_srv->callback_stream_ch_closed = a_callback_stream_ch_closed;
+        l_srv->callback_stream_ch_write = a_callback_stream_ch_write;
     }else{
         log_it(L_ERROR, "Can't find service with 0x%016"DAP_UINT64_FORMAT_X, a_uid.uint64);
         l_ret= -1;
@@ -830,23 +923,13 @@ const dap_chain_net_srv_uid_t * dap_chain_net_srv_list(void)
  * @return
  */
 dap_chain_datum_tx_receipt_t * dap_chain_net_srv_issue_receipt(dap_chain_net_srv_t *a_srv,
-                dap_chain_net_srv_usage_t * a_usage,
-                dap_chain_net_srv_price_t * a_price,
-                const void * a_ext, size_t a_ext_size
-                )
+                                                               dap_chain_net_srv_price_t * a_price,
+                                                               const void * a_ext, size_t a_ext_size)
 {
     dap_chain_datum_tx_receipt_t * l_receipt = dap_chain_datum_tx_receipt_create(
                     a_srv->uid, a_price->units_uid, a_price->units, a_price->value_datoshi, a_ext, a_ext_size);
-    size_t l_receipt_size = l_receipt->size; // nested receipt plus 8 bits for type
-
     // Sign with our wallet
-    l_receipt_size = dap_chain_datum_tx_receipt_sign_add(&l_receipt,l_receipt_size , dap_chain_wallet_get_key( a_price->wallet,0) );
-
-    a_usage->receipt = l_receipt;
-    a_usage->receipt_size = l_receipt_size;
-    a_usage->wallet = a_price->wallet;
-
-    return  l_receipt;
+    return dap_chain_datum_tx_receipt_sign_add(l_receipt, dap_chain_wallet_get_key(a_price->wallet, 0));
 }
 
 
diff --git a/modules/net/srv/dap_chain_net_srv_client.c b/modules/net/srv/dap_chain_net_srv_client.c
index 0ee137a38b..a597b7db58 100644
--- a/modules/net/srv/dap_chain_net_srv_client.c
+++ b/modules/net/srv/dap_chain_net_srv_client.c
@@ -48,14 +48,14 @@ dap_chain_net_srv_client_t *dap_chain_net_srv_client_create_n_connect(dap_chain_
         .disconnected = s_srv_client_callback_disconnected,
         .delete = s_srv_client_callback_deleted
     };
-    if (a_callbacks && a_callbacks->pkt_in)
-        l_callbacks.srv_pkt_in = a_callbacks->pkt_in;
-    else
-        l_callbacks.srv_pkt_in = (dap_stream_ch_callback_packet_t)s_srv_client_pkt_in;
+    l_callbacks.srv_pkt_in = (dap_stream_ch_callback_packet_t)s_srv_client_pkt_in;
     dap_chain_node_info_t *l_info = DAP_NEW_Z(dap_chain_node_info_t);
     inet_pton(AF_INET, a_addr, &l_info->hdr.ext_addr_v4);
     l_info->hdr.ext_port = a_port;
-    l_ret->node_client = dap_chain_node_client_create_n_connect(a_net, l_info, "R", &l_callbacks, l_ret);
+    const char l_channels[] = {dap_stream_ch_chain_net_srv_get_id(), '\0'};
+    l_ret->node_client = dap_chain_node_client_create_n_connect(a_net, l_info,
+                                                                l_channels,
+                                                                &l_callbacks, l_ret);
     DAP_DELETE(l_info);
     return l_ret;
 }
@@ -64,6 +64,13 @@ ssize_t dap_chain_net_srv_client_write(dap_chain_net_srv_client_t *a_client, uin
 {
     if (!a_client || !a_client->net_client || dap_client_get_stage(a_client->net_client) != STAGE_STREAM_STREAMING)
         return -1;
+    if (a_type == DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST) {
+        dap_stream_ch_t *l_ch = dap_client_get_stream_ch_unsafe(a_client->net_client,
+                                                                dap_stream_ch_chain_net_srv_get_id());
+        dap_stream_ch_chain_net_srv_t *a_ch_chain = DAP_STREAM_CH_CHAIN_NET_SRV(l_ch);
+        dap_stream_ch_chain_net_srv_pkt_request_t *l_request = (dap_stream_ch_chain_net_srv_pkt_request_t *)a_pkt_data;
+        a_ch_chain->srv_uid.uint64 = l_request->hdr.srv_uid.uint64;
+    }
     dap_stream_worker_t *l_stream_worker = dap_client_get_stream_worker(a_client->net_client);
     return dap_stream_ch_pkt_write_mt(l_stream_worker, a_client->ch_uuid, a_type, a_pkt_data, a_pkt_data_size);
 }
@@ -76,17 +83,6 @@ static void s_srv_client_callback_connected(dap_chain_node_client_t *a_node_clie
     l_srv_client->net_client = a_node_client->client;
     if (l_srv_client->callbacks.connected)
         l_srv_client->callbacks.connected(l_srv_client, l_srv_client->callbacks_arg);
-    /*const char *l_test_data = "Sevice test custom data example";
-    int l_test_size = strlen(l_test_data) + 1;
-    size_t l_request_size = l_test_size + sizeof(dap_stream_ch_chain_net_srv_pkt_data_t);
-    dap_stream_ch_chain_net_srv_pkt_data_t *l_request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_data_t, l_request_size);
-    l_request->hdr.version = 1;
-    l_request->hdr.data_size = l_test_size;
-    l_request->hdr.srv_uid.uint64 = 156;
-    memcpy(l_request->data, l_test_data, l_test_size);
-    // dap_hash_fast(l_request->data, l_request->data_size, &l_request->data_hash);
-    dap_chain_net_srv_client_write(l_srv_client, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA, l_request, l_request_size);
-    DAP_DELETE(l_request);*/
 }
 
 static void s_srv_client_callback_disconnected(dap_chain_node_client_t *a_node_client, void *a_arg)
@@ -110,26 +106,83 @@ static void s_srv_client_callback_deleted(dap_chain_node_client_t *a_node_client
 
 static void s_srv_client_pkt_in(dap_stream_ch_chain_net_srv_t *a_ch_chain, uint8_t a_pkt_type, dap_stream_ch_pkt_t *a_pkt, void *a_arg)
 {
-    UNUSED(a_ch_chain);
     dap_chain_net_srv_client_t *l_srv_client = (dap_chain_net_srv_client_t *)a_arg;
-    UNUSED(l_srv_client);
     switch (a_pkt_type) {
     case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE: {
-            dap_stream_ch_chain_net_srv_pkt_test_t *l_request = (dap_stream_ch_chain_net_srv_pkt_test_t *)a_pkt->data;
-            size_t l_request_size = l_request->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t);
-            if(a_pkt->hdr.size != l_request_size) {
-                log_it(L_WARNING, "Wrong request size, less or more than required");
-                break;
+        dap_stream_ch_chain_net_srv_pkt_test_t *l_response = (dap_stream_ch_chain_net_srv_pkt_test_t *)a_pkt->data;
+        size_t l_response_size = l_response->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t);
+        if (a_pkt->hdr.size != l_response_size) {
+            log_it(L_WARNING, "Wrong response size %u, required %zu", a_pkt->hdr.size, l_response_size);
+            if (l_srv_client->callbacks.error)
+                l_srv_client->callbacks.error(l_srv_client,
+                                              DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_SIZE,
+                                              l_srv_client->callbacks_arg);
+            break;
+        }
+        struct timeval l_recv_time;
+        gettimeofday(&l_recv_time, NULL);
+        l_response->recv_time1 = l_recv_time;
+        dap_chain_hash_fast_t l_data_hash;
+        dap_hash_fast(l_response->data, l_response->data_size, &l_data_hash);
+        if (!dap_hash_fast_compare(&l_data_hash, &l_response->data_hash)) {
+            if (l_srv_client->callbacks.error)
+                l_srv_client->callbacks.error(l_srv_client,
+                                              DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_HASH,
+                                              l_srv_client->callbacks_arg);
+            break;
+        }
+        if (l_srv_client->callbacks.check)
+            l_srv_client->callbacks.check(l_srv_client, l_response, l_srv_client->callbacks_arg);
+    } break;
+    case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST: {
+        log_it(L_NOTICE, "Requested receipt to sign");
+        dap_chain_datum_tx_receipt_t *l_receipt = (dap_chain_datum_tx_receipt_t *)a_pkt->data;
+        if (a_pkt->hdr.size != l_receipt->size) {
+            log_it(L_WARNING, "Wrong response size %u, required %"DAP_UINT64_FORMAT_U, a_pkt->hdr.size, l_receipt->size);
+            if (l_srv_client->callbacks.error)
+                l_srv_client->callbacks.error(l_srv_client,
+                                              DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_SIZE,
+                                              l_srv_client->callbacks_arg);
+            break;
+        }
+        if (l_srv_client->callbacks.sign) {
+            // Duplicate receipt for realloc can be applied
+            dap_chain_datum_tx_receipt_t *l_rec_cpy = DAP_DUP_SIZE(l_receipt, l_receipt->size);
+            // Sign receipt     
+            l_rec_cpy = l_srv_client->callbacks.sign(l_srv_client, l_rec_cpy, l_srv_client->callbacks_arg);
+            if (l_rec_cpy) {
+                dap_stream_ch_pkt_write_unsafe(a_ch_chain->ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE,
+                                               l_rec_cpy, l_rec_cpy->size);
+                DAP_DELETE(l_rec_cpy);
+            } else {
+                log_it(L_ERROR, "Problem with receipt signing, callback.sign returned NULL");
             }
-            log_it(L_INFO, "Service client check request success!");
-        } break;
-    case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE:
-    case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS:
-    case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR:
-        break;
-    case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA: {
+        }
+    } break;
+    case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS: {
+        log_it( L_NOTICE, "Responsed with success");
+        dap_stream_ch_chain_net_srv_pkt_success_t *l_success = (dap_stream_ch_chain_net_srv_pkt_success_t *)a_pkt->data;
+        size_t l_success_size = a_pkt->hdr.size;
+        if (l_srv_client->callbacks.success) {
+            l_srv_client->callbacks.success(l_srv_client, l_success, l_success_size, l_srv_client->callbacks_arg);
+        }
+    } break;
+    case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR: {
+       if (a_pkt->hdr.size == sizeof (dap_stream_ch_chain_net_srv_pkt_error_t)) {
+            dap_stream_ch_chain_net_srv_pkt_error_t *l_err = (dap_stream_ch_chain_net_srv_pkt_error_t *)a_pkt->data;
+            log_it(L_WARNING, "Remote responsed with error code 0x%08X", l_err->code);
+            if (l_srv_client->callbacks.error)
+                l_srv_client->callbacks.error(l_srv_client, l_err->code, l_srv_client->callbacks_arg);
+        } else {
+            log_it(L_ERROR, "Wrong error response size, %u when expected %zu", a_pkt->hdr.size,
+                   sizeof ( dap_stream_ch_chain_net_srv_pkt_error_t) );
+        }
+    } break;
+    case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_DATA: {
         dap_stream_ch_chain_net_srv_pkt_data_t *l_response = (dap_stream_ch_chain_net_srv_pkt_data_t *)a_pkt->data;
-        log_it(L_INFO, "Service client respose with data '%s'", l_response->data);
+        log_it(L_DEBUG, "Service client got custom data response");
+        if (l_srv_client->callbacks.data)
+            l_srv_client->callbacks.data(l_srv_client, l_response->data, l_response->hdr.data_size, l_srv_client->callbacks_arg);
     }
     default:
         break;
diff --git a/modules/net/srv/dap_chain_net_srv_common.c b/modules/net/srv/dap_chain_net_srv_common.c
deleted file mode 100644
index 457980cecd..0000000000
--- a/modules/net/srv/dap_chain_net_srv_common.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Authors:
- * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
- * Aleksandr Lysikov <alexander.lysikov@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * Kelvin Project https://github.com/kelvinblockchain
- * Copyright  (c) 2019
- * All rights reserved.
-
- This file is part of DAP (Deus Applications Prototypes) the open source project
-
- DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- DAP is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef WIN32
-#include <winsock2.h>
-#include <windows.h>
-#include <mswsock.h>
-#include <ws2tcpip.h>
-#include <io.h>
-#endif
-
-#include <pthread.h>
-
-#include "dap_strfuncs.h"
-#include "rand/dap_rand.h"
-#include "dap_chain_datum_tx_items.h"
-#include "dap_stream.h"
-#include "dap_chain_net_srv_common.h"
-#include "dap_chain_net_srv.h"
-/*
- * Init service client
- * l_uid service id
- * a_callback_client_success callback to start client service
- */
-//
-int dap_chain_net_srv_remote_init(dap_chain_net_srv_uid_t a_uid,
-        dap_chain_net_srv_callback_data_t a_callback_request,
-        dap_chain_net_srv_callback_data_t a_callback_response_success,
-        dap_chain_net_srv_callback_data_t a_callback_response_error,
-        dap_chain_net_srv_callback_data_t a_callback_receipt_next_success,
-        dap_chain_net_srv_callback_data_t a_callback_client_success,
-        dap_chain_net_srv_callback_sign_request_t a_callback_client_sign_request,
-        void *a_inhertor)
-{
-    dap_chain_net_srv_t *l_srv_custom = dap_chain_net_srv_get(a_uid);
-    if(!l_srv_custom) {
-        l_srv_custom = dap_chain_net_srv_add(a_uid, a_callback_request,
-                a_callback_response_success, a_callback_response_error,
-                a_callback_receipt_next_success);
-    }
-    l_srv_custom->callback_client_success = a_callback_client_success;
-    l_srv_custom->callback_client_sign_request = a_callback_client_sign_request;
-    if(a_inhertor)
-        l_srv_custom->_inhertor = a_inhertor;
-    return 0;
-}
-
-
diff --git a/modules/net/srv/dap_chain_net_srv_stream_session.c b/modules/net/srv/dap_chain_net_srv_stream_session.c
index 3a2763bd69..e72e03bad1 100644
--- a/modules/net/srv/dap_chain_net_srv_stream_session.c
+++ b/modules/net/srv/dap_chain_net_srv_stream_session.c
@@ -59,7 +59,6 @@ dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_add (dap_chain_net_srv_stream
 {
     if ( a_srv_session && a_net && a_srv ){
         dap_chain_net_srv_usage_t * l_ret = DAP_NEW_Z(dap_chain_net_srv_usage_t);
-        //l_ret->id = 666;
         randombytes(&l_ret->id, sizeof(l_ret->id));
         l_ret->net = a_net;
         l_ret->service = a_srv;
diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h
index 9844e08c6f..43d3795173 100755
--- a/modules/net/srv/include/dap_chain_net_srv.h
+++ b/modules/net/srv/include/dap_chain_net_srv.h
@@ -24,17 +24,188 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 */
 #pragma once
 
+#include "dap_chain_net.h"
+#include "dap_chain_net_remote.h"
+#include "dap_chain_wallet.h"
+#include "dap_common.h"
 #include "dap_config.h"
-#include "dap_chain_net_srv_common.h"
-#include "dap_chain_net_srv_client.h"
-#include "dap_chain_net_srv_stream_session.h"
+#include "dap_stream_ch.h"
+
+//Service direction
+enum dap_chain_net_srv_order_direction{
+    SERV_DIR_BUY = 1,
+    SERV_DIR_SELL = 2,
+    SERV_DIR_UNDEFINED = 0
+};
+typedef byte_t dap_chain_net_srv_order_direction_t;
+
+
+typedef struct dap_chain_net_srv_abstract
+{
+    uint8_t class; //Class of service (once or permanent)
+    dap_chain_net_srv_uid_t type_id; //Type of service
+    union {
+        struct {
+            int bandwith;
+            int abuse_resistant;
+            size_t limit_bytes;
+        } vpn;
+        /*struct {
+         int value;
+         } another_srv;*/
+    } proposal_params;
+
+    //size_t pub_key_data_size;
+    //void * pub_key_data;
+
+    uint64_t price; //  service price, for SERV_CLASS_ONCE ONCE for the whole service, for SERV_CLASS_PERMANENT  for one unit.
+    uint8_t price_units; // Unit of service (seconds, megabytes, etc.) Only for SERV_CLASS_PERMANENT
+    char decription[128];
+}DAP_ALIGN_PACKED dap_chain_net_srv_abstract_t;
+
+typedef void (*dap_chain_callback_trafic_t)(dap_events_socket_t *, dap_stream_ch_t *);
+
+typedef struct dap_chain_net_srv_price
+{
+    dap_chain_wallet_t * wallet;
+    char * net_name;
+    dap_chain_net_t * net;
+    uint64_t value_datoshi;
+    char token[DAP_CHAIN_TICKER_SIZE_MAX];
+    uint64_t units;
+    dap_chain_net_srv_price_unit_uid_t units_uid;
+    struct dap_chain_net_srv_price * next;
+    struct dap_chain_net_srv_price * prev;
+} dap_chain_net_srv_price_t;
+
+// Ch pkt types
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST                       0x01
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST                  0x10
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE                 0x11
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED                0x20
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA                          0x30
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_DATA                 0x31
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS              0xf0
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR                0xff
+// for connection testing
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST                 0x40
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE                0x41
+
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_UNDEFINED                  0x00000000
+
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND          0x00000100
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_CH_NOT_FOUND       0x00000101
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_IN_CLIENT_MODE     0x00000102
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NOT_FOUND          0x00000200
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER          0x00000201
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE             0x00000300
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND          0x00000400
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT        0x00000401
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH         0x00000402
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN   0x00000403
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID      0x00000404
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_SIZE                 0x00000405
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_CANT_FIND          0x00000500
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_NO_SIGN            0x00000501
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_WRONG_PKEY_HASH    0x00000502
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_BANNED_PKEY_HASH   0x00000503
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_PRICE_NOT_FOUND            0x00000600
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_HASH                 0x00000BAD
+
+#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_UNKNOWN                    0xffffffff
+// TYPE_REQUEST
+typedef struct dap_stream_ch_chain_net_srv_pkt_request_hdr{
+    dap_chain_net_id_t net_id;// Network id wheither to request
+    dap_chain_hash_fast_t tx_cond; // Conditioned transaction with paymemt for
+    dap_chain_net_srv_uid_t srv_uid;
+    char token[DAP_CHAIN_TICKER_SIZE_MAX];
+} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_request_hdr_t;
+
+typedef struct dap_stream_ch_chain_net_srv_pkt_request{
+    dap_stream_ch_chain_net_srv_pkt_request_hdr_t hdr;
+    uint8_t data[];
+} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_request_t;
+
+// Custom service data packet
+typedef struct dap_stream_ch_chain_net_srv_pkt_data_hdr{
+    uint8_t version;
+    uint16_t data_size;
+    uint8_t padding;
+    uint32_t usage_id;
+    dap_chain_net_srv_uid_t srv_uid;
+} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_data_hdr_t;
+
+typedef struct dap_stream_ch_chain_net_srv_pkt_data{
+    dap_stream_ch_chain_net_srv_pkt_data_hdr_t hdr;
+    uint8_t data[];
+} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_data_t;
+
+
+typedef struct dap_stream_ch_chain_net_srv_pkt_success_hdr{
+    uint32_t usage_id;
+    dap_chain_net_id_t net_id;
+    dap_chain_net_srv_uid_t srv_uid;
+} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_success_hdr_t;
+
+typedef struct dap_stream_ch_chain_net_srv_pkt_success{
+    dap_stream_ch_chain_net_srv_pkt_success_hdr_t hdr;
+    uint8_t custom_data[];
+} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_success_t;
+
+// TYPE_RESPONSE_ERROR
+typedef struct dap_stream_ch_chain_net_srv_pkt_error{
+    dap_chain_net_id_t net_id;
+    dap_chain_net_srv_uid_t srv_uid;
+    uint32_t usage_id;
+    uint32_t code; // error code
+} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_error_t;
+
+// data packet for connectiont test
+typedef struct dap_stream_ch_chain_net_srv_pkt_test{
+    uint32_t usage_id;
+    dap_chain_net_id_t net_id;
+    dap_chain_net_srv_uid_t srv_uid;
+    int32_t  time_connect_ms;
+    struct timeval recv_time1;
+    struct timeval recv_time2;
+    struct timeval send_time1;
+    struct timeval send_time2;
+    char ip_send[16];
+    char ip_recv[16];
+    int32_t err_code;
+    size_t data_size_send;
+    size_t data_size_recv;
+    size_t data_size;
+    dap_chain_hash_fast_t data_hash;
+    uint8_t data[];
+} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_test_t;
 
 typedef struct dap_chain_net_srv dap_chain_net_srv_t;
+typedef struct dap_chain_net_srv_usage dap_chain_net_srv_usage_t;
+
+typedef struct dap_chain_net_srv_grace {
+    dap_stream_worker_t *stream_worker;
+    dap_stream_ch_uuid_t ch_uuid;
+    dap_chain_net_srv_usage_t *usage;
+    dap_stream_ch_chain_net_srv_pkt_request_t *request;
+    size_t request_size;
+} dap_chain_net_srv_grace_t;
+
+typedef struct dap_chain_net_srv_client_remote
+{
+    dap_stream_ch_t * ch; // Use ONLY in own context, not thread-safe
+    time_t ts_created;
+    dap_stream_worker_t * stream_worker;
+    int session_id;
+    dap_chain_net_remote_t *net_remote; // For remotes
+    uint64_t bytes_received;
+    uint64_t bytes_sent;
+    struct dap_chain_net_srv_client_remote *prev;
+    struct dap_chain_net_srv_client_remote *next;
+} dap_chain_net_srv_client_remote_t;
 
-typedef void (*dap_chain_net_srv_callback_t)(dap_chain_net_srv_t *, dap_chain_net_srv_client_remote_t *);
-typedef int (*dap_chain_net_srv_callback_data_t)(dap_chain_net_srv_t *, uint32_t, dap_chain_net_srv_client_remote_t *, const void *, size_t );
-typedef void* (*dap_chain_net_srv_callback_data_with_out_data_t)(dap_chain_net_srv_t *, uint32_t, dap_chain_net_srv_client_remote_t *, const void *, size_t, size_t *);
-typedef int (*dap_chain_net_srv_callback_sign_request_t)(dap_chain_net_srv_t *, uint32_t, dap_chain_net_srv_client_remote_t *, dap_chain_datum_tx_receipt_t **, size_t );
+typedef int  (*dap_chain_net_srv_callback_data_t)(dap_chain_net_srv_t *, uint32_t, dap_chain_net_srv_client_remote_t *, const void *, size_t);
+typedef void* (*dap_chain_net_srv_callback_custom_data_t)(dap_chain_net_srv_t *, dap_chain_net_srv_usage_t *, const void *, size_t, size_t *);
 typedef void (*dap_chain_net_srv_callback_ch_t)(dap_chain_net_srv_t *, dap_stream_ch_t *);
 
 typedef struct dap_chain_net_srv_banlist_item {
@@ -68,51 +239,35 @@ typedef struct dap_chain_net_srv
     // Receipt next sign succesfull
     dap_chain_net_srv_callback_data_t callback_receipt_next_success;
 
-    // Stream CH callbacks - channed opened,ready for read, ready for write and closed
-    dap_chain_net_srv_callback_ch_t      callback_stream_ch_opened;
-    dap_chain_net_srv_callback_data_t callback_stream_ch_read;
-    dap_chain_net_srv_callback_data_with_out_data_t callback_stream_ch_read_with_out_data;
-    dap_chain_net_srv_callback_ch_t callback_stream_ch_write;
-    dap_chain_net_srv_callback_ch_t      callback_stream_ch_closed;
-
-    // Client have to start service
-    dap_chain_net_srv_callback_data_t callback_client_success;
-    // Client have to sign receipt
-    dap_chain_net_srv_callback_sign_request_t callback_client_sign_request;
+    // Custom data processing
+    dap_chain_net_srv_callback_custom_data_t callback_custom_data;
 
+    // Stream CH callbacks - channel opened, closed and write
+    dap_chain_net_srv_callback_ch_t callback_stream_ch_opened;
+    dap_chain_net_srv_callback_ch_t callback_stream_ch_closed;
+    dap_chain_net_srv_callback_ch_t callback_stream_ch_write;
     // Pointer to inheritor object
-    void * _inhertor;
+    void *_inheritor;
+    // Pointer to internal server structure
+    void *_internal;
 } dap_chain_net_srv_t;
 
-typedef struct dap_chain_net_srv_client_remote
-{
-    dap_stream_ch_t * ch; // Use ONLY in own context, not thread-safe
-    time_t ts_created;
-    dap_stream_worker_t * stream_worker;
-    int session_id;
-    dap_chain_net_remote_t *net_remote; // For remotes
-    uint64_t bytes_received;
-    uint64_t bytes_sent;
-    struct dap_chain_net_srv_client_remote *prev;
-    struct dap_chain_net_srv_client_remote *next;
-} dap_chain_net_srv_client_remote_t;
-
-typedef void (*dap_chain_net_srv_callback_new_t)(dap_chain_net_srv_t *, dap_config_t *);
-
 int dap_chain_net_srv_init();
 void dap_chain_net_srv_deinit(void);
-dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid,dap_chain_net_srv_callback_data_t a_callback_requested,
+bool dap_chain_net_srv_pay_verificator(dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx, bool a_owner);
+dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid,
+                                           const char *a_config_section,
+                                           dap_chain_net_srv_callback_data_t a_callback_requested,
                                            dap_chain_net_srv_callback_data_t a_callback_response_success,
                                            dap_chain_net_srv_callback_data_t a_callback_response_error,
-                                           dap_chain_net_srv_callback_data_t a_callback_receipt_next_success
+                                           dap_chain_net_srv_callback_data_t a_callback_receipt_next_success,
+                                           dap_chain_net_srv_callback_custom_data_t a_callback_custom_data
                                            );
 
 int dap_chain_net_srv_set_ch_callbacks(dap_chain_net_srv_uid_t a_uid,
                                        dap_chain_net_srv_callback_ch_t a_callback_stream_ch_opened,
-                                       dap_chain_net_srv_callback_data_t a_callback_stream_ch_read,
-                                       dap_chain_net_srv_callback_data_with_out_data_t a_callback_stream_ch_read_with_out_data,
-                                       dap_chain_net_srv_callback_ch_t a_callback_stream_ch_write,
-                                       dap_chain_net_srv_callback_ch_t a_callback_stream_ch_closed
+                                       dap_chain_net_srv_callback_ch_t a_callback_stream_ch_closed,
+                                       dap_chain_net_srv_callback_ch_t a_callback_stream_ch_write
                                        );
 
 void dap_chain_net_srv_del(dap_chain_net_srv_t * a_srv);
@@ -126,16 +281,18 @@ dap_chain_net_srv_t * dap_chain_net_srv_get(dap_chain_net_srv_uid_t a_uid);
 size_t dap_chain_net_srv_count(void);
 const dap_chain_net_srv_uid_t * dap_chain_net_srv_list(void);
 dap_chain_datum_tx_receipt_t * dap_chain_net_srv_issue_receipt(dap_chain_net_srv_t *a_srv,
-                dap_chain_net_srv_usage_t * a_usage,
-                dap_chain_net_srv_price_t * a_price, const void * a_ext, size_t a_ext_size
-                );
-
-
-int dap_chain_net_srv_remote_init(dap_chain_net_srv_uid_t a_uid,
-        dap_chain_net_srv_callback_data_t a_callback_request,
-        dap_chain_net_srv_callback_data_t a_callback_response_success,
-        dap_chain_net_srv_callback_data_t a_callback_response_error,
-        dap_chain_net_srv_callback_data_t a_callback_receipt_next_success,
-        dap_chain_net_srv_callback_data_t a_callback_client_success,
-        dap_chain_net_srv_callback_sign_request_t a_callback_client_sign_request,
-        void *a_inhertor);
+                                                               dap_chain_net_srv_price_t * a_price,
+                                                               const void * a_ext, size_t a_ext_size);
+uint8_t dap_stream_ch_chain_net_srv_get_id();
+
+DAP_STATIC_INLINE const char * dap_chain_net_srv_price_unit_uid_to_str( dap_chain_net_srv_price_unit_uid_t a_uid )
+{
+    switch ( a_uid.enm) {
+        case SERV_UNIT_B: return "BYTE";
+        case SERV_UNIT_KB: return "KILOBYTE";
+        case SERV_UNIT_MB: return "MEGABYTE";
+        case SERV_UNIT_SEC: return "SECOND";
+        case SERV_UNIT_DAY: return  "DAY";
+        default: return "UNKNOWN";
+    }
+}
diff --git a/modules/net/srv/include/dap_chain_net_srv_client.h b/modules/net/srv/include/dap_chain_net_srv_client.h
index fe42c8b4c9..93c2c95f33 100644
--- a/modules/net/srv/include/dap_chain_net_srv_client.h
+++ b/modules/net/srv/include/dap_chain_net_srv_client.h
@@ -28,21 +28,29 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 
 
 #include "dap_enc_key.h"
-#include "dap_stream_session.h"
 #include "dap_stream_worker.h"
-#include "dap_chain_net_srv_common.h"
+#include "dap_chain_net_srv.h"
 #include "dap_chain_net_remote.h"
 #include "dap_chain_node_client.h"
 
 typedef struct dap_chain_net_srv_client dap_chain_net_srv_client_t;
 
-typedef void (*dap_chain_net_srv_client_callback_t)(dap_chain_net_srv_client_t *, void *);
+typedef void   (*dap_chain_net_srv_client_callback_t)(dap_chain_net_srv_client_t *, void *);
+typedef void   (*dap_chain_net_srv_client_callback_check_t)(dap_chain_net_srv_client_t *, dap_stream_ch_chain_net_srv_pkt_test_t *, void *);
+typedef dap_chain_datum_tx_receipt_t * (*dap_chain_net_srv_client_callback_sign_t)(dap_chain_net_srv_client_t *, dap_chain_datum_tx_receipt_t *, void *);
+typedef void   (*dap_chain_net_srv_client_callback_success_t)(dap_chain_net_srv_client_t *, dap_stream_ch_chain_net_srv_pkt_success_t *, size_t, void *);
+typedef void   (*dap_chain_net_srv_client_callback_error_t)(dap_chain_net_srv_client_t *, int, void *);
+typedef void   (*dap_chain_net_srv_client_data_t)(dap_chain_net_srv_client_t *, uint8_t *, size_t, void *);
 
 typedef struct dap_chain_net_srv_client_callbacks {
     dap_chain_net_srv_client_callback_t connected;
     dap_chain_net_srv_client_callback_t disconnected;
     dap_chain_net_srv_client_callback_t deleted;
-    dap_stream_ch_callback_packet_t pkt_in;
+    dap_chain_net_srv_client_callback_check_t check;        // Client has got response for test
+    dap_chain_net_srv_client_callback_success_t success;    // Client has started service
+    dap_chain_net_srv_client_callback_error_t error;        // Client recieved an error
+    dap_chain_net_srv_client_callback_sign_t sign;          // Cleint has got receipt for sign
+    dap_chain_net_srv_client_data_t data;                   // Client has got custom data response
 } dap_chain_net_srv_client_callbacks_t;
 
 typedef struct dap_chain_net_srv_client {
diff --git a/modules/net/srv/include/dap_chain_net_srv_common.h b/modules/net/srv/include/dap_chain_net_srv_common.h
deleted file mode 100755
index 51cdfee526..0000000000
--- a/modules/net/srv/include/dap_chain_net_srv_common.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Authors:
- * Aleksandr Lysikov <alexander.lysikov@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * Kelvin Project https://github.com/kelvinblockchain
- * Copyright  (c) 2019
- * All rights reserved.
-
- This file is part of DAP (Deus Applications Prototypes) the open source project
-
- DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- DAP is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-#include <stdint.h>
-#include <stdbool.h>
-#include "dap_server.h"
-#include "dap_common.h"
-#include "dap_math_ops.h"
-#include "dap_stream_ch.h"
-#include "dap_chain_common.h"
-#include "dap_chain_ledger.h"
-#include "dap_chain_net.h"
-#include "dap_chain_wallet.h"
-//#include "dap_chain_net_srv_stream_session.h"
-
-
-//Service direction
-enum dap_chain_net_srv_order_direction{
-    SERV_DIR_BUY = 1,
-    SERV_DIR_SELL = 2,
-    SERV_DIR_UNDEFINED = 0
-};
-typedef byte_t dap_chain_net_srv_order_direction_t;
-
-
-typedef struct dap_chain_net_srv_abstract
-{
-    uint8_t class; //Class of service (once or permanent)
-    dap_chain_net_srv_uid_t type_id; //Type of service
-    union {
-        struct {
-            int bandwith;
-            int abuse_resistant;
-            size_t limit_bytes;
-        } vpn;
-        /*struct {
-         int value;
-         } another_srv;*/
-    } proposal_params;
-
-    //size_t pub_key_data_size;
-    //void * pub_key_data;
-
-    uint64_t price; //  service price, for SERV_CLASS_ONCE ONCE for the whole service, for SERV_CLASS_PERMANENT  for one unit.
-    uint8_t price_units; // Unit of service (seconds, megabytes, etc.) Only for SERV_CLASS_PERMANENT
-    char decription[128];
-}DAP_ALIGN_PACKED dap_chain_net_srv_abstract_t;
-
-typedef void (*dap_chain_callback_trafic_t)(dap_events_socket_t *, dap_stream_ch_t *);
-
-typedef struct dap_chain_net_srv_price
-{
-    dap_chain_wallet_t * wallet;
-    char * net_name;
-    dap_chain_net_t * net;
-    uint64_t value_datoshi;
-    char token[DAP_CHAIN_TICKER_SIZE_MAX];
-    uint64_t units;
-    dap_chain_net_srv_price_unit_uid_t units_uid;
-    struct dap_chain_net_srv_price * next;
-    struct dap_chain_net_srv_price * prev;
-} dap_chain_net_srv_price_t;
-
-// Ch pkt types
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST                       0x01
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST                  0x10
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE                 0x11
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED                0x20
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA                          0x30
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS              0xf0
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR                0xff
-// for connection testing
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST                 0x40
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE                0x41
-
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_UNDEFINED                  0x00000000
-
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND          0x00000100
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_CH_NOT_FOUND       0x00000101
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_IN_CLIENT_MODE     0x00000102
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NOT_FOUND          0x00000200
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER          0x00000201
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_USAGE_CANT_ADD             0x00000300
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND          0x00000400
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT        0x00000401
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH         0x00000402
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN   0x00000403
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID      0x00000404
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SIZE         0x00000405
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_CANT_FIND          0x00000500
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_NO_SIGN            0x00000501
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_WRONG_PKEY_HASH    0x00000502
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_BANNED_PKEY_HASH   0x00000503
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_PRICE_NOT_FOUND            0x00000600
-
-#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_UNKNOWN                    0xffffffff
-// TYPE_REQUEST
-typedef struct dap_stream_ch_chain_net_srv_pkt_request_hdr{
-    dap_chain_net_id_t net_id;// Network id wheither to request
-    dap_chain_hash_fast_t tx_cond; // Conditioned transaction with paymemt for
-    dap_chain_net_srv_uid_t srv_uid;
-    char token[DAP_CHAIN_TICKER_SIZE_MAX];
-} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_request_hdr_t;
-
-typedef struct dap_stream_ch_chain_net_srv_pkt_request{
-    dap_stream_ch_chain_net_srv_pkt_request_hdr_t hdr;
-    uint8_t data[];
-} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_request_t;
-
-// Custom service data packet
-typedef struct dap_stream_ch_chain_net_srv_pkt_data_hdr{
-    uint8_t version;
-    uint16_t data_size;
-    uint8_t padding;
-    uint32_t usage_id;
-    dap_chain_net_srv_uid_t srv_uid;
-} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_data_hdr_t;
-
-typedef struct dap_stream_ch_chain_net_srv_pkt_data{
-    dap_stream_ch_chain_net_srv_pkt_data_hdr_t hdr;
-    uint8_t data[];
-} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_data_t;
-
-
-typedef struct dap_stream_ch_chain_net_srv_pkt_success_hdr{
-    uint32_t usage_id;
-    dap_chain_net_id_t net_id;
-    dap_chain_net_srv_uid_t srv_uid;
-} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_success_hdr_t;
-
-typedef struct dap_stream_ch_chain_net_srv_pkt_success{
-    dap_stream_ch_chain_net_srv_pkt_success_hdr_t hdr;
-    uint8_t custom_data[];
-} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_success_t;
-
-// TYPE_RESPONSE_ERROR
-typedef struct dap_stream_ch_chain_net_srv_pkt_error{
-    dap_chain_net_id_t net_id;
-    dap_chain_net_srv_uid_t srv_uid;
-    uint32_t usage_id;
-    uint32_t code; // error code
-} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_error_t;
-
-// data packet for connectiont test
-typedef struct dap_stream_ch_chain_net_srv_pkt_test{
-    uint32_t usage_id;
-    dap_chain_net_id_t net_id;
-    dap_chain_net_srv_uid_t srv_uid;
-    int32_t  time_connect_ms;
-    struct timeval recv_time1;
-    struct timeval recv_time2;
-    struct timeval send_time1;
-    struct timeval send_time2;
-    char ip_send[16];
-    char ip_recv[16];
-    int32_t err_code;
-    size_t data_size_send;
-    size_t data_size_recv;
-    size_t data_size;
-    dap_chain_hash_fast_t data_hash;
-    uint8_t data[];
-} DAP_ALIGN_PACKED dap_stream_ch_chain_net_srv_pkt_test_t;
-
-typedef struct dap_chain_net_srv_usage dap_chain_net_srv_usage_t;
-
-typedef struct dap_chain_net_srv_grace {
-    dap_stream_worker_t *stream_worker;
-    dap_stream_ch_uuid_t ch_uuid;
-    dap_chain_net_srv_usage_t *usage;
-    dap_stream_ch_chain_net_srv_pkt_request_t *request;
-    size_t request_size;
-} dap_chain_net_srv_grace_t;
-
-DAP_STATIC_INLINE const char * dap_chain_net_srv_price_unit_uid_to_str( dap_chain_net_srv_price_unit_uid_t a_uid )
-{
-    switch ( a_uid.enm) {
-        case SERV_UNIT_B: return "BYTE";
-        case SERV_UNIT_KB: return "KILOBYTE";
-        case SERV_UNIT_MB: return "MEGABYTE";
-        case SERV_UNIT_SEC: return "SECOND";
-        case SERV_UNIT_DAY: return  "DAY";
-        default: return "UNKNOWN";
-    }
-}
-
-uint8_t dap_stream_ch_chain_net_srv_get_id();
-
diff --git a/modules/net/srv/include/dap_chain_net_srv_order.h b/modules/net/srv/include/dap_chain_net_srv_order.h
index 9ec7c2ded3..dc2c85e568 100644
--- a/modules/net/srv/include/dap_chain_net_srv_order.h
+++ b/modules/net/srv/include/dap_chain_net_srv_order.h
@@ -27,7 +27,7 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include "dap_common.h"
 #include "dap_string.h"
 #include "dap_chain_common.h"
-#include "dap_chain_net_srv_common.h"
+#include "dap_chain_net_srv.h"
 
 typedef struct dap_chain_net_srv_order
 {
diff --git a/modules/net/srv/include/dap_chain_net_srv_stream_session.h b/modules/net/srv/include/dap_chain_net_srv_stream_session.h
index e3d117b5f2..76272f66c7 100644
--- a/modules/net/srv/include/dap_chain_net_srv_stream_session.h
+++ b/modules/net/srv/include/dap_chain_net_srv_stream_session.h
@@ -31,25 +31,19 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include "dap_sign.h"
 #include "dap_chain_datum_tx.h"
 #include "dap_chain_datum_tx_receipt.h"
-#include "dap_chain_net_srv_order.h"
 #include "dap_chain_wallet.h"
-
-typedef struct dap_chain_net_srv dap_chain_net_srv_t;
-typedef struct dap_chain_net_srv_client_remote dap_chain_net_srv_client_remote_t;
+#include "dap_chain_net_srv.h"
 
 typedef struct dap_chain_net_srv_usage {
     uint32_t id; // Usage id
     pthread_rwlock_t rwlock;
     time_t ts_created; // Created timpestamp
     dap_chain_net_t * net; // Chain network where everything happens
-    dap_chain_wallet_t * wallet;
     dap_chain_net_srv_t * service; // Service that used
 
     dap_chain_datum_tx_receipt_t* receipt;
     dap_chain_datum_tx_receipt_t* receipt_next; // Receipt on the next units amount
     dap_chain_net_srv_price_t * price; // Price for issue next receipt
-    size_t receipt_size;
-    size_t receipt_next_size;
     dap_chain_net_srv_client_remote_t *client;
     dap_chain_datum_tx_t * tx_cond;
     dap_chain_hash_fast_t tx_cond_hash;
diff --git a/modules/service/stake/dap_chain_net_srv_stake.c b/modules/service/stake/dap_chain_net_srv_stake.c
index f913f7f3bc..e38aacad72 100644
--- a/modules/service/stake/dap_chain_net_srv_stake.c
+++ b/modules/service/stake/dap_chain_net_srv_stake.c
@@ -28,7 +28,7 @@
 #include "dap_enc_base58.h"
 #include "dap_chain_common.h"
 #include "dap_chain_mempool.h"
-#include "dap_chain_net_srv_common.h"
+#include "dap_chain_net_srv.h"
 #include "dap_chain_cs_block_poa.h"
 #include "dap_chain_cs_dag_poa.h"
 #include "dap_chain_net_srv_stake.h"
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c
index e1e2a3cda7..1f7e566bfb 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn.c
+++ b/modules/service/vpn/dap_chain_net_srv_vpn.c
@@ -533,138 +533,6 @@ static dap_events_socket_t * s_tun_event_stream_create(dap_worker_t * a_worker,
     return l_es;
 }
 
-/**
- * @brief s_callback_client_success
- * @param a_srv
- * @param a_usage_id
- * @param a_srv_client
- * @param a_success
- * @param a_success_size
- * @return
- */
-static int s_callback_client_success(dap_chain_net_srv_t * a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t * a_srv_client,
-                    const void * a_success, size_t a_success_size)
-{
-    if(!a_srv || !a_srv_client || !a_srv_client->stream_worker || !a_success || a_success_size < sizeof(dap_stream_ch_chain_net_srv_pkt_success_t))
-        return -1;
-    dap_stream_ch_chain_net_srv_pkt_success_t * l_success = (dap_stream_ch_chain_net_srv_pkt_success_t*) a_success;
-
-    dap_stream_session_lock();
-    dap_stream_session_t *l_stream_session = dap_stream_session_id_unsafe(a_srv_client->session_id);
-    dap_chain_net_srv_stream_session_t * l_srv_session =
-            (dap_chain_net_srv_stream_session_t *) l_stream_session->_inheritor;
-
-    dap_chain_net_srv_vpn_t* l_srv_vpn = (dap_chain_net_srv_vpn_t*) a_srv->_inhertor;
-    //a_srv_client->ch->
-    dap_chain_net_t * l_net = dap_chain_net_by_id(l_success->hdr.net_id);
-    dap_chain_net_srv_usage_t *l_usage = dap_chain_net_srv_usage_add(l_srv_session, l_net, a_srv);
-    if(!l_usage){
-        dap_stream_session_unlock();
-        return -2;
-    }
-
-    dap_chain_net_srv_ch_vpn_t * l_srv_ch_vpn =
-            (dap_chain_net_srv_ch_vpn_t*) a_srv_client->ch->stream->channel[DAP_CHAIN_NET_SRV_VPN_ID] ?
-                    a_srv_client->ch->stream->channel[DAP_CHAIN_NET_SRV_VPN_ID]->internal : NULL;
-    if ( ! l_srv_ch_vpn ){
-        log_it(L_ERROR, "No VPN service stream channel, its closed?");
-        return -3;
-    }
-    l_srv_ch_vpn->usage_id = l_usage->id;
-    l_usage->is_active = true;
-    l_usage->is_free = true;
-
-    dap_stream_ch_t *l_ch = dap_chain_net_vpn_client_get_stream_ch();
-
-
-    if(l_ch) { // Is present in hash table such destination address
-        size_t l_ipv4_str_len = 0; //dap_strlen(a_ipv4_str);
-        ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header) + l_ipv4_str_len);
-
-        pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_ADDR_REQUEST;
-        //pkt_out->header.sock_id = l_stream->stream->events_socket->socket;
-        //pkt_out->header.op_connect.addr_size = l_ipv4_str_len; //remoteAddrBA.length();
-        //pkt_out->header.op_connect.port = a_port;
-        //memcpy(pkt_out->data, a_ipv4_str, l_ipv4_str_len);
-
-        dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out,
-                pkt_out->header.op_data.data_size + sizeof(pkt_out->header));
-        dap_stream_ch_set_ready_to_write_unsafe(l_ch, true);
-        //DAP_DELETE(pkt_out);
-    }
-
-    // usage is present, we've accepted packets
-    dap_stream_ch_set_ready_to_read_unsafe( l_srv_ch_vpn->ch , true );
-    return 0;
-}
-
-/**
- * @brief callback_client_sign_request
- * @param a_srv
- * @param a_usage_id
- * @param a_srv_client
- * @param a_receipt
- * @param a_receipt_size
- * @return
- */
-static int s_callback_client_sign_request(dap_chain_net_srv_t * a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t * a_srv_client,
-                    dap_chain_datum_tx_receipt_t **a_receipt, size_t a_receipt_size)
-{
-    dap_chain_datum_tx_receipt_t *l_receipt = *a_receipt;
-    char *l_gdb_group = dap_strdup_printf("local.%s", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX);
-    char *l_wallet_name = (char*) dap_chain_global_db_gr_get(dap_strdup("wallet_name"), NULL, l_gdb_group);
-
-    dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_name, dap_chain_wallet_get_path(g_config));
-    if(l_wallet) {
-        dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
-        dap_chain_datum_tx_receipt_sign_add(&l_receipt, dap_chain_datum_tx_receipt_get_size(l_receipt), l_enc_key);
-        dap_chain_wallet_close(l_wallet);
-        *a_receipt = l_receipt;
-    }
-    DAP_DELETE(l_gdb_group);
-    DAP_DELETE(l_wallet_name);
-    return 0;
-}
-
-
-/**
- * @brief dap_chain_net_srv_client_vpn_init
- * @details  Client VPN init (call after dap_chain_net_srv_vpn_init!)
- * @param l_config
- * @return
- */
-int dap_chain_net_srv_client_vpn_init(dap_config_t * l_config) {
-    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID };
-    dap_chain_net_srv_t *l_srv = dap_chain_net_srv_get(l_uid);
-    dap_chain_net_srv_vpn_t* l_srv_vpn = l_srv ? (dap_chain_net_srv_vpn_t*) l_srv->_inhertor : NULL;
-    // if vpn server disabled
-    if(!l_srv_vpn) {
-        l_srv_vpn = DAP_NEW_Z(dap_chain_net_srv_vpn_t);
-        if(l_srv)
-            l_srv->_inhertor = l_srv_vpn;
-        dap_stream_ch_proc_add(DAP_STREAM_CH_ID_NET_SRV_VPN, s_ch_vpn_new, s_ch_vpn_delete, s_ch_packet_in, s_ch_packet_out);
-        pthread_mutex_init(&s_sf_socks_mutex, NULL);
-        pthread_cond_init(&s_sf_socks_cond, NULL);
-    }
-
-
-    if(!dap_chain_net_srv_remote_init(l_uid, s_callback_requested,
-            s_callback_response_success, s_callback_response_error,
-            s_callback_receipt_next_success,
-            s_callback_client_success,
-            s_callback_client_sign_request,
-            l_srv_vpn)) {
-        l_srv = dap_chain_net_srv_get(l_uid);
-        //l_srv_vpn = l_srv ? (dap_chain_net_srv_vpn_t*)l_srv->_inhertor : NULL;
-        //l_srv_vpn->parent = l_srv;
-        l_srv->_inhertor = l_srv_vpn;
-    }
-    l_srv_vpn->parent = (dap_chain_net_srv_t*) l_srv;
-
-    return 0;
-}
-
-
 /**
  * @brief s_vpn_tun_create
  * @param g_config
@@ -777,91 +645,14 @@ static int s_vpn_tun_init()
 static int s_vpn_service_create(dap_config_t * g_config)
 {
     dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID };
-    dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add( l_uid, s_callback_requested,
-                                                        s_callback_response_success, s_callback_response_error,
-                                                        s_callback_receipt_next_success);
-
+    dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, "srv_vpn", s_callback_requested,
+                                                       s_callback_response_success, s_callback_response_error,
+                                                       s_callback_receipt_next_success, NULL);
     dap_chain_net_srv_vpn_t* l_srv_vpn  = DAP_NEW_Z( dap_chain_net_srv_vpn_t);
-    l_srv->_inhertor = l_srv_vpn;
+    l_srv->_internal = l_srv_vpn;
     l_srv_vpn->parent = l_srv;
-
     // Read if we need to dump all pkt operations
     s_debug_more= dap_config_get_item_bool_default(g_config,"srv_vpn", "debug_more",false);
-
-    l_srv->grace_period = dap_config_get_item_uint32_default(g_config, "srv_vpn", "grace_period", 60);
-    //! IMPORTANT ! This fetch is single-action and cannot be further reused, since it modifies the stored config data
-    //! it also must NOT be freed within this module !
-    uint16_t l_pricelist_count = 0;
-    char **l_pricelist = dap_config_get_array_str(g_config, "srv_vpn", "pricelist", &l_pricelist_count); // must not be freed!
-    for (uint16_t i = 0; i < l_pricelist_count; i++) {
-        dap_chain_net_srv_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_price_t);
-        short l_iter = 0;
-        char *l_ctx;
-        for (char *l_price_token = strtok_r(l_pricelist[i], ":", &l_ctx); l_price_token || l_iter == 6; l_price_token = strtok_r(NULL, ":", &l_ctx), ++l_iter) {
-            //log_it(L_DEBUG, "Tokenizer: %s", l_price_token);
-            switch (l_iter) {
-            case 0:
-                l_price->net_name = l_price_token;
-                if (!(l_price->net = dap_chain_net_by_name(l_price->net_name))) {
-                    log_it(L_ERROR, "Error parsing pricelist: can't find network \"%s\"", l_price_token);
-                    DAP_DELETE(l_price);
-                    break;
-                }
-                continue;
-            case 1:
-                l_price->value_datoshi = dap_chain_coins_to_datoshi(strtold(l_price_token, NULL));
-                if (!l_price->value_datoshi) {
-                    log_it(L_ERROR, "Error parsing pricelist: text on 2nd position \"%s\" is not floating number", l_price_token);
-                    l_iter = 0;
-                    DAP_DELETE(l_price);
-                    break;
-                }
-                continue;
-            case 2:
-                dap_stpcpy(l_price->token, l_price_token);
-                continue;
-            case 3:
-                l_price->units = strtoul(l_price_token, NULL, 10);
-                if (!l_price->units) {
-                    log_it(L_ERROR, "Error parsing pricelist: text on 4th position \"%s\" is not unsigned integer", l_price_token);
-                    l_iter = 0;
-                    DAP_DELETE(l_price);
-                    break;
-                }
-                continue;
-            case 4:
-                if (!strcmp(l_price_token,      "SEC"))
-                    l_price->units_uid.enm = SERV_UNIT_SEC;
-                else if (!strcmp(l_price_token, "DAY"))
-                    l_price->units_uid.enm = SERV_UNIT_DAY;
-                else if (!strcmp(l_price_token, "MB"))
-                    l_price->units_uid.enm = SERV_UNIT_MB;
-                else {
-                    log_it(L_ERROR, "Error parsing pricelist: wrong unit type \"%s\"", l_price_token);
-                    l_iter = 0;
-                    DAP_DELETE(l_price);
-                    break;
-                }
-                continue;
-            case 5:
-                if (!(l_price->wallet = dap_chain_wallet_open(l_price_token, dap_config_get_item_str_default(g_config, "resources", "wallets_path", NULL)))) {
-                    log_it(L_ERROR, "Error parsing pricelist: can't open wallet \"%s\"", l_price_token);
-                    l_iter = 0;
-                    DAP_DELETE(l_price);
-                    break;
-                }
-                continue;
-            case 6:
-                log_it(L_INFO, "Price item correct, added to service");
-                DL_APPEND(l_srv->pricelist, l_price);
-                break;
-            default:
-                break;
-            }
-            log_it(L_DEBUG, "Done with price item %d", i);
-            break; // double break exits tokenizer loop and steps to next price item
-        }
-    }
     return 0;
 
 }
@@ -1059,7 +850,7 @@ static void s_ch_vpn_delete(dap_stream_ch_t* a_ch, void* arg)
 {
     (void) arg;
     dap_chain_net_srv_ch_vpn_t * l_ch_vpn = CH_VPN(a_ch);
-    dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_ch_vpn->net_srv->_inhertor;
+    dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_ch_vpn->net_srv->_internal;
 
 
     // So complicated to update usage client to be sure that nothing breaks it
@@ -1200,10 +991,9 @@ static void s_update_limits(dap_stream_ch_t * a_ch ,
     // If issue new receipt
     if ( l_issue_new_receipt ) {
         if ( a_usage->receipt){
-            dap_chain_datum_tx_receipt_t * l_receipt =dap_chain_net_srv_issue_receipt(a_usage->service, a_usage,a_usage->price,NULL,0 );
-            a_usage->receipt_next = l_receipt;
-            dap_stream_ch_pkt_write_unsafe( a_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST ,
-                                     l_receipt, l_receipt->size);
+            a_usage->receipt_next = dap_chain_net_srv_issue_receipt(a_usage->service, a_usage->price, NULL, 0);
+            dap_stream_ch_pkt_write_unsafe(a_usage->client->ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST,
+                                           a_usage->receipt_next, a_usage->receipt_next->size);
         }
     }
 
@@ -1229,7 +1019,7 @@ static void send_pong_pkt(dap_stream_ch_t* a_ch)
  */
 static void s_ch_packet_in_vpn_address_request(dap_stream_ch_t* a_ch, dap_chain_net_srv_usage_t * a_usage){
     dap_chain_net_srv_ch_vpn_t *l_ch_vpn = CH_VPN(a_ch);
-    dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) a_usage->service->_inhertor;
+    dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) a_usage->service->_internal;
     dap_chain_net_srv_stream_session_t * l_srv_session= DAP_CHAIN_NET_SRV_STREAM_SESSION(l_ch_vpn->ch->stream->session);
 
     if (! s_raw_server)
@@ -1412,7 +1202,7 @@ void s_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
 
 
     // TODO move address leasing to this structure
-    //dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_usage->service->_inhertor;
+    //dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_usage->service->_internal;
 
     ch_vpn_pkt_t * l_vpn_pkt = (ch_vpn_pkt_t *) l_pkt->data;
     size_t l_vpn_pkt_size = l_pkt->hdr.size - sizeof (l_vpn_pkt->header);
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
index d8e943f77d..3e1d171e03 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
+++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c
@@ -2,6 +2,7 @@
 #include "dap_chain_node_cli.h"
 #include "dap_chain_node_cli_cmd.h"
 #include "dap_chain_net_srv_vpn_cmd.h"
+#include "dap_chain_net_srv_stream_session.h"
 #include "dap_chain_net_vpn_client.h"
 
 
diff --git a/modules/service/vpn/dap_chain_net_vpn_client.c b/modules/service/vpn/dap_chain_net_vpn_client.c
index 8383b3203c..7a6ebacc2d 100644
--- a/modules/service/vpn/dap_chain_net_vpn_client.c
+++ b/modules/service/vpn/dap_chain_net_vpn_client.c
@@ -57,6 +57,7 @@
 #include "dap_chain_common.h"
 #include "dap_chain_mempool.h"
 #include "dap_chain_node_cli.h"
+#include "dap_chain_net_srv_order.h"
 #include "dap_chain_net_srv_vpn.h"
 #include "dap_chain_net_vpn_client.h"
 
@@ -134,6 +135,98 @@ dap_stream_ch_t* dap_chain_net_vpn_client_get_stream_ch(void)
 
  }*/
 
+/**
+ * @brief s_callback_client_success
+ * @param a_srv
+ * @param a_usage_id
+ * @param a_srv_client
+ * @param a_success
+ * @param a_success_size
+ * @return
+ */
+static int s_callback_client_success(dap_chain_net_srv_t * a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t * a_srv_client,
+                    const void * a_success, size_t a_success_size)
+{
+    if(!a_srv || !a_srv_client || !a_srv_client->stream_worker || !a_success || a_success_size < sizeof(dap_stream_ch_chain_net_srv_pkt_success_t))
+        return -1;
+    dap_stream_ch_chain_net_srv_pkt_success_t * l_success = (dap_stream_ch_chain_net_srv_pkt_success_t*) a_success;
+
+    dap_stream_session_lock();
+    dap_stream_session_t *l_stream_session = dap_stream_session_id_unsafe(a_srv_client->session_id);
+    dap_chain_net_srv_stream_session_t * l_srv_session =
+            (dap_chain_net_srv_stream_session_t *) l_stream_session->_inheritor;
+
+    //dap_chain_net_srv_vpn_t* l_srv_vpn = (dap_chain_net_srv_vpn_t*) a_srv->_internal;
+    //a_srv_client->ch->
+    dap_chain_net_t * l_net = dap_chain_net_by_id(l_success->hdr.net_id);
+    dap_chain_net_srv_usage_t *l_usage = dap_chain_net_srv_usage_add(l_srv_session, l_net, a_srv);
+    if(!l_usage){
+        dap_stream_session_unlock();
+        return -2;
+    }
+
+    dap_chain_net_srv_ch_vpn_t * l_srv_ch_vpn =
+            (dap_chain_net_srv_ch_vpn_t*) a_srv_client->ch->stream->channel[DAP_CHAIN_NET_SRV_VPN_ID] ?
+                    a_srv_client->ch->stream->channel[DAP_CHAIN_NET_SRV_VPN_ID]->internal : NULL;
+    if ( ! l_srv_ch_vpn ){
+        log_it(L_ERROR, "No VPN service stream channel, its closed?");
+        return -3;
+    }
+    l_srv_ch_vpn->usage_id = l_usage->id;
+    l_usage->is_active = true;
+    l_usage->is_free = true;
+
+    dap_stream_ch_t *l_ch = dap_chain_net_vpn_client_get_stream_ch();
+
+
+    if(l_ch) { // Is present in hash table such destination address
+        size_t l_ipv4_str_len = 0; //dap_strlen(a_ipv4_str);
+        ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header) + l_ipv4_str_len);
+
+        pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_ADDR_REQUEST;
+        //pkt_out->header.sock_id = l_stream->stream->events_socket->socket;
+        //pkt_out->header.op_connect.addr_size = l_ipv4_str_len; //remoteAddrBA.length();
+        //pkt_out->header.op_connect.port = a_port;
+        //memcpy(pkt_out->data, a_ipv4_str, l_ipv4_str_len);
+
+        dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out,
+                pkt_out->header.op_data.data_size + sizeof(pkt_out->header));
+        dap_stream_ch_set_ready_to_write_unsafe(l_ch, true);
+        //DAP_DELETE(pkt_out);
+    }
+
+    // usage is present, we've accepted packets
+    dap_stream_ch_set_ready_to_read_unsafe( l_srv_ch_vpn->ch , true );
+    return 0;
+}
+
+/**
+ * @brief callback_client_sign_request
+ * @param a_srv
+ * @param a_usage_id
+ * @param a_srv_client
+ * @param a_receipt
+ * @param a_receipt_size
+ * @return
+ */
+static dap_chain_datum_tx_receipt_t * s_callback_client_sign_request(dap_chain_net_srv_t * a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t * a_srv_client,
+                    dap_chain_datum_tx_receipt_t *a_receipt, size_t a_receipt_size)
+{
+    char *l_gdb_group = dap_strdup_printf("local.%s", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX);
+    char *l_wallet_name = (char*) dap_chain_global_db_gr_get(dap_strdup("wallet_name"), NULL, l_gdb_group);
+
+    dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_name, dap_chain_wallet_get_path(g_config));
+    dap_chain_datum_tx_receipt_t *l_ret = NULL;
+    if(l_wallet) {
+        dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
+        l_ret = dap_chain_datum_tx_receipt_sign_add(a_receipt, l_enc_key);
+        dap_chain_wallet_close(l_wallet);
+    }
+    DAP_DELETE(l_gdb_group);
+    DAP_DELETE(l_wallet_name);
+    return l_ret;
+}
+
 /**
  * Get tx_cond_hash
  *
@@ -229,19 +322,13 @@ static dap_chain_hash_fast_t* dap_chain_net_vpn_client_tx_cond_hash(dap_chain_ne
     if(!l_tx_cond_hash) {
         dap_chain_wallet_t *l_wallet_from = a_wallet;
         log_it(L_DEBUG, "Create tx from wallet %s", l_wallet_from->name);
-        dap_enc_key_t *l_key_from = l_enc_key; //dap_chain_wallet_get_key(l_wallet_from, 0);
-        dap_enc_key_t *l_client_key = l_enc_key;
-        //dap_chain_cell_id_t *xccell = dap_chain_net_get_cur_cell(l_tpl->net);
-        //uint64_t uint64 =dap_chain_net_get_cur_cell(l_tpl->net)->uint64;
-
-        size_t l_pub_key_data_size = 0;
-        uint8_t *l_pub_key_data = dap_enc_key_serealize_pub_key(l_enc_key, &l_pub_key_data_size);
+        dap_pkey_t *l_client_key = dap_pkey_from_enc_key(l_enc_key);
         // where to take coins for service
         dap_chain_addr_t *l_addr_from = dap_chain_wallet_get_addr(l_wallet_from, a_net->pub.id);
         dap_chain_net_srv_price_unit_uid_t l_price_unit = { .enm = SERV_UNIT_SEC };
         dap_chain_net_srv_uid_t l_srv_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID };
-        l_tx_cond_hash = dap_chain_proc_tx_create_cond(a_net, l_key_from, l_client_key, l_addr_from,
-                a_token_ticker, a_value_datoshi, 0, l_price_unit, l_srv_uid, 0, l_pub_key_data, l_pub_key_data_size);
+        l_tx_cond_hash = dap_chain_mempool_tx_create_cond(a_net, l_enc_key, l_client_key,
+                a_token_ticker, a_value_datoshi, 0, l_price_unit, l_srv_uid, 0, NULL, 0);
         //char *l_addr_from_str = dap_chain_addr_to_str(l_addr_from);
         DAP_DELETE(l_addr_from);
         if(!l_tx_cond_hash) {
@@ -251,8 +338,7 @@ static dap_chain_hash_fast_t* dap_chain_net_vpn_client_tx_cond_hash(dap_chain_ne
             dap_chain_global_db_gr_set(dap_strdup("client_tx_cond_hash"), l_tx_cond_hash, sizeof(dap_chain_hash_fast_t),
                     l_gdb_group);
         }
-        //DAP_DELETE(l_addr_from_str);
-        DAP_DELETE(l_pub_key_data);
+        DAP_DELETE(l_client_key);
     }
     dap_enc_key_delete(l_enc_key);
     DAP_DELETE(l_gdb_group);
@@ -563,7 +649,7 @@ int dap_chain_net_vpn_client_start(dap_chain_net_t *a_net, const char *a_ipv4_st
                 DAP_DELETE(l_tx_cond);
             }
             // set srv id
-            dap_stream_ch_chain_net_srv_set_srv_uid(l_ch, l_request.hdr.srv_uid);
+            //dap_stream_ch_chain_net_srv_set_srv_uid(l_ch, l_request.hdr.srv_uid);
             //dap_chain_hash_fast_t l_request
             //.hdr.tx_cond = a_txCond.value();
 //    	    strncpy(l_request->hdr.token, a_token.toLatin1().constData(),sizeof (l_request->hdr.token)-1);
@@ -690,8 +776,19 @@ int dap_chain_net_vpn_client_init(dap_config_t * g_config)
             "vpn_client check result -net <net name> [-H hex|base58(default)]\n"
             );
 
-
-    return dap_chain_net_srv_client_vpn_init(g_config);
+    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID };
+    /*if(!dap_chain_net_srv_remote_init(l_uid, s_callback_requested,
+            s_callback_response_success, s_callback_response_error,
+            s_callback_receipt_next_success,
+            s_callback_client_success,
+            s_callback_client_sign_request,
+            l_srv_vpn)) {
+        l_srv = dap_chain_net_srv_get(l_uid);
+        //l_srv_vpn = l_srv ? (dap_chain_net_srv_vpn_t*)l_srv->_internal : NULL;
+        //l_srv_vpn->parent = l_srv;
+        l_srv->_internal = l_srv_vpn;
+    }*/
+    return 0;
 }
 
 void dap_chain_net_vpn_client_deinit()
diff --git a/modules/service/vpn/include/dap_chain_net_vpn_client.h b/modules/service/vpn/include/dap_chain_net_vpn_client.h
index 5faf509bb8..ac5ed4d4fc 100644
--- a/modules/service/vpn/include/dap_chain_net_vpn_client.h
+++ b/modules/service/vpn/include/dap_chain_net_vpn_client.h
@@ -26,7 +26,9 @@
 
 #include "dap_stream_ch.h"
 #include "dap_stream_ch_pkt.h"
+#include "dap_stream_session.h"
 #include "dap_chain_net.h"
+#include "dap_chain_net_srv.h"
 #include "dap_chain_net_srv_vpn.h"
 
 typedef enum dap_chain_net_vpn_client_status_enum{
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index 966a13a4dc..2a26800d61 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -27,7 +27,7 @@
 #include "dap_string.h"
 #include "dap_chain_common.h"
 #include "dap_chain_mempool.h"
-#include "dap_chain_net_srv_common.h"
+#include "dap_chain_net_srv.h"
 #include "dap_chain_net_srv_xchange.h"
 
 #define LOG_TAG "dap_chain_net_srv_xchange"
@@ -70,10 +70,11 @@ int dap_chain_net_srv_xchange_init()
          "\tDisable eXchange service\n"
     );
     dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID };
-    dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, s_callback_requested, s_callback_response_success,
-                                                       s_callback_response_error, s_callback_receipt_next_success);
+    dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, "srv_xchange", s_callback_requested,
+                                                       s_callback_response_success, s_callback_response_error,
+                                                       s_callback_receipt_next_success, NULL);
     s_srv_xchange = DAP_NEW_Z(dap_chain_net_srv_xchange_t);
-    l_srv->_inhertor = s_srv_xchange;
+    l_srv->_internal = s_srv_xchange;
     s_srv_xchange->parent = l_srv;
     s_srv_xchange->enabled = false;
     size_t l_prices_count = 0;
-- 
GitLab