From e929addc06b73ec7c66a0fde9369c9b6a4722c2a Mon Sep 17 00:00:00 2001
From: "pavel.uhanov" <pavel.uhanov@demlabs.net>
Date: Sat, 28 Dec 2024 07:59:04 +0000
Subject: [PATCH] feature-13637

---
 dap-sdk                                       |   2 +-
 modules/chain/dap_chain_srv.c                 |   2 +
 modules/chain/tests/dap_chain_ledger_tests.c  |   6 +-
 .../consensus/esbocs/dap_chain_cs_esbocs.c    |   8 +-
 modules/datum/dap_chain_datum_decree.c        |  23 +-
 modules/datum/dap_chain_datum_token.c         |   2 +-
 modules/datum/dap_chain_datum_tx_items.c      |  21 +-
 modules/datum/dap_chain_datum_tx_receipt.c    |   2 +-
 .../datum/include/dap_chain_datum_decree.h    |   9 +
 .../datum/include/dap_chain_datum_tx_items.h  |   6 +-
 .../include/dap_chain_datum_tx_out_cond.h     |   1 +
 modules/ledger/dap_chain_ledger.c             |  35 ++
 modules/ledger/dap_chain_ledger_decree.c      |  15 +-
 modules/ledger/include/dap_chain_ledger.h     |   1 +
 modules/net-srv/dap_chain_net_srv_order.c     |   2 +-
 modules/net/dap_chain_net_ch.c                |   2 +-
 modules/node-cli/dap_chain_node_cli_cmd.c     |   4 +-
 .../node-cli/dap_chain_node_cli_cmd_token.c   |   2 +-
 modules/node-cli/dap_chain_node_cli_cmd_tx.c  |  10 +-
 .../dap_chain_net_srv_stake_pos_delegate.c    | 354 ++++++++++++++++--
 .../dap_chain_net_srv_stake_pos_delegate.h    |   4 +-
 modules/type/blocks/dap_chain_block.c         |   2 +-
 modules/type/blocks/dap_chain_cs_blocks.c     |   2 +-
 modules/type/dag/dap_chain_cs_dag_event.c     |   6 +-
 modules/wallet/dap_chain_wallet.c             |  10 +-
 modules/wallet/include/dap_chain_wallet.h     |   3 +-
 26 files changed, 471 insertions(+), 63 deletions(-)

diff --git a/dap-sdk b/dap-sdk
index 16b196ba28..0b186bf875 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit 16b196ba28b0bd3caac2a263710093333b271b04
+Subproject commit 0b186bf875b9eac4d0df092f6bb849f73994251b
diff --git a/modules/chain/dap_chain_srv.c b/modules/chain/dap_chain_srv.c
index f230fc9461..9a405ce2d6 100644
--- a/modules/chain/dap_chain_srv.c
+++ b/modules/chain/dap_chain_srv.c
@@ -234,6 +234,8 @@ void *dap_chain_srv_get_internal(dap_chain_net_id_t a_net_id, dap_chain_srv_uid_
     struct service_list *l_service_item = s_service_find(a_srv_uid);
     if (!l_service_item)
         return NULL;
+    if (a_net_id.uint64 == 0)
+        return l_service_item->networks;
     struct network_service *l_service = s_net_service_find(l_service_item, a_net_id);
     return l_service ? l_service->service : NULL;
 }
diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c
index 0d095b8844..6e18ff6e92 100644
--- a/modules/chain/tests/dap_chain_ledger_tests.c
+++ b/modules/chain/tests/dap_chain_ledger_tests.c
@@ -42,7 +42,7 @@ dap_chain_datum_token_t *dap_ledger_test_create_datum_update(dap_cert_t *a_cert,
         memcpy(l_token->tsd_n_signs, a_tsd_section, a_size_tsd_section);
     }
     dap_sign_t * l_sign = dap_cert_sign(a_cert,l_token,
-                                        sizeof(*l_token) + a_size_tsd_section, 0);
+                                        sizeof(*l_token) + a_size_tsd_section, DAP_SIGN_HASH_TYPE_DEFAULT);
     if (l_sign) {
         size_t l_sign_size = dap_sign_get_size(l_sign);
         l_token = DAP_REALLOC(l_token, sizeof(dap_chain_datum_token_t) + a_size_tsd_section + l_sign_size);
@@ -77,7 +77,7 @@ dap_chain_datum_token_t  *dap_ledger_test_create_datum_decl(dap_cert_t *a_cert,
         memcpy(l_token->tsd_n_signs, a_tsd_section, a_size_tsd_section);
     }
     dap_sign_t * l_sign = dap_cert_sign(a_cert,l_token,
-                                        sizeof(*l_token) + a_size_tsd_section, 0);
+                                        sizeof(*l_token) + a_size_tsd_section, DAP_SIGN_HASH_TYPE_DEFAULT);
     if (l_sign) {
         size_t l_sign_size = dap_sign_get_size(l_sign);
         l_token = DAP_REALLOC(l_token, sizeof(dap_chain_datum_token_t) + a_size_tsd_section + l_sign_size);
@@ -365,7 +365,7 @@ int dap_ledger_test_create_reward_decree(dap_chain_t *a_chain, dap_chain_net_id_
     l_tsd->size = sizeof(uint256_t);
     *(uint256_t*)(l_tsd->data) = a_value;
     // Sign it
-    dap_sign_t *l_sign = dap_cert_sign(a_cert, l_decree, l_decree_size, 0);
+    dap_sign_t *l_sign = dap_cert_sign(a_cert, l_decree, l_decree_size, DAP_SIGN_HASH_TYPE_DEFAULT);
     if (!l_sign) {
         DAP_DELETE(l_decree);
         return -2;
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index 12c8828be7..ed9be96ca9 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -308,7 +308,7 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
             dap_hash_fast_t l_stake_tx_hash = {};
             uint256_t l_weight = dap_chain_net_srv_stake_get_allowed_min_value(a_chain->net_id);
             dap_chain_net_srv_stake_key_delegate(l_net, &l_signing_addr, &l_stake_tx_hash,
-                                                 l_weight, &l_signer_node_addr);
+                                                 l_weight, &l_signer_node_addr, dap_pkey_from_enc_key(l_cert_cur->enc_key));
         }
     }
     if (!i)
@@ -748,7 +748,7 @@ static int s_callback_purge(dap_chain_t *a_chain)
     for (dap_list_t *it = l_esbocs_pvt->poa_validators; it; it = it->next) {
         dap_chain_esbocs_validator_t *l_validator = it->data;
         dap_chain_net_srv_stake_key_delegate(l_net, &l_validator->signing_addr, &l_stake_tx_hash,
-                                             l_weight, &l_validator->node_addr);
+                                             l_weight, &l_validator->node_addr, NULL);
     }
     l_esbocs_pvt->min_validators_count = l_esbocs_pvt->start_validators_min;
     return 0;
@@ -2539,7 +2539,7 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain
                             l_message->hdr.attempt_num, l_candidate_hash_str);
             size_t l_offset = dap_chain_block_get_sign_offset(l_store->candidate, l_store->candidate_size);
             dap_sign_t *l_candidate_sign = dap_sign_create(PVT(l_session->esbocs)->blocks_sign_key,
-                                            l_store->candidate, l_offset + sizeof(l_store->candidate->hdr), 0);
+                                            l_store->candidate, l_offset + sizeof(l_store->candidate->hdr), DAP_SIGN_ADD_PKEY_HASHING_FLAG(DAP_SIGN_HASH_TYPE_DEFAULT));
             size_t l_candidate_sign_size = dap_sign_get_size(l_candidate_sign);
             s_message_send(l_session, DAP_CHAIN_ESBOCS_MSG_TYPE_COMMIT_SIGN, l_candidate_hash,
                            l_candidate_sign, l_candidate_sign_size, l_session->cur_round.validators_list);
@@ -2744,7 +2744,7 @@ static void s_message_send(dap_chain_esbocs_session_t *a_session, uint8_t a_mess
                                                            NODE_ADDR_FP_ARGS_S(l_validator->node_addr));
             l_message->hdr.recv_addr = l_validator->node_addr;
             l_message->hdr.sign_size = 0;
-            dap_sign_t *l_sign = dap_sign_create( PVT(a_session->esbocs)->blocks_sign_key, l_message, l_message_size, 0 );
+            dap_sign_t *l_sign = dap_sign_create( PVT(a_session->esbocs)->blocks_sign_key, l_message, l_message_size, DAP_SIGN_ADD_PKEY_HASHING_FLAG(DAP_SIGN_HASH_TYPE_DEFAULT) );
             size_t l_sign_size = dap_sign_get_size(l_sign);
             l_message->hdr.sign_size = l_sign_size;
             dap_chain_esbocs_message_t *l_message_signed = DAP_REALLOC_RET_IF_FAIL(l_message, l_message_size + l_sign_size, l_sign, l_message);
