From f19324a2db668e49017d57e81b36c4394731f970 Mon Sep 17 00:00:00 2001
From: Roman Khlopkov <roman.khlopkov@demlabs.net>
Date: Sat, 13 Jun 2020 06:56:23 +0300
Subject: [PATCH] [*] Stake service CLI debugged

---
 modules/common/dap_chain_common.c             |  31 ++++-
 modules/common/include/dap_chain_common.h     |   3 +-
 .../consensus/dag-poa/dap_chain_cs_dag_poa.c  |   2 +-
 .../consensus/dag-pos/dap_chain_cs_dag_pos.c  |   2 +-
 modules/mempool/dap_chain_mempool.c           |   2 +-
 modules/net/dap_chain_net.c                   |   2 +-
 modules/net/srv/dap_chain_net_srv_order.c     |   4 +-
 .../service/stake/dap_chain_net_srv_stake.c   | 110 ++++++++++--------
 .../stake/include/dap_chain_net_srv_stake.h   |  21 +---
 .../xchange/dap_chain_net_srv_xchange.c       |   2 +-
 modules/type/dag/dap_chain_cs_dag.c           |   2 +-
 modules/wallet/dap_chain_wallet.c             |  13 +--
 12 files changed, 108 insertions(+), 86 deletions(-)

diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c
index c5c66ffa67..cccf61a1c2 100644
--- a/modules/common/dap_chain_common.c
+++ b/modules/common/dap_chain_common.c
@@ -222,18 +222,41 @@ dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str( const char * a_net_srv_u
 
 
 /**
- * @brief dap_chain_addr_fill
+ * @brief dap_chain_addr_fill_from_key
  * @param a_addr
  * @param a_key
  * @param a_net_id
  * @return
  */
-void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_sign_type_t a_type, dap_chain_hash_fast_t *a_pkey_hash, dap_chain_net_id_t *a_net_id)
+void dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t a_net_id) {
+    dap_sign_type_t l_type = dap_sign_type_from_key_type(a_key->type);
+    size_t l_pub_key_data_size;
+    uint8_t *l_pub_key_data = dap_enc_key_serealize_pub_key(a_key, &l_pub_key_data_size);
+    if (!l_pub_key_data) {
+        log_it(L_ERROR,"Can't fill address from key, its empty");
+        return;
+    }
+    dap_chain_hash_fast_t l_hash_public_key;
+    // serialized key -> key hash
+    dap_hash_fast(l_pub_key_data, l_pub_key_data_size, &l_hash_public_key);
+    dap_chain_addr_fill(a_addr, l_type, &l_hash_public_key, a_net_id);
+    DAP_DELETE(l_pub_key_data);
+}
+
+/**
+ * @brief dap_chain_addr_fill
+ * @param a_addr
+ * @param a_type
+ * @param a_pkey_hash
+ * @param a_net_id
+ * @return
+ */
+void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_sign_type_t a_type, dap_chain_hash_fast_t *a_pkey_hash, dap_chain_net_id_t a_net_id)
 {
-    if(!a_addr || !a_pkey_hash || !a_net_id)
+    if(!a_addr || !a_pkey_hash)
         return;
     a_addr->addr_ver = DAP_CHAIN_ADDR_VERSION_CURRENT;
-    a_addr->net_id.uint64 = a_net_id->uint64;
+    a_addr->net_id.uint64 = a_net_id.uint64;
     a_addr->sig_type.raw = a_type.raw;
     memcpy(a_addr->data.hash, a_pkey_hash, sizeof(dap_chain_hash_fast_t));
     // calc checksum
diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h
index c8617a1dac..fdd043c7c2 100644
--- a/modules/common/include/dap_chain_common.h
+++ b/modules/common/include/dap_chain_common.h
@@ -207,7 +207,8 @@ dap_chain_addr_t* dap_chain_addr_from_str(const char *str);
 dap_chain_net_id_t dap_chain_net_id_from_str(const char* a_str);
 dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str(const char* a_str);
 
-void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_sign_type_t a_type, dap_chain_hash_fast_t *a_pkey_hash, dap_chain_net_id_t *a_net_id);
+void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_sign_type_t a_type, dap_chain_hash_fast_t *a_pkey_hash, dap_chain_net_id_t a_net_id);
+void dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t a_net_id);
 
 int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr);
 
diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
index 4d5bf15f7b..ed9a1d1ffe 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -324,7 +324,7 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_
                     return -5;
                 }
                 dap_chain_addr_t l_addr = {};
-                dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, &a_dag->chain->net_id);
+                dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, a_dag->chain->net_id);
                 dap_chain_datum_t *l_datum = (dap_chain_datum_t *)dap_chain_cs_dag_event_get_datum(a_dag_event);
                 if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) {
                     dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data;
diff --git a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c
index 689e2dda83..2eb04c7ae8 100644
--- a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c
+++ b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c
@@ -235,7 +235,7 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_
                 log_it(L_WARNING, "Event's sign has no any key");
                 return -5;
             }
-            dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, &a_dag->chain->net_id);
+            dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, a_dag->chain->net_id);
 
             if (l_sig_pos == 0) {
                 dap_chain_datum_t *l_datum = (dap_chain_datum_t *)dap_chain_cs_dag_event_get_datum(a_dag_event);
diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c
index 2f72e5d0bb..28ce8491f0 100644
--- a/modules/mempool/dap_chain_mempool.c
+++ b/modules/mempool/dap_chain_mempool.c
@@ -375,7 +375,7 @@ dap_chain_hash_fast_t* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t *
         int l_tmp_cond_idx;
         // Find all transactions
         while (l_value_cond < l_value_send) {
-            l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(l_ledger, &l_tx_cur_hash, &l_tmp_cond, &l_tmp_cond_idx);
+            l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(l_ledger, &l_tx_cur_hash, &l_tmp_cond, &l_tmp_cond_idx, NULL);
             if (!l_tx_tmp) {
                 break;
             }
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index ee54f8d116..cc09de5d24 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -279,7 +279,7 @@ static void s_gbd_history_callback_notify (void * a_arg, const char a_op_code, c
                 return;
             }
             dap_chain_addr_t l_addr = {0};
-            dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, &l_net->pub.id);
+            dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, l_net->pub.id);
             uint64_t l_solvency = dap_chain_ledger_calc_balance(l_net->pub.ledger, &l_addr, l_order->price_ticker);
             if (l_solvency < l_order->price) {
                 dap_chain_global_db_gr_del((char *)a_key, a_group);
diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c
index 91e4b5c6ca..63c5012756 100644
--- a/modules/net/srv/dap_chain_net_srv_order.c
+++ b/modules/net/srv/dap_chain_net_srv_order.c
@@ -78,12 +78,14 @@ void dap_chain_net_srv_order_deinit()
 
 size_t dap_chain_net_srv_order_get_size(dap_chain_net_srv_order_t *a_order)
 {
+    if (!a_order)
+        return 0;
     size_t l_sign_size = 0;
     if (a_order->version > 1) {
         dap_sign_t *l_sign = (dap_sign_t *)&a_order->ext[a_order->ext_size];
         l_sign_size = dap_sign_get_size(l_sign);
     }
-    return a_order ? sizeof(dap_chain_net_srv_order_t) + a_order->ext_size + l_sign_size : 0;
+    return sizeof(dap_chain_net_srv_order_t) + a_order->ext_size + l_sign_size;
 }
 
 /**
diff --git a/modules/service/stake/dap_chain_net_srv_stake.c b/modules/service/stake/dap_chain_net_srv_stake.c
index 79bb415aae..04bcbdab0d 100644
--- a/modules/service/stake/dap_chain_net_srv_stake.c
+++ b/modules/service/stake/dap_chain_net_srv_stake.c
@@ -45,22 +45,22 @@ static dap_chain_net_srv_stake_t *s_srv_stake;
 int dap_chain_net_srv_stake_init()
 {
     dap_chain_node_cli_cmd_item_create("srv_stake", s_cli_srv_stake, NULL, "Delegated stake service commands",
-    "srv_stake order create -net <net name> -from_addr <addr> -token <ticker> -coins <value> -to_addr <addr> -fee_percent <value>\n"
+    "srv_stake order create -net <net name> -from_addr <addr> -token <ticker> -coins <value> -wallet <name> -fee_percent <value>\n"
         "\tCreate a new order with specified amount of datoshi to delegate it to the specified address."
         "The fee with specified percent with this delagation will be returned to the fee address pointed by delegator\n"
     "srv_stake order remove -net <net name> -order <order hash>\n"
          "\tRemove order with specified hash\n"
-    "srv_stake order update -net <net name> -order <order hash> {-from_addr <addr> | -token <ticker> -coins <value> | "
-                                                                "-to_addr <addr> | -fee_percent <value>}\n"
+    "srv_stake order update -net <net name> -order <order hash> -wallet <name>"
+                            "{-from_addr <addr> | -token <ticker> -coins <value> | -fee_percent <value>}\n"
          "\tUpdate order with specified hash\n"
     "srv_stake order list -net <net name>\n"
          "\tGet the stake orders list within specified net name\n"
     "srv_stake delegate -order <order hash> -net <net name> -wallet <wallet_name> -fee_addr <addr>\n"
          "\tDelegate tokens with specified order within specified net name. Specify fee address\n"
-    "srv_stake transactions -net <net name> {-addr <addr from>}"
-         "\tShow the list of active stake transactions (optional delegated from addr)"
-    "srv_stake invalidate -net <net name> -tx <transaction hash> -wallet <wallet name>"
-         "\tInvalidate stake transaction by hash within net name and return stake to specified wallet"
+    "srv_stake transactions -net <net name> {-addr <addr from>}\n"
+         "\tShow the list of active stake transactions (optional delegated from addr)\n"
+    "srv_stake invalidate -net <net name> -tx <transaction hash> -wallet <wallet name>\n"
+         "\tInvalidate stake transaction by hash within net name and return stake to specified wallet\n"
     );
     s_srv_stake = DAP_NEW_Z(dap_chain_net_srv_stake_t);
     uint16_t l_net_count;
@@ -72,7 +72,7 @@ int dap_chain_net_srv_stake_init()
         dap_chain_tx_out_cond_t *l_out_cond;
         int l_out_cond_idx;
         char l_token[DAP_CHAIN_TICKER_SIZE_MAX];
-        // Find all transactions
+        // Find all stake transactions
         do {
             l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(l_ledger, &l_tx_cur_hash, &l_out_cond, &l_out_cond_idx, l_token);
             if (!l_tx_tmp) {
@@ -94,7 +94,7 @@ int dap_chain_net_srv_stake_init()
             if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash)) {
                 continue;
             }
-            dap_chain_addr_fill(&l_stake->addr_from, l_sign->header.type, &l_pkey_hash, &l_net_list[i]->pub.id);
+            dap_chain_addr_fill(&l_stake->addr_from, l_sign->header.type, &l_pkey_hash, l_net_list[i]->pub.id);
             memcpy(&l_stake->addr_to, l_out_cond->params, sizeof(dap_chain_addr_t));
             memcpy(&l_stake->addr_fee, &l_out_cond->subtype.srv_stake.fee_addr, sizeof(dap_chain_addr_t));
             l_stake->fee_value = l_out_cond->subtype.srv_stake.fee_value;
@@ -103,6 +103,7 @@ int dap_chain_net_srv_stake_init()
         } while (l_tx_tmp);
     }
     DAP_DELETE(l_net_list);
+    s_srv_stake->initialized = true;
     return 0;
 }
 
@@ -125,6 +126,14 @@ bool dap_chain_net_srv_stake_verificator(dap_chain_tx_out_cond_t *a_cond, dap_ch
 
 bool dap_chain_net_srv_stake_validator(dap_chain_addr_t *a_addr, dap_chain_datum_tx_t *a_tx)
 {
+    if (!s_srv_stake) {
+        return true;
+    }
+    while (!s_srv_stake->initialized);
+
+    if (!a_addr || !a_tx) {
+        return false;
+    }
     dap_chain_net_srv_stake_item_t *l_stake = NULL;
     HASH_FIND(hh, s_srv_stake->itemlist, a_addr, sizeof(dap_chain_addr_t), l_stake);
     if (l_stake == NULL) { // public key not delegated for this network
@@ -175,7 +184,7 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_srv_stake_item_t *a
     dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(a_stake->net->pub.name);
     dap_chain_addr_t *l_owner_addr = (dap_chain_addr_t *)dap_chain_wallet_get_addr(a_wallet, a_stake->net->pub.id);
     if (memcmp(l_owner_addr, &a_stake->addr_from, sizeof(dap_chain_addr_t))) {
-        log_it(L_WARNING, "Odree and wallet address do not match");
+        log_it(L_WARNING, "Odrer and wallet address do not match");
         return NULL;
     }
     dap_enc_key_t *l_owner_key = dap_chain_wallet_get_key(a_wallet, 0);
@@ -185,7 +194,7 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_srv_stake_item_t *a
     if(!l_list_used_out) {
         dap_chain_datum_tx_delete(l_tx);
         DAP_DELETE(l_owner_addr);
-        log_it(L_WARNING, "Nothing to change (not enough funds)");
+        log_it(L_WARNING, "Nothing to delegate (not enough funds)");
         return NULL;
     }
 
@@ -305,7 +314,7 @@ static bool s_stake_tx_invalidate(dap_chain_net_srv_stake_item_t *a_stake, dap_c
     return true;
 }
 
-char *s_stake_order_create(dap_chain_net_srv_stake_item_t *a_item)
+char *s_stake_order_create(dap_chain_net_srv_stake_item_t *a_item, dap_enc_key_t *l_key)
 {
     dap_chain_hash_fast_t l_tx_hash = {};
     dap_srv_stake_order_ext_t l_ext;
@@ -318,7 +327,7 @@ char *s_stake_order_create(dap_chain_net_srv_stake_item_t *a_item)
     dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_ID };
     char *l_order_hash_str = dap_chain_net_srv_order_create(a_item->net, SERV_DIR_BUY, l_uid, *l_node_addr,
                                                             l_tx_hash, a_item->value, l_unit, a_item->token, 0,
-                                                            (uint8_t *)&l_ext, l_ext_size, NULL, 0, NULL);
+                                                            (uint8_t *)&l_ext, l_ext_size, NULL, 0, l_key);
     return l_order_hash_str;
 }
 
@@ -357,7 +366,7 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, cha
     switch (l_cmd_num) {
         case CMD_CREATE: {
             const char *l_net_str = NULL, *l_token_str = NULL, *l_coins_str = NULL;
-            const char *l_addr_from_str = NULL, *l_addr_to_str = NULL, *l_fee_str = NULL;
+            const char *l_addr_from_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL;
             dap_chain_net_t *l_net = NULL;
             dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
             if (!l_net_str) {
@@ -398,14 +407,14 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, cha
                 dap_chain_node_cli_set_reply_text(a_str_reply, "Wrong address format");
                 return -10;
             }
-            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-addr_to", &l_addr_to_str);
-            if (!l_addr_to_str) {
-                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order create' required parameter -addr_to");
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_wallet_str);
+            if (!l_wallet_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order create' required parameter -wallet");
                 return -9;
             }
-            dap_chain_addr_t *l_addr_to = dap_chain_addr_from_str(l_addr_to_str);
-            if (!l_addr_to) {
-                dap_chain_node_cli_set_reply_text(a_str_reply, "Wrong address format");
+            dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config));
+            if (!l_wallet) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Can't open wallet %s", l_wallet_str);
                 return -10;
             }
             dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-fee_percent", &l_fee_str);
@@ -424,12 +433,15 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, cha
             dap_stpcpy(l_stake->token, l_token_str);
             l_stake->value = l_value;
             memcpy(&l_stake->addr_from, l_addr_from, sizeof(dap_chain_addr_t));
+            dap_chain_addr_t *l_addr_to = dap_chain_wallet_get_addr(l_wallet, l_net->pub.id);
             memcpy(&l_stake->addr_to, l_addr_to, sizeof(dap_chain_addr_t));
             DAP_DELETE(l_addr_from);
             DAP_DELETE(l_addr_to);
             l_stake->fee_value = l_fee;
+            dap_enc_key_t *l_key = dap_chain_wallet_get_key(l_wallet, 0);
             // Create the order & put it to GDB
-            char *l_order_hash_str = s_stake_order_create(l_stake);
+            char *l_order_hash_str = s_stake_order_create(l_stake, l_key);
+            dap_chain_wallet_close(l_wallet);
             if (l_order_hash_str) {
                 dap_chain_node_cli_set_reply_text(a_str_reply, "Successfully created order %s", l_order_hash_str);
                 DAP_DELETE(l_order_hash_str);
@@ -466,7 +478,7 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, cha
         } break;
         case CMD_UPDATE: {
             const char *l_net_str = NULL, *l_token_str = NULL, *l_coins_str = NULL;
-            const char *l_addr_from_str = NULL, *l_addr_to_str = NULL, *l_fee_str = NULL;
+            const char *l_addr_from_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL;
             char *l_order_hash_str = NULL;
             dap_chain_net_t *l_net = NULL;
             dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
@@ -488,6 +500,16 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, cha
                 dap_chain_node_cli_set_reply_text(a_str_reply, "Can't find order %s\n", l_order_hash_str);
                 return -14;
             }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_wallet_str);
+            if (!l_wallet_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order update' required parameter -wallet");
+                return -9;
+            }
+            dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config));
+            if (!l_wallet) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Can't open wallet %s", l_wallet_str);
+                return -10;
+            }
             dap_chain_net_srv_stake_item_t *l_stake = s_stake_item_from_order(l_net, l_order);
             dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-token", &l_token_str);
             if (l_token_str) {
@@ -506,24 +528,6 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, cha
                 }
                 l_stake->value = l_value;
             }
-            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-addr_from", &l_addr_from_str);
-            if (l_addr_from_str) {
-                dap_chain_addr_t *l_addr_from = dap_chain_addr_from_str(l_addr_from_str);
-                if (!l_addr_from) {
-                    dap_chain_node_cli_set_reply_text(a_str_reply, "Wrong address format");
-                    return -10;
-                }
-                memcpy(&l_stake->addr_from, l_addr_from, sizeof(dap_chain_addr_t));
-            }
-            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-addr_to", &l_addr_to_str);
-            if (l_addr_to_str) {
-                dap_chain_addr_t *l_addr_to = dap_chain_addr_from_str(l_addr_to_str);
-                if (!l_addr_to) {
-                    dap_chain_node_cli_set_reply_text(a_str_reply, "Wrong address format");
-                    return -10;
-                }
-                memcpy(&l_stake->addr_to, l_addr_to, sizeof(dap_chain_addr_t));
-            }
             dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-fee_percent", &l_fee_str);
             if (l_fee_str) {
                 long double l_fee = strtold(l_fee_str, NULL);
@@ -532,13 +536,18 @@ static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, cha
                     return -12;
                 }
             }
-            if (!l_token_str && !l_coins_str && !l_addr_from_str && !l_addr_to_str && !l_fee_str) {
+            if (!l_token_str && !l_coins_str && !l_addr_from_str && !l_fee_str) {
                 dap_chain_node_cli_set_reply_text(a_str_reply, "At least one of updating parameters is mandatory");
                 return -16;
             }
+            dap_chain_addr_t *l_addr_to = dap_chain_wallet_get_addr(l_wallet, l_net->pub.id);
+            memcpy(&l_stake->addr_to, l_addr_to, sizeof(dap_chain_addr_t));
+            DAP_DELETE(l_addr_to);
+            dap_enc_key_t *l_key = dap_chain_wallet_get_key(l_wallet, 0);
             // Create the order & put it to GDB
             dap_chain_net_srv_order_delete_by_hash_str(l_net, l_order_hash_str);
-            l_order_hash_str = s_stake_order_create(l_stake);
+            l_order_hash_str = s_stake_order_create(l_stake, l_key);
+            dap_chain_wallet_close(l_wallet);
             if (l_order_hash_str) {
                 dap_chain_node_cli_set_reply_text(a_str_reply, "Successfully created order %s", l_order_hash_str);
                 DAP_DELETE(l_order_hash_str);
@@ -607,6 +616,12 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void *a_arg_func, char **a
     else if (dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "delegate", NULL)) {
         l_cmd_num = CMD_DELEGATE;
     }
+    else if (dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "transactions", NULL)) {
+        l_cmd_num = CMD_TX;
+    }
+    else if (dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "invalidate", NULL)) {
+        l_cmd_num = CMD_INVALIDATE;
+    }
     switch (l_cmd_num) {
         case CMD_ORDER:
             return s_cli_srv_stake_order(a_argc, a_argv, l_arg_index + 1, a_str_reply);
@@ -656,9 +671,12 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void *a_arg_func, char **a
                 // Create conditional transaction
                 dap_chain_datum_tx_t *l_tx = s_stake_tx_create(l_stake, l_wallet);
                 dap_chain_wallet_close(l_wallet);
-                if (l_tx && s_stake_tx_put(l_tx, l_net)) {
-                    // TODO send request to order owner to delete it
-                    dap_chain_net_srv_order_delete_by_hash_str(l_net, l_order_hash_str);
+                if (l_tx) {
+                    dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_stake->tx_hash);
+                    if (s_stake_tx_put(l_tx, l_net)) {
+                        // TODO send request to order owner to delete it
+                        dap_chain_net_srv_order_delete_by_hash_str(l_net, l_order_hash_str);
+                    }
                 }
                 DAP_DELETE(l_order);
                 dap_chain_node_cli_set_reply_text(a_str_reply, l_tx ? "Stake transaction has done" :
@@ -706,7 +724,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void *a_arg_func, char **a
                 DAP_DELETE(l_addr_fee_str);
             }
             if (!l_reply_str->len) {
-                dap_string_append(l_reply_str, "Pricelist is empty");
+                dap_string_append(l_reply_str, "No transaction found");
             }
             *a_str_reply = dap_string_free(l_reply_str, false);
         } break;
diff --git a/modules/service/stake/include/dap_chain_net_srv_stake.h b/modules/service/stake/include/dap_chain_net_srv_stake.h
index 6cc4feab7e..34b1626437 100644
--- a/modules/service/stake/include/dap_chain_net_srv_stake.h
+++ b/modules/service/stake/include/dap_chain_net_srv_stake.h
@@ -42,19 +42,6 @@ typedef struct dap_chain_net_srv_stake_item {
     UT_hash_handle hh;
 } dap_chain_net_srv_stake_item_t;
 
-/*typedef struct dap_chain_net_srv_xchange_db_item {
-    char token_sell[DAP_CHAIN_TICKER_SIZE_MAX];
-    char token_buy[DAP_CHAIN_TICKER_SIZE_MAX];
-    uint8_t padding[4];
-    uint64_t net_sell_id;
-    uint64_t net_buy_id;
-    uint64_t datoshi_sell;
-    long double rate;
-    dap_chain_hash_fast_t tx_hash;
-    dap_chain_hash_fast_t order_hash;
-    char wallet_str[];
-} DAP_ALIGN_PACKED dap_chain_net_srv_xchange_db_item_t;*/
-
 typedef struct dap_srv_stake_order_ext {
     dap_chain_addr_t addr_from;
     dap_chain_addr_t addr_to;
@@ -62,9 +49,11 @@ typedef struct dap_srv_stake_order_ext {
 } dap_srv_stake_order_ext_t;
 
 typedef struct dap_chain_net_srv_stake {
+    bool initialized;
     dap_chain_net_srv_stake_item_t *itemlist;
 } dap_chain_net_srv_stake_t;
 
-int dap_chain_net_srv_xchange_init();
-void dap_chain_net_srv_xchange_deinit();
-bool dap_chain_net_srv_xchange_verificator(dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx);
+int dap_chain_net_srv_stake_init();
+void dap_chain_net_srv_stake_deinit();
+bool dap_chain_net_srv_stake_verificator(dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx);
+bool dap_chain_net_srv_stake_validator(dap_chain_addr_t *a_addr, dap_chain_datum_tx_t *a_tx);
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index 5ac9c7f983..20c03c5db4 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -82,7 +82,7 @@ int dap_chain_net_srv_xchange_init()
         HASH_ADD_KEYPTR(hh, s_srv_xchange->pricelist, l_price->key_ptr, strlen(l_price->key_ptr), l_price);
     }
     dap_chain_global_db_objs_delete(l_prices, l_prices_count);
-    return 0;
+    return 1;
 }
 
 void dap_chain_net_srv_xchange_deinit()
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index f43a37fd4c..3d76887d71 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -1269,7 +1269,7 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply)
                         dap_chain_addr_t l_addr = {0};
                         dap_chain_hash_fast_t l_pkey_hash;
                         dap_sign_get_pkey_hash(l_sign, &l_pkey_hash);
