diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index f96876ca0c123643f522706371c5c3aef96b8354..6aad4f7ffe6143583d9c305eff9c7eedbb3df851 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -156,14 +156,17 @@ typedef struct dap_chain_net_pvt{
     dap_balancer_type_t balancer_type;
     bool load_mode;
 
-    uint16_t permanent_links_count;
-    dap_link_info_t **permanent_links;
+    uint16_t permanent_links_addrs_count;
+    dap_stream_node_addr_t *permanent_links_addrs;
 
+    uint16_t permanent_links_hosts_count;
+    struct request_link_info **permanent_links_hosts;
+    
     uint16_t authorized_nodes_count;
     dap_stream_node_addr_t *authorized_nodes_addrs;
 
     uint16_t seed_nodes_count;
-    struct request_link_info **seed_nodes_info;
+    struct request_link_info **seed_nodes_hosts;
 
     struct chain_sync_context sync_context;
 
@@ -353,12 +356,12 @@ static struct request_link_info *s_balancer_link_from_cfg(dap_chain_net_t *a_net
         l_idx = dap_random_uint16() % PVT(a_net)->seed_nodes_count;
     break;
     }
-    if ( !PVT(a_net)->seed_nodes_info[l_idx] ) {
+    if ( !PVT(a_net)->seed_nodes_hosts[l_idx] ) {
         // Unresolved before? Let's try again
         const char **l_seed_nodes_hosts = dap_config_get_array_str(a_net->pub.config, "general", "seed_nodes_hosts", NULL);
-        PVT(a_net)->seed_nodes_info[l_idx] = s_net_resolve_host(l_seed_nodes_hosts[l_idx]);
+        PVT(a_net)->seed_nodes_hosts[l_idx] = s_net_resolve_host(l_seed_nodes_hosts[l_idx]);
     }
-    return PVT(a_net)->seed_nodes_info[l_idx];
+    return PVT(a_net)->seed_nodes_hosts[l_idx];
 }
 
 dap_chain_node_info_t *dap_chain_net_get_my_node_info(dap_chain_net_t *a_net)
@@ -435,8 +438,8 @@ static void s_link_manager_callback_connected(dap_link_t *a_link, uint64_t a_net
 static bool s_net_check_link_is_permanent(dap_chain_net_t *a_net, dap_stream_node_addr_t a_addr)
 {
     dap_chain_net_pvt_t *l_net_pvt = PVT(a_net);
-    for (uint16_t i = 0; i < l_net_pvt->permanent_links_count; i++) {
-        if (l_net_pvt->permanent_links[i]->node_addr.uint64 == a_addr.uint64)
+    for (uint16_t i = 0; i < l_net_pvt->permanent_links_addrs_count; i++) {
+        if (l_net_pvt->permanent_links_addrs[i].uint64 == a_addr.uint64)
             return true;
     }
     return false;
@@ -521,22 +524,47 @@ int s_link_manager_link_request(uint64_t a_net_id)
     return dap_worker_exec_callback_on(dap_worker_get_auto(), dap_chain_net_balancer_request, l_arg), 0;
 }
 
+struct request_link_info *s_get_permanent_link_info(dap_chain_net_t *a_net, dap_chain_node_addr_t *a_address)
+{
+    dap_chain_net_pvt_t *l_net_pvt = PVT(a_net);
+    for (uint16_t i = 0; i < l_net_pvt->permanent_links_addrs_count; ++i) {
+        if (l_net_pvt->permanent_links_addrs[i].uint64 == a_address->uint64 &&
+            i < l_net_pvt->permanent_links_hosts_count &&
+            i < l_net_pvt->permanent_links_hosts[i]->addr[0] && 
+            i < l_net_pvt->permanent_links_hosts[i]->port)
+            return l_net_pvt->permanent_links_hosts[i];
+    }
+    return NULL;
+}
+
 int s_link_manager_fill_net_info(dap_link_t *a_link)
 {
 // sanity check
     dap_return_val_if_pass(!a_link, -1);
 // func work
-    dap_chain_node_info_t *l_node_info = NULL;
-    for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next) {
-        if (( l_node_info = dap_chain_node_info_read(net, &a_link->addr) ))
+    const char *l_host = NULL;
+    uint16_t l_port = 0;
+    struct request_link_info *l_permanent_link = NULL;
+    for (dap_chain_net_t *l_net = s_nets_by_name; l_net; l_net = l_net->hh.next) {
+        if ( dap_chain_net_get_state(l_net) > NET_STATE_OFFLINE && ( l_permanent_link = s_get_permanent_link_info(l_net, &a_link->addr) )) {
+            l_host = l_permanent_link->addr;
+            l_port = l_permanent_link->port;
             break;
+        }
     }
-    if (!l_node_info)
-        return -3;
-    a_link->uplink.ready = true;
-    if ( dap_link_manager_link_update(&a_link->addr, l_node_info->ext_host, l_node_info->ext_port) )
-        a_link->uplink.ready = true;
-    DAP_DELETE(l_node_info);
+    if (!l_host || !l_host[0] || !l_port) {
+            dap_chain_node_info_t *l_node_info = NULL;
+        for (dap_chain_net_t *net = s_nets_by_name; net; net = net->hh.next) {
+            if (( l_node_info = dap_chain_node_info_read(net, &a_link->addr) ))
+                break;
+        }
+        if (!l_node_info)
+            return -3;
+        l_host = l_node_info->ext_host;
+        l_port = l_node_info->ext_port;
+        DAP_DELETE(l_node_info);
+    }
+    a_link->uplink.ready = !dap_link_manager_link_update(&a_link->addr, l_host, l_port);
     return 0;
 }
 
@@ -647,6 +675,9 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg)
                 *a_native_ticker= dap_config_get_item_str(a_cfg, "general", "native_ticker");
     dap_chain_net_id_t l_net_id;
 
+    if(!a_node_role)
+        return log_it(L_ERROR, "Can't create l_net, can't read node role config"), NULL;
+
     if(!l_net_name_str || !l_net_id_str || dap_chain_net_id_parse(l_net_id_str, &l_net_id))
         return log_it(L_ERROR, "Can't create l_net, can't read name or ID config"), NULL;
 
@@ -1723,6 +1754,56 @@ int dap_chain_net_test_init()
 #endif
 
 
+int s_nodes_addrs_init(dap_config_t *a_cfg, const char *a_addrs_type, dap_stream_node_addr_t **a_addrs, uint16_t *a_addrs_count)
+{
+    dap_return_val_if_pass(!a_cfg || !a_addrs_type || !a_addrs || !a_addrs_count, -1);
+    const char **l_nodes_addrs = dap_config_get_array_str(a_cfg, "general", a_addrs_type, a_addrs_count);
+    if (*a_addrs_count) {
+        *a_addrs = DAP_NEW_Z_COUNT(dap_chain_node_addr_t, *a_addrs_count);
+        if (!*a_addrs) {
+            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+            return -1;
+        }
+        for (uint16_t i = 0; i < *a_addrs_count; ++i) {
+            dap_chain_node_addr_t l_addr;
+            if (dap_stream_node_addr_from_str(&l_addr, l_nodes_addrs[i])) {
+                log_it(L_ERROR, "Incorrect format of %s address \"%s\", fix net config and restart node", a_addrs_type, l_nodes_addrs[i]);
+                return -2;
+            }
+            (*a_addrs)[i].uint64 = l_addr.uint64;
+        }
+    }
+    return 0;
+}
+
+int s_nodes_hosts_init(dap_chain_net_t *a_net, dap_config_t *a_cfg, const char *a_hosts_type, struct request_link_info ***a_hosts, uint16_t *a_hosts_count)
+{
+    dap_return_val_if_pass(!a_cfg || !a_hosts_type || !a_hosts || !a_hosts_count, -1);
+    const char **l_nodes_addrs = dap_config_get_array_str(a_cfg, "general", a_hosts_type, a_hosts_count);
+    if (*a_hosts_count) {
+        *a_hosts = DAP_NEW_Z_COUNT(struct request_link_info *, *a_hosts_count);
+        if (!*a_hosts) {
+            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+            return -1;
+        }
+        uint16_t i = 0, e = 0;
+        for (; i < *a_hosts_count; ++i) {
+            if (!( (*a_hosts)[i] = s_net_resolve_host(l_nodes_addrs[i]) )) {
+                log_it(L_ERROR, "Incorrect address [ %s : %u ], fix \"%s\" network config"
+                                "or check internet connection and restart node",
+                                (*a_hosts)[i]->addr, (*a_hosts)[i]->port,  a_net->pub.name);
+                ++e;
+                continue;
+            }
+        }
+        debug_if(e, L_ERROR, "%d / %d %s links are invalid or can't be accessed, fix \"%s\""
+                        "network config or check internet connection and restart node",
+                        e, i, a_hosts_type, a_net->pub.name);
+
+    }
+    return 0;
+}
+
 /**
  * @brief load network config settings from cellframe-node.cfg file
  *
@@ -1762,88 +1843,21 @@ int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx)
             l_net->pub.bridged_networks = DAP_REALLOC_COUNT(l_net->pub.bridged_networks, j); // Can be NULL, it's ok
     }
 
-    const char **l_permanent_nodes_addrs = dap_config_get_array_str(l_cfg, "general", "permanent_nodes_addrs", &l_net_pvt->permanent_links_count);
-    if (l_net_pvt->permanent_links_count) {
-        l_net_pvt->permanent_links = DAP_NEW_Z_COUNT(dap_link_info_t *, l_net_pvt->permanent_links_count);
-        if (!l_net_pvt->permanent_links) {
-            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            dap_chain_net_delete(l_net);
-            dap_config_close(l_cfg);
-            return -4;
-        }
-    }
-    for (uint16_t i = 0; i < l_net_pvt->permanent_links_count; ++i) {
-        l_net_pvt->permanent_links[i] = DAP_NEW_Z(dap_link_info_t);
-        if (!l_net_pvt->permanent_links[i]) {
-            log_it(L_CRITICAL, "%s", c_error_memory_alloc);
-            dap_chain_net_delete(l_net);
-            dap_config_close(l_cfg);
-            return -4;
-        }
-        if (dap_stream_node_addr_from_str(&l_net_pvt->permanent_links[i]->node_addr, l_permanent_nodes_addrs[i])) {
-            log_it(L_ERROR, "Incorrect format of node address \"%s\", fix net config and restart node", l_permanent_nodes_addrs[i]);
-            dap_chain_net_delete(l_net);
-            dap_config_close(l_cfg);
-            return -16;
-        }
-    }
-    uint16_t l_permalink_hosts_count = 0, i, e;
-    const char **l_permanent_links_hosts = dap_config_get_array_str(l_cfg, "general", "permanent_nodes_hosts", &l_permalink_hosts_count);
-    for (i = 0, e = 0; i < dap_min(l_permalink_hosts_count, l_net_pvt->permanent_links_count); ++i) {
-        struct request_link_info *l_tmp = s_net_resolve_host( l_permanent_links_hosts[i] );
-        if ( !l_tmp ) {
-            log_it(L_ERROR, "Incorrect address \"%s\", fix \"%s\" network config"
-                            "or check internet connection and restart node",
-                            a_net_name, l_permanent_links_hosts[i]);
-            ++e;
-            continue;
-        }
-        l_net_pvt->permanent_links[i]->uplink_port = l_tmp->port;
-        dap_strncpy(l_net_pvt->permanent_links[i]->uplink_addr, l_tmp->addr, DAP_HOSTADDR_STRLEN);
-        DAP_DELETE(l_tmp);
-    }
-    debug_if(e, L_ERROR, "%d / %d permanent links are invalid or can't be accessed, fix \"%s\""
-                    "network config or check internet connection and restart node",
-                    e, i, a_net_name);
-
-    const char **l_authorized_nodes_addrs = dap_config_get_array_str(l_cfg, "general", "authorized_nodes_addrs", &l_net_pvt->authorized_nodes_count);
-    if (!l_net_pvt->authorized_nodes_count)
-        log_it(L_WARNING, "Can't read PoA nodes addresses");
-    else
-        l_net_pvt->authorized_nodes_addrs = DAP_NEW_Z_COUNT(dap_chain_node_addr_t, l_net_pvt->authorized_nodes_count);
-    for (i = 0; i < l_net_pvt->authorized_nodes_count; ++i) {
-        dap_chain_node_addr_t l_addr;
-        if (dap_stream_node_addr_from_str(&l_addr, l_authorized_nodes_addrs[i])) {
-            log_it(L_ERROR, "Incorrect format of node address \"%s\", fix net config and restart node", l_authorized_nodes_addrs[i]);
-            dap_chain_net_delete(l_net);
-            dap_config_close(l_cfg);
-            return -17;
-        }
-        l_net_pvt->authorized_nodes_addrs[i].uint64 = l_addr.uint64;
-    }
-    const char **l_seed_nodes_hosts = dap_config_get_array_str(l_cfg, "general", "seed_nodes_hosts", &l_net_pvt->seed_nodes_count);
-    if (!l_net_pvt->seed_nodes_count)
-         l_seed_nodes_hosts  = dap_config_get_array_str(l_cfg, "general", "bootstrap_hosts", &l_net_pvt->seed_nodes_count);
-    if (!l_net_pvt->seed_nodes_count)
-        log_it(L_WARNING, "Can't read seed nodes addresses, work with local balancer only");
-    else if (!( l_net_pvt->seed_nodes_info = DAP_NEW_Z_COUNT(struct request_link_info*, l_net_pvt->seed_nodes_count) )) {
-        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+    // read permanent and authorized nodes addrs
+    if (
+        s_nodes_addrs_init(l_cfg, "permanent_nodes_addrs", &l_net_pvt->permanent_links_addrs, &l_net_pvt->permanent_links_addrs_count) ||
+        s_nodes_addrs_init(l_cfg, "authorized_nodes_addrs", &l_net_pvt->authorized_nodes_addrs, &l_net_pvt->authorized_nodes_count) ||
+        s_nodes_hosts_init(l_net, l_cfg, "permanent_nodes_hosts", &l_net_pvt->permanent_links_hosts, &l_net_pvt->permanent_links_hosts_count) ||
+        s_nodes_hosts_init(l_net, l_cfg, "seed_nodes_hosts", &l_net_pvt->seed_nodes_hosts, &l_net_pvt->seed_nodes_count) || 
+        (!l_net_pvt->seed_nodes_count && s_nodes_hosts_init(l_net, l_cfg, "bootstrap_hosts", &l_net_pvt->seed_nodes_hosts, &l_net_pvt->seed_nodes_count) )
+    ) {
         dap_chain_net_delete(l_net);
         dap_config_close(l_cfg);
         return -4;
     }
-    for (i = 0, e = 0; i < l_net_pvt->seed_nodes_count; ++i) {
-        if (!( l_net_pvt->seed_nodes_info[i] = s_net_resolve_host(l_seed_nodes_hosts[i]) )) {
-            log_it(L_ERROR, "Incorrect address \"%s\", fix \"%s\" network config"
-                            "or check internet connection and restart node",
-                            a_net_name, l_seed_nodes_hosts[i]);
-            ++e;
-            continue;
-        }
-    }
-    debug_if(e, L_ERROR, "%d / %d seed links are invalid or can't be accessed, fix \"%s\""
-                    "network config or check internet connection and restart node",
-                    e, i, a_net_name);
+    debug_if(!l_net_pvt->authorized_nodes_count, L_WARNING, "Can't read PoA nodes addresses");
+    if (!l_net_pvt->seed_nodes_count)
+        log_it(L_WARNING, "Can't read seed nodes addresses, work with local balancer only");
 
     /* *** Chains init by configs *** */
     DIR *l_chains_dir = opendir(a_path);
@@ -1875,12 +1889,14 @@ int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx)
     dap_chain_t *l_chain;
     dap_chain_type_t *l_types_arr;
     char l_occupied_default_types[CHAIN_TYPE_MAX] = { 0 };
-    uint16_t k;
     HASH_ITER(hh, l_all_chain_configs, l_chain_config, l_tmp_cfg) {
         if (( l_chain = dap_chain_load_from_cfg(l_net->pub.name, l_net->pub.id, l_chain_config) )) {
             DL_APPEND(l_net->pub.chains, l_chain);
             l_types_arr = l_chain->default_datum_types;
-            for (i = 0, k = l_chain->default_datum_types_count; i < k; ++i) {
+            uint16_t
+                i = 0,
+                k = l_chain->default_datum_types_count;
+            for ( ; i < k; ++i) {
                 if ( l_occupied_default_types[l_types_arr[i]] ) {
                     if ( i < k - 1 )
                         l_types_arr[i] =
@@ -2433,14 +2449,14 @@ char * dap_chain_net_get_gdb_group_mempool_by_chain_type(dap_chain_net_t *a_net,
  * @param l_net
  * @return
  */
-dap_chain_net_state_t dap_chain_net_get_state (dap_chain_net_t * l_net)
+dap_chain_net_state_t dap_chain_net_get_state (dap_chain_net_t *a_net)
 {
-    return PVT(l_net)->state;
+    return PVT(a_net)->state;
 }
 
-dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t * l_net)
+dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t *a_net)
 {
-    return  PVT(l_net)->node_info ? &PVT(l_net)->node_info->cell_id: 0;
+    return  PVT(a_net)->node_info ? &PVT(a_net)->node_info->cell_id: 0;
 }
 
 /**
@@ -3272,25 +3288,12 @@ int dap_chain_net_state_go_to(dap_chain_net_t *a_net, dap_chain_net_state_t a_ne
         dap_link_manager_set_net_condition(a_net->pub.id.uint64, true);
         uint16_t l_permalink_hosts_count = 0;
         dap_config_get_array_str(a_net->pub.config, "general", "permanent_nodes_hosts", &l_permalink_hosts_count);
-        l_permalink_hosts_count = dap_min(l_permalink_hosts_count, PVT(a_net)->permanent_links_count);
-        for (uint16_t i = 0; i < l_permalink_hosts_count; ++i) {
-            dap_link_info_t *l_permalink_info = PVT(a_net)->permanent_links[i];
-            if ( !*l_permalink_info->uplink_addr ) {
-                // Unresolved before? Let's try again
-                const char **l_permanent_links_hosts = dap_config_get_array_str(a_net->pub.config, "general", "permanent_nodes_hosts", NULL);
-                struct request_link_info *l_tmp = s_net_resolve_host(l_permanent_links_hosts[i]);
-                if (l_tmp) {
-                    l_permalink_info->uplink_port = l_tmp->port;
-                    dap_strncpy(l_permalink_info->uplink_addr, l_tmp->addr, DAP_HOSTADDR_STRLEN);
-                    DAP_DELETE(l_tmp);
-                } else {
-                    log_it(L_ERROR, "Can't resolve permanent link address %s for net %s, possibly an internet connection issue",
-                                    l_permanent_links_hosts[i], a_net->pub.name);
-                    continue;
-                }
-            }
-            if (dap_chain_net_link_add(a_net, &l_permalink_info->node_addr, l_permalink_info->uplink_addr, l_permalink_info->uplink_port)) {
-                log_it(L_ERROR, "Can't create permanent link to addr " NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_permalink_info->node_addr));
+        for (uint16_t i = 0; i < PVT(a_net)->permanent_links_addrs_count; ++i) {
+            if (dap_chain_net_link_add(a_net, PVT(a_net)->permanent_links_addrs + i, 
+                i < PVT(a_net)->permanent_links_hosts_count ? (PVT(a_net)->permanent_links_hosts[i])->addr : NULL,
+                i < PVT(a_net)->permanent_links_hosts_count ? (PVT(a_net)->permanent_links_hosts[i])->port : 0)
+             ) {
+                log_it(L_ERROR, "Can't create permanent link to addr " NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS(PVT(a_net)->permanent_links_addrs + i));
                 continue;
             }
             PVT(a_net)->state = NET_STATE_LINKS_CONNECTING;