diff --git a/modules/datum/dap_chain_datum_decree.c b/modules/datum/dap_chain_datum_decree.c
index 007bfdc1bb..e2f613465f 100644
--- a/modules/datum/dap_chain_datum_decree.c
+++ b/modules/datum/dap_chain_datum_decree.c
@@ -149,6 +149,20 @@ int dap_chain_datum_decree_get_ban_addr(dap_chain_datum_decree_t *a_decree, cons
     return l_tsd ? ( *a_addr = dap_tsd_get_string_const(l_tsd), !dap_strcmp(*a_addr, DAP_TSD_CORRUPTED_STRING) ) : 1;
 }
 
+/**
+ * @brief get pkey from decree tsd
+ * @param a_decree
+ * @return pointer to dap_pkey_t if find, if not or error - NULL
+ */
+dap_pkey_t *dap_chain_datum_decree_get_pkey(dap_chain_datum_decree_t *a_decree)
+{
+    dap_return_val_if_fail(a_decree, NULL);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY);
+    if (!l_tsd)
+        return NULL;
+    return dap_pkey_get_size((dap_pkey_t *)l_tsd->data) == l_tsd->size ? (dap_pkey_t *)l_tsd->data : NULL;
+}
+
 void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type)
 {
     char *l_type_str;
@@ -309,6 +323,13 @@ void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_d
             dap_sign_type_t l_sign_type = { .type = l_type };
             json_object_object_add(a_json_out, "Signature type", json_object_new_string(dap_sign_type_to_str(l_sign_type)));
             break;
+        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY:
+            if (l_tsd->size != dap_pkey_get_size((dap_pkey_t *)(l_tsd->data))) {
+                json_object_object_add(a_json_out, "pkey type", json_object_new_string("WRONG SIZE"));
+                break;
+            }
+            json_object_object_add(a_json_out, "pkey type", json_object_new_string( dap_pkey_type_to_str(((dap_pkey_t *)(l_tsd->data))->header.type) ));
+            break; 
         default:
             json_object_object_add(a_json_out, "UNKNOWN_TYPE_TSD_SECTION", json_object_new_string(""));
             break;
@@ -379,7 +400,7 @@ dap_chain_datum_decree_t *dap_chain_datum_decree_sign_in_cycle(dap_cert_t **a_ce
 
     for(size_t i = 0; i < a_certs_count; i++) {
         dap_sign_t * l_sign = dap_cert_sign(a_certs[i], a_datum_decree,
-                                            sizeof(dap_chain_datum_decree_t) + a_datum_decree->header.data_size, 0);
+                                            sizeof(dap_chain_datum_decree_t) + a_datum_decree->header.data_size, DAP_SIGN_HASH_TYPE_DEFAULT);
         if (!l_sign) {
             log_it(L_ERROR, "Decree signing failed");
             DAP_DELETE(a_datum_decree);
diff --git a/modules/datum/dap_chain_datum_token.c b/modules/datum/dap_chain_datum_token.c
index cd066fca13..a396f9bbeb 100644
--- a/modules/datum/dap_chain_datum_token.c
+++ b/modules/datum/dap_chain_datum_token.c
@@ -427,7 +427,7 @@ dap_chain_datum_token_emission_t *dap_chain_datum_emission_add_sign(dap_enc_key_
     }
     a_emission->data.type_auth.signs_count = 0;
     a_emission->data.type_auth.tsd_n_signs_size = 0;
-    dap_sign_t *l_new_sign = dap_sign_create(a_sign_key, a_emission, sizeof(dap_chain_datum_token_emission_t) + a_emission->data.type_auth.tsd_total_size, 0);
+    dap_sign_t *l_new_sign = dap_sign_create(a_sign_key, a_emission, sizeof(dap_chain_datum_token_emission_t) + a_emission->data.type_auth.tsd_total_size, DAP_SIGN_HASH_TYPE_DEFAULT);
     if (!l_new_sign)
         return NULL;
     size_t l_emission_size = dap_chain_datum_emission_get_size((uint8_t *)a_emission);
diff --git a/modules/datum/dap_chain_datum_tx_items.c b/modules/datum/dap_chain_datum_tx_items.c
index b7307dda1b..b3c066ad7f 100644
--- a/modules/datum/dap_chain_datum_tx_items.c
+++ b/modules/datum/dap_chain_datum_tx_items.c
@@ -340,12 +340,14 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap
 
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake(dap_chain_srv_uid_t a_srv_uid, uint256_t a_value,
                                                                            dap_chain_addr_t *a_signing_addr, dap_chain_node_addr_t *a_signer_node_addr,
-                                                                           dap_chain_addr_t *a_sovereign_addr, uint256_t a_sovereign_tax)
+                                                                           dap_chain_addr_t *a_sovereign_addr, uint256_t a_sovereign_tax, dap_pkey_t *a_pkey)
 {
     if (IS_ZERO_256(a_value))
         return NULL;
-    size_t l_tsd_total_size = a_sovereign_addr && !dap_chain_addr_is_blank(a_sovereign_addr) ?
-                                dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size() : 0;
+    bool l_tsd_sovereign_addr = a_sovereign_addr && !dap_chain_addr_is_blank(a_sovereign_addr);
+    size_t l_pkey_size = dap_pkey_get_size(a_pkey);
+    size_t l_tsd_total_size =  dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size(l_tsd_sovereign_addr, l_pkey_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) + l_tsd_total_size);
     if (!l_item) {
         return NULL;
@@ -358,8 +360,15 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake(dap_c
     l_item->subtype.srv_stake_pos_delegate.signer_node_addr = *a_signer_node_addr;
     if (l_tsd_total_size) {
         l_item->tsd_size = l_tsd_total_size;
-        byte_t *l_next_tsd_ptr = dap_tsd_write(l_item->tsd, DAP_CHAIN_TX_OUT_COND_TSD_ADDR, a_sovereign_addr, sizeof(*a_sovereign_addr));
-        dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_VALUE, &a_sovereign_tax, sizeof(a_sovereign_tax));
+        byte_t *l_next_tsd_ptr = l_item->tsd;
+        if (l_tsd_sovereign_addr) {
+            l_next_tsd_ptr = dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_ADDR, a_sovereign_addr, sizeof(*a_sovereign_addr));
+            l_next_tsd_ptr = dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_VALUE, &a_sovereign_tax, sizeof(a_sovereign_tax));
+        }
+        if (l_pkey_size) {
+            dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD, a_pkey, l_pkey_size);
+            l_item->subtype.srv_stake_pos_delegate.flags = DAP_SIGN_ADD_PKEY_HASHING_FLAG(l_item->subtype.srv_stake_pos_delegate.flags);
+        }
     }
     return l_item;
 }
@@ -432,7 +441,7 @@ dap_chain_tx_sig_t *dap_chain_datum_tx_item_sign_create(dap_enc_key_t *a_key, da
         return NULL;
     }
     l_tx->header.tx_items_size = 0;
-    dap_sign_t *l_chain_sign = dap_sign_create(a_key, l_tx, l_tx_size, 0);
+    dap_sign_t *l_chain_sign = dap_sign_create(a_key, l_tx, l_tx_size, DAP_SIGN_HASH_TYPE_DEFAULT);
     DAP_DELETE(l_tx);
     if (!l_chain_sign)
         return NULL;
diff --git a/modules/datum/dap_chain_datum_tx_receipt.c b/modules/datum/dap_chain_datum_tx_receipt.c
index 4624ef30e5..52aef80185 100644
--- a/modules/datum/dap_chain_datum_tx_receipt.c
+++ b/modules/datum/dap_chain_datum_tx_receipt.c
@@ -71,7 +71,7 @@ dap_chain_datum_tx_receipt_t *dap_chain_datum_tx_receipt_sign_add(dap_chain_datu
         return NULL;
     }
 
-    dap_sign_t *l_sign = dap_sign_create(a_key, &a_receipt->receipt_info, sizeof(a_receipt->receipt_info), 0);
+    dap_sign_t *l_sign = dap_sign_create(a_key, &a_receipt->receipt_info, sizeof(a_receipt->receipt_info), DAP_SIGN_HASH_TYPE_DEFAULT);
     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?");