-                        dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, &l_net->pub.id);
+                        dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, l_net->pub.id);
                         char * l_addr_str = dap_chain_addr_to_str(&l_addr);
                         dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\ttype: %s\taddr: %s"
                                                            "n", dap_sign_type_to_str( l_sign->header.type ),
diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c
index b392881900..f213b0ea63 100644
--- a/modules/wallet/dap_chain_wallet.c
+++ b/modules/wallet/dap_chain_wallet.c
@@ -205,19 +205,8 @@ dap_chain_addr_t* dap_chain_wallet_get_addr(dap_chain_wallet_t * a_wallet, dap_c
  */
 dap_chain_addr_t * dap_cert_to_addr(dap_cert_t * a_cert, dap_chain_net_id_t a_net_id)
 {
-    dap_sign_type_t l_type = dap_sign_type_from_key_type(a_cert->enc_key->type);
-    size_t l_pub_key_data_size;
-    uint8_t *l_pub_key_data = dap_enc_key_serealize_pub_key(a_cert->enc_key, &l_pub_key_data_size);
-    if (!l_pub_key_data) {
-        log_it(L_ERROR,"Can't fill address from key, its empty");
-        return NULL;
-    }
-    dap_chain_hash_fast_t l_hash_public_key;
-    // serialized key -> key hash
-    dap_hash_fast(l_pub_key_data, l_pub_key_data_size, &l_hash_public_key);
     dap_chain_addr_t * l_addr = DAP_NEW_Z(dap_chain_addr_t);
-    dap_chain_addr_fill(l_addr, l_type, &l_hash_public_key, &a_net_id);
-    DAP_DELETE(l_pub_key_data);
+    dap_chain_addr_fill_from_key(l_addr, a_cert->enc_key, a_net_id);
     return l_addr;
 }
 
-- 
GitLab