diff --git a/modules/datum/include/dap_chain_datum_decree.h b/modules/datum/include/dap_chain_datum_decree.h
index 075939ce71..da4a463cad 100644
--- a/modules/datum/include/dap_chain_datum_decree.h
+++ b/modules/datum/include/dap_chain_datum_decree.h
@@ -76,6 +76,7 @@ DAP_STATIC_INLINE size_t dap_chain_datum_decree_get_size(dap_chain_datum_decree_
 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS          0x000D
 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE         0x000E
 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK                      0x000F
+#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE             0x0010 
 
 // DECREE TSD types
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE                               0x0100
@@ -95,6 +96,7 @@ DAP_STATIC_INLINE size_t dap_chain_datum_decree_get_size(dap_chain_datum_decree_
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION                              0x010A
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE                      0x010B
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_BLOCK_NUM                           0x010C
+#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY                          0x010D 
 
 DAP_STATIC_INLINE const char *dap_chain_datum_decree_subtype_to_str(uint16_t a_decree_subtype)
 {
@@ -125,6 +127,8 @@ DAP_STATIC_INLINE const char *dap_chain_datum_decree_subtype_to_str(uint16_t a_d
         return "DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS";
     case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE:
         return "DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE";
+    case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE:
+        return "DECREE_COMMON_SUBTYPE_STAKE_UPDATE";
     default:
         return "DECREE_SUBTYPE_UNKNOWN";
     }
@@ -157,6 +161,8 @@ DAP_STATIC_INLINE uint16_t dap_chain_datum_decree_type_from_str(const char *a_de
         return DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS;
     } else if (!dap_strcmp(a_decree_type, "check_signs_structure")) {
         return DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE;
+    } else if (!dap_strcmp(a_decree_type, "stake_update")) {
+        return DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE;
     } else {
         return 0;
     }
@@ -196,6 +202,8 @@ DAP_STATIC_INLINE const char *dap_chain_datum_decree_tsd_type_to_str(uint16_t a_
          return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION";
     case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE:
          return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY:
+         return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY";
     default:
         return "DECREE_TSD_TYPE_UNKNOWN";
     }
@@ -303,6 +311,7 @@ int dap_chain_datum_decree_get_stake_min_signers_count(dap_chain_datum_decree_t
 int dap_chain_datum_decree_get_action(dap_chain_datum_decree_t *a_decree, uint8_t *a_action);
 int dap_chain_datum_decree_get_signature_type(dap_chain_datum_decree_t *a_decree, uint32_t *a_signature_type);
 int dap_chain_datum_decree_get_ban_addr(dap_chain_datum_decree_t *a_decree, const char **a_addr);
+dap_pkey_t *dap_chain_datum_decree_get_pkey(dap_chain_datum_decree_t *a_decree);
 
 /**
  * @breif dap_chain_datum_decree_dump Dump information about decree
diff --git a/modules/datum/include/dap_chain_datum_tx_items.h b/modules/datum/include/dap_chain_datum_tx_items.h
index 25ef0070a4..c8be707da1 100644
--- a/modules/datum/include/dap_chain_datum_tx_items.h
+++ b/modules/datum/include/dap_chain_datum_tx_items.h
@@ -155,8 +155,8 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap
                                                                              const char *a_token, uint256_t a_value_rate, const dap_chain_addr_t *a_seller_addr,
                                                                              const void *a_params, uint32_t a_params_size);
 
-DAP_STATIC_INLINE uint32_t dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size() {
-    return sizeof(dap_chain_addr_t) + sizeof(uint256_t) + 2 * sizeof(dap_tsd_t);
+DAP_STATIC_INLINE uint32_t dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size(bool a_sovereign_addr, uint32_t a_pkey_size) {
+    return a_sovereign_addr ? sizeof(dap_chain_addr_t) + sizeof(uint256_t) + 2 * sizeof(dap_tsd_t) : 0 + a_pkey_size ? a_pkey_size + sizeof(dap_tsd_t) : 0;
 }
 
 /**
@@ -166,7 +166,7 @@ DAP_STATIC_INLINE uint32_t dap_chain_datum_tx_item_out_cond_create_srv_stake_get
  */
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake(dap_chain_srv_uid_t a_srv_uid, uint256_t a_value,
                                                                            dap_chain_addr_t *a_signing_addr, dap_chain_node_addr_t *a_signer_node_addr,
-                                                                           dap_chain_addr_t *a_sovereign_addr, uint256_t a_sovereign_tax);
+                                                                           dap_chain_addr_t *a_sovereign_addr, uint256_t a_sovereign_tax, dap_pkey_t *a_pkey);
 
 // Create cond out
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake_lock(dap_chain_srv_uid_t a_srv_uid,
diff --git a/modules/datum/include/dap_chain_datum_tx_out_cond.h b/modules/datum/include/dap_chain_datum_tx_out_cond.h
index 8a9a1b25fa..c765295b49 100644
--- a/modules/datum/include/dap_chain_datum_tx_out_cond.h
+++ b/modules/datum/include/dap_chain_datum_tx_out_cond.h
@@ -116,6 +116,7 @@ typedef struct dap_chain_tx_out_cond {
             dap_chain_addr_t signing_addr;
             // Node address of signer with this stake
             dap_chain_node_addr_t signer_node_addr;
+            uint32_t flags;
         } DAP_ALIGN_PACKED srv_stake_pos_delegate;
         struct {
             dap_time_t		time_unlock;
diff --git a/modules/ledger/dap_chain_ledger.c b/modules/ledger/dap_chain_ledger.c
index 853193834d..1f1cb90674 100644
--- a/modules/ledger/dap_chain_ledger.c
+++ b/modules/ledger/dap_chain_ledger.c
@@ -1227,6 +1227,41 @@ const dap_chain_datum_tx_t* dap_ledger_tx_find_by_pkey(dap_ledger_t *a_ledger,
     pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
     return l_cur_tx;
 }
+/**
+ * @brief dap_ledger_find_pkey_by_hash
+ * @param a_ledger to search
+ * @param a_pkey_hash - pkey hash
+ * @return pointer to dap_pkey_t if finded, other - NULL
+ */
+dap_pkey_t *dap_ledger_find_pkey_by_hash(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_pkey_hash)
+{
+    dap_return_val_if_pass(!a_pkey_hash || dap_hash_fast_is_blank(a_pkey_hash), NULL);
+
+    dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
+    dap_ledger_tx_item_t *l_iter_current, *l_item_tmp;
+    dap_pkey_t *l_ret = NULL;
+    pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock);
+    HASH_ITER(hh, l_ledger_pvt->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;
+        // Get sign item from transaction
+        dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(l_tx_tmp, NULL,
+                NULL, TX_ITEM_TYPE_SIG, NULL);
+        // Get dap_sign_t from item
+        dap_sign_t *l_sig = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig);
+        if(l_sig) {
+            // compare public key in transaction with a_public_key
+            dap_chain_hash_fast_t l_sign_hash = {};
+            dap_sign_get_pkey_hash(l_sig, &l_sign_hash);
+            if(!memcmp(&l_sign_hash, a_pkey_hash, sizeof(dap_chain_hash_fast_t))) {
+                l_ret = dap_pkey_get_from_sign(l_sig);
+                break;
+            }
+        }
+    }
+    pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
+    return l_ret;
+}
 
 /**
  * @brief Get all transactions from the cache with the out_cond item
diff --git a/modules/ledger/dap_chain_ledger_decree.c b/modules/ledger/dap_chain_ledger_decree.c
index 3ecfd2f963..1756af8d5e 100644
--- a/modules/ledger/dap_chain_ledger_decree.c
+++ b/modules/ledger/dap_chain_ledger_decree.c
@@ -410,9 +410,22 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
             }
             if (!a_apply)
                 break;
-            dap_chain_net_srv_stake_key_delegate(a_net, &l_addr, &l_hash, l_value, &l_node_addr);
+            
+            dap_chain_net_srv_stake_key_delegate(a_net, &l_addr, &l_hash, l_value, &l_node_addr, NULL);
             dap_chain_net_srv_stake_add_approving_decree_info(a_decree, a_net);
             break;
+        case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE:
+            if (!a_anchored)
+                break;
+            if (!a_apply)
+                break;
+            dap_pkey_t *l_pkey = NULL;
+            if (! (l_pkey = dap_chain_datum_decree_get_pkey(a_decree)) ){
+                log_it(L_WARNING,"Can't get pkey from decree.");
+                return -105;
+            }
+            dap_chain_net_srv_stake_pkey_update(a_net, l_pkey);
+            break;
         case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE: {
             if (dap_chain_datum_decree_get_stake_signing_addr(a_decree, &l_addr)){
                 log_it(L_WARNING,"Can't get signing address from decree.");
diff --git a/modules/ledger/include/dap_chain_ledger.h b/modules/ledger/include/dap_chain_ledger.h
index 191093ae4a..5892b17f3d 100644
--- a/modules/ledger/include/dap_chain_ledger.h
+++ b/modules/ledger/include/dap_chain_ledger.h
@@ -506,3 +506,4 @@ dap_ledger_hardfork_anchors_t *dap_ledger_anchors_aggregate(dap_ledger_t *a_ledg
 
 uint256_t dap_ledger_coin_get_uncoloured_value(dap_ledger_t *a_ledger, dap_hash_fast_t *a_voting_hash, dap_hash_fast_t *a_tx_prev_hash, int a_out_idx);
 void dap_ledger_tx_clear_colour(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash);
+dap_pkey_t *dap_ledger_find_pkey_by_hash(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_pkey_hash);
diff --git a/modules/net-srv/dap_chain_net_srv_order.c b/modules/net-srv/dap_chain_net_srv_order.c
index 4767c73355..d49efaf214 100644
--- a/modules/net-srv/dap_chain_net_srv_order.c
+++ b/modules/net-srv/dap_chain_net_srv_order.c
@@ -360,7 +360,7 @@ dap_chain_net_srv_order_t *dap_chain_net_srv_order_compose(dap_chain_net_t *a_ne
     if ( a_price_ticker)
         strncpy(l_order->price_ticker, a_price_ticker, DAP_CHAIN_TICKER_SIZE_MAX - 1);
     l_order->units = a_units;
-    dap_sign_t *l_sign = dap_sign_create(a_key, l_order, sizeof(dap_chain_net_srv_order_t) + l_order->ext_size, 0);
+    dap_sign_t *l_sign = dap_sign_create(a_key, l_order, sizeof(dap_chain_net_srv_order_t) + l_order->ext_size, DAP_SIGN_HASH_TYPE_DEFAULT);
     if (!l_sign) {
         DAP_DELETE(l_order);
         return NULL;
diff --git a/modules/net/dap_chain_net_ch.c b/modules/net/dap_chain_net_ch.c
index 35903022e6..33e9ebd115 100644
--- a/modules/net/dap_chain_net_ch.c
+++ b/modules/net/dap_chain_net_ch.c
@@ -231,7 +231,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void* a_arg)
 
             if (l_enc_key_pvt) {
                 flags = flags | F_CERT;//faund sert
-                l_sign = dap_sign_create(l_enc_key_pvt, (uint8_t*)l_ch_chain_net_pkt->data, l_ch_chain_net_pkt->hdr.data_size, 0);
+                l_sign = dap_sign_create(l_enc_key_pvt, (uint8_t*)l_ch_chain_net_pkt->data, l_ch_chain_net_pkt->hdr.data_size, DAP_SIGN_HASH_TYPE_DEFAULT);
                 if (l_sign) {
                     sign_s = dap_sign_get_size(l_sign);
                     flags = flags | D_SIGN;//data signed
diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c
index 037c382c1d..a70606456a 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd.c
@@ -3859,7 +3859,7 @@ static dap_chain_datum_anchor_t * s_sign_anchor_in_cycle(dap_cert_t ** a_certs,
     for(size_t i = 0; i < a_certs_count; i++)
     {
         dap_sign_t * l_sign = dap_cert_sign(a_certs[i],  a_datum_anchor,
-           sizeof(dap_chain_datum_anchor_t) + a_datum_anchor->header.data_size, 0);
+           sizeof(dap_chain_datum_anchor_t) + a_datum_anchor->header.data_size, DAP_SIGN_HASH_TYPE_DEFAULT);
 
         if (l_sign) {
             size_t l_sign_size = dap_sign_get_size(l_sign);
@@ -5266,7 +5266,7 @@ static int s_sign_file(const char *a_filename, dap_sign_signer_file_t a_flags, c
         DAP_DELETE(l_buffer);
         return -8;
     }
-    *a_signed = dap_sign_create(l_cert->enc_key, l_data, l_full_size_for_sign, 0);
+    *a_signed = dap_sign_create(l_cert->enc_key, l_data, l_full_size_for_sign, DAP_SIGN_HASH_TYPE_DEFAULT);
     if (*a_signed == NULL) {
         DAP_DELETE(l_buffer);
         return -9;
diff --git a/modules/node-cli/dap_chain_node_cli_cmd_token.c b/modules/node-cli/dap_chain_node_cli_cmd_token.c
index 0ea06e1d4b..d839b90ce1 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd_token.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd_token.c
@@ -82,7 +82,7 @@ static dap_chain_datum_token_t * s_sign_cert_in_cycle(dap_cert_t ** l_certs, dap
 
     for (size_t i = 0; i < l_certs_count; i++) {
         dap_sign_t * l_sign = dap_cert_sign(l_certs[i],  l_datum_token,
-           sizeof(*l_datum_token) + l_tsd_size, 0);
+           sizeof(*l_datum_token) + l_tsd_size, DAP_SIGN_HASH_TYPE_DEFAULT);
         if (l_sign) {
             size_t l_sign_size = dap_sign_get_size(l_sign);
             dap_chain_datum_token_t *l_datum_token_new
diff --git a/modules/node-cli/dap_chain_node_cli_cmd_tx.c b/modules/node-cli/dap_chain_node_cli_cmd_tx.c
index ada6781479..486a2182e8 100644
--- a/modules/node-cli/dap_chain_node_cli_cmd_tx.c
+++ b/modules/node-cli/dap_chain_node_cli_cmd_tx.c
@@ -1730,8 +1730,16 @@ int s_json_rpc_tx_parse_json(dap_chain_net_t *a_net, dap_chain_t *a_chain, json_
                     log_it(L_ERROR, "Json TX: bad node_addr in OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE");
                     break;
                 }
+                // Maybe should get pkey and tronsform to dap_pkey_t
+                dap_pkey_t *l_pkey = NULL;
+                const char *l_pkey_full_str = s_json_get_text(l_json_item_obj, "pkey_full");
+                if(l_pkey_full_str) { 
+                    l_pkey = dap_pkey_get_from_str(l_pkey_full_str);
+                    debug_if(!l_pkey, L_ERROR, "Json TX: bad pkey in OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE");
+                }
+                
                 dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_item_out_cond_create_srv_stake(l_srv_uid, l_value, l_signing_addr,
-                                                                                                             &l_signer_node_addr, NULL, uint256_0);
+                                                                                                             &l_signer_node_addr, NULL, uint256_0, l_pkey);
                 l_item = (const uint8_t*) l_out_cond_item;
                 // Save value for using in In item
                 if(l_item) {
diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
index 9fe9c7ee21..f4f1b2fd1e 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
@@ -167,6 +167,20 @@ DAP_STATIC_INLINE char *s_get_approved_group(dap_chain_net_t *a_net)
     return a_net ? dap_strdup_printf("%s.orders.stake.approved", a_net->pub.gdb_groups_prefix) : NULL;
 }
 
+static dap_pkey_t *s_get_pkey_by_hash_callback(const uint8_t *a_hash)
+{
+    dap_list_t *l_srv_stake_list = dap_chain_srv_get_internal((dap_chain_net_id_t) { .uint64 = 0 }, (dap_chain_srv_uid_t) { .uint64 = DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ID });
+    dap_chain_net_srv_stake_item_t *l_stake = NULL;
+    for ( ; l_srv_stake_list && !l_stake; l_srv_stake_list = l_srv_stake_list->next) {
+        struct srv_stake *l_srv_stake = l_srv_stake_list->data;
+        HASH_FIND(hh, l_srv_stake->itemlist, a_hash, sizeof(dap_hash_fast_t), l_stake);
+    }
+    if (l_stake) {
+        return l_stake->pkey;
+    }
+    return NULL; 
+}
+
 /**
  * @brief dap_stream_ch_vpn_init Init actions for VPN stream channel
  * @return 0 if everything is okay, lesser then zero if errors
@@ -189,7 +203,7 @@ int dap_chain_net_srv_stake_pos_delegate_init()
     "srv_stake order remove -net <net_name> -order <order_hash>\n"
         "\tRemove order with specified hash\n"
             "\t\t === Commands for work with stake delegate ===\n"
-    "srv_stake delegate {[-cert <pub_cert_name> | -pkey <pkey> -sign_type <sign_type>] -value <datoshi> | "
+    "srv_stake delegate {[-cert <pub_cert_name> | {-pkey <pkey_hash> | -pkey_full <pkey>}-sign_type <sign_type>] -value <datoshi> | "
                                 "-order <order_hash> {[-tax_addr <wallet_addr_for_tax_collecting>] | "
                                         "-cert <priv_cert_name> [-node_addr <for_validator_node>]}}"
                         " -net <net_name> -w <wallet_name> -fee <value>\n"
@@ -219,6 +233,8 @@ int dap_chain_net_srv_stake_pos_delegate_init()
     "\texample datoshi amount syntax (only integer) 1 20 0.4321e+4\n"
     );
 
+    s_debug_more = dap_config_get_item_bool_default(g_config, "stake", "debug_more", s_debug_more);
+    dap_sign_set_pkey_by_hash_callback(s_get_pkey_by_hash_callback);
     dap_chain_static_srv_callbacks_t l_callbacks = { .start = s_pos_delegate_start,
                                                      .delete = s_pos_delegate_delete,
                                                      .purge = s_pos_delegate_purge,
@@ -258,7 +274,7 @@ static void s_pos_delegate_delete(void *a_service_internal)
     HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp) {
         // Clang bug at this, l_stake should change at every loop cycle
         HASH_DEL(l_srv_stake->itemlist, l_stake);
-        DAP_DELETE(l_stake);
+        DAP_DEL_MULTY(l_stake->pkey, l_stake);
     }
     struct cache_item *l_cache_item = NULL, *l_cache_tmp = NULL;
     HASH_ITER(hh, l_srv_stake->cache, l_cache_item, l_cache_tmp) {
@@ -466,7 +482,7 @@ static void s_stake_recalculate_weights(dap_chain_net_id_t a_net_id)
 }
 
 void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr_t *a_signing_addr, dap_hash_fast_t *a_stake_tx_hash,
-                                          uint256_t a_value, dap_chain_node_addr_t *a_node_addr)
+                                          uint256_t a_value, dap_chain_node_addr_t *a_node_addr, dap_pkey_t *a_pkey)
 {
     dap_return_if_fail(a_net && a_signing_addr && a_node_addr && a_stake_tx_hash);
     struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(a_net->pub.id);
@@ -489,14 +505,31 @@ void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr
     l_stake->value = l_stake->locked_value = a_value;
     l_stake->tx_hash = *a_stake_tx_hash;
     l_stake->is_active = true;
+    l_stake->pkey = DAP_DUP_SIZE(a_pkey, dap_pkey_get_size(a_pkey));
     if (!l_found)
         HASH_ADD(hh, l_srv_stake->itemlist, signing_addr.data.hash_fast, sizeof(dap_hash_fast_t), l_stake);
     if (!dap_hash_fast_is_blank(a_stake_tx_hash)) {
         HASH_ADD(ht, l_srv_stake->tx_itemlist, tx_hash, sizeof(dap_hash_fast_t), l_stake);
         dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, a_stake_tx_hash);
         if (l_tx) {
+            dap_pkey_t *l_pkey = NULL;
             dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, NULL);
-            if (l_cond && l_cond->tsd_size == dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size()) {
+            if (!l_stake->pkey) {
+                if (l_cond && DAP_SIGN_GET_PKEY_HASHING_FLAG(l_cond->subtype.srv_stake_pos_delegate.flags)) {
+                    dap_tsd_t *l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD);
+                    if (!l_tsd) {
+                        log_it(L_WARNING, "NULL tsd pkey in tx_out_cond with active PKEY_HASHING_FLAG");
+                    } else {
+                        l_pkey = (dap_pkey_t *)l_tsd->data;
+                        l_stake->pkey = DAP_DUP_SIZE(l_pkey, dap_pkey_get_size(l_pkey));
+                    }
+                }
+                if (!l_stake->pkey) {
+                    l_pkey = dap_ledger_find_pkey_by_hash(a_net->pub.ledger, &a_signing_addr->data.hash_fast);
+                    l_stake->pkey = DAP_DUP_SIZE(l_pkey, dap_pkey_get_size(l_pkey));
+                }
+            }
+            if (l_cond && (l_cond->tsd_size == dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size(true, dap_pkey_get_size(l_stake->pkey)))) {
                 dap_tsd_t *l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_ADDR);
                 l_stake->sovereign_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t);
                 l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_VALUE);
@@ -559,6 +592,28 @@ void dap_chain_net_srv_stake_key_update(dap_chain_addr_t *a_signing_addr, uint25
     s_stake_recalculate_weights(a_signing_addr->net_id);
 }
 
+/**
+ * @brief add pkey to dap_chain_net_srv_stake_item_t
+ * @param a_net to add
+ * @param a_pkey
+ */
+void dap_chain_net_srv_stake_pkey_update(dap_chain_net_t *a_net, dap_pkey_t *a_pkey)
+{
+    dap_return_if_pass(!a_net || !a_pkey);
+    struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(a_net->pub.id);
+    if (!l_srv_stake)
+        return log_it(L_ERROR, "Can't update pkey: no stake service found by net id %"DAP_UINT64_FORMAT_U, a_net->pub.id.uint64);
+    dap_hash_fast_t l_pkey_hash = {};
+    dap_pkey_get_hash(a_pkey, &l_pkey_hash);
+    dap_chain_net_srv_stake_item_t *l_stake = NULL;
+    HASH_FIND(hh, l_srv_stake->itemlist, &l_pkey_hash, sizeof(dap_hash_fast_t), l_stake);
+    if (!l_stake)
+        return log_it(L_WARNING, "No delegated found to update pkey %s", dap_hash_fast_to_str_static(&l_pkey_hash));
+    if (l_stake->pkey)
+        return log_it(L_INFO, "pkey %s to update already exist", dap_hash_fast_to_str_static(&l_pkey_hash));
+    l_stake->pkey = DAP_DUP_SIZE(a_pkey, dap_pkey_get_size(a_pkey));
+}
+
 void dap_chain_net_srv_stake_set_allowed_min_value(dap_chain_net_id_t a_net_id, uint256_t a_value)
 {
     struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
@@ -769,10 +824,9 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_enc_
                                                uint256_t a_value, uint256_t a_fee,
                                                dap_chain_addr_t *a_signing_addr, dap_chain_node_addr_t *a_node_addr,
                                                dap_chain_addr_t *a_sovereign_addr, uint256_t a_sovereign_tax,
-                                               dap_chain_datum_tx_t *a_prev_tx)
+                                               dap_chain_datum_tx_t *a_prev_tx, dap_pkey_t *a_pkey)
 {
-    if (!a_net || !a_key || IS_ZERO_256(a_value) || !a_signing_addr || !a_node_addr)
-        return NULL;
+    dap_return_val_if_pass (!a_net || !a_key || IS_ZERO_256(a_value) || !a_signing_addr || !a_node_addr, NULL);
 
     const char *l_native_ticker = a_net->pub.native_ticker;
     char l_delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
@@ -834,7 +888,8 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_enc_
     // add 'out_cond' & 'out_ext' items
     dap_chain_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ID };
     dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_stake(l_uid, a_value, a_signing_addr, a_node_addr,
-                                                                                          a_sovereign_addr, a_sovereign_tax);
+                                                                                          a_sovereign_addr, a_sovereign_tax, a_pkey);
+
     if (!l_tx_out) {
         log_it(L_ERROR, "Can't compose the transaction conditional output");
         goto tx_fail;
@@ -1024,7 +1079,7 @@ static dap_chain_datum_tx_t *s_order_tx_create(dap_chain_net_t * a_net, dap_enc_
     dap_chain_node_addr_t l_node_addr = {};
     return s_stake_tx_create(a_net, a_key, a_value, a_fee,
                              (dap_chain_addr_t *)&c_dap_chain_addr_blank, &l_node_addr,
-                             a_sovereign_addr, a_sovereign_tax, NULL);
+                             a_sovereign_addr, a_sovereign_tax, NULL, NULL);
 }
 
 // Put the transaction to mempool
@@ -1122,13 +1177,30 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
     *(dap_chain_addr_t*)(l_tsd->data) = l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr;
     l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
 
+    if (DAP_SIGN_GET_PKEY_HASHING_FLAG(l_tx_out_cond->subtype.srv_stake_pos_delegate.flags)) {
+        dap_tsd_t *l_tsd = dap_tsd_find(l_tx_out_cond->tsd, l_tx_out_cond->tsd_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD);
+        if (!l_tsd) {
+            log_it(L_WARNING, "NULL tsd pkey in tx_out_cond with active PKEY_HASHING_FLAG");
+        } else {
+            l_total_tsd_size += dap_tsd_size(l_tsd);
+            l_tsd = DAP_DUP_SIZE(l_tsd, dap_tsd_size(l_tsd));
+            if (!l_tsd) {
+                log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+                dap_list_free_full(l_tsd_list, NULL);
+                return NULL;
+            }
+            l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY;
+            l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
+        }
+    }
+    
     l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(dap_chain_node_addr_t);
     l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
     if (!l_tsd) {
         log_it(L_CRITICAL, "%s", c_error_memory_alloc);
         dap_list_free_full(l_tsd_list, NULL);
         return NULL;
-    }
+    }   
     l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR;
     l_tsd->size = sizeof(dap_chain_node_addr_t);
     *(dap_chain_node_addr_t*)(l_tsd->data) = l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr;
@@ -1192,6 +1264,56 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
     return l_decree;
 }
 
+static dap_chain_datum_decree_t *s_decree_pkey_update(dap_chain_net_t *a_net, dap_cert_t *a_cert, dap_pkey_t *a_pkey)
+{
+    dap_return_val_if_pass(!a_net || !a_cert || !a_pkey, NULL);
+    // create updating decree
+    dap_chain_datum_decree_t *l_decree = NULL;
+
+    size_t l_total_tsd_size = sizeof(dap_tsd_t) + dap_pkey_get_size(a_pkey);
+
+    l_decree = DAP_NEW_Z_SIZE(dap_chain_datum_decree_t, sizeof(dap_chain_datum_decree_t) + l_total_tsd_size);
+    if (!l_decree) {
+        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+        return NULL;
+    }
+    l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION;
+    l_decree->header.ts_created = dap_time_now();
+    l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
+    l_decree->header.common_decree_params.net_id = a_net->pub.id;
+    dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
+    if (!l_chain)
+        l_chain =  dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
+    if (!l_chain) {
+        log_it(L_ERROR, "No chain supported anchor datum type");
+        DAP_DEL_Z(l_decree);
+        return NULL;
+    }
+    l_decree->header.common_decree_params.chain_id = l_chain->id;
+    l_decree->header.common_decree_params.cell_id = *dap_chain_net_get_cur_cell(a_net);
+    l_decree->header.sub_type = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE;
+    l_decree->header.data_size = l_total_tsd_size;
+    l_decree->header.signs_size = 0;
+    dap_tsd_write((byte_t*)l_decree->data_n_signs, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY, a_pkey, dap_pkey_get_size(a_pkey));
+
+    dap_sign_t *l_sign = dap_cert_sign(a_cert,  l_decree,
+       sizeof(dap_chain_datum_decree_t) + l_decree->header.data_size, DAP_SIGN_HASH_TYPE_DEFAULT);
+
+    if (l_sign) {
+        l_decree->header.signs_size = dap_sign_get_size(l_sign);
+        l_decree = DAP_REALLOC_RET_VAL_IF_FAIL(l_decree, sizeof(dap_chain_datum_decree_t) + l_decree->header.data_size + l_decree->header.signs_size, NULL, l_decree, l_sign);
+        memcpy((byte_t*)l_decree->data_n_signs + l_decree->header.data_size, l_sign, l_decree->header.signs_size);
+        DAP_DELETE(l_sign);
+        log_it(L_DEBUG,"<-- Signed with '%s'", a_cert->name);
+    } else {
+        log_it(L_ERROR, "Decree signing failed");
+        DAP_DELETE(l_decree);
+        return NULL;
+    }
+
+    return l_decree;
+}
+
 // Put the decree to mempool
 static char *s_stake_decree_put(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net)
 {
@@ -1406,7 +1528,7 @@ static dap_chain_datum_decree_t *s_stake_decree_invalidate(dap_chain_net_t *a_ne
     size_t l_total_signs_size = l_decree->header.signs_size;
 
     dap_sign_t * l_sign = dap_cert_sign(a_cert,  l_decree,
-       sizeof(dap_chain_datum_decree_t) + l_decree->header.data_size, 0);
+       sizeof(dap_chain_datum_decree_t) + l_decree->header.data_size, DAP_SIGN_HASH_TYPE_DEFAULT);
 
     if (l_sign) {
         size_t l_sign_size = dap_sign_get_size(l_sign);
@@ -2032,13 +2154,24 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, voi
                         dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_order->tx_cond_hash);
                         if (l_tx) {
                             dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, NULL);
-                            if (l_cond && l_cond->tsd_size == dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size()) {
-                                dap_tsd_t *l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_ADDR);
-                                l_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t);
-                                l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_VALUE);
-                                l_tax = dap_tsd_get_scalar(l_tsd, uint256_t);
-                                MULT_256_256(l_tax, GET_256_FROM_64(100), &l_tax);
-                                l_error = false;
+                            if (l_cond) {
+                                dap_pkey_t *l_pkey = NULL;
+                                if (DAP_SIGN_GET_PKEY_HASHING_FLAG(l_cond->subtype.srv_stake_pos_delegate.flags)) {
+                                    dap_tsd_t *l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD);
+                                    if (!l_tsd) {
+                                        log_it(L_WARNING, "NULL tsd pkey in tx_out_cond with active PKEY_HASHING_FLAG");
+                                    } else {
+                                        l_pkey = (dap_pkey_t *)l_tsd->data;
+                                    }
+                                }
+                                if (l_cond->tsd_size == dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size(true, dap_pkey_get_size(l_pkey))) {
+                                    dap_tsd_t *l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_ADDR);
+                                    l_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t);
+                                    l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_VALUE);
+                                    l_tax = dap_tsd_get_scalar(l_tsd, uint256_t);
+                                    MULT_256_256(l_tax, GET_256_FROM_64(100), &l_tax);
+                                    l_error = false;
+                                }
                             }
                         }                   
                         if (!l_error) {
@@ -2123,11 +2256,14 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
                *l_wallet_str = NULL,
                *l_cert_str = NULL,
                *l_pkey_str = NULL,
+               *l_pkey_full_str = NULL,
                *l_sign_type_str = NULL,
                *l_value_str = NULL,
                *l_fee_str = NULL,
                *l_node_addr_str = NULL,
                *l_order_hash_str = NULL;
+    
+    dap_pkey_t *l_pkey = NULL;
     bool l_add_hash_to_gdb = false;
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-net", &l_net_str);
     if (!l_net_str) {
@@ -2157,14 +2293,20 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
     uint256_t l_sovereign_tax = uint256_0;
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str);
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-pkey", &l_pkey_str);
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-pkey_full", &l_pkey_full_str);
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-sign_type", &l_sign_type_str);
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-order", &l_order_hash_str);
-    if (!l_cert_str && !l_order_hash_str && !l_pkey_str) {
+    if (!l_cert_str && !l_order_hash_str && !l_pkey_str && !l_pkey_full_str) {
         dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR, "Command 'delegate' requires parameter -cert and/or -order and/or -pkey");
         dap_enc_key_delete(l_enc_key);
-        return -13;
+        return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR;
     }
-    if (l_pkey_str && !l_sign_type_str) {
+    if (l_pkey_str && l_pkey_full_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR, "Command 'delegate' requires only one, -pkey or -pkey_full");
+        dap_enc_key_delete(l_enc_key);
+        return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR;
+    }
+    if ((l_pkey_str || l_pkey_full_str) && !l_sign_type_str) {
         dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR, "Command 'delegate' requires parameter -sign_type for pkey");
         dap_enc_key_delete(l_enc_key);
         return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR;
@@ -2198,16 +2340,34 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
             dap_enc_key_delete(l_enc_key);
             return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_WRONG_CERT_ERR;
         }
+        l_pkey = dap_pkey_from_enc_key(l_signing_cert->enc_key);
         dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-node_addr", &l_node_addr_str);
-    } else if (l_pkey_str) {
-        dap_chain_hash_fast_t l_hash_public_key = {0};
+    } else if (l_pkey_str || l_pkey_full_str) {
         dap_sign_type_t l_type = dap_sign_type_from_str(l_sign_type_str);
         if (l_type.type == SIG_TYPE_NULL) {
             dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_WRONG_SIGN_ERR, "Wrong sign type");
             dap_enc_key_delete(l_enc_key);
             return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_WRONG_SIGN_ERR;
         }
-        if (dap_chain_hash_fast_from_str(l_pkey_str, &l_hash_public_key)) {
+        if (l_pkey_full_str) {
+            l_pkey = dap_pkey_get_from_str(l_pkey_full_str);
+        } else {
+            dap_hash_fast_t l_pkey_hash = {};
+            if (!dap_chain_hash_fast_from_str(l_pkey_str, &l_pkey_hash))
+                l_pkey = dap_ledger_find_pkey_by_hash(l_net->pub.ledger, &l_pkey_hash);
+        }
+        if (!l_pkey) {
+            dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "Invalid pkey string format");
+            dap_enc_key_delete(l_enc_key);
+            return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR;
+        }
+        if (l_pkey->header.type.type != dap_pkey_type_from_sign_type(l_type).type) {
+            dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "pkey and sign types is different");
+            dap_enc_key_delete(l_enc_key);
+            return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR;
+        }
+        dap_chain_hash_fast_t l_hash_public_key = {0};
+        if (!dap_pkey_get_hash(l_pkey, &l_hash_public_key)) {
             dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "Invalid pkey hash format");
             dap_enc_key_delete(l_enc_key);
             return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR;
@@ -2270,7 +2430,7 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
                 log_it(L_WARNING, "Requested conditional transaction have another ticker (not %s)", l_delegated_ticker);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_ANOTHER_TICKER_ERR;
             }
-            if (l_cond->tsd_size != dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size()) {
+            if (l_cond->tsd_size != dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size(true, 0)) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_COND_TX_FORMAT_ERR, "The order's conditional transaction has invalid format");
                 dap_enc_key_delete(l_enc_key);
                 DAP_DELETE(l_order);
@@ -2354,6 +2514,7 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_UNSIGNED_ORDER_ERR;
             }
             dap_chain_addr_fill_from_sign(&l_signing_addr, l_sign, l_net->pub.id);
+            l_pkey = dap_pkey_get_from_sign(l_sign);
             char l_delegated_ticker_str[DAP_CHAIN_TICKER_SIZE_MAX];
             dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker_str, l_net->pub.native_ticker);
             if (dap_strcmp(l_order->price_ticker, l_delegated_ticker_str)) {
@@ -2374,6 +2535,11 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
         }
         DIV_256(l_sovereign_tax, GET_256_FROM_64(100), &l_sovereign_tax);
     }
+    if (!l_pkey) {
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "pkey not defined");
+        dap_enc_key_delete(l_enc_key);
+        return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR;
+    }
 
     int l_check_result = dap_chain_net_srv_stake_verify_key_and_node(&l_signing_addr, &l_node_addr);
     if (l_check_result) {
@@ -2404,8 +2570,9 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
 
     // Create conditional transaction
     dap_chain_datum_tx_t *l_tx = s_stake_tx_create(l_net, l_enc_key, l_value, l_fee, &l_signing_addr, &l_node_addr,
-                                                   l_order_hash_str ? &l_sovereign_addr : NULL, l_sovereign_tax, l_prev_tx);
+                                                   l_order_hash_str ? &l_sovereign_addr : NULL, l_sovereign_tax, l_prev_tx, l_pkey);
     dap_enc_key_delete(l_enc_key);
+    DAP_DELETE(l_pkey);
     char *l_tx_hash_str;
     if (!l_tx || !(l_tx_hash_str = s_stake_tx_put(l_tx, l_net, a_hash_out_type))) {
         dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_STAKE_ERR, "Stake transaction error");
@@ -2431,6 +2598,61 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
     return 0;
 }
 
+static int s_cli_srv_stake_pkey_show(int a_argc, char **a_argv, int a_arg_index, void **a_str_reply, const char *a_hash_out_type)
+{
+    json_object **a_json_arr_reply = (json_object **)a_str_reply;
+    const char *l_net_str = NULL,
+               *l_pkey_hash_str = NULL;
+    dap_hash_fast_t l_pkey_hash = {};
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-net", &l_net_str);
+    if (!l_net_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR, "Command 'pkey_show' requires parameter -net");
+        return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR;
+    }
+    dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str);
+    if (!l_net) {
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_NET_ERR, "Network %s not found", l_net_str);
+        return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_NET_ERR;
+    }
+
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-pkey", &l_pkey_hash_str);
+
+    if (!l_pkey_hash_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR, "Command 'pkey_show' requires parameter -pkey");
+        return -13;
+    }
+
+    if (dap_chain_hash_fast_from_str(l_pkey_hash_str, &l_pkey_hash)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "pkey not defined");
+        return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR;
+    }
+
+    struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(l_net->pub.id);
+    if (!l_srv_stake) {
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "Specified net have no stake service activated");
+        return -25;
+    } 
+    // search in curren
+    dap_chain_net_srv_stake_item_t *l_stake = NULL;
+    HASH_FIND(hh, l_srv_stake->itemlist, &l_pkey_hash, sizeof(dap_hash_fast_t), l_stake);
+    dap_pkey_t *l_pkey = l_stake ? l_stake->pkey : NULL;
+    if (!l_pkey) {
+        l_pkey = dap_ledger_find_pkey_by_hash(l_net->pub.ledger, &l_pkey_hash);
+    }
+    if (!l_pkey) {
+        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "pkey not finded");
+        return -25;
+    }
+    const char *l_pkey_str = dap_pkey_to_str(l_pkey, a_hash_out_type);
+    json_object* l_json_obj_pkey = json_object_new_object();
+    json_object_object_add(l_json_obj_pkey, "hash", json_object_new_string(l_pkey_hash_str));
+    json_object_object_add(l_json_obj_pkey, "pkey", json_object_new_string(l_pkey_str));
+
+    json_object_array_add(*a_json_arr_reply, l_json_obj_pkey);
+    DAP_DELETE(l_pkey_str);
+    return 0;
+}
+
 
 typedef enum s_cli_srv_stake_update_err{
     DAP_CHAIN_NODE_CLI_SRV_STAKE_UPDATE_OK = 0,
@@ -2844,6 +3066,9 @@ static void s_srv_stake_print(dap_chain_net_srv_stake_item_t *a_stake, uint256_t
     char l_node_addr[32];
     snprintf(l_node_addr, 32, ""NODE_ADDR_FP_STR"", NODE_ADDR_FP_ARGS_S(a_stake->node_addr));
     json_object_object_add(l_json_obj_stake, "pkey_hash", json_object_new_string(l_pkey_hash_str));
+    if (s_debug_more) {
+        json_object_object_add(l_json_obj_stake, "pkey_full", json_object_new_string(a_stake->pkey ? "true" : "false"));
+    }
     json_object_object_add(l_json_obj_stake, "stake_value", json_object_new_string(l_balance));
     json_object_object_add(l_json_obj_stake, "effective_value", json_object_new_string(l_effective_weight));
     json_object_object_add(l_json_obj_stake, "related_weight", json_object_new_string(l_rel_weight_str));
@@ -3021,7 +3246,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
 {
     json_object **a_json_arr_reply = (json_object **)a_str_reply;
     enum {
-        CMD_NONE, CMD_ORDER, CMD_DELEGATE, CMD_UPDATE, CMD_APPROVE, CMD_LIST, CMD_INVALIDATE, CMD_MIN_VALUE, CMD_CHECK, CMD_MAX_WEIGHT, CMD_REWARD 
+        CMD_NONE, CMD_ORDER, CMD_DELEGATE, CMD_UPDATE, CMD_APPROVE, CMD_LIST, CMD_INVALIDATE, CMD_MIN_VALUE, CMD_CHECK, CMD_MAX_WEIGHT, CMD_REWARD, CMD_PKEY_SHOW, CMD_PKEY_UPDATE
     };
     int l_arg_index = 1;
 
@@ -3068,6 +3293,12 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
     else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "check", NULL)) {
         l_cmd_num = CMD_CHECK;
     }
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "pkey_show", NULL)) {
+        l_cmd_num = CMD_PKEY_SHOW;
+    }
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "pkey_update", NULL)) {
+        l_cmd_num = CMD_PKEY_UPDATE;
+    }
     else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "reward", NULL)) {
         l_cmd_num = CMD_REWARD;
     }
@@ -3085,6 +3316,9 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
 
         case CMD_INVALIDATE:
             return s_cli_srv_stake_invalidate(a_argc, a_argv, l_arg_index + 1, a_str_reply, l_hash_out_type);
+        
+        case CMD_PKEY_SHOW:
+            return s_cli_srv_stake_pkey_show(a_argc, a_argv, l_arg_index + 1, a_str_reply, l_hash_out_type);
 
         case CMD_CHECK:
         {
@@ -3211,6 +3445,70 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
             DAP_DELETE(l_decree_hash_str);
         } break;
 
+        case CMD_PKEY_UPDATE: {
+            const char *l_net_str = NULL, *l_tx_hash_str = NULL, *l_cert_str = NULL;
+            l_arg_index++;
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
+            if (!l_net_str) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_PARAM_ERR, "Command 'pkey_update' requires parameter -net");
+                return DAP_CHAIN_NODE_CLI_SRV_STAKE_PARAM_ERR;
+            }
+            dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str);
+            if (!l_net) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_NET_ERR, "Network %s not found", l_net_str);
+                return DAP_CHAIN_NODE_CLI_SRV_STAKE_NET_ERR;
+            }
+            struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(l_net->pub.id);
+            if (!l_srv_stake) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_NO_STAKE_IN_NET_ERR, "Specified net have no stake service activated");
+                return DAP_CHAIN_NODE_CLI_SRV_STAKE_NO_STAKE_IN_NET_ERR;
+            }
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-poa_cert", &l_cert_str);
+            if (!l_cert_str) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_PARAM_ERR, "Command 'pkey_update' requires parameter -poa_cert");
+                return DAP_CHAIN_NODE_CLI_SRV_STAKE_PARAM_ERR;
+            }
+            dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_str);
+            if (!l_cert) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_NO_CERT_ERR, "Specified certificate not found");
+                return DAP_CHAIN_NODE_CLI_SRV_STAKE_NO_CERT_ERR;
+            }
+            if (!s_srv_stake_is_poa_cert(l_net, l_cert->enc_key)) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_NOT_POA_ERR, "Specified certificate is not PoA root one");
+                return DAP_CHAIN_NODE_CLI_SRV_STAKE_NOT_POA_ERR;
+            }
+            const char *l_pkey_full_str = NULL;
+            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-pkey_full", &l_pkey_full_str);
+            if (!l_pkey_full_str) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR, "Command 'pkey_update' requires parameter -pkey_full");
+                return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR;
+            }
+            dap_pkey_t *l_pkey = dap_pkey_get_from_str(l_pkey_full_str);
+            dap_hash_fast_t l_pkey_hash = {};
+            dap_pkey_get_hash(l_pkey, &l_pkey_hash);
+            dap_chain_net_srv_stake_item_t *l_stake = NULL;
+            HASH_FIND(hh, l_srv_stake->itemlist, &l_pkey_hash, sizeof(dap_hash_fast_t), l_stake);
+            if (!l_stake) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_STAKE_ERR, "Specified pkey hash %s isn't delegated or approved", dap_hash_fast_to_str_static(&l_pkey_hash));
+                return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_STAKE_ERR;
+            }
+            if (l_stake->pkey) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_STAKE_ERR, "Specified pkey_full already present");
+                return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_STAKE_ERR;
+            }
+            dap_chain_datum_decree_t *l_decree = s_decree_pkey_update(l_net, l_cert, l_pkey);
+            DAP_DELETE(l_pkey);
+            char *l_decree_hash_str = NULL;
+            if (!l_decree || !(l_decree_hash_str = s_stake_decree_put(l_decree, l_net))) {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DECREE_ERR, "pkey update decree error");
+                return DAP_CHAIN_NODE_CLI_SRV_STAKE_DECREE_ERR;
+            }
+            DAP_DELETE(l_decree);
+            char *l_approve_str = dap_strdup_printf("pkey update decree %s successfully created", l_decree_hash_str);
+            json_object_array_add(*a_json_arr_reply, json_object_new_string(l_approve_str));
+            DAP_DEL_MULTY(l_decree_hash_str, l_approve_str);
+        } break;
+
         case CMD_LIST: {
             l_arg_index++;            
             if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "keys", NULL)) {
@@ -3262,7 +3560,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                     }
                     l_stake = dap_chain_net_srv_stake_check_pkey_hash(l_net->pub.id, &l_pkey_hash);
                     if (!l_stake) {
-                        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_HASH_ERR, "Specified pkey hash isn't delegated nor approved");
+                        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_HASH_ERR, "Specified pkey hash isn't delegated or approved");
                         return DAP_CHAIN_NODE_CLI_SRV_STAKE_HASH_ERR;
                     }
                 }
diff --git a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h
index 8f8b2b5fcd..cbdeeb0669 100644
--- a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h
+++ b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h
@@ -42,6 +42,7 @@ typedef struct dap_chain_net_srv_stake_item { // TODO move it to private section
     dap_chain_node_addr_t node_addr;
     dap_chain_addr_t sovereign_addr;
     uint256_t sovereign_tax;
+    dap_pkey_t *pkey;
     UT_hash_handle hh, ht;
 } dap_chain_net_srv_stake_item_t;
 
@@ -49,9 +50,10 @@ int dap_chain_net_srv_stake_pos_delegate_init();
 void dap_chain_net_srv_stake_pos_delegate_deinit();
 
 void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr_t *a_signing_addr, dap_hash_fast_t *a_stake_tx_hash,
-                                          uint256_t a_value, dap_chain_node_addr_t *a_node_addr);
+                                          uint256_t a_value, dap_chain_node_addr_t *a_node_addr, dap_pkey_t *a_pkey);
 void dap_chain_net_srv_stake_key_invalidate(dap_chain_addr_t *a_signing_addr);
 void dap_chain_net_srv_stake_key_update(dap_chain_addr_t *a_signing_addr, uint256_t a_new_value, dap_hash_fast_t *a_new_tx_hash);
+void dap_chain_net_srv_stake_pkey_update(dap_chain_net_t *a_net, dap_pkey_t *a_pkey);
 void dap_chain_net_srv_stake_set_allowed_min_value(dap_chain_net_id_t a_net_id, uint256_t a_value);
 uint256_t dap_chain_net_srv_stake_get_allowed_min_value(dap_chain_net_id_t a_net_id);
 void dap_chain_net_srv_stake_set_percent_max(dap_chain_net_id_t a_net_id, uint256_t a_value);
diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c
index 887f06e0c8..7b7349c25e 100644
--- a/modules/type/blocks/dap_chain_block.c
+++ b/modules/type/blocks/dap_chain_block.c
@@ -283,7 +283,7 @@ size_t dap_chain_block_sign_add(dap_chain_block_t **a_block_ptr, size_t a_block_
     assert(a_block_ptr);
     dap_chain_block_t *l_block = *a_block_ptr;
     size_t l_offset = dap_chain_block_get_sign_offset(l_block, a_block_size);
-    dap_sign_t *l_block_sign = dap_sign_create(a_key, l_block, l_offset + sizeof(l_block->hdr), 0);
+    dap_sign_t *l_block_sign = dap_sign_create(a_key, l_block, l_offset + sizeof(l_block->hdr), DAP_SIGN_ADD_PKEY_HASHING_FLAG(DAP_SIGN_HASH_TYPE_DEFAULT));
     size_t l_block_sign_size = dap_sign_get_size(l_block_sign);
     if (!l_block_sign_size)
         return 0;
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 4810a2a993..b98acbf16d 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -426,7 +426,7 @@ static char *s_blocks_decree_set_reward(dap_chain_net_t *a_net, dap_chain_t *a_c
     l_tsd->size = sizeof(uint256_t);
     *(uint256_t*)(l_tsd->data) = a_value;
     // Sign it
-    dap_sign_t *l_sign = dap_cert_sign(a_cert, l_decree, l_decree_size, 0);
+    dap_sign_t *l_sign = dap_cert_sign(a_cert, l_decree, l_decree_size, DAP_SIGN_HASH_TYPE_DEFAULT);
     if (!l_sign) {
         log_it(L_ERROR, "Decree signing failed");
         DAP_DELETE(l_decree);
diff --git a/modules/type/dag/dap_chain_cs_dag_event.c b/modules/type/dag/dap_chain_cs_dag_event.c
index c15b936a36..c8f7d8784c 100644
--- a/modules/type/dag/dap_chain_cs_dag_event.c
+++ b/modules/type/dag/dap_chain_cs_dag_event.c
@@ -66,7 +66,7 @@ dap_chain_cs_dag_event_t *dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id,
     memcpy( l_event_new->hashes_n_datum_n_signs + l_hashes_size, a_datum,l_datum_size );
 
     if ( a_key ){
-        dap_sign_t *l_sign = dap_sign_create(a_key, l_event_new, l_event_size, 0);
+        dap_sign_t *l_sign = dap_sign_create(a_key, l_event_new, l_event_size, DAP_SIGN_HASH_TYPE_DEFAULT);
         if ( !l_sign )
             return DAP_DELETE(l_event_new), log_it(L_ERROR,"Can't sign dag event!"), NULL;
         size_t l_sign_size = dap_sign_get_size(l_sign);
@@ -151,7 +151,7 @@ size_t dap_chain_cs_dag_event_sign_add(dap_chain_cs_dag_event_t **a_event_ptr, s
         return log_it(L_DEBUG, "Already signed with pkey %s", dap_get_data_hash_str(l_pub_key, l_pub_key_size).s), DAP_DELETE(l_pub_key), 0;
     }
     size_t l_event_size_excl_sign = dap_chain_cs_dag_event_calc_size_excl_signs(l_event, a_event_size);
-    dap_sign_t *l_sign = dap_sign_create(a_key, l_event, l_event_size_excl_sign, 0);
+    dap_sign_t *l_sign = dap_sign_create(a_key, l_event, l_event_size_excl_sign, DAP_SIGN_HASH_TYPE_DEFAULT);
     size_t l_sign_size = dap_sign_get_size(l_sign);
     l_event = DAP_REALLOC_RET_VAL_IF_FAIL(*a_event_ptr, a_event_size + l_sign_size, a_event_size, l_sign);
     size_t l_event_size = a_event_size - sizeof(l_event->header);
@@ -235,7 +235,7 @@ size_t dap_chain_cs_dag_event_round_sign_add(dap_chain_cs_dag_event_round_item_t
     dap_chain_cs_dag_event_round_item_t *l_round_item = *a_round_item_ptr;
     if (dap_chain_cs_dag_event_round_sign_exists(l_round_item, a_key))
         return 0;
-    dap_sign_t * l_sign = dap_sign_create(a_key, &l_round_item->round_info.datum_hash, sizeof(dap_chain_hash_fast_t), 0);
+    dap_sign_t * l_sign = dap_sign_create(a_key, &l_round_item->round_info.datum_hash, sizeof(dap_chain_hash_fast_t), DAP_SIGN_HASH_TYPE_DEFAULT);
     size_t l_sign_size = dap_sign_get_size(l_sign);
     l_round_item = DAP_REALLOC_RET_VAL_IF_FAIL(*a_round_item_ptr, a_round_item_size + l_sign_size, a_round_item_size, l_sign);
     *a_round_item_ptr = l_round_item;
diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c
index 8717e40b56..238d391715 100644
--- a/modules/wallet/dap_chain_wallet.c
+++ b/modules/wallet/dap_chain_wallet.c
@@ -1291,6 +1291,14 @@ int dap_chain_wallet_get_pkey_hash(dap_chain_wallet_t *a_wallet, dap_hash_fast_t
     dap_enc_key_t *l_key = dap_chain_wallet_get_key(a_wallet, 0);
     dap_return_val_if_fail_err(l_key, -2, "Can't get wallet key!");
     int ret = dap_enc_key_get_pkey_hash(l_key, a_out_hash);
-    DAP_DELETE(l_key);
+    dap_enc_key_delete(l_key);
     return ret;
 }
+
+char *dap_chain_wallet_get_pkey_str(dap_chain_wallet_t *a_wallet, const char *a_str_type)
+{
+    dap_pkey_t *l_pkey = dap_chain_wallet_get_pkey(a_wallet, 0);
+    char *l_ret = dap_pkey_to_str(l_pkey, a_str_type);
+    DAP_DELETE(l_pkey);
+    return l_ret;
+}
diff --git a/modules/wallet/include/dap_chain_wallet.h b/modules/wallet/include/dap_chain_wallet.h
index be5c52f72b..73c18b418c 100644
--- a/modules/wallet/include/dap_chain_wallet.h
+++ b/modules/wallet/include/dap_chain_wallet.h
@@ -98,5 +98,6 @@ int dap_chain_wallet_add_wallet_opened_notify(dap_chain_wallet_opened_callback_t
 int dap_chain_wallet_add_wallet_created_notify(dap_chain_wallet_opened_callback_t a_callback, void *a_arg);
 
 int dap_chain_wallet_get_pkey_hash(dap_chain_wallet_t *a_wallet, dap_hash_fast_t *a_out_hash);
+char *dap_chain_wallet_get_pkey_str(dap_chain_wallet_t *a_wallet, const char *a_str_type);
 
-dap_list_t* dap_chain_wallet_get_local_addr();
\ No newline at end of file
+dap_list_t* dap_chain_wallet_get_local_addr();
-- 
GitLab